Merge tag 'drm/for-3.14-rc1-20140123' of git://anongit.freedesktop.org/tegra/linux...
authorDave Airlie <airlied@redhat.com>
Wed, 29 Jan 2014 02:03:56 +0000 (12:03 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 29 Jan 2014 02:03:56 +0000 (12:03 +1000)
drm/tegra: Changes for v3.14-rc1 (update)

These patches fix some issues caused by the DRM panel support from the
previous pull request and add two more panels (for the Toshiba AC100 as
well as the Seaboard and Ventana).

* tag 'drm/for-3.14-rc1-20140123' of git://anongit.freedesktop.org/tegra/linux:
  drm/tegra: Obtain head number from DT
  drm/panel: update EDID BLOB in panel_simple_get_modes()
  gpu: host1x: Remove unnecessary include
  drm/tegra: Use proper data type
  drm/tegra: Clarify how panel modes override others
  drm/tegra: Fix possible CRTC mask for RGB outputs
  drm/i915: Use drm_encoder_crtc_ok()
  drm: Move drm_encoder_crtc_ok() to core
  drm: provide a helper for the encoder possible_crtcs mask
  drm/tegra: Don't check resource with devm_ioremap_resource()
  drm/panel: Add support for Chunghwa CLAA101WA01A panel
  drm/panel: Add support for Samsung LTN101NT05 panel

994 files changed:
Documentation/block/null_blk.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/exynos5250-clock.txt
Documentation/kernel-parameters.txt
Documentation/module-signing.txt [new file with mode: 0644]
Documentation/networking/ip-sysctl.txt
MAINTAINERS
Makefile
arch/arc/include/uapi/asm/unistd.h
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/crypto/aesbs-core.S_shipped
arch/arm/crypto/bsaes-armv7.pl
arch/arm/include/asm/io.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/xen/page.h
arch/arm/kernel/devtree.c
arch/arm/kernel/perf_event_cpu.c
arch/arm/kernel/traps.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/omap4-common.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_7xx_data.c
arch/arm/mach-pxa/include/mach/lubbock.h
arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-bockw.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-lager.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mm/flush.c
arch/arm/mm/init.c
arch/arm/net/bpf_jit_32.c
arch/arm/xen/enlighten.c
arch/arm64/include/asm/io.h
arch/arm64/include/asm/xen/page-coherent.h
arch/arm64/kernel/ptrace.c
arch/mips/include/asm/cacheops.h
arch/mips/include/asm/r4kcache.h
arch/mips/mm/c-r4k.c
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/page.h
arch/parisc/include/uapi/asm/socket.h
arch/parisc/kernel/cache.c
arch/powerpc/boot/dts/mpc5125twr.dts
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_asm.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/switch_to.h
arch/powerpc/include/asm/unaligned.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/smp.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/book3s_rmhandlers.S
arch/powerpc/kvm/booke.c
arch/powerpc/lib/copyuser_64.S
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/opal-lpc.c
arch/powerpc/platforms/powernv/opal-xscom.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/pseries/lparcfg.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/nvram.c
arch/powerpc/platforms/pseries/pci.c
arch/s390/Kconfig
arch/s390/include/asm/smp.h
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/net/bpf_jit_comp.c
arch/s390/pci/pci_event.c
arch/sh/kernel/sh_ksyms_32.c
arch/sh/lib/Makefile
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/kernel/iommu.c
arch/sparc/kernel/ioport.c
arch/sparc/kernel/kgdb_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/net/bpf_jit_comp.c
arch/x86/Kconfig
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/preempt.h
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd_ibs.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kvm/lapic.c
arch/x86/kvm/vmx.c
arch/x86/mm/fault.c
arch/x86/mm/gup.c
arch/x86/net/bpf_jit_comp.c
arch/x86/vdso/vclock_gettime.c
block/blk-mq-sysfs.c
drivers/acpi/Kconfig
drivers/acpi/ac.c
drivers/acpi/apei/Kconfig
drivers/acpi/apei/erst.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/ata/ahci.c
drivers/ata/ahci_imx.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/sata_sis.c
drivers/block/null_blk.c
drivers/block/skd_main.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/char/Makefile
drivers/char/agp/Kconfig
drivers/char/agp/Makefile
drivers/char/agp/intel-agp.c
drivers/char/agp/intel-gtt.c
drivers/char/tpm/tpm_ppi.c
drivers/clk/clk-divider.c
drivers/clk/clk-s2mps11.c
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clocksource/Kconfig
drivers/clocksource/cadence_ttc_timer.c
drivers/clocksource/clksrc-of.c
drivers/clocksource/dw_apb_timer_of.c
drivers/clocksource/sun4i_timer.c
drivers/clocksource/time-armada-370-xp.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/cpuidle-calxeda.c
drivers/crypto/ixp4xx_crypto.c
drivers/dma/Kconfig
drivers/dma/at_hdmac_regs.h
drivers/dma/dmaengine.c
drivers/dma/dmatest.c
drivers/dma/fsldma.c
drivers/dma/ioat/dma.c
drivers/dma/mv_xor.c
drivers/dma/pl330.c
drivers/dma/ppc4xx/adma.c
drivers/dma/txx9dmac.c
drivers/firewire/sbp2.c
drivers/firmware/Makefile
drivers/firmware/efi/Kconfig
drivers/firmware/efi/Makefile
drivers/firmware/efi/efi-pstore.c
drivers/gpio/gpio-msm-v2.c
drivers/gpio/gpio-rcar.c
drivers/gpio/gpio-twl4030.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/armada/Kconfig
drivers/gpu/drm/armada/armada_drm.h
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/armada/armada_fbdev.c
drivers/gpu/drm/armada/armada_gem.c
drivers/gpu/drm/ast/ast_fb.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/ast/ast_ttm.c
drivers/gpu/drm/bochs/Kconfig [new file with mode: 0644]
drivers/gpu/drm/bochs/Makefile [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs.h [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_drv.c [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_fbdev.c [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_hw.c [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_kms.c [new file with mode: 0644]
drivers/gpu/drm/bochs/bochs_mm.c [new file with mode: 0644]
drivers/gpu/drm/cirrus/cirrus_drv.h
drivers/gpu/drm/cirrus/cirrus_fbdev.c
drivers/gpu/drm/cirrus/cirrus_main.c
drivers/gpu/drm/cirrus/cirrus_mode.c
drivers/gpu/drm/cirrus/cirrus_ttm.c
drivers/gpu/drm/drm_agpsupport.c
drivers/gpu/drm/drm_buffer.c
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_edid_load.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_memory.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/drm_usb.c
drivers/gpu/drm/drm_vm.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gem.h
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/gma500/accel_2d.c
drivers/gpu/drm/gma500/cdv_intel_dp.c
drivers/gpu/drm/gma500/gma_display.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/gma500/psb_intel_drv.h
drivers/gpu/drm/gma500/psb_irq.c
drivers/gpu/drm/gma500/psb_irq.h
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i810/i810_drv.c
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/dvo_ns2501.c
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_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_stolen.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/i915_ums.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_pll.c
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sdvo_regs.h
drivers/gpu/drm/i915/intel_sideband.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/mga/mga_dma.c
drivers/gpu/drm/mga/mga_drv.h
drivers/gpu/drm/mga/mga_ioc32.c
drivers/gpu/drm/mga/mga_irq.c
drivers/gpu/drm/mga/mga_state.c
drivers/gpu/drm/mgag200/mgag200_cursor.c
drivers/gpu/drm/mgag200/mgag200_fb.c
drivers/gpu/drm/mgag200/mgag200_main.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_ttm.c
drivers/gpu/drm/msm/Kconfig
drivers/gpu/drm/msm/Makefile
drivers/gpu/drm/msm/NOTES
drivers/gpu/drm/msm/adreno/a2xx.xml.h
drivers/gpu/drm/msm/adreno/a3xx.xml.h
drivers/gpu/drm/msm/adreno/a3xx_gpu.c
drivers/gpu/drm/msm/adreno/a3xx_gpu.h
drivers/gpu/drm/msm/adreno/adreno_common.xml.h
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.h
drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
drivers/gpu/drm/msm/dsi/dsi.xml.h
drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
drivers/gpu/drm/msm/dsi/sfpb.xml.h
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi.h
drivers/gpu/drm/msm/hdmi/hdmi.xml.h
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
drivers/gpu/drm/msm/hdmi/hdmi_connector.c
drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c [new file with mode: 0644]
drivers/gpu/drm/msm/hdmi/qfprom.xml.h
drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp_common.xml.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp_format.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp_kms.c [new file with mode: 0644]
drivers/gpu/drm/msm/mdp/mdp_kms.h [new file with mode: 0644]
drivers/gpu/drm/msm/mdp4/mdp4.xml.h [deleted file]
drivers/gpu/drm/msm/mdp4/mdp4_crtc.c [deleted file]
drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c [deleted file]
drivers/gpu/drm/msm/mdp4/mdp4_format.c [deleted file]
drivers/gpu/drm/msm/mdp4/mdp4_irq.c [deleted file]
drivers/gpu/drm/msm/mdp4/mdp4_kms.c [deleted file]
drivers/gpu/drm/msm/mdp4/mdp4_kms.h [deleted file]
drivers/gpu/drm/msm/mdp4/mdp4_plane.c [deleted file]
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_fb.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h
drivers/gpu/drm/msm/msm_iommu.c [new file with mode: 0644]
drivers/gpu/drm/msm/msm_kms.h [new file with mode: 0644]
drivers/gpu/drm/msm/msm_mmu.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/core/engine.c
drivers/gpu/drm/nouveau/core/core/subdev.c
drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
drivers/gpu/drm/nouveau/core/engine/device/base.c
drivers/gpu/drm/nouveau/core/engine/device/nv04.c
drivers/gpu/drm/nouveau/core/engine/device/nv10.c
drivers/gpu/drm/nouveau/core/engine/device/nv20.c
drivers/gpu/drm/nouveau/core/engine/device/nv30.c
drivers/gpu/drm/nouveau/core/engine/device/nv40.c
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
drivers/gpu/drm/nouveau/core/engine/device/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
drivers/gpu/drm/nouveau/core/engine/disp/vga.c
drivers/gpu/drm/nouveau/core/engine/falcon.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5 [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5 [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h
drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc
drivers/gpu/drm/nouveau/core/engine/graph/nv108.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c
drivers/gpu/drm/nouveau/core/include/core/device.h
drivers/gpu/drm/nouveau/core/include/engine/fifo.h
drivers/gpu/drm/nouveau/core/include/engine/graph.h
drivers/gpu/drm/nouveau/core/include/subdev/bar.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h
drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h
drivers/gpu/drm/nouveau/core/include/subdev/devinit.h
drivers/gpu/drm/nouveau/core/include/subdev/fb.h
drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
drivers/gpu/drm/nouveau/core/include/subdev/instmem.h
drivers/gpu/drm/nouveau/core/include/subdev/vm.h
drivers/gpu/drm/nouveau/core/subdev/bar/base.c
drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/bar/priv.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c
drivers/gpu/drm/nouveau/core/subdev/bios/timing.c
drivers/gpu/drm/nouveau/core/subdev/clock/base.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
drivers/gpu/drm/nouveau/core/subdev/devinit/base.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c
drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h
drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c
drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c
drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h
drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h
drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
drivers/gpu/drm/nouveau/core/subdev/vm/base.c
drivers/gpu/drm/nouveau/dispnv04/dfp.c
drivers/gpu/drm/nouveau/dispnv04/disp.c
drivers/gpu/drm/nouveau/dispnv04/disp.h
drivers/gpu/drm/nouveau/dispnv04/overlay.c
drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_display.h
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_dma.h
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_debugfs.c
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_drv.h
drivers/gpu/drm/omapdrm/omap_encoder.c
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/omapdrm/omap_irq.c
drivers/gpu/drm/qxl/Kconfig
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_ioctl.c
drivers/gpu/drm/qxl/qxl_irq.c
drivers/gpu/drm/qxl/qxl_kms.c
drivers/gpu/drm/r128/r128_cce.c
drivers/gpu/drm/r128/r128_drv.h
drivers/gpu/drm/r128/r128_ioc32.c
drivers/gpu/drm/r128/r128_irq.c
drivers/gpu/drm/r128/r128_state.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_i2c.c
drivers/gpu/drm/radeon/btc_dpm.c
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/ci_smc.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/cik_sdma.c
drivers/gpu/drm/radeon/cikd.h
drivers/gpu/drm/radeon/cypress_dpm.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/evergreen_reg.h
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/kv_dpm.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/ni_dma.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/pptable.h
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r300_cmdbuf.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_cp.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600_dma.c
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/r600_dpm.h
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_irq.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_mem.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_sa.c
drivers/gpu/drm/radeon/radeon_state.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rs780_dpm.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv6xx_dpm.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/rv770_dpm.h
drivers/gpu/drm/radeon/rv770d.h
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/radeon/si_smc.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/radeon/sislands_smc.h
drivers/gpu/drm/radeon/sumo_dpm.c
drivers/gpu/drm/radeon/sumo_smc.c
drivers/gpu/drm/radeon/trinity_dpm.c
drivers/gpu/drm/radeon/trinity_smc.c
drivers/gpu/drm/radeon/uvd_v2_2.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rcar-du/rcar_du_drv.h
drivers/gpu/drm/rcar-du/rcar_du_kms.c
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
drivers/gpu/drm/rcar-du/rcar_du_plane.c
drivers/gpu/drm/savage/savage_bci.c
drivers/gpu/drm/savage/savage_state.c
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/sis/sis_mm.c
drivers/gpu/drm/tegra/bus.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/ttm/ttm_lock.c
drivers/gpu/drm/ttm/ttm_object.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/via/via_dma.c
drivers/gpu/drm/via/via_dmablit.c
drivers/gpu/drm/via/via_drv.c
drivers/gpu/drm/via/via_drv.h
drivers/gpu/drm/via/via_irq.c
drivers/gpu/drm/via/via_video.c
drivers/gpu/drm/vmwgfx/Makefile
drivers/gpu/drm/vmwgfx/svga3d_reg.h
drivers/gpu/drm/vmwgfx/svga_reg.h
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
drivers/gpu/drm/vmwgfx/vmwgfx_context.c
drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_mob.c [new file with mode: 0644]
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c [new file with mode: 0644]
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/hwmon/coretemp.c
drivers/idle/intel_idle.c
drivers/iio/adc/ad7887.c
drivers/iio/imu/adis16400_core.c
drivers/iio/light/cm36651.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/ulp/ipoib/ipoib_netlink.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/input/input.c
drivers/input/touchscreen/zforce_ts.c
drivers/irqchip/irq-renesas-intc-irqpin.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/telespci.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/md/bcache/alloc.c
drivers/md/bcache/bcache.h
drivers/md/bcache/btree.c
drivers/md/bcache/movinggc.c
drivers/md/bcache/super.c
drivers/md/bcache/sysfs.c
drivers/md/bcache/util.c
drivers/md/bcache/util.h
drivers/md/bcache/writeback.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/mfd/rtsx_pcr.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/can/usb/ems_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
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_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/chelsio/cxgb4/l2t.c
drivers/net/ethernet/chelsio/cxgb4/l2t.h
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/intel/e1000e/80003es2lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/yam.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macvlan.c
drivers/net/phy/phy.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/dm9601.c
drivers/net/usb/hso.c
drivers/net/usb/mcs7830.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/of/Kconfig
drivers/of/address.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/pci-acpi.c
drivers/phy/Kconfig
drivers/phy/phy-core.c
drivers/pinctrl/sh-pfc/sh_pfc.h
drivers/power/Kconfig
drivers/power/power_supply_core.c
drivers/powercap/intel_rapl.c
drivers/regulator/s2mps11.c
drivers/s390/char/tty3270.c
drivers/scsi/qla2xxx/qla_target.c
drivers/staging/bcm/Bcmnet.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/iio/magnetometer/hmc5843.c
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/imx-tve.c
drivers/staging/imx-drm/ipu-v3/ipu-common.c
drivers/staging/netlogic/xlr_net.c
drivers/staging/rtl8188eu/os_dep/os_intfs.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_device.c
drivers/target/target_core_file.c
drivers/target/target_core_file.h
drivers/target/target_core_tpg.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/tty_ldsem.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-wdm.c
drivers/usb/dwc3/core.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/xhci-pci.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/phy/phy-twl6030-usb.c
drivers/usb/serial/option.c
drivers/usb/serial/zte_ev.c
drivers/video/fbmem.c
drivers/video/omap2/dss/dispc.c
drivers/virtio/virtio_balloon.c
drivers/xen/balloon.c
drivers/xen/grant-table.c
drivers/xen/privcmd.c
fs/aio.c
fs/ceph/addr.c
fs/ceph/inode.c
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/link.c
fs/dcache.c
fs/eventpoll.c
fs/ext2/super.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/fs-writeback.c
fs/gfs2/aops.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/log.c
fs/gfs2/meta_io.c
fs/gfs2/ops_fstype.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/transaction.c
fs/namespace.c
fs/nilfs2/segment.c
fs/pstore/platform.c
fs/sysfs/file.c
fs/xfs/xfs_attr_remote.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_trans_buf.c
include/acpi/acpi_bus.h
include/asm-generic/pgtable.h
include/asm-generic/preempt.h
include/drm/drmP.h
include/drm/drm_agpsupport.h
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h
include/drm/drm_dp_helper.h
include/drm/drm_os_linux.h
include/drm/drm_pciids.h
include/drm/ttm/ttm_bo_driver.h
include/drm/ttm/ttm_object.h
include/linux/auxvec.h
include/linux/crash_dump.h
include/linux/fb.h
include/linux/i2c.h
include/linux/libata.h
include/linux/lockref.h
include/linux/math64.h
include/linux/migrate.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/netdevice.h
include/linux/percpu-defs.h
include/linux/pstore.h
include/linux/reboot.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/seqlock.h
include/linux/skbuff.h
include/net/if_inet6.h
include/net/llc_pdu.h
include/net/sctp/structs.h
include/rdma/ib_verbs.h
include/target/target_core_base.h
include/uapi/drm/drm.h
include/uapi/drm/i915_drm.h
include/uapi/drm/radeon_drm.h
include/uapi/drm/vmwgfx_drm.h
include/uapi/linux/input.h
include/uapi/linux/perf_event.h
include/xen/interface/io/blkif.h
init/Kconfig
kernel/Makefile
kernel/bounds.c
kernel/cgroup.c
kernel/events/core.c
kernel/fork.c
kernel/freezer.c
kernel/kexec.c
kernel/power/console.c
kernel/reboot.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/time/sched_clock.c
kernel/trace/ftrace.c
kernel/user.c
lib/percpu_counter.c
mm/Kconfig
mm/compaction.c
mm/fremap.c
mm/huge_memory.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mlock.c
mm/mprotect.c
mm/page_alloc.c
mm/pgtable-generic.c
mm/rmap.c
mm/util.c
net/8021q/vlan_dev.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/fragmentation.c
net/batman-adv/icmp_socket.c
net/batman-adv/main.c
net/batman-adv/network-coding.c
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/bluetooth/hci_sock.c
net/bridge/br_multicast.c
net/core/dev.c
net/core/filter.c
net/core/flow_dissector.c
net/core/neighbour.c
net/core/netpoll.c
net/dccp/probe.c
net/ieee802154/6lowpan.c
net/ieee802154/nl-phy.c
net/ipv4/gre_offload.c
net/ipv4/inet_diag.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv4/netfilter/nft_reject_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/addrconf.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/ip6mr.c
net/ipv6/netfilter/ip6t_SYNPROXY.c
net/ipv6/route.c
net/ipv6/sit.c
net/llc/af_llc.c
net/mac80211/iface.c
net/mac80211/tx.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/nf_conntrack_seqadj.c
net/netfilter/nf_conntrack_timestamp.c
net/netfilter/nf_nat_irc.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_log.c
net/netfilter/nft_exthdr.c
net/nfc/core.c
net/rds/ib.c
net/rds/ib_recv.c
net/rose/af_rose.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ipt.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/sch_generic.c
net/sctp/outqueue.c
net/sctp/probe.c
net/tipc/link.c
net/tipc/port.c
net/tipc/port.h
net/tipc/socket.c
net/unix/af_unix.c
net/wireless/radiotap.c
net/wireless/sme.c
scripts/link-vmlinux.sh
security/selinux/hooks.c
security/selinux/include/objsec.h
sound/core/pcm_lib.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/sam9x5_wm8731.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/imx-wm8962.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/soc-pcm.c
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_i2s.c
tools/power/cpupower/utils/cpupower-set.c

diff --git a/Documentation/block/null_blk.txt b/Documentation/block/null_blk.txt
new file mode 100644 (file)
index 0000000..b2830b4
--- /dev/null
@@ -0,0 +1,72 @@
+Null block device driver
+================================================================================
+
+I. Overview
+
+The null block device (/dev/nullb*) is used for benchmarking the various
+block-layer implementations. It emulates a block device of X gigabytes in size.
+The following instances are possible:
+
+  Single-queue block-layer
+    - Request-based.
+    - Single submission queue per device.
+    - Implements IO scheduling algorithms (CFQ, Deadline, noop).
+  Multi-queue block-layer
+    - Request-based.
+    - Configurable submission queues per device.
+  No block-layer (Known as bio-based)
+    - Bio-based. IO requests are submitted directly to the device driver.
+    - Directly accepts bio data structure and returns them.
+
+All of them have a completion queue for each core in the system.
+
+II. Module parameters applicable for all instances:
+
+queue_mode=[0-2]: Default: 2-Multi-queue
+  Selects which block-layer the module should instantiate with.
+
+  0: Bio-based.
+  1: Single-queue.
+  2: Multi-queue.
+
+home_node=[0--nr_nodes]: Default: NUMA_NO_NODE
+  Selects what CPU node the data structures are allocated from.
+
+gb=[Size in GB]: Default: 250GB
+  The size of the device reported to the system.
+
+bs=[Block size (in bytes)]: Default: 512 bytes
+  The block size reported to the system.
+
+nr_devices=[Number of devices]: Default: 2
+  Number of block devices instantiated. They are instantiated as /dev/nullb0,
+  etc.
+
+irq_mode=[0-2]: Default: 1-Soft-irq
+  The completion mode used for completing IOs to the block-layer.
+
+  0: None.
+  1: Soft-irq. Uses IPI to complete IOs across CPU nodes. Simulates the overhead
+     when IOs are issued from another CPU node than the home the device is
+     connected to.
+  2: Timer: Waits a specific period (completion_nsec) for each IO before
+     completion.
+
+completion_nsec=[ns]: Default: 10.000ns
+  Combined with irq_mode=2 (timer). The time each completion event must wait.
+
+submit_queues=[0..nr_cpus]:
+  The number of submission queues attached to the device driver. If unset, it
+  defaults to 1 on single-queue and bio-based instances. For multi-queue,
+  it is ignored when use_per_node_hctx module parameter is 1.
+
+hw_queue_depth=[0..qdepth]: Default: 64
+  The hardware queue depth of the device.
+
+III: Multi-queue specific parameters
+
+use_per_node_hctx=[0/1]: Default: 0
+  0: The number of submit queues are set to the value of the submit_queues
+     parameter.
+  1: The multi-queue block layer is instantiated with a hardware dispatch
+     queue for each CPU node in the system.
index 46f5c791ea0df6e94e2ea6bd8ef26436231f8ebe..0f2f920e87348515995cb553ece45cf0949213b7 100644 (file)
@@ -159,6 +159,8 @@ clock which they consume.
   mixer                        343
   hdmi                 344
   g2d                  345
+  mdma0                        346
+  smmu_mdma0           347
 
 
    [Clock Muxes]
index 50680a59a2ff9a913e449a1d71ced9fab3004fe4..b9e9bd85429801efa537bc1ea85f773fc92099f8 100644 (file)
@@ -1529,6 +1529,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
                        * atapi_dmadir: Enable ATAPI DMADIR bridge support
 
+                       * disable: Disable this device.
+
                        If there are multiple matching configurations changing
                        the same attribute, the last one is used.
 
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
new file mode 100644 (file)
index 0000000..2b40e04
--- /dev/null
@@ -0,0 +1,240 @@
+                       ==============================
+                       KERNEL MODULE SIGNING FACILITY
+                       ==============================
+
+CONTENTS
+
+ - Overview.
+ - Configuring module signing.
+ - Generating signing keys.
+ - Public keys in the kernel.
+ - Manually signing modules.
+ - Signed modules and stripping.
+ - Loading signed modules.
+ - Non-valid signatures and unsigned modules.
+ - Administering/protecting the private key.
+
+
+========
+OVERVIEW
+========
+
+The kernel module signing facility cryptographically signs modules during
+installation and then checks the signature upon loading the module.  This
+allows increased kernel security by disallowing the loading of unsigned modules
+or modules signed with an invalid key.  Module signing increases security by
+making it harder to load a malicious module into the kernel.  The module
+signature checking is done by the kernel so that it is not necessary to have
+trusted userspace bits.
+
+This facility uses X.509 ITU-T standard certificates to encode the public keys
+involved.  The signatures are not themselves encoded in any industrial standard
+type.  The facility currently only supports the RSA public key encryption
+standard (though it is pluggable and permits others to be used).  The possible
+hash algorithms that can be used are SHA-1, SHA-224, SHA-256, SHA-384, and
+SHA-512 (the algorithm is selected by data in the signature).
+
+
+==========================
+CONFIGURING MODULE SIGNING
+==========================
+
+The module signing facility is enabled by going to the "Enable Loadable Module
+Support" section of the kernel configuration and turning on
+
+       CONFIG_MODULE_SIG       "Module signature verification"
+
+This has a number of options available:
+
+ (1) "Require modules to be validly signed" (CONFIG_MODULE_SIG_FORCE)
+
+     This specifies how the kernel should deal with a module that has a
+     signature for which the key is not known or a module that is unsigned.
+
+     If this is off (ie. "permissive"), then modules for which the key is not
+     available and modules that are unsigned are permitted, but the kernel will
+     be marked as being tainted.
+
+     If this is on (ie. "restrictive"), only modules that have a valid
+     signature that can be verified by a public key in the kernel's possession
+     will be loaded.  All other modules will generate an error.
+
+     Irrespective of the setting here, if the module has a signature block that
+     cannot be parsed, it will be rejected out of hand.
+
+
+ (2) "Automatically sign all modules" (CONFIG_MODULE_SIG_ALL)
+
+     If this is on then modules will be automatically signed during the
+     modules_install phase of a build.  If this is off, then the modules must
+     be signed manually using:
+
+       scripts/sign-file
+
+
+ (3) "Which hash algorithm should modules be signed with?"
+
+     This presents a choice of which hash algorithm the installation phase will
+     sign the modules with:
+
+       CONFIG_SIG_SHA1         "Sign modules with SHA-1"
+       CONFIG_SIG_SHA224       "Sign modules with SHA-224"
+       CONFIG_SIG_SHA256       "Sign modules with SHA-256"
+       CONFIG_SIG_SHA384       "Sign modules with SHA-384"
+       CONFIG_SIG_SHA512       "Sign modules with SHA-512"
+
+     The algorithm selected here will also be built into the kernel (rather
+     than being a module) so that modules signed with that algorithm can have
+     their signatures checked without causing a dependency loop.
+
+
+=======================
+GENERATING SIGNING KEYS
+=======================
+
+Cryptographic keypairs are required to generate and check signatures.  A
+private key is used to generate a signature and the corresponding public key is
+used to check it.  The private key is only needed during the build, after which
+it can be deleted or stored securely.  The public key gets built into the
+kernel so that it can be used to check the signatures as the modules are
+loaded.
+
+Under normal conditions, the kernel build will automatically generate a new
+keypair using openssl if one does not exist in the files:
+
+       signing_key.priv
+       signing_key.x509
+
+during the building of vmlinux (the public part of the key needs to be built
+into vmlinux) using parameters in the:
+
+       x509.genkey
+
+file (which is also generated if it does not already exist).
+
+It is strongly recommended that you provide your own x509.genkey file.
+
+Most notably, in the x509.genkey file, the req_distinguished_name section
+should be altered from the default:
+
+       [ req_distinguished_name ]
+       O = Magrathea
+       CN = Glacier signing key
+       emailAddress = slartibartfast@magrathea.h2g2
+
+The generated RSA key size can also be set with:
+
+       [ req ]
+       default_bits = 4096
+
+
+It is also possible to manually generate the key private/public files using the
+x509.genkey key generation configuration file in the root node of the Linux
+kernel sources tree and the openssl command.  The following is an example to
+generate the public/private key files:
+
+       openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
+          -config x509.genkey -outform DER -out signing_key.x509 \
+          -keyout signing_key.priv
+
+
+=========================
+PUBLIC KEYS IN THE KERNEL
+=========================
+
+The kernel contains a ring of public keys that can be viewed by root.  They're
+in a keyring called ".system_keyring" that can be seen by:
+
+       [root@deneb ~]# cat /proc/keys
+       ...
+       223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
+       302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
+       ...
+
+Beyond the public key generated specifically for module signing, any file
+placed in the kernel source root directory or the kernel build root directory
+whose name is suffixed with ".x509" will be assumed to be an X.509 public key
+and will be added to the keyring.
+
+Further, the architecture code may take public keys from a hardware store and
+add those in also (e.g. from the UEFI key database).
+
+Finally, it is possible to add additional public keys by doing:
+
+       keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]
+
+e.g.:
+
+       keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
+
+Note, however, that the kernel will only permit keys to be added to
+.system_keyring _if_ the new key's X.509 wrapper is validly signed by a key
+that is already resident in the .system_keyring at the time the key was added.
+
+
+=========================
+MANUALLY SIGNING MODULES
+=========================
+
+To manually sign a module, use the scripts/sign-file tool available in
+the Linux kernel source tree.  The script requires 4 arguments:
+
+       1.  The hash algorithm (e.g., sha256)
+       2.  The private key filename
+       3.  The public key filename
+       4.  The kernel module to be signed
+
+The following is an example to sign a kernel module:
+
+       scripts/sign-file sha512 kernel-signkey.priv \
+               kernel-signkey.x509 module.ko
+
+The hash algorithm used does not have to match the one configured, but if it
+doesn't, you should make sure that hash algorithm is either built into the
+kernel or can be loaded without requiring itself.
+
+
+============================
+SIGNED MODULES AND STRIPPING
+============================
+
+A signed module has a digital signature simply appended at the end.  The string
+"~Module signature appended~." at the end of the module's file confirms that a
+signature is present but it does not confirm that the signature is valid!
+
+Signed modules are BRITTLE as the signature is outside of the defined ELF
+container.  Thus they MAY NOT be stripped once the signature is computed and
+attached.  Note the entire module is the signed payload, including any and all
+debug information present at the time of signing.
+
+
+======================
+LOADING SIGNED MODULES
+======================
+
+Modules are loaded with insmod, modprobe, init_module() or finit_module(),
+exactly as for unsigned modules as no processing is done in userspace.  The
+signature checking is all done within the kernel.
+
+
+=========================================
+NON-VALID SIGNATURES AND UNSIGNED MODULES
+=========================================
+
+If CONFIG_MODULE_SIG_FORCE is enabled or enforcemodulesig=1 is supplied on
+the kernel command line, the kernel will only load validly signed modules
+for which it has a public key.   Otherwise, it will also load modules that are
+unsigned.   Any module for which the kernel has a key, but which proves to have
+a signature mismatch will not be permitted to load.
+
+Any module that has an unparseable signature will be rejected.
+
+
+=========================================
+ADMINISTERING/PROTECTING THE PRIVATE KEY
+=========================================
+
+Since the private key is used to sign modules, viruses and malware could use
+the private key to sign modules and compromise the operating system.  The
+private key must be either destroyed or moved to a secure location and not kept
+in the root node of the kernel source tree.
index 3c12d9a7ed00391d5c3f49ef80d7b1ae9abc40fe..8a984e994e61616a9dba0a4f425a5b4371b3ae99 100644 (file)
@@ -16,8 +16,12 @@ ip_default_ttl - INTEGER
        Default: 64 (as recommended by RFC1700)
 
 ip_no_pmtu_disc - BOOLEAN
-       Disable Path MTU Discovery.
-       default FALSE
+       Disable Path MTU Discovery. If enabled and a
+       fragmentation-required ICMP is received, the PMTU to this
+       destination will be set to min_pmtu (see below). You will need
+       to raise min_pmtu to the smallest interface MTU on your system
+       manually if you want to avoid locally generated fragments.
+       Default: FALSE
 
 min_pmtu - INTEGER
        default 552 - minimum discovered Path MTU
index 1344816c4c06aca6db27c51e8f1e9c3911c751ac..6a6e4ac7228774a8b7d3b9dd492571c03d734fe0 100644 (file)
@@ -783,7 +783,7 @@ F:  arch/arm/boot/dts/sama*.dts
 F:     arch/arm/boot/dts/sama*.dtsi
 
 ARM/CALXEDA HIGHBANK ARCHITECTURE
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-highbank/
@@ -1008,6 +1008,8 @@ M:        Santosh Shilimkar <santosh.shilimkar@ti.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-keystone/
+F:     drivers/clk/keystone/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
 
 ARM/LOGICPD PXA270 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
@@ -1366,6 +1368,9 @@ T:        git git://git.xilinx.com/linux-xlnx.git
 S:     Supported
 F:     arch/arm/mach-zynq/
 F:     drivers/cpuidle/cpuidle-zynq.c
+N:     zynq
+N:     xilinx
+F:     drivers/clocksource/cadence_ttc_timer.c
 
 ARM SMMU DRIVER
 M:     Will Deacon <will.deacon@arm.com>
@@ -2823,8 +2828,10 @@ F:       include/uapi/drm/
 
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Daniel Vetter <daniel.vetter@ffwll.ch>
+M:     Jani Nikula <jani.nikula@linux.intel.com>
 L:     intel-gfx@lists.freedesktop.org
 L:     dri-devel@lists.freedesktop.org
+Q:     http://patchwork.freedesktop.org/project/intel-gfx/
 T:     git git://people.freedesktop.org/~danvet/drm-intel
 S:     Supported
 F:     drivers/gpu/drm/i915/
@@ -3761,9 +3768,11 @@ F:       include/uapi/linux/gigaset_dev.h
 
 GPIO SUBSYSTEM
 M:     Linus Walleij <linus.walleij@linaro.org>
-S:     Maintained
+M:     Alexandre Courbot <gnurou@gmail.com>
 L:     linux-gpio@vger.kernel.org
-F:     Documentation/gpio.txt
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
+S:     Maintained
+F:     Documentation/gpio/
 F:     drivers/gpio/
 F:     include/linux/gpio*
 F:     include/asm-generic/gpio.h
@@ -3831,6 +3840,12 @@ T:       git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/
 
+GUID PARTITION TABLE (GPT)
+M:     Davidlohr Bueso <davidlohr@hp.com>
+L:     linux-efi@vger.kernel.org
+S:     Maintained
+F:     block/partitions/efi.*
+
 STK1160 USB VIDEO CAPTURE DRIVER
 M:     Ezequiel Garcia <elezegarcia@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -5911,12 +5926,21 @@ M:      Steffen Klassert <steffen.klassert@secunet.com>
 M:     Herbert Xu <herbert@gondor.apana.org.au>
 M:     "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
 S:     Maintained
 F:     net/xfrm/
 F:     net/key/
 F:     net/ipv4/xfrm*
+F:     net/ipv4/esp4.c
+F:     net/ipv4/ah4.c
+F:     net/ipv4/ipcomp.c
+F:     net/ipv4/ip_vti.c
 F:     net/ipv6/xfrm*
+F:     net/ipv6/esp6.c
+F:     net/ipv6/ah6.c
+F:     net/ipv6/ipcomp6.c
+F:     net/ipv6/ip6_vti.c
 F:     include/uapi/linux/xfrm.h
 F:     include/net/xfrm.h
 
@@ -6237,7 +6261,7 @@ F:        drivers/i2c/busses/i2c-ocores.c
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Grant Likely <grant.likely@linaro.org>
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 L:     devicetree@vger.kernel.org
 W:     http://fdt.secretlab.ca
 T:     git git://git.secretlab.ca/git/linux-2.6.git
@@ -6249,7 +6273,7 @@ K:        of_get_property
 K:     of_match_table
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 M:     Pawel Moll <pawel.moll@arm.com>
 M:     Mark Rutland <mark.rutland@arm.com>
 M:     Ian Campbell <ijc+devicetree@hellion.org.uk>
@@ -9207,6 +9231,7 @@ F:        include/media/videobuf2-*
 
 VIRTIO CONSOLE DRIVER
 M:     Amit Shah <amit.shah@redhat.com>
+L:     virtio-dev@lists.oasis-open.org
 L:     virtualization@lists.linux-foundation.org
 S:     Maintained
 F:     drivers/char/virtio_console.c
@@ -9216,6 +9241,7 @@ F:        include/uapi/linux/virtio_console.h
 VIRTIO CORE, NET AND BLOCK DRIVERS
 M:     Rusty Russell <rusty@rustcorp.com.au>
 M:     "Michael S. Tsirkin" <mst@redhat.com>
+L:     virtio-dev@lists.oasis-open.org
 L:     virtualization@lists.linux-foundation.org
 S:     Maintained
 F:     drivers/virtio/
@@ -9228,6 +9254,7 @@ F:        include/uapi/linux/virtio_*.h
 VIRTIO HOST (VHOST)
 M:     "Michael S. Tsirkin" <mst@redhat.com>
 L:     kvm@vger.kernel.org
+L:     virtio-dev@lists.oasis-open.org
 L:     virtualization@lists.linux-foundation.org
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -9571,7 +9598,7 @@ F:        drivers/xen/*swiotlb*
 
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
-M:     Dave Chinner <dchinner@fromorbit.com>
+M:     Dave Chinner <david@fromorbit.com>
 M:     Ben Myers <bpm@sgi.com>
 M:     xfs@oss.sgi.com
 L:     xfs@oss.sgi.com
index 858a147fd836a668a7b35d2ed0ddb6a9adc68c29..b8b7f74696b4094de39ba65839de236edd5e643e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION =
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
@@ -732,19 +732,15 @@ export mod_strip_cmd
 # Select initial ramdisk compression format, default is gzip(1).
 # This shall be used by the dracut(8) tool while creating an initramfs image.
 #
-INITRD_COMPRESS=gzip
-ifeq ($(CONFIG_RD_BZIP2), y)
-        INITRD_COMPRESS=bzip2
-else ifeq ($(CONFIG_RD_LZMA), y)
-        INITRD_COMPRESS=lzma
-else ifeq ($(CONFIG_RD_XZ), y)
-        INITRD_COMPRESS=xz
-else ifeq ($(CONFIG_RD_LZO), y)
-        INITRD_COMPRESS=lzo
-else ifeq ($(CONFIG_RD_LZ4), y)
-        INITRD_COMPRESS=lz4
-endif
-export INITRD_COMPRESS
+INITRD_COMPRESS-y                  := gzip
+INITRD_COMPRESS-$(CONFIG_RD_BZIP2) := bzip2
+INITRD_COMPRESS-$(CONFIG_RD_LZMA)  := lzma
+INITRD_COMPRESS-$(CONFIG_RD_XZ)    := xz
+INITRD_COMPRESS-$(CONFIG_RD_LZO)   := lzo
+INITRD_COMPRESS-$(CONFIG_RD_LZ4)   := lz4
+# do not export INITRD_COMPRESS, since we didn't actually
+# choose a sane default compression above.
+# export INITRD_COMPRESS := $(INITRD_COMPRESS-y)
 
 ifdef CONFIG_MODULE_SIG_ALL
 MODSECKEY = ./signing_key.priv
index 68125dd766c68feeb9de6715c9d1694ed24e5491..39e58d1cdf90b7d8f84d108d8024d8974c3b800c 100644 (file)
@@ -8,7 +8,11 @@
 
 /******** no-legacy-syscalls-ABI *******/
 
-#ifndef _UAPI_ASM_ARC_UNISTD_H
+/*
+ * Non-typical guard macro to enable inclusion twice in ARCH sys.c
+ * That is how the Generic syscall wrapper generator works
+ */
+#if !defined(_UAPI_ASM_ARC_UNISTD_H) || defined(__SYSCALL)
 #define _UAPI_ASM_ARC_UNISTD_H
 
 #define __ARCH_WANT_SYS_EXECVE
@@ -36,4 +40,6 @@ __SYSCALL(__NR_arc_gettls, sys_arc_gettls)
 #define __NR_sysfs             (__NR_arch_specific_syscall + 3)
 __SYSCALL(__NR_sysfs, sys_sysfs)
 
+#undef __SYSCALL
+
 #endif
index 9db5047812f3d6c05a36643abbea0e1fb33e8195..177becde7a268bdcee91be7b049567d17daf9809 100644 (file)
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x10800000 0x1000>;
                        interrupts = <0 33 0>;
-                       clocks = <&clock 271>;
+                       clocks = <&clock 346>;
                        clock-names = "apb_pclk";
                        #dma-cells = <1>;
                        #dma-channels = <8>;
index ee845fad939b895a1bfb907c6597f9f916d926f8..9987dd0e9c599929042b1ce70d4b1d6c3ec1ebfb 100644 (file)
@@ -87,9 +87,9 @@
                interrupts = <1 9 0xf04>;
        };
 
-       gpio0: gpio@ffc40000 {
+       gpio0: gpio@e6050000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc40000 0 0x2c>;
+               reg = <0 0xe6050000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 4 0x4>;
                #gpio-cells = <2>;
@@ -99,9 +99,9 @@
                interrupt-controller;
        };
 
-       gpio1: gpio@ffc41000 {
+       gpio1: gpio@e6051000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc41000 0 0x2c>;
+               reg = <0 0xe6051000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 5 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio2: gpio@ffc42000 {
+       gpio2: gpio@e6052000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc42000 0 0x2c>;
+               reg = <0 0xe6052000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 6 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio3: gpio@ffc43000 {
+       gpio3: gpio@e6053000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc43000 0 0x2c>;
+               reg = <0 0xe6053000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 7 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio4: gpio@ffc44000 {
+       gpio4: gpio@e6054000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc44000 0 0x2c>;
+               reg = <0 0xe6054000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 8 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio5: gpio@ffc45000 {
+       gpio5: gpio@e6055000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc45000 0 0x2c>;
+               reg = <0 0xe6055000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 9 0x4>;
                #gpio-cells = <2>;
 
        sdhi0: sdhi@ee100000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee100000 0 0x100>;
+               reg = <0 0xee100000 0 0x200>;
                interrupt-parent = <&gic>;
                interrupts = <0 165 4>;
                cap-sd-highspeed;
 
        sdhi1: sdhi@ee120000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee120000 0 0x100>;
+               reg = <0 0xee120000 0 0x200>;
                interrupt-parent = <&gic>;
                interrupts = <0 166 4>;
                cap-sd-highspeed;
index 64205d453260d12ec1e2d43c424fab1c3251788a..71e5fc7cfb18f489f3adadb20c6f8049421fb079 100644 (file)
@@ -58,7 +58,7 @@
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_ARCH__  7
 #endif
 
 #ifdef __thumb__
index f3d96d9325737fba399dc5e6613d223e03fcb7a1..be068db960ee0006ac1aa25a4e69b95265404844 100644 (file)
@@ -701,7 +701,7 @@ $code.=<<___;
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_ARCH__  7
 #endif
 
 #ifdef __thumb__
index 3c597c222ef278a8eb170a4169b5e54dcc158ac0..fbeb39c869e9fdcedace1d61688247c14141cab3 100644 (file)
@@ -329,7 +329,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  */
 #define ioremap(cookie,size)           __arm_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arm_ioremap((cookie), (size), MT_DEVICE)
-#define ioremap_cached(cookie,size)    __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
+#define ioremap_cache(cookie,size)     __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)                __arm_ioremap((cookie), (size), MT_DEVICE_WC)
 #define iounmap                                __arm_iounmap
 
index 6976b03e521369bddedfe6968cfa221c6705c552..8756e4bcdba0609ff789a4f1efaa551faa39ed98 100644 (file)
@@ -347,7 +347,8 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
 #define ARCH_PFN_OFFSET                PHYS_PFN_OFFSET
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+#define virt_addr_valid(kaddr) (((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory) \
+                                       && pfn_valid(__pa(kaddr) >> PAGE_SHIFT) )
 
 #endif
 
index 75579a9d6f76cba3cc84ad61d01ed103269378bd..3759cacdd7f8601322b98ffed6598d97ee8bd016 100644 (file)
@@ -117,6 +117,6 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
        return __set_phys_to_machine(pfn, mfn);
 }
 
-#define xen_remap(cookie, size) ioremap_cached((cookie), (size));
+#define xen_remap(cookie, size) ioremap_cache((cookie), (size));
 
 #endif /* _ASM_ARM_XEN_PAGE_H */
index 739c3dfc1da25c6145268809459c567aa80e543f..34d5fd585bbb1d472015838c2665dea5aad376f7 100644 (file)
@@ -171,7 +171,7 @@ void __init arm_dt_init_cpu_maps(void)
 
 bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
 {
-       return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu);
+       return phys_id == cpu_logical_map(cpu);
 }
 
 static const void * __init arch_get_next_mach(const char *const **match)
index d85055cd24bacc55cde9e99f1547afbfe33317ae..20d553c9f5e2928a0c4321878a30520dde87656d 100644 (file)
@@ -254,7 +254,7 @@ static int probe_current_pmu(struct arm_pmu *pmu)
 static int cpu_pmu_device_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id;
-       int (*init_fn)(struct arm_pmu *);
+       const int (*init_fn)(struct arm_pmu *);
        struct device_node *node = pdev->dev.of_node;
        struct arm_pmu *pmu;
        int ret = -ENODEV;
index 7940241f0576b0db1cc0a749e449c7faf492518a..4636d56af2db63f64703b7417a551d78dffecbe0 100644 (file)
 #include <asm/system_misc.h>
 #include <asm/opcodes.h>
 
-static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+static const char *handler[]= {
+       "prefetch abort",
+       "data abort",
+       "address exception",
+       "interrupt",
+       "undefined instruction",
+};
 
 void *vectors_page;
 
@@ -425,9 +431,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
                        instr2 = __mem_to_opcode_thumb16(instr2);
                        instr = __opcode_thumb32_compose(instr, instr2);
                }
-       } else if (get_user(instr, (u32 __user *)pc)) {
+       } else {
+               if (get_user(instr, (u32 __user *)pc))
+                       goto die_sig;
                instr = __mem_to_opcode_arm(instr);
-               goto die_sig;
        }
 
        if (call_undef_hook(regs, instr) == 0)
index 9ee78f7b4990751386cf7f29337ec075297349dd..782f6c71fa0a6c761269cfc4b74fc6cdd0839e75 100644 (file)
@@ -96,11 +96,12 @@ static struct irqaction footbridge_timer_irq = {
 void __init footbridge_timer_init(void)
 {
        struct clock_event_device *ce = &ckevt_dc21285;
+       unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
 
-       clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16);
+       clocksource_register_hz(&cksrc_dc21285, rate);
 
        setup_irq(ce->irq, &footbridge_timer_irq);
 
        ce->cpumask = cpumask_of(smp_processor_id());
-       clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff);
+       clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
 }
index bd3bf66ce3449a31c9c7c9f56be6b4225ee9cbf9..c7de89b263dd3b3e8e69e554b00b9af7d8079aee 100644 (file)
@@ -53,6 +53,7 @@ static void __init highbank_scu_map_io(void)
 
 static void highbank_l2x0_disable(void)
 {
+       outer_flush_all();
        /* Disable PL310 L2 Cache controller */
        highbank_smc1(0x102, 0x0);
 }
index 4ec8d82b0492f3e66e75bec0aa7cff8cd25a5faa..44a59c3abfb0535e8c9168284a5bf67ed0f13bb6 100644 (file)
@@ -242,12 +242,18 @@ static void __init ldp_display_init(void)
 
 static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
 {
+       int res;
+
        /* LCD enable GPIO */
        ldp_lcd_pdata.enable_gpio = gpio + 7;
 
        /* Backlight enable GPIO */
        ldp_lcd_pdata.backlight_gpio = gpio + 15;
 
+       res = platform_device_register(&ldp_lcd_device);
+       if (res)
+               pr_err("Unable to register LCD: %d\n", res);
+
        return 0;
 }
 
@@ -346,7 +352,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 
 static struct platform_device *ldp_devices[] __initdata = {
        &ldp_gpio_keys_device,
-       &ldp_lcd_device,
 };
 
 #ifdef CONFIG_OMAP_MUX
index 58347bb874a01dcd4d203f4f191712d473a338a3..4cf165502b35cfdd06c09696a20b09758d974169 100644 (file)
@@ -101,13 +101,51 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
        { "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
+static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+{
+       u32 enable_mask, enable_shift;
+       u32 pipd_mask, pipd_shift;
+       u32 reg;
+
+       if (dsi_id == 0) {
+               enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
+               enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
+               pipd_mask = OMAP4_DSI1_PIPD_MASK;
+               pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
+       } else if (dsi_id == 1) {
+               enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
+               enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
+               pipd_mask = OMAP4_DSI2_PIPD_MASK;
+               pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
+       } else {
+               return -ENODEV;
+       }
+
+       reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+       reg &= ~enable_mask;
+       reg &= ~pipd_mask;
+
+       reg |= (lanes << enable_shift) & enable_mask;
+       reg |= (lanes << pipd_shift) & pipd_mask;
+
+       omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+       return 0;
+}
+
 static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
+       if (cpu_is_omap44xx())
+               return omap4_dsi_mux_pads(dsi_id, lane_mask);
+
        return 0;
 }
 
 static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
+       if (cpu_is_omap44xx())
+               omap4_dsi_mux_pads(dsi_id, 0);
 }
 
 static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput)
index b39efd46abf991827169a6c17a6aa91f3dfeb39f..c0ab9b26be3da9f0c50630cfacf5b371467fd015 100644 (file)
@@ -162,6 +162,7 @@ void __iomem *omap4_get_l2cache_base(void)
 
 static void omap4_l2x0_disable(void)
 {
+       outer_flush_all();
        /* Disable PL310 L2 Cache controller */
        omap_smc1(0x102, 0x0);
 }
index 56cebb05509e15c0054f342e158a21214b7a6603..d23c77fadb31036058ab7b750cf02495d2ef33ab 100644 (file)
@@ -796,7 +796,7 @@ struct omap_hwmod omap2xxx_counter_32k_hwmod = {
 
 /* gpmc */
 static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
-       { .irq = 20 },
+       { .irq = 20 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -841,7 +841,7 @@ static struct omap_hwmod_class omap2_rng_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap2_rng_mpu_irqs[] = {
-       { .irq = 52 },
+       { .irq = 52 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
index d33742908f970a21b24c2cefeef03799d3d84532..4c3b1e6df50806700cbcfc3c4f582650b36cc3a3 100644 (file)
@@ -2165,7 +2165,7 @@ static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
-       { .irq = 20 },
+       { .irq = 20 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -2999,7 +2999,7 @@ static struct omap_mmu_dev_attr mmu_isp_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmu_isp_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mmu_isp_irqs[] = {
-       { .irq = 24 },
+       { .irq = 24 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -3041,7 +3041,7 @@ static struct omap_mmu_dev_attr mmu_iva_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmu_iva_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mmu_iva_irqs[] = {
-       { .irq = 28 },
+       { .irq = 28 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
index db32d5380b118cda247e6f8e863bc14906eed6bc..18f333c440db3b72ff49577ef71d24b64dbcc916 100644 (file)
@@ -1637,7 +1637,7 @@ static struct omap_hwmod dra7xx_uart1_hwmod = {
        .class          = &dra7xx_uart_hwmod_class,
        .clkdm_name     = "l4per_clkdm",
        .main_clk       = "uart1_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .flags          = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP2UART1_FLAGS,
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = DRA7XX_CM_L4PER_UART1_CLKCTRL_OFFSET,
index 2a086e8373eb7bf1104892784aba7a5236a3bd5b..958cd6af93842566308a33d11f1799dd78f332d9 100644 (file)
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <mach/irqs.h>
+
 #define LUBBOCK_ETH_PHYS       PXA_CS3_PHYS
 
 #define LUBBOCK_FPGA_PHYS      PXA_CS2_PHYS
index 7eb9a10fc1af68d81b1dd308ebfd352d28c9e416..2fddf38192df3ad0f67bc646914e7d4121a6b41c 100644 (file)
@@ -8,8 +8,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/clk-provider.h>
-#include <linux/irqchip.h>
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
@@ -48,15 +46,9 @@ static void __init s3c64xx_dt_map_io(void)
                panic("SoC is not S3C64xx!");
 }
 
-static void __init s3c64xx_dt_init_irq(void)
-{
-       of_clk_init(NULL);
-       samsung_wdt_reset_of_init();
-       irqchip_init();
-};
-
 static void __init s3c64xx_dt_init_machine(void)
 {
+       samsung_wdt_reset_of_init();
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
@@ -79,7 +71,6 @@ DT_MACHINE_START(S3C6400_DT, "Samsung S3C64xx (Flattened Device Tree)")
        /* Maintainer: Tomasz Figa <tomasz.figa@gmail.com> */
        .dt_compat      = s3c64xx_dt_compat,
        .map_io         = s3c64xx_dt_map_io,
-       .init_irq       = s3c64xx_dt_init_irq,
        .init_machine   = s3c64xx_dt_init_machine,
        .restart        = s3c64xx_dt_restart,
 MACHINE_END
index 958e3cbf0ac2f2110e7f4fc9ca41dc19e66e4ca8..8ea87bd45c330abd37df9eba0b30b8f4efc8dc47 100644 (file)
@@ -483,7 +483,7 @@ static struct platform_device lcdc0_device = {
        .id             = 0,
        .dev    = {
                .platform_data  = &lcdc0_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -580,7 +580,7 @@ static struct platform_device hdmi_lcdc_device = {
        .id             = 1,
        .dev    = {
                .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -614,6 +614,11 @@ static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
        REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
 };
 
+/* Fixed 3.3V regulator used by LCD backlight */
+static struct regulator_consumer_supply fixed5v0_power_consumers[] = {
+       REGULATOR_SUPPLY("power", "pwm-backlight.0"),
+};
+
 /* Fixed 3.3V regulator to be used by SDHI0 */
 static struct regulator_consumer_supply vcc_sdhi0_consumers[] = {
        REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
@@ -1196,6 +1201,8 @@ static void __init eva_init(void)
 
        regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
                                     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+       regulator_register_always_on(3, "fixed-5.0V", fixed5v0_power_consumers,
+                                    ARRAY_SIZE(fixed5v0_power_consumers), 5000000);
 
        pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map));
        pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
index 38611526fe9a55953372afcd2662aa668b34e080..3c4995aebd220870406934ba905d90d5949d18ca 100644 (file)
@@ -679,7 +679,7 @@ static void __init bockw_init(void)
                        .id             = i,
                        .data           = &rsnd_card_info[i],
                        .size_data      = sizeof(struct asoc_simple_card_info),
-                       .dma_mask       = ~0,
+                       .dma_mask       = DMA_BIT_MASK(32),
                };
 
                platform_device_register_full(&cardinfo);
index fe689b7fdc9e715ecd724edcc746913010627fb4..bc40b853ffd3cff2204bdfdc283863a9577f51bc 100644 (file)
@@ -334,7 +334,7 @@ static struct platform_device lcdc_device = {
        .resource       = lcdc_resources,
        .dev    = {
                .platform_data  = &lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
index a8d3ce646fb900514fa983964bf8d70d0e88c278..e0406fd373906e4d43d53769a7d7cfa548b6f388 100644 (file)
@@ -245,7 +245,9 @@ static void __init lager_init(void)
 {
        lager_add_standard_devices();
 
-       phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup);
+       if (IS_ENABLED(CONFIG_PHYLIB))
+               phy_register_fixup_for_id("r8a7790-ether-ff:01",
+                                         lager_ksz8041_fixup);
 }
 
 static const char * const lager_boards_compat_dt[] __initconst = {
index af06753eb8092500de41707ac68216bd3ed244a0..e721d2ccceaef8c1d57bd0d671fa097a2c0f539a 100644 (file)
@@ -409,7 +409,7 @@ static struct platform_device lcdc_device = {
        .resource       = lcdc_resources,
        .dev    = {
                .platform_data  = &lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -499,7 +499,7 @@ static struct platform_device hdmi_lcdc_device = {
        .id             = 1,
        .dev    = {
                .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
index 6d5ba9afb16a4409d50dbdbc03d08c83642df9b4..3387e60e4ea381c579725774ebab8d587eeded0c 100644 (file)
@@ -175,16 +175,16 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
                unsigned long i;
                if (cache_is_vipt_nonaliasing()) {
                        for (i = 0; i < (1 << compound_order(page)); i++) {
-                               void *addr = kmap_atomic(page);
+                               void *addr = kmap_atomic(page + i);
                                __cpuc_flush_dcache_area(addr, PAGE_SIZE);
                                kunmap_atomic(addr);
                        }
                } else {
                        for (i = 0; i < (1 << compound_order(page)); i++) {
-                               void *addr = kmap_high_get(page);
+                               void *addr = kmap_high_get(page + i);
                                if (addr) {
                                        __cpuc_flush_dcache_area(addr, PAGE_SIZE);
-                                       kunmap_high(page);
+                                       kunmap_high(page + i);
                                }
                        }
                }
index 1f7b19a470606726595ebc692f3b05aae94729c6..3e8f106ee5fe01855fe12f66b0c581822c0521da 100644 (file)
@@ -229,7 +229,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc)
 #ifdef CONFIG_ZONE_DMA
        if (mdesc->dma_zone_size) {
                arm_dma_zone_size = mdesc->dma_zone_size;
-               arm_dma_limit = __pv_phys_offset + arm_dma_zone_size - 1;
+               arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
        } else
                arm_dma_limit = 0xffffffff;
        arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT;
index 9ed155ad0f97c42c80fd903919a51dac8b0298d4..271b5e9715682ab40869a1ea8a02c9696eaebf07 100644 (file)
@@ -641,10 +641,10 @@ load_ind:
                        emit(ARM_MUL(r_A, r_A, r_X), ctx);
                        break;
                case BPF_S_ALU_DIV_K:
-                       /* current k == reciprocal_value(userspace k) */
+                       if (k == 1)
+                               break;
                        emit_mov_i(r_scratch, k, ctx);
-                       /* A = top 32 bits of the product */
-                       emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
+                       emit_udiv(r_A, r_A, r_scratch, ctx);
                        break;
                case BPF_S_ALU_DIV_X:
                        update_on_xread(ctx);
index 83e4f959ee47c6b9b18a77d9f50995b7b4fc5ab0..85501238b4258316272f9448ad8829b18a1111b2 100644 (file)
@@ -96,7 +96,7 @@ static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
        struct remap_data *info = data;
        struct page *page = info->pages[info->index++];
        unsigned long pfn = page_to_pfn(page);
-       pte_t pte = pfn_pte(pfn, info->prot);
+       pte_t pte = pte_mkspecial(pfn_pte(pfn, info->prot));
 
        if (map_foreign_page(pfn, info->fgmfn, info->domid))
                return -EFAULT;
@@ -224,10 +224,10 @@ static int __init xen_guest_init(void)
        }
        if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
                return 0;
-       xen_hvm_resume_frames = res.start >> PAGE_SHIFT;
+       xen_hvm_resume_frames = res.start;
        xen_events_irq = irq_of_parse_and_map(node, 0);
        pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n",
-                       version, xen_events_irq, xen_hvm_resume_frames);
+                       version, xen_events_irq, (xen_hvm_resume_frames >> PAGE_SHIFT));
        xen_domain_type = XEN_HVM_DOMAIN;
 
        xen_setup_features();
index 57276972722768b86f5c21d0cdd50481e1a48683..4cc813eddacbebee4c84f864f103bb6492d7c193 100644 (file)
@@ -229,7 +229,7 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
 extern void __iounmap(volatile void __iomem *addr);
 extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 
-#define PROT_DEFAULT           (pgprot_default | PTE_DIRTY)
+#define PROT_DEFAULT           (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
 #define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
 #define PROT_NORMAL            (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))
index 2820f1a6eebe0252d280e5d56e0a6bc60ac14182..dde3fc9c49f015c80b43f9ca21f1d996b9d2a910 100644 (file)
@@ -23,25 +23,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir,
             struct dma_attrs *attrs)
 {
-       __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
 }
 
 static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir,
                struct dma_attrs *attrs)
 {
-       __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
 }
 
 static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
-       __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
 }
 
 static inline void xen_dma_sync_single_for_device(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
-       __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
 }
 #endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */
index 6777a2192b83846f1065f442f5777d4092e9bc0c..6a8928bba03c9e8135c4481b497268f7018ca393 100644 (file)
@@ -214,31 +214,29 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
 {
        int err, len, type, disabled = !ctrl.enabled;
 
-       if (disabled) {
-               len = 0;
-               type = HW_BREAKPOINT_EMPTY;
-       } else {
-               err = arch_bp_generic_fields(ctrl, &len, &type);
-               if (err)
-                       return err;
-
-               switch (note_type) {
-               case NT_ARM_HW_BREAK:
-                       if ((type & HW_BREAKPOINT_X) != type)
-                               return -EINVAL;
-                       break;
-               case NT_ARM_HW_WATCH:
-                       if ((type & HW_BREAKPOINT_RW) != type)
-                               return -EINVAL;
-                       break;
-               default:
+       attr->disabled = disabled;
+       if (disabled)
+               return 0;
+
+       err = arch_bp_generic_fields(ctrl, &len, &type);
+       if (err)
+               return err;
+
+       switch (note_type) {
+       case NT_ARM_HW_BREAK:
+               if ((type & HW_BREAKPOINT_X) != type)
                        return -EINVAL;
-               }
+               break;
+       case NT_ARM_HW_WATCH:
+               if ((type & HW_BREAKPOINT_RW) != type)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
        }
 
        attr->bp_len    = len;
        attr->bp_type   = type;
-       attr->disabled  = disabled;
 
        return 0;
 }
index c75025f27c201f02a9b85f65c2fdbbc529768325..06b9bc7ea14b1da802dc29090174230cc2e1d613 100644 (file)
@@ -83,6 +83,6 @@
 /*
  * Loongson2-specific cacheops
  */
-#define Hit_Invalidate_I_Loongson23    0x00
+#define Hit_Invalidate_I_Loongson2     0x00
 
 #endif /* __ASM_CACHEOPS_H */
index 34d1a19171257ff8d8e602988615b8b8e2878ff9..c84caddb8bdedea260acac25a71c0d5a9c59ef19 100644 (file)
@@ -165,7 +165,7 @@ static inline void flush_icache_line(unsigned long addr)
        __iflush_prologue
        switch (boot_cpu_type()) {
        case CPU_LOONGSON2:
-               cache_op(Hit_Invalidate_I_Loongson23, addr);
+               cache_op(Hit_Invalidate_I_Loongson2, addr);
                break;
 
        default:
@@ -219,7 +219,7 @@ static inline void protected_flush_icache_line(unsigned long addr)
 {
        switch (boot_cpu_type()) {
        case CPU_LOONGSON2:
-               protected_cache_op(Hit_Invalidate_I_Loongson23, addr);
+               protected_cache_op(Hit_Invalidate_I_Loongson2, addr);
                break;
 
        default:
@@ -357,8 +357,8 @@ static inline void invalidate_tcache_page(unsigned long addr)
                  "i" (op));
 
 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
-static inline void blast_##pfx##cache##lsize(void)                     \
+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra)   \
+static inline void extra##blast_##pfx##cache##lsize(void)              \
 {                                                                      \
        unsigned long start = INDEX_BASE;                               \
        unsigned long end = start + current_cpu_data.desc.waysize;      \
@@ -376,7 +376,7 @@ static inline void blast_##pfx##cache##lsize(void)                  \
        __##pfx##flush_epilogue                                         \
 }                                                                      \
                                                                        \
-static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
+static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \
 {                                                                      \
        unsigned long start = page;                                     \
        unsigned long end = page + PAGE_SIZE;                           \
@@ -391,7 +391,7 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
        __##pfx##flush_epilogue                                         \
 }                                                                      \
                                                                        \
-static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
+static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
 {                                                                      \
        unsigned long indexmask = current_cpu_data.desc.waysize - 1;    \
        unsigned long start = INDEX_BASE + (page & indexmask);          \
@@ -410,23 +410,24 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
        __##pfx##flush_epilogue                                         \
 }
 
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
-
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
+
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
 
 /* build blast_xxx_range, protected_blast_xxx_range */
 #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra)       \
@@ -452,8 +453,8 @@ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start,
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson23, \
-       protected_, loongson23_)
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \
+       protected_, loongson2_)
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
 /* blast_inv_dcache_range */
index 62ffd20ea86909be81906691dd1531a35733c410..49e572d879e1348234bc1413f2e9f25e593d9318 100644 (file)
@@ -237,6 +237,8 @@ static void r4k_blast_icache_page_setup(void)
                r4k_blast_icache_page = (void *)cache_noop;
        else if (ic_lsize == 16)
                r4k_blast_icache_page = blast_icache16_page;
+       else if (ic_lsize == 32 && current_cpu_type() == CPU_LOONGSON2)
+               r4k_blast_icache_page = loongson2_blast_icache32_page;
        else if (ic_lsize == 32)
                r4k_blast_icache_page = blast_icache32_page;
        else if (ic_lsize == 64)
@@ -261,6 +263,9 @@ static void r4k_blast_icache_page_indexed_setup(void)
                else if (TX49XX_ICACHE_INDEX_INV_WAR)
                        r4k_blast_icache_page_indexed =
                                tx49_blast_icache32_page_indexed;
+               else if (current_cpu_type() == CPU_LOONGSON2)
+                       r4k_blast_icache_page_indexed =
+                               loongson2_blast_icache32_page_indexed;
                else
                        r4k_blast_icache_page_indexed =
                                blast_icache32_page_indexed;
@@ -284,6 +289,8 @@ static void r4k_blast_icache_setup(void)
                        r4k_blast_icache = blast_r4600_v1_icache32;
                else if (TX49XX_ICACHE_INDEX_INV_WAR)
                        r4k_blast_icache = tx49_blast_icache32;
+               else if (current_cpu_type() == CPU_LOONGSON2)
+                       r4k_blast_icache = loongson2_blast_icache32;
                else
                        r4k_blast_icache = blast_icache32;
        } else if (ic_lsize == 64)
@@ -580,11 +587,11 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo
        else {
                switch (boot_cpu_type()) {
                case CPU_LOONGSON2:
-                       protected_blast_icache_range(start, end);
+                       protected_loongson2_blast_icache_range(start, end);
                        break;
 
                default:
-                       protected_loongson23_blast_icache_range(start, end);
+                       protected_blast_icache_range(start, end);
                        break;
                }
        }
index f0e2784e7ccacd6c6d0856ce87d1f1d26e81c083..2f9b751878ba86bf6cc32cfdadd9b7847ad158d5 100644 (file)
@@ -125,42 +125,38 @@ flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vma
 void mark_rodata_ro(void);
 #endif
 
-#ifdef CONFIG_PA8X00
-/* Only pa8800, pa8900 needs this */
-
 #include <asm/kmap_types.h>
 
 #define ARCH_HAS_KMAP
 
-void kunmap_parisc(void *addr);
-
 static inline void *kmap(struct page *page)
 {
        might_sleep();
+       flush_dcache_page(page);
        return page_address(page);
 }
 
 static inline void kunmap(struct page *page)
 {
-       kunmap_parisc(page_address(page));
+       flush_kernel_dcache_page_addr(page_address(page));
 }
 
 static inline void *kmap_atomic(struct page *page)
 {
        pagefault_disable();
+       flush_dcache_page(page);
        return page_address(page);
 }
 
 static inline void __kunmap_atomic(void *addr)
 {
-       kunmap_parisc(addr);
+       flush_kernel_dcache_page_addr(addr);
        pagefault_enable();
 }
 
 #define kmap_atomic_prot(page, prot)   kmap_atomic(page)
 #define kmap_atomic_pfn(pfn)   kmap_atomic(pfn_to_page(pfn))
 #define kmap_atomic_to_page(ptr)       virt_to_page(ptr)
-#endif
 
 #endif /* _PARISC_CACHEFLUSH_H */
 
index b7adb2ac049c0e6b72817dee3df92d124c612e42..c53fc63149e8312437fe4109e8070495ba39d90a 100644 (file)
@@ -28,9 +28,8 @@ struct page;
 
 void clear_page_asm(void *page);
 void copy_page_asm(void *to, void *from);
-void clear_user_page(void *vto, unsigned long vaddr, struct page *pg);
-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-                          struct page *pg);
+#define clear_user_page(vto, vaddr, page) clear_page_asm(vto)
+#define copy_user_page(vto, vfrom, vaddr, page) copy_page_asm(vto, vfrom)
 
 /* #define CONFIG_PARISC_TMPALIAS */
 
index f33113a6141e7540da2195cc72469152edfbecf2..70b3674dac4e39c1048b1844dc53dee85f907296 100644 (file)
@@ -75,6 +75,6 @@
 
 #define SO_BUSY_POLL           0x4027
 
-#define SO_MAX_PACING_RATE     0x4048
+#define SO_MAX_PACING_RATE     0x4028
 
 #endif /* _UAPI_ASM_SOCKET_H */
index c035673209f732f0850aaa4dc98d2d49eee3b74c..a72545554a3154c254eace0648a769d4df645b25 100644 (file)
@@ -388,41 +388,6 @@ void flush_kernel_dcache_page_addr(void *addr)
 }
 EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
 
-void clear_user_page(void *vto, unsigned long vaddr, struct page *page)
-{
-       clear_page_asm(vto);
-       if (!parisc_requires_coherency())
-               flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(clear_user_page);
-
-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-       struct page *pg)
-{
-       /* Copy using kernel mapping.  No coherency is needed
-          (all in kmap/kunmap) on machines that don't support
-          non-equivalent aliasing.  However, the `from' page
-          needs to be flushed before it can be accessed through
-          the kernel mapping. */
-       preempt_disable();
-       flush_dcache_page_asm(__pa(vfrom), vaddr);
-       preempt_enable();
-       copy_page_asm(vto, vfrom);
-       if (!parisc_requires_coherency())
-               flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(copy_user_page);
-
-#ifdef CONFIG_PA8X00
-
-void kunmap_parisc(void *addr)
-{
-       if (parisc_requires_coherency())
-               flush_kernel_dcache_page_addr(addr);
-}
-EXPORT_SYMBOL(kunmap_parisc);
-#endif
-
 void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 {
        unsigned long flags;
index 4177b62240c2440ff19f6089cb84cd5b9e0d27a0..a618dfc13e4c8f88a5ff70b88325fd39675c9e8a 100644 (file)
@@ -58,7 +58,6 @@
                compatible = "fsl,mpc5121-immr";
                #address-cells = <1>;
                #size-cells = <1>;
-               #interrupt-cells = <2>;
                ranges = <0x0 0x80000000 0x400000>;
                reg = <0x80000000 0x400000>;
                bus-frequency = <66000000>;     // 66 MHz ips bus
                        reg = <0xA000 0x1000>;
                };
 
+               // disable USB1 port
+               // TODO:
+               // correct pinmux config and fix USB3320 ulpi dependency
+               // before re-enabling it
                usb@3000 {
                        compatible = "fsl,mpc5121-usb2-dr";
                        reg = <0x3000 0x400>;
                        interrupts = <43 0x8>;
                        dr_mode = "host";
                        phy_type = "ulpi";
+                       status = "disabled";
                };
 
                // 5125 PSCs are not 52xx or 5121 PSC compatible
index 894662a5d4d5c5aa25f43e30653609d80d901774..243ce69ad685ffd335041537e6f0b33b0aafe3df 100644 (file)
@@ -284,7 +284,7 @@ do_kvm_##n:                                                         \
        subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack  */ \
        beq-    1f;                                                        \
        ld      r1,PACAKSAVE(r13);      /* kernel stack to use          */ \
-1:     cmpdi   cr1,r1,0;               /* check if r1 is in userspace  */ \
+1:     cmpdi   cr1,r1,-INT_FRAME_SIZE; /* check if r1 is in userspace  */ \
        blt+    cr1,3f;                 /* abort if it is               */ \
        li      r1,(n);                 /* will be reloaded later       */ \
        sth     r1,PACA_TRAP_SAVE(r13);                                    \
index 4a594b76674d4e536ce714b40c183f598bf380d6..bc23b1ba798068b1c5a1f21e93da8bd47018ff55 100644 (file)
@@ -192,6 +192,10 @@ extern void kvmppc_load_up_vsx(void);
 extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
 extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
 extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
+extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
+                                struct kvm_vcpu *vcpu);
+extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
+                                  struct kvmppc_book3s_shadow_vcpu *svcpu);
 
 static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 {
index 0bd9348a4db91264d5e8a104f17ed77afcd5f815..192917d2239c4ed5a0eafd36b1206d176f0dddaa 100644 (file)
@@ -79,6 +79,7 @@ struct kvmppc_host_state {
        ulong vmhandler;
        ulong scratch0;
        ulong scratch1;
+       ulong scratch2;
        u8 in_guest;
        u8 restore_hid5;
        u8 napping;
@@ -106,6 +107,7 @@ struct kvmppc_host_state {
 };
 
 struct kvmppc_book3s_shadow_vcpu {
+       bool in_use;
        ulong gpr[14];
        u32 cr;
        u32 xer;
index 033c06be1d840da02423d596121940d0aa11adb5..7bdcf340016c412285df77ac56162aaa94982416 100644 (file)
@@ -720,13 +720,13 @@ int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe,
 int64_t opal_pci_poll(uint64_t phb_id);
 int64_t opal_return_cpu(void);
 
-int64_t opal_xscom_read(uint32_t gcid, uint32_t pcb_addr, uint64_t *val);
+int64_t opal_xscom_read(uint32_t gcid, uint32_t pcb_addr, __be64 *val);
 int64_t opal_xscom_write(uint32_t gcid, uint32_t pcb_addr, uint64_t val);
 
 int64_t opal_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type,
                       uint32_t addr, uint32_t data, uint32_t sz);
 int64_t opal_lpc_read(uint32_t chip_id, enum OpalLPCAddressType addr_type,
-                     uint32_t addr, uint32_t *data, uint32_t sz);
+                     uint32_t addr, __be32 *data, uint32_t sz);
 int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
 int64_t opal_manage_flash(uint8_t op);
 int64_t opal_update_flash(uint64_t blk_list);
index 9ee12610af02bdca7fd61b9b7f6b16f2c74d36d0..aace90547614db30ea638945d30d143fbdfb336e 100644 (file)
@@ -35,7 +35,7 @@ extern void giveup_vsx(struct task_struct *);
 extern void enable_kernel_spe(void);
 extern void giveup_spe(struct task_struct *);
 extern void load_up_spe(struct task_struct *);
-extern void switch_booke_debug_regs(struct thread_struct *new_thread);
+extern void switch_booke_debug_regs(struct debug_reg *new_debug);
 
 #ifndef CONFIG_SMP
 extern void discard_lazy_cpu_state(void);
index 5f1b1e3c21374d5a1833ed00c9af9d5c06a35123..8296381ae43294e679976f6a82d3bb936d64921f 100644 (file)
@@ -4,13 +4,18 @@
 #ifdef __KERNEL__
 
 /*
- * The PowerPC can do unaligned accesses itself in big endian mode.
+ * The PowerPC can do unaligned accesses itself based on its endian mode.
  */
 #include <linux/unaligned/access_ok.h>
 #include <linux/unaligned/generic.h>
 
+#ifdef __LITTLE_ENDIAN__
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
+#else
 #define get_unaligned  __get_unaligned_be
 #define put_unaligned  __put_unaligned_be
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UNALIGNED_H */
index 2ea5cc033ec8b633febb50071c43cfd31958f4f3..d3de01066f7dd786cd531614046b801ff7ebb18f 100644 (file)
@@ -576,6 +576,7 @@ int main(void)
        HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
        HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
        HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
+       HSTATE_FIELD(HSTATE_SCRATCH2, scratch2);
        HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
        HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
        HSTATE_FIELD(HSTATE_NAPPING, napping);
index 779a78c2643502a4414af7d646f4dce810deba72..11c1d069d920a1fc97ec601ab0542c41708d7cc1 100644 (file)
@@ -124,15 +124,15 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
 void crash_free_reserved_phys_range(unsigned long begin, unsigned long end)
 {
        unsigned long addr;
-       const u32 *basep, *sizep;
+       const __be32 *basep, *sizep;
        unsigned int rtas_start = 0, rtas_end = 0;
 
        basep = of_get_property(rtas.dev, "linux,rtas-base", NULL);
        sizep = of_get_property(rtas.dev, "rtas-size", NULL);
 
        if (basep && sizep) {
-               rtas_start = *basep;
-               rtas_end = *basep + *sizep;
+               rtas_start = be32_to_cpup(basep);
+               rtas_end = rtas_start + be32_to_cpup(sizep);
        }
 
        for (addr = begin; addr < end; addr += PAGE_SIZE) {
index 2ae41aba40530f7facf916f6ce101ad3196a7363..4f0946de2d5c917540f6f51a50c13640011fea8c 100644 (file)
@@ -80,6 +80,7 @@ END_FTR_SECTION(0, 1)
         * of the function that the cpu should jump to to continue
         * initialization.
         */
+       .balign 8
        .globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
        .llong  0x0
@@ -470,6 +471,7 @@ _STATIC(__after_prom_start)
        mtctr   r8
        bctr
 
+.balign 8
 p_end: .llong  _end - _stext
 
 4:     /* Now copy the rest of the kernel up to _end */
index 3386d8ab7eb0607b3c9d6f03e68824d4abe4bd88..4a96556fd2d49e484c143ed3643db6c8a24962df 100644 (file)
@@ -339,7 +339,7 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
 #endif
 }
 
-static void prime_debug_regs(struct thread_struct *thread)
+static void prime_debug_regs(struct debug_reg *debug)
 {
        /*
         * We could have inherited MSR_DE from userspace, since
@@ -348,22 +348,22 @@ static void prime_debug_regs(struct thread_struct *thread)
         */
        mtmsr(mfmsr() & ~MSR_DE);
 
-       mtspr(SPRN_IAC1, thread->debug.iac1);
-       mtspr(SPRN_IAC2, thread->debug.iac2);
+       mtspr(SPRN_IAC1, debug->iac1);
+       mtspr(SPRN_IAC2, debug->iac2);
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
-       mtspr(SPRN_IAC3, thread->debug.iac3);
-       mtspr(SPRN_IAC4, thread->debug.iac4);
+       mtspr(SPRN_IAC3, debug->iac3);
+       mtspr(SPRN_IAC4, debug->iac4);
 #endif
-       mtspr(SPRN_DAC1, thread->debug.dac1);
-       mtspr(SPRN_DAC2, thread->debug.dac2);
+       mtspr(SPRN_DAC1, debug->dac1);
+       mtspr(SPRN_DAC2, debug->dac2);
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
-       mtspr(SPRN_DVC1, thread->debug.dvc1);
-       mtspr(SPRN_DVC2, thread->debug.dvc2);
+       mtspr(SPRN_DVC1, debug->dvc1);
+       mtspr(SPRN_DVC2, debug->dvc2);
 #endif
-       mtspr(SPRN_DBCR0, thread->debug.dbcr0);
-       mtspr(SPRN_DBCR1, thread->debug.dbcr1);
+       mtspr(SPRN_DBCR0, debug->dbcr0);
+       mtspr(SPRN_DBCR1, debug->dbcr1);
 #ifdef CONFIG_BOOKE
-       mtspr(SPRN_DBCR2, thread->debug.dbcr2);
+       mtspr(SPRN_DBCR2, debug->dbcr2);
 #endif
 }
 /*
@@ -371,11 +371,11 @@ static void prime_debug_regs(struct thread_struct *thread)
  * debug registers, set the debug registers from the values
  * stored in the new thread.
  */
-void switch_booke_debug_regs(struct thread_struct *new_thread)
+void switch_booke_debug_regs(struct debug_reg *new_debug)
 {
        if ((current->thread.debug.dbcr0 & DBCR0_IDM)
-               || (new_thread->debug.dbcr0 & DBCR0_IDM))
-                       prime_debug_regs(new_thread);
+               || (new_debug->dbcr0 & DBCR0_IDM))
+                       prime_debug_regs(new_debug);
 }
 EXPORT_SYMBOL_GPL(switch_booke_debug_regs);
 #else  /* !CONFIG_PPC_ADV_DEBUG_REGS */
@@ -683,7 +683,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-       switch_booke_debug_regs(&new->thread);
+       switch_booke_debug_regs(&new->thread.debug);
 #else
 /*
  * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would
index cb64a6e1dc5186918b4d2052e52e961cfb14eedb..078145acf7fb867dca6278f776a935ba0b2ecf25 100644 (file)
@@ -1986,19 +1986,23 @@ static void __init prom_init_stdout(void)
        /* Get the full OF pathname of the stdout device */
        memset(path, 0, 256);
        call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
-       stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
-       val = cpu_to_be32(stdout_node);
-       prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
-                    &val, sizeof(val));
        prom_printf("OF stdout device is: %s\n", of_stdout_device);
        prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
                     path, strlen(path) + 1);
 
-       /* If it's a display, note it */
-       memset(type, 0, sizeof(type));
-       prom_getprop(stdout_node, "device_type", type, sizeof(type));
-       if (strcmp(type, "display") == 0)
-               prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
+       /* instance-to-package fails on PA-Semi */
+       stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
+       if (stdout_node != PROM_ERROR) {
+               val = cpu_to_be32(stdout_node);
+               prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
+                            &val, sizeof(val));
+
+               /* If it's a display, note it */
+               memset(type, 0, sizeof(type));
+               prom_getprop(stdout_node, "device_type", type, sizeof(type));
+               if (strcmp(type, "display") == 0)
+                       prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
+       }
 }
 
 static int __init prom_find_machine_type(void)
index 75fb40498b419c3e8c1f2c639acfaa4f61f419d2..2e3d2bf536c5662c00f02e07cf36cd1e4b111825 100644 (file)
@@ -1555,7 +1555,7 @@ long arch_ptrace(struct task_struct *child, long request,
 
                        flush_fp_to_thread(child);
                        if (fpidx < (PT_FPSCR - PT_FPR0))
-                               memcpy(&tmp, &child->thread.fp_state.fpr,
+                               memcpy(&tmp, &child->thread.TS_FPR(fpidx),
                                       sizeof(long));
                        else
                                tmp = child->thread.fp_state.fpscr;
@@ -1588,7 +1588,7 @@ long arch_ptrace(struct task_struct *child, long request,
 
                        flush_fp_to_thread(child);
                        if (fpidx < (PT_FPSCR - PT_FPR0))
-                               memcpy(&child->thread.fp_state.fpr, &data,
+                               memcpy(&child->thread.TS_FPR(fpidx), &data,
                                       sizeof(long));
                        else
                                child->thread.fp_state.fpscr = data;
index febc80445d25850acf2578943c60357d8436b1c2..bc76cc6b419c2a8d0b5491637afadfe046278142 100644 (file)
@@ -479,7 +479,7 @@ void __init smp_setup_cpu_maps(void)
        if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) &&
            (dn = of_find_node_by_path("/rtas"))) {
                int num_addr_cell, num_size_cell, maxcpus;
-               const unsigned int *ireg;
+               const __be32 *ireg;
 
                num_addr_cell = of_n_addr_cells(dn);
                num_size_cell = of_n_size_cells(dn);
@@ -489,7 +489,7 @@ void __init smp_setup_cpu_maps(void)
                if (!ireg)
                        goto out;
 
-               maxcpus = ireg[num_addr_cell + num_size_cell];
+               maxcpus = be32_to_cpup(ireg + num_addr_cell + num_size_cell);
 
                /* Double maxcpus for processors which have SMT capability */
                if (cpu_has_feature(CPU_FTR_SMT))
index a3b64f3bf9a298b057cfdc57b008ea01eebecf63..c1cf4a1522d9940bf3bb97a3e995a2642dee41ca 100644 (file)
@@ -580,7 +580,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 int cpu_to_core_id(int cpu)
 {
        struct device_node *np;
-       const int *reg;
+       const __be32 *reg;
        int id = -1;
 
        np = of_get_cpu_node(cpu, NULL);
@@ -591,7 +591,7 @@ int cpu_to_core_id(int cpu)
        if (!reg)
                goto out;
 
-       id = *reg;
+       id = be32_to_cpup(reg);
 out:
        of_node_put(np);
        return id;
index f3ff587a8b7d58e064e6364606e98a0e6473f106..c5d148434c08197034eba8ababd951176adb6a1f 100644 (file)
@@ -469,11 +469,14 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
                slb_v = vcpu->kvm->arch.vrma_slb_v;
        }
 
+       preempt_disable();
        /* Find the HPTE in the hash table */
        index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
                                         HPTE_V_VALID | HPTE_V_ABSENT);
-       if (index < 0)
+       if (index < 0) {
+               preempt_enable();
                return -ENOENT;
+       }
        hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
        v = hptep[0] & ~HPTE_V_HVLOCK;
        gr = kvm->arch.revmap[index].guest_rpte;
@@ -481,6 +484,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
        /* Unlock the HPTE */
        asm volatile("lwsync" : : : "memory");
        hptep[0] = v;
+       preempt_enable();
 
        gpte->eaddr = eaddr;
        gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff);
@@ -665,6 +669,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        return -EFAULT;
        } else {
                page = pages[0];
+               pfn = page_to_pfn(page);
                if (PageHuge(page)) {
                        page = compound_head(page);
                        pte_size <<= compound_order(page);
@@ -689,7 +694,6 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        }
                        rcu_read_unlock_sched();
                }
-               pfn = page_to_pfn(page);
        }
 
        ret = -EFAULT;
@@ -707,8 +711,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                r = (r & ~(HPTE_R_W|HPTE_R_I|HPTE_R_G)) | HPTE_R_M;
        }
 
-       /* Set the HPTE to point to pfn */
-       r = (r & ~(HPTE_R_PP0 - pte_size)) | (pfn << PAGE_SHIFT);
+       /*
+        * Set the HPTE to point to pfn.
+        * Since the pfn is at PAGE_SIZE granularity, make sure we
+        * don't mask out lower-order bits if psize < PAGE_SIZE.
+        */
+       if (psize < PAGE_SIZE)
+               psize = PAGE_SIZE;
+       r = (r & ~(HPTE_R_PP0 - psize)) | ((pfn << PAGE_SHIFT) & ~(psize - 1));
        if (hpte_is_writable(r) && !write_ok)
                r = hpte_make_readonly(r);
        ret = RESUME_GUEST;
index 072287f1c3bc7347b6ff4f959843c97053fa4aa1..b51d5db780684ea5dcb3b6dae5c5bc70224dca43 100644 (file)
@@ -131,8 +131,9 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
 static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       unsigned long flags;
 
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE &&
            vc->preempt_tb != TB_NIL) {
                vc->stolen_tb += mftb() - vc->preempt_tb;
@@ -143,19 +144,20 @@ static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
                vcpu->arch.busy_stolen += mftb() - vcpu->arch.busy_preempt;
                vcpu->arch.busy_preempt = TB_NIL;
        }
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags);
 }
 
 static void kvmppc_core_vcpu_put_hv(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       unsigned long flags;
 
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
                vc->preempt_tb = mftb();
        if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST)
                vcpu->arch.busy_preempt = mftb();
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags);
 }
 
 static void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
@@ -486,11 +488,11 @@ static u64 vcore_stolen_time(struct kvmppc_vcore *vc, u64 now)
         */
        if (vc->vcore_state != VCORE_INACTIVE &&
            vc->runner->arch.run_task != current) {
-               spin_lock(&vc->runner->arch.tbacct_lock);
+               spin_lock_irq(&vc->runner->arch.tbacct_lock);
                p = vc->stolen_tb;
                if (vc->preempt_tb != TB_NIL)
                        p += now - vc->preempt_tb;
-               spin_unlock(&vc->runner->arch.tbacct_lock);
+               spin_unlock_irq(&vc->runner->arch.tbacct_lock);
        } else {
                p = vc->stolen_tb;
        }
@@ -512,10 +514,10 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
        core_stolen = vcore_stolen_time(vc, now);
        stolen = core_stolen - vcpu->arch.stolen_logged;
        vcpu->arch.stolen_logged = core_stolen;
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irq(&vcpu->arch.tbacct_lock);
        stolen += vcpu->arch.busy_stolen;
        vcpu->arch.busy_stolen = 0;
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irq(&vcpu->arch.tbacct_lock);
        if (!dt || !vpa)
                return;
        memset(dt, 0, sizeof(struct dtl_entry));
@@ -589,7 +591,9 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
                if (list_empty(&vcpu->kvm->arch.rtas_tokens))
                        return RESUME_HOST;
 
+               idx = srcu_read_lock(&vcpu->kvm->srcu);
                rc = kvmppc_rtas_hcall(vcpu);
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
                if (rc == -ENOENT)
                        return RESUME_HOST;
@@ -1115,13 +1119,13 @@ static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
 
        if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
                return;
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irq(&vcpu->arch.tbacct_lock);
        now = mftb();
        vcpu->arch.busy_stolen += vcore_stolen_time(vc, now) -
                vcpu->arch.stolen_logged;
        vcpu->arch.busy_preempt = now;
        vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irq(&vcpu->arch.tbacct_lock);
        --vc->n_runnable;
        list_del(&vcpu->arch.run_list);
 }
index 9c515440ad1ae7e0451d3b3b67dd029ab06a0ebb..8689e2e308573b0df26996e2ebfed77e235df59c 100644 (file)
@@ -225,6 +225,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                is_io = pa & (HPTE_R_I | HPTE_R_W);
                pte_size = PAGE_SIZE << (pa & KVMPPC_PAGE_ORDER_MASK);
                pa &= PAGE_MASK;
+               pa |= gpa & ~PAGE_MASK;
        } else {
                /* Translate to host virtual address */
                hva = __gfn_to_hva_memslot(memslot, gfn);
@@ -238,13 +239,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                                ptel = hpte_make_readonly(ptel);
                        is_io = hpte_cache_bits(pte_val(pte));
                        pa = pte_pfn(pte) << PAGE_SHIFT;
+                       pa |= hva & (pte_size - 1);
+                       pa |= gpa & ~PAGE_MASK;
                }
        }
 
        if (pte_size < psize)
                return H_PARAMETER;
-       if (pa && pte_size > psize)
-               pa |= gpa & (pte_size - 1);
 
        ptel &= ~(HPTE_R_PP0 - psize);
        ptel |= pa;
@@ -749,6 +750,10 @@ static int slb_base_page_shift[4] = {
        20,     /* 1M, unsupported */
 };
 
+/* When called from virtmode, this func should be protected by
+ * preempt_disable(), otherwise, the holding of HPTE_V_HVLOCK
+ * can trigger deadlock issue.
+ */
 long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
                              unsigned long valid)
 {
index bc8de75b1925cd34ad1d11379fee8c09f1d275e5..be4fa04a37c96d56d5f07d241395afe22e1627dd 100644 (file)
@@ -153,7 +153,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 13:    b       machine_check_fwnmi
 
-
 /*
  * We come in here when wakened from nap mode on a secondary hw thread.
  * Relocation is off and most register values are lost.
@@ -224,6 +223,11 @@ kvm_start_guest:
        /* Clear our vcpu pointer so we don't come back in early */
        li      r0, 0
        std     r0, HSTATE_KVM_VCPU(r13)
+       /*
+        * Make sure we clear HSTATE_KVM_VCPU(r13) before incrementing
+        * the nap_count, because once the increment to nap_count is
+        * visible we could be given another vcpu.
+        */
        lwsync
        /* Clear any pending IPI - we're an offline thread */
        ld      r5, HSTATE_XICS_PHYS(r13)
@@ -241,7 +245,6 @@ kvm_start_guest:
        /* increment the nap count and then go to nap mode */
        ld      r4, HSTATE_KVM_VCORE(r13)
        addi    r4, r4, VCORE_NAP_COUNT
-       lwsync                          /* make previous updates visible */
 51:    lwarx   r3, 0, r4
        addi    r3, r3, 1
        stwcx.  r3, 0, r4
@@ -751,15 +754,14 @@ kvmppc_interrupt_hv:
         * guest CR, R12 saved in shadow VCPU SCRATCH1/0
         * guest R13 saved in SPRN_SCRATCH0
         */
-       /* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */
-       std     r9, HSTATE_HOST_R2(r13)
+       std     r9, HSTATE_SCRATCH2(r13)
 
        lbz     r9, HSTATE_IN_GUEST(r13)
        cmpwi   r9, KVM_GUEST_MODE_HOST_HV
        beq     kvmppc_bad_host_intr
 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        cmpwi   r9, KVM_GUEST_MODE_GUEST
-       ld      r9, HSTATE_HOST_R2(r13)
+       ld      r9, HSTATE_SCRATCH2(r13)
        beq     kvmppc_interrupt_pr
 #endif
        /* We're now back in the host but in guest MMU context */
@@ -779,7 +781,7 @@ kvmppc_interrupt_hv:
        std     r6, VCPU_GPR(R6)(r9)
        std     r7, VCPU_GPR(R7)(r9)
        std     r8, VCPU_GPR(R8)(r9)
-       ld      r0, HSTATE_HOST_R2(r13)
+       ld      r0, HSTATE_SCRATCH2(r13)
        std     r0, VCPU_GPR(R9)(r9)
        std     r10, VCPU_GPR(R10)(r9)
        std     r11, VCPU_GPR(R11)(r9)
@@ -990,14 +992,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
         */
        /* Increment the threads-exiting-guest count in the 0xff00
           bits of vcore->entry_exit_count */
-       lwsync
        ld      r5,HSTATE_KVM_VCORE(r13)
        addi    r6,r5,VCORE_ENTRY_EXIT
 41:    lwarx   r3,0,r6
        addi    r0,r3,0x100
        stwcx.  r0,0,r6
        bne     41b
-       lwsync
+       isync           /* order stwcx. vs. reading napping_threads */
 
        /*
         * At this point we have an interrupt that we have to pass
@@ -1030,6 +1031,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        sld     r0,r0,r4
        andc.   r3,r3,r0                /* no sense IPI'ing ourselves */
        beq     43f
+       /* Order entry/exit update vs. IPIs */
+       sync
        mulli   r4,r4,PACA_SIZE         /* get paca for thread 0 */
        subf    r6,r4,r13
 42:    andi.   r0,r3,1
@@ -1638,10 +1641,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
        bge     kvm_cede_exit
        stwcx.  r4,0,r6
        bne     31b
+       /* order napping_threads update vs testing entry_exit_count */
+       isync
        li      r0,1
        stb     r0,HSTATE_NAPPING(r13)
-       /* order napping_threads update vs testing entry_exit_count */
-       lwsync
        mr      r4,r3
        lwz     r7,VCORE_ENTRY_EXIT(r5)
        cmpwi   r7,0x100
index f4dd041c14eac9400fb012beae92792fe9c9cfd1..f779450cb07c728681ede6d566ef85920117337e 100644 (file)
@@ -129,29 +129,32 @@ kvm_start_lightweight:
         * R12      = exit handler id
         * R13      = PACA
         * SVCPU.*  = guest *
+        * MSR.EE   = 1
         *
         */
 
+       PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
+
+       /*
+        * kvmppc_copy_from_svcpu can clobber volatile registers, save
+        * the exit handler id to the vcpu and restore it from there later.
+        */
+       stw     r12, VCPU_TRAP(r3)
+
        /* Transfer reg values from shadow vcpu back to vcpu struct */
        /* On 64-bit, interrupts are still off at this point */
-       PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
+
        GET_SHADOW_VCPU(r4)
        bl      FUNC(kvmppc_copy_from_svcpu)
        nop
 
 #ifdef CONFIG_PPC_BOOK3S_64
-       /* Re-enable interrupts */
-       ld      r3, HSTATE_HOST_MSR(r13)
-       ori     r3, r3, MSR_EE
-       MTMSR_EERI(r3)
-
        /*
         * Reload kernel SPRG3 value.
         * No need to save guest value as usermode can't modify SPRG3.
         */
        ld      r3, PACA_SPRG3(r13)
        mtspr   SPRN_SPRG3, r3
-
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
        /* R7 = vcpu */
@@ -177,7 +180,7 @@ kvm_start_lightweight:
        PPC_STL r31, VCPU_GPR(R31)(r7)
 
        /* Pass the exit number as 3rd argument to kvmppc_handle_exit */
-       mr      r5, r12
+       lwz     r5, VCPU_TRAP(r7)
 
        /* Restore r3 (kvm_run) and r4 (vcpu) */
        REST_2GPRS(3, r1)
index fe14ca3dd171cd60b3c07191fa3bdd78a141e2a6..5b9e9063cfaf0c407be267a67ab26d35fcc84a93 100644 (file)
@@ -66,6 +66,7 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb));
        svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu->in_use = 0;
        svcpu_put(svcpu);
 #endif
        vcpu->cpu = smp_processor_id();
@@ -78,6 +79,9 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       if (svcpu->in_use) {
+               kvmppc_copy_from_svcpu(vcpu, svcpu);
+       }
        memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
        to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
        svcpu_put(svcpu);
@@ -110,12 +114,26 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
        svcpu->ctr = vcpu->arch.ctr;
        svcpu->lr  = vcpu->arch.lr;
        svcpu->pc  = vcpu->arch.pc;
+       svcpu->in_use = true;
 }
 
 /* Copy data touched by real-mode code from shadow vcpu back to vcpu */
 void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
                            struct kvmppc_book3s_shadow_vcpu *svcpu)
 {
+       /*
+        * vcpu_put would just call us again because in_use hasn't
+        * been updated yet.
+        */
+       preempt_disable();
+
+       /*
+        * Maybe we were already preempted and synced the svcpu from
+        * our preempt notifiers. Don't bother touching this svcpu then.
+        */
+       if (!svcpu->in_use)
+               goto out;
+
        vcpu->arch.gpr[0] = svcpu->gpr[0];
        vcpu->arch.gpr[1] = svcpu->gpr[1];
        vcpu->arch.gpr[2] = svcpu->gpr[2];
@@ -139,6 +157,10 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
        vcpu->arch.fault_dar   = svcpu->fault_dar;
        vcpu->arch.fault_dsisr = svcpu->fault_dsisr;
        vcpu->arch.last_inst   = svcpu->last_inst;
+       svcpu->in_use = false;
+
+out:
+       preempt_enable();
 }
 
 static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu)
index a38c4c9edab87aca16929b5e96377368b5016fbd..c3c5231adade6f3871709a318fed1abc752040fe 100644 (file)
@@ -153,15 +153,11 @@ _GLOBAL(kvmppc_entry_trampoline)
 
        li      r6, MSR_IR | MSR_DR
        andc    r6, r5, r6      /* Clear DR and IR in MSR value */
-#ifdef CONFIG_PPC_BOOK3S_32
        /*
         * Set EE in HOST_MSR so that it's enabled when we get into our
-        * C exit handler function.  On 64-bit we delay enabling
-        * interrupts until we have finished transferring stuff
-        * to or from the PACA.
+        * C exit handler function.
         */
        ori     r5, r5, MSR_EE
-#endif
        mtsrr0  r7
        mtsrr1  r6
        RFI
index 53e65a210b9a451ab1089bfe788277ddda071cf3..0591e05db74b1a1a1f906af6a2a67cf9770320fa 100644 (file)
@@ -681,7 +681,7 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
        int ret, s;
-       struct thread_struct thread;
+       struct debug_reg debug;
 #ifdef CONFIG_PPC_FPU
        struct thread_fp_state fp;
        int fpexc_mode;
@@ -723,9 +723,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
        /* Switch to guest debug context */
-       thread.debug = vcpu->arch.shadow_dbg_reg;
-       switch_booke_debug_regs(&thread);
-       thread.debug = current->thread.debug;
+       debug = vcpu->arch.shadow_dbg_reg;
+       switch_booke_debug_regs(&debug);
+       debug = current->thread.debug;
        current->thread.debug = vcpu->arch.shadow_dbg_reg;
 
        kvmppc_fix_ee_before_entry();
@@ -736,8 +736,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
           We also get here with interrupts enabled. */
 
        /* Switch back to user space debug context */
-       switch_booke_debug_regs(&thread);
-       current->thread.debug = thread.debug;
+       switch_booke_debug_regs(&debug);
+       current->thread.debug = debug;
 
 #ifdef CONFIG_PPC_FPU
        kvmppc_save_guest_fp(vcpu);
index d73a5901490018486fed19115fce46d88084f701..596a285c07554d65dfd561367a52ffed47aba55d 100644 (file)
@@ -9,6 +9,14 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 
+#ifdef __BIG_ENDIAN__
+#define sLd sld                /* Shift towards low-numbered address. */
+#define sHd srd                /* Shift towards high-numbered address. */
+#else
+#define sLd srd                /* Shift towards low-numbered address. */
+#define sHd sld                /* Shift towards high-numbered address. */
+#endif
+
        .align  7
 _GLOBAL(__copy_tofrom_user)
 BEGIN_FTR_SECTION
@@ -118,10 +126,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 24:    ld      r9,0(r4)        /* 3+2n loads, 2+2n stores */
 25:    ld      r0,8(r4)
-       sld     r6,r9,r10
+       sLd     r6,r9,r10
 26:    ldu     r9,16(r4)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        or      r7,r7,r6
        blt     cr6,79f
 27:    ld      r0,8(r4)
@@ -129,35 +137,35 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 28:    ld      r0,0(r4)        /* 4+2n loads, 3+2n stores */
 29:    ldu     r9,8(r4)
-       sld     r8,r0,r10
+       sLd     r8,r0,r10
        addi    r3,r3,-8
        blt     cr6,5f
 30:    ld      r0,8(r4)
-       srd     r12,r9,r11
-       sld     r6,r9,r10
+       sHd     r12,r9,r11
+       sLd     r6,r9,r10
 31:    ldu     r9,16(r4)
        or      r12,r8,r12
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        addi    r3,r3,16
        beq     cr6,78f
 
 1:     or      r7,r7,r6
 32:    ld      r0,8(r4)
 76:    std     r12,8(r3)
-2:     srd     r12,r9,r11
-       sld     r6,r9,r10
+2:     sHd     r12,r9,r11
+       sLd     r6,r9,r10
 33:    ldu     r9,16(r4)
        or      r12,r8,r12
 77:    stdu    r7,16(r3)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        bdnz    1b
 
 78:    std     r12,8(r3)
        or      r7,r7,r6
 79:    std     r7,16(r3)
-5:     srd     r12,r9,r11
+5:     sHd     r12,r9,r11
        or      r12,r8,r12
 80:    std     r12,24(r3)
        bne     6f
@@ -165,23 +173,38 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        blr
 6:     cmpwi   cr1,r5,8
        addi    r3,r3,32
-       sld     r9,r9,r10
+       sLd     r9,r9,r10
        ble     cr1,7f
 34:    ld      r0,8(r4)
-       srd     r7,r0,r11
+       sHd     r7,r0,r11
        or      r9,r7,r9
 7:
        bf      cr7*4+1,1f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,32
+#endif
 94:    stw     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,32
+#endif
        addi    r3,r3,4
 1:     bf      cr7*4+2,2f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,16
+#endif
 95:    sth     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,16
+#endif
        addi    r3,r3,2
 2:     bf      cr7*4+3,3f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,8
+#endif
 96:    stb     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,8
+#endif
 3:     li      r3,0
        blr
 
index ac3c2a10dafda9e73145dabfbc7181548f288fd5..555034f8505e8d1d83bfeef3480a9bc058499754 100644 (file)
@@ -223,10 +223,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
                        }
                        PPC_DIVWU(r_A, r_A, r_X);
                        break;
-               case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
+               case BPF_S_ALU_DIV_K: /* A /= K */
+                       if (K == 1)
+                               break;
                        PPC_LI32(r_scratch1, K);
-                       /* Top 32 bits of 64bit result -> A */
-                       PPC_MULHWU(r_A, r_A, r_scratch1);
+                       PPC_DIVWU(r_A, r_A, r_scratch1);
                        break;
                case BPF_S_ALU_AND_X:
                        ctx->seen |= SEEN_XREG;
index 02245cee78183852d52f3a907023dcd9a63529bf..d7ddcee7feb8bc8084d18be32f348263c8de6e0e 100644 (file)
@@ -36,7 +36,6 @@
 #include "powernv.h"
 #include "pci.h"
 
-static char *hub_diag = NULL;
 static int ioda_eeh_nb_init = 0;
 
 static int ioda_eeh_event(struct notifier_block *nb,
@@ -140,15 +139,6 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
                ioda_eeh_nb_init = 1;
        }
 
-       /* We needn't HUB diag-data on PHB3 */
-       if (phb->type == PNV_PHB_IODA1 && !hub_diag) {
-               hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-               if (!hub_diag) {
-                       pr_err("%s: Out of memory !\n", __func__);
-                       return -ENOMEM;
-               }
-       }
-
 #ifdef CONFIG_DEBUG_FS
        if (phb->dbgfs) {
                debugfs_create_file("err_injct_outbound", 0600,
@@ -633,11 +623,10 @@ static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
 static void ioda_eeh_hub_diag(struct pci_controller *hose)
 {
        struct pnv_phb *phb = hose->private_data;
-       struct OpalIoP7IOCErrorData *data;
+       struct OpalIoP7IOCErrorData *data = &phb->diag.hub_diag;
        long rc;
 
-       data = (struct OpalIoP7IOCErrorData *)ioda_eeh_hub_diag;
-       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, PAGE_SIZE);
+       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data));
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
                           __func__, phb->hub_id, rc);
@@ -820,14 +809,15 @@ static void ioda_eeh_phb_diag(struct pci_controller *hose)
        struct OpalIoPhbErrorCommon *common;
        long rc;
 
-       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, common, PAGE_SIZE);
+       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+                                        PNV_PCI_DIAG_BUF_SIZE);
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
                            __func__, hose->global_number, rc);
                return;
        }
 
+       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
        switch (common->ioType) {
        case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
                ioda_eeh_p7ioc_phb_diag(hose, common);
index e7e59e4f9892deb85b8ff96b502a6c14fe989d19..79d83cad3d6709c543dad5bb96eafba2ff8756a7 100644 (file)
@@ -24,25 +24,25 @@ static int opal_lpc_chip_id = -1;
 static u8 opal_lpc_inb(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xffff)
                return 0xff;
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 1);
-       return rc ? 0xff : data;
+       return rc ? 0xff : be32_to_cpu(data);
 }
 
 static __le16 __opal_lpc_inw(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xfffe)
                return 0xffff;
        if (port & 1)
                return (__le16)opal_lpc_inb(port) << 8 | opal_lpc_inb(port + 1);
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 2);
-       return rc ? 0xffff : data;
+       return rc ? 0xffff : be32_to_cpu(data);
 }
 static u16 opal_lpc_inw(unsigned long port)
 {
@@ -52,7 +52,7 @@ static u16 opal_lpc_inw(unsigned long port)
 static __le32 __opal_lpc_inl(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xfffc)
                return 0xffffffff;
@@ -62,7 +62,7 @@ static __le32 __opal_lpc_inl(unsigned long port)
                       (__le32)opal_lpc_inb(port + 2) <<  8 |
                               opal_lpc_inb(port + 3);
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 4);
-       return rc ? 0xffffffff : data;
+       return rc ? 0xffffffff : be32_to_cpu(data);
 }
 
 static u32 opal_lpc_inl(unsigned long port)
index 4d99a8fd55acf2a286e8f7877cd919d2150355bf..4fbf276ac99eeb4e2900196e3905a3343bedc988 100644 (file)
@@ -96,9 +96,11 @@ static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
 {
        struct opal_scom_map *m = map;
        int64_t rc;
+       __be64 v;
 
        reg = opal_scom_unmangle(reg);
-       rc = opal_xscom_read(m->chip, m->addr + reg, (uint64_t *)__pa(value));
+       rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v));
+       *value = be64_to_cpu(v);
        return opal_xscom_err_xlate(rc);
 }
 
index 911c24ef033e0ae207036e5d5cab8bceaf07e14a..1ed8d5f40f5ad1423f78c9ae7fdac42abac4376d 100644 (file)
@@ -172,11 +172,13 @@ struct pnv_phb {
                } ioda;
        };
 
-       /* PHB status structure */
+       /* PHB and hub status structure */
        union {
                unsigned char                   blob[PNV_PCI_DIAG_BUF_SIZE];
                struct OpalIoP7IOCPhbErrorData  p7ioc;
+               struct OpalIoP7IOCErrorData     hub_diag;
        } diag;
+
 };
 
 extern struct pci_ops pnv_pci_ops;
index e738007eae643262d72942c599a6418b252b4849..c9fecf09b8fada71dec94e9833c35be524b498e4 100644 (file)
@@ -157,7 +157,7 @@ static void parse_ppp_data(struct seq_file *m)
 {
        struct hvcall_ppp_data ppp_data;
        struct device_node *root;
-       const int *perf_level;
+       const __be32 *perf_level;
        int rc;
 
        rc = h_get_ppp(&ppp_data);
@@ -201,7 +201,7 @@ static void parse_ppp_data(struct seq_file *m)
                perf_level = of_get_property(root,
                                "ibm,partition-performance-parameters-level",
                                             NULL);
-               if (perf_level && (*perf_level >= 1)) {
+               if (perf_level && (be32_to_cpup(perf_level) >= 1)) {
                        seq_printf(m,
                            "physical_procs_allocated_to_virtualization=%d\n",
                                   ppp_data.phys_platform_procs);
@@ -435,7 +435,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        int partition_potential_processors;
        int partition_active_processors;
        struct device_node *rtas_node;
-       const int *lrdrp = NULL;
+       const __be32 *lrdrp = NULL;
 
        rtas_node = of_find_node_by_path("/rtas");
        if (rtas_node)
@@ -444,7 +444,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        if (lrdrp == NULL) {
                partition_potential_processors = vdso_data->processorCount;
        } else {
-               partition_potential_processors = *(lrdrp + 4);
+               partition_potential_processors = be32_to_cpup(lrdrp + 4);
        }
        of_node_put(rtas_node);
 
@@ -654,7 +654,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
        const char *model = "";
        const char *system_id = "";
        const char *tmp;
-       const unsigned int *lp_index_ptr;
+       const __be32 *lp_index_ptr;
        unsigned int lp_index = 0;
 
        seq_printf(m, "%s %s\n", MODULE_NAME, MODULE_VERS);
@@ -670,7 +670,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
                lp_index_ptr = of_get_property(rootdn, "ibm,partition-no",
                                        NULL);
                if (lp_index_ptr)
-                       lp_index = *lp_index_ptr;
+                       lp_index = be32_to_cpup(lp_index_ptr);
                of_node_put(rootdn);
        }
        seq_printf(m, "serial_number=%s\n", system_id);
index 6d2f0abce6fae652d207b499ac99a47e20a500f2..0c882e83c4ce29373f6d3957b7de34979d9fae98 100644 (file)
@@ -130,7 +130,8 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
 {
        struct device_node *dn;
        struct pci_dn *pdn;
-       const u32 *req_msi;
+       const __be32 *p;
+       u32 req_msi;
 
        pdn = pci_get_pdn(pdev);
        if (!pdn)
@@ -138,19 +139,20 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
 
        dn = pdn->node;
 
-       req_msi = of_get_property(dn, prop_name, NULL);
-       if (!req_msi) {
+       p = of_get_property(dn, prop_name, NULL);
+       if (!p) {
                pr_debug("rtas_msi: No %s on %s\n", prop_name, dn->full_name);
                return -ENOENT;
        }
 
-       if (*req_msi < nvec) {
+       req_msi = be32_to_cpup(p);
+       if (req_msi < nvec) {
                pr_debug("rtas_msi: %s requests < %d MSIs\n", prop_name, nvec);
 
-               if (*req_msi == 0) /* Be paranoid */
+               if (req_msi == 0) /* Be paranoid */
                        return -ENOSPC;
 
-               return *req_msi;
+               return req_msi;
        }
 
        return 0;
@@ -171,7 +173,7 @@ static int check_req_msix(struct pci_dev *pdev, int nvec)
 static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
 {
        struct device_node *dn;
-       const u32 *p;
+       const __be32 *p;
 
        dn = of_node_get(pci_device_to_OF_node(dev));
        while (dn) {
@@ -179,7 +181,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
                if (p) {
                        pr_debug("rtas_msi: found prop on dn %s\n",
                                dn->full_name);
-                       *total = *p;
+                       *total = be32_to_cpup(p);
                        return dn;
                }
 
@@ -232,13 +234,13 @@ struct msi_counts {
 static void *count_non_bridge_devices(struct device_node *dn, void *data)
 {
        struct msi_counts *counts = data;
-       const u32 *p;
+       const __be32 *p;
        u32 class;
 
        pr_debug("rtas_msi: counting %s\n", dn->full_name);
 
        p = of_get_property(dn, "class-code", NULL);
-       class = p ? *p : 0;
+       class = p ? be32_to_cpup(p) : 0;
 
        if ((class >> 8) != PCI_CLASS_BRIDGE_PCI)
                counts->num_devices++;
@@ -249,7 +251,7 @@ static void *count_non_bridge_devices(struct device_node *dn, void *data)
 static void *count_spare_msis(struct device_node *dn, void *data)
 {
        struct msi_counts *counts = data;
-       const u32 *p;
+       const __be32 *p;
        int req;
 
        if (dn == counts->requestor)
@@ -260,11 +262,11 @@ static void *count_spare_msis(struct device_node *dn, void *data)
                req = 0;
                p = of_get_property(dn, "ibm,req#msi", NULL);
                if (p)
-                       req = *p;
+                       req = be32_to_cpup(p);
 
                p = of_get_property(dn, "ibm,req#msi-x", NULL);
                if (p)
-                       req = max(req, (int)*p);
+                       req = max(req, (int)be32_to_cpup(p));
        }
 
        if (req < counts->quota)
index 7bfaf58d4664460db12c94499fc151e251f47f68..d7096f2f7751a5a0e41cb30ee48fef3242901f09 100644 (file)
@@ -43,8 +43,8 @@ static char nvram_buf[NVRW_CNT];      /* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
 struct err_log_info {
-       int error_type;
-       unsigned int seq_num;
+       __be32 error_type;
+       __be32 seq_num;
 };
 
 struct nvram_os_partition {
@@ -79,9 +79,9 @@ static const char *pseries_nvram_os_partitions[] = {
 };
 
 struct oops_log_info {
-       u16 version;
-       u16 report_length;
-       u64 timestamp;
+       __be16 version;
+       __be16 report_length;
+       __be64 timestamp;
 } __attribute__((packed));
 
 static void oops_to_nvram(struct kmsg_dumper *dumper,
@@ -291,8 +291,8 @@ int nvram_write_os_partition(struct nvram_os_partition *part, char * buff,
                length = part->size;
        }
 
-       info.error_type = err_type;
-       info.seq_num = error_log_cnt;
+       info.error_type = cpu_to_be32(err_type);
+       info.seq_num = cpu_to_be32(error_log_cnt);
 
        tmp_index = part->index;
 
@@ -364,8 +364,8 @@ int nvram_read_partition(struct nvram_os_partition *part, char *buff,
        }
 
        if (part->os_partition) {
-               *error_log_cnt = info.seq_num;
-               *err_type = info.error_type;
+               *error_log_cnt = be32_to_cpu(info.seq_num);
+               *err_type = be32_to_cpu(info.error_type);
        }
 
        return 0;
@@ -529,9 +529,9 @@ static int zip_oops(size_t text_len)
                pr_err("nvram: logging uncompressed oops/panic report\n");
                return -1;
        }
-       oops_hdr->version = OOPS_HDR_VERSION;
-       oops_hdr->report_length = (u16) zipped_len;
-       oops_hdr->timestamp = get_seconds();
+       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+       oops_hdr->report_length = cpu_to_be16(zipped_len);
+       oops_hdr->timestamp = cpu_to_be64(get_seconds());
        return 0;
 }
 
@@ -574,9 +574,9 @@ static int nvram_pstore_write(enum pstore_type_id type,
                                clobbering_unread_rtas_event())
                return -1;
 
-       oops_hdr->version = OOPS_HDR_VERSION;
-       oops_hdr->report_length = (u16) size;
-       oops_hdr->timestamp = get_seconds();
+       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+       oops_hdr->report_length = cpu_to_be16(size);
+       oops_hdr->timestamp = cpu_to_be64(get_seconds());
 
        if (compressed)
                err_type = ERR_TYPE_KERNEL_PANIC_GZ;
@@ -670,16 +670,16 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
                size_t length, hdr_size;
 
                oops_hdr = (struct oops_log_info *)buff;
-               if (oops_hdr->version < OOPS_HDR_VERSION) {
+               if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
                        /* Old format oops header had 2-byte record size */
                        hdr_size = sizeof(u16);
-                       length = oops_hdr->version;
+                       length = be16_to_cpu(oops_hdr->version);
                        time->tv_sec = 0;
                        time->tv_nsec = 0;
                } else {
                        hdr_size = sizeof(*oops_hdr);
-                       length = oops_hdr->report_length;
-                       time->tv_sec = oops_hdr->timestamp;
+                       length = be16_to_cpu(oops_hdr->report_length);
+                       time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
                        time->tv_nsec = 0;
                }
                *buf = kmalloc(length, GFP_KERNEL);
@@ -889,13 +889,13 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
                kmsg_dump_get_buffer(dumper, false,
                                     oops_data, oops_data_sz, &text_len);
                err_type = ERR_TYPE_KERNEL_PANIC;
-               oops_hdr->version = OOPS_HDR_VERSION;
-               oops_hdr->report_length = (u16) text_len;
-               oops_hdr->timestamp = get_seconds();
+               oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+               oops_hdr->report_length = cpu_to_be16(text_len);
+               oops_hdr->timestamp = cpu_to_be64(get_seconds());
        }
 
        (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-               (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
+               (int) (sizeof(*oops_hdr) + text_len), err_type,
                ++oops_count);
 
        spin_unlock_irqrestore(&lock, flags);
index 5f93856cdf479a3950cd053288174e1a85db4cad..70670a2d9cf2ddd691a936dbe489d8e338ed4029 100644 (file)
@@ -113,7 +113,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
        struct device_node *dn, *pdn;
        struct pci_bus *bus;
-       const uint32_t *pcie_link_speed_stats;
+       const __be32 *pcie_link_speed_stats;
 
        bus = bridge->bus;
 
@@ -122,7 +122,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                return 0;
 
        for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
-               pcie_link_speed_stats = (const uint32_t *) of_get_property(pdn,
+               pcie_link_speed_stats = of_get_property(pdn,
                        "ibm,pcie-link-speed-stats", NULL);
                if (pcie_link_speed_stats)
                        break;
@@ -135,7 +135,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                return 0;
        }
 
-       switch (pcie_link_speed_stats[0]) {
+       switch (be32_to_cpup(pcie_link_speed_stats)) {
        case 0x01:
                bus->max_bus_speed = PCIE_SPEED_2_5GT;
                break;
@@ -147,7 +147,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                break;
        }
 
-       switch (pcie_link_speed_stats[1]) {
+       switch (be32_to_cpup(pcie_link_speed_stats)) {
        case 0x01:
                bus->cur_bus_speed = PCIE_SPEED_2_5GT;
                break;
index 1e1a03d2d19fbbb35804d4fc28d8d9eac355a9c4..e9f3125325266ff8b93f13c009003d3d4aa335de 100644 (file)
@@ -135,7 +135,6 @@ config S390
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_UID16 if 32BIT
        select HAVE_VIRT_CPU_ACCOUNTING
-       select INIT_ALL_POSSIBLE
        select KTIME_SCALAR if 32BIT
        select MODULES_USE_ELF_RELA
        select OLD_SIGACTION
index ac9bed8e103fa741f85b3aecc64fcc9a18511c82..16077939409622fc946b943f4556d91cc272211c 100644 (file)
@@ -31,6 +31,7 @@ extern void smp_yield(void);
 extern void smp_stop_cpu(void);
 extern void smp_cpu_set_polarization(int cpu, int val);
 extern int smp_cpu_get_polarization(int cpu);
+extern void smp_fill_possible_mask(void);
 
 #else /* CONFIG_SMP */
 
@@ -50,6 +51,7 @@ static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
 static inline void smp_yield(void) { }
 static inline void smp_stop_cpu(void) { }
+static inline void smp_fill_possible_mask(void) { }
 
 #endif /* CONFIG_SMP */
 
index 4444875266ee028bdcc4d43604a4dea591a1a47c..0f3d44ecbfc6d5cd66541a0fe4c651acdf6a8336 100644 (file)
@@ -1023,6 +1023,7 @@ void __init setup_arch(char **cmdline_p)
        setup_vmcoreinfo();
        setup_lowcore();
 
+       smp_fill_possible_mask();
         cpu_init();
        s390_init_cpu_topology();
 
index dc4a534650604a972967ab5dedd2c1b7155c29ad..958704798f4a8e91ff898149b8d6379a39cede13 100644 (file)
@@ -721,18 +721,14 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
        return 0;
 }
 
-static int __init setup_possible_cpus(char *s)
-{
-       int max, cpu;
+static unsigned int setup_possible_cpus __initdata;
 
-       if (kstrtoint(s, 0, &max) < 0)
-               return 0;
-       init_cpu_possible(cpumask_of(0));
-       for (cpu = 1; cpu < max && cpu < nr_cpu_ids; cpu++)
-               set_cpu_possible(cpu, true);
+static int __init _setup_possible_cpus(char *s)
+{
+       get_option(&s, &setup_possible_cpus);
        return 0;
 }
-early_param("possible_cpus", setup_possible_cpus);
+early_param("possible_cpus", _setup_possible_cpus);
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -775,6 +771,17 @@ void __noreturn cpu_die(void)
 
 #endif /* CONFIG_HOTPLUG_CPU */
 
+void __init smp_fill_possible_mask(void)
+{
+       unsigned int possible, cpu;
+
+       possible = setup_possible_cpus;
+       if (!possible)
+               possible = MACHINE_IS_VM ? 64 : nr_cpu_ids;
+       for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++)
+               set_cpu_possible(cpu, true);
+}
+
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        /* request the 0x1201 emergency signal external interrupt */
index 16871da3737164d986412ff40cc8fb95c2c7119b..708d60e4006676486b3892195b165ede007d2544 100644 (file)
@@ -368,14 +368,16 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
                EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
                /* lhi %r4,0 */
                EMIT4(0xa7480000);
-               /* dr %r4,%r12 */
-               EMIT2(0x1d4c);
+               /* dlr %r4,%r12 */
+               EMIT4(0xb997004c);
                break;
-       case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */
-               /* m %r4,<d(K)>(%r13) */
-               EMIT4_DISP(0x5c40d000, EMIT_CONST(K));
-               /* lr %r5,%r4 */
-               EMIT2(0x1854);
+       case BPF_S_ALU_DIV_K: /* A /= K */
+               if (K == 1)
+                       break;
+               /* lhi %r4,0 */
+               EMIT4(0xa7480000);
+               /* dl %r4,<d(K)>(%r13) */
+               EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K));
                break;
        case BPF_S_ALU_MOD_X: /* A %= X */
                jit->seen |= SEEN_XREG | SEEN_RET0;
@@ -385,16 +387,21 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
                EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
                /* lhi %r4,0 */
                EMIT4(0xa7480000);
-               /* dr %r4,%r12 */
-               EMIT2(0x1d4c);
+               /* dlr %r4,%r12 */
+               EMIT4(0xb997004c);
                /* lr %r5,%r4 */
                EMIT2(0x1854);
                break;
        case BPF_S_ALU_MOD_K: /* A %= K */
+               if (K == 1) {
+                       /* lhi %r5,0 */
+                       EMIT4(0xa7580000);
+                       break;
+               }
                /* lhi %r4,0 */
                EMIT4(0xa7480000);
-               /* d %r4,<d(K)>(%r13) */
-               EMIT4_DISP(0x5d40d000, EMIT_CONST(K));
+               /* dl %r4,<d(K)>(%r13) */
+               EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K));
                /* lr %r5,%r4 */
                EMIT2(0x1854);
                break;
index 800f064b0da7c9a32c3910ecefdfb3e6979d7f9b..069607209a3075c6f4ff2c62fe91b7eb1d99c8aa 100644 (file)
@@ -75,6 +75,7 @@ void zpci_event_availability(void *data)
                if (!zdev || zdev->state == ZPCI_FN_STATE_CONFIGURED)
                        break;
                zdev->state = ZPCI_FN_STATE_CONFIGURED;
+               zdev->fh = ccdf->fh;
                ret = zpci_enable_device(zdev);
                if (ret)
                        break;
@@ -101,6 +102,7 @@ void zpci_event_availability(void *data)
                if (pdev)
                        pci_stop_and_remove_bus_device(pdev);
 
+               zdev->fh = ccdf->fh;
                zpci_disable_device(zdev);
                zdev->state = ZPCI_FN_STATE_STANDBY;
                break;
index 2a0a596ebf67d948663df3009d1ca14c8b09dabc..d77f2f6c7ff0761de1b51f09eb8926923c817681 100644 (file)
@@ -20,6 +20,11 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(empty_zero_page);
+#ifdef CONFIG_FLATMEM
+/* need in pfn_valid macro */
+EXPORT_SYMBOL(min_low_pfn);
+EXPORT_SYMBOL(max_low_pfn);
+#endif
 
 #define DECLARE_EXPORT(name)           \
        extern void name(void);EXPORT_SYMBOL(name)
index 7b95f29e31749ec180e67028424580fadda1c3af..3baff31e58cf22c30b2d770162ee3c4b10c087ea 100644 (file)
@@ -6,7 +6,7 @@ lib-y  = delay.o memmove.o memchr.o \
         checksum.o strlen.o div64.o div64-generic.o
 
 # Extracted from libgcc
-lib-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
+obj-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
         ashlsi3.o ashrsi3.o ashiftrt.o lshrsi3.o \
         udiv_qrnnd.o
 
index 8358dc144959aacc8b369830c21c130593b9a804..0f9e94537eee78d9d41fffe82e32fc0098811ed2 100644 (file)
@@ -619,7 +619,7 @@ static inline unsigned long pte_present(pte_t pte)
 }
 
 #define pte_accessible pte_accessible
-static inline unsigned long pte_accessible(pte_t a)
+static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
 {
        return pte_val(a) & _PAGE_VALID;
 }
@@ -847,7 +847,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
         * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
         *             and SUN4V pte layout, so this inline test is fine.
         */
-       if (likely(mm != &init_mm) && pte_accessible(orig))
+       if (likely(mm != &init_mm) && pte_accessible(mm, orig))
                tlb_batch_add(mm, addr, ptep, orig, fullmm);
 }
 
index e562d3caee57457a3b188f13b2959d47a7f835b4..ad7e178337f12f2f753f66ec2a9c26dae65c9f68 100644 (file)
@@ -262,8 +262,8 @@ extern unsigned long __must_check __clear_user(void __user *, unsigned long);
 extern __must_check long strlen_user(const char __user *str);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
-#define __copy_to_user_inatomic ___copy_to_user
-#define __copy_from_user_inatomic ___copy_from_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 struct pt_regs;
 extern unsigned long compute_effective_address(struct pt_regs *,
index 070ed141aac79728da15f406289219a9c385fe27..76663b019eb5207f389655dac5133afce6e553aa 100644 (file)
@@ -854,7 +854,7 @@ int dma_supported(struct device *dev, u64 device_mask)
                return 1;
 
 #ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return pci64_dma_supported(to_pci_dev(dev), device_mask);
 #endif
 
index 2096468de9b27f7dd2bb54f17e3b308f8d359836..e7e215dfa86668750c9490331d94b288ab78857c 100644 (file)
@@ -666,10 +666,9 @@ EXPORT_SYMBOL(dma_ops);
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-#ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return 1;
-#endif
+
        return 0;
 }
 EXPORT_SYMBOL(dma_supported);
index 60b19f50c80a8f9d7f31b4b4105ed4fcded6a5ca..b45fe3fb4d2cfbc7999d34a1b25baf9bc0278c2e 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
 #include <linux/ftrace.h>
+#include <linux/context_tracking.h>
 
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
index b66a5338231e965252fef5f23234141bb2fc8f85..b085311dcd0ea9f81840e1fc2550c4f870e984eb 100644 (file)
@@ -123,11 +123,12 @@ void smp_callin(void)
                rmb();
 
        set_cpu_online(cpuid, true);
-       local_irq_enable();
 
        /* idle thread is expected to have preempt disabled */
        preempt_disable();
 
+       local_irq_enable();
+
        cpu_startup_entry(CPUHP_ONLINE);
 }
 
index 218b6b23c378f888ef6ab0accf7ee4882e2911e2..01fe9946d388de469e140532b3f973f8a6db28fb 100644 (file)
@@ -497,9 +497,20 @@ void bpf_jit_compile(struct sk_filter *fp)
                        case BPF_S_ALU_MUL_K:   /* A *= K */
                                emit_alu_K(MUL, K);
                                break;
-                       case BPF_S_ALU_DIV_K:   /* A /= K */
-                               emit_alu_K(MUL, K);
-                               emit_read_y(r_A);
+                       case BPF_S_ALU_DIV_K:   /* A /= K with K != 0*/
+                               if (K == 1)
+                                       break;
+                               emit_write_y(G0);
+#ifdef CONFIG_SPARC32
+                               /* The Sparc v8 architecture requires
+                                * three instructions between a %y
+                                * register write and the first use.
+                                */
+                               emit_nop();
+                               emit_nop();
+                               emit_nop();
+#endif
+                               emit_alu_K(DIV, K);
                                break;
                        case BPF_S_ALU_DIV_X:   /* A /= X; */
                                emit_cmpi(r_X, 0);
index e903c71f7e69822d2ce5240b957399dbab783037..0952ecd60ecaf7e8fcadb4360731ba22dea22c22 100644 (file)
@@ -26,6 +26,7 @@ config X86
        select HAVE_AOUT if X86_32
        select HAVE_UNSTABLE_SCHED_CLOCK
        select ARCH_SUPPORTS_NUMA_BALANCING
+       select ARCH_SUPPORTS_INT128 if X86_64
        select ARCH_WANTS_PROT_NUMA_PROT_NONE
        select HAVE_IDE
        select HAVE_OPROFILE
index c49a613c6452fc66afdf5de52572dc8d033a8fcc..cea1c76d49bf5b04344bb17c353bab35869cf01a 100644 (file)
@@ -293,12 +293,13 @@ 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));
+       if (unlikely(static_cpu_has(X86_FEATURE_FXSAVE_LEAK))) {
+               asm volatile(
+                       "fnclex\n\t"
+                       "emms\n\t"
+                       "fildl %P[addr]"        /* set F?P to defined value */
+                       : : [addr] "m" (tsk->thread.fpu.has_fpu));
+       }
 
        return fpu_restore_checking(&tsk->thread.fpu);
 }
index 3d1999458709231affdc977df99530acf3a833ac..bbc8b12fa443d47ee9a8faa59b36767e7aec866c 100644 (file)
@@ -452,9 +452,16 @@ static inline int pte_present(pte_t a)
 }
 
 #define pte_accessible pte_accessible
-static inline int pte_accessible(pte_t a)
+static inline bool pte_accessible(struct mm_struct *mm, pte_t a)
 {
-       return pte_flags(a) & _PAGE_PRESENT;
+       if (pte_flags(a) & _PAGE_PRESENT)
+               return true;
+
+       if ((pte_flags(a) & (_PAGE_PROTNONE | _PAGE_NUMA)) &&
+                       mm_tlb_flush_pending(mm))
+               return true;
+
+       return false;
 }
 
 static inline int pte_hidden(pte_t pte)
index 8729723636fd1632eebd92197dd292fa26de10d7..c8b051933b1b384ccd723267d99c9ff052875dff 100644 (file)
@@ -7,6 +7,12 @@
 
 DECLARE_PER_CPU(int, __preempt_count);
 
+/*
+ * We use the PREEMPT_NEED_RESCHED bit as an inverted NEED_RESCHED such
+ * that a decrement hitting 0 means we can and should reschedule.
+ */
+#define PREEMPT_ENABLED        (0 + PREEMPT_NEED_RESCHED)
+
 /*
  * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
  * that think a non-zero value indicates we cannot preempt.
@@ -74,6 +80,11 @@ static __always_inline void __preempt_count_sub(int val)
        __this_cpu_add_4(__preempt_count, -val);
 }
 
+/*
+ * Because we keep PREEMPT_NEED_RESCHED set when we do _not_ need to reschedule
+ * a decrement which hits zero means we have no preempt_count and should
+ * reschedule.
+ */
 static __always_inline bool __preempt_count_dec_and_test(void)
 {
        GEN_UNARY_RMWcc("decl", __preempt_count, __percpu_arg(0), "e");
index dc1ec0dff939ecff5e55bcccaeb5bea322ad982a..ea04b342c026f8c8871f70a0c383d80651e12524 100644 (file)
@@ -387,7 +387,8 @@ static void init_intel(struct cpuinfo_x86 *c)
                        set_cpu_cap(c, X86_FEATURE_PEBS);
        }
 
-       if (c->x86 == 6 && c->x86_model == 29 && cpu_has_clflush)
+       if (c->x86 == 6 && cpu_has_clflush &&
+           (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
                set_cpu_cap(c, X86_FEATURE_CLFLUSH_MONITOR);
 
 #ifdef CONFIG_X86_64
index fd00bb29425d4da50194241c6ae3835775e12e6e..c1a861829d817a2749372060df21c6d689294fff 100644 (file)
@@ -262,11 +262,20 @@ struct cpu_hw_events {
        __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \
                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
 
-#define EVENT_CONSTRAINT_END           \
-       EVENT_CONSTRAINT(0, 0, 0)
+/*
+ * We define the end marker as having a weight of -1
+ * to enable blacklisting of events using a counter bitmask
+ * of zero and thus a weight of zero.
+ * The end marker has a weight that cannot possibly be
+ * obtained from counting the bits in the bitmask.
+ */
+#define EVENT_CONSTRAINT_END { .weight = -1 }
 
+/*
+ * Check for end marker with weight == -1
+ */
 #define for_each_event_constraint(e, c)        \
-       for ((e) = (c); (e)->weight; (e)++)
+       for ((e) = (c); (e)->weight != -1; (e)++)
 
 /*
  * Extra registers for specific events.
index e09f0bfb7b8f23b3206ed623289df4b9bff67605..4b8e4d3cd6ea62bc9c9047e869fa84cbd9cbe33a 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/ptrace.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/apic.h>
 
@@ -816,6 +817,18 @@ out:
        return ret;
 }
 
+static void ibs_eilvt_setup(void)
+{
+       /*
+        * Force LVT offset assignment for family 10h: The offsets are
+        * not assigned by the BIOS for this family, so the OS is
+        * responsible for doing it. If the OS assignment fails, fall
+        * back to BIOS settings and try to setup this.
+        */
+       if (boot_cpu_data.x86 == 0x10)
+               force_ibs_eilvt_setup();
+}
+
 static inline int get_ibs_lvt_offset(void)
 {
        u64 val;
@@ -851,6 +864,36 @@ static void clear_APIC_ibs(void *dummy)
                setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
 }
 
+#ifdef CONFIG_PM
+
+static int perf_ibs_suspend(void)
+{
+       clear_APIC_ibs(NULL);
+       return 0;
+}
+
+static void perf_ibs_resume(void)
+{
+       ibs_eilvt_setup();
+       setup_APIC_ibs(NULL);
+}
+
+static struct syscore_ops perf_ibs_syscore_ops = {
+       .resume         = perf_ibs_resume,
+       .suspend        = perf_ibs_suspend,
+};
+
+static void perf_ibs_pm_init(void)
+{
+       register_syscore_ops(&perf_ibs_syscore_ops);
+}
+
+#else
+
+static inline void perf_ibs_pm_init(void) { }
+
+#endif
+
 static int
 perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
 {
@@ -877,18 +920,12 @@ static __init int amd_ibs_init(void)
        if (!caps)
                return -ENODEV; /* ibs not supported by the cpu */
 
-       /*
-        * Force LVT offset assignment for family 10h: The offsets are
-        * not assigned by the BIOS for this family, so the OS is
-        * responsible for doing it. If the OS assignment fails, fall
-        * back to BIOS settings and try to setup this.
-        */
-       if (boot_cpu_data.x86 == 0x10)
-               force_ibs_eilvt_setup();
+       ibs_eilvt_setup();
 
        if (!ibs_eilvt_valid())
                goto out;
 
+       perf_ibs_pm_init();
        get_online_cpus();
        ibs_caps = caps;
        /* make ibs_caps visible to other cpus: */
index 51e2988c5728d5d57b5b8f0ef035258cc292b2c1..a2a4f4697889657675289e15e358b7f354ea2225 100644 (file)
@@ -1082,7 +1082,7 @@ ENTRY(ftrace_caller)
        pushl $0        /* Pass NULL as regs pointer */
        movl 4*4(%esp), %eax
        movl 0x4(%ebp), %edx
-       leal function_trace_op, %ecx
+       movl function_trace_op, %ecx
        subl $MCOUNT_INSN_SIZE, %eax
 
 .globl ftrace_call
@@ -1140,7 +1140,7 @@ ENTRY(ftrace_regs_caller)
        movl 12*4(%esp), %eax   /* Load ip (1st parameter) */
        subl $MCOUNT_INSN_SIZE, %eax    /* Adjust ip */
        movl 0x4(%ebp), %edx    /* Load parent ip (2nd parameter) */
-       leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
+       movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
        pushl %esp              /* Save pt_regs as 4th parameter */
 
 GLOBAL(ftrace_regs_call)
index e21b0785a85b2fc2f2ca1615820d5e432a9f4675..1e96c3628bf24fc4fe0086ac6f9dc70b2c1c590d 100644 (file)
@@ -88,7 +88,7 @@ END(function_hook)
        MCOUNT_SAVE_FRAME \skip
 
        /* Load the ftrace_ops into the 3rd parameter */
-       leaq function_trace_op, %rdx
+       movq function_trace_op(%rip), %rdx
 
        /* Load ip into the first parameter */
        movq RIP(%rsp), %rdi
index dec48bfaddb8ff79ee7f7734cebfca7f36844461..775702f649ca686ff7a1dcf467c5325b8a3e9c3c 100644 (file)
@@ -1350,8 +1350,12 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                return;
        }
 
+       if (!kvm_vcpu_is_bsp(apic->vcpu))
+               value &= ~MSR_IA32_APICBASE_BSP;
+       vcpu->arch.apic_base = value;
+
        /* update jump label if enable bit changes */
-       if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) {
+       if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) {
                if (value & MSR_IA32_APICBASE_ENABLE)
                        static_key_slow_dec_deferred(&apic_hw_disabled);
                else
@@ -1359,10 +1363,6 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                recalculate_apic_map(vcpu->kvm);
        }
 
-       if (!kvm_vcpu_is_bsp(apic->vcpu))
-               value &= ~MSR_IA32_APICBASE_BSP;
-
-       vcpu->arch.apic_base = value;
        if ((old_value ^ value) & X2APIC_ENABLE) {
                if (value & X2APIC_ENABLE) {
                        u32 id = kvm_apic_id(apic);
index b2fe1c252f35f92e3b6707406998738a9275c8d2..da7837e1349da8ac4ac06468fb2f05e798e136f1 100644 (file)
@@ -8283,8 +8283,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
        vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
        kvm_set_cr4(vcpu, vmcs12->host_cr4);
 
-       if (nested_cpu_has_ept(vmcs12))
-               nested_ept_uninit_mmu_context(vcpu);
+       nested_ept_uninit_mmu_context(vcpu);
 
        kvm_set_cr3(vcpu, vmcs12->host_cr3);
        kvm_mmu_reset_context(vcpu);
index 9ff85bb8dd698182fa6605ee565a00f7843e6303..9d591c895803101e2decbc85a0ce9f23a0b4eaeb 100644 (file)
@@ -641,6 +641,20 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 
        /* Are we prepared to handle this kernel fault? */
        if (fixup_exception(regs)) {
+               /*
+                * Any interrupt that takes a fault gets the fixup. This makes
+                * the below recursive fault logic only apply to a faults from
+                * task context.
+                */
+               if (in_interrupt())
+                       return;
+
+               /*
+                * Per the above we're !in_interrupt(), aka. task context.
+                *
+                * In this case we need to make sure we're not recursively
+                * faulting through the emulate_vsyscall() logic.
+                */
                if (current_thread_info()->sig_on_uaccess_error && signal) {
                        tsk->thread.trap_nr = X86_TRAP_PF;
                        tsk->thread.error_code = error_code | PF_USER;
@@ -649,6 +663,10 @@ no_context(struct pt_regs *regs, unsigned long error_code,
                        /* XXX: hwpoison faults will set the wrong code. */
                        force_sig_info_fault(signal, si_code, address, tsk, 0);
                }
+
+               /*
+                * Barring that, we can do the fixup and be happy.
+                */
                return;
        }
 
index dd74e46828c0fc243740b61a18c2dea654fafb5e..0596e8e0cc1992b1fc32a00277a4f879cd07a8f3 100644 (file)
@@ -83,6 +83,12 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                pte_t pte = gup_get_pte(ptep);
                struct page *page;
 
+               /* Similar to the PMD case, NUMA hinting must take slow path */
+               if (pte_numa(pte)) {
+                       pte_unmap(ptep);
+                       return 0;
+               }
+
                if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {
                        pte_unmap(ptep);
                        return 0;
@@ -167,6 +173,13 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
                if (unlikely(pmd_large(pmd))) {
+                       /*
+                        * NUMA hinting faults need to be handled in the GUP
+                        * slowpath for accounting purposes and so that they
+                        * can be serialised against THP migration.
+                        */
+                       if (pmd_numa(pmd))
+                               return 0;
                        if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))
                                return 0;
                } else {
index 26328e800869fc6ac1821c0ab3dcd2baa1506ec1..4ed75dd81d052ff96cc832702d174ad4d63bffec 100644 (file)
@@ -359,15 +359,21 @@ void bpf_jit_compile(struct sk_filter *fp)
                                EMIT2(0x89, 0xd0);      /* mov %edx,%eax */
                                break;
                        case BPF_S_ALU_MOD_K: /* A %= K; */
+                               if (K == 1) {
+                                       CLEAR_A();
+                                       break;
+                               }
                                EMIT2(0x31, 0xd2);      /* xor %edx,%edx */
                                EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */
                                EMIT2(0xf7, 0xf1);      /* div %ecx */
                                EMIT2(0x89, 0xd0);      /* mov %edx,%eax */
                                break;
-                       case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
-                               EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */
-                               EMIT(K, 4);
-                               EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */
+                       case BPF_S_ALU_DIV_K: /* A /= K */
+                               if (K == 1)
+                                       break;
+                               EMIT2(0x31, 0xd2);      /* xor %edx,%edx */
+                               EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */
+                               EMIT2(0xf7, 0xf1);      /* div %ecx */
                                break;
                        case BPF_S_ALU_AND_X:
                                seen |= SEEN_XREG;
index 2ada505067cceca9001bda33bb6aa66941d34b0d..eb5d7a56f8d4b5627171d70c6df94513a99e09d0 100644 (file)
@@ -178,7 +178,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
 
        ts->tv_nsec = 0;
        do {
-               seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+               seq = raw_read_seqcount_begin(&gtod->seq);
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->wall_time_sec;
                ns = gtod->wall_time_snsec;
@@ -198,7 +198,7 @@ notrace static int do_monotonic(struct timespec *ts)
 
        ts->tv_nsec = 0;
        do {
-               seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+               seq = raw_read_seqcount_begin(&gtod->seq);
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->monotonic_time_sec;
                ns = gtod->monotonic_time_snsec;
@@ -214,7 +214,7 @@ notrace static int do_realtime_coarse(struct timespec *ts)
 {
        unsigned long seq;
        do {
-               seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+               seq = raw_read_seqcount_begin(&gtod->seq);
                ts->tv_sec = gtod->wall_time_coarse.tv_sec;
                ts->tv_nsec = gtod->wall_time_coarse.tv_nsec;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
@@ -225,7 +225,7 @@ notrace static int do_monotonic_coarse(struct timespec *ts)
 {
        unsigned long seq;
        do {
-               seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+               seq = raw_read_seqcount_begin(&gtod->seq);
                ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
                ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
index ba6cf8e9aa0a598a50d4b24eb2c8f2914bf5c5ef..b91ce75bd35db9e00edb4c4af0a0e3036fd66df8 100644 (file)
@@ -335,9 +335,22 @@ static struct kobj_type blk_mq_hw_ktype = {
 void blk_mq_unregister_disk(struct gendisk *disk)
 {
        struct request_queue *q = disk->queue;
+       struct blk_mq_hw_ctx *hctx;
+       struct blk_mq_ctx *ctx;
+       int i, j;
+
+       queue_for_each_hw_ctx(q, hctx, i) {
+               hctx_for_each_ctx(hctx, ctx, j) {
+                       kobject_del(&ctx->kobj);
+                       kobject_put(&ctx->kobj);
+               }
+               kobject_del(&hctx->kobj);
+               kobject_put(&hctx->kobj);
+       }
 
        kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
        kobject_del(&q->mq_kobj);
+       kobject_put(&q->mq_kobj);
 
        kobject_put(&disk_to_dev(disk)->kobj);
 }
index 5d9248526d780b06c51bee967cdd088c9c90e5e5..4770de5707b9b9eb0a4c27f14c7ec9ad13035257 100644 (file)
@@ -348,7 +348,6 @@ source "drivers/acpi/apei/Kconfig"
 config ACPI_EXTLOG
        tristate "Extended Error Log support"
        depends on X86_MCE && X86_LOCAL_APIC
-       select EFI
        select UEFI_CPER
        default n
        help
index 8711e3797165fa73fd0c401cedbb54c61eb68e4a..3c2e4aa529c479e92090c8862deaadcf0a8645e5 100644 (file)
@@ -207,7 +207,7 @@ static int acpi_ac_probe(struct platform_device *pdev)
                goto end;
 
        result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac);
+                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler, ac);
        if (result) {
                power_supply_unregister(&ac->charger);
                goto end;
@@ -255,7 +255,7 @@ static int acpi_ac_remove(struct platform_device *pdev)
                return -EINVAL;
 
        acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler);
+                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler);
 
        ac = platform_get_drvdata(pdev);
        if (ac->charger.dev)
index 786294bb682c104f111525ca17df7ccfafab0d88..3650b21832279a91568266208059296fadfab94c 100644 (file)
@@ -2,7 +2,6 @@ config ACPI_APEI
        bool "ACPI Platform Error Interface (APEI)"
        select MISC_FILESYSTEMS
        select PSTORE
-       select EFI
        select UEFI_CPER
        depends on X86
        help
index 26311f23c824f91354b3e47fe6fa5e5e448275dc..cb1d557fc22c054fa36beb1f74bfae42ea49f2c2 100644 (file)
@@ -942,6 +942,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count,
 static struct pstore_info erst_info = {
        .owner          = THIS_MODULE,
        .name           = "erst",
+       .flags          = PSTORE_FLAGS_FRAGILE,
        .open           = erst_open_pstore,
        .close          = erst_close_pstore,
        .read           = erst_reader,
index fbf1aceda8b8ab915a7d2476d78db2b6e2b94e68..5876a49dfd386a4653325d99fcc69aa8452b12e1 100644 (file)
@@ -62,6 +62,7 @@ MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
 MODULE_DESCRIPTION("ACPI Battery Driver");
 MODULE_LICENSE("GPL");
 
+static int battery_bix_broken_package;
 static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
@@ -416,7 +417,12 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
                return -ENODEV;
        }
-       if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
+
+       if (battery_bix_broken_package)
+               result = extract_package(battery, buffer.pointer,
+                               extended_info_offsets + 1,
+                               ARRAY_SIZE(extended_info_offsets) - 1);
+       else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
                result = extract_package(battery, buffer.pointer,
                                extended_info_offsets,
                                ARRAY_SIZE(extended_info_offsets));
@@ -754,6 +760,17 @@ static int battery_notify(struct notifier_block *nb,
        return 0;
 }
 
+static struct dmi_system_id bat_dmi_table[] = {
+       {
+               .ident = "NEC LZ750/LS",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
+               },
+       },
+       {},
+};
+
 static int acpi_battery_add(struct acpi_device *device)
 {
        int result = 0;
@@ -846,6 +863,9 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
 {
        if (acpi_disabled)
                return;
+
+       if (dmi_check_system(bat_dmi_table))
+               battery_bix_broken_package = 1;
        acpi_bus_register_driver(&acpi_battery_driver);
 }
 
index bba9b72e25f8235e6d12593bdd16bb378c7af25a..0710004055c809f3059cde2337373503666fd96f 100644 (file)
@@ -156,6 +156,16 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data)
 }
 EXPORT_SYMBOL(acpi_bus_get_private_data);
 
+void acpi_bus_no_hotplug(acpi_handle handle)
+{
+       struct acpi_device *adev = NULL;
+
+       acpi_bus_get_device(handle, &adev);
+       if (adev)
+               adev->flags.no_hotplug = true;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
+
 static void acpi_print_osc_error(acpi_handle handle,
        struct acpi_osc_context *context, char *error)
 {
index 14f1e95063380a5e2a315428fc8a4d5e8bcc39d3..e3a92a6da39ae258cf9a4094f4293799e378271b 100644 (file)
@@ -427,6 +427,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9128 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
+                        PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9170 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
@@ -1238,15 +1241,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       /* AHCI controllers often implement SFF compatible interface.
-        * Grab all PCI BARs just in case.
-        */
-       rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
-       if (rc == -EBUSY)
-               pcim_pin_device(pdev);
-       if (rc)
-               return rc;
-
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
            (pdev->device == 0x2652 || pdev->device == 0x2653)) {
                u8 map;
@@ -1263,6 +1257,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
+       /* AHCI controllers often implement SFF compatible interface.
+        * Grab all PCI BARs just in case.
+        */
+       rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
+       if (rc == -EBUSY)
+               pcim_pin_device(pdev);
+       if (rc)
+               return rc;
+
        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
        if (!hpriv)
                return -ENOMEM;
index ae2d73fe321e2f2c62d8e5709a788905edfd5a89..3e23e9941dad0080d629581723243c6550d4d476 100644 (file)
@@ -113,7 +113,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
        /*
         * set PHY Paremeters, two steps to configure the GPR13,
         * one write for rest of parameters, mask of first write
-        * is 0x07fffffd, and the other one write for setting
+        * is 0x07ffffff, and the other one write for setting
         * the mpll_clk_en.
         */
        regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK
@@ -124,6 +124,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
                        | IMX6Q_GPR13_SATA_TX_ATTEN_MASK
                        | IMX6Q_GPR13_SATA_TX_BOOST_MASK
                        | IMX6Q_GPR13_SATA_TX_LVL_MASK
+                       | IMX6Q_GPR13_SATA_MPLL_CLK_EN
                        | IMX6Q_GPR13_SATA_TX_EDGE_RATE
                        , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB
                        | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M
index 75b93678bbcd7f4231e0c2028995795487db671c..1393a5890ed5356e5ef36965ea74e49e226c0a29 100644 (file)
@@ -2149,9 +2149,16 @@ static int ata_dev_config_ncq(struct ata_device *dev,
                                    "failed to get NCQ Send/Recv Log Emask 0x%x\n",
                                    err_mask);
                } else {
+                       u8 *cmds = dev->ncq_send_recv_cmds;
+
                        dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
-                       memcpy(dev->ncq_send_recv_cmds, ap->sector_buf,
-                               ATA_LOG_NCQ_SEND_RECV_SIZE);
+                       memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE);
+
+                       if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) {
+                               ata_dev_dbg(dev, "disabling queued TRIM support\n");
+                               cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &=
+                                       ~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM;
+                       }
                }
        }
 
@@ -4156,6 +4163,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST3320[68]13AS",     "SD1[5-9]",     ATA_HORKAGE_NONCQ |
                                                ATA_HORKAGE_FIRMWARE_WARN },
 
+       /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
+       { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
        { "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
@@ -4202,6 +4212,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
+       /* devices that don't properly handle queued TRIM commands */
+       { "Micron_M500*",               NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Crucial_CT???M500SSD1",      NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+
        /* End Marker */
        { }
 };
@@ -6519,6 +6533,7 @@ static int __init ata_parse_force_one(char **cur,
                { "norst",      .lflags         = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
                { "rstonce",    .lflags         = ATA_LFLAG_RST_ONCE },
                { "atapi_dmadir", .horkage_on   = ATA_HORKAGE_ATAPI_DMADIR },
+               { "disable",    .horkage_on     = ATA_HORKAGE_DISABLE },
        };
        char *start = *cur, *p = *cur;
        char *id, *val, *endp;
index ab58556d347c19120c9724389583c2ae67a2d81e..377eb889f555dd2029c46a01254a3a204744ac81 100644 (file)
@@ -3872,6 +3872,27 @@ void ata_scsi_hotplug(struct work_struct *work)
                return;
        }
 
+       /*
+        * XXX - UGLY HACK
+        *
+        * The block layer suspend/resume path is fundamentally broken due
+        * to freezable kthreads and workqueue and may deadlock if a block
+        * device gets removed while resume is in progress.  I don't know
+        * what the solution is short of removing freezable kthreads and
+        * workqueues altogether.
+        *
+        * The following is an ugly hack to avoid kicking off device
+        * removal while freezer is active.  This is a joke but does avoid
+        * this particular deadlock scenario.
+        *
+        * https://bugzilla.kernel.org/show_bug.cgi?id=62801
+        * http://marc.info/?l=linux-kernel&m=138695698516487
+        */
+#ifdef CONFIG_FREEZER
+       while (pm_freezing)
+               msleep(10);
+#endif
+
        DPRINTK("ENTER\n");
        mutex_lock(&ap->scsi_scan_mutex);
 
index fe3ca0989b14cac2e712ef2778f2a1b7e528c85b..1ad2f62d34b98fd0b41be9a239827e1634327c54 100644 (file)
@@ -83,6 +83,10 @@ static struct pci_driver sis_pci_driver = {
        .id_table               = sis_pci_tbl,
        .probe                  = sis_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static struct scsi_host_template sis_sht = {
index f370fc13aea5d7d8c2a2c78fb40722da0cc27407..83a598ebb65a4ab7699d1dcebe1b44b42ea8ae5a 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/module.h>
+
 #include <linux/moduleparam.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -65,7 +66,7 @@ enum {
        NULL_Q_MQ               = 2,
 };
 
-static int submit_queues = 1;
+static int submit_queues;
 module_param(submit_queues, int, S_IRUGO);
 MODULE_PARM_DESC(submit_queues, "Number of submission queues");
 
@@ -101,9 +102,9 @@ static int hw_queue_depth = 64;
 module_param(hw_queue_depth, int, S_IRUGO);
 MODULE_PARM_DESC(hw_queue_depth, "Queue depth for each hardware queue. Default: 64");
 
-static bool use_per_node_hctx = true;
+static bool use_per_node_hctx = false;
 module_param(use_per_node_hctx, bool, S_IRUGO);
-MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: true");
+MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: false");
 
 static void put_tag(struct nullb_queue *nq, unsigned int tag)
 {
@@ -346,8 +347,37 @@ static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq)
 
 static struct blk_mq_hw_ctx *null_alloc_hctx(struct blk_mq_reg *reg, unsigned int hctx_index)
 {
-       return kzalloc_node(sizeof(struct blk_mq_hw_ctx), GFP_KERNEL,
-                               hctx_index);
+       int b_size = DIV_ROUND_UP(reg->nr_hw_queues, nr_online_nodes);
+       int tip = (reg->nr_hw_queues % nr_online_nodes);
+       int node = 0, i, n;
+
+       /*
+        * Split submit queues evenly wrt to the number of nodes. If uneven,
+        * fill the first buckets with one extra, until the rest is filled with
+        * no extra.
+        */
+       for (i = 0, n = 1; i < hctx_index; i++, n++) {
+               if (n % b_size == 0) {
+                       n = 0;
+                       node++;
+
+                       tip--;
+                       if (!tip)
+                               b_size = reg->nr_hw_queues / nr_online_nodes;
+               }
+       }
+
+       /*
+        * A node might not be online, therefore map the relative node id to the
+        * real node id.
+        */
+       for_each_online_node(n) {
+               if (!node)
+                       break;
+               node--;
+       }
+
+       return kzalloc_node(sizeof(struct blk_mq_hw_ctx), GFP_KERNEL, n);
 }
 
 static void null_free_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_index)
@@ -355,16 +385,24 @@ static void null_free_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_index)
        kfree(hctx);
 }
 
+static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq)
+{
+       BUG_ON(!nullb);
+       BUG_ON(!nq);
+
+       init_waitqueue_head(&nq->wait);
+       nq->queue_depth = nullb->queue_depth;
+}
+
 static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
                          unsigned int index)
 {
        struct nullb *nullb = data;
        struct nullb_queue *nq = &nullb->queues[index];
 
-       init_waitqueue_head(&nq->wait);
-       nq->queue_depth = nullb->queue_depth;
-       nullb->nr_queues++;
        hctx->driver_data = nq;
+       null_init_queue(nullb, nq);
+       nullb->nr_queues++;
 
        return 0;
 }
@@ -387,10 +425,7 @@ static void null_del_dev(struct nullb *nullb)
        list_del_init(&nullb->list);
 
        del_gendisk(nullb->disk);
-       if (queue_mode == NULL_Q_MQ)
-               blk_mq_free_queue(nullb->q);
-       else
-               blk_cleanup_queue(nullb->q);
+       blk_cleanup_queue(nullb->q);
        put_disk(nullb->disk);
        kfree(nullb);
 }
@@ -417,13 +452,13 @@ static int setup_commands(struct nullb_queue *nq)
 
        nq->cmds = kzalloc(nq->queue_depth * sizeof(*cmd), GFP_KERNEL);
        if (!nq->cmds)
-               return 1;
+               return -ENOMEM;
 
        tag_size = ALIGN(nq->queue_depth, BITS_PER_LONG) / BITS_PER_LONG;
        nq->tag_map = kzalloc(tag_size * sizeof(unsigned long), GFP_KERNEL);
        if (!nq->tag_map) {
                kfree(nq->cmds);
-               return 1;
+               return -ENOMEM;
        }
 
        for (i = 0; i < nq->queue_depth; i++) {
@@ -454,33 +489,37 @@ static void cleanup_queues(struct nullb *nullb)
 
 static int setup_queues(struct nullb *nullb)
 {
-       struct nullb_queue *nq;
-       int i;
-
-       nullb->queues = kzalloc(submit_queues * sizeof(*nq), GFP_KERNEL);
+       nullb->queues = kzalloc(submit_queues * sizeof(struct nullb_queue),
+                                                               GFP_KERNEL);
        if (!nullb->queues)
-               return 1;
+               return -ENOMEM;
 
        nullb->nr_queues = 0;
        nullb->queue_depth = hw_queue_depth;
 
-       if (queue_mode == NULL_Q_MQ)
-               return 0;
+       return 0;
+}
+
+static int init_driver_queues(struct nullb *nullb)
+{
+       struct nullb_queue *nq;
+       int i, ret = 0;
 
        for (i = 0; i < submit_queues; i++) {
                nq = &nullb->queues[i];
-               init_waitqueue_head(&nq->wait);
-               nq->queue_depth = hw_queue_depth;
-               if (setup_commands(nq))
-                       break;
+
+               null_init_queue(nullb, nq);
+
+               ret = setup_commands(nq);
+               if (ret)
+                       goto err_queue;
                nullb->nr_queues++;
        }
 
-       if (i == submit_queues)
-               return 0;
-
+       return 0;
+err_queue:
        cleanup_queues(nullb);
-       return 1;
+       return ret;
 }
 
 static int null_add_dev(void)
@@ -518,11 +557,13 @@ static int null_add_dev(void)
        } else if (queue_mode == NULL_Q_BIO) {
                nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node);
                blk_queue_make_request(nullb->q, null_queue_bio);
+               init_driver_queues(nullb);
        } else {
                nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node);
                blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
                if (nullb->q)
                        blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
+               init_driver_queues(nullb);
        }
 
        if (!nullb->q)
@@ -534,10 +575,7 @@ static int null_add_dev(void)
        disk = nullb->disk = alloc_disk_node(1, home_node);
        if (!disk) {
 queue_fail:
-               if (queue_mode == NULL_Q_MQ)
-                       blk_mq_free_queue(nullb->q);
-               else
-                       blk_cleanup_queue(nullb->q);
+               blk_cleanup_queue(nullb->q);
                cleanup_queues(nullb);
 err:
                kfree(nullb);
@@ -579,7 +617,13 @@ static int __init null_init(void)
        }
 #endif
 
-       if (submit_queues > nr_cpu_ids)
+       if (queue_mode == NULL_Q_MQ && use_per_node_hctx) {
+               if (submit_queues < nr_online_nodes) {
+                       pr_warn("null_blk: submit_queues param is set to %u.",
+                                                       nr_online_nodes);
+                       submit_queues = nr_online_nodes;
+               }
+       } else if (submit_queues > nr_cpu_ids)
                submit_queues = nr_cpu_ids;
        else if (!submit_queues)
                submit_queues = 1;
index 9199c93be926ed97f33eaa95fc9ce4ec0549cea7..eb6e1e0e8db25f78f2d2407e0d54dafc2a2b9583 100644 (file)
@@ -5269,7 +5269,7 @@ const char *skd_skdev_state_to_str(enum skd_drvr_state state)
        }
 }
 
-const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
+static const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
 {
        switch (state) {
        case SKD_MSG_STATE_IDLE:
@@ -5281,7 +5281,7 @@ const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
        }
 }
 
-const char *skd_skreq_state_to_str(enum skd_req_state state)
+static const char *skd_skreq_state_to_str(enum skd_req_state state)
 {
        switch (state) {
        case SKD_REQ_STATE_IDLE:
index 6bfc1bb318f6399397ca8f169cc07fd98b46256d..dceb85f8d9a8251ed115e06af348692898f6a400 100644 (file)
@@ -87,6 +87,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0CF3, 0xE005) },
        { USB_DEVICE(0x0930, 0x0219) },
+       { USB_DEVICE(0x0930, 0x0220) },
        { USB_DEVICE(0x0489, 0xe057) },
        { USB_DEVICE(0x13d3, 0x3393) },
        { USB_DEVICE(0x0489, 0xe04e) },
@@ -129,6 +130,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
index c0ff34f2d2df577efffe902562f9578690ea4e39..3980fd18f6eaeeb129fe543728f19231df80bd59 100644 (file)
@@ -154,6 +154,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
index 7ff1d0d208a7c3f89f6827fd3e9ba8815dad202d..2d68054f97954402095051600529754b0f4b3e56 100644 (file)
@@ -50,7 +50,7 @@ obj-$(CONFIG_GPIO_TB0219)     += tb0219.o
 obj-$(CONFIG_TELCLOCK)         += tlclk.o
 
 obj-$(CONFIG_MWAVE)            += mwave/
-obj-$(CONFIG_AGP)              += agp/
+obj-y                          += agp/
 obj-$(CONFIG_PCMCIA)           += pcmcia/
 
 obj-$(CONFIG_HANGCHECK_TIMER)  += hangcheck-timer.o
index d8b1b576556cf8eba8c2fa398c6c9bc8d6960803..c528f96ee204fb3f480e29d96992e1e0c1870272 100644 (file)
@@ -68,6 +68,7 @@ config AGP_AMD64
 config AGP_INTEL
        tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
        depends on AGP && X86
+       select INTEL_GTT
        help
          This option gives you AGP support for the GLX component of X
          on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
@@ -155,3 +156,7 @@ config AGP_SGI_TIOCA
           This option gives you AGP GART support for the SGI TIO chipset
           for IA64 processors.
 
+config INTEL_GTT
+       tristate
+       depends on X86 && PCI
+
index 8eb56e273e75719f51d617fe3a2ed5c4b9cc06f2..604489bcdbf9b6c70b51e89f093accfdb34f4d25 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1)      += hp-agp.o
 obj-$(CONFIG_AGP_PARISC)       += parisc-agp.o
 obj-$(CONFIG_AGP_I460)         += i460-agp.o
 obj-$(CONFIG_AGP_INTEL)                += intel-agp.o
-obj-$(CONFIG_AGP_INTEL)                += intel-gtt.o
+obj-$(CONFIG_INTEL_GTT)                += intel-gtt.o
 obj-$(CONFIG_AGP_NVIDIA)       += nvidia-agp.o
 obj-$(CONFIG_AGP_SGI_TIOCA)    += sgi-agp.o
 obj-$(CONFIG_AGP_SIS)          += sis-agp.o
index a426ee1f57a6fd71b30fbd80429cac7c97aa1b4c..9ef0a48a5b28196600a780e4f76ec33ab4120c5e 100644 (file)
@@ -14,9 +14,6 @@
 #include "intel-agp.h"
 #include <drm/intel-gtt.h>
 
-int intel_agp_enabled;
-EXPORT_SYMBOL(intel_agp_enabled);
-
 static int intel_fetch_size(void)
 {
        int i;
@@ -814,8 +811,6 @@ static int agp_intel_probe(struct pci_dev *pdev,
 found_gmch:
        pci_set_drvdata(pdev, bridge);
        err = agp_add_bridge(bridge);
-       if (!err)
-               intel_agp_enabled = 1;
        return err;
 }
 
index b8e2014cb9cb0681d8fa1a21d7930b13e1e2a261..078968d8d07d933b974c8183b6cbd1f9a7163011 100644 (file)
@@ -94,6 +94,7 @@ static struct _intel_private {
 #define IS_IRONLAKE    intel_private.driver->is_ironlake
 #define HAS_PGTBL_EN   intel_private.driver->has_pgtbl_enable
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_gtt_map_memory(struct page **pages,
                                unsigned int num_entries,
                                struct sg_table *st)
@@ -168,6 +169,7 @@ static void i8xx_destroy_pages(struct page *page)
        __free_pages(page, 2);
        atomic_dec(&agp_bridge->current_memory_agp);
 }
+#endif
 
 #define I810_GTT_ORDER 4
 static int i810_setup(void)
@@ -209,6 +211,7 @@ static void i810_cleanup(void)
        free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER);
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start,
                                      int type)
 {
@@ -289,6 +292,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
        }
        kfree(curr);
 }
+#endif
 
 static int intel_gtt_setup_scratch_page(void)
 {
@@ -647,7 +651,9 @@ static int intel_gtt_init(void)
                return -ENOMEM;
        }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
        global_cache_flush();   /* FIXME: ? */
+#endif
 
        intel_private.stolen_size = intel_gtt_stolen_size();
 
@@ -671,6 +677,7 @@ static int intel_gtt_init(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_fetch_size(void)
 {
        int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes);
@@ -689,6 +696,7 @@ static int intel_fake_agp_fetch_size(void)
 
        return 0;
 }
+#endif
 
 static void i830_cleanup(void)
 {
@@ -801,6 +809,7 @@ static int i830_setup(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge)
 {
        agp_bridge->gatt_table_real = NULL;
@@ -825,6 +834,7 @@ static int intel_fake_agp_configure(void)
 
        return 0;
 }
+#endif
 
 static bool i830_check_flags(unsigned int flags)
 {
@@ -863,6 +873,7 @@ void intel_gtt_insert_sg_entries(struct sg_table *st,
 }
 EXPORT_SYMBOL(intel_gtt_insert_sg_entries);
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static void intel_gtt_insert_pages(unsigned int first_entry,
                                   unsigned int num_entries,
                                   struct page **pages,
@@ -928,6 +939,7 @@ out_err:
        mem->is_flushed = true;
        return ret;
 }
+#endif
 
 void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
 {
@@ -941,6 +953,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
 }
 EXPORT_SYMBOL(intel_gtt_clear_range);
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_remove_entries(struct agp_memory *mem,
                                         off_t pg_start, int type)
 {
@@ -982,6 +995,7 @@ static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count,
        /* always return NULL for other allocation types for now */
        return NULL;
 }
+#endif
 
 static int intel_alloc_chipset_flush_resource(void)
 {
@@ -1138,6 +1152,7 @@ static int i9xx_setup(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static const struct agp_bridge_driver intel_fake_agp_driver = {
        .owner                  = THIS_MODULE,
        .size_type              = FIXED_APER_SIZE,
@@ -1159,6 +1174,7 @@ static const struct agp_bridge_driver intel_fake_agp_driver = {
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_destroy_pages      = agp_generic_destroy_pages,
 };
+#endif
 
 static const struct intel_gtt_driver i81x_gtt_driver = {
        .gen = 1,
@@ -1376,11 +1392,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
 
        intel_private.refcount++;
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
        if (bridge) {
                bridge->driver = &intel_fake_agp_driver;
                bridge->dev_private_data = &intel_private;
                bridge->dev = bridge_pdev;
        }
+#endif
 
        intel_private.bridge_dev = pci_dev_get(bridge_pdev);
 
index 8e562dc656016cd9c4dbeaaa3dac0a96a02d0f26..e1f3337a0cf9f7d7fa223a86e84282765d915108 100644 (file)
@@ -27,15 +27,18 @@ static char *tpm_device_name = "TPM";
 static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
                                void **return_value)
 {
-       acpi_status status;
+       acpi_status status = AE_OK;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-       if (strstr(buffer.pointer, context) != NULL) {
-               *return_value = handle;
+
+       if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) {
+               if (strstr(buffer.pointer, context) != NULL) {
+                       *return_value = handle;
+                       status = AE_CTRL_TERMINATE;
+               }
                kfree(buffer.pointer);
-               return AE_CTRL_TERMINATE;
        }
-       return AE_OK;
+
+       return status;
 }
 
 static inline void ppi_assign_params(union acpi_object params[4],
index 8d3009e44fba40d4fba82825bd59d98febf53984..5543b7df8e16c736c210407a5d837ffb32ab3beb 100644 (file)
@@ -87,7 +87,7 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
        return 0;
 }
 
-static unsigned int _get_val(struct clk_divider *divider, u8 div)
+static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
 {
        if (divider->flags & CLK_DIVIDER_ONE_BASED)
                return div;
index 7be41e676a6470ab02b0bfd52867f54561a7960d..00a3abe103a5ac472dfb352a1bb0cec42cd29ddb 100644 (file)
@@ -60,7 +60,7 @@ static int s2mps11_clk_prepare(struct clk_hw *hw)
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
        int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap,
+       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
                                S2MPS11_REG_RTC_CTRL,
                                 s2mps11->mask, s2mps11->mask);
        if (!ret)
@@ -74,7 +74,7 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw)
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
        int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
+       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, S2MPS11_REG_RTC_CTRL,
                           s2mps11->mask, ~s2mps11->mask);
 
        if (!ret)
@@ -174,7 +174,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
                s2mps11_clk->hw.init = &s2mps11_clks_init[i];
                s2mps11_clk->mask = 1 << i;
 
-               ret = regmap_read(s2mps11_clk->iodev->regmap,
+               ret = regmap_read(s2mps11_clk->iodev->regmap_pmic,
                                  S2MPS11_REG_RTC_CTRL, &val);
                if (ret < 0)
                        goto err_reg;
index 39b40aaede2b36a3bd92546ff344420b480fb569..68e515d093d864ca9cc704d6f90a441695e67a6d 100644 (file)
@@ -26,17 +26,17 @@ static struct clk_onecell_data clk_data;
 #define ASS_CLK_DIV 0x4
 #define ASS_CLK_GATE 0x8
 
+/* list of all parent clock list */
+static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
+static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };
+
+#ifdef CONFIG_PM_SLEEP
 static unsigned long reg_save[][2] = {
        {ASS_CLK_SRC,  0},
        {ASS_CLK_DIV,  0},
        {ASS_CLK_GATE, 0},
 };
 
-/* list of all parent clock list */
-static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
-static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };
-
-#ifdef CONFIG_PM_SLEEP
 static int exynos_audss_clk_suspend(void)
 {
        int i;
index ad5ff50c5f281a5e1c31c498c78c5a717aa464de..1a7c1b929c690b03b2b24a1423da55a97b66aa00 100644 (file)
@@ -39,7 +39,7 @@
 #define SRC_TOP1               0xc214
 #define SRC_CAM                        0xc220
 #define SRC_TV                 0xc224
-#define SRC_MFC                        0xcc28
+#define SRC_MFC                        0xc228
 #define SRC_G3D                        0xc22c
 #define E4210_SRC_IMAGE                0xc230
 #define SRC_LCD0               0xc234
index adf32343c9f9c408f5b8bc7c78a6ce3bc66c27a7..e52359cf9b6fe76db63b787717f003454d89e12e 100644 (file)
@@ -25,6 +25,7 @@
 #define MPLL_LOCK              0x4000
 #define MPLL_CON0              0x4100
 #define SRC_CORE1              0x4204
+#define GATE_IP_ACP            0x8800
 #define CPLL_LOCK              0x10020
 #define EPLL_LOCK              0x10030
 #define VPLL_LOCK              0x10040
@@ -75,7 +76,6 @@
 #define SRC_CDREX              0x20200
 #define PLL_DIV2_SEL           0x20a24
 #define GATE_IP_DISP1          0x10928
-#define GATE_IP_ACP            0x10000
 
 /* list of PLLs to be registered */
 enum exynos5250_plls {
@@ -120,7 +120,8 @@ enum exynos5250_clks {
        spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
        hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
        tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
-       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d,
+       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d, mdma0,
+       smmu_mdma0,
 
        /* mux clocks */
        mout_hdmi = 1024,
@@ -354,8 +355,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
        GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
        GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
-       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
-       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 1, 0, 0),
        GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0),
        GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0),
        GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
@@ -406,7 +407,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(hsi2c2, "hsi2c2", "aclk66", GATE_IP_PERIC, 30, 0, 0),
        GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0),
        GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0),
-       GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0),
+       GATE(sysreg, "sysreg", "aclk66",
+                       GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0),
        GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED, 0),
        GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0),
        GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0),
@@ -492,6 +494,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(mixer, "mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
        GATE(hdmi, "hdmi", "mout_aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
        GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0),
+       GATE(mdma0, "mdma0", "aclk266", GATE_IP_ACP, 1, 0, 0),
+       GATE(smmu_mdma0, "smmu_mdma0", "aclk266", GATE_IP_ACP, 5, 0, 0),
 };
 
 static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
index 5c07a56962dbcffc038b81eb09305e61ee1d83e6..634c4d6dd45a489384d4c6b293e56f0fcc2ba331 100644 (file)
@@ -75,6 +75,7 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 config CLKSRC_EFM32
        bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32
        depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
+       select CLKSRC_MMIO
        default ARCH_EFM32
        help
          Support to use the timers of EFM32 SoCs as clock source and clock
index b2bb3a4bc20542199cb4a3eab1bc71bcc5022dfa..a92350b55d32604e3783368d8c4ab8a794ce55c8 100644 (file)
  * struct ttc_timer - This definition defines local timer structure
  *
  * @base_addr: Base address of timer
+ * @freq:      Timer input clock frequency
  * @clk:       Associated clock source
  * @clk_rate_change_nb Notifier block for clock rate changes
  */
 struct ttc_timer {
        void __iomem *base_addr;
+       unsigned long freq;
        struct clk *clk;
        struct notifier_block clk_rate_change_nb;
 };
@@ -196,9 +198,8 @@ static void ttc_set_mode(enum clock_event_mode mode,
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               ttc_set_interval(timer,
-                               DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk),
-                                       PRESCALE * HZ));
+               ttc_set_interval(timer, DIV_ROUND_CLOSEST(ttce->ttc.freq,
+                                               PRESCALE * HZ));
                break;
        case CLOCK_EVT_MODE_ONESHOT:
        case CLOCK_EVT_MODE_UNUSED:
@@ -273,6 +274,8 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
                return;
        }
 
+       ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk);
+
        ttccs->ttc.clk_rate_change_nb.notifier_call =
                ttc_rate_change_clocksource_cb;
        ttccs->ttc.clk_rate_change_nb.next = NULL;
@@ -298,16 +301,14 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
        __raw_writel(CNT_CNTRL_RESET,
                     ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET);
 
-       err = clocksource_register_hz(&ttccs->cs,
-                       clk_get_rate(ttccs->ttc.clk) / PRESCALE);
+       err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE);
        if (WARN_ON(err)) {
                kfree(ttccs);
                return;
        }
 
        ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET;
-       setup_sched_clock(ttc_sched_clock_read, 16,
-                       clk_get_rate(ttccs->ttc.clk) / PRESCALE);
+       setup_sched_clock(ttc_sched_clock_read, 16, ttccs->ttc.freq / PRESCALE);
 }
 
 static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
@@ -334,6 +335,9 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
                                ndata->new_rate / PRESCALE);
                local_irq_restore(flags);
 
+               /* update cached frequency */
+               ttc->freq = ndata->new_rate;
+
                /* fall through */
        }
        case PRE_RATE_CHANGE:
@@ -367,6 +371,7 @@ static void __init ttc_setup_clockevent(struct clk *clk,
        if (clk_notifier_register(ttcce->ttc.clk,
                                &ttcce->ttc.clk_rate_change_nb))
                pr_warn("Unable to register clock notifier.\n");
+       ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk);
 
        ttcce->ttc.base_addr = base;
        ttcce->ce.name = "ttc_clockevent";
@@ -396,7 +401,7 @@ static void __init ttc_setup_clockevent(struct clk *clk,
        }
 
        clockevents_config_and_register(&ttcce->ce,
-                       clk_get_rate(ttcce->ttc.clk) / PRESCALE, 1, 0xfffe);
+                       ttcce->ttc.freq / PRESCALE, 1, 0xfffe);
 }
 
 /**
index 35639cf4e5a208af89c9b692eae32227bcefc5d3..b9ddd9e3a2f599e2cc7424c1eac18d4280b2f850 100644 (file)
@@ -35,6 +35,5 @@ void __init clocksource_of_init(void)
 
                init_func = match->data;
                init_func(np);
-               of_node_put(np);
        }
 }
index 45ba8aecc7298428016dd6d5601482362cce0c4e..2a2ea2717f3ac94dfba2fdd6a986c4630556e7da 100644 (file)
@@ -108,12 +108,11 @@ static void __init add_clocksource(struct device_node *source_timer)
 
 static u64 read_sched_clock(void)
 {
-       return __raw_readl(sched_io_base);
+       return ~__raw_readl(sched_io_base);
 }
 
 static const struct of_device_id sptimer_ids[] __initconst = {
        { .compatible = "picochip,pc3x2-rtc" },
-       { .compatible = "snps,dw-apb-timer-sp" },
        { /* Sentinel */ },
 };
 
@@ -151,4 +150,6 @@ static void __init dw_apb_timer_init(struct device_node *timer)
        num_called++;
 }
 CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
index 2fb4695a28d83e2e0f26c1e787b0c575612c650c..a4f6119aafd814efe2839f416bbe8fe99bc41554 100644 (file)
@@ -179,6 +179,9 @@ static void __init sun4i_timer_init(struct device_node *node)
        writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
               timer_base + TIMER_CTL_REG(0));
 
+       /* Make sure timer is stopped before playing with interrupts */
+       sun4i_clkevt_time_stop(0);
+
        ret = setup_irq(irq, &sun4i_timer_irq);
        if (ret)
                pr_warn("failed to setup irq %d\n", irq);
index d8e47e5027858faf9f99c0b3ad99883bd7bc9cc2..4e7f6802e840ba9379eb42d733801526d173e89e 100644 (file)
@@ -255,11 +255,6 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
 
        ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
 
-       /*
-        * Set scale and timer for sched_clock.
-        */
-       sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk);
-
        /*
         * Setup free-running clocksource timer (interrupts
         * disabled).
@@ -270,6 +265,11 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
        timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN |
                             TIMER0_DIV(TIMER_DIVIDER_SHIFT));
 
+       /*
+        * Set scale and timer for sched_clock.
+        */
+       sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk);
+
        clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
                              "armada_370_xp_clocksource",
                              timer_clk, 300, 32, clocksource_mmio_readl_down);
index 02d534da22dda0bb22277c4f80f7c1d27f24cd65..8d19f7c06010c364ff6ee758c15096c252f9f4bd 100644 (file)
@@ -828,14 +828,17 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
        int ret = 0;
 
        memcpy(&new_policy, policy, sizeof(*policy));
+
+       /* Use the default policy if its valid. */
+       if (cpufreq_driver->setpolicy)
+               cpufreq_parse_governor(policy->governor->name,
+                                       &new_policy.policy, NULL);
+
        /* assure that the starting sequence is run in cpufreq_set_policy */
        policy->governor = NULL;
 
        /* set default policy */
        ret = cpufreq_set_policy(policy, &new_policy);
-       policy->user_policy.policy = policy->policy;
-       policy->user_policy.governor = policy->governor;
-
        if (ret) {
                pr_debug("setting policy failed\n");
                if (cpufreq_driver->exit)
@@ -845,8 +848,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
 
 #ifdef CONFIG_HOTPLUG_CPU
 static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
-                                 unsigned int cpu, struct device *dev,
-                                 bool frozen)
+                                 unsigned int cpu, struct device *dev)
 {
        int ret = 0;
        unsigned long flags;
@@ -877,11 +879,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
                }
        }
 
-       /* Don't touch sysfs links during light-weight init */
-       if (!frozen)
-               ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
-
-       return ret;
+       return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
 }
 #endif
 
@@ -926,6 +924,27 @@ err_free_policy:
        return NULL;
 }
 
+static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
+{
+       struct kobject *kobj;
+       struct completion *cmp;
+
+       down_read(&policy->rwsem);
+       kobj = &policy->kobj;
+       cmp = &policy->kobj_unregister;
+       up_read(&policy->rwsem);
+       kobject_put(kobj);
+
+       /*
+        * We need to make sure that the underlying kobj is
+        * actually not referenced anymore by anybody before we
+        * proceed with unloading.
+        */
+       pr_debug("waiting for dropping of refcount\n");
+       wait_for_completion(cmp);
+       pr_debug("wait complete\n");
+}
+
 static void cpufreq_policy_free(struct cpufreq_policy *policy)
 {
        free_cpumask_var(policy->related_cpus);
@@ -986,7 +1005,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
        list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
                if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
                        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
-                       ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen);
+                       ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev);
                        up_read(&cpufreq_rwsem);
                        return ret;
                }
@@ -994,15 +1013,17 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 
-       if (frozen)
-               /* Restore the saved policy when doing light-weight init */
-               policy = cpufreq_policy_restore(cpu);
-       else
+       /*
+        * Restore the saved policy when doing light-weight init and fall back
+        * to the full init if that fails.
+        */
+       policy = frozen ? cpufreq_policy_restore(cpu) : NULL;
+       if (!policy) {
+               frozen = false;
                policy = cpufreq_policy_alloc();
-
-       if (!policy)
-               goto nomem_out;
-
+               if (!policy)
+                       goto nomem_out;
+       }
 
        /*
         * In the resume path, since we restore a saved policy, the assignment
@@ -1047,8 +1068,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
         */
        cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
 
-       policy->user_policy.min = policy->min;
-       policy->user_policy.max = policy->max;
+       if (!frozen) {
+               policy->user_policy.min = policy->min;
+               policy->user_policy.max = policy->max;
+       }
 
        blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                                     CPUFREQ_START, policy);
@@ -1079,6 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 
        cpufreq_init_policy(policy);
 
+       if (!frozen) {
+               policy->user_policy.policy = policy->policy;
+               policy->user_policy.governor = policy->governor;
+       }
+
        kobject_uevent(&policy->kobj, KOBJ_ADD);
        up_read(&cpufreq_rwsem);
 
@@ -1096,7 +1124,13 @@ err_get_freq:
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(policy);
 err_set_policy_cpu:
+       if (frozen) {
+               /* Do not leave stale fallback data behind. */
+               per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
+               cpufreq_policy_put_kobj(policy);
+       }
        cpufreq_policy_free(policy);
+
 nomem_out:
        up_read(&cpufreq_rwsem);
 
@@ -1118,7 +1152,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 }
 
 static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
-                                          unsigned int old_cpu, bool frozen)
+                                          unsigned int old_cpu)
 {
        struct device *cpu_dev;
        int ret;
@@ -1126,10 +1160,6 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
        /* first sibling now owns the new sysfs dir */
        cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
 
-       /* Don't touch sysfs files during light-weight tear-down */
-       if (frozen)
-               return cpu_dev->id;
-
        sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
        ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
        if (ret) {
@@ -1196,7 +1226,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                if (!frozen)
                        sysfs_remove_link(&dev->kobj, "cpufreq");
        } else if (cpus > 1) {
-               new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
+               new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
                if (new_cpu >= 0) {
                        update_policy_cpu(policy, new_cpu);
 
@@ -1218,8 +1248,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
        int ret;
        unsigned long flags;
        struct cpufreq_policy *policy;
-       struct kobject *kobj;
-       struct completion *cmp;
 
        read_lock_irqsave(&cpufreq_driver_lock, flags);
        policy = per_cpu(cpufreq_cpu_data, cpu);
@@ -1249,22 +1277,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                        }
                }
 
-               if (!frozen) {
-                       down_read(&policy->rwsem);
-                       kobj = &policy->kobj;
-                       cmp = &policy->kobj_unregister;
-                       up_read(&policy->rwsem);
-                       kobject_put(kobj);
-
-                       /*
-                        * We need to make sure that the underlying kobj is
-                        * actually not referenced anymore by anybody before we
-                        * proceed with unloading.
-                        */
-                       pr_debug("waiting for dropping of refcount\n");
-                       wait_for_completion(cmp);
-                       pr_debug("wait complete\n");
-               }
+               if (!frozen)
+                       cpufreq_policy_put_kobj(policy);
 
                /*
                 * Perform the ->exit() even during light-weight tear-down,
index 5f1cbae369611062c18ee50982ffa5c6f724d30f..d51f17ed691e023196bbd7e56a3341d4025ce092 100644 (file)
@@ -581,7 +581,8 @@ static void intel_pstate_timer_func(unsigned long __data)
 }
 
 #define ICPU(model, policy) \
-       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&policy }
+       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\
+                       (unsigned long)&policy }
 
 static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        ICPU(0x2a, core_params),
@@ -614,6 +615,11 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        cpu = all_cpu_data[cpunum];
 
        intel_pstate_get_cpu_pstates(cpu);
+       if (!cpu->pstate.current_pstate) {
+               all_cpu_data[cpunum] = NULL;
+               kfree(cpu);
+               return -ENODATA;
+       }
 
        cpu->cpu = cpunum;
 
index 36795639df0da2d828c784b61c82a728037f6e1c..6e51114057d0963605ef1dfc80b231946e1b88f7 100644 (file)
@@ -65,7 +65,7 @@ static struct cpuidle_driver calxeda_idle_driver = {
        .state_count = 2,
 };
 
-static int __init calxeda_cpuidle_probe(struct platform_device *pdev)
+static int calxeda_cpuidle_probe(struct platform_device *pdev)
 {
        return cpuidle_register(&calxeda_idle_driver, NULL);
 }
index 9dd6e01eac33050b8304c5f8758440e7286606f2..f757a0f428bde807a8e5402af8404e98314c2bf8 100644 (file)
@@ -1410,14 +1410,12 @@ static const struct platform_device_info ixp_dev_info __initdata = {
 static int __init ixp_module_init(void)
 {
        int num = ARRAY_SIZE(ixp4xx_algos);
-       int i, err ;
+       int i, err;
 
        pdev = platform_device_register_full(&ixp_dev_info);
        if (IS_ERR(pdev))
                return PTR_ERR(pdev);
 
-       dev = &pdev->dev;
-
        spin_lock_init(&desc_lock);
        spin_lock_init(&emerg_lock);
 
index 446687cc2334ed2f60a0b6f0170382fe733aae01..c823daaf90430bb501ff9bc168e88adbcecf87ef 100644 (file)
@@ -62,6 +62,7 @@ config INTEL_IOATDMA
        tristate "Intel I/OAT DMA support"
        depends on PCI && X86
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select DCA
        help
          Enable support for the Intel(R) I/OAT DMA engine present
@@ -112,6 +113,7 @@ config MV_XOR
        bool "Marvell XOR engine support"
        depends on PLAT_ORION
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        ---help---
          Enable support for the Marvell XOR engine.
@@ -187,6 +189,7 @@ config AMCC_PPC440SPE_ADMA
        tristate "AMCC PPC440SPe ADMA support"
        depends on 440SPe || 440SP
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ARCH_HAS_ASYNC_TX_FIND_CHANNEL
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        help
@@ -352,6 +355,7 @@ config NET_DMA
        bool "Network: TCP receive copy offload"
        depends on DMA_ENGINE && NET
        default (INTEL_IOATDMA || FSL_DMA)
+       depends on BROKEN
        help
          This enables the use of DMA engines in the network stack to
          offload receive copy-to-user operations, freeing CPU cycles.
@@ -377,4 +381,7 @@ config DMATEST
          Simple DMA test client. Say N unless you're debugging a
          DMA Device driver.
 
+config DMA_ENGINE_RAID
+       bool
+
 endif
index f31d647acdfaac3730371e1366ff964e245435ac..2787aba60c6bdee8ed0489cb932338d6a81528ac 100644 (file)
@@ -347,10 +347,6 @@ static struct device *chan2dev(struct dma_chan *chan)
 {
        return &chan->dev->device;
 }
-static struct device *chan2parent(struct dma_chan *chan)
-{
-       return chan->dev->device.parent;
-}
 
 #if defined(VERBOSE_DEBUG)
 static void vdbg_dump_regs(struct at_dma_chan *atchan)
index 24095ff8a93b0a0ff121254198e6d4e46bc6ddb8..ed610b4975186b8e389de7360d4d3c8e6f5785e3 100644 (file)
@@ -967,7 +967,7 @@ struct dmaengine_unmap_pool {
 #define __UNMAP_POOL(x) { .size = x, .name = "dmaengine-unmap-" __stringify(x) }
 static struct dmaengine_unmap_pool unmap_pool[] = {
        __UNMAP_POOL(2),
-       #if IS_ENABLED(CONFIG_ASYNC_TX_DMA)
+       #if IS_ENABLED(CONFIG_DMA_ENGINE_RAID)
        __UNMAP_POOL(16),
        __UNMAP_POOL(128),
        __UNMAP_POOL(256),
@@ -1109,7 +1109,7 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
        dma_cookie_t cookie;
        unsigned long flags;
 
-       unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOIO);
+       unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOWAIT);
        if (!unmap)
                return -ENOMEM;
 
index 20f9a3aaf9266ea6daa71a18f08d258afa8a1a1e..9dfcaf5c12888d3de80483329ffccc7fbbacd02a 100644 (file)
@@ -539,9 +539,9 @@ static int dmatest_func(void *data)
 
                um->len = params->buf_size;
                for (i = 0; i < src_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->srcs[i];
+                       void *buf = thread->srcs[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
                                                   um->len, DMA_TO_DEVICE);
@@ -559,9 +559,9 @@ static int dmatest_func(void *data)
                /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
                dsts = &um->addr[src_cnt];
                for (i = 0; i < dst_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->dsts[i];
+                       void *buf = thread->dsts[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
                                               DMA_BIDIRECTIONAL);
index 7086a16a55f2ed488573e475e615600c80be767e..f157c6f76b32b8c98dce28eed6253db033acc258 100644 (file)
@@ -86,11 +86,6 @@ static void set_desc_cnt(struct fsldma_chan *chan,
        hw->count = CPU_TO_DMA(chan, count, 32);
 }
 
-static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
-{
-       return DMA_TO_CPU(chan, desc->hw.count, 32);
-}
-
 static void set_desc_src(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
@@ -101,16 +96,6 @@ static void set_desc_src(struct fsldma_chan *chan,
        hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
 }
 
-static dma_addr_t get_desc_src(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_dst(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
@@ -121,16 +106,6 @@ static void set_desc_dst(struct fsldma_chan *chan,
        hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
 }
 
-static dma_addr_t get_desc_dst(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_next(struct fsldma_chan *chan,
                          struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
@@ -408,7 +383,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
        struct fsl_desc_sw *child;
        unsigned long flags;
-       dma_cookie_t cookie;
+       dma_cookie_t cookie = -EINVAL;
 
        spin_lock_irqsave(&chan->desc_lock, flags);
 
@@ -854,10 +829,6 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
                                      struct fsl_desc_sw *desc)
 {
        struct dma_async_tx_descriptor *txd = &desc->async_tx;
-       struct device *dev = chan->common.device->dev;
-       dma_addr_t src = get_desc_src(chan, desc);
-       dma_addr_t dst = get_desc_dst(chan, desc);
-       u32 len = get_desc_cnt(chan, desc);
 
        /* Run the link descriptor callback function */
        if (txd->callback) {
index 1a49c777607c50d313482f3ead21c19572a1cf8d..87529181efccb9851467cc04be04bd91fecb15b3 100644 (file)
@@ -817,7 +817,15 @@ int ioat_dma_self_test(struct ioatdma_device *device)
        }
 
        dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, dma_src)) {
+               dev_err(dev, "mapping src buffer failed\n");
+               goto free_resources;
+       }
        dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
+       if (dma_mapping_error(dev, dma_dest)) {
+               dev_err(dev, "mapping dest buffer failed\n");
+               goto unmap_src;
+       }
        flags = DMA_PREP_INTERRUPT;
        tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,
                                                   IOAT_TEST_SIZE, flags);
@@ -855,8 +863,9 @@ int ioat_dma_self_test(struct ioatdma_device *device)
        }
 
 unmap_dma:
-       dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
        dma_unmap_single(dev, dma_dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
+unmap_src:
+       dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
 free_resources:
        dma->device_free_chan_resources(dma_chan);
 out:
index 7807f0ef4e209c25ad90db9d32f7bc13955391cf..53fb0c8365b0b27f29a893a3072103c9fb2360e9 100644 (file)
@@ -54,12 +54,6 @@ static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
        hw_desc->desc_command = (1 << 31);
 }
 
-static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
-{
-       struct mv_xor_desc *hw_desc = desc->hw_desc;
-       return hw_desc->phy_dest_addr;
-}
-
 static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
                                   u32 byte_count)
 {
@@ -787,7 +781,6 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
 /*
  * Perform a transaction to verify the HW works.
  */
-#define MV_XOR_TEST_SIZE 2000
 
 static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
 {
@@ -797,20 +790,21 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        struct dma_chan *dma_chan;
        dma_cookie_t cookie;
        struct dma_async_tx_descriptor *tx;
+       struct dmaengine_unmap_data *unmap;
        int err = 0;
 
-       src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+       src = kmalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
        if (!src)
                return -ENOMEM;
 
-       dest = kzalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+       dest = kzalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
        if (!dest) {
                kfree(src);
                return -ENOMEM;
        }
 
        /* Fill in src buffer */
-       for (i = 0; i < MV_XOR_TEST_SIZE; i++)
+       for (i = 0; i < PAGE_SIZE; i++)
                ((u8 *) src)[i] = (u8)i;
 
        dma_chan = &mv_chan->dmachan;
@@ -819,14 +813,26 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
                goto out;
        }
 
-       dest_dma = dma_map_single(dma_chan->device->dev, dest,
-                                 MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+       unmap = dmaengine_get_unmap_data(dma_chan->device->dev, 2, GFP_KERNEL);
+       if (!unmap) {
+               err = -ENOMEM;
+               goto free_resources;
+       }
+
+       src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0,
+                                PAGE_SIZE, DMA_TO_DEVICE);
+       unmap->to_cnt = 1;
+       unmap->addr[0] = src_dma;
 
-       src_dma = dma_map_single(dma_chan->device->dev, src,
-                                MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
+       dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0,
+                                 PAGE_SIZE, DMA_FROM_DEVICE);
+       unmap->from_cnt = 1;
+       unmap->addr[1] = dest_dma;
+
+       unmap->len = PAGE_SIZE;
 
        tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
-                                   MV_XOR_TEST_SIZE, 0);
+                                   PAGE_SIZE, 0);
        cookie = mv_xor_tx_submit(tx);
        mv_xor_issue_pending(dma_chan);
        async_tx_ack(tx);
@@ -841,8 +847,8 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
        dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
-                               MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
-       if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
+                               PAGE_SIZE, DMA_FROM_DEVICE);
+       if (memcmp(src, dest, PAGE_SIZE)) {
                dev_err(dma_chan->device->dev,
                        "Self-test copy failed compare, disabling\n");
                err = -ENODEV;
@@ -850,6 +856,7 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
 free_resources:
+       dmaengine_unmap_put(unmap);
        mv_xor_free_chan_resources(dma_chan);
 out:
        kfree(src);
@@ -867,13 +874,15 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST];
        dma_addr_t dest_dma;
        struct dma_async_tx_descriptor *tx;
+       struct dmaengine_unmap_data *unmap;
        struct dma_chan *dma_chan;
        dma_cookie_t cookie;
        u8 cmp_byte = 0;
        u32 cmp_word;
        int err = 0;
+       int src_count = MV_XOR_NUM_SRC_TEST;
 
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+       for (src_idx = 0; src_idx < src_count; src_idx++) {
                xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
                if (!xor_srcs[src_idx]) {
                        while (src_idx--)
@@ -890,13 +899,13 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        }
 
        /* Fill in src buffers */
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+       for (src_idx = 0; src_idx < src_count; src_idx++) {
                u8 *ptr = page_address(xor_srcs[src_idx]);
                for (i = 0; i < PAGE_SIZE; i++)
                        ptr[i] = (1 << src_idx);
        }
 
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++)
+       for (src_idx = 0; src_idx < src_count; src_idx++)
                cmp_byte ^= (u8) (1 << src_idx);
 
        cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
@@ -910,16 +919,29 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
                goto out;
        }
 
+       unmap = dmaengine_get_unmap_data(dma_chan->device->dev, src_count + 1,
+                                        GFP_KERNEL);
+       if (!unmap) {
+               err = -ENOMEM;
+               goto free_resources;
+       }
+
        /* test xor */
-       dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
-                               DMA_FROM_DEVICE);
+       for (i = 0; i < src_count; i++) {
+               unmap->addr[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+                                             0, PAGE_SIZE, DMA_TO_DEVICE);
+               dma_srcs[i] = unmap->addr[i];
+               unmap->to_cnt++;
+       }
 
-       for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++)
-               dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
-                                          0, PAGE_SIZE, DMA_TO_DEVICE);
+       unmap->addr[src_count] = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
+                                     DMA_FROM_DEVICE);
+       dest_dma = unmap->addr[src_count];
+       unmap->from_cnt = 1;
+       unmap->len = PAGE_SIZE;
 
        tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
-                                MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
+                                src_count, PAGE_SIZE, 0);
 
        cookie = mv_xor_tx_submit(tx);
        mv_xor_issue_pending(dma_chan);
@@ -948,9 +970,10 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        }
 
 free_resources:
+       dmaengine_unmap_put(unmap);
        mv_xor_free_chan_resources(dma_chan);
 out:
-       src_idx = MV_XOR_NUM_SRC_TEST;
+       src_idx = src_count;
        while (src_idx--)
                __free_page(xor_srcs[src_idx]);
        __free_page(dest);
@@ -1176,6 +1199,7 @@ static int mv_xor_probe(struct platform_device *pdev)
                int i = 0;
 
                for_each_child_of_node(pdev->dev.of_node, np) {
+                       struct mv_xor_chan *chan;
                        dma_cap_mask_t cap_mask;
                        int irq;
 
@@ -1193,21 +1217,21 @@ static int mv_xor_probe(struct platform_device *pdev)
                                goto err_channel_add;
                        }
 
-                       xordev->channels[i] =
-                               mv_xor_channel_add(xordev, pdev, i,
-                                                  cap_mask, irq);
-                       if (IS_ERR(xordev->channels[i])) {
-                               ret = PTR_ERR(xordev->channels[i]);
-                               xordev->channels[i] = NULL;
+                       chan = mv_xor_channel_add(xordev, pdev, i,
+                                                 cap_mask, irq);
+                       if (IS_ERR(chan)) {
+                               ret = PTR_ERR(chan);
                                irq_dispose_mapping(irq);
                                goto err_channel_add;
                        }
 
+                       xordev->channels[i] = chan;
                        i++;
                }
        } else if (pdata && pdata->channels) {
                for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
                        struct mv_xor_channel_data *cd;
+                       struct mv_xor_chan *chan;
                        int irq;
 
                        cd = &pdata->channels[i];
@@ -1222,13 +1246,14 @@ static int mv_xor_probe(struct platform_device *pdev)
                                goto err_channel_add;
                        }
 
-                       xordev->channels[i] =
-                               mv_xor_channel_add(xordev, pdev, i,
-                                                  cd->cap_mask, irq);
-                       if (IS_ERR(xordev->channels[i])) {
-                               ret = PTR_ERR(xordev->channels[i]);
+                       chan = mv_xor_channel_add(xordev, pdev, i,
+                                                 cd->cap_mask, irq);
+                       if (IS_ERR(chan)) {
+                               ret = PTR_ERR(chan);
                                goto err_channel_add;
                        }
+
+                       xordev->channels[i] = chan;
                }
        }
 
index cdf0483b8f2dfb8f746b786fd6bf84b0d5f6657b..536632f6479c6966029022614f2bf863974256b4 100644 (file)
@@ -2492,12 +2492,9 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
 
 static inline void _init_desc(struct dma_pl330_desc *desc)
 {
-       desc->pchan = NULL;
        desc->req.x = &desc->px;
        desc->req.token = desc;
        desc->rqcfg.swap = SWAP_NO;
-       desc->rqcfg.privileged = 0;
-       desc->rqcfg.insnaccess = 0;
        desc->rqcfg.scctl = SCCTRL0;
        desc->rqcfg.dcctl = DCCTRL0;
        desc->req.cfg = &desc->rqcfg;
@@ -2517,7 +2514,7 @@ static int add_desc(struct dma_pl330_dmac *pdmac, gfp_t flg, int count)
        if (!pdmac)
                return 0;
 
-       desc = kmalloc(count * sizeof(*desc), flg);
+       desc = kcalloc(count, sizeof(*desc), flg);
        if (!desc)
                return 0;
 
index 8da48c6b2a38ccd76f3e127d53e4be5ab7be425c..8bba298535b0984e241793403af6920399d7366d 100644 (file)
@@ -532,29 +532,6 @@ static void ppc440spe_desc_init_memcpy(struct ppc440spe_adma_desc_slot *desc,
        hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
 }
 
-/**
- * ppc440spe_desc_init_memset - initialize the descriptor for MEMSET operation
- */
-static void ppc440spe_desc_init_memset(struct ppc440spe_adma_desc_slot *desc,
-                                       int value, unsigned long flags)
-{
-       struct dma_cdb *hw_desc = desc->hw_desc;
-
-       memset(desc->hw_desc, 0, sizeof(struct dma_cdb));
-       desc->hw_next = NULL;
-       desc->src_cnt = 1;
-       desc->dst_cnt = 1;
-
-       if (flags & DMA_PREP_INTERRUPT)
-               set_bit(PPC440SPE_DESC_INT, &desc->flags);
-       else
-               clear_bit(PPC440SPE_DESC_INT, &desc->flags);
-
-       hw_desc->sg1u = hw_desc->sg1l = cpu_to_le32((u32)value);
-       hw_desc->sg3u = hw_desc->sg3l = cpu_to_le32((u32)value);
-       hw_desc->opc = DMA_CDB_OPC_DFILL128;
-}
-
 /**
  * ppc440spe_desc_set_src_addr - set source address into the descriptor
  */
@@ -1504,8 +1481,6 @@ static dma_cookie_t ppc440spe_adma_run_tx_complete_actions(
                struct ppc440spe_adma_chan *chan,
                dma_cookie_t cookie)
 {
-       int i;
-
        BUG_ON(desc->async_tx.cookie < 0);
        if (desc->async_tx.cookie > 0) {
                cookie = desc->async_tx.cookie;
@@ -3898,7 +3873,7 @@ static void ppc440spe_adma_init_capabilities(struct ppc440spe_adma_device *adev)
                        ppc440spe_adma_prep_dma_interrupt;
        }
        pr_info("%s: AMCC(R) PPC440SP(E) ADMA Engine: "
-         "( %s%s%s%s%s%s%s)\n",
+         "( %s%s%s%s%s%s)\n",
          dev_name(adev->dev),
          dma_has_cap(DMA_PQ, adev->common.cap_mask) ? "pq " : "",
          dma_has_cap(DMA_PQ_VAL, adev->common.cap_mask) ? "pq_val " : "",
index bae6c29f5502ab951f7926bdf621977703bc96b1..17686caf64d5c4beedd0d189dd4487a57acb1254 100644 (file)
@@ -406,7 +406,6 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
        dma_async_tx_callback callback;
        void *param;
        struct dma_async_tx_descriptor *txd = &desc->txd;
-       struct txx9dmac_slave *ds = dc->chan.private;
 
        dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
                 txd->cookie, desc);
index b0bb056458a363b0ee457beea13a8b926a63d483..281029daf98c7ea291886d46ecf05378bfa98718 100644 (file)
@@ -1623,7 +1623,6 @@ static struct scsi_host_template scsi_driver_template = {
        .cmd_per_lun            = 1,
        .can_queue              = 1,
        .sdev_attrs             = sbp2_scsi_sysfs_attrs,
-       .no_write_same          = 1,
 };
 
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
index 299fad6b5867287f0869648e4a99eaa9b581d872..5373dc5b60114f31af5cf66cdbb923bdc6b0f973 100644 (file)
@@ -14,3 +14,4 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)  += google/
 obj-$(CONFIG_EFI)              += efi/
+obj-$(CONFIG_UEFI_CPER)                += efi/
index 3150aa4874e8f67e4360635934acdcb11bac6fef..6aecbc86ec9482f322e55735de02c9daa1e4775a 100644 (file)
@@ -36,7 +36,7 @@ config EFI_VARS_PSTORE_DEFAULT_DISABLE
          backend for pstore by default. This setting can be overridden
          using the efivars module's pstore_disable parameter.
 
-config UEFI_CPER
-       def_bool n
-
 endmenu
+
+config UEFI_CPER
+       bool
index 9ba156d3c7755e6854595b9983fc23db20fa2111..6c2a41ec21baf63989e9d676b569a21132c006c8 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Makefile for linux kernel
 #
-obj-y                                  += efi.o vars.o
+obj-$(CONFIG_EFI)                      += efi.o vars.o
 obj-$(CONFIG_EFI_VARS)                 += efivars.o
 obj-$(CONFIG_EFI_VARS_PSTORE)          += efi-pstore.o
 obj-$(CONFIG_UEFI_CPER)                        += cper.o
index 743fd426f21bf29299b850833d0137348a2bca64..4b9dc836dcf956e86c3800398946d40b0d1cf6dc 100644 (file)
@@ -356,6 +356,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 static struct pstore_info efi_pstore_info = {
        .owner          = THIS_MODULE,
        .name           = "efi",
+       .flags          = PSTORE_FLAGS_FRAGILE,
        .open           = efi_pstore_open,
        .close          = efi_pstore_close,
        .read           = efi_pstore_read,
index 7b37300973dbc15d1a424448d932867b4d10d06d..2baf0ddf7e0230f2b334fc9e25dfca3bbe0205c9 100644 (file)
@@ -252,7 +252,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
        writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
-       clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+       clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
        __clear_bit(gpio, msm_gpio.enabled_irqs);
        spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
@@ -264,7 +264,7 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
        __set_bit(gpio, msm_gpio.enabled_irqs);
-       set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+       set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
        writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
        spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
index fe088a30567ac63325fd02be82b8e682aa2323eb..8b7e719a68c3662f454c76b3e82b9569abeb22f8 100644 (file)
@@ -169,7 +169,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
        u32 pending;
        unsigned int offset, irqs_handled = 0;
 
-       while ((pending = gpio_rcar_read(p, INTDT))) {
+       while ((pending = gpio_rcar_read(p, INTDT) &
+                         gpio_rcar_read(p, INTMSK))) {
                offset = __ffs(pending);
                gpio_rcar_write(p, INTCLR, BIT(offset));
                generic_handle_irq(irq_find_mapping(p->irq_domain, offset));
index b97d6a6577b961d379a977e14a3c5c693cce5049..f9996899c1f29cd26e7267cbeb349378c6e26bb4 100644 (file)
@@ -300,7 +300,7 @@ static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
        if (offset < TWL4030_GPIO_MAX)
                ret = twl4030_set_gpio_direction(offset, 1);
        else
-               ret = -EINVAL;
+               ret = -EINVAL;  /* LED outputs can't be set as input */
 
        if (!ret)
                priv->direction &= ~BIT(offset);
@@ -354,11 +354,20 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
 static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
 {
        struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
-       int ret = -EINVAL;
+       int ret = 0;
 
        mutex_lock(&priv->mutex);
-       if (offset < TWL4030_GPIO_MAX)
+       if (offset < TWL4030_GPIO_MAX) {
                ret = twl4030_set_gpio_direction(offset, 0);
+               if (ret) {
+                       mutex_unlock(&priv->mutex);
+                       return ret;
+               }
+       }
+
+       /*
+        *  LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output
+        */
 
        priv->direction |= BIT(offset);
        mutex_unlock(&priv->mutex);
index 5b1cb7e73ee8c1f1be33a949e8d82be2320685de..8e7fa4dbaed867ca45cb9c885db53543a65a74b9 100644 (file)
@@ -192,6 +192,8 @@ source "drivers/gpu/drm/tilcdc/Kconfig"
 
 source "drivers/gpu/drm/qxl/Kconfig"
 
+source "drivers/gpu/drm/bochs/Kconfig"
+
 source "drivers/gpu/drm/msm/Kconfig"
 
 source "drivers/gpu/drm/tegra/Kconfig"
index d1a5c7277678c7e39db151497b0a734403a09b2e..292a79d64146274428ad1ef251d08e1d78d46bf5 100644 (file)
@@ -58,6 +58,7 @@ obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_OMAP) += omapdrm/
 obj-$(CONFIG_DRM_TILCDC)       += tilcdc/
 obj-$(CONFIG_DRM_QXL) += qxl/
+obj-$(CONFIG_DRM_BOCHS) += bochs/
 obj-$(CONFIG_DRM_MSM) += msm/
 obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-y                  += i2c/
index 40d371521fe19fea47b4a59b0a4fe1db2054aa54..50ae88ad4d76fb85b863adfd6129ea7a75df2178 100644 (file)
@@ -5,6 +5,7 @@ config DRM_ARMADA
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select DRM_KMS_HELPER
+       select DRM_KMS_FB_HELPER
        help
          Support the "LCD" controllers found on the Marvell Armada 510
          devices.  There are two controllers on the device, each controller
index eef09ec9a5ff03691f259031d6b0dc5337e4fb02..a72cae03b99b781d7becf0987c91317c3777a65c 100644 (file)
@@ -103,6 +103,7 @@ void armada_drm_queue_unref_work(struct drm_device *,
 extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs;
 
 int armada_fbdev_init(struct drm_device *);
+void armada_fbdev_lastclose(struct drm_device *);
 void armada_fbdev_fini(struct drm_device *);
 
 int armada_overlay_plane_create(struct drm_device *, unsigned long);
index 4f2b28354915c68fcbc730af9ef8b50142ef26bb..acf3a36c9ebc453737b1a849aa6715f41b241d68 100644 (file)
@@ -128,6 +128,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
                return -ENOMEM;
        }
 
+       platform_set_drvdata(dev->platformdev, dev);
        dev->dev_private = priv;
 
        /* Get the implementation specific driver data. */
@@ -321,6 +322,11 @@ static struct drm_ioctl_desc armada_ioctls[] = {
                DRM_UNLOCKED),
 };
 
+static void armada_drm_lastclose(struct drm_device *dev)
+{
+       armada_fbdev_lastclose(dev);
+}
+
 static const struct file_operations armada_drm_fops = {
        .owner                  = THIS_MODULE,
        .llseek                 = no_llseek,
@@ -337,7 +343,7 @@ static struct drm_driver armada_drm_driver = {
        .open                   = NULL,
        .preclose               = NULL,
        .postclose              = NULL,
-       .lastclose              = NULL,
+       .lastclose              = armada_drm_lastclose,
        .unload                 = armada_drm_unload,
        .get_vblank_counter     = drm_vblank_count,
        .enable_vblank          = armada_drm_enable_vblank,
@@ -376,7 +382,7 @@ static int armada_drm_probe(struct platform_device *pdev)
 
 static int armada_drm_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&armada_drm_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
        return 0;
 }
 
index dd5ea77dac960c916fd5d8169c625a572a897e05..948cb14c561ec501e10bae0f89adb043dc0b2808 100644 (file)
@@ -105,9 +105,9 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
        drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth);
        drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height);
 
-       DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08x\n",
-               dfb->fb.width, dfb->fb.height,
-               dfb->fb.bits_per_pixel, obj->phys_addr);
+       DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n",
+               dfb->fb.width, dfb->fb.height, dfb->fb.bits_per_pixel,
+               (unsigned long long)obj->phys_addr);
 
        return 0;
 
@@ -177,6 +177,16 @@ int armada_fbdev_init(struct drm_device *dev)
        return ret;
 }
 
+void armada_fbdev_lastclose(struct drm_device *dev)
+{
+       struct armada_private *priv = dev->dev_private;
+
+       drm_modeset_lock_all(dev);
+       if (priv->fbdev)
+               drm_fb_helper_restore_fbdev_mode(priv->fbdev);
+       drm_modeset_unlock_all(dev);
+}
+
 void armada_fbdev_fini(struct drm_device *dev)
 {
        struct armada_private *priv = dev->dev_private;
@@ -192,11 +202,11 @@ void armada_fbdev_fini(struct drm_device *dev)
                        framebuffer_release(info);
                }
 
+               drm_fb_helper_fini(fbh);
+
                if (fbh->fb)
                        fbh->fb->funcs->destroy(fbh->fb);
 
-               drm_fb_helper_fini(fbh);
-
                priv->fbdev = NULL;
        }
 }
index 9f2356bae7fdafb5318b172d47535b6b32408e07..887816f43476937fcfbceed5207025b63eccb132 100644 (file)
@@ -172,8 +172,9 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj)
                obj->dev_addr = obj->linear->start;
        }
 
-       DRM_DEBUG_DRIVER("obj %p phys %#x dev %#x\n",
-                        obj, obj->phys_addr, obj->dev_addr);
+       DRM_DEBUG_DRIVER("obj %p phys %#llx dev %#llx\n", obj,
+                        (unsigned long long)obj->phys_addr,
+                        (unsigned long long)obj->dev_addr);
 
        return 0;
 }
@@ -557,7 +558,6 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
                         * refcount on the gem object itself.
                         */
                        drm_gem_object_reference(obj);
-                       dma_buf_put(buf);
                        return obj;
                }
        }
@@ -573,6 +573,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
        }
 
        dobj->obj.import_attach = attach;
+       get_dma_buf(buf);
 
        /*
         * Don't call dma_buf_map_attachment() here - it maps the
index 7b33e14e44aa17a8026d4c1c33b8e2dbc529f93f..3f65dd6676b2c1354a4faef7d723f171ad840c67 100644 (file)
@@ -65,7 +65,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
         * then the BO is being moved and we should
         * store up the damage until later.
         */
-       if (!in_interrupt())
+       if (!drm_can_sleep())
                ret = ast_bo_reserve(bo, true);
        if (ret) {
                if (ret != -EBUSY)
index af0b868a9dfd6c5b3849f147f01fbf2cc29c4471..50535fd5a88d258492b90ca9e9e9cebfaf2de563 100644 (file)
@@ -189,53 +189,6 @@ static int ast_get_dram_info(struct drm_device *dev)
        return 0;
 }
 
-uint32_t ast_get_max_dclk(struct drm_device *dev, int bpp)
-{
-       struct ast_private *ast = dev->dev_private;
-       uint32_t dclk, jreg;
-       uint32_t dram_bus_width, mclk, dram_bandwidth, actual_dram_bandwidth, dram_efficency = 500;
-
-       dram_bus_width = ast->dram_bus_width;
-       mclk = ast->mclk;
-
-       if (ast->chip == AST2100 ||
-           ast->chip == AST1100 ||
-           ast->chip == AST2200 ||
-           ast->chip == AST2150 ||
-           ast->dram_bus_width == 16)
-               dram_efficency = 600;
-       else if (ast->chip == AST2300)
-               dram_efficency = 400;
-
-       dram_bandwidth = mclk * dram_bus_width * 2 / 8;
-       actual_dram_bandwidth = dram_bandwidth * dram_efficency / 1000;
-
-       if (ast->chip == AST1180)
-               dclk = actual_dram_bandwidth / ((bpp + 1) / 8);
-       else {
-               jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
-               if ((jreg & 0x08) && (ast->chip == AST2000))
-                       dclk = actual_dram_bandwidth / ((bpp + 1 + 16) / 8);
-               else if ((jreg & 0x08) && (bpp == 8))
-                       dclk = actual_dram_bandwidth / ((bpp + 1 + 24) / 8);
-               else
-                       dclk = actual_dram_bandwidth / ((bpp + 1) / 8);
-       }
-
-       if (ast->chip == AST2100 ||
-           ast->chip == AST2200 ||
-           ast->chip == AST2300 ||
-           ast->chip == AST1180) {
-               if (dclk > 200)
-                       dclk = 200;
-       } else {
-               if (dclk > 165)
-                       dclk = 165;
-       }
-
-       return dclk;
-}
-
 static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
        struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb);
@@ -449,7 +402,7 @@ int ast_dumb_create(struct drm_file *file,
        return 0;
 }
 
-void ast_bo_unref(struct ast_bo **bo)
+static void ast_bo_unref(struct ast_bo **bo)
 {
        struct ttm_buffer_object *tbo;
 
index 7fc9f7272b56e7e9ebe846b650e9e2f18f28cc5f..cca063b110831aa4d4fc2f46afd6e9cc35ac30b9 100644 (file)
@@ -404,7 +404,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
        }
 }
 
-void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,
+static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,
                      struct ast_vbios_mode_info *vbios_mode)
 {
        struct ast_private *ast = dev->dev_private;
@@ -415,7 +415,7 @@ void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,
        ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
 }
 
-bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
+static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
                     struct ast_vbios_mode_info *vbios_mode)
 {
        switch (crtc->fb->bits_per_pixel) {
@@ -427,7 +427,7 @@ bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
        return true;
 }
 
-void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset)
+static void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset)
 {
        struct ast_private *ast = crtc->dev->dev_private;
        u32 addr;
@@ -623,7 +623,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = {
        .destroy = ast_crtc_destroy,
 };
 
-int ast_crtc_init(struct drm_device *dev)
+static int ast_crtc_init(struct drm_device *dev)
 {
        struct ast_crtc *crtc;
        int i;
@@ -710,7 +710,7 @@ static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = {
        .mode_set = ast_encoder_mode_set,
 };
 
-int ast_encoder_init(struct drm_device *dev)
+static int ast_encoder_init(struct drm_device *dev)
 {
        struct ast_encoder *ast_encoder;
 
@@ -777,7 +777,7 @@ static const struct drm_connector_funcs ast_connector_funcs = {
        .destroy = ast_connector_destroy,
 };
 
-int ast_connector_init(struct drm_device *dev)
+static int ast_connector_init(struct drm_device *dev)
 {
        struct ast_connector *ast_connector;
        struct drm_connector *connector;
@@ -810,7 +810,7 @@ int ast_connector_init(struct drm_device *dev)
 }
 
 /* allocate cursor cache and pin at start of VRAM */
-int ast_cursor_init(struct drm_device *dev)
+static int ast_cursor_init(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
        int size;
@@ -847,7 +847,7 @@ fail:
        return ret;
 }
 
-void ast_cursor_fini(struct drm_device *dev)
+static void ast_cursor_fini(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
        ttm_bo_kunmap(&ast->cache_kmap);
@@ -965,7 +965,7 @@ static void ast_i2c_destroy(struct ast_i2c_chan *i2c)
        kfree(i2c);
 }
 
-void ast_show_cursor(struct drm_crtc *crtc)
+static void ast_show_cursor(struct drm_crtc *crtc)
 {
        struct ast_private *ast = crtc->dev->dev_private;
        u8 jreg;
@@ -976,7 +976,7 @@ void ast_show_cursor(struct drm_crtc *crtc)
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);
 }
 
-void ast_hide_cursor(struct drm_crtc *crtc)
+static void ast_hide_cursor(struct drm_crtc *crtc)
 {
        struct ast_private *ast = crtc->dev->dev_private;
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00);
index 32aecb34dbced78308a393833e177fd46a1e5c9b..4ea9b17ac17a9c5459617898718f1145eaf232ba 100644 (file)
@@ -80,7 +80,7 @@ static int ast_ttm_global_init(struct ast_private *ast)
        return 0;
 }
 
-void
+static void
 ast_ttm_global_release(struct ast_private *ast)
 {
        if (ast->ttm.mem_global_ref.release == NULL)
@@ -102,7 +102,7 @@ static void ast_bo_ttm_destroy(struct ttm_buffer_object *tbo)
        kfree(bo);
 }
 
-bool ast_ttm_bo_is_ast_bo(struct ttm_buffer_object *bo)
+static bool ast_ttm_bo_is_ast_bo(struct ttm_buffer_object *bo)
 {
        if (bo->destroy == &ast_bo_ttm_destroy)
                return true;
@@ -208,7 +208,7 @@ static struct ttm_backend_func ast_tt_backend_func = {
 };
 
 
-struct ttm_tt *ast_ttm_tt_create(struct ttm_bo_device *bdev,
+static struct ttm_tt *ast_ttm_tt_create(struct ttm_bo_device *bdev,
                                 unsigned long size, uint32_t page_flags,
                                 struct page *dummy_read_page)
 {
diff --git a/drivers/gpu/drm/bochs/Kconfig b/drivers/gpu/drm/bochs/Kconfig
new file mode 100644 (file)
index 0000000..c8fcf12
--- /dev/null
@@ -0,0 +1,11 @@
+config DRM_BOCHS
+       tristate "DRM Support for bochs dispi vga interface (qemu stdvga)"
+       depends on DRM && PCI
+       select DRM_KMS_HELPER
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select DRM_TTM
+       help
+         Choose this option for qemu.
+         If M is selected the module will be called bochs-drm.
diff --git a/drivers/gpu/drm/bochs/Makefile b/drivers/gpu/drm/bochs/Makefile
new file mode 100644 (file)
index 0000000..844a556
--- /dev/null
@@ -0,0 +1,4 @@
+ccflags-y := -Iinclude/drm
+bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_fbdev.o bochs_hw.o
+
+obj-$(CONFIG_DRM_BOCHS)        += bochs-drm.o
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
new file mode 100644 (file)
index 0000000..741965c
--- /dev/null
@@ -0,0 +1,164 @@
+#include <linux/io.h>
+#include <linux/fb.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_page_alloc.h>
+
+/* ---------------------------------------------------------------------- */
+
+#define VBE_DISPI_IOPORT_INDEX           0x01CE
+#define VBE_DISPI_IOPORT_DATA            0x01CF
+
+#define VBE_DISPI_INDEX_ID               0x0
+#define VBE_DISPI_INDEX_XRES             0x1
+#define VBE_DISPI_INDEX_YRES             0x2
+#define VBE_DISPI_INDEX_BPP              0x3
+#define VBE_DISPI_INDEX_ENABLE           0x4
+#define VBE_DISPI_INDEX_BANK             0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH       0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT      0x7
+#define VBE_DISPI_INDEX_X_OFFSET         0x8
+#define VBE_DISPI_INDEX_Y_OFFSET         0x9
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
+
+#define VBE_DISPI_ID0                    0xB0C0
+#define VBE_DISPI_ID1                    0xB0C1
+#define VBE_DISPI_ID2                    0xB0C2
+#define VBE_DISPI_ID3                    0xB0C3
+#define VBE_DISPI_ID4                    0xB0C4
+#define VBE_DISPI_ID5                    0xB0C5
+
+#define VBE_DISPI_DISABLED               0x00
+#define VBE_DISPI_ENABLED                0x01
+#define VBE_DISPI_GETCAPS                0x02
+#define VBE_DISPI_8BIT_DAC               0x20
+#define VBE_DISPI_LFB_ENABLED            0x40
+#define VBE_DISPI_NOCLEARMEM             0x80
+
+/* ---------------------------------------------------------------------- */
+
+enum bochs_types {
+       BOCHS_QEMU_STDVGA,
+       BOCHS_UNKNOWN,
+};
+
+struct bochs_framebuffer {
+       struct drm_framebuffer base;
+       struct drm_gem_object *obj;
+};
+
+struct bochs_device {
+       /* hw */
+       void __iomem   *mmio;
+       int            ioports;
+       void __iomem   *fb_map;
+       unsigned long  fb_base;
+       unsigned long  fb_size;
+
+       /* mode */
+       u16 xres;
+       u16 yres;
+       u16 yres_virtual;
+       u32 stride;
+       u32 bpp;
+
+       /* drm */
+       struct drm_device  *dev;
+       struct drm_crtc crtc;
+       struct drm_encoder encoder;
+       struct drm_connector connector;
+       bool mode_config_initialized;
+
+       /* ttm */
+       struct {
+               struct drm_global_reference mem_global_ref;
+               struct ttm_bo_global_ref bo_global_ref;
+               struct ttm_bo_device bdev;
+               bool initialized;
+       } ttm;
+
+       /* fbdev */
+       struct {
+               struct bochs_framebuffer gfb;
+               struct drm_fb_helper helper;
+               int size;
+               int x1, y1, x2, y2; /* dirty rect */
+               spinlock_t dirty_lock;
+               bool initialized;
+       } fb;
+};
+
+#define to_bochs_framebuffer(x) container_of(x, struct bochs_framebuffer, base)
+
+struct bochs_bo {
+       struct ttm_buffer_object bo;
+       struct ttm_placement placement;
+       struct ttm_bo_kmap_obj kmap;
+       struct drm_gem_object gem;
+       u32 placements[3];
+       int pin_count;
+};
+
+static inline struct bochs_bo *bochs_bo(struct ttm_buffer_object *bo)
+{
+       return container_of(bo, struct bochs_bo, bo);
+}
+
+static inline struct bochs_bo *gem_to_bochs_bo(struct drm_gem_object *gem)
+{
+       return container_of(gem, struct bochs_bo, gem);
+}
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo)
+{
+       return drm_vma_node_offset_addr(&bo->bo.vma_node);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* bochs_hw.c */
+int bochs_hw_init(struct drm_device *dev, uint32_t flags);
+void bochs_hw_fini(struct drm_device *dev);
+
+void bochs_hw_setmode(struct bochs_device *bochs,
+                     struct drm_display_mode *mode);
+void bochs_hw_setbase(struct bochs_device *bochs,
+                     int x, int y, u64 addr);
+
+/* bochs_mm.c */
+int bochs_mm_init(struct bochs_device *bochs);
+void bochs_mm_fini(struct bochs_device *bochs);
+int bochs_mmap(struct file *filp, struct vm_area_struct *vma);
+
+int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+                    struct drm_gem_object **obj);
+int bochs_gem_init_object(struct drm_gem_object *obj);
+void bochs_gem_free_object(struct drm_gem_object *obj);
+int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
+                     struct drm_mode_create_dumb *args);
+int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+                          uint32_t handle, uint64_t *offset);
+
+int bochs_framebuffer_init(struct drm_device *dev,
+                          struct bochs_framebuffer *gfb,
+                          struct drm_mode_fb_cmd2 *mode_cmd,
+                          struct drm_gem_object *obj);
+int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr);
+int bochs_bo_unpin(struct bochs_bo *bo);
+
+extern const struct drm_mode_config_funcs bochs_mode_funcs;
+
+/* bochs_kms.c */
+int bochs_kms_init(struct bochs_device *bochs);
+void bochs_kms_fini(struct bochs_device *bochs);
+
+/* bochs_fbdev.c */
+int bochs_fbdev_init(struct bochs_device *bochs);
+void bochs_fbdev_fini(struct bochs_device *bochs);
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
new file mode 100644 (file)
index 0000000..395bba2
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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/mm.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "bochs.h"
+
+static bool enable_fbdev = true;
+module_param_named(fbdev, enable_fbdev, bool, 0444);
+MODULE_PARM_DESC(fbdev, "register fbdev device");
+
+/* ---------------------------------------------------------------------- */
+/* drm interface                                                          */
+
+static int bochs_unload(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+
+       bochs_fbdev_fini(bochs);
+       bochs_kms_fini(bochs);
+       bochs_mm_fini(bochs);
+       bochs_hw_fini(dev);
+       kfree(bochs);
+       dev->dev_private = NULL;
+       return 0;
+}
+
+static int bochs_load(struct drm_device *dev, unsigned long flags)
+{
+       struct bochs_device *bochs;
+       int ret;
+
+       bochs = kzalloc(sizeof(*bochs), GFP_KERNEL);
+       if (bochs == NULL)
+               return -ENOMEM;
+       dev->dev_private = bochs;
+       bochs->dev = dev;
+
+       ret = bochs_hw_init(dev, flags);
+       if (ret)
+               goto err;
+
+       ret = bochs_mm_init(bochs);
+       if (ret)
+               goto err;
+
+       ret = bochs_kms_init(bochs);
+       if (ret)
+               goto err;
+
+       if (enable_fbdev)
+               bochs_fbdev_init(bochs);
+
+       return 0;
+
+err:
+       bochs_unload(dev);
+       return ret;
+}
+
+static const struct file_operations bochs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = drm_open,
+       .release        = drm_release,
+       .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = drm_compat_ioctl,
+#endif
+       .poll           = drm_poll,
+       .read           = drm_read,
+       .llseek         = no_llseek,
+       .mmap           = bochs_mmap,
+};
+
+static struct drm_driver bochs_driver = {
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET,
+       .load                   = bochs_load,
+       .unload                 = bochs_unload,
+       .fops                   = &bochs_fops,
+       .name                   = "bochs-drm",
+       .desc                   = "bochs dispi vga interface (qemu stdvga)",
+       .date                   = "20130925",
+       .major                  = 1,
+       .minor                  = 0,
+       .gem_free_object        = bochs_gem_free_object,
+       .dumb_create            = bochs_dumb_create,
+       .dumb_map_offset        = bochs_dumb_mmap_offset,
+       .dumb_destroy           = drm_gem_dumb_destroy,
+};
+
+/* ---------------------------------------------------------------------- */
+/* pci interface                                                          */
+
+static int bochs_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+       struct apertures_struct *ap;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return -ENOMEM;
+
+       ap->ranges[0].base = pci_resource_start(pdev, 0);
+       ap->ranges[0].size = pci_resource_len(pdev, 0);
+       remove_conflicting_framebuffers(ap, "bochsdrmfb", false);
+       kfree(ap);
+
+       return 0;
+}
+
+static int bochs_pci_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
+{
+       int ret;
+
+       ret = bochs_kick_out_firmware_fb(pdev);
+       if (ret)
+               return ret;
+
+       return drm_get_pci_dev(pdev, ent, &bochs_driver);
+}
+
+static void bochs_pci_remove(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+
+       drm_put_dev(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(bochs_pci_tbl) = {
+       {
+               .vendor      = 0x1234,
+               .device      = 0x1111,
+               .subvendor   = 0x1af4,
+               .subdevice   = 0x1100,
+               .driver_data = BOCHS_QEMU_STDVGA,
+       },
+       {
+               .vendor      = 0x1234,
+               .device      = 0x1111,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = BOCHS_UNKNOWN,
+       },
+       { /* end of list */ }
+};
+
+static struct pci_driver bochs_pci_driver = {
+       .name =         "bochs-drm",
+       .id_table =     bochs_pci_tbl,
+       .probe =        bochs_pci_probe,
+       .remove =       bochs_pci_remove,
+};
+
+/* ---------------------------------------------------------------------- */
+/* module init/exit                                                       */
+
+static int __init bochs_init(void)
+{
+       return drm_pci_init(&bochs_driver, &bochs_pci_driver);
+}
+
+static void __exit bochs_exit(void)
+{
+       drm_pci_exit(&bochs_driver, &bochs_pci_driver);
+}
+
+module_init(bochs_init);
+module_exit(bochs_exit);
+
+MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
+MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
new file mode 100644 (file)
index 0000000..4da5206
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * 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 "bochs.h"
+
+/* ---------------------------------------------------------------------- */
+
+static struct fb_ops bochsfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var = drm_fb_helper_check_var,
+       .fb_set_par = drm_fb_helper_set_par,
+       .fb_fillrect = sys_fillrect,
+       .fb_copyarea = sys_copyarea,
+       .fb_imageblit = sys_imageblit,
+       .fb_pan_display = drm_fb_helper_pan_display,
+       .fb_blank = drm_fb_helper_blank,
+       .fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int bochsfb_create_object(struct bochs_device *bochs,
+                                struct drm_mode_fb_cmd2 *mode_cmd,
+                                struct drm_gem_object **gobj_p)
+{
+       struct drm_device *dev = bochs->dev;
+       struct drm_gem_object *gobj;
+       u32 size;
+       int ret = 0;
+
+       size = mode_cmd->pitches[0] * mode_cmd->height;
+       ret = bochs_gem_create(dev, size, true, &gobj);
+       if (ret)
+               return ret;
+
+       *gobj_p = gobj;
+       return ret;
+}
+
+static int bochsfb_create(struct drm_fb_helper *helper,
+                         struct drm_fb_helper_surface_size *sizes)
+{
+       struct bochs_device *bochs =
+               container_of(helper, struct bochs_device, fb.helper);
+       struct drm_device *dev = bochs->dev;
+       struct fb_info *info;
+       struct drm_framebuffer *fb;
+       struct drm_mode_fb_cmd2 mode_cmd;
+       struct device *device = &dev->pdev->dev;
+       struct drm_gem_object *gobj = NULL;
+       struct bochs_bo *bo = NULL;
+       int size, ret;
+
+       if (sizes->surface_bpp != 32)
+               return -EINVAL;
+
+       mode_cmd.width = sizes->surface_width;
+       mode_cmd.height = sizes->surface_height;
+       mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
+       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+                                                         sizes->surface_depth);
+       size = mode_cmd.pitches[0] * mode_cmd.height;
+
+       /* alloc, pin & map bo */
+       ret = bochsfb_create_object(bochs, &mode_cmd, &gobj);
+       if (ret) {
+               DRM_ERROR("failed to create fbcon backing object %d\n", ret);
+               return ret;
+       }
+
+       bo = gem_to_bochs_bo(gobj);
+
+       ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+       if (ret)
+               return ret;
+
+       ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+       if (ret) {
+               DRM_ERROR("failed to pin fbcon\n");
+               ttm_bo_unreserve(&bo->bo);
+               return ret;
+       }
+
+       ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages,
+                         &bo->kmap);
+       if (ret) {
+               DRM_ERROR("failed to kmap fbcon\n");
+               ttm_bo_unreserve(&bo->bo);
+               return ret;
+       }
+
+       ttm_bo_unreserve(&bo->bo);
+
+       /* init fb device */
+       info = framebuffer_alloc(0, device);
+       if (info == NULL)
+               return -ENOMEM;
+
+       info->par = &bochs->fb.helper;
+
+       ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj);
+       if (ret)
+               return ret;
+
+       bochs->fb.size = size;
+
+       /* setup helper */
+       fb = &bochs->fb.gfb.base;
+       bochs->fb.helper.fb = fb;
+       bochs->fb.helper.fbdev = info;
+
+       strcpy(info->fix.id, "bochsdrmfb");
+
+       info->flags = FBINFO_DEFAULT;
+       info->fbops = &bochsfb_ops;
+
+       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+       drm_fb_helper_fill_var(info, &bochs->fb.helper, sizes->fb_width,
+                              sizes->fb_height);
+
+       info->screen_base = bo->kmap.virtual;
+       info->screen_size = size;
+
+#if 0
+       /* FIXME: get this right for mmap(/dev/fb0) */
+       info->fix.smem_start = bochs_bo_mmap_offset(bo);
+       info->fix.smem_len = size;
+#endif
+
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret) {
+               DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int bochs_fbdev_destroy(struct bochs_device *bochs)
+{
+       struct bochs_framebuffer *gfb = &bochs->fb.gfb;
+       struct fb_info *info;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       if (bochs->fb.helper.fbdev) {
+               info = bochs->fb.helper.fbdev;
+
+               unregister_framebuffer(info);
+               if (info->cmap.len)
+                       fb_dealloc_cmap(&info->cmap);
+               framebuffer_release(info);
+       }
+
+       if (gfb->obj) {
+               drm_gem_object_unreference_unlocked(gfb->obj);
+               gfb->obj = NULL;
+       }
+
+       drm_fb_helper_fini(&bochs->fb.helper);
+       drm_framebuffer_unregister_private(&gfb->base);
+       drm_framebuffer_cleanup(&gfb->base);
+
+       return 0;
+}
+
+void bochs_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+                       u16 blue, int regno)
+{
+}
+
+void bochs_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                       u16 *blue, int regno)
+{
+       *red   = regno;
+       *green = regno;
+       *blue  = regno;
+}
+
+static struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
+       .gamma_set = bochs_fb_gamma_set,
+       .gamma_get = bochs_fb_gamma_get,
+       .fb_probe = bochsfb_create,
+};
+
+int bochs_fbdev_init(struct bochs_device *bochs)
+{
+       int ret;
+
+       bochs->fb.helper.funcs = &bochs_fb_helper_funcs;
+       spin_lock_init(&bochs->fb.dirty_lock);
+
+       ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
+                                1, 1);
+       if (ret)
+               return ret;
+
+       drm_fb_helper_single_add_all_connectors(&bochs->fb.helper);
+       drm_helper_disable_unused_functions(bochs->dev);
+       drm_fb_helper_initial_config(&bochs->fb.helper, 32);
+
+       bochs->fb.initialized = true;
+       return 0;
+}
+
+void bochs_fbdev_fini(struct bochs_device *bochs)
+{
+       if (!bochs->fb.initialized)
+               return;
+
+       bochs_fbdev_destroy(bochs);
+       bochs->fb.initialized = false;
+}
diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c
new file mode 100644 (file)
index 0000000..dbe619e
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * 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 "bochs.h"
+
+/* ---------------------------------------------------------------------- */
+
+static void bochs_vga_writeb(struct bochs_device *bochs, u16 ioport, u8 val)
+{
+       if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
+               return;
+
+       if (bochs->mmio) {
+               int offset = ioport - 0x3c0 + 0x400;
+               writeb(val, bochs->mmio + offset);
+       } else {
+               outb(val, ioport);
+       }
+}
+
+static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
+{
+       u16 ret = 0;
+
+       if (bochs->mmio) {
+               int offset = 0x500 + (reg << 1);
+               ret = readw(bochs->mmio + offset);
+       } else {
+               outw(reg, VBE_DISPI_IOPORT_INDEX);
+               ret = inw(VBE_DISPI_IOPORT_DATA);
+       }
+       return ret;
+}
+
+static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
+{
+       if (bochs->mmio) {
+               int offset = 0x500 + (reg << 1);
+               writew(val, bochs->mmio + offset);
+       } else {
+               outw(reg, VBE_DISPI_IOPORT_INDEX);
+               outw(val, VBE_DISPI_IOPORT_DATA);
+       }
+}
+
+int bochs_hw_init(struct drm_device *dev, uint32_t flags)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct pci_dev *pdev = dev->pdev;
+       unsigned long addr, size, mem, ioaddr, iosize;
+       u16 id;
+
+       if (/* (ent->driver_data == BOCHS_QEMU_STDVGA) && */
+           (pdev->resource[2].flags & IORESOURCE_MEM)) {
+               /* mmio bar with vga and bochs registers present */
+               if (pci_request_region(pdev, 2, "bochs-drm") != 0) {
+                       DRM_ERROR("Cannot request mmio region\n");
+                       return -EBUSY;
+               }
+               ioaddr = pci_resource_start(pdev, 2);
+               iosize = pci_resource_len(pdev, 2);
+               bochs->mmio = ioremap(ioaddr, iosize);
+               if (bochs->mmio == NULL) {
+                       DRM_ERROR("Cannot map mmio region\n");
+                       return -ENOMEM;
+               }
+       } else {
+               ioaddr = VBE_DISPI_IOPORT_INDEX;
+               iosize = 2;
+               if (!request_region(ioaddr, iosize, "bochs-drm")) {
+                       DRM_ERROR("Cannot request ioports\n");
+                       return -EBUSY;
+               }
+               bochs->ioports = 1;
+       }
+
+       id = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID);
+       mem = bochs_dispi_read(bochs, VBE_DISPI_INDEX_VIDEO_MEMORY_64K)
+               * 64 * 1024;
+       if ((id & 0xfff0) != VBE_DISPI_ID0) {
+               DRM_ERROR("ID mismatch\n");
+               return -ENODEV;
+       }
+
+       if ((pdev->resource[0].flags & IORESOURCE_MEM) == 0)
+               return -ENODEV;
+       addr = pci_resource_start(pdev, 0);
+       size = pci_resource_len(pdev, 0);
+       if (addr == 0)
+               return -ENODEV;
+       if (size != mem) {
+               DRM_ERROR("Size mismatch: pci=%ld, bochs=%ld\n",
+                       size, mem);
+               size = min(size, mem);
+       }
+
+       if (pci_request_region(pdev, 0, "bochs-drm") != 0) {
+               DRM_ERROR("Cannot request framebuffer\n");
+               return -EBUSY;
+       }
+
+       bochs->fb_map = ioremap(addr, size);
+       if (bochs->fb_map == NULL) {
+               DRM_ERROR("Cannot map framebuffer\n");
+               return -ENOMEM;
+       }
+       bochs->fb_base = addr;
+       bochs->fb_size = size;
+
+       DRM_INFO("Found bochs VGA, ID 0x%x.\n", id);
+       DRM_INFO("Framebuffer size %ld kB @ 0x%lx, %s @ 0x%lx.\n",
+                size / 1024, addr,
+                bochs->ioports ? "ioports" : "mmio",
+                ioaddr);
+       return 0;
+}
+
+void bochs_hw_fini(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+
+       if (bochs->mmio)
+               iounmap(bochs->mmio);
+       if (bochs->ioports)
+               release_region(VBE_DISPI_IOPORT_INDEX, 2);
+       if (bochs->fb_map)
+               iounmap(bochs->fb_map);
+       pci_release_regions(dev->pdev);
+}
+
+void bochs_hw_setmode(struct bochs_device *bochs,
+                     struct drm_display_mode *mode)
+{
+       bochs->xres = mode->hdisplay;
+       bochs->yres = mode->vdisplay;
+       bochs->bpp = 32;
+       bochs->stride = mode->hdisplay * (bochs->bpp / 8);
+       bochs->yres_virtual = bochs->fb_size / bochs->stride;
+
+       DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n",
+                        bochs->xres, bochs->yres, bochs->bpp,
+                        bochs->yres_virtual);
+
+       bochs_vga_writeb(bochs, 0x3c0, 0x20); /* unblank */
+
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_BPP,         bochs->bpp);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_XRES,        bochs->xres);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_YRES,        bochs->yres);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_BANK,        0);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH,  bochs->xres);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_HEIGHT,
+                         bochs->yres_virtual);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET,    0);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET,    0);
+
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
+                         VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+}
+
+void bochs_hw_setbase(struct bochs_device *bochs,
+                     int x, int y, u64 addr)
+{
+       unsigned long offset = (unsigned long)addr +
+               y * bochs->stride +
+               x * (bochs->bpp / 8);
+       int vy = offset / bochs->stride;
+       int vx = (offset % bochs->stride) * 8 / bochs->bpp;
+
+       DRM_DEBUG_DRIVER("x %d, y %d, addr %llx -> offset %lx, vx %d, vy %d\n",
+                        x, y, addr, offset, vx, vy);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET, vx);
+       bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET, vy);
+}
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
new file mode 100644 (file)
index 0000000..62ec7d4
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * 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 "bochs.h"
+
+static int defx = 1024;
+static int defy = 768;
+
+module_param(defx, int, 0444);
+module_param(defy, int, 0444);
+MODULE_PARM_DESC(defx, "default x resolution");
+MODULE_PARM_DESC(defy, "default y resolution");
+
+/* ---------------------------------------------------------------------- */
+
+static void bochs_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+       default:
+               return;
+       }
+}
+
+static bool bochs_crtc_mode_fixup(struct drm_crtc *crtc,
+                                 const struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+                                   struct drm_framebuffer *old_fb)
+{
+       struct bochs_device *bochs =
+               container_of(crtc, struct bochs_device, crtc);
+       struct bochs_framebuffer *bochs_fb;
+       struct bochs_bo *bo;
+       u64 gpu_addr = 0;
+       int ret;
+
+       if (old_fb) {
+               bochs_fb = to_bochs_framebuffer(old_fb);
+               bo = gem_to_bochs_bo(bochs_fb->obj);
+               ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+               if (ret) {
+                       DRM_ERROR("failed to reserve old_fb bo\n");
+               } else {
+                       bochs_bo_unpin(bo);
+                       ttm_bo_unreserve(&bo->bo);
+               }
+       }
+
+       if (WARN_ON(crtc->fb == NULL))
+               return -EINVAL;
+
+       bochs_fb = to_bochs_framebuffer(crtc->fb);
+       bo = gem_to_bochs_bo(bochs_fb->obj);
+       ret = ttm_bo_reserve(&bo->bo, true, false, false, 0);
+       if (ret)
+               return ret;
+
+       ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
+       if (ret) {
+               ttm_bo_unreserve(&bo->bo);
+               return ret;
+       }
+
+       ttm_bo_unreserve(&bo->bo);
+       bochs_hw_setbase(bochs, x, y, gpu_addr);
+       return 0;
+}
+
+static int bochs_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 bochs_device *bochs =
+               container_of(crtc, struct bochs_device, crtc);
+
+       bochs_hw_setmode(bochs, mode);
+       bochs_crtc_mode_set_base(crtc, x, y, old_fb);
+       return 0;
+}
+
+static void bochs_crtc_prepare(struct drm_crtc *crtc)
+{
+}
+
+static void bochs_crtc_commit(struct drm_crtc *crtc)
+{
+}
+
+static void bochs_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
+                                u16 *blue, uint32_t start, uint32_t size)
+{
+}
+
+/* These provide the minimum set of functions required to handle a CRTC */
+static const struct drm_crtc_funcs bochs_crtc_funcs = {
+       .gamma_set = bochs_crtc_gamma_set,
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = drm_crtc_cleanup,
+};
+
+static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
+       .dpms = bochs_crtc_dpms,
+       .mode_fixup = bochs_crtc_mode_fixup,
+       .mode_set = bochs_crtc_mode_set,
+       .mode_set_base = bochs_crtc_mode_set_base,
+       .prepare = bochs_crtc_prepare,
+       .commit = bochs_crtc_commit,
+       .load_lut = bochs_crtc_load_lut,
+};
+
+static void bochs_crtc_init(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct drm_crtc *crtc = &bochs->crtc;
+
+       drm_crtc_init(dev, crtc, &bochs_crtc_funcs);
+       drm_mode_crtc_set_gamma_size(crtc, 256);
+       drm_crtc_helper_add(crtc, &bochs_helper_funcs);
+}
+
+static bool bochs_encoder_mode_fixup(struct drm_encoder *encoder,
+                                    const struct drm_display_mode *mode,
+                                    struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void bochs_encoder_mode_set(struct drm_encoder *encoder,
+                                  struct drm_display_mode *mode,
+                                  struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void bochs_encoder_dpms(struct drm_encoder *encoder, int state)
+{
+}
+
+static void bochs_encoder_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void bochs_encoder_commit(struct drm_encoder *encoder)
+{
+}
+
+static const struct drm_encoder_helper_funcs bochs_encoder_helper_funcs = {
+       .dpms = bochs_encoder_dpms,
+       .mode_fixup = bochs_encoder_mode_fixup,
+       .mode_set = bochs_encoder_mode_set,
+       .prepare = bochs_encoder_prepare,
+       .commit = bochs_encoder_commit,
+};
+
+static const struct drm_encoder_funcs bochs_encoder_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+static void bochs_encoder_init(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct drm_encoder *encoder = &bochs->encoder;
+
+       encoder->possible_crtcs = 0x1;
+       drm_encoder_init(dev, encoder, &bochs_encoder_encoder_funcs,
+                        DRM_MODE_ENCODER_DAC);
+       drm_encoder_helper_add(encoder, &bochs_encoder_helper_funcs);
+}
+
+
+int bochs_connector_get_modes(struct drm_connector *connector)
+{
+       int count;
+
+       count = drm_add_modes_noedid(connector, 8192, 8192);
+       drm_set_preferred_mode(connector, defx, defy);
+       return count;
+}
+
+static int bochs_connector_mode_valid(struct drm_connector *connector,
+                                     struct drm_display_mode *mode)
+{
+       struct bochs_device *bochs =
+               container_of(connector, struct bochs_device, connector);
+       unsigned long size = mode->hdisplay * mode->vdisplay * 4;
+
+       /*
+        * Make sure we can fit two framebuffers into video memory.
+        * This allows up to 1600x1200 with 16 MB (default size).
+        * If you want more try this:
+        *     'qemu -vga std -global VGA.vgamem_mb=32 $otherargs'
+        */
+       if (size * 2 > bochs->fb_size)
+               return MODE_BAD;
+
+       return MODE_OK;
+}
+
+static struct drm_encoder *
+bochs_connector_best_encoder(struct drm_connector *connector)
+{
+       int enc_id = connector->encoder_ids[0];
+       struct drm_mode_object *obj;
+       struct drm_encoder *encoder;
+
+       /* pick the encoder ids */
+       if (enc_id) {
+               obj = drm_mode_object_find(connector->dev, enc_id,
+                                          DRM_MODE_OBJECT_ENCODER);
+               if (!obj)
+                       return NULL;
+               encoder = obj_to_encoder(obj);
+               return encoder;
+       }
+       return NULL;
+}
+
+static enum drm_connector_status bochs_connector_detect(struct drm_connector
+                                                       *connector, bool force)
+{
+       return connector_status_connected;
+}
+
+struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
+       .get_modes = bochs_connector_get_modes,
+       .mode_valid = bochs_connector_mode_valid,
+       .best_encoder = bochs_connector_best_encoder,
+};
+
+struct drm_connector_funcs bochs_connector_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = bochs_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = drm_connector_cleanup,
+};
+
+static void bochs_connector_init(struct drm_device *dev)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct drm_connector *connector = &bochs->connector;
+
+       drm_connector_init(dev, connector, &bochs_connector_connector_funcs,
+                          DRM_MODE_CONNECTOR_VIRTUAL);
+       drm_connector_helper_add(connector,
+                                &bochs_connector_connector_helper_funcs);
+}
+
+
+int bochs_kms_init(struct bochs_device *bochs)
+{
+       drm_mode_config_init(bochs->dev);
+       bochs->mode_config_initialized = true;
+
+       bochs->dev->mode_config.max_width = 8192;
+       bochs->dev->mode_config.max_height = 8192;
+
+       bochs->dev->mode_config.fb_base = bochs->fb_base;
+       bochs->dev->mode_config.preferred_depth = 24;
+       bochs->dev->mode_config.prefer_shadow = 0;
+
+       bochs->dev->mode_config.funcs = (void *)&bochs_mode_funcs;
+
+       bochs_crtc_init(bochs->dev);
+       bochs_encoder_init(bochs->dev);
+       bochs_connector_init(bochs->dev);
+       drm_mode_connector_attach_encoder(&bochs->connector,
+                                         &bochs->encoder);
+
+       return 0;
+}
+
+void bochs_kms_fini(struct bochs_device *bochs)
+{
+       if (bochs->mode_config_initialized) {
+               drm_mode_config_cleanup(bochs->dev);
+               bochs->mode_config_initialized = false;
+       }
+}
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
new file mode 100644 (file)
index 0000000..ce68587
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * 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 "bochs.h"
+
+static void bochs_ttm_placement(struct bochs_bo *bo, int domain);
+
+/* ---------------------------------------------------------------------- */
+
+static inline struct bochs_device *bochs_bdev(struct ttm_bo_device *bd)
+{
+       return container_of(bd, struct bochs_device, ttm.bdev);
+}
+
+static int bochs_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+       return ttm_mem_global_init(ref->object);
+}
+
+static void bochs_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+       ttm_mem_global_release(ref->object);
+}
+
+static int bochs_ttm_global_init(struct bochs_device *bochs)
+{
+       struct drm_global_reference *global_ref;
+       int r;
+
+       global_ref = &bochs->ttm.mem_global_ref;
+       global_ref->global_type = DRM_GLOBAL_TTM_MEM;
+       global_ref->size = sizeof(struct ttm_mem_global);
+       global_ref->init = &bochs_ttm_mem_global_init;
+       global_ref->release = &bochs_ttm_mem_global_release;
+       r = drm_global_item_ref(global_ref);
+       if (r != 0) {
+               DRM_ERROR("Failed setting up TTM memory accounting "
+                         "subsystem.\n");
+               return r;
+       }
+
+       bochs->ttm.bo_global_ref.mem_glob =
+               bochs->ttm.mem_global_ref.object;
+       global_ref = &bochs->ttm.bo_global_ref.ref;
+       global_ref->global_type = DRM_GLOBAL_TTM_BO;
+       global_ref->size = sizeof(struct ttm_bo_global);
+       global_ref->init = &ttm_bo_global_init;
+       global_ref->release = &ttm_bo_global_release;
+       r = drm_global_item_ref(global_ref);
+       if (r != 0) {
+               DRM_ERROR("Failed setting up TTM BO subsystem.\n");
+               drm_global_item_unref(&bochs->ttm.mem_global_ref);
+               return r;
+       }
+
+       return 0;
+}
+
+static void bochs_ttm_global_release(struct bochs_device *bochs)
+{
+       if (bochs->ttm.mem_global_ref.release == NULL)
+               return;
+
+       drm_global_item_unref(&bochs->ttm.bo_global_ref.ref);
+       drm_global_item_unref(&bochs->ttm.mem_global_ref);
+       bochs->ttm.mem_global_ref.release = NULL;
+}
+
+
+static void bochs_bo_ttm_destroy(struct ttm_buffer_object *tbo)
+{
+       struct bochs_bo *bo;
+
+       bo = container_of(tbo, struct bochs_bo, bo);
+       drm_gem_object_release(&bo->gem);
+       kfree(bo);
+}
+
+static bool bochs_ttm_bo_is_bochs_bo(struct ttm_buffer_object *bo)
+{
+       if (bo->destroy == &bochs_bo_ttm_destroy)
+               return true;
+       return false;
+}
+
+static int bochs_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+                                 struct ttm_mem_type_manager *man)
+{
+       switch (type) {
+       case TTM_PL_SYSTEM:
+               man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+               man->available_caching = TTM_PL_MASK_CACHING;
+               man->default_caching = TTM_PL_FLAG_CACHED;
+               break;
+       case TTM_PL_VRAM:
+               man->func = &ttm_bo_manager_func;
+               man->flags = TTM_MEMTYPE_FLAG_FIXED |
+                       TTM_MEMTYPE_FLAG_MAPPABLE;
+               man->available_caching = TTM_PL_FLAG_UNCACHED |
+                       TTM_PL_FLAG_WC;
+               man->default_caching = TTM_PL_FLAG_WC;
+               break;
+       default:
+               DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void
+bochs_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
+{
+       struct bochs_bo *bochsbo = bochs_bo(bo);
+
+       if (!bochs_ttm_bo_is_bochs_bo(bo))
+               return;
+
+       bochs_ttm_placement(bochsbo, TTM_PL_FLAG_SYSTEM);
+       *pl = bochsbo->placement;
+}
+
+static int bochs_bo_verify_access(struct ttm_buffer_object *bo,
+                                 struct file *filp)
+{
+       struct bochs_bo *bochsbo = bochs_bo(bo);
+
+       return drm_vma_node_verify_access(&bochsbo->gem.vma_node, filp);
+}
+
+static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
+                                   struct ttm_mem_reg *mem)
+{
+       struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+       struct bochs_device *bochs = bochs_bdev(bdev);
+
+       mem->bus.addr = NULL;
+       mem->bus.offset = 0;
+       mem->bus.size = mem->num_pages << PAGE_SHIFT;
+       mem->bus.base = 0;
+       mem->bus.is_iomem = false;
+       if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+               return -EINVAL;
+       switch (mem->mem_type) {
+       case TTM_PL_SYSTEM:
+               /* system memory */
+               return 0;
+       case TTM_PL_VRAM:
+               mem->bus.offset = mem->start << PAGE_SHIFT;
+               mem->bus.base = bochs->fb_base;
+               mem->bus.is_iomem = true;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+static void bochs_ttm_io_mem_free(struct ttm_bo_device *bdev,
+                                 struct ttm_mem_reg *mem)
+{
+}
+
+static int bochs_bo_move(struct ttm_buffer_object *bo,
+                        bool evict, bool interruptible,
+                        bool no_wait_gpu,
+                        struct ttm_mem_reg *new_mem)
+{
+       return ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
+}
+
+
+static void bochs_ttm_backend_destroy(struct ttm_tt *tt)
+{
+       ttm_tt_fini(tt);
+       kfree(tt);
+}
+
+static struct ttm_backend_func bochs_tt_backend_func = {
+       .destroy = &bochs_ttm_backend_destroy,
+};
+
+static struct ttm_tt *bochs_ttm_tt_create(struct ttm_bo_device *bdev,
+                                         unsigned long size,
+                                         uint32_t page_flags,
+                                         struct page *dummy_read_page)
+{
+       struct ttm_tt *tt;
+
+       tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
+       if (tt == NULL)
+               return NULL;
+       tt->func = &bochs_tt_backend_func;
+       if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
+               kfree(tt);
+               return NULL;
+       }
+       return tt;
+}
+
+struct ttm_bo_driver bochs_bo_driver = {
+       .ttm_tt_create = bochs_ttm_tt_create,
+       .ttm_tt_populate = ttm_pool_populate,
+       .ttm_tt_unpopulate = ttm_pool_unpopulate,
+       .init_mem_type = bochs_bo_init_mem_type,
+       .evict_flags = bochs_bo_evict_flags,
+       .move = bochs_bo_move,
+       .verify_access = bochs_bo_verify_access,
+       .io_mem_reserve = &bochs_ttm_io_mem_reserve,
+       .io_mem_free = &bochs_ttm_io_mem_free,
+};
+
+int bochs_mm_init(struct bochs_device *bochs)
+{
+       struct ttm_bo_device *bdev = &bochs->ttm.bdev;
+       int ret;
+
+       ret = bochs_ttm_global_init(bochs);
+       if (ret)
+               return ret;
+
+       ret = ttm_bo_device_init(&bochs->ttm.bdev,
+                                bochs->ttm.bo_global_ref.ref.object,
+                                &bochs_bo_driver, DRM_FILE_PAGE_OFFSET,
+                                true);
+       if (ret) {
+               DRM_ERROR("Error initialising bo driver; %d\n", ret);
+               return ret;
+       }
+
+       ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
+                            bochs->fb_size >> PAGE_SHIFT);
+       if (ret) {
+               DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
+               return ret;
+       }
+
+       bochs->ttm.initialized = true;
+       return 0;
+}
+
+void bochs_mm_fini(struct bochs_device *bochs)
+{
+       if (!bochs->ttm.initialized)
+               return;
+
+       ttm_bo_device_release(&bochs->ttm.bdev);
+       bochs_ttm_global_release(bochs);
+       bochs->ttm.initialized = false;
+}
+
+static void bochs_ttm_placement(struct bochs_bo *bo, int domain)
+{
+       u32 c = 0;
+       bo->placement.fpfn = 0;
+       bo->placement.lpfn = 0;
+       bo->placement.placement = bo->placements;
+       bo->placement.busy_placement = bo->placements;
+       if (domain & TTM_PL_FLAG_VRAM) {
+               bo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED
+                       | TTM_PL_FLAG_VRAM;
+       }
+       if (domain & TTM_PL_FLAG_SYSTEM) {
+               bo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+       }
+       if (!c) {
+               bo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+       }
+       bo->placement.num_placement = c;
+       bo->placement.num_busy_placement = c;
+}
+
+static inline u64 bochs_bo_gpu_offset(struct bochs_bo *bo)
+{
+       return bo->bo.offset;
+}
+
+int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr)
+{
+       int i, ret;
+
+       if (bo->pin_count) {
+               bo->pin_count++;
+               if (gpu_addr)
+                       *gpu_addr = bochs_bo_gpu_offset(bo);
+               return 0;
+       }
+
+       bochs_ttm_placement(bo, pl_flag);
+       for (i = 0; i < bo->placement.num_placement; i++)
+               bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
+       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+       if (ret)
+               return ret;
+
+       bo->pin_count = 1;
+       if (gpu_addr)
+               *gpu_addr = bochs_bo_gpu_offset(bo);
+       return 0;
+}
+
+int bochs_bo_unpin(struct bochs_bo *bo)
+{
+       int i, ret;
+
+       if (!bo->pin_count) {
+               DRM_ERROR("unpin bad %p\n", bo);
+               return 0;
+       }
+       bo->pin_count--;
+
+       if (bo->pin_count)
+               return 0;
+
+       for (i = 0; i < bo->placement.num_placement; i++)
+               bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
+       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+int bochs_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *file_priv;
+       struct bochs_device *bochs;
+
+       if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
+               return drm_mmap(filp, vma);
+
+       file_priv = filp->private_data;
+       bochs = file_priv->minor->dev->dev_private;
+       return ttm_bo_mmap(filp, vma, &bochs->ttm.bdev);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int bochs_bo_create(struct drm_device *dev, int size, int align,
+                          uint32_t flags, struct bochs_bo **pbochsbo)
+{
+       struct bochs_device *bochs = dev->dev_private;
+       struct bochs_bo *bochsbo;
+       size_t acc_size;
+       int ret;
+
+       bochsbo = kzalloc(sizeof(struct bochs_bo), GFP_KERNEL);
+       if (!bochsbo)
+               return -ENOMEM;
+
+       ret = drm_gem_object_init(dev, &bochsbo->gem, size);
+       if (ret) {
+               kfree(bochsbo);
+               return ret;
+       }
+
+       bochsbo->bo.bdev = &bochs->ttm.bdev;
+       bochsbo->bo.bdev->dev_mapping = dev->dev_mapping;
+
+       bochs_ttm_placement(bochsbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
+
+       acc_size = ttm_bo_dma_acc_size(&bochs->ttm.bdev, size,
+                                      sizeof(struct bochs_bo));
+
+       ret = ttm_bo_init(&bochs->ttm.bdev, &bochsbo->bo, size,
+                         ttm_bo_type_device, &bochsbo->placement,
+                         align >> PAGE_SHIFT, false, NULL, acc_size,
+                         NULL, bochs_bo_ttm_destroy);
+       if (ret)
+               return ret;
+
+       *pbochsbo = bochsbo;
+       return 0;
+}
+
+int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+                    struct drm_gem_object **obj)
+{
+       struct bochs_bo *bochsbo;
+       int ret;
+
+       *obj = NULL;
+
+       size = ALIGN(size, PAGE_SIZE);
+       if (size == 0)
+               return -EINVAL;
+
+       ret = bochs_bo_create(dev, size, 0, 0, &bochsbo);
+       if (ret) {
+               if (ret != -ERESTARTSYS)
+                       DRM_ERROR("failed to allocate GEM object\n");
+               return ret;
+       }
+       *obj = &bochsbo->gem;
+       return 0;
+}
+
+int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
+                     struct drm_mode_create_dumb *args)
+{
+       struct drm_gem_object *gobj;
+       u32 handle;
+       int ret;
+
+       args->pitch = args->width * ((args->bpp + 7) / 8);
+       args->size = args->pitch * args->height;
+
+       ret = bochs_gem_create(dev, args->size, false,
+                              &gobj);
+       if (ret)
+               return ret;
+
+       ret = drm_gem_handle_create(file, gobj, &handle);
+       drm_gem_object_unreference_unlocked(gobj);
+       if (ret)
+               return ret;
+
+       args->handle = handle;
+       return 0;
+}
+
+static void bochs_bo_unref(struct bochs_bo **bo)
+{
+       struct ttm_buffer_object *tbo;
+
+       if ((*bo) == NULL)
+               return;
+
+       tbo = &((*bo)->bo);
+       ttm_bo_unref(&tbo);
+       if (tbo == NULL)
+               *bo = NULL;
+
+}
+
+void bochs_gem_free_object(struct drm_gem_object *obj)
+{
+       struct bochs_bo *bochs_bo = gem_to_bochs_bo(obj);
+
+       if (!bochs_bo)
+               return;
+       bochs_bo_unref(&bochs_bo);
+}
+
+int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+                          uint32_t handle, uint64_t *offset)
+{
+       struct drm_gem_object *obj;
+       int ret;
+       struct bochs_bo *bo;
+
+       mutex_lock(&dev->struct_mutex);
+       obj = drm_gem_object_lookup(dev, file, handle);
+       if (obj == NULL) {
+               ret = -ENOENT;
+               goto out_unlock;
+       }
+
+       bo = gem_to_bochs_bo(obj);
+       *offset = bochs_bo_mmap_offset(bo);
+
+       drm_gem_object_unreference(obj);
+       ret = 0;
+out_unlock:
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void bochs_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+       struct bochs_framebuffer *bochs_fb = to_bochs_framebuffer(fb);
+       if (bochs_fb->obj)
+               drm_gem_object_unreference_unlocked(bochs_fb->obj);
+       drm_framebuffer_cleanup(fb);
+       kfree(fb);
+}
+
+static const struct drm_framebuffer_funcs bochs_fb_funcs = {
+       .destroy = bochs_user_framebuffer_destroy,
+};
+
+int bochs_framebuffer_init(struct drm_device *dev,
+                          struct bochs_framebuffer *gfb,
+                          struct drm_mode_fb_cmd2 *mode_cmd,
+                          struct drm_gem_object *obj)
+{
+       int ret;
+
+       drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
+       gfb->obj = obj;
+       ret = drm_framebuffer_init(dev, &gfb->base, &bochs_fb_funcs);
+       if (ret) {
+               DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+static struct drm_framebuffer *
+bochs_user_framebuffer_create(struct drm_device *dev,
+                             struct drm_file *filp,
+                             struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       struct drm_gem_object *obj;
+       struct bochs_framebuffer *bochs_fb;
+       int ret;
+
+       DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n",
+              mode_cmd->width, mode_cmd->height,
+              (mode_cmd->pixel_format)       & 0xff,
+              (mode_cmd->pixel_format >> 8)  & 0xff,
+              (mode_cmd->pixel_format >> 16) & 0xff,
+              (mode_cmd->pixel_format >> 24) & 0xff);
+
+       if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888)
+               return ERR_PTR(-ENOENT);
+
+       obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
+       if (obj == NULL)
+               return ERR_PTR(-ENOENT);
+
+       bochs_fb = kzalloc(sizeof(*bochs_fb), GFP_KERNEL);
+       if (!bochs_fb) {
+               drm_gem_object_unreference_unlocked(obj);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       ret = bochs_framebuffer_init(dev, bochs_fb, mode_cmd, obj);
+       if (ret) {
+               drm_gem_object_unreference_unlocked(obj);
+               kfree(bochs_fb);
+               return ERR_PTR(ret);
+       }
+       return &bochs_fb->base;
+}
+
+const struct drm_mode_config_funcs bochs_mode_funcs = {
+       .fb_create = bochs_user_framebuffer_create,
+};
index b6aded73838bca0fb11c5a936db40a8db1e1e180..117d3eca5e3782e5db3571a968d8e92111c1da4c 100644 (file)
@@ -222,7 +222,7 @@ void cirrus_fbdev_fini(struct cirrus_device *cdev);
 void cirrus_driver_irq_preinstall(struct drm_device *dev);
 int cirrus_driver_irq_postinstall(struct drm_device *dev);
 void cirrus_driver_irq_uninstall(struct drm_device *dev);
-irqreturn_t cirrus_driver_irq_handler(DRM_IRQ_ARGS);
+irqreturn_t cirrus_driver_irq_handler(int irq, void *arg);
 
                                /* cirrus_kms.c */
 int cirrus_driver_load(struct drm_device *dev, unsigned long flags);
index b27e95666fabf6fb28d56b07cd62fd3363776a0b..2fd4a92162cb8880b3c0834ee294184b57b7edf7 100644 (file)
@@ -39,7 +39,7 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
         * then the BO is being moved and we should
         * store up the damage until later.
         */
-       if (!in_interrupt())
+       if (!drm_can_sleep())
                ret = cirrus_bo_reserve(bo, true);
        if (ret) {
                if (ret != -EBUSY)
@@ -233,6 +233,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
        info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
        info->apertures->ranges[0].size = cdev->mc.vram_size;
 
+       info->fix.smem_start = cdev->dev->mode_config.fb_base;
+       info->fix.smem_len = cdev->mc.vram_size;
+
        info->screen_base = sysram;
        info->screen_size = size;
 
index 78e76f24343d17bad9bc81e5474f900fbd090b33..4b0170cf53fd9225f07f731766cb8fe71fb40e91 100644 (file)
@@ -255,7 +255,7 @@ int cirrus_dumb_create(struct drm_file *file,
        return 0;
 }
 
-void cirrus_bo_unref(struct cirrus_bo **bo)
+static void cirrus_bo_unref(struct cirrus_bo **bo)
 {
        struct ttm_buffer_object *tbo;
 
index adabc3daaa5b4f644969944a28de07921ab1895d..530f78f84deed250a2f96350254657b49a0166c9 100644 (file)
@@ -102,7 +102,7 @@ static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc,
        return true;
 }
 
-void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
+static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
 {
        struct cirrus_device *cdev = crtc->dev->dev_private;
        u32 addr;
@@ -273,8 +273,8 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
                sr07 |= 0x11;
                break;
        case 16:
-               sr07 |= 0xc1;
-               hdr = 0xc0;
+               sr07 |= 0x17;
+               hdr = 0xc1;
                break;
        case 24:
                sr07 |= 0x15;
@@ -453,7 +453,7 @@ static void cirrus_encoder_commit(struct drm_encoder *encoder)
 {
 }
 
-void cirrus_encoder_destroy(struct drm_encoder *encoder)
+static void cirrus_encoder_destroy(struct drm_encoder *encoder)
 {
        struct cirrus_encoder *cirrus_encoder = to_cirrus_encoder(encoder);
        drm_encoder_cleanup(encoder);
@@ -492,7 +492,7 @@ static struct drm_encoder *cirrus_encoder_init(struct drm_device *dev)
 }
 
 
-int cirrus_vga_get_modes(struct drm_connector *connector)
+static int cirrus_vga_get_modes(struct drm_connector *connector)
 {
        int count;
 
@@ -509,7 +509,7 @@ static int cirrus_vga_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
+static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
                                                  *connector)
 {
        int enc_id = connector->encoder_ids[0];
index 75becdeac07d710e1322a64096df65850bf31fd4..8b37c25ff9bd0074810fc942fcee38fab3cbab4a 100644 (file)
@@ -80,7 +80,7 @@ static int cirrus_ttm_global_init(struct cirrus_device *cirrus)
        return 0;
 }
 
-void
+static void
 cirrus_ttm_global_release(struct cirrus_device *cirrus)
 {
        if (cirrus->ttm.mem_global_ref.release == NULL)
@@ -102,7 +102,7 @@ static void cirrus_bo_ttm_destroy(struct ttm_buffer_object *tbo)
        kfree(bo);
 }
 
-bool cirrus_ttm_bo_is_cirrus_bo(struct ttm_buffer_object *bo)
+static bool cirrus_ttm_bo_is_cirrus_bo(struct ttm_buffer_object *bo)
 {
        if (bo->destroy == &cirrus_bo_ttm_destroy)
                return true;
@@ -208,7 +208,7 @@ static struct ttm_backend_func cirrus_tt_backend_func = {
 };
 
 
-struct ttm_tt *cirrus_ttm_tt_create(struct ttm_bo_device *bdev,
+static struct ttm_tt *cirrus_ttm_tt_create(struct ttm_bo_device *bdev,
                                 unsigned long size, uint32_t page_flags,
                                 struct page *dummy_read_page)
 {
@@ -375,26 +375,6 @@ int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr)
        return 0;
 }
 
-int cirrus_bo_unpin(struct cirrus_bo *bo)
-{
-       int i, ret;
-       if (!bo->pin_count) {
-               DRM_ERROR("unpin bad %p\n", bo);
-               return 0;
-       }
-       bo->pin_count--;
-       if (bo->pin_count)
-               return 0;
-
-       for (i = 0; i < bo->placement.num_placement ; i++)
-               bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
-       ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
 int cirrus_bo_push_sysram(struct cirrus_bo *bo)
 {
        int i, ret;
index e301d653d97e42f4537efdb50806cdc682930505..dde205cef384c08db92d114c16138c607ddc1da0 100644 (file)
@@ -53,7 +53,7 @@
  */
 int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
 {
-       DRM_AGP_KERN *kern;
+       struct agp_kern_info *kern;
 
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
@@ -198,17 +198,15 @@ int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
 int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
 {
        struct drm_agp_mem *entry;
-       DRM_AGP_MEM *memory;
+       struct agp_memory *memory;
        unsigned long pages;
        u32 type;
 
        if (!dev->agp || !dev->agp->acquired)
                return -EINVAL;
-       if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
+       if (!(entry = kzalloc(sizeof(*entry), GFP_KERNEL)))
                return -ENOMEM;
 
-       memset(entry, 0, sizeof(*entry));
-
        pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
        type = (u32) request->type;
        if (!(memory = agp_allocate_memory(dev->agp->bridge, pages, type))) {
@@ -393,14 +391,16 @@ int drm_agp_free_ioctl(struct drm_device *dev, void *data,
  * Gets the drm_agp_t structure which is made available by the agpgart module
  * via the inter_module_* functions. Creates and initializes a drm_agp_head
  * structure.
+ *
+ * Note that final cleanup of the kmalloced structure is directly done in
+ * drm_pci_agp_destroy.
  */
 struct drm_agp_head *drm_agp_init(struct drm_device *dev)
 {
        struct drm_agp_head *head = NULL;
 
-       if (!(head = kmalloc(sizeof(*head), GFP_KERNEL)))
+       if (!(head = kzalloc(sizeof(*head), GFP_KERNEL)))
                return NULL;
-       memset((void *)head, 0, sizeof(*head));
        head->bridge = agp_find_bridge(dev->pdev);
        if (!head->bridge) {
                if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
@@ -439,7 +439,7 @@ void drm_agp_clear(struct drm_device *dev)
 {
        struct drm_agp_mem *entry, *tempe;
 
-       if (!drm_core_has_AGP(dev) || !dev->agp)
+       if (!dev->agp)
                return;
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return;
@@ -459,21 +459,6 @@ void drm_agp_clear(struct drm_device *dev)
        dev->agp->enabled = 0;
 }
 
-/**
- * drm_agp_destroy - Destroy AGP head
- * @dev: DRM device
- *
- * Destroy resources that were previously allocated via drm_agp_initp. Caller
- * must ensure to clean up all AGP resources before calling this. See
- * drm_agp_clear().
- *
- * Call this to destroy AGP heads allocated via drm_agp_init().
- */
-void drm_agp_destroy(struct drm_agp_head *agp)
-{
-       kfree(agp);
-}
-
 /**
  * Binds a collection of pages into AGP memory at the given offset, returning
  * the AGP memory structure containing them.
@@ -481,14 +466,14 @@ void drm_agp_destroy(struct drm_agp_head *agp)
  * No reference is held on the pages during this time -- it is up to the
  * caller to handle that.
  */
-DRM_AGP_MEM *
+struct agp_memory *
 drm_agp_bind_pages(struct drm_device *dev,
                   struct page **pages,
                   unsigned long num_pages,
                   uint32_t gtt_offset,
                   u32 type)
 {
-       DRM_AGP_MEM *mem;
+       struct agp_memory *mem;
        int ret, i;
 
        DRM_DEBUG("\n");
index 39a718340319ea13ce3f813ea30b82d60c0b9264..0406110f83edd2ac3f607fe575c8e7b6c491e88a 100644 (file)
@@ -114,7 +114,7 @@ int drm_buffer_copy_from_user(struct drm_buffer *buf,
 
        for (idx = 0; idx < nr_pages; ++idx) {
 
-               if (DRM_COPY_FROM_USER(buf->data[idx],
+               if (copy_from_user(buf->data[idx],
                        user_data + idx * PAGE_SIZE,
                        min(PAGE_SIZE, size - idx * PAGE_SIZE))) {
                        DRM_ERROR("Failed to copy user data (%p) to drm buffer"
index 471e051d295e383b61ebb2a2a19c0e0d67d8827a..edec31fe3fed865aa2669e7c8e17aec912a82058 100644 (file)
@@ -261,7 +261,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
                struct drm_agp_mem *entry;
                int valid = 0;
 
-               if (!drm_core_has_AGP(dev)) {
+               if (!dev->agp) {
                        kfree(map);
                        return -EINVAL;
                }
@@ -303,9 +303,6 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
 
                break;
        }
-       case _DRM_GEM:
-               DRM_ERROR("tried to addmap GEM object\n");
-               break;
        case _DRM_SCATTER_GATHER:
                if (!dev->sg) {
                        kfree(map);
@@ -483,9 +480,6 @@ int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
                dmah.size = map->size;
                __drm_pci_free(dev, &dmah);
                break;
-       case _DRM_GEM:
-               DRM_ERROR("tried to rmmap GEM object\n");
-               break;
        }
        kfree(map);
 
@@ -1396,7 +1390,7 @@ int drm_mapbufs(struct drm_device *dev, void *data,
        spin_unlock(&dev->count_lock);
 
        if (request->count >= dma->buf_count) {
-               if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
+               if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP))
                    || (drm_core_check_feature(dev, DRIVER_SG)
                        && (dma->flags & _DRM_DMA_USE_SG))) {
                        struct drm_local_map *map = dev->agp_buffer_map;
index 452bcbd0eab97dd7801a172a8969119e26ae47b5..3b7d32da16046ffcdc238ba41b1b03a3ec152435 100644 (file)
@@ -2790,10 +2790,8 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        }
 
        if (fb->funcs->dirty) {
-               drm_modeset_lock_all(dev);
                ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
                                       clips, num_clips);
-               drm_modeset_unlock_all(dev);
        } else {
                ret = -ENOSYS;
        }
index 48c90cbceb06102ebb120f004d5811bfa0126052..ea92b827e787e3543a745b119822085618c16988 100644 (file)
@@ -507,7 +507,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
         * are later needed by vblank and swap-completion
         * timestamping. They are derived from true hwmode.
         */
-       drm_calc_timestamping_constants(crtc);
+       drm_calc_timestamping_constants(crtc, &crtc->hwmode);
 
        /* FIXME: add subpixel order */
 done:
index d9137e49c4e81594a992297a1dd10181006faf06..345be03c23db27203d4ce69bd74586a77e8f6ab1 100644 (file)
@@ -315,9 +315,6 @@ long drm_ioctl(struct file *filp,
        if (drm_device_is_unplugged(dev))
                return -ENODEV;
 
-       atomic_inc(&dev->ioctl_count);
-       ++file_priv->ioctl_count;
-
        if ((nr >= DRM_CORE_IOCTL_COUNT) &&
            ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
                goto err_i1;
@@ -410,7 +407,6 @@ long drm_ioctl(struct file *filp,
 
        if (kdata != stack_kdata)
                kfree(kdata);
-       atomic_dec(&dev->ioctl_count);
        if (retcode)
                DRM_DEBUG("ret = %d\n", retcode);
        return retcode;
index 0a1e4a5f4234dce320788330e97e8888016338ba..b924306b84775f39592887a632f76553297c5a57 100644 (file)
@@ -68,6 +68,8 @@
 #define EDID_QUIRK_DETAILED_SYNC_PP            (1 << 6)
 /* Force reduced-blanking timings for detailed modes */
 #define EDID_QUIRK_FORCE_REDUCED_BLANKING      (1 << 7)
+/* Force 8bpc */
+#define EDID_QUIRK_FORCE_8BPC                  (1 << 8)
 
 struct detailed_mode_closure {
        struct drm_connector *connector;
@@ -128,6 +130,9 @@ static struct edid_quirk {
 
        /* Medion MD 30217 PG */
        { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 },
+
+       /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
+       { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC },
 };
 
 /*
@@ -600,347 +605,347 @@ static const struct drm_display_mode edid_cea_modes[] = {
        { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
                   752, 800, 0, 480, 490, 492, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 2 - 720x480@60Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 3 - 720x480@60Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 4 - 1280x720@60Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
                   1430, 1650, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 5 - 1920x1080i@60Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 6 - 1440x480i@60Hz */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 7 - 1440x480i@60Hz */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 8 - 1440x240@60Hz */
        { DRM_MODE("1440x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
                   1602, 1716, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 9 - 1440x240@60Hz */
        { DRM_MODE("1440x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
                   1602, 1716, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 10 - 2880x480i@60Hz */
        { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 11 - 2880x480i@60Hz */
        { DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 12 - 2880x240@60Hz */
        { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 13 - 2880x240@60Hz */
        { DRM_MODE("2880x240", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
                   3204, 3432, 0, 240, 244, 247, 262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 14 - 1440x480@60Hz */
        { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472,
                   1596, 1716, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 15 - 1440x480@60Hz */
        { DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1472,
                   1596, 1716, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 16 - 1920x1080@60Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 17 - 720x576@50Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 18 - 720x576@50Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 19 - 1280x720@50Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
                   1760, 1980, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 20 - 1920x1080i@50Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 21 - 1440x576i@50Hz */
        { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 22 - 1440x576i@50Hz */
        { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 23 - 1440x288@50Hz */
        { DRM_MODE("1440x288", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
                   1590, 1728, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 24 - 1440x288@50Hz */
        { DRM_MODE("1440x288", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
                   1590, 1728, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 25 - 2880x576i@50Hz */
        { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 26 - 2880x576i@50Hz */
        { DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 27 - 2880x288@50Hz */
        { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 28 - 2880x288@50Hz */
        { DRM_MODE("2880x288", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
                   3180, 3456, 0, 288, 290, 293, 312, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 29 - 1440x576@50Hz */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1592, 1728, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 30 - 1440x576@50Hz */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1592, 1728, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 31 - 1920x1080@50Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 32 - 1920x1080@24Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
                   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 24, },
+         .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 33 - 1920x1080@25Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 25, },
+         .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 34 - 1920x1080@30Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 30, },
+         .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 35 - 2880x480@60Hz */
        { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944,
                   3192, 3432, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 36 - 2880x480@60Hz */
        { DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2944,
                   3192, 3432, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 60, },
+         .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 37 - 2880x576@50Hz */
        { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928,
                   3184, 3456, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 38 - 2880x576@50Hz */
        { DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 108000, 2880, 2928,
                   3184, 3456, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 39 - 1920x1080i@50Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952,
                   2120, 2304, 0, 1080, 1126, 1136, 1250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 50, },
+         .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 40 - 1920x1080i@100Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 41 - 1280x720@100Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
                   1760, 1980, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 42 - 720x576@100Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 43 - 720x576@100Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 44 - 1440x576i@100Hz */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 45 - 1440x576i@100Hz */
        { DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 100, },
+         .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 46 - 1920x1080i@120Hz */
        { DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
                        DRM_MODE_FLAG_INTERLACE),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 47 - 1280x720@120Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
                   1430, 1650, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 48 - 720x480@120Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 49 - 720x480@120Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 50 - 1440x480i@120Hz */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 51 - 1440x480i@120Hz */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 120, },
+         .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 52 - 720x576@200Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 200, },
+         .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 53 - 720x576@200Hz */
        { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 720, 732,
                   796, 864, 0, 576, 581, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 200, },
+         .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 54 - 1440x576i@200Hz */
        { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 200, },
+         .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 55 - 1440x576i@200Hz */
        { DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
                   1590, 1728, 0, 576, 580, 586, 625, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 200, },
+         .vrefresh = 200, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 56 - 720x480@240Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 240, },
+         .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 57 - 720x480@240Hz */
        { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 720, 736,
                   798, 858, 0, 480, 489, 495, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-         .vrefresh = 240, },
+         .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 58 - 1440x480i@240 */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 240, },
+         .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
        /* 59 - 1440x480i@240 */
        { DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
                   1602, 1716, 0, 480, 488, 494, 525, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
                        DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
-         .vrefresh = 240, },
+         .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 60 - 1280x720@24Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 24, },
+         .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 61 - 1280x720@25Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700,
                   3740, 3960, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 25, },
+         .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 62 - 1280x720@30Hz */
        { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040,
                   3080, 3300, 0, 720, 725, 730, 750, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-         .vrefresh = 30, },
+         .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 63 - 1920x1080@120Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
                   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-        .vrefresh = 120, },
+        .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
        /* 64 - 1920x1080@100Hz */
        { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
                   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-        .vrefresh = 100, },
+        .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 };
 
 /*
@@ -2557,25 +2562,40 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
        return modes;
 }
 
-static int
-do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
+static struct drm_display_mode *
+drm_display_mode_from_vic_index(struct drm_connector *connector,
+                               const u8 *video_db, u8 video_len,
+                               u8 video_index)
 {
        struct drm_device *dev = connector->dev;
-       const u8 *mode;
+       struct drm_display_mode *newmode;
        u8 cea_mode;
-       int modes = 0;
 
-       for (mode = db; mode < db + len; mode++) {
-               cea_mode = (*mode & 127) - 1; /* CEA modes are numbered 1..127 */
-               if (cea_mode < ARRAY_SIZE(edid_cea_modes)) {
-                       struct drm_display_mode *newmode;
-                       newmode = drm_mode_duplicate(dev,
-                                                    &edid_cea_modes[cea_mode]);
-                       if (newmode) {
-                               newmode->vrefresh = 0;
-                               drm_mode_probed_add(connector, newmode);
-                               modes++;
-                       }
+       if (video_db == NULL || video_index >= video_len)
+               return NULL;
+
+       /* CEA modes are numbered 1..127 */
+       cea_mode = (video_db[video_index] & 127) - 1;
+       if (cea_mode >= ARRAY_SIZE(edid_cea_modes))
+               return NULL;
+
+       newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
+       newmode->vrefresh = 0;
+
+       return newmode;
+}
+
+static int
+do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
+{
+       int i, modes = 0;
+
+       for (i = 0; i < len; i++) {
+               struct drm_display_mode *mode;
+               mode = drm_display_mode_from_vic_index(connector, db, len, i);
+               if (mode) {
+                       drm_mode_probed_add(connector, mode);
+                       modes++;
                }
        }
 
@@ -2669,21 +2689,13 @@ static int add_hdmi_mode(struct drm_connector *connector, u8 vic)
 static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
                               const u8 *video_db, u8 video_len, u8 video_index)
 {
-       struct drm_device *dev = connector->dev;
        struct drm_display_mode *newmode;
        int modes = 0;
-       u8 cea_mode;
-
-       if (video_db == NULL || video_index >= video_len)
-               return 0;
-
-       /* CEA modes are numbered 1..127 */
-       cea_mode = (video_db[video_index] & 127) - 1;
-       if (cea_mode >= ARRAY_SIZE(edid_cea_modes))
-               return 0;
 
        if (structure & (1 << 0)) {
-               newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
+               newmode = drm_display_mode_from_vic_index(connector, video_db,
+                                                         video_len,
+                                                         video_index);
                if (newmode) {
                        newmode->flags |= DRM_MODE_FLAG_3D_FRAME_PACKING;
                        drm_mode_probed_add(connector, newmode);
@@ -2691,7 +2703,9 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
                }
        }
        if (structure & (1 << 6)) {
-               newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
+               newmode = drm_display_mode_from_vic_index(connector, video_db,
+                                                         video_len,
+                                                         video_index);
                if (newmode) {
                        newmode->flags |= DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
                        drm_mode_probed_add(connector, newmode);
@@ -2699,7 +2713,9 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
                }
        }
        if (structure & (1 << 8)) {
-               newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
+               newmode = drm_display_mode_from_vic_index(connector, video_db,
+                                                         video_len,
+                                                         video_index);
                if (newmode) {
                        newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
                        drm_mode_probed_add(connector, newmode);
@@ -2723,7 +2739,7 @@ static int
 do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
                   const u8 *video_db, u8 video_len)
 {
-       int modes = 0, offset = 0, i, multi_present = 0;
+       int modes = 0, offset = 0, i, multi_present = 0, multi_len;
        u8 vic_len, hdmi_3d_len = 0;
        u16 mask;
        u16 structure_all;
@@ -2769,32 +2785,84 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
        }
        offset += 1 + vic_len;
 
-       if (!(multi_present == 1 || multi_present == 2))
-               goto out;
+       if (multi_present == 1)
+               multi_len = 2;
+       else if (multi_present == 2)
+               multi_len = 4;
+       else
+               multi_len = 0;
 
-       if ((multi_present == 1 && len < (9 + offset)) ||
-           (multi_present == 2 && len < (11 + offset)))
+       if (len < (8 + offset + hdmi_3d_len - 1))
                goto out;
 
-       if ((multi_present == 1 && hdmi_3d_len < 2) ||
-           (multi_present == 2 && hdmi_3d_len < 4))
+       if (hdmi_3d_len < multi_len)
                goto out;
 
-       /* 3D_Structure_ALL */
-       structure_all = (db[8 + offset] << 8) | db[9 + offset];
+       if (multi_present == 1 || multi_present == 2) {
+               /* 3D_Structure_ALL */
+               structure_all = (db[8 + offset] << 8) | db[9 + offset];
 
-       /* check if 3D_MASK is present */
-       if (multi_present == 2)
-               mask = (db[10 + offset] << 8) | db[11 + offset];
-       else
-               mask = 0xffff;
+               /* check if 3D_MASK is present */
+               if (multi_present == 2)
+                       mask = (db[10 + offset] << 8) | db[11 + offset];
+               else
+                       mask = 0xffff;
+
+               for (i = 0; i < 16; i++) {
+                       if (mask & (1 << i))
+                               modes += add_3d_struct_modes(connector,
+                                               structure_all,
+                                               video_db,
+                                               video_len, i);
+               }
+       }
+
+       offset += multi_len;
+
+       for (i = 0; i < (hdmi_3d_len - multi_len); i++) {
+               int vic_index;
+               struct drm_display_mode *newmode = NULL;
+               unsigned int newflag = 0;
+               bool detail_present;
 
-       for (i = 0; i < 16; i++) {
-               if (mask & (1 << i))
-                       modes += add_3d_struct_modes(connector,
-                                                    structure_all,
-                                                    video_db,
-                                                    video_len, i);
+               detail_present = ((db[8 + offset + i] & 0x0f) > 7);
+
+               if (detail_present && (i + 1 == hdmi_3d_len - multi_len))
+                       break;
+
+               /* 2D_VIC_order_X */
+               vic_index = db[8 + offset + i] >> 4;
+
+               /* 3D_Structure_X */
+               switch (db[8 + offset + i] & 0x0f) {
+               case 0:
+                       newflag = DRM_MODE_FLAG_3D_FRAME_PACKING;
+                       break;
+               case 6:
+                       newflag = DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
+                       break;
+               case 8:
+                       /* 3D_Detail_X */
+                       if ((db[9 + offset + i] >> 4) == 1)
+                               newflag = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
+                       break;
+               }
+
+               if (newflag != 0) {
+                       newmode = drm_display_mode_from_vic_index(connector,
+                                                                 video_db,
+                                                                 video_len,
+                                                                 vic_index);
+
+                       if (newmode) {
+                               newmode->flags |= newflag;
+                               drm_mode_probed_add(connector, newmode);
+                               modes++;
+                       }
+               }
+
+               if (detail_present)
+                       i++;
        }
 
 out:
@@ -3435,6 +3503,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 
        drm_add_display_info(edid, &connector->display_info);
 
+       if (quirks & EDID_QUIRK_FORCE_8BPC)
+               connector->display_info.bpc = 8;
+
        return num_modes;
 }
 EXPORT_SYMBOL(drm_add_edid_modes);
index 9081172ef0573a0eb1b17ac8e3681b0c559486cc..1b4c7a5442c5de22210925c2cea8317790340b04 100644 (file)
@@ -141,7 +141,7 @@ static int edid_size(const u8 *edid, int data_size)
        return (edid[0x7e] + 1) * EDID_LENGTH;
 }
 
-static u8 *edid_load(struct drm_connector *connector, const char *name,
+static void *edid_load(struct drm_connector *connector, const char *name,
                        const char *connector_name)
 {
        const struct firmware *fw = NULL;
@@ -263,7 +263,7 @@ int drm_load_edid_firmware(struct drm_connector *connector)
        if (*last == '\n')
                *last = '\0';
 
-       edid = (struct edid *) edid_load(connector, edidname, connector_name);
+       edid = edid_load(connector, edidname, connector_name);
        if (IS_ERR_OR_NULL(edid))
                return 0;
 
index 0a19401aff803bcf2a1ff4dddcbd1fab42a0a187..98a03639b413d834d08c5c73c0ef08cec3d37c55 100644 (file)
@@ -359,6 +359,11 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
        struct drm_crtc *crtc;
        int bound = 0, crtcs_bound = 0;
 
+       /* Sometimes user space wants everything disabled, so don't steal the
+        * display if there's a master. */
+       if (dev->primary->master)
+               return false;
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (crtc->fb)
                        crtcs_bound++;
@@ -368,6 +373,7 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
 
        if (bound < crtcs_bound)
                return false;
+
        return true;
 }
 
index c5b929c3f77ae617d14fa87b387557bbf3cd3f7b..7f2af9aca03895b97c75af76968093a61930b501 100644 (file)
@@ -232,7 +232,6 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
                goto out_put_pid;
        }
 
-       priv->ioctl_count = 0;
        /* for compatibility root is always authenticated */
        priv->always_authenticated = capable(CAP_SYS_ADMIN);
        priv->authenticated = priv->always_authenticated;
@@ -392,9 +391,6 @@ static void drm_legacy_dev_reinit(struct drm_device *dev)
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return;
 
-       atomic_set(&dev->ioctl_count, 0);
-       atomic_set(&dev->vma_count, 0);
-
        dev->sigdata.lock = NULL;
 
        dev->context_flag = 0;
@@ -578,12 +574,7 @@ int drm_release(struct inode *inode, struct file *filp)
         */
 
        if (!--dev->open_count) {
-               if (atomic_read(&dev->ioctl_count)) {
-                       DRM_ERROR("Device busy: %d\n",
-                                 atomic_read(&dev->ioctl_count));
-                       retcode = -EBUSY;
-               } else
-                       retcode = drm_lastclose(dev);
+               retcode = drm_lastclose(dev);
                if (drm_device_is_unplugged(dev))
                        drm_put_dev(dev);
        }
index 4761adedad2abe5f03ae586354436f3bf1b32cbb..5bbad873c798a8e2168f50c33828f27828c378ed 100644 (file)
 int
 drm_gem_init(struct drm_device *dev)
 {
-       struct drm_gem_mm *mm;
+       struct drm_vma_offset_manager *vma_offset_manager;
 
        mutex_init(&dev->object_name_lock);
        idr_init(&dev->object_name_idr);
 
-       mm = kzalloc(sizeof(struct drm_gem_mm), GFP_KERNEL);
-       if (!mm) {
+       vma_offset_manager = kzalloc(sizeof(*vma_offset_manager), GFP_KERNEL);
+       if (!vma_offset_manager) {
                DRM_ERROR("out of memory\n");
                return -ENOMEM;
        }
 
-       dev->mm_private = mm;
-       drm_vma_offset_manager_init(&mm->vma_manager,
+       dev->vma_offset_manager = vma_offset_manager;
+       drm_vma_offset_manager_init(vma_offset_manager,
                                    DRM_FILE_PAGE_OFFSET_START,
                                    DRM_FILE_PAGE_OFFSET_SIZE);
 
@@ -113,11 +113,10 @@ drm_gem_init(struct drm_device *dev)
 void
 drm_gem_destroy(struct drm_device *dev)
 {
-       struct drm_gem_mm *mm = dev->mm_private;
 
-       drm_vma_offset_manager_destroy(&mm->vma_manager);
-       kfree(mm);
-       dev->mm_private = NULL;
+       drm_vma_offset_manager_destroy(dev->vma_offset_manager);
+       kfree(dev->vma_offset_manager);
+       dev->vma_offset_manager = NULL;
 }
 
 /**
@@ -129,11 +128,12 @@ int drm_gem_object_init(struct drm_device *dev,
 {
        struct file *filp;
 
+       drm_gem_private_object_init(dev, obj, size);
+
        filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
        if (IS_ERR(filp))
                return PTR_ERR(filp);
 
-       drm_gem_private_object_init(dev, obj, size);
        obj->filp = filp;
 
        return 0;
@@ -175,11 +175,6 @@ drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
        mutex_unlock(&filp->prime.lock);
 }
 
-static void drm_gem_object_ref_bug(struct kref *list_kref)
-{
-       BUG();
-}
-
 /**
  * Called after the last handle to the object has been closed
  *
@@ -195,13 +190,6 @@ static void drm_gem_object_handle_free(struct drm_gem_object *obj)
        if (obj->name) {
                idr_remove(&dev->object_name_idr, obj->name);
                obj->name = 0;
-               /*
-                * The object name held a reference to this object, drop
-                * that now.
-               *
-               * This cannot be the last reference, since the handle holds one too.
-                */
-               kref_put(&obj->refcount, drm_gem_object_ref_bug);
        }
 }
 
@@ -374,9 +362,8 @@ void
 drm_gem_free_mmap_offset(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
-       struct drm_gem_mm *mm = dev->mm_private;
 
-       drm_vma_offset_remove(&mm->vma_manager, &obj->vma_node);
+       drm_vma_offset_remove(dev->vma_offset_manager, &obj->vma_node);
 }
 EXPORT_SYMBOL(drm_gem_free_mmap_offset);
 
@@ -398,9 +385,8 @@ int
 drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
 {
        struct drm_device *dev = obj->dev;
-       struct drm_gem_mm *mm = dev->mm_private;
 
-       return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
+       return drm_vma_offset_add(dev->vma_offset_manager, &obj->vma_node,
                                  size / PAGE_SIZE);
 }
 EXPORT_SYMBOL(drm_gem_create_mmap_offset_size);
@@ -602,9 +588,6 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
                        goto err;
 
                obj->name = ret;
-
-               /* Allocate a reference for the name table.  */
-               drm_gem_object_reference(obj);
        }
 
        args->name = (uint64_t) obj->name;
@@ -833,7 +816,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct drm_file *priv = filp->private_data;
        struct drm_device *dev = priv->minor->dev;
-       struct drm_gem_mm *mm = dev->mm_private;
        struct drm_gem_object *obj;
        struct drm_vma_offset_node *node;
        int ret = 0;
@@ -843,7 +825,8 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 
        mutex_lock(&dev->struct_mutex);
 
-       node = drm_vma_offset_exact_lookup(&mm->vma_manager, vma->vm_pgoff,
+       node = drm_vma_offset_exact_lookup(dev->vma_offset_manager,
+                                          vma->vm_pgoff,
                                           vma_pages(vma));
        if (!node) {
                mutex_unlock(&dev->struct_mutex);
index 7d5a152eeb0288f05e5770a9699b92e253f689e4..7473035dd28b781ed8f382d0e8b6cd3743df772e 100644 (file)
@@ -186,14 +186,14 @@ int drm_clients_info(struct seq_file *m, void *data)
        struct drm_file *priv;
 
        mutex_lock(&dev->struct_mutex);
-       seq_printf(m, "a dev    pid    uid      magic     ioctls\n\n");
+       seq_printf(m, "a dev    pid    uid      magic\n\n");
        list_for_each_entry(priv, &dev->filelist, lhead) {
-               seq_printf(m, "%c %3d %5d %5d %10u %10lu\n",
+               seq_printf(m, "%c %3d %5d %5d %10u\n",
                           priv->authenticated ? 'y' : 'n',
                           priv->minor->index,
                           pid_vnr(priv->pid),
                           from_kuid_munged(seq_user_ns(m), priv->uid),
-                          priv->magic, priv->ioctl_count);
+                          priv->magic);
        }
        mutex_unlock(&dev->struct_mutex);
        return 0;
@@ -234,14 +234,18 @@ int drm_vma_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        struct drm_vma_entry *pt;
        struct vm_area_struct *vma;
+       unsigned long vma_count = 0;
 #if defined(__i386__)
        unsigned int pgprot;
 #endif
 
        mutex_lock(&dev->struct_mutex);
-       seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n",
-                  atomic_read(&dev->vma_count),
-                  high_memory, (void *)(unsigned long)virt_to_phys(high_memory));
+       list_for_each_entry(pt, &dev->vmalist, head)
+               vma_count++;
+
+       seq_printf(m, "vma use count: %lu, high_memory = %pK, 0x%pK\n",
+                  vma_count, high_memory,
+                  (void *)(unsigned long)virt_to_phys(high_memory));
 
        list_for_each_entry(pt, &dev->vmalist, head) {
                vma = pt->vma;
index 64c34d5876ffc7c8378b3df4a389db203dd1c576..c2676b5908d9f6edbcf4dd8d9fb126cfb93cd5ab 100644 (file)
@@ -368,7 +368,7 @@ int drm_irq_uninstall(struct drm_device *dev)
        if (dev->num_crtcs) {
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
                for (i = 0; i < dev->num_crtcs; i++) {
-                       DRM_WAKEUP(&dev->vblank[i].queue);
+                       wake_up(&dev->vblank[i].queue);
                        dev->vblank[i].enabled = false;
                        dev->vblank[i].last =
                                dev->driver->get_vblank_counter(dev, i);
@@ -436,45 +436,41 @@ int drm_control(struct drm_device *dev, void *data,
 }
 
 /**
- * drm_calc_timestamping_constants - Calculate and
- * store various constants which are later needed by
- * vblank and swap-completion timestamping, e.g, by
- * drm_calc_vbltimestamp_from_scanoutpos().
- * They are derived from crtc's true scanout timing,
- * so they take things like panel scaling or other
- * adjustments into account.
+ * drm_calc_timestamping_constants - Calculate vblank timestamp constants
  *
  * @crtc drm_crtc whose timestamp constants should be updated.
+ * @mode display mode containing the scanout timings
  *
+ * Calculate and store various constants which are later
+ * needed by vblank and swap-completion timestamping, e.g,
+ * by drm_calc_vbltimestamp_from_scanoutpos(). They are
+ * derived from crtc's true scanout timing, so they take
+ * things like panel scaling or other adjustments into account.
  */
-void drm_calc_timestamping_constants(struct drm_crtc *crtc)
+void drm_calc_timestamping_constants(struct drm_crtc *crtc,
+                                    const struct drm_display_mode *mode)
 {
-       s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
-       u64 dotclock;
-
-       /* Dot clock in Hz: */
-       dotclock = (u64) crtc->hwmode.clock * 1000;
-
-       /* Fields of interlaced scanout modes are only half a frame duration.
-        * Double the dotclock to get half the frame-/line-/pixelduration.
-        */
-       if (crtc->hwmode.flags & DRM_MODE_FLAG_INTERLACE)
-               dotclock *= 2;
+       int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0;
+       int dotclock = mode->crtc_clock;
 
        /* Valid dotclock? */
        if (dotclock > 0) {
-               int frame_size;
-               /* Convert scanline length in pixels and video dot clock to
-                * line duration, frame duration and pixel duration in
-                * nanoseconds:
+               int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
+
+               /*
+                * Convert scanline length in pixels and video
+                * dot clock to line duration, frame duration
+                * and pixel duration in nanoseconds:
                 */
-               pixeldur_ns = (s64) div64_u64(1000000000, dotclock);
-               linedur_ns  = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal *
-                                             1000000000), dotclock);
-               frame_size = crtc->hwmode.crtc_htotal *
-                               crtc->hwmode.crtc_vtotal;
-               framedur_ns = (s64) div64_u64((u64) frame_size * 1000000000,
-                                             dotclock);
+               pixeldur_ns = 1000000 / dotclock;
+               linedur_ns  = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
+               framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
+
+               /*
+                * Fields of interlaced scanout modes are only half a frame duration.
+                */
+               if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+                       framedur_ns /= 2;
        } else
                DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n",
                          crtc->base.id);
@@ -484,11 +480,11 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc)
        crtc->framedur_ns = framedur_ns;
 
        DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
-                 crtc->base.id, crtc->hwmode.crtc_htotal,
-                 crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay);
+                 crtc->base.id, mode->crtc_htotal,
+                 mode->crtc_vtotal, mode->crtc_vdisplay);
        DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n",
-                 crtc->base.id, (int) dotclock/1000, (int) framedur_ns,
-                 (int) linedur_ns, (int) pixeldur_ns);
+                 crtc->base.id, dotclock, framedur_ns,
+                 linedur_ns, pixeldur_ns);
 }
 EXPORT_SYMBOL(drm_calc_timestamping_constants);
 
@@ -521,6 +517,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
  *         0 = Default.
  *         DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler.
  * @refcrtc: drm_crtc* of crtc which defines scanout timing.
+ * @mode: mode which defines the scanout timings
  *
  * Returns negative value on error, failure or if not supported in current
  * video mode:
@@ -540,14 +537,14 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                                          int *max_error,
                                          struct timeval *vblank_time,
                                          unsigned flags,
-                                         struct drm_crtc *refcrtc)
+                                         const struct drm_crtc *refcrtc,
+                                         const struct drm_display_mode *mode)
 {
        ktime_t stime, etime, mono_time_offset;
        struct timeval tv_etime;
-       struct drm_display_mode *mode;
-       int vbl_status, vtotal, vdisplay;
+       int vbl_status;
        int vpos, hpos, i;
-       s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
+       int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
        bool invbl;
 
        if (crtc < 0 || crtc >= dev->num_crtcs) {
@@ -561,10 +558,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                return -EIO;
        }
 
-       mode = &refcrtc->hwmode;
-       vtotal = mode->crtc_vtotal;
-       vdisplay = mode->crtc_vdisplay;
-
        /* Durations of frames, lines, pixels in nanoseconds. */
        framedur_ns = refcrtc->framedur_ns;
        linedur_ns  = refcrtc->linedur_ns;
@@ -573,7 +566,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
        /* If mode timing undefined, just return as no-op:
         * Happens during initial modesetting of a crtc.
         */
-       if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) {
+       if (framedur_ns == 0) {
                DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
                return -EAGAIN;
        }
@@ -590,7 +583,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                 * Get vertical and horizontal scanout position vpos, hpos,
                 * and bounding timestamps stime, etime, pre/post query.
                 */
-               vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos,
+               vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos,
                                                               &hpos, &stime, &etime);
 
                /*
@@ -611,18 +604,18 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime);
 
                /* Accept result with <  max_error nsecs timing uncertainty. */
-               if (duration_ns <= (s64) *max_error)
+               if (duration_ns <= *max_error)
                        break;
        }
 
        /* Noisy system timing? */
        if (i == DRM_TIMESTAMP_MAXRETRIES) {
                DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n",
-                         crtc, (int) duration_ns/1000, *max_error/1000, i);
+                         crtc, duration_ns/1000, *max_error/1000, i);
        }
 
        /* Return upper bound of timestamp precision error. */
-       *max_error = (int) duration_ns;
+       *max_error = duration_ns;
 
        /* Check if in vblank area:
         * vpos is >=0 in video scanout area, but negative
@@ -635,25 +628,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
         * since start of scanout at first display scanline. delta_ns
         * can be negative if start of scanout hasn't happened yet.
         */
-       delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns;
-
-       /* Is vpos outside nominal vblank area, but less than
-        * 1/100 of a frame height away from start of vblank?
-        * If so, assume this isn't a massively delayed vblank
-        * interrupt, but a vblank interrupt that fired a few
-        * microseconds before true start of vblank. Compensate
-        * by adding a full frame duration to the final timestamp.
-        * Happens, e.g., on ATI R500, R600.
-        *
-        * We only do this if DRM_CALLED_FROM_VBLIRQ.
-        */
-       if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl &&
-           ((vdisplay - vpos) < vtotal / 100)) {
-               delta_ns = delta_ns - framedur_ns;
-
-               /* Signal this correction as "applied". */
-               vbl_status |= 0x8;
-       }
+       delta_ns = vpos * linedur_ns + hpos * pixeldur_ns;
 
        if (!drm_timestamp_monotonic)
                etime = ktime_sub(etime, mono_time_offset);
@@ -673,7 +648,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
                  crtc, (int)vbl_status, hpos, vpos,
                  (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
                  (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
-                 (int)duration_ns/1000, i);
+                 duration_ns/1000, i);
 
        vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD;
        if (invbl)
@@ -960,7 +935,7 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
        if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
            (drm_vblank_offdelay > 0))
                mod_timer(&dev->vblank_disable_timer,
-                         jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000));
+                         jiffies + ((drm_vblank_offdelay * HZ)/1000));
 }
 EXPORT_SYMBOL(drm_vblank_put);
 
@@ -980,7 +955,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        vblank_disable_and_save(dev, crtc);
-       DRM_WAKEUP(&dev->vblank[crtc].queue);
+       wake_up(&dev->vblank[crtc].queue);
 
        /* Send any queued vblank events, lest the natives grow disquiet */
        seq = drm_vblank_count_and_time(dev, crtc, &now);
@@ -1244,7 +1219,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
        DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
                  vblwait->request.sequence, crtc);
        dev->vblank[crtc].last_wait = vblwait->request.sequence;
-       DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ,
+       DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * HZ,
                    (((drm_vblank_count(dev, crtc) -
                       vblwait->request.sequence) <= (1 << 23)) ||
                     !dev->irq_enabled));
@@ -1363,7 +1338,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
                          crtc, (int) diff_ns);
        }
 
-       DRM_WAKEUP(&dev->vblank[crtc].queue);
+       wake_up(&dev->vblank[crtc].queue);
        drm_handle_vblank_events(dev, crtc);
 
        spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
index 64e44fad8ae84282d43f449d21772c4346acab68..00c67c0f238127d1d36c8ba17e6caf184412c446 100644 (file)
@@ -82,19 +82,19 @@ static void *agp_remap(unsigned long offset, unsigned long size,
 }
 
 /** Wrapper around agp_free_memory() */
-void drm_free_agp(DRM_AGP_MEM * handle, int pages)
+void drm_free_agp(struct agp_memory * handle, int pages)
 {
        agp_free_memory(handle);
 }
 
 /** Wrapper around agp_bind_memory() */
-int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
+int drm_bind_agp(struct agp_memory * handle, unsigned int start)
 {
        return agp_bind_memory(handle, start);
 }
 
 /** Wrapper around agp_unbind_memory() */
-int drm_unbind_agp(DRM_AGP_MEM * handle)
+int drm_unbind_agp(struct agp_memory * handle)
 {
        return agp_unbind_memory(handle);
 }
@@ -110,8 +110,7 @@ static inline void *agp_remap(unsigned long offset, unsigned long size,
 
 void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
 {
-       if (drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+       if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
                map->handle = agp_remap(map->offset, map->size, dev);
        else
                map->handle = ioremap(map->offset, map->size);
@@ -120,8 +119,7 @@ EXPORT_SYMBOL(drm_core_ioremap);
 
 void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)
 {
-       if (drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+       if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
                map->handle = agp_remap(map->offset, map->size, dev);
        else
                map->handle = ioremap_wc(map->offset, map->size);
@@ -133,8 +131,7 @@ void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
        if (!map->handle || !map->size)
                return;
 
-       if (drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+       if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
                vunmap(map->handle);
        else
                iounmap(map->handle);
index 85071a1c4547921f53fd5372c2664a3066d00ef4..b0733153dfd294f178ff1818618fadbe63a1d144 100644 (file)
@@ -1041,7 +1041,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
                                /* if equal delete the probed mode */
                                mode->status = pmode->status;
                                /* Merge type bits together */
-                               mode->type = pmode->type;
+                               mode->type |= pmode->type;
                                list_del(&pmode->head);
                                drm_mode_destroy(connector->dev, pmode);
                                break;
index 02679793c9e2e73d3d175136bbfb638a7cd0784f..5736aaa7e86cb069d30fd458b5842fd42defae17 100644 (file)
@@ -262,16 +262,11 @@ static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
        return 0;
 }
 
-static int drm_pci_agp_init(struct drm_device *dev)
+static void drm_pci_agp_init(struct drm_device *dev)
 {
-       if (drm_core_has_AGP(dev)) {
+       if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
                if (drm_pci_device_is_agp(dev))
                        dev->agp = drm_agp_init(dev);
-               if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
-                   && (dev->agp == NULL)) {
-                       DRM_ERROR("Cannot initialize the agpgart module.\n");
-                       return -EINVAL;
-               }
                if (dev->agp) {
                        dev->agp->agp_mtrr = arch_phys_wc_add(
                                dev->agp->agp_info.aper_base,
@@ -279,15 +274,14 @@ static int drm_pci_agp_init(struct drm_device *dev)
                                1024 * 1024);
                }
        }
-       return 0;
 }
 
-static void drm_pci_agp_destroy(struct drm_device *dev)
+void drm_pci_agp_destroy(struct drm_device *dev)
 {
-       if (drm_core_has_AGP(dev) && dev->agp) {
+       if (dev->agp) {
                arch_phys_wc_del(dev->agp->agp_mtrr);
                drm_agp_clear(dev);
-               drm_agp_destroy(dev->agp);
+               kfree(dev->agp);
                dev->agp = NULL;
        }
 }
@@ -299,8 +293,6 @@ static struct drm_bus drm_pci_bus = {
        .set_busid = drm_pci_set_busid,
        .set_unique = drm_pci_set_unique,
        .irq_by_busid = drm_pci_irq_by_busid,
-       .agp_init = drm_pci_agp_init,
-       .agp_destroy = drm_pci_agp_destroy,
 };
 
 /**
@@ -338,17 +330,25 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                pci_set_drvdata(pdev, dev);
 
+       drm_pci_agp_init(dev);
+
        ret = drm_dev_register(dev, ent->driver_data);
        if (ret)
-               goto err_pci;
+               goto err_agp;
 
        DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
                 driver->name, driver->major, driver->minor, driver->patchlevel,
                 driver->date, pci_name(pdev), dev->primary->index);
 
+       /* No locking needed since shadow-attach is single-threaded since it may
+        * only be called from the per-driver module init hook. */
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list);
+
        return 0;
 
-err_pci:
+err_agp:
+       drm_pci_agp_destroy(dev);
        pci_disable_device(pdev);
 err_free:
        drm_dev_free(dev);
@@ -375,7 +375,6 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
 
        DRM_DEBUG("\n");
 
-       INIT_LIST_HEAD(&driver->device_list);
        driver->kdriver.pci = pdriver;
        driver->bus = &drm_pci_bus;
 
@@ -383,6 +382,7 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
                return pci_register_driver(pdriver);
 
        /* If not using KMS, fall back to stealth mode manual scanning. */
+       INIT_LIST_HEAD(&driver->legacy_dev_list);
        for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
                pid = &pdriver->id_table[i];
 
@@ -452,6 +452,7 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
        return -1;
 }
 
+void drm_pci_agp_destroy(struct drm_device *dev) {}
 #endif
 
 EXPORT_SYMBOL(drm_pci_init);
@@ -465,8 +466,11 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
        if (driver->driver_features & DRIVER_MODESET) {
                pci_unregister_driver(pdriver);
        } else {
-               list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
+               list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list,
+                                        legacy_dev_list) {
                        drm_put_dev(dev);
+                       list_del(&dev->legacy_dev_list);
+               }
        }
        DRM_INFO("Module unloaded\n");
 }
index fc24fee8ec833b6bdb2c26ada2b45e947622b941..21fc82006b78c3423c801b54ef5acd40d4f79805 100644 (file)
@@ -147,18 +147,6 @@ int drm_platform_init(struct drm_driver *driver, struct platform_device *platfor
 
        driver->kdriver.platform_device = platform_device;
        driver->bus = &drm_platform_bus;
-       INIT_LIST_HEAD(&driver->device_list);
        return drm_get_platform_dev(platform_device, driver);
 }
 EXPORT_SYMBOL(drm_platform_init);
-
-void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device)
-{
-       struct drm_device *dev, *tmp;
-       DRM_DEBUG("\n");
-
-       list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
-               drm_put_dev(dev);
-       DRM_INFO("Module unloaded\n");
-}
-EXPORT_SYMBOL(drm_platform_exit);
index f53d5246979c386ed632b21c08decb3ab1296f9e..98a33c580ca1aeceed513f2af38b6742cee30f85 100644 (file)
@@ -99,13 +99,19 @@ void drm_ut_debug_printk(unsigned int request_level,
                         const char *function_name,
                         const char *format, ...)
 {
+       struct va_format vaf;
        va_list args;
 
        if (drm_debug & request_level) {
-               if (function_name)
-                       printk(KERN_DEBUG "[%s:%s], ", prefix, function_name);
                va_start(args, format);
-               vprintk(format, args);
+               vaf.fmt = format;
+               vaf.va = &args;
+
+               if (function_name)
+                       printk(KERN_DEBUG "[%s:%s], %pV", prefix,
+                              function_name, &vaf);
+               else
+                       printk(KERN_DEBUG "%pV", &vaf);
                va_end(args);
        }
 }
@@ -521,16 +527,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
 
        mutex_lock(&drm_global_mutex);
 
-       if (dev->driver->bus->agp_init) {
-               ret = dev->driver->bus->agp_init(dev);
-               if (ret)
-                       goto out_unlock;
-       }
-
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
                if (ret)
-                       goto err_agp;
+                       goto out_unlock;
        }
 
        if (drm_core_check_feature(dev, DRIVER_RENDER) && drm_rnodes) {
@@ -557,8 +557,6 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
                        goto err_unload;
        }
 
-       list_add_tail(&dev->driver_item, &dev->driver->device_list);
-
        ret = 0;
        goto out_unlock;
 
@@ -566,14 +564,11 @@ err_unload:
        if (dev->driver->unload)
                dev->driver->unload(dev);
 err_primary_node:
-       drm_put_minor(dev->primary);
+       drm_unplug_minor(dev->primary);
 err_render_node:
-       drm_put_minor(dev->render);
+       drm_unplug_minor(dev->render);
 err_control_node:
-       drm_put_minor(dev->control);
-err_agp:
-       if (dev->driver->bus->agp_destroy)
-               dev->driver->bus->agp_destroy(dev);
+       drm_unplug_minor(dev->control);
 out_unlock:
        mutex_unlock(&drm_global_mutex);
        return ret;
@@ -597,8 +592,8 @@ void drm_dev_unregister(struct drm_device *dev)
        if (dev->driver->unload)
                dev->driver->unload(dev);
 
-       if (dev->driver->bus->agp_destroy)
-               dev->driver->bus->agp_destroy(dev);
+       if (dev->agp)
+               drm_pci_agp_destroy(dev);
 
        drm_vblank_cleanup(dev);
 
@@ -608,7 +603,5 @@ void drm_dev_unregister(struct drm_device *dev)
        drm_unplug_minor(dev->control);
        drm_unplug_minor(dev->render);
        drm_unplug_minor(dev->primary);
-
-       list_del(&dev->driver_item);
 }
 EXPORT_SYMBOL(drm_dev_unregister);
index b179b70e7853b4bb4eb69c9a97a57295ae26a084..0f8cb1ae76074d2bf21d75d678585222019f2cdd 100644 (file)
@@ -1,4 +1,5 @@
 #include <drm/drmP.h>
+#include <drm/drm_usb.h>
 #include <linux/usb.h>
 #include <linux/module.h>
 
@@ -63,7 +64,6 @@ int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver)
        int res;
        DRM_DEBUG("\n");
 
-       INIT_LIST_HEAD(&driver->device_list);
        driver->kdriver.usb = udriver;
        driver->bus = &drm_usb_bus;
 
index 93e95d7efd575fc7bf084e431ae560793e733728..24e045c4f53140270ebbb28f9a6be21209b704a7 100644 (file)
@@ -101,7 +101,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        /*
         * Find the right map
         */
-       if (!drm_core_has_AGP(dev))
+       if (!dev->agp)
                goto vm_fault_error;
 
        if (!dev->agp || !dev->agp->cant_use_aperture)
@@ -220,7 +220,6 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_dec(&dev->vma_count);
 
        map = vma->vm_private_data;
 
@@ -266,9 +265,6 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
                                dmah.size = map->size;
                                __drm_pci_free(dev, &dmah);
                                break;
-                       case _DRM_GEM:
-                               DRM_ERROR("tried to rmmap GEM object\n");
-                               break;
                        }
                        kfree(map);
                }
@@ -408,7 +404,6 @@ void drm_vm_open_locked(struct drm_device *dev,
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_inc(&dev->vma_count);
 
        vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL);
        if (vma_entry) {
@@ -436,7 +431,6 @@ void drm_vm_close_locked(struct drm_device *dev,
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
                  vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_dec(&dev->vma_count);
 
        list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
                if (pt->vma == vma) {
@@ -595,7 +589,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
        switch (map->type) {
 #if !defined(__arm__)
        case _DRM_AGP:
-               if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
+               if (dev->agp && dev->agp->cant_use_aperture) {
                        /*
                         * On some platforms we can't talk to bus dma address from the CPU, so for
                         * memory of type DRM_AGP, we'll deal with sorting out the real physical
index 22b8f5eced80f3407b0fa9fc365c1d9e349d7e54..9d096a0c5f8d5f6bf0583d37f5efe433085504e4 100644 (file)
@@ -14,6 +14,8 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
+#include <linux/anon_inodes.h>
+
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
@@ -119,6 +121,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
        drm_vblank_offdelay = VBLANK_OFF_DELAY;
 
+       platform_set_drvdata(dev->platformdev, dev);
+
        return 0;
 
 err_drm_device:
@@ -150,9 +154,14 @@ static int exynos_drm_unload(struct drm_device *dev)
        return 0;
 }
 
+static const struct file_operations exynos_drm_gem_fops = {
+       .mmap = exynos_drm_gem_mmap_buffer,
+};
+
 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_exynos_file_private *file_priv;
+       struct file *anon_filp;
        int ret;
 
        file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
@@ -167,6 +176,16 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
                file->driver_priv = NULL;
        }
 
+       anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops,
+                                       NULL, 0);
+       if (IS_ERR(anon_filp)) {
+               kfree(file_priv);
+               return PTR_ERR(anon_filp);
+       }
+
+       anon_filp->f_mode = FMODE_READ | FMODE_WRITE;
+       file_priv->anon_filp = anon_filp;
+
        return ret;
 }
 
@@ -179,6 +198,7 @@ static void exynos_drm_preclose(struct drm_device *dev,
 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct exynos_drm_private *private = dev->dev_private;
+       struct drm_exynos_file_private *file_priv;
        struct drm_pending_vblank_event *v, *vt;
        struct drm_pending_event *e, *et;
        unsigned long flags;
@@ -204,6 +224,9 @@ static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
        }
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
+       file_priv = file->driver_priv;
+       if (file_priv->anon_filp)
+               fput(file_priv->anon_filp);
 
        kfree(file->driver_priv);
        file->driver_priv = NULL;
@@ -305,7 +328,7 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
 
 static int exynos_drm_platform_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&exynos_drm_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
 
        return 0;
 }
index eaa19668bf00328657bdd370c304f27cf66ece5e..0eaf5a27e120e586129074446e816b902d7316f3 100644 (file)
@@ -226,6 +226,7 @@ struct exynos_drm_ipp_private {
 struct drm_exynos_file_private {
        struct exynos_drm_g2d_private   *g2d_priv;
        struct exynos_drm_ipp_private   *ipp_priv;
+       struct file                     *anon_filp;
 };
 
 /*
index a61878bf5dcd091cf31ed64a8374d230b580dc1e..a20440ce32e6c39ee450d926f668f5638df0cca8 100644 (file)
@@ -347,7 +347,7 @@ static void fimd_wait_for_vblank(struct device *dev)
         */
        if (!wait_event_timeout(ctx->wait_vsync_queue,
                                !atomic_read(&ctx->wait_vsync_event),
-                               DRM_HZ/20))
+                               HZ/20))
                DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
@@ -706,7 +706,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
        /* set wait vsync event to zero and wake up queue. */
        if (atomic_read(&ctx->wait_vsync_event)) {
                atomic_set(&ctx->wait_vsync_event, 0);
-               DRM_WAKEUP(&ctx->wait_vsync_queue);
+               wake_up(&ctx->wait_vsync_queue);
        }
 out:
        return IRQ_HANDLED;
@@ -954,7 +954,7 @@ static int fimd_probe(struct platform_device *pdev)
        }
 
        ctx->driver_data = drm_fimd_get_driver_data(pdev);
-       DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
+       init_waitqueue_head(&ctx->wait_vsync_queue);
        atomic_set(&ctx->wait_vsync_event, 0);
 
        subdrv = &ctx->subdrv;
index 1ade191d84f4d6514fd16871cb54cbdc3208d925..49b8c9b2290225dcf9cdf5993075c30ea0fd475e 100644 (file)
@@ -338,46 +338,22 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
                        &args->offset);
 }
 
-static struct drm_file *exynos_drm_find_drm_file(struct drm_device *drm_dev,
-                                                       struct file *filp)
-{
-       struct drm_file *file_priv;
-
-       /* find current process's drm_file from filelist. */
-       list_for_each_entry(file_priv, &drm_dev->filelist, lhead)
-               if (file_priv->filp == filp)
-                       return file_priv;
-
-       WARN_ON(1);
-
-       return ERR_PTR(-EFAULT);
-}
-
-static int exynos_drm_gem_mmap_buffer(struct file *filp,
+int exynos_drm_gem_mmap_buffer(struct file *filp,
                                      struct vm_area_struct *vma)
 {
        struct drm_gem_object *obj = filp->private_data;
        struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
        struct drm_device *drm_dev = obj->dev;
        struct exynos_drm_gem_buf *buffer;
-       struct drm_file *file_priv;
        unsigned long vm_size;
        int ret;
 
+       WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
+
        vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
        vma->vm_private_data = obj;
        vma->vm_ops = drm_dev->driver->gem_vm_ops;
 
-       /* restore it to driver's fops. */
-       filp->f_op = fops_get(drm_dev->driver->fops);
-
-       file_priv = exynos_drm_find_drm_file(drm_dev, filp);
-       if (IS_ERR(file_priv))
-               return PTR_ERR(file_priv);
-
-       /* restore it to drm_file. */
-       filp->private_data = file_priv;
-
        update_vm_cache_attr(exynos_gem_obj, vma);
 
        vm_size = vma->vm_end - vma->vm_start;
@@ -411,15 +387,13 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
        return 0;
 }
 
-static const struct file_operations exynos_drm_gem_fops = {
-       .mmap = exynos_drm_gem_mmap_buffer,
-};
-
 int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *file_priv)
 {
+       struct drm_exynos_file_private *exynos_file_priv;
        struct drm_exynos_gem_mmap *args = data;
        struct drm_gem_object *obj;
+       struct file *anon_filp;
        unsigned long addr;
 
        if (!(dev->driver->driver_features & DRIVER_GEM)) {
@@ -427,47 +401,25 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
                return -ENODEV;
        }
 
+       mutex_lock(&dev->struct_mutex);
+
        obj = drm_gem_object_lookup(dev, file_priv, args->handle);
        if (!obj) {
                DRM_ERROR("failed to lookup gem object.\n");
+               mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
        }
 
-       /*
-        * We have to use gem object and its fops for specific mmaper,
-        * but vm_mmap() can deliver only filp. So we have to change
-        * filp->f_op and filp->private_data temporarily, then restore
-        * again. So it is important to keep lock until restoration the
-        * settings to prevent others from misuse of filp->f_op or
-        * filp->private_data.
-        */
-       mutex_lock(&dev->struct_mutex);
-
-       /*
-        * Set specific mmper's fops. And it will be restored by
-        * exynos_drm_gem_mmap_buffer to dev->driver->fops.
-        * This is used to call specific mapper temporarily.
-        */
-       file_priv->filp->f_op = &exynos_drm_gem_fops;
-
-       /*
-        * Set gem object to private_data so that specific mmaper
-        * can get the gem object. And it will be restored by
-        * exynos_drm_gem_mmap_buffer to drm_file.
-        */
-       file_priv->filp->private_data = obj;
+       exynos_file_priv = file_priv->driver_priv;
+       anon_filp = exynos_file_priv->anon_filp;
+       anon_filp->private_data = obj;
 
-       addr = vm_mmap(file_priv->filp, 0, args->size,
-                       PROT_READ | PROT_WRITE, MAP_SHARED, 0);
+       addr = vm_mmap(anon_filp, 0, args->size, PROT_READ | PROT_WRITE,
+                       MAP_SHARED, 0);
 
        drm_gem_object_unreference(obj);
 
        if (IS_ERR_VALUE(addr)) {
-               /* check filp->f_op, filp->private_data are restored */
-               if (file_priv->filp->f_op == &exynos_drm_gem_fops) {
-                       file_priv->filp->f_op = fops_get(dev->driver->fops);
-                       file_priv->filp->private_data = file_priv;
-               }
                mutex_unlock(&dev->struct_mutex);
                return (int)addr;
        }
index 702ec3abe85cc88eb74aa2e7dc99b5224c175dcf..fde860c7eba34b35b733ff7afef350f0c1b56527 100644 (file)
@@ -122,6 +122,9 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
 int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *file_priv);
 
+int exynos_drm_gem_mmap_buffer(struct file *filp,
+                                     struct vm_area_struct *vma);
+
 /* map user space allocated by malloc to pages. */
 int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
                                      struct drm_file *file_priv);
index 63bc5f92fbb320e6287fa106a8357c7eac503435..2dfa48c76f54644d1c7efd6fb6e52bedacc02e70 100644 (file)
@@ -868,7 +868,7 @@ static void mixer_wait_for_vblank(void *ctx)
         */
        if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
                                !atomic_read(&mixer_ctx->wait_vsync_event),
-                               DRM_HZ/20))
+                               HZ/20))
                DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
@@ -1019,7 +1019,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
                /* set wait vsync event to zero and wake up queue. */
                if (atomic_read(&ctx->wait_vsync_event)) {
                        atomic_set(&ctx->wait_vsync_event, 0);
-                       DRM_WAKEUP(&ctx->wait_vsync_queue);
+                       wake_up(&ctx->wait_vsync_queue);
                }
        }
 
@@ -1209,7 +1209,7 @@ static int mixer_probe(struct platform_device *pdev)
        drm_hdmi_ctx->ctx = (void *)ctx;
        ctx->vp_enabled = drv->is_vp_enabled;
        ctx->mxr_ver = drv->version;
-       DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
+       init_waitqueue_head(&ctx->wait_vsync_queue);
        atomic_set(&ctx->wait_vsync_event, 0);
 
        platform_set_drvdata(pdev, drm_hdmi_ctx);
index d5ef1a5793c8832e9a251fa817f7e19c246c06e6..de6f62a6ceb7a2d85ab67ba2eb64e8f688c05320 100644 (file)
@@ -326,7 +326,7 @@ int psbfb_sync(struct fb_info *info)
        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;
+       unsigned long _end = jiffies + HZ;
        int busy = 0;
        unsigned long flags;
 
index f88a1815d87c4e795492ead6ef1c4c07a4d31b89..0490ce36b53fd9237e754de7877f51f3aaffee97 100644 (file)
@@ -483,7 +483,7 @@ cdv_intel_dp_aux_native_write(struct gma_encoder *encoder,
 
        if (send_bytes > 16)
                return -1;
-       msg[0] = AUX_NATIVE_WRITE << 4;
+       msg[0] = DP_AUX_NATIVE_WRITE << 4;
        msg[1] = address >> 8;
        msg[2] = address & 0xff;
        msg[3] = send_bytes - 1;
@@ -493,9 +493,10 @@ cdv_intel_dp_aux_native_write(struct gma_encoder *encoder,
                ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+               ack >>= 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        break;
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
                        udelay(100);
                else
                        return -EIO;
@@ -523,7 +524,7 @@ cdv_intel_dp_aux_native_read(struct gma_encoder *encoder,
        uint8_t ack;
        int ret;
 
-       msg[0] = AUX_NATIVE_READ << 4;
+       msg[0] = DP_AUX_NATIVE_READ << 4;
        msg[1] = address >> 8;
        msg[2] = address & 0xff;
        msg[3] = recv_bytes - 1;
@@ -538,12 +539,12 @@ cdv_intel_dp_aux_native_read(struct gma_encoder *encoder,
                        return -EPROTO;
                if (ret < 0)
                        return ret;
-               ack = reply[0];
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+               ack = reply[0] >> 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) {
                        memcpy(recv, reply + 1, ret - 1);
                        return ret - 1;
                }
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
                        udelay(100);
                else
                        return -EIO;
@@ -569,12 +570,12 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 
        /* Set up the command byte */
        if (mode & MODE_I2C_READ)
-               msg[0] = AUX_I2C_READ << 4;
+               msg[0] = DP_AUX_I2C_READ << 4;
        else
-               msg[0] = AUX_I2C_WRITE << 4;
+               msg[0] = DP_AUX_I2C_WRITE << 4;
 
        if (!(mode & MODE_I2C_STOP))
-               msg[0] |= AUX_I2C_MOT << 4;
+               msg[0] |= DP_AUX_I2C_MOT << 4;
 
        msg[1] = address >> 8;
        msg[2] = address;
@@ -606,16 +607,16 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        return ret;
                }
 
-               switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
-               case AUX_NATIVE_REPLY_ACK:
+               switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
+               case DP_AUX_NATIVE_REPLY_ACK:
                        /* I2C-over-AUX Reply field is only valid
                         * when paired with AUX ACK.
                         */
                        break;
-               case AUX_NATIVE_REPLY_NACK:
+               case DP_AUX_NATIVE_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_ch native nack\n");
                        return -EREMOTEIO;
-               case AUX_NATIVE_REPLY_DEFER:
+               case DP_AUX_NATIVE_REPLY_DEFER:
                        udelay(100);
                        continue;
                default:
@@ -624,16 +625,16 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        return -EREMOTEIO;
                }
 
-               switch (reply[0] & AUX_I2C_REPLY_MASK) {
-               case AUX_I2C_REPLY_ACK:
+               switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) {
+               case DP_AUX_I2C_REPLY_ACK:
                        if (mode == MODE_I2C_READ) {
                                *read_byte = reply[1];
                        }
                        return reply_bytes - 1;
-               case AUX_I2C_REPLY_NACK:
+               case DP_AUX_I2C_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_i2c nack\n");
                        return -EREMOTEIO;
-               case AUX_I2C_REPLY_DEFER:
+               case DP_AUX_I2C_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_i2c defer\n");
                        udelay(100);
                        break;
@@ -677,7 +678,7 @@ cdv_intel_dp_i2c_init(struct gma_connector *connector,
        return ret;
 }
 
-void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
+static void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
        struct drm_display_mode *adjusted_mode)
 {
        adjusted_mode->hdisplay = fixed_mode->hdisplay;
index 24e8af3d22bfd34583d8b826b3fd75f7023002c7..386de2c9dc8649f449580a062d4d91c62fd3a733 100644 (file)
@@ -349,6 +349,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
        /* If we didn't get a handle then turn the cursor off */
        if (!handle) {
                temp = CURSOR_MODE_DISABLE;
+               mutex_lock(&dev->struct_mutex);
 
                if (gma_power_begin(dev, false)) {
                        REG_WRITE(control, temp);
@@ -365,6 +366,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
                        gma_crtc->cursor_obj = NULL;
                }
 
+               mutex_unlock(&dev->struct_mutex);
                return 0;
        }
 
@@ -374,9 +376,12 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
+       mutex_lock(&dev->struct_mutex);
        obj = drm_gem_object_lookup(dev, file_priv, handle);
-       if (!obj)
-               return -ENOENT;
+       if (!obj) {
+               ret = -ENOENT;
+               goto unlock;
+       }
 
        if (obj->size < width * height * 4) {
                dev_dbg(dev->dev, "Buffer is too small\n");
@@ -440,10 +445,13 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
        }
 
        gma_crtc->cursor_obj = obj;
+unlock:
+       mutex_unlock(&dev->struct_mutex);
        return ret;
 
 unref_cursor:
        drm_gem_object_unreference(obj);
+       mutex_unlock(&dev->struct_mutex);
        return ret;
 }
 
index b59e6588c34327b9162c0346de826729633b20cc..5ad6a03e477eae63aa8cc635981887febca71ac1 100644 (file)
@@ -212,8 +212,8 @@ enum {
 #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 PSB_WATCHDOG_DELAY (HZ * 2)
+#define PSB_LID_DELAY (HZ / 10)
 
 #define MDFLD_PNW_B0 0x04
 #define MDFLD_PNW_C0 0x08
@@ -232,7 +232,7 @@ enum {
 #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 MDFLD_DSR_DELAY                (HZ / MDFLD_DSR_RR)
 
 #define PSB_PWR_STATE_ON               1
 #define PSB_PWR_STATE_OFF              2
@@ -769,7 +769,7 @@ extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
  *psb_irq.c
  */
 
-extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t psb_irq_handler(int irq, void *arg);
 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);
index bde27fdb41bf9d9a7ab79f0e3545e5ae0f9c96a5..dc2c8eb030faeaf29f4bd7d32c87c803ab846e30 100644 (file)
@@ -250,11 +250,6 @@ extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector,
 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,
                                      const struct drm_display_mode *mode,
                                      struct drm_display_mode *adjusted_mode);
index ba4830342d3450593bbc1f49a5a6fded4419c510..f883f9e4c5240ee923cbaabb3c57b88472983431 100644 (file)
@@ -200,7 +200,7 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
                mid_pipe_event_handler(dev, 1);
 }
 
-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t psb_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = arg;
        struct drm_psb_private *dev_priv = dev->dev_private;
@@ -253,7 +253,7 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
 
        PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
        (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
-       DRM_READMEMORYBARRIER();
+       rmb();
 
        if (!handled)
                return IRQ_NONE;
@@ -450,21 +450,6 @@ int psb_irq_disable_dpst(struct drm_device *dev)
        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->vblank.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
  */
index debb7f190c062a725e43e38c567dc815823b38f0..d0b45ffa112600b65beb932f8fb1b4e5802453af 100644 (file)
@@ -32,7 +32,7 @@ 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);
+irqreturn_t psb_irq_handler(int irq, void *arg);
 
 int psb_irq_enable_dpst(struct drm_device *dev);
 int psb_irq_disable_dpst(struct drm_device *dev);
index 249fdff305c63b50fd72c2f62a499eb2a0d3e576..aeace37415aac8ae62ab2aa53a3b927ae648fb6c 100644 (file)
@@ -1193,6 +1193,10 @@ static int i810_flip_bufs(struct drm_device *dev, void *data,
 
 int i810_driver_load(struct drm_device *dev, unsigned long flags)
 {
+       /* Our userspace depends upon the agp mapping support. */
+       if (!dev->agp)
+               return -EINVAL;
+
        pci_set_master(dev->pdev);
 
        return 0;
index d8180d22ceddb38965e3c6f59367d75a8421dff2..441ccf8f5bdc3a7d2ebad9b4724eff2044d2c34b 100644 (file)
@@ -57,7 +57,7 @@ static const struct file_operations i810_driver_fops = {
 
 static struct drm_driver driver = {
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
+           DRIVER_USE_AGP |
            DRIVER_HAVE_DMA,
        .dev_priv_size = sizeof(drm_i810_buf_priv_t),
        .load = i810_driver_load,
index 6199d0b5b958fb2610e83810e117ea89c5057e6e..73ed59eff139a88948c7766dcc0c999398f59254 100644 (file)
@@ -1,8 +1,10 @@
 config DRM_I915
        tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
        depends on DRM
-       depends on AGP
-       depends on AGP_INTEL
+       depends on X86 && PCI
+       depends on (AGP || AGP=n)
+       select INTEL_GTT
+       select AGP_INTEL if AGP
        # we need shmfs for the swappable backing store, and in particular
        # the shmem_readpage() which depends upon tmpfs
        select SHMEM
@@ -35,15 +37,14 @@ config DRM_I915
 config DRM_I915_KMS
        bool "Enable modesetting on intel by default"
        depends on DRM_I915
+       default y
        help
-         Choose this option if you want kernel modesetting enabled by default,
-         and you have a new enough userspace to support this. Running old
-         userspaces with this enabled will cause pain.  Note that this causes
-         the driver to bind to PCI devices, which precludes loading things
-         like intelfb.
+         Choose this option if you want kernel modesetting enabled by default.
+
+         If in doubt, say "Y".
 
 config DRM_I915_FBDEV
-       bool "Enable legacy fbdev support for the modesettting intel driver"
+       bool "Enable legacy fbdev support for the modesetting intel driver"
        depends on DRM_I915
        select DRM_KMS_FB_HELPER
        select FB_CFB_FILLRECT
@@ -55,9 +56,12 @@ config DRM_I915_FBDEV
          support. Note that this support also provide the linux console
          support on top of the intel modesetting driver.
 
+         If in doubt, say "Y".
+
 config DRM_I915_PRELIMINARY_HW_SUPPORT
        bool "Enable preliminary support for prerelease Intel hardware by default"
        depends on DRM_I915
+       default n
        help
          Choose this option if you have prerelease Intel hardware and want the
          i915 driver to support it by default.  You can enable such support at
@@ -65,3 +69,15 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT
          option changes the default for that module option.
 
          If in doubt, say "N".
+
+config DRM_I915_UMS
+       bool "Enable userspace modesetting on Intel hardware (DEPRECATED)"
+       depends on DRM_I915
+       default n
+       help
+         Choose this option if you still need userspace modesetting.
+
+         Userspace modesetting is deprecated for quite some time now, so
+         enable this only if you have ancient versions of the DDX drivers.
+
+         If in doubt, say "N".
index 41838eaa799c5afcb7510bae31118099d4d848a3..da682cbcb8061dd33d8c67c901e476ffebeffc32 100644 (file)
@@ -4,7 +4,6 @@
 
 ccflags-y := -Iinclude/drm
 i915-y := i915_drv.o i915_dma.o i915_irq.o \
-         i915_debugfs.o \
          i915_gpu_error.o \
           i915_suspend.o \
          i915_gem.o \
@@ -55,6 +54,8 @@ i915-$(CONFIG_ACPI)   += intel_acpi.o
 
 i915-$(CONFIG_DRM_I915_FBDEV) += intel_fbdev.o
 
+i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o
+
 obj-$(CONFIG_DRM_I915)  += i915.o
 
 CFLAGS_i915_trace_points.o := -I$(src)
index c4a255be697921caade4bf3dd064217e82230763..954acb2c7021d8eb9a90fe1e49ea5bc806f1f344 100644 (file)
@@ -87,49 +87,6 @@ struct ns2501_priv {
  * when switching the resolution.
  */
 
-static void enable_dvo(struct intel_dvo_device *dvo)
-{
-       struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
-       struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
-       struct drm_i915_private *dev_priv = bus->dev_priv;
-
-       DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n", __FUNCTION__);
-
-       ns->dvoc = I915_READ(DVO_C);
-       ns->pll_a = I915_READ(_DPLL_A);
-       ns->srcdim = I915_READ(DVOC_SRCDIM);
-       ns->fw_blc = I915_READ(FW_BLC);
-
-       I915_WRITE(DVOC, 0x10004084);
-       I915_WRITE(_DPLL_A, 0xd0820000);
-       I915_WRITE(DVOC_SRCDIM, 0x400300);      // 1024x768
-       I915_WRITE(FW_BLC, 0x1080304);
-
-       I915_WRITE(DVOC, 0x90004084);
-}
-
-/*
- * Restore the I915 registers modified by the above
- * trigger function.
- */
-static void restore_dvo(struct intel_dvo_device *dvo)
-{
-       struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
-       struct drm_i915_private *dev_priv = bus->dev_priv;
-       struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
-
-       I915_WRITE(DVOC, ns->dvoc);
-       I915_WRITE(_DPLL_A, ns->pll_a);
-       I915_WRITE(DVOC_SRCDIM, ns->srcdim);
-       I915_WRITE(FW_BLC, ns->fw_blc);
-}
-
 /*
 ** Read a register from the ns2501.
 ** Returns true if successful, false otherwise.
@@ -300,7 +257,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
                            struct drm_display_mode *adjusted_mode)
 {
        bool ok;
-       bool restore = false;
+       int retries = 10;
        struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
 
        DRM_DEBUG_KMS
@@ -476,20 +433,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
                        ns->reg_8_shadow |= NS2501_8_BPAS;
                }
                ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
-
-               if (!ok) {
-                       if (restore)
-                               restore_dvo(dvo);
-                       enable_dvo(dvo);
-                       restore = true;
-               }
-       } while (!ok);
-       /*
-        * Restore the old i915 registers before
-        * forcing the ns2501 on.
-        */
-       if (restore)
-               restore_dvo(dvo);
+       } while (!ok && retries--);
 }
 
 /* set the NS2501 power state */
@@ -510,7 +454,7 @@ static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
 static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
 {
        bool ok;
-       bool restore = false;
+       int retries = 10;
        struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
        unsigned char ch;
 
@@ -537,16 +481,7 @@ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
                        ok &=
                            ns2501_writeb(dvo, 0x35,
                                          enable ? 0xff : 0x00);
-                       if (!ok) {
-                               if (restore)
-                                       restore_dvo(dvo);
-                               enable_dvo(dvo);
-                               restore = true;
-                       }
-               } while (!ok);
-
-               if (restore)
-                       restore_dvo(dvo);
+               } while (!ok && retries--);
        }
 }
 
index 6ed45a984230c6db3bb8cc4b8fbdc2eec9a661d1..b2b46c52294c6d4d9c2a20890fafaa4b122e7fa3 100644 (file)
@@ -40,8 +40,6 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
-#if defined(CONFIG_DEBUG_FS)
-
 enum {
        ACTIVE_LIST,
        INACTIVE_LIST,
@@ -406,16 +404,26 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
        seq_putc(m, '\n');
        list_for_each_entry_reverse(file, &dev->filelist, lhead) {
                struct file_stats stats;
+               struct task_struct *task;
 
                memset(&stats, 0, sizeof(stats));
                idr_for_each(&file->object_idr, per_file_stats, &stats);
+               /*
+                * Although we have a valid reference on file->pid, that does
+                * not guarantee that the task_struct who called get_pid() is
+                * still alive (e.g. get_pid(current) => fork() => exit()).
+                * Therefore, we need to protect this ->comm access using RCU.
+                */
+               rcu_read_lock();
+               task = pid_task(file->pid, PIDTYPE_PID);
                seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu unbound)\n",
-                          get_pid_task(file->pid, PIDTYPE_PID)->comm,
+                          task ? task->comm : "<unknown>",
                           stats.count,
                           stats.total,
                           stats.active,
                           stats.inactive,
                           stats.unbound);
+               rcu_read_unlock();
        }
 
        mutex_unlock(&dev->struct_mutex);
@@ -564,10 +572,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for_each_ring(ring, dev_priv, i)
                i915_ring_seqno_info(m, ring);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -585,6 +595,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        if (INTEL_INFO(dev)->gen >= 8) {
                int i;
@@ -711,6 +722,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                }
                i915_ring_seqno_info(m, ring);
        }
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -904,9 +916,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        crstanddelay = I915_READ16(CRSTANDVID);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
@@ -919,7 +933,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       int ret;
+       int ret = 0;
+
+       intel_runtime_pm_get(dev_priv);
 
        flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
@@ -945,9 +961,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                /* RPSTAT1 is in the GT power well */
                ret = mutex_lock_interruptible(&dev->struct_mutex);
                if (ret)
-                       return ret;
+                       goto out;
 
-               gen6_gt_force_wake_get(dev_priv);
+               gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
                reqf = I915_READ(GEN6_RPNSWREQ);
                reqf &= ~GEN6_TURBO_DISABLE;
@@ -970,7 +986,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                        cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
                cagf *= GT_FREQUENCY_MULTIPLIER;
 
-               gen6_gt_force_wake_put(dev_priv);
+               gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
                mutex_unlock(&dev->struct_mutex);
 
                seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
@@ -1018,23 +1034,24 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
                seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
 
-               val = vlv_punit_read(dev_priv, PUNIT_FUSE_BUS1);
+               val = valleyview_rps_max_freq(dev_priv);
                seq_printf(m, "max GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq, val));
+                          vlv_gpu_freq(dev_priv, val));
 
-               val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM);
+               val = valleyview_rps_min_freq(dev_priv);
                seq_printf(m, "min GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq, val));
+                          vlv_gpu_freq(dev_priv, val));
 
                seq_printf(m, "current GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq,
-                                       (freq_sts >> 8) & 0xff));
+                          vlv_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
                mutex_unlock(&dev_priv->rps.hw_lock);
        } else {
                seq_puts(m, "no P-state info available\n");
        }
 
-       return 0;
+out:
+       intel_runtime_pm_put(dev_priv);
+       return ret;
 }
 
 static int i915_delayfreq_table(struct seq_file *m, void *unused)
@@ -1048,6 +1065,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for (i = 0; i < 16; i++) {
                delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -1055,6 +1073,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
                           (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
        }
 
+       intel_runtime_pm_put(dev_priv);
+
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1076,12 +1096,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for (i = 1; i <= 32; i++) {
                inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
                seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
        }
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1099,11 +1121,13 @@ static int ironlake_drpc_info(struct seq_file *m)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        rgvmodectl = I915_READ(MEMMODECTL);
        rstdbyctl = I915_READ(RSTDBYCTL);
        crstandvid = I915_READ16(CRSTANDVID);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
@@ -1154,6 +1178,50 @@ static int ironlake_drpc_info(struct seq_file *m)
        return 0;
 }
 
+static int vlv_drpc_info(struct seq_file *m)
+{
+
+       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;
+       u32 rpmodectl1, rcctl1;
+       unsigned fw_rendercount = 0, fw_mediacount = 0;
+
+       rpmodectl1 = I915_READ(GEN6_RP_CONTROL);
+       rcctl1 = I915_READ(GEN6_RC_CONTROL);
+
+       seq_printf(m, "Video Turbo Mode: %s\n",
+                  yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
+       seq_printf(m, "Turbo enabled: %s\n",
+                  yesno(rpmodectl1 & GEN6_RP_ENABLE));
+       seq_printf(m, "HW control enabled: %s\n",
+                  yesno(rpmodectl1 & GEN6_RP_ENABLE));
+       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",
+                  yesno(rcctl1 & (GEN7_RC_CTL_TO_MODE |
+                                       GEN6_RC_CTL_EI_MODE(1))));
+       seq_printf(m, "Render Power Well: %s\n",
+                       (I915_READ(VLV_GTLC_PW_STATUS) &
+                               VLV_GTLC_PW_RENDER_STATUS_MASK) ? "Up" : "Down");
+       seq_printf(m, "Media Power Well: %s\n",
+                       (I915_READ(VLV_GTLC_PW_STATUS) &
+                               VLV_GTLC_PW_MEDIA_STATUS_MASK) ? "Up" : "Down");
+
+       spin_lock_irq(&dev_priv->uncore.lock);
+       fw_rendercount = dev_priv->uncore.fw_rendercount;
+       fw_mediacount = dev_priv->uncore.fw_mediacount;
+       spin_unlock_irq(&dev_priv->uncore.lock);
+
+       seq_printf(m, "Forcewake Render Count = %u\n", fw_rendercount);
+       seq_printf(m, "Forcewake Media Count = %u\n", fw_mediacount);
+
+
+       return 0;
+}
+
+
 static int gen6_drpc_info(struct seq_file *m)
 {
 
@@ -1167,6 +1235,7 @@ static int gen6_drpc_info(struct seq_file *m)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        spin_lock_irq(&dev_priv->uncore.lock);
        forcewake_count = dev_priv->uncore.forcewake_count;
@@ -1192,6 +1261,8 @@ static int gen6_drpc_info(struct seq_file *m)
        sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
        mutex_unlock(&dev_priv->rps.hw_lock);
 
+       intel_runtime_pm_put(dev_priv);
+
        seq_printf(m, "Video Turbo Mode: %s\n",
                   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
        seq_printf(m, "HW control enabled: %s\n",
@@ -1256,7 +1327,9 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
 
-       if (IS_GEN6(dev) || IS_GEN7(dev))
+       if (IS_VALLEYVIEW(dev))
+               return vlv_drpc_info(m);
+       else if (IS_GEN6(dev) || IS_GEN7(dev))
                return gen6_drpc_info(m);
        else
                return ironlake_drpc_info(m);
@@ -1268,7 +1341,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
 
-       if (!I915_HAS_FBC(dev)) {
+       if (!HAS_FBC(dev)) {
                seq_puts(m, "FBC unsupported on this chipset\n");
                return 0;
        }
@@ -1330,7 +1403,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
                return 0;
        }
 
-       if (I915_READ(IPS_CTL) & IPS_ENABLE)
+       if (IS_BROADWELL(dev) || I915_READ(IPS_CTL) & IPS_ENABLE)
                seq_puts(m, "enabled\n");
        else
                seq_puts(m, "disabled\n");
@@ -1406,6 +1479,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
@@ -1422,6 +1496,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
                           ((ia_freq >> 8) & 0xff) * 100);
        }
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return 0;
@@ -1437,8 +1512,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
+       intel_runtime_pm_put(dev_priv);
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -1565,13 +1642,21 @@ 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;
+       unsigned forcewake_count = 0, fw_rendercount = 0, fw_mediacount = 0;
 
        spin_lock_irq(&dev_priv->uncore.lock);
-       forcewake_count = dev_priv->uncore.forcewake_count;
+       if (IS_VALLEYVIEW(dev)) {
+               fw_rendercount = dev_priv->uncore.fw_rendercount;
+               fw_mediacount = dev_priv->uncore.fw_mediacount;
+       } else
+               forcewake_count = dev_priv->uncore.forcewake_count;
        spin_unlock_irq(&dev_priv->uncore.lock);
 
-       seq_printf(m, "forcewake count = %u\n", forcewake_count);
+       if (IS_VALLEYVIEW(dev)) {
+               seq_printf(m, "fw_rendercount = %u\n", fw_rendercount);
+               seq_printf(m, "fw_mediacount = %u\n", fw_mediacount);
+       } else
+               seq_printf(m, "forcewake count = %u\n", forcewake_count);
 
        return 0;
 }
@@ -1610,6 +1695,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
                   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
@@ -1641,6 +1727,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
                seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
                           I915_READ(DISP_ARB_CTL));
        }
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1701,16 +1788,19 @@ static int i915_ppgtt_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;
 
        int ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        if (INTEL_INFO(dev)->gen >= 8)
                gen8_ppgtt_info(m, dev);
        else if (INTEL_INFO(dev)->gen >= 6)
                gen6_ppgtt_info(m, dev);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1735,28 +1825,28 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 
        seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
 
-       seq_printf(m, "DPIO_DIV_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_A));
-       seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_B));
+       seq_printf(m, "DPIO PLL DW3 CH0 : 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(0)));
+       seq_printf(m, "DPIO PLL DW3 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(1)));
 
-       seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_A));
-       seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_B));
+       seq_printf(m, "DPIO PLL DW5 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(0)));
+       seq_printf(m, "DPIO PLL DW5 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(1)));
 
-       seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_A));
-       seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_B));
+       seq_printf(m, "DPIO PLL DW7 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(0)));
+       seq_printf(m, "DPIO PLL DW7 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(1)));
 
-       seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_A));
-       seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_B));
+       seq_printf(m, "DPIO PLL DW10 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(0)));
+       seq_printf(m, "DPIO PLL DW10 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(1)));
 
        seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, DPIO_FASTCLK_DISABLE));
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_CMN_DW0));
 
        mutex_unlock(&dev_priv->dpio_lock);
 
@@ -1784,6 +1874,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
        u32 psrperf = 0;
        bool enabled = false;
 
+       intel_runtime_pm_get(dev_priv);
+
        seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
        seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
 
@@ -1796,6 +1888,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
                        EDP_PSR_PERF_CNT_MASK;
        seq_printf(m, "Performance_Counter: %u\n", psrperf);
 
+       intel_runtime_pm_put(dev_priv);
        return 0;
 }
 
@@ -1845,6 +1938,76 @@ static int i915_pc8_status(struct seq_file *m, void *unused)
        return 0;
 }
 
+static const char *power_domain_str(enum intel_display_power_domain domain)
+{
+       switch (domain) {
+       case POWER_DOMAIN_PIPE_A:
+               return "PIPE_A";
+       case POWER_DOMAIN_PIPE_B:
+               return "PIPE_B";
+       case POWER_DOMAIN_PIPE_C:
+               return "PIPE_C";
+       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+               return "PIPE_A_PANEL_FITTER";
+       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
+               return "PIPE_B_PANEL_FITTER";
+       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
+               return "PIPE_C_PANEL_FITTER";
+       case POWER_DOMAIN_TRANSCODER_A:
+               return "TRANSCODER_A";
+       case POWER_DOMAIN_TRANSCODER_B:
+               return "TRANSCODER_B";
+       case POWER_DOMAIN_TRANSCODER_C:
+               return "TRANSCODER_C";
+       case POWER_DOMAIN_TRANSCODER_EDP:
+               return "TRANSCODER_EDP";
+       case POWER_DOMAIN_VGA:
+               return "VGA";
+       case POWER_DOMAIN_AUDIO:
+               return "AUDIO";
+       case POWER_DOMAIN_INIT:
+               return "INIT";
+       default:
+               WARN_ON(1);
+               return "?";
+       }
+}
+
+static int i915_power_domain_info(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       int i;
+
+       mutex_lock(&power_domains->lock);
+
+       seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count");
+       for (i = 0; i < power_domains->power_well_count; i++) {
+               struct i915_power_well *power_well;
+               enum intel_display_power_domain power_domain;
+
+               power_well = &power_domains->power_wells[i];
+               seq_printf(m, "%-25s %d\n", power_well->name,
+                          power_well->count);
+
+               for (power_domain = 0; power_domain < POWER_DOMAIN_NUM;
+                    power_domain++) {
+                       if (!(BIT(power_domain) & power_well->domains))
+                               continue;
+
+                       seq_printf(m, "  %-23s %d\n",
+                                power_domain_str(power_domain),
+                                power_domains->domain_use_count[power_domain]);
+               }
+       }
+
+       mutex_unlock(&power_domains->lock);
+
+       return 0;
+}
+
 struct pipe_crc_info {
        const char *name;
        struct drm_device *dev;
@@ -1857,6 +2020,9 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep)
        struct drm_i915_private *dev_priv = info->dev->dev_private;
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe];
 
+       if (info->pipe >= INTEL_INFO(info->dev)->num_pipes)
+               return -ENODEV;
+
        spin_lock_irq(&pipe_crc->lock);
 
        if (pipe_crc->opened) {
@@ -2005,8 +2171,8 @@ static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor,
        info->dev = dev;
        ent = debugfs_create_file(info->name, S_IRUGO, root, info,
                                  &i915_pipe_crc_fops);
-       if (IS_ERR(ent))
-               return PTR_ERR(ent);
+       if (!ent)
+               return -ENOMEM;
 
        return drm_add_fake_info_node(minor, ent, info);
 }
@@ -2347,7 +2513,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
-       u32 val;
+       u32 val = 0; /* shut up gcc */
        int ret;
 
        if (pipe_crc->source == source)
@@ -2742,7 +2908,7 @@ i915_drop_caches_set(void *data, u64 val)
        struct i915_vma *vma, *x;
        int ret;
 
-       DRM_DEBUG_DRIVER("Dropping caches: 0x%08llx\n", val);
+       DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
 
        /* No need to check and wait for gpu resets, only libdrm auto-restarts
         * on ioctls on -EAGAIN. */
@@ -2810,8 +2976,7 @@ i915_max_freq_get(void *data, u64 *val)
                return ret;
 
        if (IS_VALLEYVIEW(dev))
-               *val = vlv_gpu_freq(dev_priv->mem_freq,
-                                   dev_priv->rps.max_delay);
+               *val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
        else
                *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -2841,9 +3006,9 @@ i915_max_freq_set(void *data, u64 val)
         * Turbo will still be enabled, but won't go above the set value.
         */
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
                dev_priv->rps.max_delay = val;
-               gen6_set_rps(dev, val);
+               valleyview_set_rps(dev, val);
        } else {
                do_div(val, GT_FREQUENCY_MULTIPLIER);
                dev_priv->rps.max_delay = val;
@@ -2876,8 +3041,7 @@ i915_min_freq_get(void *data, u64 *val)
                return ret;
 
        if (IS_VALLEYVIEW(dev))
-               *val = vlv_gpu_freq(dev_priv->mem_freq,
-                                   dev_priv->rps.min_delay);
+               *val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
        else
                *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -2907,7 +3071,7 @@ i915_min_freq_set(void *data, u64 val)
         * Turbo will still be enabled, but won't go below the set value.
         */
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
                dev_priv->rps.min_delay = val;
                valleyview_set_rps(dev, val);
        } else {
@@ -2938,8 +3102,11 @@ i915_cache_sharing_get(void *data, u64 *val)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev_priv->dev->struct_mutex);
 
        *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
@@ -2960,6 +3127,7 @@ i915_cache_sharing_set(void *data, u64 val)
        if (val > 3)
                return -EINVAL;
 
+       intel_runtime_pm_get(dev_priv);
        DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
 
        /* Update the cache sharing policy here as well */
@@ -2968,6 +3136,7 @@ i915_cache_sharing_set(void *data, u64 val)
        snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
        I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
+       intel_runtime_pm_put(dev_priv);
        return 0;
 }
 
@@ -2983,7 +3152,8 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
        if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
-       gen6_gt_force_wake_get(dev_priv);
+       intel_runtime_pm_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        return 0;
 }
@@ -2996,7 +3166,8 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
        if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+       intel_runtime_pm_put(dev_priv);
 
        return 0;
 }
@@ -3016,8 +3187,8 @@ static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor)
                                  S_IRUSR,
                                  root, dev,
                                  &i915_forcewake_fops);
-       if (IS_ERR(ent))
-               return PTR_ERR(ent);
+       if (!ent)
+               return -ENOMEM;
 
        return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops);
 }
@@ -3034,8 +3205,8 @@ static int i915_debugfs_create(struct dentry *root,
                                  S_IRUGO | S_IWUSR,
                                  root, dev,
                                  fops);
-       if (IS_ERR(ent))
-               return PTR_ERR(ent);
+       if (!ent)
+               return -ENOMEM;
 
        return drm_add_fake_info_node(minor, ent, fops);
 }
@@ -3079,6 +3250,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
        {"i915_edp_psr_status", i915_edp_psr_status, 0},
        {"i915_energy_uJ", i915_energy_uJ, 0},
        {"i915_pc8_status", i915_pc8_status, 0},
+       {"i915_power_domain_info", i915_power_domain_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
@@ -3102,10 +3274,10 @@ static const struct i915_debugfs_files {
 void intel_display_crc_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
+       enum pipe pipe;
 
-       for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
-               struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i];
+       for_each_pipe(pipe) {
+               struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
 
                pipe_crc->opened = false;
                spin_lock_init(&pipe_crc->lock);
@@ -3164,5 +3336,3 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
                drm_debugfs_remove_files(info_list, 1, minor);
        }
 }
-
-#endif /* CONFIG_DEBUG_FS */
index 0cab2d045135b66d0462c88d390e43eff3df7b20..15a74f979b4bf8c773b6bde25c65f0badf6afb8e 100644 (file)
@@ -42,6 +42,8 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -83,6 +85,14 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv;
 
+       /*
+        * The dri breadcrumb update races against the drm master disappearing.
+        * Instead of trying to fix this (this is by far not the only ums issue)
+        * just don't do the update in kms mode.
+        */
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
+
        if (dev->primary->master) {
                master_priv = dev->primary->master->driver_priv;
                if (master_priv->sarea_priv)
@@ -783,7 +793,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
                master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
 
        if (ring->irq_get(ring)) {
-               DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, ring->irq_queue, 3 * HZ,
                            READ_BREADCRUMB(dev_priv) >= irq_nr);
                ring->irq_put(ring);
        } else if (wait_for(READ_BREADCRUMB(dev_priv) >= irq_nr, 3000))
@@ -820,7 +830,7 @@ static int i915_irq_emit(struct drm_device *dev, void *data,
        result = i915_emit_irq(dev);
        mutex_unlock(&dev->struct_mutex);
 
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
+       if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
@@ -1008,8 +1018,8 @@ static int i915_getparam(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
-               DRM_ERROR("DRM_COPY_TO_USER failed\n");
+       if (copy_to_user(param->value, &value, sizeof(int))) {
+               DRM_ERROR("copy_to_user failed\n");
                return -EFAULT;
        }
 
@@ -1403,7 +1413,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
        master->driver_priv = NULL;
 }
 
-#ifdef CONFIG_DRM_I915_FBDEV
+#if IS_ENABLED(CONFIG_FB)
 static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 {
        struct apertures_struct *ap;
@@ -1476,6 +1486,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                return -ENODEV;
        }
 
+       /* UMS needs agp support. */
+       if (!drm_core_check_feature(dev, DRIVER_MODESET) && !dev->agp)
+               return -EINVAL;
+
        dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
        if (dev_priv == NULL)
                return -ENOMEM;
@@ -1486,20 +1500,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        spin_lock_init(&dev_priv->irq_lock);
        spin_lock_init(&dev_priv->gpu_error.lock);
-       spin_lock_init(&dev_priv->backlight.lock);
+       spin_lock_init(&dev_priv->backlight_lock);
        spin_lock_init(&dev_priv->uncore.lock);
        spin_lock_init(&dev_priv->mm.object_stat_lock);
        mutex_init(&dev_priv->dpio_lock);
-       mutex_init(&dev_priv->rps.hw_lock);
        mutex_init(&dev_priv->modeset_restore_lock);
 
-       mutex_init(&dev_priv->pc8.lock);
-       dev_priv->pc8.requirements_met = false;
-       dev_priv->pc8.gpu_idle = false;
-       dev_priv->pc8.irqs_disabled = false;
-       dev_priv->pc8.enabled = false;
-       dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
-       INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
+       intel_pm_setup(dev);
 
        intel_display_crc_init(dev);
 
@@ -1603,7 +1610,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        }
 
        intel_irq_init(dev);
-       intel_pm_init(dev);
        intel_uncore_sanitize(dev);
 
        /* Try to make sure MCHBAR is enabled before poking at it */
@@ -1639,8 +1645,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                        goto out_gem_unload;
        }
 
-       if (HAS_POWER_WELL(dev))
-               intel_power_domains_init(dev);
+       intel_power_domains_init(dev);
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                ret = i915_load_modeset_init(dev);
@@ -1664,11 +1669,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (IS_GEN5(dev))
                intel_gpu_ips_init(dev_priv);
 
+       intel_init_runtime_pm(dev_priv);
+
        return 0;
 
 out_power_well:
-       if (HAS_POWER_WELL(dev))
-               intel_power_domains_remove(dev);
+       intel_power_domains_remove(dev);
        drm_vblank_cleanup(dev);
 out_gem_unload:
        if (dev_priv->mm.inactive_shrinker.scan_objects)
@@ -1679,6 +1685,7 @@ out_gem_unload:
 
        intel_teardown_gmbus(dev);
        intel_teardown_mchbar(dev);
+       pm_qos_remove_request(&dev_priv->pm_qos);
        destroy_workqueue(dev_priv->wq);
 out_mtrrfree:
        arch_phys_wc_del(dev_priv->gtt.mtrr);
@@ -1704,25 +1711,27 @@ int i915_driver_unload(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
+       ret = i915_gem_suspend(dev);
+       if (ret) {
+               DRM_ERROR("failed to idle hardware: %d\n", ret);
+               return ret;
+       }
+
+       intel_fini_runtime_pm(dev_priv);
+
        intel_gpu_ips_teardown();
 
-       if (HAS_POWER_WELL(dev)) {
-               /* The i915.ko module is still not prepared to be loaded when
-                * the power well is not enabled, so just enable it in case
-                * we're going to unload/reload. */
-               intel_display_set_init_power(dev, true);
-               intel_power_domains_remove(dev);
-       }
+       /* The i915.ko module is still not prepared to be loaded when
+        * the power well is not enabled, so just enable it in case
+        * we're going to unload/reload. */
+       intel_display_set_init_power(dev, true);
+       intel_power_domains_remove(dev);
 
        i915_teardown_sysfs(dev);
 
        if (dev_priv->mm.inactive_shrinker.scan_objects)
                unregister_shrinker(&dev_priv->mm.inactive_shrinker);
 
-       ret = i915_gem_suspend(dev);
-       if (ret)
-               DRM_ERROR("failed to idle hardware: %d\n", ret);
-
        io_mapping_free(dev_priv->gtt.mappable);
        arch_phys_wc_del(dev_priv->gtt.mtrr);
 
@@ -1777,7 +1786,6 @@ int i915_driver_unload(struct drm_device *dev)
 
        list_del(&dev_priv->gtt.base.global_link);
        WARN_ON(!list_empty(&dev_priv->vm_list));
-       drm_mm_takedown(&dev_priv->gtt.base.mm);
 
        drm_vblank_cleanup(dev);
 
@@ -1848,8 +1856,10 @@ void i915_driver_lastclose(struct drm_device * dev)
 
 void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
+       mutex_lock(&dev->struct_mutex);
        i915_gem_context_close(dev, file_priv);
        i915_gem_release(dev, file_priv);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
@@ -1908,6 +1918,7 @@ const struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
index 2e367a1c6a644b70e7f5375f9e88a22dd0531e08..04f1f02c4019f57873caeb0c70fea14e0816ddeb 100644 (file)
@@ -59,7 +59,7 @@ MODULE_PARM_DESC(powersave,
                "Enable powersavings, fbc, downclocking, etc. (default: true)");
 
 int i915_semaphores __read_mostly = -1;
-module_param_named(semaphores, i915_semaphores, int, 0600);
+module_param_named(semaphores, i915_semaphores, int, 0400);
 MODULE_PARM_DESC(semaphores,
                "Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
 
@@ -114,7 +114,7 @@ MODULE_PARM_DESC(enable_hangcheck,
                "(default: true)");
 
 int i915_enable_ppgtt __read_mostly = -1;
-module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
+module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0400);
 MODULE_PARM_DESC(i915_enable_ppgtt,
                "Enable PPGTT (default: true)");
 
@@ -155,7 +155,6 @@ MODULE_PARM_DESC(prefault_disable,
                "Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only.");
 
 static struct drm_driver driver;
-extern int intel_agp_enabled;
 
 static const struct intel_device_info intel_i830_info = {
        .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
@@ -173,6 +172,7 @@ static const struct intel_device_info intel_i85x_info = {
        .gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,
        .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING,
 };
 
@@ -192,6 +192,7 @@ static const struct intel_device_info intel_i915gm_info = {
        .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
        .supports_tv = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING,
 };
 static const struct intel_device_info intel_i945g_info = {
@@ -204,6 +205,7 @@ static const struct intel_device_info intel_i945gm_info = {
        .has_hotplug = 1, .cursor_needs_physical = 1,
        .has_overlay = 1, .overlay_needs_physical = 1,
        .supports_tv = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING,
 };
 
@@ -265,6 +267,7 @@ static const struct intel_device_info intel_ironlake_m_info = {
 static const struct intel_device_info intel_sandybridge_d_info = {
        .gen = 6, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING,
        .has_llc = 1,
 };
@@ -280,6 +283,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
 #define GEN7_FEATURES  \
        .gen = 7, .num_pipes = 3, \
        .need_gfx_hws = 1, .has_hotplug = 1, \
+       .has_fbc = 1, \
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
        .has_llc = 1
 
@@ -292,7 +296,6 @@ static const struct intel_device_info intel_ivybridge_m_info = {
        GEN7_FEATURES,
        .is_ivybridge = 1,
        .is_mobile = 1,
-       .has_fbc = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_q_info = {
@@ -307,6 +310,7 @@ static const struct intel_device_info intel_valleyview_m_info = {
        .num_pipes = 2,
        .is_valleyview = 1,
        .display_mmio_offset = VLV_DISPLAY_BASE,
+       .has_fbc = 0, /* legal, last one wins */
        .has_llc = 0, /* legal, last one wins */
 };
 
@@ -315,6 +319,7 @@ static const struct intel_device_info intel_valleyview_d_info = {
        .num_pipes = 2,
        .is_valleyview = 1,
        .display_mmio_offset = VLV_DISPLAY_BASE,
+       .has_fbc = 0, /* legal, last one wins */
        .has_llc = 0, /* legal, last one wins */
 };
 
@@ -332,12 +337,10 @@ static const struct intel_device_info intel_haswell_m_info = {
        .is_mobile = 1,
        .has_ddi = 1,
        .has_fpga_dbg = 1,
-       .has_fbc = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 };
 
 static const struct intel_device_info intel_broadwell_d_info = {
-       .is_preliminary = 1,
        .gen = 8, .num_pipes = 3,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
@@ -346,7 +349,6 @@ static const struct intel_device_info intel_broadwell_d_info = {
 };
 
 static const struct intel_device_info intel_broadwell_m_info = {
-       .is_preliminary = 1,
        .gen = 8, .is_mobile = 1, .num_pipes = 3,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
@@ -476,12 +478,12 @@ check_next:
 bool i915_semaphore_is_enabled(struct drm_device *dev)
 {
        if (INTEL_INFO(dev)->gen < 6)
-               return 0;
+               return false;
 
        /* Until we get further testing... */
        if (IS_GEN8(dev)) {
                WARN_ON(!i915_preliminary_hw_support);
-               return 0;
+               return false;
        }
 
        if (i915_semaphores >= 0)
@@ -493,7 +495,7 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
                return false;
 #endif
 
-       return 1;
+       return true;
 }
 
 static int i915_drm_freeze(struct drm_device *dev)
@@ -501,6 +503,8 @@ static int i915_drm_freeze(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
 
+       intel_runtime_pm_get(dev_priv);
+
        /* ignore lid events during suspend */
        mutex_lock(&dev_priv->modeset_restore_lock);
        dev_priv->modeset_restore = MODESET_SUSPENDED;
@@ -651,6 +655,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
                intel_modeset_init_hw(dev);
 
                drm_modeset_lock_all(dev);
+               drm_mode_config_reset(dev);
                intel_modeset_setup_hw_state(dev, true);
                drm_modeset_unlock_all(dev);
 
@@ -687,6 +692,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
        mutex_lock(&dev_priv->modeset_restore_lock);
        dev_priv->modeset_restore = MODESET_DONE;
        mutex_unlock(&dev_priv->modeset_restore_lock);
+
+       intel_runtime_pm_put(dev_priv);
        return error;
 }
 
@@ -761,14 +768,14 @@ int i915_reset(struct drm_device *dev)
                DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
                dev_priv->gpu_error.stop_rings = 0;
                if (ret == -ENODEV) {
-                       DRM_ERROR("Reset not implemented, but ignoring "
-                                 "error for simulated gpu hangs\n");
+                       DRM_INFO("Reset not implemented, but ignoring "
+                                "error for simulated gpu hangs\n");
                        ret = 0;
                }
        }
 
        if (ret) {
-               DRM_ERROR("Failed to reset chip.\n");
+               DRM_ERROR("Failed to reset chip: %i\n", ret);
                mutex_unlock(&dev->struct_mutex);
                return ret;
        }
@@ -789,12 +796,9 @@ int i915_reset(struct drm_device *dev)
         */
        if (drm_core_check_feature(dev, DRIVER_MODESET) ||
                        !dev_priv->ums.mm_suspended) {
-               bool hw_contexts_disabled = dev_priv->hw_contexts_disabled;
                dev_priv->ums.mm_suspended = 0;
 
                ret = i915_gem_init_hw(dev);
-               if (!hw_contexts_disabled && dev_priv->hw_contexts_disabled)
-                       DRM_ERROR("HW contexts didn't survive reset\n");
                mutex_unlock(&dev->struct_mutex);
                if (ret) {
                        DRM_ERROR("Failed hw init on reset %d\n", ret);
@@ -830,17 +834,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (PCI_FUNC(pdev->devfn))
                return -ENODEV;
 
-       /* We've managed to ship a kms-enabled ddx that shipped with an XvMC
-        * implementation for gen3 (and only gen3) that used legacy drm maps
-        * (gasp!) to share buffers between X and the client. Hence we need to
-        * keep around the fake agp stuff for gen3, even when kms is enabled. */
-       if (intel_info->gen != 3) {
-               driver.driver_features &=
-                       ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP);
-       } else if (!intel_agp_enabled) {
-               DRM_ERROR("drm/i915 can't work without intel_agp module!\n");
-               return -ENODEV;
-       }
+       driver.driver_features &= ~(DRIVER_USE_AGP);
 
        return drm_get_pci_dev(pdev, ent, &driver);
 }
@@ -914,6 +908,49 @@ static int i915_pm_poweroff(struct device *dev)
        return i915_drm_freeze(drm_dev);
 }
 
+static int i915_runtime_suspend(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       WARN_ON(!HAS_RUNTIME_PM(dev));
+
+       DRM_DEBUG_KMS("Suspending device\n");
+
+       i915_gem_release_all_mmaps(dev_priv);
+
+       del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
+       dev_priv->pm.suspended = true;
+
+       /*
+        * current versions of firmware which depend on this opregion
+        * notification have repurposed the D1 definition to mean
+        * "runtime suspended" vs. what you would normally expect (D3)
+        * to distinguish it from notifications that might be sent
+        * via the suspend path.
+        */
+       intel_opregion_notify_adapter(dev, PCI_D1);
+
+       return 0;
+}
+
+static int i915_runtime_resume(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       WARN_ON(!HAS_RUNTIME_PM(dev));
+
+       DRM_DEBUG_KMS("Resuming device\n");
+
+       intel_opregion_notify_adapter(dev, PCI_D0);
+       dev_priv->pm.suspended = false;
+
+       return 0;
+}
+
 static const struct dev_pm_ops i915_pm_ops = {
        .suspend = i915_pm_suspend,
        .resume = i915_pm_resume,
@@ -921,6 +958,8 @@ static const struct dev_pm_ops i915_pm_ops = {
        .thaw = i915_pm_thaw,
        .poweroff = i915_pm_poweroff,
        .restore = i915_pm_resume,
+       .runtime_suspend = i915_runtime_suspend,
+       .runtime_resume = i915_runtime_resume,
 };
 
 static const struct vm_operations_struct i915_gem_vm_ops = {
@@ -948,7 +987,7 @@ static struct drm_driver driver = {
         * deal with them for Intel hardware.
         */
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
+           DRIVER_USE_AGP |
            DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME |
            DRIVER_RENDER,
        .load = i915_driver_load,
@@ -1023,14 +1062,24 @@ static int __init i915_init(void)
                driver.driver_features &= ~DRIVER_MODESET;
 #endif
 
-       if (!(driver.driver_features & DRIVER_MODESET))
+       if (!(driver.driver_features & DRIVER_MODESET)) {
                driver.get_vblank_timestamp = NULL;
+#ifndef CONFIG_DRM_I915_UMS
+               /* Silently fail loading to not upset userspace. */
+               return 0;
+#endif
+       }
 
        return drm_pci_init(&driver, &i915_pci_driver);
 }
 
 static void __exit i915_exit(void)
 {
+#ifndef CONFIG_DRM_I915_UMS
+       if (!(driver.driver_features & DRIVER_MODESET))
+               return; /* Never loaded a driver. */
+#endif
+
        drm_pci_exit(&driver, &i915_pci_driver);
 }
 
index ccdbecca070d2340919d5499f80824ddb84db4ac..98322053eb2addb091ca0f5c3f9c86a10583815d 100644 (file)
@@ -89,6 +89,18 @@ enum port {
 };
 #define port_name(p) ((p) + 'A')
 
+#define I915_NUM_PHYS_VLV 1
+
+enum dpio_channel {
+       DPIO_CH0,
+       DPIO_CH1
+};
+
+enum dpio_phy {
+       DPIO_PHY0,
+       DPIO_PHY1
+};
+
 enum intel_display_power_domain {
        POWER_DOMAIN_PIPE_A,
        POWER_DOMAIN_PIPE_B,
@@ -101,6 +113,7 @@ enum intel_display_power_domain {
        POWER_DOMAIN_TRANSCODER_C,
        POWER_DOMAIN_TRANSCODER_EDP,
        POWER_DOMAIN_VGA,
+       POWER_DOMAIN_AUDIO,
        POWER_DOMAIN_INIT,
 
        POWER_DOMAIN_NUM,
@@ -310,13 +323,14 @@ struct drm_i915_error_state {
        u32 instps[I915_NUM_RINGS];
        u32 extra_instdone[I915_NUM_INSTDONE_REG];
        u32 seqno[I915_NUM_RINGS];
-       u64 bbaddr;
+       u64 bbaddr[I915_NUM_RINGS];
        u32 fault_reg[I915_NUM_RINGS];
        u32 done_reg;
        u32 faddr[I915_NUM_RINGS];
        u64 fence[I915_MAX_NUM_FENCES];
        struct timeval time;
        struct drm_i915_error_ring {
+               bool valid;
                struct drm_i915_error_object {
                        int page_count;
                        u32 gtt_offset;
@@ -351,6 +365,7 @@ struct drm_i915_error_state {
        enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS];
 };
 
+struct intel_connector;
 struct intel_crtc_config;
 struct intel_crtc;
 struct intel_limit;
@@ -358,7 +373,7 @@ struct dpll;
 
 struct drm_i915_display_funcs {
        bool (*fbc_enabled)(struct drm_device *dev);
-       void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
+       void (*enable_fbc)(struct drm_crtc *crtc);
        void (*disable_fbc)(struct drm_device *dev);
        int (*get_display_clock_speed)(struct drm_device *dev);
        int (*get_fifo_size)(struct drm_device *dev, int plane);
@@ -413,11 +428,20 @@ struct drm_i915_display_funcs {
        /* render clock increase/decrease */
        /* display clock increase/decrease */
        /* pll clock increase/decrease */
+
+       int (*setup_backlight)(struct intel_connector *connector);
+       uint32_t (*get_backlight)(struct intel_connector *connector);
+       void (*set_backlight)(struct intel_connector *connector,
+                             uint32_t level);
+       void (*disable_backlight)(struct intel_connector *connector);
+       void (*enable_backlight)(struct intel_connector *connector);
 };
 
 struct intel_uncore_funcs {
-       void (*force_wake_get)(struct drm_i915_private *dev_priv);
-       void (*force_wake_put)(struct drm_i915_private *dev_priv);
+       void (*force_wake_get)(struct drm_i915_private *dev_priv,
+                                                       int fw_engine);
+       void (*force_wake_put)(struct drm_i915_private *dev_priv,
+                                                       int fw_engine);
 
        uint8_t  (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
        uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
@@ -442,6 +466,9 @@ struct intel_uncore {
        unsigned fifo_count;
        unsigned forcewake_count;
 
+       unsigned fw_rendercount;
+       unsigned fw_mediacount;
+
        struct delayed_work force_wake_work;
 };
 
@@ -669,7 +696,6 @@ struct i915_fbc {
                struct delayed_work work;
                struct drm_crtc *crtc;
                struct drm_framebuffer *fb;
-               int interval;
        } *fbc_work;
 
        enum no_fbc_reason {
@@ -708,7 +734,6 @@ enum intel_sbi_destination {
 #define QUIRK_PIPEA_FORCE (1<<0)
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
 #define QUIRK_INVERT_BRIGHTNESS (1<<2)
-#define QUIRK_NO_PCH_PWM_ENABLE (1<<3)
 
 struct intel_fbdev;
 struct intel_fbc_work;
@@ -761,8 +786,6 @@ struct i915_suspend_saved_registers {
        u32 saveBLC_PWM_CTL;
        u32 saveBLC_PWM_CTL2;
        u32 saveBLC_HIST_CTL_B;
-       u32 saveBLC_PWM_CTL_B;
-       u32 saveBLC_PWM_CTL2_B;
        u32 saveBLC_CPU_PWM_CTL;
        u32 saveBLC_CPU_PWM_CTL2;
        u32 saveFPB0;
@@ -932,21 +955,29 @@ struct intel_ilk_power_mgmt {
 
 /* Power well structure for haswell */
 struct i915_power_well {
+       const char *name;
+       bool always_on;
        /* power well enable/disable usage count */
        int count;
+       unsigned long domains;
+       void *data;
+       void (*set)(struct drm_device *dev, struct i915_power_well *power_well,
+                   bool enable);
+       bool (*is_enabled)(struct drm_device *dev,
+                          struct i915_power_well *power_well);
 };
 
-#define I915_MAX_POWER_WELLS 1
-
 struct i915_power_domains {
        /*
         * Power wells needed for initialization at driver init and suspend
         * time are on. They are kept on until after the first modeset.
         */
        bool init_power_on;
+       int power_well_count;
 
        struct mutex lock;
-       struct i915_power_well power_wells[I915_MAX_POWER_WELLS];
+       int domain_use_count[POWER_DOMAIN_NUM];
+       struct i915_power_well *power_wells;
 };
 
 struct i915_dri1_state {
@@ -1077,34 +1108,30 @@ struct i915_gpu_error {
        unsigned long missed_irq_rings;
 
        /**
-        * State variable and reset counter controlling the reset flow
+        * State variable controlling the reset flow and count
         *
-        * Upper bits are for the reset counter.  This counter is used by the
-        * wait_seqno code to race-free noticed that a reset event happened and
-        * that it needs to restart the entire ioctl (since most likely the
-        * seqno it waited for won't ever signal anytime soon).
+        * This is a counter which gets incremented when reset is triggered,
+        * and again when reset has been handled. So odd values (lowest bit set)
+        * means that reset is in progress and even values that
+        * (reset_counter >> 1):th reset was successfully completed.
+        *
+        * If reset is not completed succesfully, the I915_WEDGE bit is
+        * set meaning that hardware is terminally sour and there is no
+        * recovery. All waiters on the reset_queue will be woken when
+        * that happens.
+        *
+        * This counter is used by the wait_seqno code to notice that reset
+        * event happened and it needs to restart the entire ioctl (since most
+        * likely the seqno it waited for won't ever signal anytime soon).
         *
         * This is important for lock-free wait paths, where no contended lock
         * naturally enforces the correct ordering between the bail-out of the
         * waiter and the gpu reset work code.
-        *
-        * Lowest bit controls the reset state machine: Set means a reset is in
-        * progress. This state will (presuming we don't have any bugs) decay
-        * into either unset (successful reset) or the special WEDGED value (hw
-        * terminally sour). All waiters on the reset_queue will be woken when
-        * that happens.
         */
        atomic_t reset_counter;
 
-       /**
-        * Special values/flags for reset_counter
-        *
-        * Note that the code relies on
-        *      I915_WEDGED & I915_RESET_IN_PROGRESS_FLAG
-        * being true.
-        */
 #define I915_RESET_IN_PROGRESS_FLAG    1
-#define I915_WEDGED                    0xffffffff
+#define I915_WEDGED                    (1 << 31)
 
        /**
         * Waitqueue to signal when the reset has completed. Used by clients
@@ -1158,6 +1185,11 @@ struct intel_vbt_data {
        int edp_bpp;
        struct edp_power_seq edp_pps;
 
+       struct {
+               u16 pwm_freq_hz;
+               bool active_low_pwm;
+       } backlight;
+
        /* MIPI DSI */
        struct {
                u16 panel_id;
@@ -1184,7 +1216,7 @@ struct intel_wm_level {
        uint32_t fbc_val;
 };
 
-struct hsw_wm_values {
+struct ilk_wm_values {
        uint32_t wm_pipe[3];
        uint32_t wm_lp[3];
        uint32_t wm_lp_spr[3];
@@ -1262,6 +1294,10 @@ struct i915_package_c8 {
        } regsave;
 };
 
+struct i915_runtime_pm {
+       bool suspended;
+};
+
 enum intel_pipe_crc_source {
        INTEL_PIPE_CRC_SOURCE_NONE,
        INTEL_PIPE_CRC_SOURCE_PLANE1,
@@ -1366,15 +1402,9 @@ typedef struct drm_i915_private {
 
        /* overlay */
        struct intel_overlay *overlay;
-       unsigned int sprite_scaling_enabled;
 
-       /* backlight */
-       struct {
-               int level;
-               bool enabled;
-               spinlock_t lock; /* bl registers and the above bl fields */
-               struct backlight_device *device;
-       } backlight;
+       /* backlight registers and fields in struct intel_panel */
+       spinlock_t backlight_lock;
 
        /* LVDS info */
        bool no_aux_handshake;
@@ -1426,6 +1456,7 @@ typedef struct drm_i915_private {
        int num_shared_dpll;
        struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
        struct intel_ddi_plls ddi_plls;
+       int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
 
        /* Reclocking support */
        bool render_reclock_avail;
@@ -1470,7 +1501,6 @@ typedef struct drm_i915_private {
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
 
-       bool hw_contexts_disabled;
        uint32_t hw_context_size;
        struct list_head context_list;
 
@@ -1492,11 +1522,13 @@ typedef struct drm_i915_private {
                uint16_t cur_latency[5];
 
                /* current hardware state */
-               struct hsw_wm_values hw;
+               struct ilk_wm_values hw;
        } wm;
 
        struct i915_package_c8 pc8;
 
+       struct i915_runtime_pm pm;
+
        /* Old dri1 support infrastructure, beware the dragons ya fools entering
         * here! */
        struct i915_dri1_state dri1;
@@ -1755,8 +1787,13 @@ struct drm_i915_file_private {
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 #define IS_HSW_EARLY_SDV(dev)  (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0xFF00) == 0x0C00)
-#define IS_ULT(dev)            (IS_HASWELL(dev) && \
+#define IS_BDW_ULT(dev)                (IS_BROADWELL(dev) && \
+                                (((dev)->pdev->device & 0xf) == 0x2  || \
+                                ((dev)->pdev->device & 0xf) == 0x6 || \
+                                ((dev)->pdev->device & 0xf) == 0xe))
+#define IS_HSW_ULT(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0xFF00) == 0x0A00)
+#define IS_ULT(dev)            (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
 #define IS_HSW_GT3(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0x00F0) == 0x0020)
 #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
@@ -1808,15 +1845,15 @@ struct drm_i915_file_private {
 
 #define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
 #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
-#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
+#define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
 
 #define HAS_IPS(dev)           (IS_ULT(dev) || IS_BROADWELL(dev))
 
 #define HAS_DDI(dev)           (INTEL_INFO(dev)->has_ddi)
-#define HAS_POWER_WELL(dev)    (IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_FPGA_DBG_UNCLAIMED(dev)    (INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)           (IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_PC8(dev)           (IS_HASWELL(dev)) /* XXX HSW:ULX */
+#define HAS_RUNTIME_PM(dev)    (IS_HASWELL(dev))
 
 #define INTEL_PCH_DEVICE_ID_MASK               0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE           0x3b00
@@ -1901,14 +1938,11 @@ void i915_queue_hangcheck(struct drm_device *dev);
 void i915_handle_error(struct drm_device *dev, bool wedged);
 
 extern void intel_irq_init(struct drm_device *dev);
-extern void intel_pm_init(struct drm_device *dev);
 extern void intel_hpd_init(struct drm_device *dev);
-extern void intel_pm_init(struct drm_device *dev);
 
 extern void intel_uncore_sanitize(struct drm_device *dev);
 extern void intel_uncore_early_sanitize(struct drm_device *dev);
 extern void intel_uncore_init(struct drm_device *dev);
-extern void intel_uncore_clear_errors(struct drm_device *dev);
 extern void intel_uncore_check_errors(struct drm_device *dev);
 extern void intel_uncore_fini(struct drm_device *dev);
 
@@ -1984,6 +2018,7 @@ void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
 int __must_check i915_vma_unbind(struct i915_vma *vma);
 int __must_check i915_gem_object_ggtt_unbind(struct drm_i915_gem_object *obj);
 int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
+void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 
@@ -2060,12 +2095,17 @@ int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
 static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
 {
        return unlikely(atomic_read(&error->reset_counter)
-                       & I915_RESET_IN_PROGRESS_FLAG);
+                       & (I915_RESET_IN_PROGRESS_FLAG | I915_WEDGED));
 }
 
 static inline bool i915_terminally_wedged(struct i915_gpu_error *error)
 {
-       return atomic_read(&error->reset_counter) == I915_WEDGED;
+       return atomic_read(&error->reset_counter) & I915_WEDGED;
+}
+
+static inline u32 i915_reset_count(struct i915_gpu_error *error)
+{
+       return ((atomic_read(&error->reset_counter) & ~I915_WEDGED) + 1) / 2;
 }
 
 void i915_gem_reset(struct drm_device *dev);
@@ -2177,7 +2217,7 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
 }
 
 /* i915_gem_context.c */
-void i915_gem_context_init(struct drm_device *dev);
+int __must_check i915_gem_context_init(struct drm_device *dev);
 void i915_gem_context_fini(struct drm_device *dev);
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
 int i915_switch_context(struct intel_ring_buffer *ring,
@@ -2395,6 +2435,8 @@ extern int intel_enable_rc6(const struct drm_device *dev);
 extern bool i915_semaphore_is_enabled(struct drm_device *dev);
 int i915_reg_read_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file);
+int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file);
 
 /* overlay */
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
@@ -2410,8 +2452,8 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
  * must be set to prevent GT core from power down and stale values being
  * returned.
  */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine);
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine);
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
 int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
@@ -2426,6 +2468,8 @@ u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg);
 void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg);
 void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg);
 void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg);
@@ -2434,9 +2478,30 @@ u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
                   enum intel_sbi_destination destination);
 void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
                     enum intel_sbi_destination destination);
+u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+
+int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val);
+int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val);
+
+void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine);
+void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine);
+
+#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
+       (((reg) >= 0x2000 && (reg) < 0x4000) ||\
+       ((reg) >= 0x5000 && (reg) < 0x8000) ||\
+       ((reg) >= 0xB000 && (reg) < 0x12000) ||\
+       ((reg) >= 0x2E000 && (reg) < 0x30000))
+
+#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\
+       (((reg) >= 0x12000 && (reg) < 0x14000) ||\
+       ((reg) >= 0x22000 && (reg) < 0x24000) ||\
+       ((reg) >= 0x30000 && (reg) < 0x40000))
+
+#define FORCEWAKE_RENDER       (1 << 0)
+#define FORCEWAKE_MEDIA                (1 << 1)
+#define FORCEWAKE_ALL          (FORCEWAKE_RENDER | FORCEWAKE_MEDIA)
 
-int vlv_gpu_freq(int ddr_freq, int val);
-int vlv_freq_opcode(int ddr_freq, int val);
 
 #define I915_READ8(reg)                dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true)
 #define I915_WRITE8(reg, val)  dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true)
index 621c7c67a6439b2e785fc4b0f9898784aad47b01..00c8361547253ecccf8ba17d6c06d730c688ca3b 100644 (file)
@@ -1015,9 +1015,11 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
                        struct drm_i915_file_private *file_priv)
 {
        drm_i915_private_t *dev_priv = ring->dev->dev_private;
+       const bool irq_test_in_progress =
+               ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
        struct timespec before, now;
        DEFINE_WAIT(wait);
-       long timeout_jiffies;
+       unsigned long timeout_expire;
        int ret;
 
        WARN(dev_priv->pc8.irqs_disabled, "IRQs disabled\n");
@@ -1025,7 +1027,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
        if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
                return 0;
 
-       timeout_jiffies = timeout ? timespec_to_jiffies_timeout(timeout) : 1;
+       timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
 
        if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) {
                gen6_rps_boost(dev_priv);
@@ -1035,8 +1037,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
                                         msecs_to_jiffies(100));
        }
 
-       if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)) &&
-           WARN_ON(!ring->irq_get(ring)))
+       if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring)))
                return -ENODEV;
 
        /* Record current time in case interrupted by signal, or wedged */
@@ -1044,7 +1045,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
        getrawmonotonic(&before);
        for (;;) {
                struct timer_list timer;
-               unsigned long expire;
 
                prepare_to_wait(&ring->irq_queue, &wait,
                                interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
@@ -1070,23 +1070,22 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
                        break;
                }
 
-               if (timeout_jiffies <= 0) {
+               if (timeout && time_after_eq(jiffies, timeout_expire)) {
                        ret = -ETIME;
                        break;
                }
 
                timer.function = NULL;
                if (timeout || missed_irq(dev_priv, ring)) {
+                       unsigned long expire;
+
                        setup_timer_on_stack(&timer, fake_irq, (unsigned long)current);
-                       expire = jiffies + (missed_irq(dev_priv, ring) ? 1: timeout_jiffies);
+                       expire = missed_irq(dev_priv, ring) ? jiffies + 1 : timeout_expire;
                        mod_timer(&timer, expire);
                }
 
                io_schedule();
 
-               if (timeout)
-                       timeout_jiffies = expire - jiffies;
-
                if (timer.function) {
                        del_singleshot_timer_sync(&timer);
                        destroy_timer_on_stack(&timer);
@@ -1095,7 +1094,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
        getrawmonotonic(&now);
        trace_i915_gem_request_wait_end(ring, seqno);
 
-       ring->irq_put(ring);
+       if (!irq_test_in_progress)
+               ring->irq_put(ring);
 
        finish_wait(&ring->irq_queue, &wait);
 
@@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        int ret = 0;
        bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
 
+       intel_runtime_pm_get(dev_priv);
+
        /* We don't use vmf->pgoff since that has the fake offset */
        page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
                PAGE_SHIFT;
@@ -1427,8 +1429,10 @@ out:
                /* If this -EIO is due to a gpu hang, give the reset code a
                 * chance to clean up the mess. Otherwise return the proper
                 * SIGBUS. */
-               if (i915_terminally_wedged(&dev_priv->gpu_error))
-                       return VM_FAULT_SIGBUS;
+               if (i915_terminally_wedged(&dev_priv->gpu_error)) {
+                       ret = VM_FAULT_SIGBUS;
+                       break;
+               }
        case -EAGAIN:
                /*
                 * EAGAIN means the gpu is hung and we'll wait for the error
@@ -1443,15 +1447,38 @@ out:
                 * EBUSY is ok: this just means that another thread
                 * already did the job.
                 */
-               return VM_FAULT_NOPAGE;
+               ret = VM_FAULT_NOPAGE;
+               break;
        case -ENOMEM:
-               return VM_FAULT_OOM;
+               ret = VM_FAULT_OOM;
+               break;
        case -ENOSPC:
-               return VM_FAULT_SIGBUS;
+               ret = VM_FAULT_SIGBUS;
+               break;
        default:
                WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
-               return VM_FAULT_SIGBUS;
+               ret = VM_FAULT_SIGBUS;
+               break;
        }
+
+       intel_runtime_pm_put(dev_priv);
+       return ret;
+}
+
+void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
+{
+       struct i915_vma *vma;
+
+       /*
+        * Only the global gtt is relevant for gtt memory mappings, so restrict
+        * list traversal to objects bound into the global address space. Note
+        * that the active list should be empty, but better safe than sorry.
+        */
+       WARN_ON(!list_empty(&dev_priv->gtt.base.active_list));
+       list_for_each_entry(vma, &dev_priv->gtt.base.active_list, mm_list)
+               i915_gem_release_mmap(vma->obj);
+       list_for_each_entry(vma, &dev_priv->gtt.base.inactive_list, mm_list)
+               i915_gem_release_mmap(vma->obj);
 }
 
 /**
@@ -2303,7 +2330,7 @@ static void i915_set_reset_status(struct intel_ring_buffer *ring,
 
        if (ring->hangcheck.action != HANGCHECK_WAIT &&
            i915_request_guilty(request, acthd, &inside)) {
-               DRM_ERROR("%s hung %s bo (0x%lx ctx %d) at 0x%x\n",
+               DRM_DEBUG("%s hung %s bo (0x%lx ctx %d) at 0x%x\n",
                          ring->name,
                          inside ? "inside" : "flushing",
                          offset,
@@ -2343,28 +2370,24 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request)
        kfree(request);
 }
 
-static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
-                                     struct intel_ring_buffer *ring)
+static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
+                                      struct intel_ring_buffer *ring)
 {
-       u32 completed_seqno;
-       u32 acthd;
-
-       acthd = intel_ring_get_active_head(ring);
-       completed_seqno = ring->get_seqno(ring, false);
-
-       while (!list_empty(&ring->request_list)) {
-               struct drm_i915_gem_request *request;
-
-               request = list_first_entry(&ring->request_list,
-                                          struct drm_i915_gem_request,
-                                          list);
+       u32 completed_seqno = ring->get_seqno(ring, false);
+       u32 acthd = intel_ring_get_active_head(ring);
+       struct drm_i915_gem_request *request;
 
-               if (request->seqno > completed_seqno)
-                       i915_set_reset_status(ring, request, acthd);
+       list_for_each_entry(request, &ring->request_list, list) {
+               if (i915_seqno_passed(completed_seqno, request->seqno))
+                       continue;
 
-               i915_gem_free_request(request);
+               i915_set_reset_status(ring, request, acthd);
        }
+}
 
+static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
+                                       struct intel_ring_buffer *ring)
+{
        while (!list_empty(&ring->active_list)) {
                struct drm_i915_gem_object *obj;
 
@@ -2374,6 +2397,23 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
 
                i915_gem_object_move_to_inactive(obj);
        }
+
+       /*
+        * We must free the requests after all the corresponding objects have
+        * been moved off active lists. Which is the same order as the normal
+        * retire_requests function does. This is important if object hold
+        * implicit references on things like e.g. ppgtt address spaces through
+        * the request.
+        */
+       while (!list_empty(&ring->request_list)) {
+               struct drm_i915_gem_request *request;
+
+               request = list_first_entry(&ring->request_list,
+                                          struct drm_i915_gem_request,
+                                          list);
+
+               i915_gem_free_request(request);
+       }
 }
 
 void i915_gem_restore_fences(struct drm_device *dev)
@@ -2403,8 +2443,16 @@ void i915_gem_reset(struct drm_device *dev)
        struct intel_ring_buffer *ring;
        int i;
 
+       /*
+        * Before we free the objects from the requests, we need to inspect
+        * them for finding the guilty party. As the requests only borrow
+        * their reference to the objects, the inspection must be done first.
+        */
        for_each_ring(ring, dev_priv, i)
-               i915_gem_reset_ring_lists(dev_priv, ring);
+               i915_gem_reset_ring_status(dev_priv, ring);
+
+       for_each_ring(ring, dev_priv, i)
+               i915_gem_reset_ring_cleanup(dev_priv, ring);
 
        i915_gem_cleanup_ringbuffer(dev);
 
@@ -2746,7 +2794,6 @@ int i915_vma_unbind(struct i915_vma *vma)
                obj->has_aliasing_ppgtt_mapping = 0;
        }
        i915_gem_gtt_finish_object(obj);
-       i915_gem_object_unpin_pages(obj);
 
        list_del(&vma->mm_list);
        /* Avoid an unnecessary call to unbind on rebind. */
@@ -2754,7 +2801,6 @@ int i915_vma_unbind(struct i915_vma *vma)
                obj->map_and_fenceable = true;
 
        drm_mm_remove_node(&vma->node);
-
        i915_gem_vma_destroy(vma);
 
        /* Since the unbound list is global, only move to that list if
@@ -2762,6 +2808,12 @@ int i915_vma_unbind(struct i915_vma *vma)
        if (list_empty(&obj->vma_list))
                list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
 
+       /* And finally now the object is completely decoupled from this vma,
+        * we can drop its hold on the backing storage and allow it to be
+        * reaped by the shrinker.
+        */
+       i915_gem_object_unpin_pages(obj);
+
        return 0;
 }
 
@@ -3054,7 +3106,7 @@ i915_find_fence_reg(struct drm_device *dev)
        }
 
        if (avail == NULL)
-               return NULL;
+               goto deadlock;
 
        /* None available, try to steal one or wait for a user to finish */
        list_for_each_entry(reg, &dev_priv->mm.fence_list, lru_list) {
@@ -3064,7 +3116,12 @@ i915_find_fence_reg(struct drm_device *dev)
                return reg;
        }
 
-       return NULL;
+deadlock:
+       /* Wait for completion of pending flips which consume fences */
+       if (intel_has_pending_fb_unpin(dev))
+               return ERR_PTR(-EAGAIN);
+
+       return ERR_PTR(-EDEADLK);
 }
 
 /**
@@ -3109,8 +3166,8 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
                }
        } else if (enable) {
                reg = i915_find_fence_reg(dev);
-               if (reg == NULL)
-                       return -EDEADLK;
+               if (IS_ERR(reg))
+                       return PTR_ERR(reg);
 
                if (reg->obj) {
                        struct drm_i915_gem_object *old = reg->obj;
@@ -4165,6 +4222,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct i915_vma *vma, *next;
 
+       intel_runtime_pm_get(dev_priv);
+
        trace_i915_gem_object_destroy(obj);
 
        if (obj->phys_obj)
@@ -4209,6 +4268,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 
        kfree(obj->bit_17);
        i915_gem_object_free(obj);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
@@ -4465,7 +4526,13 @@ i915_gem_init_hw(struct drm_device *dev)
         * XXX: There was some w/a described somewhere suggesting loading
         * contexts before PPGTT.
         */
-       i915_gem_context_init(dev);
+       ret = i915_gem_context_init(dev);
+       if (ret) {
+               i915_gem_cleanup_ringbuffer(dev);
+               DRM_ERROR("Context initialization failed %d\n", ret);
+               return ret;
+       }
+
        if (dev_priv->mm.aliasing_ppgtt) {
                ret = dev_priv->mm.aliasing_ppgtt->enable(dev);
                if (ret) {
index 72a3df32292f79d88d1ba17dc8d620a24ad435ca..e08acaba540269736777a7f7758a88d97f2aa4b6 100644 (file)
@@ -247,36 +247,34 @@ err_destroy:
        return ret;
 }
 
-void i915_gem_context_init(struct drm_device *dev)
+int i915_gem_context_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
 
-       if (!HAS_HW_CONTEXTS(dev)) {
-               dev_priv->hw_contexts_disabled = true;
-               DRM_DEBUG_DRIVER("Disabling HW Contexts; old hardware\n");
-               return;
-       }
+       if (!HAS_HW_CONTEXTS(dev))
+               return 0;
 
        /* If called from reset, or thaw... we've been here already */
-       if (dev_priv->hw_contexts_disabled ||
-           dev_priv->ring[RCS].default_context)
-               return;
+       if (dev_priv->ring[RCS].default_context)
+               return 0;
 
        dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
 
        if (dev_priv->hw_context_size > (1<<20)) {
-               dev_priv->hw_contexts_disabled = true;
                DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
-               return;
+               return -E2BIG;
        }
 
-       if (create_default_context(dev_priv)) {
-               dev_priv->hw_contexts_disabled = true;
-               DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n");
-               return;
+       ret = create_default_context(dev_priv);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %d\n",
+                                ret);
+               return ret;
        }
 
        DRM_DEBUG_DRIVER("HW context support initialized\n");
+       return 0;
 }
 
 void i915_gem_context_fini(struct drm_device *dev)
@@ -284,7 +282,7 @@ void i915_gem_context_fini(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(dev))
                return;
 
        /* The only known way to stop the gpu from accessing the hw context is
@@ -327,16 +325,16 @@ i915_gem_context_get_hang_stats(struct drm_device *dev,
                                struct drm_file *file,
                                u32 id)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_file_private *file_priv = file->driver_priv;
        struct i915_hw_context *ctx;
 
        if (id == DEFAULT_CONTEXT_ID)
                return &file_priv->hang_stats;
 
-       ctx = NULL;
-       if (!dev_priv->hw_contexts_disabled)
-               ctx = i915_gem_context_get(file->driver_priv, id);
+       if (!HAS_HW_CONTEXTS(dev))
+               return ERR_PTR(-ENOENT);
+
+       ctx = i915_gem_context_get(file->driver_priv, id);
        if (ctx == NULL)
                return ERR_PTR(-ENOENT);
 
@@ -347,10 +345,8 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
 
-       mutex_lock(&dev->struct_mutex);
        idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
        idr_destroy(&file_priv->context_idr);
-       mutex_unlock(&dev->struct_mutex);
 }
 
 static struct i915_hw_context *
@@ -423,11 +419,21 @@ static int do_switch(struct i915_hw_context *to)
        if (ret)
                return ret;
 
-       /* Clear this page out of any CPU caches for coherent swap-in/out. Note
+       /*
+        * Pin can switch back to the default context if we end up calling into
+        * evict_everything - as a last ditch gtt defrag effort that also
+        * switches to the default context. Hence we need to reload from here.
+        */
+       from = ring->last_context;
+
+       /*
+        * Clear this page out of any CPU caches for coherent swap-in/out. Note
         * that thanks to write = false in this call and us not setting any gpu
         * write domains when putting a context object onto the active list
         * (when switching away from it), this won't block.
-        * XXX: We need a real interface to do this instead of trickery. */
+        *
+        * XXX: We need a real interface to do this instead of trickery.
+        */
        ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
        if (ret) {
                i915_gem_object_unpin(to->obj);
@@ -494,8 +500,6 @@ static int do_switch(struct i915_hw_context *to)
  * @ring: ring for which we'll execute the context switch
  * @file_priv: file_priv associated with the context, may be NULL
  * @id: context id number
- * @seqno: sequence number by which the new context will be switched to
- * @flags:
  *
  * The context life cycle is simple. The context refcount is incremented and
  * decremented by 1 and create and destroy. If the context is in use by the GPU,
@@ -509,7 +513,7 @@ int i915_switch_context(struct intel_ring_buffer *ring,
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
        struct i915_hw_context *to;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(ring->dev))
                return 0;
 
        WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
@@ -534,7 +538,6 @@ int i915_switch_context(struct intel_ring_buffer *ring,
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_context_create *args = data;
        struct drm_i915_file_private *file_priv = file->driver_priv;
        struct i915_hw_context *ctx;
@@ -543,7 +546,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
        if (!(dev->driver->driver_features & DRIVER_GEM))
                return -ENODEV;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(dev))
                return -ENODEV;
 
        ret = i915_mutex_lock_interruptible(dev);
index b7376533633d2cd74eeae8442a49588cf1af1cdc..2ca280f9ee53e3f6f6422fcc3605fa86b2f52afa 100644 (file)
  */
 
 #include <drm/drmP.h>
-#include "i915_drv.h"
 #include <drm/i915_drm.h>
+
+#include "i915_drv.h"
+#include "intel_drv.h"
 #include "i915_trace.h"
 
 static bool
@@ -53,6 +55,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
        struct list_head eviction_list, unwind_list;
        struct i915_vma *vma;
        int ret = 0;
+       int pass = 0;
 
        trace_i915_gem_evict(dev, min_size, alignment, mappable);
 
@@ -88,6 +91,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
        } else
                drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level);
 
+search_again:
        /* First see if there is a large enough contiguous idle region... */
        list_for_each_entry(vma, &vm->inactive_list, mm_list) {
                if (mark_free(vma, &unwind_list))
@@ -115,10 +119,27 @@ none:
                list_del_init(&vma->exec_list);
        }
 
-       /* We expect the caller to unpin, evict all and try again, or give up.
-        * So calling i915_gem_evict_vm() is unnecessary.
+       /* Can we unpin some objects such as idle hw contents,
+        * or pending flips?
+        */
+       if (nonblocking)
+               return -ENOSPC;
+
+       /* Only idle the GPU and repeat the search once */
+       if (pass++ == 0) {
+               ret = i915_gpu_idle(dev);
+               if (ret)
+                       return ret;
+
+               i915_gem_retire_requests(dev);
+               goto search_again;
+       }
+
+       /* If we still have pending pageflip completions, drop
+        * back to userspace to give our workqueues time to
+        * acquire our locks and unpin the old scanouts.
         */
-       return -ENOSPC;
+       return intel_has_pending_fb_unpin(dev) ? -EAGAIN : -ENOSPC;
 
 found:
        /* drm_mm doesn't allow any other other operations while
index b7e787fb4649321cd67d7456aef11af861757aac..d269ecf46e264cbaaef6c9e1db6ddcfb57f1424d 100644 (file)
@@ -46,7 +46,7 @@ struct eb_vmas {
 };
 
 static struct eb_vmas *
-eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm)
+eb_create(struct drm_i915_gem_execbuffer2 *args)
 {
        struct eb_vmas *eb = NULL;
 
@@ -93,7 +93,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
 {
        struct drm_i915_gem_object *obj;
        struct list_head objects;
-       int i, ret = 0;
+       int i, ret;
 
        INIT_LIST_HEAD(&objects);
        spin_lock(&file->table_lock);
@@ -106,7 +106,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Invalid object handle %d at index %d\n",
                                   exec[i].handle, i);
                        ret = -ENOENT;
-                       goto out;
+                       goto err;
                }
 
                if (!list_empty(&obj->obj_exec_link)) {
@@ -114,7 +114,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n",
                                   obj, exec[i].handle, i);
                        ret = -EINVAL;
-                       goto out;
+                       goto err;
                }
 
                drm_gem_object_reference(&obj->base);
@@ -123,9 +123,13 @@ eb_lookup_vmas(struct eb_vmas *eb,
        spin_unlock(&file->table_lock);
 
        i = 0;
-       list_for_each_entry(obj, &objects, obj_exec_link) {
+       while (!list_empty(&objects)) {
                struct i915_vma *vma;
 
+               obj = list_first_entry(&objects,
+                                      struct drm_i915_gem_object,
+                                      obj_exec_link);
+
                /*
                 * NOTE: We can leak any vmas created here when something fails
                 * later on. But that's no issue since vma_unbind can deal with
@@ -138,10 +142,12 @@ eb_lookup_vmas(struct eb_vmas *eb,
                if (IS_ERR(vma)) {
                        DRM_DEBUG("Failed to lookup VMA\n");
                        ret = PTR_ERR(vma);
-                       goto out;
+                       goto err;
                }
 
+               /* Transfer ownership from the objects list to the vmas list. */
                list_add_tail(&vma->exec_list, &eb->vmas);
+               list_del_init(&obj->obj_exec_link);
 
                vma->exec_entry = &exec[i];
                if (eb->and < 0) {
@@ -155,16 +161,22 @@ eb_lookup_vmas(struct eb_vmas *eb,
                ++i;
        }
 
+       return 0;
 
-out:
+
+err:
        while (!list_empty(&objects)) {
                obj = list_first_entry(&objects,
                                       struct drm_i915_gem_object,
                                       obj_exec_link);
                list_del_init(&obj->obj_exec_link);
-               if (ret)
-                       drm_gem_object_unreference(&obj->base);
+               drm_gem_object_unreference(&obj->base);
        }
+       /*
+        * Objects already transfered to the vmas list will be unreferenced by
+        * eb_destroy.
+        */
+
        return ret;
 }
 
@@ -240,7 +252,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj,
        struct drm_device *dev = obj->base.dev;
        uint32_t page_offset = offset_in_page(reloc->offset);
        char *vaddr;
-       int ret = -EINVAL;
+       int ret;
 
        ret = i915_gem_object_set_to_cpu_domain(obj, true);
        if (ret)
@@ -275,7 +287,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t __iomem *reloc_entry;
        void __iomem *reloc_page;
-       int ret = -EINVAL;
+       int ret;
 
        ret = i915_gem_object_set_to_gtt_domain(obj, true);
        if (ret)
@@ -323,7 +335,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
        struct drm_i915_gem_object *target_i915_obj;
        struct i915_vma *target_vma;
        uint32_t target_offset;
-       int ret = -EINVAL;
+       int ret;
 
        /* we've already hold a reference to all valid objects */
        target_vma = eb_get_vma(eb, reloc->target_handle);
@@ -332,7 +344,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
        target_i915_obj = target_vma->obj;
        target_obj = &target_vma->obj->base;
 
-       target_offset = i915_gem_obj_ggtt_offset(target_i915_obj);
+       target_offset = target_vma->node.start;
 
        /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
         * pipe_control writes because the gpu doesn't properly redirect them
@@ -353,7 +365,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
                          (int) reloc->offset,
                          reloc->read_domains,
                          reloc->write_domain);
-               return ret;
+               return -EINVAL;
        }
        if (unlikely((reloc->write_domain | reloc->read_domains)
                     & ~I915_GEM_GPU_DOMAINS)) {
@@ -364,7 +376,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
                          (int) reloc->offset,
                          reloc->read_domains,
                          reloc->write_domain);
-               return ret;
+               return -EINVAL;
        }
 
        target_obj->pending_read_domains |= reloc->read_domains;
@@ -384,14 +396,14 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
                          obj, reloc->target_handle,
                          (int) reloc->offset,
                          (int) obj->base.size);
-               return ret;
+               return -EINVAL;
        }
        if (unlikely(reloc->offset & 3)) {
                DRM_DEBUG("Relocation not 4-byte aligned: "
                          "obj %p target %d offset %d.\n",
                          obj, reloc->target_handle,
                          (int) reloc->offset);
-               return ret;
+               return -EINVAL;
        }
 
        /* We can't wait for rendering with pagefaults disabled */
@@ -479,8 +491,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma,
 }
 
 static int
-i915_gem_execbuffer_relocate(struct eb_vmas *eb,
-                            struct i915_address_space *vm)
+i915_gem_execbuffer_relocate(struct eb_vmas *eb)
 {
        struct i915_vma *vma;
        int ret = 0;
@@ -889,6 +900,24 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
        return 0;
 }
 
+static int
+i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
+                         const u32 ctx_id)
+{
+       struct i915_ctx_hang_stats *hs;
+
+       hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
+       if (IS_ERR(hs))
+               return PTR_ERR(hs);
+
+       if (hs->banned) {
+               DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static void
 i915_gem_execbuffer_move_to_active(struct list_head *vmas,
                                   struct intel_ring_buffer *ring)
@@ -968,8 +997,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        struct drm_i915_gem_object *batch_obj;
        struct drm_clip_rect *cliprects = NULL;
        struct intel_ring_buffer *ring;
-       struct i915_ctx_hang_stats *hs;
-       u32 ctx_id = i915_execbuffer2_get_context_id(*args);
+       const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
        u32 exec_start, exec_len;
        u32 mask, flags;
        int ret, mode, i;
@@ -1096,6 +1124,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                }
        }
 
+       intel_runtime_pm_get(dev_priv);
+
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                goto pre_mutex_err;
@@ -1106,7 +1136,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                goto pre_mutex_err;
        }
 
-       eb = eb_create(args, vm);
+       ret = i915_gem_validate_context(dev, file, ctx_id);
+       if (ret) {
+               mutex_unlock(&dev->struct_mutex);
+               goto pre_mutex_err;
+       }
+
+       eb = eb_create(args);
        if (eb == NULL) {
                mutex_unlock(&dev->struct_mutex);
                ret = -ENOMEM;
@@ -1129,7 +1165,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
        /* The objects are in their final locations, apply the relocations. */
        if (need_relocs)
-               ret = i915_gem_execbuffer_relocate(eb, vm);
+               ret = i915_gem_execbuffer_relocate(eb);
        if (ret) {
                if (ret == -EFAULT) {
                        ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
@@ -1158,17 +1194,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        if (ret)
                goto err;
 
-       hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
-       if (IS_ERR(hs)) {
-               ret = PTR_ERR(hs);
-               goto err;
-       }
-
-       if (hs->banned) {
-               ret = -EIO;
-               goto err;
-       }
-
        ret = i915_switch_context(ring, file, ctx_id);
        if (ret)
                goto err;
@@ -1230,6 +1255,10 @@ err:
 
 pre_mutex_err:
        kfree(cliprects);
+
+       /* intel_gpu_busy should also get a ref, so it will free when the device
+        * is really idle. */
+       intel_runtime_pm_put(dev_priv);
        return ret;
 }
 
index 38cb8d44a0133a6c096524a553d45fcb33cd72a1..6c3a6e60aeac1eba0a7b2339683a201e1e1a2bbd 100644 (file)
@@ -240,10 +240,16 @@ static int gen8_ppgtt_enable(struct drm_device *dev)
                for_each_ring(ring, dev_priv, j) {
                        ret = gen8_write_pdp(ring, i, addr);
                        if (ret)
-                               return ret;
+                               goto err_out;
                }
        }
        return 0;
+
+err_out:
+       for_each_ring(ring, dev_priv, j)
+               I915_WRITE(RING_MODE_GEN7(ring),
+                          _MASKED_BIT_DISABLE(GFX_PPGTT_ENABLE));
+       return ret;
 }
 
 static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
@@ -293,23 +299,23 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
        unsigned act_pte = first_entry % GEN8_PTES_PER_PAGE;
        struct sg_page_iter sg_iter;
 
-       pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]);
+       pt_vaddr = NULL;
        for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
-               dma_addr_t page_addr;
+               if (pt_vaddr == NULL)
+                       pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]);
 
-               page_addr = sg_dma_address(sg_iter.sg) +
-                               (sg_iter.sg_pgoffset << PAGE_SHIFT);
-               pt_vaddr[act_pte] = gen8_pte_encode(page_addr, cache_level,
-                                                   true);
+               pt_vaddr[act_pte] =
+                       gen8_pte_encode(sg_page_iter_dma_address(&sg_iter),
+                                       cache_level, true);
                if (++act_pte == GEN8_PTES_PER_PAGE) {
                        kunmap_atomic(pt_vaddr);
+                       pt_vaddr = NULL;
                        act_pt++;
-                       pt_vaddr = kmap_atomic(&ppgtt->gen8_pt_pages[act_pt]);
                        act_pte = 0;
-
                }
        }
-       kunmap_atomic(pt_vaddr);
+       if (pt_vaddr)
+               kunmap_atomic(pt_vaddr);
 }
 
 static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
@@ -318,6 +324,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
                container_of(vm, struct i915_hw_ppgtt, base);
        int i, j;
 
+       drm_mm_takedown(&vm->mm);
+
        for (i = 0; i < ppgtt->num_pd_pages ; i++) {
                if (ppgtt->pd_dma_addr[i]) {
                        pci_unmap_page(ppgtt->base.dev->pdev,
@@ -337,8 +345,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
                kfree(ppgtt->gen8_pt_dma_addr[i]);
        }
 
-       __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT);
-       __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT);
+       __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
+       __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
 }
 
 /**
@@ -381,6 +389,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
        ppgtt->base.clear_range = gen8_ppgtt_clear_range;
        ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
        ppgtt->base.cleanup = gen8_ppgtt_cleanup;
+       ppgtt->base.start = 0;
+       ppgtt->base.total = ppgtt->num_pt_pages * GEN8_PTES_PER_PAGE * PAGE_SIZE;
 
        BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS);
 
@@ -573,21 +583,23 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
        unsigned act_pte = first_entry % I915_PPGTT_PT_ENTRIES;
        struct sg_page_iter sg_iter;
 
-       pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
+       pt_vaddr = NULL;
        for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
-               dma_addr_t page_addr;
+               if (pt_vaddr == NULL)
+                       pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
 
-               page_addr = sg_page_iter_dma_address(&sg_iter);
-               pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level, true);
+               pt_vaddr[act_pte] =
+                       vm->pte_encode(sg_page_iter_dma_address(&sg_iter),
+                                      cache_level, true);
                if (++act_pte == I915_PPGTT_PT_ENTRIES) {
                        kunmap_atomic(pt_vaddr);
+                       pt_vaddr = NULL;
                        act_pt++;
-                       pt_vaddr = kmap_atomic(ppgtt->pt_pages[act_pt]);
                        act_pte = 0;
-
                }
        }
-       kunmap_atomic(pt_vaddr);
+       if (pt_vaddr)
+               kunmap_atomic(pt_vaddr);
 }
 
 static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
@@ -632,6 +644,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
        ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
        ppgtt->base.cleanup = gen6_ppgtt_cleanup;
        ppgtt->base.scratch = dev_priv->gtt.base.scratch;
+       ppgtt->base.start = 0;
+       ppgtt->base.total = GEN6_PPGTT_PD_ENTRIES * I915_PPGTT_PT_ENTRIES * PAGE_SIZE;
        ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *),
                                  GFP_KERNEL);
        if (!ppgtt->pt_pages)
@@ -906,14 +920,12 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
                WARN_ON(readq(&gtt_entries[i-1])
                        != gen8_pte_encode(addr, level, true));
 
-#if 0 /* TODO: Still needed on GEN8? */
        /* This next bit makes the above posting read even more important. We
         * want to flush the TLBs only after we're certain all the PTE updates
         * have finished.
         */
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
-#endif
 }
 
 /*
@@ -1126,7 +1138,6 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
                if (ret)
                        DRM_DEBUG_KMS("Reservation failed\n");
                obj->has_global_gtt_mapping = 1;
-               list_add(&vma->vma_link, &obj->vma_list);
        }
 
        dev_priv->gtt.base.start = start;
@@ -1241,6 +1252,11 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
        bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK;
        if (bdw_gmch_ctl)
                bdw_gmch_ctl = 1 << bdw_gmch_ctl;
+       if (bdw_gmch_ctl > 4) {
+               WARN_ON(!i915_preliminary_hw_support);
+               return 4<<20;
+       }
+
        return bdw_gmch_ctl << 20;
 }
 
@@ -1397,6 +1413,8 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
 {
 
        struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
+
+       drm_mm_takedown(&vm->mm);
        iounmap(gtt->gsm);
        teardown_scratch_page(vm->dev);
 }
@@ -1422,6 +1440,9 @@ static int i915_gmch_probe(struct drm_device *dev,
        dev_priv->gtt.base.clear_range = i915_ggtt_clear_range;
        dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries;
 
+       if (unlikely(dev_priv->gtt.do_idle_maps))
+               DRM_INFO("applying Ironlake quirks for intel_iommu\n");
+
        return 0;
 }
 
index d284d892ed9491e8f2a618e22576673e06887f74..1a24e84f231578ae772d40ad75adda4c356b8d68 100644 (file)
@@ -250,7 +250,7 @@ i915_pages_create_for_stolen(struct drm_device *dev,
        }
 
        sg = st->sgl;
-       sg->offset = offset;
+       sg->offset = 0;
        sg->length = size;
 
        sg_dma_address(sg) = (dma_addr_t)dev_priv->mm.stolen_base + offset;
@@ -420,6 +420,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
 
        list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
        list_add_tail(&vma->mm_list, &ggtt->inactive_list);
+       i915_gem_object_pin_pages(obj);
 
        return obj;
 
index 79dcb8f896c6f34363e6bd62e90f1773bfcf8f0a..d7fd2fd2f0a5e1ba6ed25f9a4dce0c20dc03b9e3 100644 (file)
@@ -239,6 +239,9 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
                                  unsigned ring)
 {
        BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
+       if (!error->ring[ring].valid)
+               return;
+
        err_printf(m, "%s command stream:\n", ring_str(ring));
        err_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
        err_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
@@ -247,12 +250,11 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
        err_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
        err_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
        err_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
-       if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
-               err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr);
-       if (INTEL_INFO(dev)->gen >= 4)
+       if (INTEL_INFO(dev)->gen >= 4) {
+               err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr[ring]);
                err_printf(m, "  BB_STATE: 0x%08x\n", error->bbstate[ring]);
-       if (INTEL_INFO(dev)->gen >= 4)
                err_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
+       }
        err_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
        err_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
        if (INTEL_INFO(dev)->gen >= 6) {
@@ -294,7 +296,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
        struct drm_device *dev = error_priv->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_error_state *error = error_priv->error;
-       struct intel_ring_buffer *ring;
        int i, j, page, offset, elt;
 
        if (!error) {
@@ -329,7 +330,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
        if (INTEL_INFO(dev)->gen == 7)
                err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
 
-       for_each_ring(ring, dev_priv, i)
+       for (i = 0; i < ARRAY_SIZE(error->ring); i++)
                i915_ring_error_state(m, dev, error, i);
 
        if (error->active_bo)
@@ -386,8 +387,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
                        }
                }
 
-               obj = error->ring[i].ctx;
-               if (obj) {
+               if ((obj = error->ring[i].ctx)) {
                        err_printf(m, "%s --- HW Context = 0x%08x\n",
                                   dev_priv->ring[i].name,
                                   obj->gtt_offset);
@@ -668,7 +668,8 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
                        return NULL;
 
                obj = ring->scratch.obj;
-               if (acthd >= i915_gem_obj_ggtt_offset(obj) &&
+               if (obj != NULL &&
+                   acthd >= i915_gem_obj_ggtt_offset(obj) &&
                    acthd < i915_gem_obj_ggtt_offset(obj) + obj->base.size)
                        return i915_error_object_create(dev_priv, obj);
        }
@@ -725,8 +726,9 @@ static void i915_record_ring_state(struct drm_device *dev,
                error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
                error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
                error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
-               if (ring->id == RCS)
-                       error->bbaddr = I915_READ64(BB_ADDR);
+               error->bbaddr[ring->id] = I915_READ(RING_BBADDR(ring->mmio_base));
+               if (INTEL_INFO(dev)->gen >= 8)
+                       error->bbaddr[ring->id] |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
                error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base));
        } else {
                error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
@@ -775,11 +777,17 @@ static void i915_gem_record_rings(struct drm_device *dev,
                                  struct drm_i915_error_state *error)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_ring_buffer *ring;
        struct drm_i915_gem_request *request;
        int i, count;
 
-       for_each_ring(ring, dev_priv, i) {
+       for (i = 0; i < I915_NUM_RINGS; i++) {
+               struct intel_ring_buffer *ring = &dev_priv->ring[i];
+
+               if (ring->dev == NULL)
+                       continue;
+
+               error->ring[i].valid = true;
+
                i915_record_ring_state(dev, error, ring);
 
                error->ring[i].batchbuffer =
index 5d1dedc02f159c8b7a21d23a940df9c5bf0c2bd2..17d8fcb1b6f7ac113b4c0c035088979b1c8083b4 100644 (file)
@@ -62,7 +62,7 @@ static const u32 hpd_mask_i915[] = {
        [HPD_PORT_D] = PORTD_HOTPLUG_INT_EN
 };
 
-static const u32 hpd_status_gen4[] = {
+static const u32 hpd_status_g4x[] = {
        [HPD_CRT] = CRT_HOTPLUG_INT_STATUS,
        [HPD_SDVO_B] = SDVOB_HOTPLUG_INT_STATUS_G4X,
        [HPD_SDVO_C] = SDVOC_HOTPLUG_INT_STATUS_G4X,
@@ -600,7 +600,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
         * Cook up a vblank counter by also checking the pixel
         * counter against vblank start.
         */
-       return ((high1 << 8) | low) + (pixel >= vbl_start);
+       return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff;
 }
 
 static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
@@ -621,36 +621,15 @@ static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
 #define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
 #define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__))
 
-static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
+static bool ilk_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t status;
-       int reg;
 
-       if (IS_VALLEYVIEW(dev)) {
-               status = pipe == PIPE_A ?
-                       I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
-                       I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-
-               reg = VLV_ISR;
-       } else if (IS_GEN2(dev)) {
-               status = pipe == PIPE_A ?
-                       I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
-                       I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-
-               reg = ISR;
-       } else if (INTEL_INFO(dev)->gen < 5) {
-               status = pipe == PIPE_A ?
-                       I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
-                       I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
-
-               reg = ISR;
-       } else if (INTEL_INFO(dev)->gen < 7) {
+       if (INTEL_INFO(dev)->gen < 7) {
                status = pipe == PIPE_A ?
                        DE_PIPEA_VBLANK :
                        DE_PIPEB_VBLANK;
-
-               reg = DEISR;
        } else {
                switch (pipe) {
                default:
@@ -664,18 +643,14 @@ static bool intel_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
                        status = DE_PIPEC_VBLANK_IVB;
                        break;
                }
-
-               reg = DEISR;
        }
 
-       if (IS_GEN2(dev))
-               return __raw_i915_read16(dev_priv, reg) & status;
-       else
-               return __raw_i915_read32(dev_priv, reg) & status;
+       return __raw_i915_read32(dev_priv, DEISR) & status;
 }
 
 static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
-                            int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
+                                   unsigned int flags, int *vpos, int *hpos,
+                                   ktime_t *stime, ktime_t *etime)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
@@ -698,6 +673,12 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
        vbl_start = mode->crtc_vblank_start;
        vbl_end = mode->crtc_vblank_end;
 
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               vbl_start = DIV_ROUND_UP(vbl_start, 2);
+               vbl_end /= 2;
+               vtotal /= 2;
+       }
+
        ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
 
        /*
@@ -722,17 +703,42 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
                else
                        position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
 
-               /*
-                * The scanline counter increments at the leading edge
-                * of hsync, ie. it completely misses the active portion
-                * of the line. Fix up the counter at both edges of vblank
-                * to get a more accurate picture whether we're in vblank
-                * or not.
-                */
-               in_vbl = intel_pipe_in_vblank_locked(dev, pipe);
-               if ((in_vbl && position == vbl_start - 1) ||
-                   (!in_vbl && position == vbl_end - 1))
-                       position = (position + 1) % vtotal;
+               if (HAS_PCH_SPLIT(dev)) {
+                       /*
+                        * The scanline counter increments at the leading edge
+                        * of hsync, ie. it completely misses the active portion
+                        * of the line. Fix up the counter at both edges of vblank
+                        * to get a more accurate picture whether we're in vblank
+                        * or not.
+                        */
+                       in_vbl = ilk_pipe_in_vblank_locked(dev, pipe);
+                       if ((in_vbl && position == vbl_start - 1) ||
+                           (!in_vbl && position == vbl_end - 1))
+                               position = (position + 1) % vtotal;
+               } else {
+                       /*
+                        * ISR vblank status bits don't work the way we'd want
+                        * them to work on non-PCH platforms (for
+                        * ilk_pipe_in_vblank_locked()), and there doesn't
+                        * appear any other way to determine if we're currently
+                        * in vblank.
+                        *
+                        * Instead let's assume that we're already in vblank if
+                        * we got called from the vblank interrupt and the
+                        * scanline counter value indicates that we're on the
+                        * line just prior to vblank start. This should result
+                        * in the correct answer, unless the vblank interrupt
+                        * delivery really got delayed for almost exactly one
+                        * full frame/field.
+                        */
+                       if (flags & DRM_CALLED_FROM_VBLIRQ &&
+                           position == vbl_start - 1) {
+                               position = (position + 1) % vtotal;
+
+                               /* Signal this correction as "applied". */
+                               ret |= 0x8;
+                       }
+               }
        } else {
                /* Have access to pixelcount since start of frame.
                 * We can split this into vertical and horizontal
@@ -809,7 +815,8 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
        /* Helper routine in DRM core does all the work: */
        return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
                                                     vblank_time, flags,
-                                                    crtc);
+                                                    crtc,
+                                                    &to_intel_crtc(crtc)->config.adjusted_mode);
 }
 
 static bool intel_hpd_irq_event(struct drm_device *dev,
@@ -1015,10 +1022,8 @@ static void gen6_pm_rps_work(struct work_struct *work)
        /* sysfs frequency interfaces may have snuck in while servicing the
         * interrupt
         */
-       if (new_delay < (int)dev_priv->rps.min_delay)
-               new_delay = dev_priv->rps.min_delay;
-       if (new_delay > (int)dev_priv->rps.max_delay)
-               new_delay = dev_priv->rps.max_delay;
+       new_delay = clamp_t(int, new_delay,
+                           dev_priv->rps.min_delay, dev_priv->rps.max_delay);
        dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
 
        if (IS_VALLEYVIEW(dev_priv->dev))
@@ -1235,9 +1240,10 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
        spin_lock(&dev_priv->irq_lock);
        for (i = 1; i < HPD_NUM_PINS; i++) {
 
-               WARN(((hpd[i] & hotplug_trigger) &&
-                     dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED),
-                    "Received HPD interrupt although disabled\n");
+               WARN_ONCE(hpd[i] & hotplug_trigger &&
+                         dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED,
+                         "Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n",
+                         hotplug_trigger, i, hpd[i]);
 
                if (!(hpd[i] & hotplug_trigger) ||
                    dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
@@ -1474,6 +1480,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 
                        intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
 
+                       if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
+                               dp_aux_irq_handler(dev);
+
                        I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
                        I915_READ(PORT_HOTPLUG_STAT);
                }
@@ -1993,7 +2002,7 @@ static void i915_error_work_func(struct work_struct *work)
                        kobject_uevent_env(&dev->primary->kdev->kobj,
                                           KOBJ_CHANGE, reset_done_event);
                } else {
-                       atomic_set(&error->reset_counter, I915_WEDGED);
+                       atomic_set_mask(I915_WEDGED, &error->reset_counter);
                }
 
                /*
@@ -2713,6 +2722,8 @@ static void gen8_irq_preinstall(struct drm_device *dev)
 #undef GEN8_IRQ_INIT_NDX
 
        POSTING_READ(GEN8_PCU_IIR);
+
+       ibx_irq_preinstall(dev);
 }
 
 static void ibx_hpd_irq_setup(struct drm_device *dev)
@@ -3138,10 +3149,10 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
  * Returns true when a page flip has completed.
  */
 static bool i8xx_handle_vblank(struct drm_device *dev,
-                              int pipe, u16 iir)
+                              int plane, int pipe, u32 iir)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe);
+       u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
 
        if (!drm_handle_vblank(dev, pipe))
                return false;
@@ -3149,7 +3160,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev,
        if ((iir & flip_pending) == 0)
                return false;
 
-       intel_prepare_page_flip(dev, pipe);
+       intel_prepare_page_flip(dev, plane);
 
        /* We detect FlipDone by looking for the change in PendingFlip from '1'
         * to '0' on the following vblank, i.e. IIR has the Pendingflip
@@ -3218,9 +3229,13 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
                        notify_ring(dev, &dev_priv->ring[RCS]);
 
                for_each_pipe(pipe) {
+                       int plane = pipe;
+                       if (HAS_FBC(dev))
+                               plane = !plane;
+
                        if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
-                           i8xx_handle_vblank(dev, pipe, iir))
-                               flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
+                           i8xx_handle_vblank(dev, plane, pipe, iir))
+                               flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
 
                        if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
                                i9xx_pipe_crc_irq_handler(dev, pipe);
@@ -3416,7 +3431,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 
                for_each_pipe(pipe) {
                        int plane = pipe;
-                       if (IS_MOBILE(dev))
+                       if (HAS_FBC(dev))
                                plane = !plane;
 
                        if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
@@ -3653,7 +3668,11 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
                                  hotplug_status);
 
                        intel_hpd_irq_handler(dev, hotplug_trigger,
-                                             IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i915);
+                                             IS_G4X(dev) ? hpd_status_g4x : hpd_status_i915);
+
+                       if (IS_G4X(dev) &&
+                           (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X))
+                               dp_aux_irq_handler(dev);
 
                        I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
                        I915_READ(PORT_HOTPLUG_STAT);
@@ -3891,8 +3910,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev)
        dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
        dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
 
-       ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
-       ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
+       ironlake_disable_display_irq(dev_priv, 0xffffffff);
+       ibx_disable_display_interrupt(dev_priv, 0xffffffff);
        ilk_disable_gt_irq(dev_priv, 0xffffffff);
        snb_disable_pm_irq(dev_priv, 0xffffffff);
 
@@ -3906,34 +3925,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
-       uint32_t val, expected;
+       uint32_t val;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
        val = I915_READ(DEIMR);
-       expected = ~DE_PCH_EVENT_IVB;
-       WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
+       WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
 
-       val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
-       expected = ~SDE_HOTPLUG_MASK_CPT;
-       WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
-            val, expected);
+       val = I915_READ(SDEIMR);
+       WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
 
        val = I915_READ(GTIMR);
-       expected = 0xffffffff;
-       WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
+       WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
 
        val = I915_READ(GEN6_PMIMR);
-       expected = 0xffffffff;
-       WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
-            expected);
+       WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
 
        dev_priv->pc8.irqs_disabled = false;
 
        ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
-       ibx_enable_display_interrupt(dev_priv,
-                                    ~dev_priv->pc8.regsave.sdeimr &
-                                    ~SDE_HOTPLUG_MASK_CPT);
+       ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
        ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
        snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
        I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
index ee2742122a02561f910b6d9d5383418794234eff..a48b7cad6f1135c29742f39cacf23e359f92faf4 100644 (file)
 #define   MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
 #define   MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
 #define   MI_INVALIDATE_ISP    (1 << 5) /* invalidate indirect state pointers */
+#define MI_REPORT_HEAD         MI_INSTR(0x07, 0)
+#define MI_ARB_ON_OFF          MI_INSTR(0x08, 0)
+#define   MI_ARB_ENABLE                        (1<<0)
+#define   MI_ARB_DISABLE               (0<<0)
 #define MI_BATCH_BUFFER_END    MI_INSTR(0x0a, 0)
 #define MI_SUSPEND_FLUSH       MI_INSTR(0x0b, 0)
 #define   MI_SUSPEND_FLUSH_EN  (1<<0)
-#define MI_REPORT_HEAD         MI_INSTR(0x07, 0)
 #define MI_OVERLAY_FLIP                MI_INSTR(0x11, 0)
 #define   MI_OVERLAY_CONTINUE  (0x0<<21)
 #define   MI_OVERLAY_ON                (0x1<<21)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
 #define   MI_DISPLAY_FLIP_IVB_PLANE_C  (4 << 19)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
-#define MI_ARB_ON_OFF          MI_INSTR(0x08, 0)
-#define   MI_ARB_ENABLE                        (1<<0)
-#define   MI_ARB_DISABLE               (0<<0)
-
+#define MI_SEMAPHORE_MBOX      MI_INSTR(0x16, 1) /* gen6+ */
+#define   MI_SEMAPHORE_GLOBAL_GTT    (1<<22)
+#define   MI_SEMAPHORE_UPDATE      (1<<21)
+#define   MI_SEMAPHORE_COMPARE     (1<<20)
+#define   MI_SEMAPHORE_REGISTER            (1<<18)
+#define   MI_SEMAPHORE_SYNC_VR     (0<<16) /* RCS  wait for VCS  (RVSYNC) */
+#define   MI_SEMAPHORE_SYNC_VER            (1<<16) /* RCS  wait for VECS (RVESYNC) */
+#define   MI_SEMAPHORE_SYNC_BR     (2<<16) /* RCS  wait for BCS  (RBSYNC) */
+#define   MI_SEMAPHORE_SYNC_BV     (0<<16) /* VCS  wait for BCS  (VBSYNC) */
+#define   MI_SEMAPHORE_SYNC_VEV            (1<<16) /* VCS  wait for VECS (VVESYNC) */
+#define   MI_SEMAPHORE_SYNC_RV     (2<<16) /* VCS  wait for RCS  (VRSYNC) */
+#define   MI_SEMAPHORE_SYNC_RB     (0<<16) /* BCS  wait for RCS  (BRSYNC) */
+#define   MI_SEMAPHORE_SYNC_VEB            (1<<16) /* BCS  wait for VECS (BVESYNC) */
+#define   MI_SEMAPHORE_SYNC_VB     (2<<16) /* BCS  wait for VCS  (BVSYNC) */
+#define   MI_SEMAPHORE_SYNC_BVE            (0<<16) /* VECS wait for BCS  (VEBSYNC) */
+#define   MI_SEMAPHORE_SYNC_VVE            (1<<16) /* VECS wait for VCS  (VEVSYNC) */
+#define   MI_SEMAPHORE_SYNC_RVE            (2<<16) /* VECS wait for RCS  (VERSYNC) */
+#define   MI_SEMAPHORE_SYNC_INVALID  (3<<16)
 #define MI_SET_CONTEXT         MI_INSTR(0x18, 0)
 #define   MI_MM_SPACE_GTT              (1<<8)
 #define   MI_MM_SPACE_PHYSICAL         (0<<8)
  */
 #define MI_LOAD_REGISTER_IMM(x)        MI_INSTR(0x22, 2*x-1)
 #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1)
-#define  MI_SRM_LRM_GLOBAL_GTT         (1<<22)
+#define   MI_SRM_LRM_GLOBAL_GTT                (1<<22)
 #define MI_FLUSH_DW            MI_INSTR(0x26, 1) /* for GEN6 */
 #define   MI_FLUSH_DW_STORE_INDEX      (1<<21)
 #define   MI_INVALIDATE_TLB            (1<<18)
 #define MI_BATCH_BUFFER                MI_INSTR(0x30, 1)
 #define   MI_BATCH_NON_SECURE          (1)
 /* for snb/ivb/vlv this also means "batch in ppgtt" when ppgtt is enabled. */
-#define   MI_BATCH_NON_SECURE_I965     (1<<8)
+#define   MI_BATCH_NON_SECURE_I965     (1<<8)
 #define   MI_BATCH_PPGTT_HSW           (1<<8)
-#define   MI_BATCH_NON_SECURE_HSW      (1<<13)
+#define   MI_BATCH_NON_SECURE_HSW      (1<<13)
 #define MI_BATCH_BUFFER_START  MI_INSTR(0x31, 0)
 #define   MI_BATCH_GTT             (2<<6) /* aliased with (1<<7) on gen4 */
 #define MI_BATCH_BUFFER_START_GEN8     MI_INSTR(0x31, 1)
-#define MI_SEMAPHORE_MBOX      MI_INSTR(0x16, 1) /* gen6+ */
-#define  MI_SEMAPHORE_GLOBAL_GTT    (1<<22)
-#define  MI_SEMAPHORE_UPDATE       (1<<21)
-#define  MI_SEMAPHORE_COMPARE      (1<<20)
-#define  MI_SEMAPHORE_REGISTER     (1<<18)
-#define  MI_SEMAPHORE_SYNC_VR      (0<<16) /* RCS  wait for VCS  (RVSYNC) */
-#define  MI_SEMAPHORE_SYNC_VER     (1<<16) /* RCS  wait for VECS (RVESYNC) */
-#define  MI_SEMAPHORE_SYNC_BR      (2<<16) /* RCS  wait for BCS  (RBSYNC) */
-#define  MI_SEMAPHORE_SYNC_BV      (0<<16) /* VCS  wait for BCS  (VBSYNC) */
-#define  MI_SEMAPHORE_SYNC_VEV     (1<<16) /* VCS  wait for VECS (VVESYNC) */
-#define  MI_SEMAPHORE_SYNC_RV      (2<<16) /* VCS  wait for RCS  (VRSYNC) */
-#define  MI_SEMAPHORE_SYNC_RB      (0<<16) /* BCS  wait for RCS  (BRSYNC) */
-#define  MI_SEMAPHORE_SYNC_VEB     (1<<16) /* BCS  wait for VECS (BVESYNC) */
-#define  MI_SEMAPHORE_SYNC_VB      (2<<16) /* BCS  wait for VCS  (BVSYNC) */
-#define  MI_SEMAPHORE_SYNC_BVE     (0<<16) /* VECS wait for BCS  (VEBSYNC) */
-#define  MI_SEMAPHORE_SYNC_VVE     (1<<16) /* VECS wait for VCS  (VEVSYNC) */
-#define  MI_SEMAPHORE_SYNC_RVE     (2<<16) /* VECS wait for RCS  (VERSYNC) */
-#define  MI_SEMAPHORE_SYNC_INVALID  (3<<16)
+
 
 #define MI_PREDICATE_RESULT_2  (0x2214)
 #define  LOWER_SLICE_ENABLED   (1<<0)
 #define   IOSF_BYTE_ENABLES_SHIFT              4
 #define   IOSF_BAR_SHIFT                       1
 #define   IOSF_SB_BUSY                         (1<<0)
+#define   IOSF_PORT_BUNIT                      0x3
 #define   IOSF_PORT_PUNIT                      0x4
 #define   IOSF_PORT_NC                         0x11
 #define   IOSF_PORT_DPIO                       0x12
 #define   IOSF_PORT_CCK                                0x14
 #define   IOSF_PORT_CCU                                0xA9
 #define   IOSF_PORT_GPS_CORE                   0x48
+#define   IOSF_PORT_FLISDSI                    0x1B
 #define VLV_IOSF_DATA                          (VLV_DISPLAY_BASE + 0x2104)
 #define VLV_IOSF_ADDR                          (VLV_DISPLAY_BASE + 0x2108)
 
+/* See configdb bunit SB addr map */
+#define BUNIT_REG_BISOC                                0x11
+
 #define PUNIT_OPCODE_REG_READ                  6
 #define PUNIT_OPCODE_REG_WRITE                 7
 
+#define PUNIT_REG_DSPFREQ                      0x36
+#define   DSPFREQSTAT_SHIFT                    30
+#define   DSPFREQSTAT_MASK                     (0x3 << DSPFREQSTAT_SHIFT)
+#define   DSPFREQGUAR_SHIFT                    14
+#define   DSPFREQGUAR_MASK                     (0x3 << DSPFREQGUAR_SHIFT)
 #define PUNIT_REG_PWRGT_CTRL                   0x60
 #define PUNIT_REG_PWRGT_STATUS                 0x61
 #define          PUNIT_CLK_GATE                        1
 #define  DSI_PLL_N1_DIV_MASK                   (3 << 16)
 #define  DSI_PLL_M1_DIV_SHIFT                  0
 #define  DSI_PLL_M1_DIV_MASK                   (0x1ff << 0)
+#define CCK_DISPLAY_CLOCK_CONTROL              0x6b
 
 /*
  * DPIO - a special bus for various display related registers to hide behind
 #define  DPIO_SFR_BYPASS               (1<<1)
 #define  DPIO_CMNRST                   (1<<0)
 
-#define _DPIO_TX3_SWING_CTL4_A         0x690
-#define _DPIO_TX3_SWING_CTL4_B         0x2a90
-#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX3_SWING_CTL4_A, \
-                                       _DPIO_TX3_SWING_CTL4_B)
+#define DPIO_PHY(pipe)                 ((pipe) >> 1)
+#define DPIO_PHY_IOSF_PORT(phy)                (dev_priv->dpio_phy_iosf_port[phy])
 
 /*
  * Per pipe/PLL DPIO regs
  */
-#define _DPIO_DIV_A                    0x800c
+#define _VLV_PLL_DW3_CH0               0x800c
 #define   DPIO_POST_DIV_SHIFT          (28) /* 3 bits */
 #define   DPIO_POST_DIV_DAC            0
 #define   DPIO_POST_DIV_HDMIDP         1 /* DAC 225-400M rate */
 #define   DPIO_ENABLE_CALIBRATION      (1<<11)
 #define   DPIO_M1DIV_SHIFT             (8) /* 3 bits */
 #define   DPIO_M2DIV_MASK              0xff
-#define _DPIO_DIV_B                    0x802c
-#define DPIO_DIV(pipe) _PIPE(pipe, _DPIO_DIV_A, _DPIO_DIV_B)
+#define _VLV_PLL_DW3_CH1               0x802c
+#define VLV_PLL_DW3(ch) _PIPE(ch, _VLV_PLL_DW3_CH0, _VLV_PLL_DW3_CH1)
 
-#define _DPIO_REFSFR_A                 0x8014
+#define _VLV_PLL_DW5_CH0               0x8014
 #define   DPIO_REFSEL_OVERRIDE         27
 #define   DPIO_PLL_MODESEL_SHIFT       24 /* 3 bits */
 #define   DPIO_BIAS_CURRENT_CTL_SHIFT  21 /* 3 bits, always 0x7 */
 #define   DPIO_PLL_REFCLK_SEL_MASK     3
 #define   DPIO_DRIVER_CTL_SHIFT                12 /* always set to 0x8 */
 #define   DPIO_CLK_BIAS_CTL_SHIFT      8 /* always set to 0x5 */
-#define _DPIO_REFSFR_B                 0x8034
-#define DPIO_REFSFR(pipe) _PIPE(pipe, _DPIO_REFSFR_A, _DPIO_REFSFR_B)
+#define _VLV_PLL_DW5_CH1               0x8034
+#define VLV_PLL_DW5(ch) _PIPE(ch, _VLV_PLL_DW5_CH0, _VLV_PLL_DW5_CH1)
 
-#define _DPIO_CORE_CLK_A               0x801c
-#define _DPIO_CORE_CLK_B               0x803c
-#define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B)
+#define _VLV_PLL_DW7_CH0               0x801c
+#define _VLV_PLL_DW7_CH1               0x803c
+#define VLV_PLL_DW7(ch) _PIPE(ch, _VLV_PLL_DW7_CH0, _VLV_PLL_DW7_CH1)
 
-#define _DPIO_IREF_CTL_A               0x8040
-#define _DPIO_IREF_CTL_B               0x8060
-#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B)
+#define _VLV_PLL_DW8_CH0               0x8040
+#define _VLV_PLL_DW8_CH1               0x8060
+#define VLV_PLL_DW8(ch) _PIPE(ch, _VLV_PLL_DW8_CH0, _VLV_PLL_DW8_CH1)
 
-#define DPIO_IREF_BCAST                        0xc044
-#define _DPIO_IREF_A                   0x8044
-#define _DPIO_IREF_B                   0x8064
-#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B)
+#define VLV_PLL_DW9_BCAST              0xc044
+#define _VLV_PLL_DW9_CH0               0x8044
+#define _VLV_PLL_DW9_CH1               0x8064
+#define VLV_PLL_DW9(ch) _PIPE(ch, _VLV_PLL_DW9_CH0, _VLV_PLL_DW9_CH1)
 
-#define _DPIO_PLL_CML_A                        0x804c
-#define _DPIO_PLL_CML_B                        0x806c
-#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B)
+#define _VLV_PLL_DW10_CH0              0x8048
+#define _VLV_PLL_DW10_CH1              0x8068
+#define VLV_PLL_DW10(ch) _PIPE(ch, _VLV_PLL_DW10_CH0, _VLV_PLL_DW10_CH1)
 
-#define _DPIO_LPF_COEFF_A              0x8048
-#define _DPIO_LPF_COEFF_B              0x8068
-#define DPIO_LPF_COEFF(pipe) _PIPE(pipe, _DPIO_LPF_COEFF_A, _DPIO_LPF_COEFF_B)
+#define _VLV_PLL_DW11_CH0              0x804c
+#define _VLV_PLL_DW11_CH1              0x806c
+#define VLV_PLL_DW11(ch) _PIPE(ch, _VLV_PLL_DW11_CH0, _VLV_PLL_DW11_CH1)
 
-#define DPIO_CALIBRATION               0x80ac
+/* Spec for ref block start counts at DW10 */
+#define VLV_REF_DW13                   0x80ac
 
-#define DPIO_FASTCLK_DISABLE           0x8100
+#define VLV_CMN_DW0                    0x8100
 
 /*
  * Per DDI channel DPIO regs
  */
 
-#define _DPIO_PCS_TX_0                 0x8200
-#define _DPIO_PCS_TX_1                 0x8400
+#define _VLV_PCS_DW0_CH0               0x8200
+#define _VLV_PCS_DW0_CH1               0x8400
 #define   DPIO_PCS_TX_LANE2_RESET      (1<<16)
 #define   DPIO_PCS_TX_LANE1_RESET      (1<<7)
-#define DPIO_PCS_TX(port) _PORT(port, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1)
+#define VLV_PCS_DW0(ch) _PORT(ch, _VLV_PCS_DW0_CH0, _VLV_PCS_DW0_CH1)
 
-#define _DPIO_PCS_CLK_0                        0x8204
-#define _DPIO_PCS_CLK_1                        0x8404
+#define _VLV_PCS_DW1_CH0               0x8204
+#define _VLV_PCS_DW1_CH1               0x8404
 #define   DPIO_PCS_CLK_CRI_RXEB_EIOS_EN        (1<<22)
 #define   DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21)
 #define   DPIO_PCS_CLK_DATAWIDTH_SHIFT (6)
 #define   DPIO_PCS_CLK_SOFT_RESET      (1<<5)
-#define DPIO_PCS_CLK(port) _PORT(port, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1)
-
-#define _DPIO_PCS_CTL_OVR1_A           0x8224
-#define _DPIO_PCS_CTL_OVR1_B           0x8424
-#define DPIO_PCS_CTL_OVER1(port) _PORT(port, _DPIO_PCS_CTL_OVR1_A, \
-                                      _DPIO_PCS_CTL_OVR1_B)
-
-#define _DPIO_PCS_STAGGER0_A           0x822c
-#define _DPIO_PCS_STAGGER0_B           0x842c
-#define DPIO_PCS_STAGGER0(port) _PORT(port, _DPIO_PCS_STAGGER0_A, \
-                                     _DPIO_PCS_STAGGER0_B)
-
-#define _DPIO_PCS_STAGGER1_A           0x8230
-#define _DPIO_PCS_STAGGER1_B           0x8430
-#define DPIO_PCS_STAGGER1(port) _PORT(port, _DPIO_PCS_STAGGER1_A, \
-                                     _DPIO_PCS_STAGGER1_B)
-
-#define _DPIO_PCS_CLOCKBUF0_A          0x8238
-#define _DPIO_PCS_CLOCKBUF0_B          0x8438
-#define DPIO_PCS_CLOCKBUF0(port) _PORT(port, _DPIO_PCS_CLOCKBUF0_A, \
-                                      _DPIO_PCS_CLOCKBUF0_B)
-
-#define _DPIO_PCS_CLOCKBUF8_A          0x825c
-#define _DPIO_PCS_CLOCKBUF8_B          0x845c
-#define DPIO_PCS_CLOCKBUF8(port) _PORT(port, _DPIO_PCS_CLOCKBUF8_A, \
-                                      _DPIO_PCS_CLOCKBUF8_B)
-
-#define _DPIO_TX_SWING_CTL2_A          0x8288
-#define _DPIO_TX_SWING_CTL2_B          0x8488
-#define DPIO_TX_SWING_CTL2(port) _PORT(port, _DPIO_TX_SWING_CTL2_A, \
-                                      _DPIO_TX_SWING_CTL2_B)
-
-#define _DPIO_TX_SWING_CTL3_A          0x828c
-#define _DPIO_TX_SWING_CTL3_B          0x848c
-#define DPIO_TX_SWING_CTL3(port) _PORT(port, _DPIO_TX_SWING_CTL3_A, \
-                                      _DPIO_TX_SWING_CTL3_B)
-
-#define _DPIO_TX_SWING_CTL4_A          0x8290
-#define _DPIO_TX_SWING_CTL4_B          0x8490
-#define DPIO_TX_SWING_CTL4(port) _PORT(port, _DPIO_TX_SWING_CTL4_A, \
-                                      _DPIO_TX_SWING_CTL4_B)
-
-#define _DPIO_TX_OCALINIT_0            0x8294
-#define _DPIO_TX_OCALINIT_1            0x8494
+#define VLV_PCS_DW1(ch) _PORT(ch, _VLV_PCS_DW1_CH0, _VLV_PCS_DW1_CH1)
+
+#define _VLV_PCS_DW8_CH0               0x8220
+#define _VLV_PCS_DW8_CH1               0x8420
+#define VLV_PCS_DW8(ch) _PORT(ch, _VLV_PCS_DW8_CH0, _VLV_PCS_DW8_CH1)
+
+#define _VLV_PCS01_DW8_CH0             0x0220
+#define _VLV_PCS23_DW8_CH0             0x0420
+#define _VLV_PCS01_DW8_CH1             0x2620
+#define _VLV_PCS23_DW8_CH1             0x2820
+#define VLV_PCS01_DW8(port) _PORT(port, _VLV_PCS01_DW8_CH0, _VLV_PCS01_DW8_CH1)
+#define VLV_PCS23_DW8(port) _PORT(port, _VLV_PCS23_DW8_CH0, _VLV_PCS23_DW8_CH1)
+
+#define _VLV_PCS_DW9_CH0               0x8224
+#define _VLV_PCS_DW9_CH1               0x8424
+#define        VLV_PCS_DW9(ch) _PORT(ch, _VLV_PCS_DW9_CH0, _VLV_PCS_DW9_CH1)
+
+#define _VLV_PCS_DW11_CH0              0x822c
+#define _VLV_PCS_DW11_CH1              0x842c
+#define VLV_PCS_DW11(ch) _PORT(ch, _VLV_PCS_DW11_CH0, _VLV_PCS_DW11_CH1)
+
+#define _VLV_PCS_DW12_CH0              0x8230
+#define _VLV_PCS_DW12_CH1              0x8430
+#define VLV_PCS_DW12(ch) _PORT(ch, _VLV_PCS_DW12_CH0, _VLV_PCS_DW12_CH1)
+
+#define _VLV_PCS_DW14_CH0              0x8238
+#define _VLV_PCS_DW14_CH1              0x8438
+#define        VLV_PCS_DW14(ch) _PORT(ch, _VLV_PCS_DW14_CH0, _VLV_PCS_DW14_CH1)
+
+#define _VLV_PCS_DW23_CH0              0x825c
+#define _VLV_PCS_DW23_CH1              0x845c
+#define VLV_PCS_DW23(ch) _PORT(ch, _VLV_PCS_DW23_CH0, _VLV_PCS_DW23_CH1)
+
+#define _VLV_TX_DW2_CH0                        0x8288
+#define _VLV_TX_DW2_CH1                        0x8488
+#define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1)
+
+#define _VLV_TX_DW3_CH0                        0x828c
+#define _VLV_TX_DW3_CH1                        0x848c
+#define VLV_TX_DW3(ch) _PORT(ch, _VLV_TX_DW3_CH0, _VLV_TX_DW3_CH1)
+
+#define _VLV_TX_DW4_CH0                        0x8290
+#define _VLV_TX_DW4_CH1                        0x8490
+#define VLV_TX_DW4(ch) _PORT(ch, _VLV_TX_DW4_CH0, _VLV_TX_DW4_CH1)
+
+#define _VLV_TX3_DW4_CH0               0x690
+#define _VLV_TX3_DW4_CH1               0x2a90
+#define VLV_TX3_DW4(ch) _PORT(ch, _VLV_TX3_DW4_CH0, _VLV_TX3_DW4_CH1)
+
+#define _VLV_TX_DW5_CH0                        0x8294
+#define _VLV_TX_DW5_CH1                        0x8494
 #define   DPIO_TX_OCALINIT_EN          (1<<31)
-#define DPIO_TX_OCALINIT(port) _PORT(port, _DPIO_TX_OCALINIT_0, \
-                                    _DPIO_TX_OCALINIT_1)
-
-#define _DPIO_TX_CTL_0                 0x82ac
-#define _DPIO_TX_CTL_1                 0x84ac
-#define DPIO_TX_CTL(port) _PORT(port, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1)
-
-#define _DPIO_TX_LANE_0                        0x82b8
-#define _DPIO_TX_LANE_1                        0x84b8
-#define DPIO_TX_LANE(port) _PORT(port, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1)
-
-#define _DPIO_DATA_CHANNEL1            0x8220
-#define _DPIO_DATA_CHANNEL2            0x8420
-#define DPIO_DATA_CHANNEL(port) _PORT(port, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2)
-
-#define _DPIO_PORT0_PCS0               0x0220
-#define _DPIO_PORT0_PCS1               0x0420
-#define _DPIO_PORT1_PCS2               0x2620
-#define _DPIO_PORT1_PCS3               0x2820
-#define DPIO_DATA_LANE_A(port) _PORT(port, _DPIO_PORT0_PCS0, _DPIO_PORT1_PCS2)
-#define DPIO_DATA_LANE_B(port) _PORT(port, _DPIO_PORT0_PCS1, _DPIO_PORT1_PCS3)
-#define DPIO_DATA_CHANNEL1              0x8220
-#define DPIO_DATA_CHANNEL2              0x8420
+#define VLV_TX_DW5(ch) _PORT(ch, _VLV_TX_DW5_CH0, _VLV_TX_DW5_CH1)
+
+#define _VLV_TX_DW11_CH0               0x82ac
+#define _VLV_TX_DW11_CH1               0x84ac
+#define VLV_TX_DW11(ch) _PORT(ch, _VLV_TX_DW11_CH0, _VLV_TX_DW11_CH1)
+
+#define _VLV_TX_DW14_CH0               0x82b8
+#define _VLV_TX_DW14_CH1               0x84b8
+#define VLV_TX_DW14(ch) _PORT(ch, _VLV_TX_DW14_CH0, _VLV_TX_DW14_CH1)
 
 /*
  * Fence registers
 #define HWSTAM         0x02098
 #define DMA_FADD_I8XX  0x020d0
 #define RING_BBSTATE(base)     ((base)+0x110)
+#define RING_BBADDR(base)      ((base)+0x140)
+#define RING_BBADDR_UDW(base)  ((base)+0x168) /* gen8+ */
 
 #define ERROR_GEN6     0x040a0
 #define GEN7_ERR_INT   0x44040
 #define   CM0_COLOR_EVICT_DISABLE (1<<3)
 #define   CM0_DEPTH_WRITE_DISABLE (1<<1)
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
-#define BB_ADDR                0x02140 /* 8 bytes */
 #define GFX_FLSH_CNTL  0x02170 /* 915+ only */
 #define GFX_FLSH_CNTL_GEN6     0x101008
 #define   GFX_FLSH_CNTL_EN     (1<<0)
 
 #define GEN7_FF_THREAD_MODE            0x20a0
 #define   GEN7_FF_SCHED_MASK           0x0077070
+#define   GEN8_FF_DS_REF_CNT_FFME      (1 << 19)
 #define   GEN7_FF_TS_SCHED_HS1         (0x5<<16)
 #define   GEN7_FF_TS_SCHED_HS0         (0x3<<16)
 #define   GEN7_FF_TS_SCHED_LOAD_BALANCE        (0x1<<16)
 #define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
 #define   FBC_CTL_C3_IDLE      (1<<13)
 #define   FBC_CTL_STRIDE_SHIFT (5)
-#define   FBC_CTL_FENCENO      (1<<0)
+#define   FBC_CTL_FENCENO_SHIFT        (0)
 #define FBC_COMMAND            0x0320c
 #define   FBC_CMD_COMPRESS     (1<<0)
 #define FBC_STATUS             0x03210
 #define   FBC_STAT_COMPRESSING (1<<31)
 #define   FBC_STAT_COMPRESSED  (1<<30)
 #define   FBC_STAT_MODIFIED    (1<<29)
-#define   FBC_STAT_CURRENT_LINE        (1<<0)
+#define   FBC_STAT_CURRENT_LINE_SHIFT  (0)
 #define FBC_CONTROL2           0x03214
 #define   FBC_CTL_FENCE_DBL    (0<<4)
 #define   FBC_CTL_IDLE_IMM     (0<<2)
  * Please check the detailed lore in the commit message for for experimental
  * evidence.
  */
-#define   PORTD_HOTPLUG_LIVE_STATUS               (1 << 29)
-#define   PORTC_HOTPLUG_LIVE_STATUS               (1 << 28)
-#define   PORTB_HOTPLUG_LIVE_STATUS               (1 << 27)
+#define   PORTD_HOTPLUG_LIVE_STATUS_G4X                (1 << 29)
+#define   PORTC_HOTPLUG_LIVE_STATUS_G4X                (1 << 28)
+#define   PORTB_HOTPLUG_LIVE_STATUS_G4X                (1 << 27)
+/* VLV DP/HDMI bits again match Bspec */
+#define   PORTD_HOTPLUG_LIVE_STATUS_VLV                (1 << 27)
+#define   PORTC_HOTPLUG_LIVE_STATUS_VLV                (1 << 28)
+#define   PORTB_HOTPLUG_LIVE_STATUS_VLV                (1 << 29)
 #define   PORTD_HOTPLUG_INT_STATUS             (3 << 21)
 #define   PORTC_HOTPLUG_INT_STATUS             (3 << 19)
 #define   PORTB_HOTPLUG_INT_STATUS             (3 << 17)
 #define   CRT_HOTPLUG_MONITOR_COLOR            (3 << 8)
 #define   CRT_HOTPLUG_MONITOR_MONO             (2 << 8)
 #define   CRT_HOTPLUG_MONITOR_NONE             (0 << 8)
+#define   DP_AUX_CHANNEL_D_INT_STATUS_G4X      (1 << 6)
+#define   DP_AUX_CHANNEL_C_INT_STATUS_G4X      (1 << 5)
+#define   DP_AUX_CHANNEL_B_INT_STATUS_G4X      (1 << 4)
+#define   DP_AUX_CHANNEL_MASK_INT_STATUS_G4X   (7 << 4)
+
 /* SDVO is different across gen3/4 */
 #define   SDVOC_HOTPLUG_INT_STATUS_G4X         (1 << 3)
 #define   SDVOB_HOTPLUG_INT_STATUS_G4X         (1 << 2)
 /* the unit of memory self-refresh latency time is 0.5us */
 #define  ILK_SRLT_MASK         0x3f
 
-/* define the fifo size on Ironlake */
-#define ILK_DISPLAY_FIFO       128
-#define ILK_DISPLAY_MAXWM      64
-#define ILK_DISPLAY_DFTWM      8
-#define ILK_CURSOR_FIFO                32
-#define ILK_CURSOR_MAXWM       16
-#define ILK_CURSOR_DFTWM       8
-
-#define ILK_DISPLAY_SR_FIFO    512
-#define ILK_DISPLAY_MAX_SRWM   0x1ff
-#define ILK_DISPLAY_DFT_SRWM   0x3f
-#define ILK_CURSOR_SR_FIFO     64
-#define ILK_CURSOR_MAX_SRWM    0x3f
-#define ILK_CURSOR_DFT_SRWM    8
-
-#define ILK_FIFO_LINE_SIZE     64
-
-/* define the WM info on Sandybridge */
-#define SNB_DISPLAY_FIFO       128
-#define SNB_DISPLAY_MAXWM      0x7f    /* bit 16:22 */
-#define SNB_DISPLAY_DFTWM      8
-#define SNB_CURSOR_FIFO                32
-#define SNB_CURSOR_MAXWM       0x1f    /* bit 4:0 */
-#define SNB_CURSOR_DFTWM       8
-
-#define SNB_DISPLAY_SR_FIFO    512
-#define SNB_DISPLAY_MAX_SRWM   0x1ff   /* bit 16:8 */
-#define SNB_DISPLAY_DFT_SRWM   0x3f
-#define SNB_CURSOR_SR_FIFO     64
-#define SNB_CURSOR_MAX_SRWM    0x3f    /* bit 5:0 */
-#define SNB_CURSOR_DFT_SRWM    8
-
-#define SNB_FBC_MAX_SRWM       0xf     /* bit 23:20 */
-
-#define SNB_FIFO_LINE_SIZE     64
-
 
 /* the address where we get all kinds of latency value */
 #define SSKPD                  0x5d10
 #define DISP_BASEADDR_MASK     (0xfffff000)
 #define I915_LO_DISPBASE(val)  (val & ~DISP_BASEADDR_MASK)
 #define I915_HI_DISPBASE(val)  (val & DISP_BASEADDR_MASK)
-#define I915_MODIFY_DISPBASE(reg, gfx_addr) \
-               (I915_WRITE((reg), (gfx_addr) | I915_LO_DISPBASE(I915_READ(reg))))
 
 /* VBIOS flags */
 #define SWF00                  (dev_priv->info->display_mmio_offset + 0x71410)
 
 #define _SPACNTR               (VLV_DISPLAY_BASE + 0x72180)
 #define   SP_ENABLE                    (1<<31)
-#define   SP_GEAMMA_ENABLE             (1<<30)
+#define   SP_GAMMA_ENABLE              (1<<30)
 #define   SP_PIXFORMAT_MASK            (0xf<<26)
 #define   SP_FORMAT_YUV422             (0<<26)
 #define   SP_FORMAT_BGR565             (5<<26)
 #define DISP_ARB_CTL   0x45000
 #define  DISP_TILE_SURFACE_SWIZZLING   (1<<13)
 #define  DISP_FBC_WM_DIS               (1<<15)
+#define DISP_ARB_CTL2  0x45004
+#define  DISP_DATA_PARTITION_5_6       (1<<6)
 #define GEN7_MSG_CTL   0x45010
 #define  WAIT_FOR_PCH_RESET_ACK                (1<<1)
 #define  WAIT_FOR_PCH_FLR_ACK          (1<<0)
 #define GEN7_L3SQCREG4                         0xb034
 #define  L3SQ_URB_READ_CAM_MATCH_DISABLE       (1<<27)
 
+/* GEN8 chicken */
+#define HDC_CHICKEN0                           0x7300
+#define  HDC_FORCE_NON_COHERENT                        (1<<4)
+
 /* WaCatErrorRejectionIssue */
 #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG         0x9030
 #define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB      (1<<11)
 #define  FORCEWAKE_ACK                         0x130090
 #define  VLV_GTLC_WAKE_CTRL                    0x130090
 #define  VLV_GTLC_PW_STATUS                    0x130094
+#define VLV_GTLC_PW_RENDER_STATUS_MASK         0x80
+#define VLV_GTLC_PW_MEDIA_STATUS_MASK          0x20
 #define  FORCEWAKE_MT                          0xa188 /* multi-threaded */
 #define   FORCEWAKE_KERNEL                     0x1
 #define   FORCEWAKE_USER                       0x2
 #define    FORCEWAKE_MT_ENABLE                 (1<<5)
 
 #define  GTFIFODBG                             0x120000
-#define    GT_FIFO_CPU_ERROR_MASK              7
+#define    GT_FIFO_SBDROPERR                   (1<<6)
+#define    GT_FIFO_BLOBDROPERR                 (1<<5)
+#define    GT_FIFO_SB_READ_ABORTERR            (1<<4)
+#define    GT_FIFO_DROPERR                     (1<<3)
 #define    GT_FIFO_OVFERR                      (1<<2)
 #define    GT_FIFO_IAWRERR                     (1<<1)
 #define    GT_FIFO_IARDERR                     (1<<0)
 
-#define  GT_FIFO_FREE_ENTRIES                  0x120008
+#define  GTFIFOCTL                             0x120008
+#define    GT_FIFO_FREE_ENTRIES_MASK           0x7f
 #define    GT_FIFO_NUM_RESERVED_ENTRIES                20
 
 #define  HSW_IDICR                             0x9008
 #define   GEN6_RC_CTL_RC6_ENABLE               (1<<18)
 #define   GEN6_RC_CTL_RC1e_ENABLE              (1<<20)
 #define   GEN6_RC_CTL_RC7_ENABLE               (1<<22)
+#define   VLV_RC_CTL_CTX_RST_PARALLEL          (1<<24)
 #define   GEN7_RC_CTL_TO_MODE                  (1<<28)
 #define   GEN6_RC_CTL_EI_MODE(x)               ((x)<<27)
 #define   GEN6_RC_CTL_HW_ENABLE                        (1<<31)
index 98790c7cccb1ab0902662e4cc541de9966f2058c..8150fdc08d497122c49959b9bbfaf0090259c7df 100644 (file)
@@ -192,7 +192,6 @@ static void i915_restore_vga(struct drm_device *dev)
 static void i915_save_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long flags;
 
        /* Display arbitration control */
        if (INTEL_INFO(dev)->gen <= 4)
@@ -203,46 +202,27 @@ static void i915_save_display(struct drm_device *dev)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                i915_save_display_reg(dev);
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
        /* LVDS state */
        if (HAS_PCH_SPLIT(dev)) {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
-               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
-               dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
-               dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
-               dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
                if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
                        dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
                dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
 
-               dev_priv->regfile.saveBLC_PWM_CTL =
-                       I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
                dev_priv->regfile.saveBLC_HIST_CTL =
                        I915_READ(VLV_BLC_HIST_CTL(PIPE_A));
-               dev_priv->regfile.saveBLC_PWM_CTL2 =
-                       I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
-               dev_priv->regfile.saveBLC_PWM_CTL_B =
-                       I915_READ(VLV_BLC_PWM_CTL(PIPE_B));
                dev_priv->regfile.saveBLC_HIST_CTL_B =
                        I915_READ(VLV_BLC_HIST_CTL(PIPE_B));
-               dev_priv->regfile.saveBLC_PWM_CTL2_B =
-                       I915_READ(VLV_BLC_PWM_CTL2(PIPE_B));
        } else {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
                dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
-               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
                dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
-               if (INTEL_INFO(dev)->gen >= 4)
-                       dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
                if (IS_MOBILE(dev) && !IS_I830(dev))
                        dev_priv->regfile.saveLVDS = I915_READ(LVDS);
        }
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
        if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
                dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
 
@@ -257,7 +237,7 @@ static void i915_save_display(struct drm_device *dev)
        }
 
        /* Only regfile.save FBC state on the platform that supports FBC */
-       if (I915_HAS_FBC(dev)) {
+       if (HAS_FBC(dev)) {
                if (HAS_PCH_SPLIT(dev)) {
                        dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
                } else if (IS_GM45(dev)) {
@@ -278,7 +258,6 @@ static void i915_restore_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 mask = 0xffffffff;
-       unsigned long flags;
 
        /* Display arbitration */
        if (INTEL_INFO(dev)->gen <= 4)
@@ -287,12 +266,6 @@ static void i915_restore_display(struct drm_device *dev)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                i915_restore_display_reg(dev);
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
-       /* LVDS state */
-       if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-               I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
-
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                mask = ~LVDS_PORT_EN;
 
@@ -305,13 +278,6 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL);
 
        if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
-               I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
-               /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
-                * otherwise we get blank eDP screen after S3 on some machines
-                */
-               I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
-               I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
                I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
                I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
                I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
@@ -319,21 +285,12 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(RSTDBYCTL,
                           dev_priv->regfile.saveMCHBAR_RENDER_STANDBY);
        } else if (IS_VALLEYVIEW(dev)) {
-               I915_WRITE(VLV_BLC_PWM_CTL(PIPE_A),
-                          dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A),
                           dev_priv->regfile.saveBLC_HIST_CTL);
-               I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_A),
-                          dev_priv->regfile.saveBLC_PWM_CTL2);
-               I915_WRITE(VLV_BLC_PWM_CTL(PIPE_B),
-                          dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B),
                           dev_priv->regfile.saveBLC_HIST_CTL);
-               I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_B),
-                          dev_priv->regfile.saveBLC_PWM_CTL2);
        } else {
                I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS);
-               I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL);
                I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
                I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
@@ -341,11 +298,9 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
        }
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
        /* only restore FBC info on the platform that supports FBC*/
        intel_disable_fbc(dev);
-       if (I915_HAS_FBC(dev)) {
+       if (HAS_FBC(dev)) {
                if (HAS_PCH_SPLIT(dev)) {
                        I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
                } else if (IS_GM45(dev)) {
index cef38fd320a7c5c53c687ca5b67b0d1d3192d615..33bcae314bf86ea5f7a2deafb80625d0382634af 100644 (file)
@@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u64 raw_time; /* 32b value may overflow during fixed point math */
        u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
+       u32 ret;
 
        if (!intel_enable_rc6(dev))
                return 0;
 
+       intel_runtime_pm_get(dev_priv);
+
        /* On VLV, residency time is in CZ units rather than 1.28us */
        if (IS_VALLEYVIEW(dev)) {
                u32 clkctl2;
@@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
                        CLK_CTL2_CZCOUNT_30NS_SHIFT;
                if (!clkctl2) {
                        WARN(!clkctl2, "bogus CZ count value");
-                       return 0;
+                       ret = 0;
+                       goto out;
                }
                units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
                if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
@@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
        }
 
        raw_time = I915_READ(reg) * units;
-       return DIV_ROUND_UP_ULL(raw_time, div);
+       ret = DIV_ROUND_UP_ULL(raw_time, div);
+
+out:
+       intel_runtime_pm_put(dev_priv);
+       return ret;
 }
 
 static ssize_t
@@ -183,13 +191,13 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
        int slice = (int)(uintptr_t)attr->private;
        int ret;
 
+       if (!HAS_HW_CONTEXTS(drm_dev))
+               return -ENXIO;
+
        ret = l3_access_valid(drm_dev, offset);
        if (ret)
                return ret;
 
-       if (dev_priv->hw_contexts_disabled)
-               return -ENXIO;
-
        ret = i915_mutex_lock_interruptible(drm_dev);
        if (ret)
                return ret;
@@ -259,7 +267,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
        if (IS_VALLEYVIEW(dev_priv->dev)) {
                u32 freq;
                freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-               ret = vlv_gpu_freq(dev_priv->mem_freq, (freq >> 8) & 0xff);
+               ret = vlv_gpu_freq(dev_priv, (freq >> 8) & 0xff);
        } else {
                ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
        }
@@ -276,8 +284,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        return snprintf(buf, PAGE_SIZE, "%d\n",
-                       vlv_gpu_freq(dev_priv->mem_freq,
-                                    dev_priv->rps.rpe_delay));
+                       vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay));
 }
 
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -291,7 +298,7 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 
        mutex_lock(&dev_priv->rps.hw_lock);
        if (IS_VALLEYVIEW(dev_priv->dev))
-               ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay);
+               ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
        else
                ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -318,7 +325,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
        mutex_lock(&dev_priv->rps.hw_lock);
 
        if (IS_VALLEYVIEW(dev_priv->dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
 
                hw_max = valleyview_rps_max_freq(dev_priv);
                hw_min = valleyview_rps_min_freq(dev_priv);
@@ -342,15 +349,15 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
                DRM_DEBUG("User requested overclocking to %d\n",
                          val * GT_FREQUENCY_MULTIPLIER);
 
+       dev_priv->rps.max_delay = val;
+
        if (dev_priv->rps.cur_delay > val) {
-               if (IS_VALLEYVIEW(dev_priv->dev))
-                       valleyview_set_rps(dev_priv->dev, val);
+               if (IS_VALLEYVIEW(dev))
+                       valleyview_set_rps(dev, val);
                else
-                       gen6_set_rps(dev_priv->dev, val);
+                       gen6_set_rps(dev, val);
        }
 
-       dev_priv->rps.max_delay = val;
-
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return count;
@@ -367,7 +374,7 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 
        mutex_lock(&dev_priv->rps.hw_lock);
        if (IS_VALLEYVIEW(dev_priv->dev))
-               ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay);
+               ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
        else
                ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -394,7 +401,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
        mutex_lock(&dev_priv->rps.hw_lock);
 
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
 
                hw_max = valleyview_rps_max_freq(dev_priv);
                hw_min = valleyview_rps_min_freq(dev_priv);
@@ -411,15 +418,15 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
                return -EINVAL;
        }
 
+       dev_priv->rps.min_delay = val;
+
        if (dev_priv->rps.cur_delay < val) {
                if (IS_VALLEYVIEW(dev))
                        valleyview_set_rps(dev, val);
                else
-                       gen6_set_rps(dev_priv->dev, val);
+                       gen6_set_rps(dev, val);
        }
 
-       dev_priv->rps.min_delay = val;
-
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return count;
@@ -449,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
        rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        if (attr == &dev_attr_gt_RP0_freq_mhz) {
index 967da4772c449a2be05d16bce648fff9bd19a63e..caa18e855815eaf04a39ecb6eedcc572cf4d6290 100644 (file)
@@ -270,6 +270,18 @@ void i915_save_display_reg(struct drm_device *dev)
        }
        /* FIXME: regfile.save TV & SDVO state */
 
+       /* Backlight */
+       if (HAS_PCH_SPLIT(dev)) {
+               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
+               dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
+               dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
+               dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
+       } else {
+               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+               if (INTEL_INFO(dev)->gen >= 4)
+                       dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+       }
+
        return;
 }
 
@@ -280,6 +292,21 @@ void i915_restore_display_reg(struct drm_device *dev)
        int dpll_b_reg, fpb0_reg, fpb1_reg;
        int i;
 
+       /* Backlight */
+       if (HAS_PCH_SPLIT(dev)) {
+               I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
+               I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
+               /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
+                * otherwise we get blank eDP screen after S3 on some machines
+                */
+               I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
+               I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
+       } else {
+               if (INTEL_INFO(dev)->gen >= 4)
+                       I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
+               I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
+       }
+
        /* Display port ratios (must be done before clock is set) */
        if (SUPPORTS_INTEGRATED_DP(dev)) {
                I915_WRITE(_PIPEA_DATA_M_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
index e4fba39631a5ae2cd5901f85c73738406ef7cdc9..f22041973f3a0a426e29424cb60ba68e042c3ed8 100644 (file)
@@ -281,6 +281,34 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
        }
 }
 
+static void
+parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
+{
+       const struct bdb_lfp_backlight_data *backlight_data;
+       const struct bdb_lfp_backlight_data_entry *entry;
+
+       backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
+       if (!backlight_data)
+               return;
+
+       if (backlight_data->entry_size != sizeof(backlight_data->data[0])) {
+               DRM_DEBUG_KMS("Unsupported backlight data entry size %u\n",
+                             backlight_data->entry_size);
+               return;
+       }
+
+       entry = &backlight_data->data[panel_type];
+
+       dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
+       dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
+       DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
+                     "active %s, min brightness %u, level %u\n",
+                     dev_priv->vbt.backlight.pwm_freq_hz,
+                     dev_priv->vbt.backlight.active_low_pwm ? "low" : "high",
+                     entry->min_brightness,
+                     backlight_data->level[panel_type]);
+}
+
 /* Try to find sdvo panel data */
 static void
 parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
@@ -327,12 +355,12 @@ static int intel_bios_ssc_frequency(struct drm_device *dev,
 {
        switch (INTEL_INFO(dev)->gen) {
        case 2:
-               return alternate ? 66 : 48;
+               return alternate ? 66667 : 48000;
        case 3:
        case 4:
-               return alternate ? 100 : 96;
+               return alternate ? 100000 : 96000;
        default:
-               return alternate ? 100 : 120;
+               return alternate ? 100000 : 120000;
        }
 }
 
@@ -796,7 +824,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
         */
        dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev,
                        !HAS_PCH_SPLIT(dev));
-       DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
+       DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq);
 
        for (port = PORT_A; port < I915_MAX_PORTS; port++) {
                struct ddi_vbt_port_info *info =
@@ -894,6 +922,7 @@ intel_parse_bios(struct drm_device *dev)
        parse_general_features(dev_priv, bdb);
        parse_general_definitions(dev_priv, bdb);
        parse_lfp_panel_data(dev_priv, bdb);
+       parse_lfp_backlight(dev_priv, bdb);
        parse_sdvo_panel_data(dev_priv, bdb);
        parse_sdvo_device_mapping(dev_priv, bdb);
        parse_device_mapping(dev_priv, bdb);
index f580a2b0ddd30f5d4338c7ab61414b6fe8bc62fc..282de5e9f39dee6566bb6d220f378864df86e8b9 100644 (file)
@@ -39,7 +39,7 @@ struct vbt_header {
        u8 reserved0;
        u32 bdb_offset;                 /**< from beginning of VBT */
        u32 aim_offset[4];              /**< from beginning of VBT */
-} __attribute__((packed));
+} __packed;
 
 struct bdb_header {
        u8 signature[16];               /**< Always 'BIOS_DATA_BLOCK' */
@@ -65,7 +65,7 @@ struct vbios_data {
        u8 rsvd4; /* popup memory size */
        u8 resize_pci_bios;
        u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
+} __packed;
 
 /*
  * There are several types of BIOS data blocks (BDBs), each block has
@@ -142,7 +142,7 @@ struct bdb_general_features {
        u8 dp_ssc_enb:1;        /* PCH attached eDP supports SSC */
        u8 dp_ssc_freq:1;       /* SSC freq for PCH attached eDP */
        u8 rsvd11:3; /* finish byte */
-} __attribute__((packed));
+} __packed;
 
 /* pre-915 */
 #define GPIO_PIN_DVI_LVDS      0x03 /* "DVI/LVDS DDC GPIO pins" */
@@ -225,7 +225,7 @@ struct old_child_dev_config {
        u8  dvo2_wiring;
        u16 extended_type;
        u8  dvo_function;
-} __attribute__((packed));
+} __packed;
 
 /* This one contains field offsets that are known to be common for all BDB
  * versions. Notice that the meaning of the contents contents may still change,
@@ -238,7 +238,7 @@ struct common_child_dev_config {
        u8 not_common2[2];
        u8 ddc_pin;
        u16 edid_ptr;
-} __attribute__((packed));
+} __packed;
 
 /* This field changes depending on the BDB version, so the most reliable way to
  * read it is by checking the BDB version and reading the raw pointer. */
@@ -279,7 +279,7 @@ struct bdb_general_definitions {
         *           sizeof(child_device_config);
         */
        union child_device_config devices[0];
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_options {
        u8 panel_type;
@@ -293,7 +293,7 @@ struct bdb_lvds_options {
        u8 lvds_edid:1;
        u8 rsvd2:1;
        u8 rsvd4;
-} __attribute__((packed));
+} __packed;
 
 /* LFP pointer table contains entries to the struct below */
 struct bdb_lvds_lfp_data_ptr {
@@ -303,12 +303,12 @@ struct bdb_lvds_lfp_data_ptr {
        u8 dvo_table_size;
        u16 panel_pnp_id_offset;
        u8 pnp_table_size;
-} __attribute__((packed));
+} __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));
+} __packed;
 
 /* LFP data has 3 blocks per entry */
 struct lvds_fp_timing {
@@ -325,7 +325,7 @@ struct lvds_fp_timing {
        u32 pfit_reg;
        u32 pfit_reg_val;
        u16 terminator;
-} __attribute__((packed));
+} __packed;
 
 struct lvds_dvo_timing {
        u16 clock;              /**< In 10khz */
@@ -353,7 +353,7 @@ struct lvds_dvo_timing {
        u8 vsync_positive:1;
        u8 hsync_positive:1;
        u8 rsvd2:1;
-} __attribute__((packed));
+} __packed;
 
 struct lvds_pnp_id {
        u16 mfg_name;
@@ -361,17 +361,33 @@ struct lvds_pnp_id {
        u32 serial;
        u8 mfg_week;
        u8 mfg_year;
-} __attribute__((packed));
+} __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));
+} __packed;
 
 struct bdb_lvds_lfp_data {
        struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
+} __packed;
+
+struct bdb_lfp_backlight_data_entry {
+       u8 type:2;
+       u8 active_low_pwm:1;
+       u8 obsolete1:5;
+       u16 pwm_freq_hz;
+       u8 min_brightness;
+       u8 obsolete2;
+       u8 obsolete3;
+} __packed;
+
+struct bdb_lfp_backlight_data {
+       u8 entry_size;
+       struct bdb_lfp_backlight_data_entry data[16];
+       u8 level[16];
+} __packed;
 
 struct aimdb_header {
        char signature[16];
@@ -379,12 +395,12 @@ struct aimdb_header {
        u16 aimdb_version;
        u16 aimdb_header_size;
        u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
 
 struct aimdb_block {
        u8 aimdb_id;
        u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
 
 struct vch_panel_data {
        u16 fp_timing_offset;
@@ -395,12 +411,12 @@ struct vch_panel_data {
        u8 text_fitting_size;
        u16 graphics_fitting_offset;
        u8 graphics_fitting_size;
-} __attribute__((packed));
+} __packed;
 
 struct vch_bdb_22 {
        struct aimdb_block aimdb_block;
        struct vch_panel_data panels[16];
-} __attribute__((packed));
+} __packed;
 
 struct bdb_sdvo_lvds_options {
        u8 panel_backlight;
@@ -416,7 +432,7 @@ struct bdb_sdvo_lvds_options {
        u8 panel_misc_bits_2;
        u8 panel_misc_bits_3;
        u8 panel_misc_bits_4;
-} __attribute__((packed));
+} __packed;
 
 
 #define BDB_DRIVER_FEATURE_NO_LVDS             0
@@ -462,7 +478,7 @@ struct bdb_driver_features {
 
        u8 hdmi_termination;
        u8 custom_vbt_version;
-} __attribute__((packed));
+} __packed;
 
 #define EDP_18BPP      0
 #define EDP_24BPP      1
@@ -487,14 +503,14 @@ struct edp_power_seq {
        u16 t9;
        u16 t10;
        u16 t11_t12;
-} __attribute__ ((packed));
+} __packed;
 
 struct edp_link_params {
        u8 rate:4;
        u8 lanes:4;
        u8 preemphasis:4;
        u8 vswing:4;
-} __attribute__ ((packed));
+} __packed;
 
 struct bdb_edp {
        struct edp_power_seq power_seqs[16];
@@ -505,7 +521,7 @@ struct bdb_edp {
        /* ith bit indicates enabled/disabled for (i+1)th panel */
        u16 edp_s3d_feature;
        u16 edp_t3_optimization;
-} __attribute__ ((packed));
+} __packed;
 
 void intel_setup_bios(struct drm_device *dev);
 int intel_parse_bios(struct drm_device *dev);
@@ -733,6 +749,6 @@ struct bdb_mipi {
        u32 hl_switch_cnt;
        u32 lp_byte_clk;
        u32 clk_lane_switch_cnt;
-} __attribute__((packed));
+} __packed;
 
 #endif /* _I830_BIOS_H_ */
index b5b1b9b23adf1b24559e7ffdce658ba37e6bbbab..e2e39e65f10954b8076b3ed01b565f0cb173bb0d 100644 (file)
@@ -222,8 +222,9 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_crt_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_crt_mode_valid(struct drm_connector *connector,
+                    struct drm_display_mode *mode)
 {
        struct drm_device *dev = connector->dev;
 
index 526c8ded16b03bc334846609a47e2d0bfc07c58c..e06b9e017d6ba918b87557de301df47076852434 100644 (file)
@@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = {
 };
 
 static const u32 bdw_ddi_translations_edp[] = {
-       0x00FFFFFF, 0x00000012,         /* DP parameters */
+       0x00FFFFFF, 0x00000012,         /* eDP parameters */
        0x00EBAFFF, 0x00020011,
        0x00C71FFF, 0x0006000F,
        0x00FFFFFF, 0x00020011,
@@ -696,25 +696,25 @@ intel_ddi_calculate_wrpll(int clock /* in Hz */,
        *n2_out = best.n2;
        *p_out = best.p;
        *r2_out = best.r2;
-
-       DRM_DEBUG_KMS("WRPLL: %dHz refresh rate with p=%d, n2=%d r2=%d\n",
-                     clock, *p_out, *n2_out, *r2_out);
 }
 
-bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
+/*
+ * Tries to find a PLL for the CRTC. If it finds, it increases the refcount and
+ * stores it in intel_crtc->ddi_pll_sel, so other mode sets won't be able to
+ * steal the selected PLL. You need to call intel_ddi_pll_enable to actually
+ * enable the PLL.
+ */
+bool intel_ddi_pll_select(struct intel_crtc *intel_crtc)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_crtc *crtc = &intel_crtc->base;
        struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
        struct drm_encoder *encoder = &intel_encoder->base;
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
        struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
        int type = intel_encoder->type;
        enum pipe pipe = intel_crtc->pipe;
-       uint32_t reg, val;
        int clock = intel_crtc->config.port_clock;
 
-       /* TODO: reuse PLLs when possible (compare values) */
-
        intel_ddi_put_crtc_pll(crtc);
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
@@ -736,66 +736,145 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
                        return false;
                }
 
-               /* We don't need to turn any PLL on because we'll use LCPLL. */
-               return true;
-
        } else if (type == INTEL_OUTPUT_HDMI) {
+               uint32_t reg, val;
                unsigned p, n2, r2;
 
-               if (plls->wrpll1_refcount == 0) {
+               intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
+
+               val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+                     WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
+                     WRPLL_DIVIDER_POST(p);
+
+               if (val == I915_READ(WRPLL_CTL1)) {
+                       DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n",
+                                     pipe_name(pipe));
+                       reg = WRPLL_CTL1;
+               } else if (val == I915_READ(WRPLL_CTL2)) {
+                       DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n",
+                                     pipe_name(pipe));
+                       reg = WRPLL_CTL2;
+               } else if (plls->wrpll1_refcount == 0) {
                        DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
                                      pipe_name(pipe));
-                       plls->wrpll1_refcount++;
                        reg = WRPLL_CTL1;
-                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
                } else if (plls->wrpll2_refcount == 0) {
                        DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n",
                                      pipe_name(pipe));
-                       plls->wrpll2_refcount++;
                        reg = WRPLL_CTL2;
-                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
                } else {
                        DRM_ERROR("No WRPLLs available!\n");
                        return false;
                }
 
-               WARN(I915_READ(reg) & WRPLL_PLL_ENABLE,
-                    "WRPLL already enabled\n");
+               DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
+                             clock, p, n2, r2);
 
-               intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
-
-               val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
-                     WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
-                     WRPLL_DIVIDER_POST(p);
+               if (reg == WRPLL_CTL1) {
+                       plls->wrpll1_refcount++;
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
+               } else {
+                       plls->wrpll2_refcount++;
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
+               }
 
        } else if (type == INTEL_OUTPUT_ANALOG) {
                if (plls->spll_refcount == 0) {
                        DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
                                      pipe_name(pipe));
                        plls->spll_refcount++;
-                       reg = SPLL_CTL;
                        intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
                } else {
                        DRM_ERROR("SPLL already in use\n");
                        return false;
                }
 
-               WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
-                    "SPLL already enabled\n");
-
-               val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
-
        } else {
                WARN(1, "Invalid DDI encoder type %d\n", type);
                return false;
        }
 
-       I915_WRITE(reg, val);
-       udelay(20);
-
        return true;
 }
 
+/*
+ * To be called after intel_ddi_pll_select(). That one selects the PLL to be
+ * used, this one actually enables the PLL.
+ */
+void intel_ddi_pll_enable(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+       int clock = crtc->config.port_clock;
+       uint32_t reg, cur_val, new_val;
+       int refcount;
+       const char *pll_name;
+       uint32_t enable_bit = (1 << 31);
+       unsigned int p, n2, r2;
+
+       BUILD_BUG_ON(enable_bit != SPLL_PLL_ENABLE);
+       BUILD_BUG_ON(enable_bit != WRPLL_PLL_ENABLE);
+
+       switch (crtc->ddi_pll_sel) {
+       case PORT_CLK_SEL_LCPLL_2700:
+       case PORT_CLK_SEL_LCPLL_1350:
+       case PORT_CLK_SEL_LCPLL_810:
+               /*
+                * LCPLL should always be enabled at this point of the mode set
+                * sequence, so nothing to do.
+                */
+               return;
+
+       case PORT_CLK_SEL_SPLL:
+               pll_name = "SPLL";
+               reg = SPLL_CTL;
+               refcount = plls->spll_refcount;
+               new_val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz |
+                         SPLL_PLL_SSC;
+               break;
+
+       case PORT_CLK_SEL_WRPLL1:
+       case PORT_CLK_SEL_WRPLL2:
+               if (crtc->ddi_pll_sel == PORT_CLK_SEL_WRPLL1) {
+                       pll_name = "WRPLL1";
+                       reg = WRPLL_CTL1;
+                       refcount = plls->wrpll1_refcount;
+               } else {
+                       pll_name = "WRPLL2";
+                       reg = WRPLL_CTL2;
+                       refcount = plls->wrpll2_refcount;
+               }
+
+               intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
+
+               new_val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+                         WRPLL_DIVIDER_REFERENCE(r2) |
+                         WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p);
+
+               break;
+
+       case PORT_CLK_SEL_NONE:
+               WARN(1, "Bad selected pll: PORT_CLK_SEL_NONE\n");
+               return;
+       default:
+               WARN(1, "Bad selected pll: 0x%08x\n", crtc->ddi_pll_sel);
+               return;
+       }
+
+       cur_val = I915_READ(reg);
+
+       WARN(refcount < 1, "Bad %s refcount: %d\n", pll_name, refcount);
+       if (refcount == 1) {
+               WARN(cur_val & enable_bit, "%s already enabled\n", pll_name);
+               I915_WRITE(reg, new_val);
+               POSTING_READ(reg);
+               udelay(20);
+       } else {
+               WARN((cur_val & enable_bit) == 0, "%s disabled\n", pll_name);
+       }
+}
+
 void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = crtc->dev->dev_private;
@@ -1057,12 +1136,18 @@ void intel_ddi_setup_hw_pll_state(struct drm_device *dev)
        enum pipe pipe;
        struct intel_crtc *intel_crtc;
 
+       dev_priv->ddi_plls.spll_refcount = 0;
+       dev_priv->ddi_plls.wrpll1_refcount = 0;
+       dev_priv->ddi_plls.wrpll2_refcount = 0;
+
        for_each_pipe(pipe) {
                intel_crtc =
                        to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 
-               if (!intel_crtc->active)
+               if (!intel_crtc->active) {
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
                        continue;
+               }
 
                intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
                                                                 pipe);
@@ -1115,9 +1200,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 
        if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-               ironlake_edp_panel_vdd_on(intel_dp);
                ironlake_edp_panel_on(intel_dp);
-               ironlake_edp_panel_vdd_off(intel_dp, true);
        }
 
        WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
@@ -1160,7 +1243,6 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-               ironlake_edp_panel_vdd_on(intel_dp);
                intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
                ironlake_edp_panel_off(intel_dp);
        }
index 1b20b4644979a1c273699e793d85c942f2ebc862..9fa24347963a38d360e365cfa20bf7cefed8beaa 100644 (file)
@@ -90,8 +90,8 @@ intel_fdi_link_freq(struct drm_device *dev)
 
 static const intel_limit_t intel_limits_i8xx_dac = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -103,8 +103,8 @@ static const intel_limit_t intel_limits_i8xx_dac = {
 
 static const intel_limit_t intel_limits_i8xx_dvo = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -116,8 +116,8 @@ static const intel_limit_t intel_limits_i8xx_dvo = {
 
 static const intel_limit_t intel_limits_i8xx_lvds = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -329,6 +329,8 @@ static void vlv_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = clock->m1 * clock->m2;
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -430,6 +432,8 @@ static void pineview_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = clock->m2 + 2;
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -443,6 +447,8 @@ static void i9xx_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = i9xx_dpll_compute_m(clock);
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -748,10 +754,10 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
        return intel_crtc->config.cpu_transcoder;
 }
 
-static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
+static void g4x_wait_for_vblank(struct drm_device *dev, int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 frame, frame_reg = PIPEFRAME(pipe);
+       u32 frame, frame_reg = PIPE_FRMCOUNT_GM45(pipe);
 
        frame = I915_READ(frame_reg);
 
@@ -772,8 +778,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipestat_reg = PIPESTAT(pipe);
 
-       if (INTEL_INFO(dev)->gen >= 5) {
-               ironlake_wait_for_vblank(dev, pipe);
+       if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
+               g4x_wait_for_vblank(dev, pipe);
                return;
        }
 
@@ -1205,15 +1211,12 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
        }
 }
 
-static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
+static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
 {
        u32 val;
        bool enabled;
 
-       if (HAS_PCH_LPT(dev_priv->dev)) {
-               DRM_DEBUG_DRIVER("LPT does not has PCH refclk, skipping check\n");
-               return;
-       }
+       WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
 
        val = I915_READ(PCH_DREF_CONTROL);
        enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
@@ -1361,6 +1364,24 @@ static void intel_init_dpio(struct drm_device *dev)
        if (!IS_VALLEYVIEW(dev))
                return;
 
+       DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
+}
+
+static void intel_reset_dpio(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!IS_VALLEYVIEW(dev))
+               return;
+
+       /*
+        * Enable the CRI clock source so we can get at the display and the
+        * reference clock for VGA hotplug / manual detection.
+        */
+       I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
+                  DPLL_REFA_CLK_ENABLE_VLV |
+                  DPLL_INTEGRATED_CRI_CLK_VLV);
+
        /*
         * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
         *  6.  De-assert cmn_reset/side_reset. Same as VLV X0.
@@ -1487,25 +1508,35 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
        /* Make sure the pipe isn't still relying on us */
        assert_pipe_disabled(dev_priv, pipe);
 
-       /* Leave integrated clock source enabled */
+       /*
+        * Leave integrated clock source and reference clock enabled for pipe B.
+        * The latter is needed for VGA hotplug / manual detection.
+        */
        if (pipe == PIPE_B)
-               val = DPLL_INTEGRATED_CRI_CLK_VLV;
+               val = DPLL_INTEGRATED_CRI_CLK_VLV | DPLL_REFA_CLK_ENABLE_VLV;
        I915_WRITE(DPLL(pipe), val);
        POSTING_READ(DPLL(pipe));
 }
 
-void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port)
+void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
+               struct intel_digital_port *dport)
 {
        u32 port_mask;
 
-       if (!port)
+       switch (dport->port) {
+       case PORT_B:
                port_mask = DPLL_PORTB_READY_MASK;
-       else
+               break;
+       case PORT_C:
                port_mask = DPLL_PORTC_READY_MASK;
+               break;
+       default:
+               BUG();
+       }
 
        if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000))
                WARN(1, "timed out waiting for port %c ready: 0x%08x\n",
-                    'B' + port, I915_READ(DPLL(0)));
+                    port_name(dport->port), I915_READ(DPLL(0)));
 }
 
 /**
@@ -2083,8 +2114,8 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                      fb->pitches[0]);
        I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
        if (INTEL_INFO(dev)->gen >= 4) {
-               I915_MODIFY_DISPBASE(DSPSURF(plane),
-                                    i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+               I915_WRITE(DSPSURF(plane),
+                          i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
                I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
                I915_WRITE(DSPLINOFF(plane), linear_offset);
        } else
@@ -2174,8 +2205,8 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
                      i915_gem_obj_ggtt_offset(obj), linear_offset, x, y,
                      fb->pitches[0]);
        I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
-       I915_MODIFY_DISPBASE(DSPSURF(plane),
-                            i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+       I915_WRITE(DSPSURF(plane),
+                  i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
        if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
        } else {
@@ -2233,7 +2264,12 @@ void intel_display_handle_reset(struct drm_device *dev)
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
                mutex_lock(&crtc->mutex);
-               if (intel_crtc->active)
+               /*
+                * FIXME: Once we have proper support for primary planes (and
+                * disabling them without disabling the entire crtc) allow again
+                * a NULL crtc->fb.
+                */
+               if (intel_crtc->active && crtc->fb)
                        dev_priv->display.update_plane(crtc, crtc->fb,
                                                       crtc->x, crtc->y);
                mutex_unlock(&crtc->mutex);
@@ -2350,6 +2386,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                        I915_WRITE(PF_WIN_POS(intel_crtc->pipe), 0);
                        I915_WRITE(PF_WIN_SZ(intel_crtc->pipe), 0);
                }
+               intel_crtc->config.pipe_src_w = adjusted_mode->crtc_hdisplay;
+               intel_crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay;
        }
 
        ret = dev_priv->display.update_plane(crtc, fb, x, y);
@@ -2944,6 +2982,30 @@ static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
        return pending;
 }
 
+bool intel_has_pending_fb_unpin(struct drm_device *dev)
+{
+       struct intel_crtc *crtc;
+
+       /* Note that we don't need to be called with mode_config.lock here
+        * as our list of CRTC objects is static for the lifetime of the
+        * device and so cannot disappear as we iterate. Similarly, we can
+        * happily treat the predicates as racy, atomic checks as userspace
+        * cannot claim and pin a new fb without at least acquring the
+        * struct_mutex and so serialising with us.
+        */
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
+               if (atomic_read(&crtc->unpin_work_count) == 0)
+                       continue;
+
+               if (crtc->unpin_work)
+                       intel_wait_for_vblank(dev, crtc->pipe);
+
+               return true;
+       }
+
+       return false;
+}
+
 static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -3399,9 +3461,8 @@ void hsw_enable_ips(struct intel_crtc *crtc)
                mutex_unlock(&dev_priv->rps.hw_lock);
                /* Quoting Art Runyan: "its not safe to expect any particular
                 * value in IPS_CTL bit 31 after enabling IPS through the
-                * mailbox." Therefore we need to defer waiting on the state
-                * change.
-                * TODO: need to fix this for state checker
+                * mailbox." Moreover, the mailbox may return a bogus state,
+                * so we need to just enable it and continue on.
                 */
        } else {
                I915_WRITE(IPS_CTL, IPS_ENABLE);
@@ -3428,9 +3489,10 @@ void hsw_disable_ips(struct intel_crtc *crtc)
                mutex_lock(&dev_priv->rps.hw_lock);
                WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
                mutex_unlock(&dev_priv->rps.hw_lock);
-       } else
+       } else {
                I915_WRITE(IPS_CTL, 0);
-       POSTING_READ(IPS_CTL);
+               POSTING_READ(IPS_CTL);
+       }
 
        /* We need to wait for a vblank before we can disable the plane. */
        intel_wait_for_vblank(dev, crtc->pipe);
@@ -3465,7 +3527,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
        /* Workaround : Do not read or write the pipe palette/gamma data while
         * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
         */
-       if (intel_crtc->config.ips_enabled &&
+       if (IS_HASWELL(dev) && intel_crtc->config.ips_enabled &&
            ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
             GAMMA_MODE_MODE_SPLIT)) {
                hsw_disable_ips(intel_crtc);
@@ -3910,6 +3972,174 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
        I915_WRITE(BCLRPAT(crtc->pipe), 0);
 }
 
+int valleyview_get_vco(struct drm_i915_private *dev_priv)
+{
+       int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
+
+       /* Obtain SKU information */
+       mutex_lock(&dev_priv->dpio_lock);
+       hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) &
+               CCK_FUSE_HPLL_FREQ_MASK;
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       return vco_freq[hpll_freq];
+}
+
+/* Adjust CDclk dividers to allow high res or save power if possible */
+static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val, cmd;
+
+       if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
+               cmd = 2;
+       else if (cdclk == 266)
+               cmd = 1;
+       else
+               cmd = 0;
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
+       val &= ~DSPFREQGUAR_MASK;
+       val |= (cmd << DSPFREQGUAR_SHIFT);
+       vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
+       if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
+                     DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
+                    50)) {
+               DRM_ERROR("timed out waiting for CDclk change\n");
+       }
+       mutex_unlock(&dev_priv->rps.hw_lock);
+
+       if (cdclk == 400) {
+               u32 divider, vco;
+
+               vco = valleyview_get_vco(dev_priv);
+               divider = ((vco << 1) / cdclk) - 1;
+
+               mutex_lock(&dev_priv->dpio_lock);
+               /* adjust cdclk divider */
+               val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+               val &= ~0xf;
+               val |= divider;
+               vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
+               mutex_unlock(&dev_priv->dpio_lock);
+       }
+
+       mutex_lock(&dev_priv->dpio_lock);
+       /* adjust self-refresh exit latency value */
+       val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
+       val &= ~0x7f;
+
+       /*
+        * For high bandwidth configs, we set a higher latency in the bunit
+        * so that the core display fetch happens in time to avoid underruns.
+        */
+       if (cdclk == 400)
+               val |= 4500 / 250; /* 4.5 usec */
+       else
+               val |= 3000 / 250; /* 3.0 usec */
+       vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       /* Since we changed the CDclk, we need to update the GMBUSFREQ too */
+       intel_i2c_reset(dev);
+}
+
+static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
+{
+       int cur_cdclk, vco;
+       int divider;
+
+       vco = valleyview_get_vco(dev_priv);
+
+       mutex_lock(&dev_priv->dpio_lock);
+       divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       divider &= 0xf;
+
+       cur_cdclk = (vco << 1) / (divider + 1);
+
+       return cur_cdclk;
+}
+
+static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
+                                int max_pixclk)
+{
+       int cur_cdclk;
+
+       cur_cdclk = valleyview_cur_cdclk(dev_priv);
+
+       /*
+        * Really only a few cases to deal with, as only 4 CDclks are supported:
+        *   200MHz
+        *   267MHz
+        *   320MHz
+        *   400MHz
+        * So we check to see whether we're above 90% of the lower bin and
+        * adjust if needed.
+        */
+       if (max_pixclk > 288000) {
+               return 400;
+       } else if (max_pixclk > 240000) {
+               return 320;
+       } else
+               return 266;
+       /* Looks like the 200MHz CDclk freq doesn't work on some configs */
+}
+
+static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv,
+                                unsigned modeset_pipes,
+                                struct intel_crtc_config *pipe_config)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct intel_crtc *intel_crtc;
+       int max_pixclk = 0;
+
+       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+                           base.head) {
+               if (modeset_pipes & (1 << intel_crtc->pipe))
+                       max_pixclk = max(max_pixclk,
+                                        pipe_config->adjusted_mode.crtc_clock);
+               else if (intel_crtc->base.enabled)
+                       max_pixclk = max(max_pixclk,
+                                        intel_crtc->config.adjusted_mode.crtc_clock);
+       }
+
+       return max_pixclk;
+}
+
+static void valleyview_modeset_global_pipes(struct drm_device *dev,
+                                           unsigned *prepare_pipes,
+                                           unsigned modeset_pipes,
+                                           struct intel_crtc_config *pipe_config)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc;
+       int max_pixclk = intel_mode_max_pixclk(dev_priv, modeset_pipes,
+                                              pipe_config);
+       int cur_cdclk = valleyview_cur_cdclk(dev_priv);
+
+       if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk)
+               return;
+
+       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+                           base.head)
+               if (intel_crtc->base.enabled)
+                       *prepare_pipes |= (1 << intel_crtc->pipe);
+}
+
+static void valleyview_modeset_global_resources(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int max_pixclk = intel_mode_max_pixclk(dev_priv, 0, NULL);
+       int cur_cdclk = valleyview_cur_cdclk(dev_priv);
+       int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
+
+       if (req_cdclk != cur_cdclk)
+               valleyview_set_cdclk(dev, req_cdclk);
+}
+
 static void valleyview_crtc_enable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -4570,9 +4800,8 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
                refclk = 100000;
        } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
            intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               refclk = dev_priv->vbt.lvds_ssc_freq * 1000;
-               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
-                             refclk / 1000);
+               refclk = dev_priv->vbt.lvds_ssc_freq;
+               DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
        } else if (!IS_GEN2(dev)) {
                refclk = 96000;
        } else {
@@ -4634,24 +4863,24 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
         * PLLB opamp always calibrates to max value of 0x3f, force enable it
         * and set it to a reasonable value instead.
         */
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
        reg_val &= 0xffffff00;
        reg_val |= 0x00000030;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION);
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
        reg_val &= 0x8cffffff;
        reg_val = 0x8c000000;
-       vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
        reg_val &= 0xffffff00;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION);
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
        reg_val &= 0x00ffffff;
        reg_val |= 0xb0000000;
-       vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
 }
 
 static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
@@ -4720,15 +4949,15 @@ static void vlv_update_pll(struct intel_crtc *crtc)
                vlv_pllb_recal_opamp(dev_priv, pipe);
 
        /* Set up Tx target for periodic Rcomp update */
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF_BCAST, 0x0100000f);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f);
 
        /* Disable target IRef on PLL */
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF_CTL(pipe));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe));
        reg_val &= 0x00ffffff;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF_CTL(pipe), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val);
 
        /* Disable fast lock */
-       vlv_dpio_write(dev_priv, pipe, DPIO_FASTCLK_DISABLE, 0x610);
+       vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610);
 
        /* Set idtafcrecal before PLL is enabled */
        mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
@@ -4742,50 +4971,54 @@ static void vlv_update_pll(struct intel_crtc *crtc)
         * Note: don't use the DAC post divider as it seems unstable.
         */
        mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT);
-       vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
 
        mdiv |= DPIO_ENABLE_CALIBRATION;
-       vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
 
        /* Set HBR and RBR LPF coefficients */
        if (crtc->config.port_clock == 162000 ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI))
-               vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe),
+               vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
                                 0x009f0003);
        else
-               vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe),
+               vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
                                 0x00d0000f);
 
        if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) {
                /* Use SSC source */
                if (!pipe)
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df40000);
                else
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df70000);
        } else { /* HDMI or VGA */
                /* Use bend source */
                if (!pipe)
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df70000);
                else
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df40000);
        }
 
-       coreclk = vlv_dpio_read(dev_priv, pipe, DPIO_CORE_CLK(pipe));
+       coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(pipe));
        coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
        if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP))
                coreclk |= 0x01000000;
-       vlv_dpio_write(dev_priv, pipe, DPIO_CORE_CLK(pipe), coreclk);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
 
-       vlv_dpio_write(dev_priv, pipe, DPIO_PLL_CML(pipe), 0x87871000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000);
 
-       /* Enable DPIO clock input */
+       /*
+        * Enable DPIO clock input. We should never disable the reference
+        * clock for pipe B, since VGA hotplug / manual detection depends
+        * on it.
+        */
        dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
                DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
        /* We should never disable this, set it here for state tracking */
@@ -5230,6 +5463,9 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
+       if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
+               return;
+
        tmp = I915_READ(PFIT_CONTROL);
        if (!(tmp & PFIT_ENABLE))
                return;
@@ -5261,7 +5497,7 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
        int refclk = 100000;
 
        mutex_lock(&dev_priv->dpio_lock);
-       mdiv = vlv_dpio_read(dev_priv, pipe, DPIO_DIV(pipe));
+       mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe));
        mutex_unlock(&dev_priv->dpio_lock);
 
        clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7;
@@ -5718,9 +5954,9 @@ static int ironlake_get_refclk(struct drm_crtc *crtc)
        }
 
        if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+               DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
                              dev_priv->vbt.lvds_ssc_freq);
-               return dev_priv->vbt.lvds_ssc_freq * 1000;
+               return dev_priv->vbt.lvds_ssc_freq;
        }
 
        return 120000;
@@ -5982,7 +6218,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
        factor = 21;
        if (is_lvds) {
                if ((intel_panel_use_ssc(dev_priv) &&
-                    dev_priv->vbt.lvds_ssc_freq == 100) ||
+                    dev_priv->vbt.lvds_ssc_freq == 100000) ||
                    (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
                        factor = 25;
        } else if (intel_crtc->config.sdvo_tv_clock)
@@ -6303,7 +6539,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
        uint32_t val;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
-               WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+               WARN(crtc->active, "CRTC for pipe %c enabled\n",
                     pipe_name(crtc->pipe));
 
        WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
@@ -6323,7 +6559,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        val = I915_READ(DEIMR);
-       WARN((val & ~DE_PCH_EVENT_IVB) != val,
+       WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff,
             "Unexpected DEIMR bits enabled: 0x%x\n", val);
        val = I915_READ(SDEIMR);
        WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
@@ -6402,7 +6638,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 
        /* Make sure we're not on PC8 state before disabling PC8, otherwise
         * we'll hang the machine! */
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        if (val & LCPLL_POWER_DOWN_ALLOW) {
                val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6436,7 +6672,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
                        DRM_ERROR("Switching back to LCPLL failed\n");
        }
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void hsw_enable_pc8_work(struct work_struct *__work)
@@ -6447,6 +6683,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
        struct drm_device *dev = dev_priv->dev;
        uint32_t val;
 
+       WARN_ON(!HAS_PC8(dev));
+
        if (dev_priv->pc8.enabled)
                return;
 
@@ -6463,6 +6701,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
        lpt_disable_clkout_dp(dev);
        hsw_pc8_disable_interrupts(dev);
        hsw_disable_lcpll(dev_priv, true, true);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
@@ -6492,12 +6732,16 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
        if (dev_priv->pc8.disable_count != 1)
                return;
 
+       WARN_ON(!HAS_PC8(dev));
+
        cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
        if (!dev_priv->pc8.enabled)
                return;
 
        DRM_DEBUG_KMS("Disabling package C8+\n");
 
+       intel_runtime_pm_get(dev_priv);
+
        hsw_restore_lcpll(dev_priv);
        hsw_pc8_restore_interrupts(dev);
        lpt_init_pch_refclk(dev);
@@ -6704,8 +6948,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
        int plane = intel_crtc->plane;
        int ret;
 
-       if (!intel_ddi_pll_mode_set(crtc))
+       if (!intel_ddi_pll_select(intel_crtc))
                return -EINVAL;
+       intel_ddi_pll_enable(intel_crtc);
 
        if (intel_crtc->config.has_dp_encoder)
                intel_dp_set_m_n(intel_crtc);
@@ -6796,8 +7041,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        if (intel_display_power_enabled(dev, pfit_domain))
                ironlake_get_pfit_config(crtc, pipe_config);
 
-       pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
-                                  (I915_READ(IPS_CTL) & IPS_ENABLE);
+       if (IS_HASWELL(dev))
+               pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
+                       (I915_READ(IPS_CTL) & IPS_ENABLE);
 
        pipe_config->pixel_multiplier = 1;
 
@@ -7689,7 +7935,7 @@ static int i9xx_pll_refclk(struct drm_device *dev,
        u32 dpll = pipe_config->dpll_hw_state.dpll;
 
        if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
-               return dev_priv->vbt.lvds_ssc_freq * 1000;
+               return dev_priv->vbt.lvds_ssc_freq;
        else if (HAS_PCH_SPLIT(dev))
                return 120000;
        else if (!IS_GEN2(dev))
@@ -7752,12 +7998,17 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
                else
                        i9xx_clock(refclk, &clock);
        } else {
-               bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
+               u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS);
+               bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
 
                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 (lvds & LVDS_CLKB_POWER_UP)
+                               clock.p2 = 7;
+                       else
+                               clock.p2 = 14;
                } else {
                        if (dpll & PLL_P1_DIVIDE_BY_TWO)
                                clock.p1 = 2;
@@ -9100,7 +9351,9 @@ intel_pipe_config_compare(struct drm_device *dev,
                PIPE_CONF_CHECK_I(pch_pfit.size);
        }
 
-       PIPE_CONF_CHECK_I(ips_enabled);
+       /* BDW+ don't expose a synchronous way to read the state */
+       if (IS_HASWELL(dev))
+               PIPE_CONF_CHECK_I(ips_enabled);
 
        PIPE_CONF_CHECK_I(double_wide);
 
@@ -9113,7 +9366,7 @@ intel_pipe_config_compare(struct drm_device *dev,
        if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
                PIPE_CONF_CHECK_I(pipe_bpp);
 
-       if (!IS_HASWELL(dev)) {
+       if (!HAS_DDI(dev)) {
                PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock);
                PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
        }
@@ -9346,21 +9599,19 @@ static int __intel_set_mode(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_display_mode *saved_mode, *saved_hwmode;
+       struct drm_display_mode *saved_mode;
        struct intel_crtc_config *pipe_config = NULL;
        struct intel_crtc *intel_crtc;
        unsigned disable_pipes, prepare_pipes, modeset_pipes;
        int ret = 0;
 
-       saved_mode = kcalloc(2, sizeof(*saved_mode), GFP_KERNEL);
+       saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL);
        if (!saved_mode)
                return -ENOMEM;
-       saved_hwmode = saved_mode + 1;
 
        intel_modeset_affected_pipes(crtc, &modeset_pipes,
                                     &prepare_pipes, &disable_pipes);
 
-       *saved_hwmode = crtc->hwmode;
        *saved_mode = crtc->mode;
 
        /* Hack: Because we don't (yet) support global modeset on multiple
@@ -9380,6 +9631,21 @@ static int __intel_set_mode(struct drm_crtc *crtc,
                                       "[modeset]");
        }
 
+       /*
+        * See if the config requires any additional preparation, e.g.
+        * to adjust global state with pipes off.  We need to do this
+        * here so we can get the modeset_pipe updated config for the new
+        * mode set on this crtc.  For other crtcs we need to use the
+        * adjusted_mode bits in the crtc directly.
+        */
+       if (IS_VALLEYVIEW(dev)) {
+               valleyview_modeset_global_pipes(dev, &prepare_pipes,
+                                               modeset_pipes, pipe_config);
+
+               /* may have added more to prepare_pipes than we should */
+               prepare_pipes &= ~disable_pipes;
+       }
+
        for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
                intel_crtc_disable(&intel_crtc->base);
 
@@ -9396,6 +9662,14 @@ static int __intel_set_mode(struct drm_crtc *crtc,
                /* mode_set/enable/disable functions rely on a correct pipe
                 * config. */
                to_intel_crtc(crtc)->config = *pipe_config;
+
+               /*
+                * Calculate and store various constants which
+                * are later needed by vblank and swap-completion
+                * timestamping. They are derived from true hwmode.
+                */
+               drm_calc_timestamping_constants(crtc,
+                                               &pipe_config->adjusted_mode);
        }
 
        /* Only after disabling all output pipelines that will be changed can we
@@ -9419,23 +9693,10 @@ static int __intel_set_mode(struct drm_crtc *crtc,
        for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
                dev_priv->display.crtc_enable(&intel_crtc->base);
 
-       if (modeset_pipes) {
-               /* Store real post-adjustment hardware mode. */
-               crtc->hwmode = pipe_config->adjusted_mode;
-
-               /* Calculate and store various constants which
-                * are later needed by vblank and swap-completion
-                * timestamping. They are derived from true hwmode.
-                */
-               drm_calc_timestamping_constants(crtc);
-       }
-
        /* FIXME: add subpixel order */
 done:
-       if (ret && crtc->enabled) {
-               crtc->hwmode = *saved_hwmode;
+       if (ret && crtc->enabled)
                crtc->mode = *saved_mode;
-       }
 
 out:
        kfree(pipe_config);
@@ -9672,17 +9933,21 @@ intel_modeset_stage_output_state(struct drm_device *dev,
        /* Check for any encoders that needs to be disabled. */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list,
                            base.head) {
+               int num_connectors = 0;
                list_for_each_entry(connector,
                                    &dev->mode_config.connector_list,
                                    base.head) {
                        if (connector->new_encoder == encoder) {
                                WARN_ON(!connector->new_encoder->new_crtc);
-
-                               goto next_encoder;
+                               num_connectors++;
                        }
                }
-               encoder->new_crtc = NULL;
-next_encoder:
+
+               if (num_connectors == 0)
+                       encoder->new_crtc = NULL;
+               else if (num_connectors > 1)
+                       return -EINVAL;
+
                /* Only now check for crtc changes so we don't miss encoders
                 * that will be disabled. */
                if (&encoder->new_crtc->base != encoder->base.crtc) {
@@ -9753,6 +10018,16 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 
                ret = intel_pipe_set_base(set->crtc,
                                          set->x, set->y, set->fb);
+               /*
+                * In the fastboot case this may be our only check of the
+                * state after boot.  It would be better to only do it on
+                * the first update, but we don't have a nice way of doing that
+                * (and really, set_config isn't used much for high freq page
+                * flipping, so increasing its cost here shouldn't be a big
+                * deal).
+                */
+               if (i915_fastboot && ret == 0)
+                       intel_modeset_check_state(set->crtc->dev);
        }
 
        if (ret) {
@@ -9813,7 +10088,7 @@ static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
                                struct intel_shared_dpll *pll)
 {
        /* PCH refclock must be enabled first */
-       assert_pch_refclk_enabled(dev_priv);
+       ibx_assert_pch_refclk_enabled(dev_priv);
 
        I915_WRITE(PCH_DPLL(pll->id), pll->hw_state.dpll);
 
@@ -9881,8 +10156,6 @@ static void intel_shared_dpll_init(struct drm_device *dev)
                dev_priv->num_shared_dpll = 0;
 
        BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
-       DRM_DEBUG_KMS("%i shared PLLs initialized\n",
-                     dev_priv->num_shared_dpll);
 }
 
 static void intel_crtc_init(struct drm_device *dev, int pipe)
@@ -9904,10 +10177,13 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
                intel_crtc->lut_b[i] = i;
        }
 
-       /* Swap pipes & planes for FBC on pre-965 */
+       /*
+        * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
+        * is hooked to plane B. Hence we want plane A feeding pipe B.
+        */
        intel_crtc->pipe = pipe;
        intel_crtc->plane = pipe;
-       if (IS_MOBILE(dev) && IS_GEN3(dev)) {
+       if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) {
                DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
                intel_crtc->plane = !pipe;
        }
@@ -9996,6 +10272,28 @@ static bool has_edp_a(struct drm_device *dev)
        return true;
 }
 
+const char *intel_output_name(int output)
+{
+       static const char *names[] = {
+               [INTEL_OUTPUT_UNUSED] = "Unused",
+               [INTEL_OUTPUT_ANALOG] = "Analog",
+               [INTEL_OUTPUT_DVO] = "DVO",
+               [INTEL_OUTPUT_SDVO] = "SDVO",
+               [INTEL_OUTPUT_LVDS] = "LVDS",
+               [INTEL_OUTPUT_TVOUT] = "TV",
+               [INTEL_OUTPUT_HDMI] = "HDMI",
+               [INTEL_OUTPUT_DISPLAYPORT] = "DisplayPort",
+               [INTEL_OUTPUT_EDP] = "eDP",
+               [INTEL_OUTPUT_DSI] = "DSI",
+               [INTEL_OUTPUT_UNKNOWN] = "Unknown",
+       };
+
+       if (output < 0 || output >= ARRAY_SIZE(names) || !names[output])
+               return "Invalid";
+
+       return names[output];
+}
+
 static void intel_setup_outputs(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -10390,8 +10688,11 @@ static void intel_init_display(struct drm_device *dev)
                }
        } else if (IS_G4X(dev)) {
                dev_priv->display.write_eld = g4x_write_eld;
-       } else if (IS_VALLEYVIEW(dev))
+       } else if (IS_VALLEYVIEW(dev)) {
+               dev_priv->display.modeset_global_resources =
+                       valleyview_modeset_global_resources;
                dev_priv->display.write_eld = ironlake_write_eld;
+       }
 
        /* Default just returns -ENODEV to indicate unsupported */
        dev_priv->display.queue_flip = intel_default_queue_flip;
@@ -10418,6 +10719,8 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.queue_flip = intel_gen7_queue_flip;
                break;
        }
+
+       intel_panel_init_backlight_funcs(dev);
 }
 
 /*
@@ -10454,17 +10757,6 @@ static void quirk_invert_brightness(struct drm_device *dev)
        DRM_INFO("applying inverted panel brightness quirk\n");
 }
 
-/*
- * Some machines (Dell XPS13) suffer broken backlight controls if
- * BLM_PCH_PWM_ENABLE is set.
- */
-static void quirk_no_pcm_pwm_enable(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE;
-       DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n");
-}
-
 struct intel_quirk {
        int device;
        int subsystem_vendor;
@@ -10519,16 +10811,20 @@ static struct intel_quirk intel_quirks[] = {
        /* Sony Vaio Y cannot use SSC on LVDS */
        { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
 
-       /*
-        * All GM45 Acer (and its brands eMachines and Packard Bell) laptops
-        * seem to use inverted backlight PWM.
-        */
-       { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness },
+       /* Acer Aspire 5734Z must invert backlight brightness */
+       { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
+
+       /* Acer/eMachines G725 */
+       { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
+
+       /* Acer/eMachines e725 */
+       { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
 
-       /* Dell XPS13 HD Sandy Bridge */
-       { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
-       /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */
-       { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable },
+       /* Acer/Packard Bell NCL20 */
+       { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
+
+       /* Acer Aspire 4736Z */
+       { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
@@ -10572,18 +10868,11 @@ static void i915_disable_vga(struct drm_device *dev)
 
 void intel_modeset_init_hw(struct drm_device *dev)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
        intel_prepare_ddi(dev);
 
        intel_init_clock_gating(dev);
 
-       /* Enable the CRI clock source so we can get at the display */
-       if (IS_VALLEYVIEW(dev))
-               I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
-                          DPLL_INTEGRATED_CRI_CLK_VLV);
-
-       intel_init_dpio(dev);
+       intel_reset_dpio(dev);
 
        mutex_lock(&dev->struct_mutex);
        intel_enable_gt_powersave(dev);
@@ -10645,6 +10934,9 @@ void intel_modeset_init(struct drm_device *dev)
                }
        }
 
+       intel_init_dpio(dev);
+       intel_reset_dpio(dev);
+
        intel_cpu_pll_init(dev);
        intel_shared_dpll_init(dev);
 
@@ -10848,7 +11140,7 @@ void i915_redisable_vga(struct drm_device *dev)
         * level, just check if the power well is enabled instead of trying to
         * follow the "don't touch the power well if we don't need it" policy
         * the rest of the driver uses. */
-       if (HAS_POWER_WELL(dev) &&
+       if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) &&
            (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0)
                return;
 
@@ -10992,7 +11284,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
                pll->on = false;
        }
 
-       if (IS_HASWELL(dev))
+       if (HAS_PCH_SPLIT(dev))
                ilk_wm_get_hw_state(dev);
 
        if (force_restore) {
@@ -11014,8 +11306,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
        }
 
        intel_modeset_check_state(dev);
-
-       drm_mode_config_reset(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
@@ -11024,7 +11314,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
 
        intel_setup_overlay(dev);
 
+       mutex_lock(&dev->mode_config.mutex);
+       drm_mode_config_reset(dev);
        intel_modeset_setup_hw_state(dev, false);
+       mutex_unlock(&dev->mode_config.mutex);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -11069,12 +11362,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
 
-       /* destroy backlight, if any, before the connectors */
-       intel_panel_destroy_backlight(dev);
-
-       /* destroy the sysfs files before encoders/connectors */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+       /* destroy the backlight and sysfs files before encoders/connectors */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               intel_panel_destroy_backlight(connector);
                drm_sysfs_connector_remove(connector);
+       }
 
        drm_mode_config_cleanup(dev);
 
@@ -11103,14 +11395,15 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
 int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
        u16 gmch_ctrl;
 
-       pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
+       pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl);
        if (state)
                gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
        else
                gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-       pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
+       pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl);
        return 0;
 }
 
@@ -11128,6 +11421,7 @@ struct intel_display_error_state {
        } cursor[I915_MAX_PIPES];
 
        struct intel_pipe_error_state {
+               bool power_domain_on;
                u32 source;
        } pipe[I915_MAX_PIPES];
 
@@ -11142,6 +11436,7 @@ struct intel_display_error_state {
        } plane[I915_MAX_PIPES];
 
        struct intel_transcoder_error_state {
+               bool power_domain_on;
                enum transcoder cpu_transcoder;
 
                u32 conf;
@@ -11175,11 +11470,13 @@ intel_display_capture_error_state(struct drm_device *dev)
        if (error == NULL)
                return NULL;
 
-       if (HAS_POWER_WELL(dev))
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 
        for_each_pipe(i) {
-               if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i)))
+               error->pipe[i].power_domain_on =
+                       intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
+               if (!error->pipe[i].power_domain_on)
                        continue;
 
                if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
@@ -11215,8 +11512,10 @@ intel_display_capture_error_state(struct drm_device *dev)
        for (i = 0; i < error->num_transcoders; i++) {
                enum transcoder cpu_transcoder = transcoders[i];
 
-               if (!intel_display_power_enabled(dev,
-                               POWER_DOMAIN_TRANSCODER(cpu_transcoder)))
+               error->transcoder[i].power_domain_on =
+                       intel_display_power_enabled_sw(dev,
+                               POWER_DOMAIN_TRANSCODER(cpu_transcoder));
+               if (!error->transcoder[i].power_domain_on)
                        continue;
 
                error->transcoder[i].cpu_transcoder = cpu_transcoder;
@@ -11246,11 +11545,13 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                return;
 
        err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
-       if (HAS_POWER_WELL(dev))
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                err_printf(m, "PWR_WELL_CTL2: %08x\n",
                           error->power_well_driver);
        for_each_pipe(i) {
                err_printf(m, "Pipe [%d]:\n", i);
+               err_printf(m, "  Power: %s\n",
+                          error->pipe[i].power_domain_on ? "on" : "off");
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
 
                err_printf(m, "Plane [%d]:\n", i);
@@ -11276,6 +11577,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
        for (i = 0; i < error->num_transcoders; i++) {
                err_printf(m, "CPU transcoder: %c\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
+               err_printf(m, "  Power: %s\n",
+                          error->transcoder[i].power_domain_on ? "on" : "off");
                err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
                err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
                err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
index 30c627c7b7ba18a0dbd546859b047a769cad1d64..5ede4e8e290df5cc2f3e1b7046ec409b9f50d538 100644 (file)
@@ -142,7 +142,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
        return (max_link_clock * max_lanes * 8) / 10;
 }
 
-static int
+static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
 {
@@ -404,7 +404,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        int i, ret, recv_bytes;
        uint32_t status;
        int try, precharge, clock = 0;
-       bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev);
+       bool has_aux_irq = true;
        uint32_t timeout;
 
        /* dp aux is extremely sensitive to irq latency, hence request the
@@ -542,7 +542,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
                return -E2BIG;
 
        intel_dp_check_edp(intel_dp);
-       msg[0] = AUX_NATIVE_WRITE << 4;
+       msg[0] = DP_AUX_NATIVE_WRITE << 4;
        msg[1] = address >> 8;
        msg[2] = address & 0xff;
        msg[3] = send_bytes - 1;
@@ -552,9 +552,10 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+               ack >>= 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        break;
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
                        udelay(100);
                else
                        return -EIO;
@@ -586,7 +587,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
                return -E2BIG;
 
        intel_dp_check_edp(intel_dp);
-       msg[0] = AUX_NATIVE_READ << 4;
+       msg[0] = DP_AUX_NATIVE_READ << 4;
        msg[1] = address >> 8;
        msg[2] = address & 0xff;
        msg[3] = recv_bytes - 1;
@@ -601,12 +602,12 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
                        return -EPROTO;
                if (ret < 0)
                        return ret;
-               ack = reply[0];
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+               ack = reply[0] >> 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) {
                        memcpy(recv, reply + 1, ret - 1);
                        return ret - 1;
                }
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
                        udelay(100);
                else
                        return -EIO;
@@ -633,12 +634,12 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
        intel_dp_check_edp(intel_dp);
        /* Set up the command byte */
        if (mode & MODE_I2C_READ)
-               msg[0] = AUX_I2C_READ << 4;
+               msg[0] = DP_AUX_I2C_READ << 4;
        else
-               msg[0] = AUX_I2C_WRITE << 4;
+               msg[0] = DP_AUX_I2C_WRITE << 4;
 
        if (!(mode & MODE_I2C_STOP))
-               msg[0] |= AUX_I2C_MOT << 4;
+               msg[0] |= DP_AUX_I2C_MOT << 4;
 
        msg[1] = address >> 8;
        msg[2] = address;
@@ -675,17 +676,17 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        goto out;
                }
 
-               switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
-               case AUX_NATIVE_REPLY_ACK:
+               switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
+               case DP_AUX_NATIVE_REPLY_ACK:
                        /* I2C-over-AUX Reply field is only valid
                         * when paired with AUX ACK.
                         */
                        break;
-               case AUX_NATIVE_REPLY_NACK:
+               case DP_AUX_NATIVE_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_ch native nack\n");
                        ret = -EREMOTEIO;
                        goto out;
-               case AUX_NATIVE_REPLY_DEFER:
+               case DP_AUX_NATIVE_REPLY_DEFER:
                        /*
                         * For now, just give more slack to branch devices. We
                         * could check the DPCD for I2C bit rate capabilities,
@@ -706,18 +707,18 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        goto out;
                }
 
-               switch (reply[0] & AUX_I2C_REPLY_MASK) {
-               case AUX_I2C_REPLY_ACK:
+               switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) {
+               case DP_AUX_I2C_REPLY_ACK:
                        if (mode == MODE_I2C_READ) {
                                *read_byte = reply[1];
                        }
                        ret = reply_bytes - 1;
                        goto out;
-               case AUX_I2C_REPLY_NACK:
+               case DP_AUX_I2C_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_i2c nack\n");
                        ret = -EREMOTEIO;
                        goto out;
-               case AUX_I2C_REPLY_DEFER:
+               case DP_AUX_I2C_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_i2c defer\n");
                        udelay(100);
                        break;
@@ -1037,6 +1038,8 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
                                I915_READ(pp_stat_reg),
                                I915_READ(pp_ctrl_reg));
        }
+
+       DRM_DEBUG_KMS("Wait complete\n");
 }
 
 static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
@@ -1092,6 +1095,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
        if (ironlake_edp_have_panel_vdd(intel_dp))
                return;
 
+       intel_runtime_pm_get(dev_priv);
+
        DRM_DEBUG_KMS("Turning eDP VDD on\n");
 
        if (!ironlake_edp_have_panel_power(intel_dp))
@@ -1140,7 +1145,11 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
                /* Make sure sequencer is idle before allowing subsequent activity */
                DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
                I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
-               msleep(intel_dp->panel_power_down_delay);
+
+               if ((pp & POWER_TARGET_ON) == 0)
+                       msleep(intel_dp->panel_power_cycle_delay);
+
+               intel_runtime_pm_put(dev_priv);
        }
 }
 
@@ -1233,20 +1242,16 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
        DRM_DEBUG_KMS("Turn eDP power off\n");
 
-       WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
-
        pp = ironlake_get_pp_control(intel_dp);
        /* We need to switch off panel power _and_ force vdd, for otherwise some
         * panels get very unhappy and cease to work. */
-       pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+       pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 
        pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
        I915_WRITE(pp_ctrl_reg, pp);
        POSTING_READ(pp_ctrl_reg);
 
-       intel_dp->want_panel_vdd = false;
-
        ironlake_wait_panel_off(intel_dp);
 }
 
@@ -1772,7 +1777,6 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 
        /* Make sure the panel is off before trying to change the mode. But also
         * ensure that we have vdd while we switch off the panel. */
-       ironlake_edp_panel_vdd_on(intel_dp);
        ironlake_edp_backlight_off(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
        ironlake_edp_panel_off(intel_dp);
@@ -1845,23 +1849,23 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
        struct edp_power_seq power_seq;
        u32 val;
 
        mutex_lock(&dev_priv->dpio_lock);
 
-       val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port));
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
        val = 0;
        if (pipe)
                val |= (1<<21);
        else
                val &= ~(1<<21);
        val |= 0x001000c4;
-       vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), 0x00760018);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), 0x00400888);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
 
        mutex_unlock(&dev_priv->dpio_lock);
 
@@ -1872,7 +1876,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 
        intel_enable_dp(encoder);
 
-       vlv_wait_port_ready(dev_priv, port);
+       vlv_wait_port_ready(dev_priv, dport);
 }
 
 static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
@@ -1882,24 +1886,24 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        /* Program Tx lane resets to default */
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
                         DPIO_PCS_TX_LANE2_RESET |
                         DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port),
                         DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
                         DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
                         (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
                                 DPIO_PCS_CLK_SOFT_RESET);
 
        /* Fix up inter-pair skew failure */
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -1941,18 +1945,6 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_
                                              DP_LINK_STATUS_SIZE);
 }
 
-#if 0
-static char    *voltage_names[] = {
-       "0.4V", "0.6V", "0.8V", "1.2V"
-};
-static char    *pre_emph_names[] = {
-       "0dB", "3.5dB", "6dB", "9.5dB"
-};
-static char    *link_train_names[] = {
-       "pattern 1", "pattern 2", "idle", "off"
-};
-#endif
-
 /*
  * These are source-specific values; current Intel hardware supports
  * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
@@ -2050,7 +2042,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
        unsigned long demph_reg_value, preemph_reg_value,
                uniqtranscale_reg_value;
        uint8_t train_set = intel_dp->train_set[0];
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
@@ -2127,14 +2119,14 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
        }
 
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x00000000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), demph_reg_value);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port),
                         uniqtranscale_reg_value);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), 0x0C782040);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), preemph_reg_value);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x80000000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0C782040);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x80000000);
        mutex_unlock(&dev_priv->dpio_lock);
 
        return 0;
@@ -2646,7 +2638,6 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 
                if (cr_tries > 5) {
                        DRM_ERROR("failed to train DP, aborting\n");
-                       intel_dp_link_down(intel_dp);
                        break;
                }
 
@@ -2899,13 +2890,11 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
 
        /* Try to read receiver status if the link appears to be up */
        if (!intel_dp_get_link_status(intel_dp, link_status)) {
-               intel_dp_link_down(intel_dp);
                return;
        }
 
        /* Now read the DPCD to see if it's actually running */
        if (!intel_dp_get_dpcd(intel_dp)) {
-               intel_dp_link_down(intel_dp);
                return;
        }
 
@@ -3020,18 +3009,34 @@ g4x_dp_detect(struct intel_dp *intel_dp)
                return status;
        }
 
-       switch (intel_dig_port->port) {
-       case PORT_B:
-               bit = PORTB_HOTPLUG_LIVE_STATUS;
-               break;
-       case PORT_C:
-               bit = PORTC_HOTPLUG_LIVE_STATUS;
-               break;
-       case PORT_D:
-               bit = PORTD_HOTPLUG_LIVE_STATUS;
-               break;
-       default:
-               return connector_status_unknown;
+       if (IS_VALLEYVIEW(dev)) {
+               switch (intel_dig_port->port) {
+               case PORT_B:
+                       bit = PORTB_HOTPLUG_LIVE_STATUS_VLV;
+                       break;
+               case PORT_C:
+                       bit = PORTC_HOTPLUG_LIVE_STATUS_VLV;
+                       break;
+               case PORT_D:
+                       bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
+                       break;
+               default:
+                       return connector_status_unknown;
+               }
+       } else {
+               switch (intel_dig_port->port) {
+               case PORT_B:
+                       bit = PORTB_HOTPLUG_LIVE_STATUS_G4X;
+                       break;
+               case PORT_C:
+                       bit = PORTC_HOTPLUG_LIVE_STATUS_G4X;
+                       break;
+               case PORT_D:
+                       bit = PORTD_HOTPLUG_LIVE_STATUS_G4X;
+                       break;
+               default:
+                       return connector_status_unknown;
+               }
        }
 
        if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0)
@@ -3082,9 +3087,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct intel_encoder *intel_encoder = &intel_dig_port->base;
        struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        enum drm_connector_status status;
        struct edid *edid = NULL;
 
+       intel_runtime_pm_get(dev_priv);
+
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, drm_get_connector_name(connector));
 
@@ -3096,7 +3104,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                status = g4x_dp_detect(intel_dp);
 
        if (status != connector_status_connected)
-               return status;
+               goto out;
 
        intel_dp_probe_oui(intel_dp);
 
@@ -3112,7 +3120,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 
        if (intel_encoder->type != INTEL_OUTPUT_EDP)
                intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-       return connector_status_connected;
+       status = connector_status_connected;
+
+out:
+       intel_runtime_pm_put(dev_priv);
+       return status;
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
index a18e88b3e4250a1e51b21bd8db18729743918f3a..fbfaaba5cc3b2a079ae9749401d5602c6674cf07 100644 (file)
@@ -65,8 +65,8 @@
 #define wait_for_atomic_us(COND, US) _wait_for((COND), \
                                               DIV_ROUND_UP((US), 1000), 0)
 
-#define KHz(x) (1000*x)
-#define MHz(x) KHz(1000*x)
+#define KHz(x) (1000 * (x))
+#define MHz(x) KHz(1000 * (x))
 
 /*
  * Display related stuff
@@ -155,7 +155,19 @@ struct intel_encoder {
 
 struct intel_panel {
        struct drm_display_mode *fixed_mode;
+       struct drm_display_mode *downclock_mode;
        int fitting_mode;
+
+       /* backlight */
+       struct {
+               bool present;
+               u32 level;
+               u32 max;
+               bool enabled;
+               bool combination_mode;  /* gen 2/4 only */
+               bool active_low_pwm;
+               struct backlight_device *device;
+       } backlight;
 };
 
 struct intel_connector {
@@ -443,7 +455,7 @@ struct intel_hdmi {
        bool rgb_quant_range_selectable;
        void (*write_infoframe)(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len);
+                               const void *frame, ssize_t len);
        void (*set_infoframes)(struct drm_encoder *encoder,
                               struct drm_display_mode *adjusted_mode);
 };
@@ -490,9 +502,9 @@ vlv_dport_to_channel(struct intel_digital_port *dport)
 {
        switch (dport->port) {
        case PORT_B:
-               return 0;
+               return DPIO_CH0;
        case PORT_C:
-               return 1;
+               return DPIO_CH1;
        default:
                BUG();
        }
@@ -601,7 +613,8 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
 void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
-bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
+bool intel_ddi_pll_select(struct intel_crtc *crtc);
+void intel_ddi_pll_enable(struct intel_crtc *crtc);
 void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
 void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
@@ -612,6 +625,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
 
 
 /* intel_display.c */
+const char *intel_output_name(int output);
+bool intel_has_pending_fb_unpin(struct drm_device *dev);
 int intel_pch_rawclk(struct drm_device *dev);
 void intel_mark_busy(struct drm_device *dev);
 void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
@@ -638,7 +653,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
 void intel_wait_for_vblank(struct drm_device *dev, int pipe);
 void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
 int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
-void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port);
+void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
+                        struct intel_digital_port *dport);
 bool intel_get_load_detect_pipe(struct drm_connector *connector,
                                struct drm_display_mode *mode,
                                struct intel_load_detect_pipe *old);
@@ -690,11 +706,10 @@ void
 ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
                                int dotclock);
 bool intel_crtc_active(struct drm_crtc *crtc);
-void i915_disable_vga_mem(struct drm_device *dev);
 void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 void intel_display_set_init_power(struct drm_device *dev, bool enable);
-
+int valleyview_get_vco(struct drm_i915_private *dev_priv);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
@@ -808,9 +823,13 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
 int intel_panel_setup_backlight(struct drm_connector *connector);
 void intel_panel_enable_backlight(struct intel_connector *connector);
 void intel_panel_disable_backlight(struct intel_connector *connector);
-void intel_panel_destroy_backlight(struct drm_device *dev);
+void intel_panel_destroy_backlight(struct drm_connector *connector);
+void intel_panel_init_backlight_funcs(struct drm_device *dev);
 enum drm_connector_status intel_panel_detect(struct drm_device *dev);
-
+extern struct drm_display_mode *intel_find_panel_downclock(
+                               struct drm_device *dev,
+                               struct drm_display_mode *fixed_mode,
+                               struct drm_connector *connector);
 
 /* intel_pm.c */
 void intel_init_clock_gating(struct drm_device *dev);
@@ -821,6 +840,7 @@ void intel_update_sprite_watermarks(struct drm_plane *plane,
                                    uint32_t sprite_width, int pixel_size,
                                    bool enabled, bool scaled);
 void intel_init_pm(struct drm_device *dev);
+void intel_pm_setup(struct drm_device *dev);
 bool intel_fbc_enabled(struct drm_device *dev);
 void intel_update_fbc(struct drm_device *dev);
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
@@ -829,6 +849,8 @@ int intel_power_domains_init(struct drm_device *dev);
 void intel_power_domains_remove(struct drm_device *dev);
 bool intel_display_power_enabled(struct drm_device *dev,
                                 enum intel_display_power_domain domain);
+bool intel_display_power_enabled_sw(struct drm_device *dev,
+                                   enum intel_display_power_domain domain);
 void intel_display_power_get(struct drm_device *dev,
                             enum intel_display_power_domain domain);
 void intel_display_power_put(struct drm_device *dev,
@@ -843,6 +865,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 
 
index d257b093ca68757874925999fae766a727755212..fabbf0d895cf2a5e133d804d5e8e05f0f26f79ad 100644 (file)
 static const struct intel_dsi_device intel_dsi_devices[] = {
 };
 
-
-static void vlv_cck_modify(struct drm_i915_private *dev_priv, u32 reg, u32 val,
-                          u32 mask)
-{
-       u32 tmp = vlv_cck_read(dev_priv, reg);
-       tmp &= ~mask;
-       tmp |= val;
-       vlv_cck_write(dev_priv, reg, tmp);
-}
-
-static void band_gap_wa(struct drm_i915_private *dev_priv)
+static void band_gap_reset(struct drm_i915_private *dev_priv)
 {
        mutex_lock(&dev_priv->dpio_lock);
 
-       /* Enable bandgap fix in GOP driver */
-       vlv_cck_modify(dev_priv, 0x6D, 0x00010000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x6E, 0x00010000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x6F, 0x00010000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x00, 0x00008000, 0x00008000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x00, 0x00000000, 0x00008000);
-       msleep(20);
-
-       /* Turn Display Trunk on */
-       vlv_cck_modify(dev_priv, 0x6B, 0x00020000, 0x00030000);
-       msleep(20);
-
-       vlv_cck_modify(dev_priv, 0x6C, 0x00020000, 0x00030000);
-       msleep(20);
-
-       vlv_cck_modify(dev_priv, 0x6D, 0x00020000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x6E, 0x00020000, 0x00030000);
-       msleep(20);
-       vlv_cck_modify(dev_priv, 0x6F, 0x00020000, 0x00030000);
+       vlv_flisdsi_write(dev_priv, 0x08, 0x0001);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0005);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0025);
+       udelay(150);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0000);
+       vlv_flisdsi_write(dev_priv, 0x08, 0x0000);
 
        mutex_unlock(&dev_priv->dpio_lock);
-
-       /* Need huge delay, otherwise clock is not stable */
-       msleep(100);
 }
 
 static struct intel_dsi *intel_attached_dsi(struct drm_connector *connector)
@@ -132,14 +101,47 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)
        vlv_enable_dsi_pll(encoder);
 }
 
+static void intel_dsi_device_ready(struct intel_encoder *encoder)
+{
+       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+       int pipe = intel_crtc->pipe;
+       u32 val;
+
+       DRM_DEBUG_KMS("\n");
+
+       val = I915_READ(MIPI_PORT_CTRL(pipe));
+       I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD);
+       usleep_range(1000, 1500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
+       usleep_range(2000, 2500);
+}
 static void intel_dsi_pre_enable(struct intel_encoder *encoder)
 {
+       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+
        DRM_DEBUG_KMS("\n");
+
+       if (intel_dsi->dev.dev_ops->panel_reset)
+               intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev);
+
+       /* put device in ready state */
+       intel_dsi_device_ready(encoder);
+
+       if (intel_dsi->dev.dev_ops->send_otp_cmds)
+               intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
 }
 
 static void intel_dsi_enable(struct intel_encoder *encoder)
 {
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        int pipe = intel_crtc->pipe;
@@ -147,41 +149,28 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
 
        DRM_DEBUG_KMS("\n");
 
-       temp = I915_READ(MIPI_DEVICE_READY(pipe));
-       if ((temp & DEVICE_READY) == 0) {
-               temp &= ~ULPS_STATE_MASK;
-               I915_WRITE(MIPI_DEVICE_READY(pipe), temp | DEVICE_READY);
-       } else if (temp & ULPS_STATE_MASK) {
-               temp &= ~ULPS_STATE_MASK;
-               I915_WRITE(MIPI_DEVICE_READY(pipe), temp | ULPS_STATE_EXIT);
-               /*
-                * We need to ensure that there is a minimum of 1 ms time
-                * available before clearing the UPLS exit state.
-                */
-               msleep(2);
-               I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
-       }
-
        if (is_cmd_mode(intel_dsi))
                I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4);
-
-       if (is_vid_mode(intel_dsi)) {
+       else {
                msleep(20); /* XXX */
                dpi_send_cmd(intel_dsi, TURN_ON);
                msleep(100);
 
                /* assert ip_tg_enable signal */
-               temp = I915_READ(MIPI_PORT_CTRL(pipe));
+               temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK;
+               temp = temp | intel_dsi->port_bits;
                I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE);
                POSTING_READ(MIPI_PORT_CTRL(pipe));
        }
 
-       intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
+       if (intel_dsi->dev.dev_ops->enable)
+               intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
 }
 
 static void intel_dsi_disable(struct intel_encoder *encoder)
 {
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        int pipe = intel_crtc->pipe;
@@ -189,8 +178,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
 
        DRM_DEBUG_KMS("\n");
 
-       intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
-
        if (is_vid_mode(intel_dsi)) {
                dpi_send_cmd(intel_dsi, SHUTDOWN);
                msleep(10);
@@ -203,20 +190,54 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
                msleep(2);
        }
 
-       temp = I915_READ(MIPI_DEVICE_READY(pipe));
-       if (temp & DEVICE_READY) {
-               temp &= ~DEVICE_READY;
-               temp &= ~ULPS_STATE_MASK;
-               I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
-       }
+       /* if disable packets are sent before sending shutdown packet then in
+        * some next enable sequence send turn on packet error is observed */
+       if (intel_dsi->dev.dev_ops->disable)
+               intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
 }
 
-static void intel_dsi_post_disable(struct intel_encoder *encoder)
+static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
 {
+       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+       int pipe = intel_crtc->pipe;
+       u32 val;
+
        DRM_DEBUG_KMS("\n");
 
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
+       usleep_range(2000, 2500);
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT);
+       usleep_range(2000, 2500);
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
+       usleep_range(2000, 2500);
+
+       val = I915_READ(MIPI_PORT_CTRL(pipe));
+       I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD);
+       usleep_range(1000, 1500);
+
+       if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT)
+                                       == 0x00000), 30))
+               DRM_ERROR("DSI LP not going Low\n");
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
+       usleep_range(2000, 2500);
+
        vlv_disable_dsi_pll(encoder);
 }
+static void intel_dsi_post_disable(struct intel_encoder *encoder)
+{
+       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+
+       DRM_DEBUG_KMS("\n");
+
+       intel_dsi_clear_device_ready(encoder);
+
+       if (intel_dsi->dev.dev_ops->disable_panel_power)
+               intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev);
+}
 
 static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
                                   enum pipe *pipe)
@@ -251,8 +272,9 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
        /* XXX: read flags, set to adjusted_mode */
 }
 
-static int intel_dsi_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_dsi_mode_valid(struct drm_connector *connector,
+                    struct drm_display_mode *mode)
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
@@ -352,11 +374,8 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
 
        DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
 
-       /* Update the DSI PLL */
-       vlv_enable_dsi_pll(intel_encoder);
-
        /* XXX: Location of the call */
-       band_gap_wa(dev_priv);
+       band_gap_reset(dev_priv);
 
        /* escape clock divider, 20MHz, shared for A and C. device ready must be
         * off when doing this! txclkesc? */
@@ -373,11 +392,7 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
        I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff);
        I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff);
 
-       I915_WRITE(MIPI_DPHY_PARAM(pipe),
-                  0x3c << EXIT_ZERO_COUNT_SHIFT |
-                  0x1f << TRAIL_COUNT_SHIFT |
-                  0xc5 << CLK_ZERO_COUNT_SHIFT |
-                  0x1f << PREPARE_COUNT_SHIFT);
+       I915_WRITE(MIPI_DPHY_PARAM(pipe), intel_dsi->dphy_reg);
 
        I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
                   adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
@@ -425,9 +440,9 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
                                       adjusted_mode->htotal,
                                       bpp, intel_dsi->lane_count) + 1);
        }
-       I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), 8309); /* max */
-       I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), 0x14); /* max */
-       I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), 0xffff); /* max */
+       I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
+       I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
+       I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), intel_dsi->rst_timer_val);
 
        /* dphy stuff */
 
@@ -442,29 +457,31 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
         *
         * XXX: write MIPI_STOP_STATE_STALL?
         */
-       I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), 0x46);
+       I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe),
+                                               intel_dsi->hs_to_lp_count);
 
        /* XXX: low power clock equivalence in terms of byte clock. the number
         * of byte clocks occupied in one low power clock. based on txbyteclkhs
         * and txclkesc. txclkesc time / txbyteclk time * (105 +
         * MIPI_STOP_STATE_STALL) / 105.???
         */
-       I915_WRITE(MIPI_LP_BYTECLK(pipe), 4);
+       I915_WRITE(MIPI_LP_BYTECLK(pipe), intel_dsi->lp_byte_clk);
 
        /* the bw essential for transmitting 16 long packets containing 252
         * bytes meant for dcs write memory command is programmed in this
         * register in terms of byte clocks. based on dsi transfer rate and the
         * number of lanes configured the time taken to transmit 16 long packets
         * in a dsi stream varies. */
-       I915_WRITE(MIPI_DBI_BW_CTRL(pipe), 0x820);
+       I915_WRITE(MIPI_DBI_BW_CTRL(pipe), intel_dsi->bw_timer);
 
        I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe),
-                  0xa << LP_HS_SSW_CNT_SHIFT |
-                  0x14 << HS_LP_PWR_SW_CNT_SHIFT);
+                  intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT |
+                  intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);
 
        if (is_vid_mode(intel_dsi))
                I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
-                          intel_dsi->video_mode_format);
+                               intel_dsi->video_frmt_cfg_bits |
+                               intel_dsi->video_mode_format);
 }
 
 static enum drm_connector_status
index c7765f33d5245fa2ff1fd03fe2bb12339a716473..b4a27cec882f76d7cab17400d8adf438532b4c9d 100644 (file)
@@ -39,6 +39,13 @@ struct intel_dsi_device {
 struct intel_dsi_dev_ops {
        bool (*init)(struct intel_dsi_device *dsi);
 
+       void (*panel_reset)(struct intel_dsi_device *dsi);
+
+       void (*disable_panel_power)(struct intel_dsi_device *dsi);
+
+       /* one time programmable commands if needed */
+       void (*send_otp_cmds)(struct intel_dsi_device *dsi);
+
        /* This callback must be able to assume DSI commands can be sent */
        void (*enable)(struct intel_dsi_device *dsi);
 
@@ -89,6 +96,20 @@ struct intel_dsi {
 
        /* eot for MIPI_EOT_DISABLE register */
        u32 eot_disable;
+
+       u32 port_bits;
+       u32 bw_timer;
+       u32 dphy_reg;
+       u32 video_frmt_cfg_bits;
+       u16 lp_byte_clk;
+
+       /* timeouts in byte clocks */
+       u16 lp_rx_timeout;
+       u16 turn_arnd_val;
+       u16 rst_timer_val;
+       u16 hs_to_lp_count;
+       u16 clk_lp_to_hs_count;
+       u16 clk_hs_to_lp_count;
 };
 
 static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
index 44279b2ade888a7821d75da44ab523ab8f1f318a..ba79ec19da3b8ce8d4379df2545c1ea54c3a8f3e 100644 (file)
@@ -50,6 +50,8 @@ static const u32 lfsr_converts[] = {
        71, 35                                                  /* 91 - 92 */
 };
 
+#ifdef DSI_CLK_FROM_RR
+
 static u32 dsi_rr_formula(const struct drm_display_mode *mode,
                          int pixel_format, int video_mode_format,
                          int lane_count, bool eotp)
@@ -121,7 +123,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
 
        /* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */
        dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8;
-       dsi_clk = dsi_bit_clock_hz / (1000 * 1000);
+       dsi_clk = dsi_bit_clock_hz / 1000;
 
        if (eotp && video_mode_format == VIDEO_MODE_BURST)
                dsi_clk *= 2;
@@ -129,64 +131,37 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
        return dsi_clk;
 }
 
-#ifdef MNP_FROM_TABLE
-
-struct dsi_clock_table {
-       u32 freq;
-       u8 m;
-       u8 p;
-};
-
-static const struct dsi_clock_table dsi_clk_tbl[] = {
-       {300, 72, 6}, {313, 75, 6}, {323, 78, 6}, {333, 80, 6},
-       {343, 82, 6}, {353, 85, 6}, {363, 87, 6}, {373, 90, 6},
-       {383, 92, 6}, {390, 78, 5}, {393, 79, 5}, {400, 80, 5},
-       {401, 80, 5}, {402, 80, 5}, {403, 81, 5}, {404, 81, 5},
-       {405, 81, 5}, {406, 81, 5}, {407, 81, 5}, {408, 82, 5},
-       {409, 82, 5}, {410, 82, 5}, {411, 82, 5}, {412, 82, 5},
-       {413, 83, 5}, {414, 83, 5}, {415, 83, 5}, {416, 83, 5},
-       {417, 83, 5}, {418, 84, 5}, {419, 84, 5}, {420, 84, 5},
-       {430, 86, 5}, {440, 88, 5}, {450, 90, 5}, {460, 92, 5},
-       {470, 75, 4}, {480, 77, 4}, {490, 78, 4}, {500, 80, 4},
-       {510, 82, 4}, {520, 83, 4}, {530, 85, 4}, {540, 86, 4},
-       {550, 88, 4}, {560, 90, 4}, {570, 91, 4}, {580, 70, 3},
-       {590, 71, 3}, {600, 72, 3}, {610, 73, 3}, {620, 74, 3},
-       {630, 76, 3}, {640, 77, 3}, {650, 78, 3}, {660, 79, 3},
-       {670, 80, 3}, {680, 82, 3}, {690, 83, 3}, {700, 84, 3},
-       {710, 85, 3}, {720, 86, 3}, {730, 88, 3}, {740, 89, 3},
-       {750, 90, 3}, {760, 91, 3}, {770, 92, 3}, {780, 62, 2},
-       {790, 63, 2}, {800, 64, 2}, {880, 70, 2}, {900, 72, 2},
-       {1000, 80, 2},          /* dsi clock frequency in Mhz*/
-};
+#else
 
-static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
+/* Get DSI clock from pixel clock */
+static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
+                         int pixel_format, int lane_count)
 {
-       unsigned int i;
-       u8 m;
-       u8 n;
-       u8 p;
-       u32 m_seed;
-
-       if (dsi_clk < 300 || dsi_clk > 1000)
-               return -ECHRNG;
+       u32 dsi_clk_khz;
+       u32 bpp;
 
-       for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) {
-               if (dsi_clk_tbl[i].freq > dsi_clk)
-                       break;
+       switch (pixel_format) {
+       default:
+       case VID_MODE_FORMAT_RGB888:
+       case VID_MODE_FORMAT_RGB666_LOOSE:
+               bpp = 24;
+               break;
+       case VID_MODE_FORMAT_RGB666:
+               bpp = 18;
+               break;
+       case VID_MODE_FORMAT_RGB565:
+               bpp = 16;
+               break;
        }
 
-       m = dsi_clk_tbl[i].m;
-       p = dsi_clk_tbl[i].p;
-       m_seed = lfsr_converts[m - 62];
-       n = 1;
-       dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + p - 2);
-       dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT |
-               m_seed << DSI_PLL_M1_DIV_SHIFT;
+       /* DSI data rate = pixel clock * bits per pixel / lane count
+          pixel clock is converted from KHz to Hz */
+       dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count);
 
-       return 0;
+       return dsi_clk_khz;
 }
 
-#else
+#endif
 
 static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
 {
@@ -194,36 +169,47 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
        u32 ref_clk;
        u32 error;
        u32 tmp_error;
-       u32 target_dsi_clk;
-       u32 calc_dsi_clk;
+       int target_dsi_clk;
+       int calc_dsi_clk;
        u32 calc_m;
        u32 calc_p;
        u32 m_seed;
 
-       if (dsi_clk < 300 || dsi_clk > 1150) {
+       /* dsi_clk is expected in KHZ */
+       if (dsi_clk < 300000 || dsi_clk > 1150000) {
                DRM_ERROR("DSI CLK Out of Range\n");
                return -ECHRNG;
        }
 
        ref_clk = 25000;
-       target_dsi_clk = dsi_clk * 1000;
+       target_dsi_clk = dsi_clk;
        error = 0xFFFFFFFF;
+       tmp_error = 0xFFFFFFFF;
        calc_m = 0;
        calc_p = 0;
 
        for (m = 62; m <= 92; m++) {
                for (p = 2; p <= 6; p++) {
-
+                       /* Find the optimal m and p divisors
+                       with minimal error +/- the required clock */
                        calc_dsi_clk = (m * ref_clk) / p;
-                       if (calc_dsi_clk >= target_dsi_clk) {
-                               tmp_error = calc_dsi_clk - target_dsi_clk;
-                               if (tmp_error < error) {
-                                       error = tmp_error;
-                                       calc_m = m;
-                                       calc_p = p;
-                               }
+                       if (calc_dsi_clk == target_dsi_clk) {
+                               calc_m = m;
+                               calc_p = p;
+                               error = 0;
+                               break;
+                       } else
+                               tmp_error = abs(target_dsi_clk - calc_dsi_clk);
+
+                       if (tmp_error < error) {
+                               error = tmp_error;
+                               calc_m = m;
+                               calc_p = p;
                        }
                }
+
+               if (error == 0)
+                       break;
        }
 
        m_seed = lfsr_converts[calc_m - 62];
@@ -235,8 +221,6 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
        return 0;
 }
 
-#endif
-
 /*
  * XXX: The muxing and gating is hard coded for now. Need to add support for
  * sharing PLLs with two DSI outputs.
@@ -251,9 +235,8 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
        struct dsi_mnp dsi_mnp;
        u32 dsi_clk;
 
-       dsi_clk = dsi_rr_formula(mode, intel_dsi->pixel_format,
-                                intel_dsi->video_mode_format,
-                                intel_dsi->lane_count, !intel_dsi->eot_disable);
+       dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format,
+                                               intel_dsi->lane_count);
 
        ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
        if (ret) {
index 3c77365468562ab026910a1e111fb932b288f242..eeff998e52efdea93534ffb680582503f9f2a56c 100644 (file)
@@ -234,8 +234,9 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_dvo_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_dvo_mode_valid(struct drm_connector *connector,
+                    struct drm_display_mode *mode)
 {
        struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
 
index 895fcb4fbd9446bfbfafc90f95948d9a4bea5c55..39eac9937a4aa1a89c176ef77d727cfb615b8cd1 100644 (file)
@@ -57,18 +57,14 @@ static struct fb_ops intelfb_ops = {
        .fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
-static int intelfb_create(struct drm_fb_helper *helper,
-                         struct drm_fb_helper_surface_size *sizes)
+static int intelfb_alloc(struct drm_fb_helper *helper,
+                        struct drm_fb_helper_surface_size *sizes)
 {
        struct intel_fbdev *ifbdev =
                container_of(helper, struct intel_fbdev, helper);
        struct drm_device *dev = helper->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct fb_info *info;
-       struct drm_framebuffer *fb;
        struct drm_mode_fb_cmd2 mode_cmd = {};
        struct drm_i915_gem_object *obj;
-       struct device *device = &dev->pdev->dev;
        int size, ret;
 
        /* we don't do packed 24bpp */
@@ -94,8 +90,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
                goto out;
        }
 
-       mutex_lock(&dev->struct_mutex);
-
        /* Flush everything out, we'll be doing GTT only from now on */
        ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
        if (ret) {
@@ -103,7 +97,50 @@ static int intelfb_create(struct drm_fb_helper *helper,
                goto out_unref;
        }
 
-       info = framebuffer_alloc(0, device);
+       ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
+       if (ret)
+               goto out_unpin;
+
+       return 0;
+
+out_unpin:
+       i915_gem_object_unpin(obj);
+out_unref:
+       drm_gem_object_unreference(&obj->base);
+out:
+       return ret;
+}
+
+static int intelfb_create(struct drm_fb_helper *helper,
+                         struct drm_fb_helper_surface_size *sizes)
+{
+       struct intel_fbdev *ifbdev =
+               container_of(helper, struct intel_fbdev, helper);
+       struct intel_framebuffer *intel_fb = &ifbdev->ifb;
+       struct drm_device *dev = helper->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct fb_info *info;
+       struct drm_framebuffer *fb;
+       struct drm_i915_gem_object *obj;
+       int size, ret;
+
+       mutex_lock(&dev->struct_mutex);
+
+       if (!intel_fb->obj) {
+               DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
+               ret = intelfb_alloc(helper, sizes);
+               if (ret)
+                       goto out_unlock;
+       } else {
+               DRM_DEBUG_KMS("re-using BIOS fb\n");
+               sizes->fb_width = intel_fb->base.width;
+               sizes->fb_height = intel_fb->base.height;
+       }
+
+       obj = intel_fb->obj;
+       size = obj->base.size;
+
+       info = framebuffer_alloc(0, &dev->pdev->dev);
        if (!info) {
                ret = -ENOMEM;
                goto out_unpin;
@@ -111,10 +148,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
        info->par = helper;
 
-       ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
-       if (ret)
-               goto out_unpin;
-
        fb = &ifbdev->ifb.base;
 
        ifbdev->helper.fb = fb;
@@ -170,17 +203,15 @@ static int intelfb_create(struct drm_fb_helper *helper,
                      fb->width, fb->height,
                      i915_gem_obj_ggtt_offset(obj), obj);
 
-
        mutex_unlock(&dev->struct_mutex);
        vga_switcheroo_client_fb_set(dev->pdev, info);
        return 0;
 
 out_unpin:
        i915_gem_object_unpin(obj);
-out_unref:
        drm_gem_object_unreference(&obj->base);
+out_unlock:
        mutex_unlock(&dev->struct_mutex);
-out:
        return ret;
 }
 
@@ -297,8 +328,6 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state)
        fb_set_suspend(info, state);
 }
 
-MODULE_LICENSE("GPL and additional rights");
-
 void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
index 03f9ca70530c03f441ae037b16cf0c5e80b908ab..6db0d9d17f47e7b5ce5c43a7aa7795de71ea6346 100644 (file)
@@ -130,9 +130,9 @@ static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
 
 static void g4x_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 val = I915_READ(VIDEO_DIP_CTL);
@@ -167,9 +167,9 @@ static void g4x_write_infoframe(struct drm_encoder *encoder,
 
 static void ibx_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -205,9 +205,9 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
 
 static void cpt_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -246,9 +246,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
 
 static void vlv_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -284,9 +284,9 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
 
 static void hsw_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
@@ -853,8 +853,9 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi)
                return 225000;
 }
 
-static int intel_hdmi_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_hdmi_mode_valid(struct drm_connector *connector,
+                     struct drm_display_mode *mode)
 {
        if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector)))
                return MODE_CLOCK_HIGH;
@@ -1081,7 +1082,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
        u32 val;
 
@@ -1090,41 +1091,33 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
 
        /* Enable clock channels for this port */
        mutex_lock(&dev_priv->dpio_lock);
-       val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port));
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
        val = 0;
        if (pipe)
                val |= (1<<21);
        else
                val &= ~(1<<21);
        val |= 0x001000c4;
-       vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val);
 
        /* HDMI 1.0V-2dB */
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port),
-                        0x2b245f5f);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port),
-                        0x5578b83a);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port),
-                        0x0c782040);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port),
-                        0x2b247878);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port),
-                        0x00002000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port),
-                        DPIO_TX_OCALINIT_EN);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), 0x2b245f5f);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), 0x5578b83a);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0c782040);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX3_DW4(port), 0x2b247878);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
 
        /* Program lane clock */
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port),
-                        0x00760018);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port),
-                        0x00400888);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
        mutex_unlock(&dev_priv->dpio_lock);
 
        intel_enable_hdmi(encoder);
 
-       vlv_wait_port_ready(dev_priv, port);
+       vlv_wait_port_ready(dev_priv, dport);
 }
 
 static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
@@ -1134,7 +1127,7 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        if (!IS_VALLEYVIEW(dev))
@@ -1142,24 +1135,22 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 
        /* Program Tx lane resets to default */
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
                         DPIO_PCS_TX_LANE2_RESET |
                         DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port),
                         DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
                         DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
                         (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
                         DPIO_PCS_CLK_SOFT_RESET);
 
        /* Fix up inter-pair skew failure */
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000);
-
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port),
-                        0x00002000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port),
-                        DPIO_TX_OCALINIT_EN);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
+
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -1169,13 +1160,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
        struct intel_crtc *intel_crtc =
                to_intel_crtc(encoder->base.crtc);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        /* Reset lanes to avoid HDMI flicker (VLV w/a) */
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), 0x00000000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), 0x00e00060);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
index 2ca17b14b6c1c91710601dfcb34c661b45707347..b1dc33f478991755ec114fe66fbad7bc40fec4c0 100644 (file)
@@ -82,20 +82,11 @@ static int get_disp_clk_div(struct drm_i915_private *dev_priv,
 
 static void gmbus_set_freq(struct drm_i915_private *dev_priv)
 {
-       int vco_freq[] = { 800, 1600, 2000, 2400 };
-       int gmbus_freq = 0, cdclk_div, hpll_freq;
+       int vco, gmbus_freq = 0, cdclk_div;
 
        BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
 
-       /* Skip setting the gmbus freq if BIOS has already programmed it */
-       if (I915_READ(GMBUSFREQ_VLV) != 0xA0)
-               return;
-
-       /* Obtain SKU information */
-       mutex_lock(&dev_priv->dpio_lock);
-       hpll_freq =
-               vlv_cck_read(dev_priv, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK;
-       mutex_unlock(&dev_priv->dpio_lock);
+       vco = valleyview_get_vco(dev_priv);
 
        /* Get the CDCLK divide ratio */
        cdclk_div = get_disp_clk_div(dev_priv, CDCLK);
@@ -106,7 +97,7 @@ static void gmbus_set_freq(struct drm_i915_private *dev_priv)
         * in fact 1MHz is the correct frequency.
         */
        if (cdclk_div)
-               gmbus_freq = (vco_freq[hpll_freq] << 1) / cdclk_div;
+               gmbus_freq = (vco << 1) / cdclk_div;
 
        if (WARN_ON(gmbus_freq == 0))
                return;
index c3b4da7895ed1c82b185b78ca06d00053cff2402..8bcb93a2a9f6b1d09780c3154f6c656895451e8e 100644 (file)
@@ -256,8 +256,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
        POSTING_READ(lvds_encoder->reg);
 }
 
-static int intel_lvds_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_lvds_mode_valid(struct drm_connector *connector,
+                     struct drm_display_mode *mode)
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
        struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
@@ -446,9 +447,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
        if (dev_priv->modeset_restore == MODESET_DONE)
                goto exit;
 
-       drm_modeset_lock_all(dev);
-       intel_modeset_setup_hw_state(dev, true);
-       drm_modeset_unlock_all(dev);
+       /*
+        * Some old platform's BIOS love to wreak havoc while the lid is closed.
+        * We try to detect this here and undo any damage. The split for PCH
+        * platforms is rather conservative and a bit arbitrary expect that on
+        * those platforms VGA disabling requires actual legacy VGA I/O access,
+        * and as part of the cleanup in the hw state restore we also redisable
+        * the vga plane.
+        */
+       if (!HAS_PCH_SPLIT(dev)) {
+               drm_modeset_lock_all(dev);
+               intel_modeset_setup_hw_state(dev, true);
+               drm_modeset_unlock_all(dev);
+       }
 
        dev_priv->modeset_restore = MODESET_DONE;
 
@@ -744,57 +755,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
        { }     /* terminating entry */
 };
 
-/**
- * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
- * @dev: drm device
- * @connector: LVDS connector
- *
- * Find the reduced downclock for LVDS in EDID.
- */
-static void intel_find_lvds_downclock(struct drm_device *dev,
-                                     struct drm_display_mode *fixed_mode,
-                                     struct drm_connector *connector)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_display_mode *scan;
-       int temp_downclock;
-
-       temp_downclock = fixed_mode->clock;
-       list_for_each_entry(scan, &connector->probed_modes, head) {
-               /*
-                * If one mode has the same resolution with the fixed_panel
-                * mode while they have the different refresh rate, it means
-                * that the reduced downclock is found for the LVDS. In such
-                * case we can set the different FPx0/1 to dynamically select
-                * between low and high frequency.
-                */
-               if (scan->hdisplay == fixed_mode->hdisplay &&
-                   scan->hsync_start == fixed_mode->hsync_start &&
-                   scan->hsync_end == fixed_mode->hsync_end &&
-                   scan->htotal == fixed_mode->htotal &&
-                   scan->vdisplay == fixed_mode->vdisplay &&
-                   scan->vsync_start == fixed_mode->vsync_start &&
-                   scan->vsync_end == fixed_mode->vsync_end &&
-                   scan->vtotal == fixed_mode->vtotal) {
-                       if (scan->clock < temp_downclock) {
-                               /*
-                                * The downclock is already found. But we
-                                * expect to find the lower downclock.
-                                */
-                               temp_downclock = scan->clock;
-                       }
-               }
-       }
-       if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) {
-               /* We found the downclock for LVDS. */
-               dev_priv->lvds_downclock_avail = 1;
-               dev_priv->lvds_downclock = temp_downclock;
-               DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
-                             "Normal clock %dKhz, downclock %dKhz\n",
-                             fixed_mode->clock, temp_downclock);
-       }
-}
-
 /*
  * Enumerate the child dev array parsed from VBT to check whether
  * the LVDS is present.
@@ -1072,8 +1032,22 @@ void intel_lvds_init(struct drm_device *dev)
 
                        fixed_mode = drm_mode_duplicate(dev, scan);
                        if (fixed_mode) {
-                               intel_find_lvds_downclock(dev, fixed_mode,
-                                                         connector);
+                               intel_connector->panel.downclock_mode =
+                                       intel_find_panel_downclock(dev,
+                                       fixed_mode, connector);
+                               if (intel_connector->panel.downclock_mode !=
+                                       NULL && i915_lvds_downclock) {
+                                       /* We found the downclock for LVDS. */
+                                       dev_priv->lvds_downclock_avail = true;
+                                       dev_priv->lvds_downclock =
+                                               intel_connector->panel.
+                                               downclock_mode->clock;
+                                       DRM_DEBUG_KMS("LVDS downclock is found"
+                                       " in EDID. Normal clock %dKhz, "
+                                       "downclock %dKhz\n",
+                                       fixed_mode->clock,
+                                       dev_priv->lvds_downclock);
+                               }
                                goto out;
                        }
                }
index 6d69a9bad86545c6a8cfc8e8ff86480d462c2132..37e9a96777efa5351a5d7cdf1ce5acd959cd1ea4 100644 (file)
@@ -64,7 +64,7 @@ struct opregion_header {
        u8 driver_ver[16];
        u32 mboxes;
        u8 reserved[164];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #1: public ACPI methods */
 struct opregion_acpi {
@@ -86,7 +86,7 @@ struct opregion_acpi {
        u32 cnot;       /* current OS notification */
        u32 nrdy;       /* driver status */
        u8 rsvd2[60];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #2: SWSCI */
 struct opregion_swsci {
@@ -94,7 +94,7 @@ struct opregion_swsci {
        u32 parm;       /* command parameters */
        u32 dslp;       /* driver sleep time-out */
        u8 rsvd[244];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #3: ASLE */
 struct opregion_asle {
@@ -115,7 +115,7 @@ struct opregion_asle {
        u32 srot;       /* supported rotation angles */
        u32 iuer;       /* IUER events */
        u8 rsvd[86];
-} __attribute__((packed));
+} __packed;
 
 /* Driver readiness indicator */
 #define ASLE_ARDY_READY                (1 << 0)
@@ -396,13 +396,8 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
 static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_encoder *encoder;
-       struct drm_connector *connector;
-       struct intel_connector *intel_connector = NULL;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
+       struct intel_connector *intel_connector;
        struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
-       u32 ret = 0;
-       bool found = false;
 
        DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
 
@@ -414,38 +409,20 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
                return ASLC_BACKLIGHT_FAILED;
 
        mutex_lock(&dev->mode_config.mutex);
+
        /*
-        * Could match the OpRegion connector here instead, but we'd also need
-        * to verify the connector could handle a backlight call.
+        * Update backlight on all connectors that support backlight (usually
+        * only one).
         */
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
-               if (encoder->crtc == crtc) {
-                       found = true;
-                       break;
-               }
-
-       if (!found) {
-               ret = ASLC_BACKLIGHT_FAILED;
-               goto out;
-       }
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               if (connector->encoder == encoder)
-                       intel_connector = to_intel_connector(connector);
-
-       if (!intel_connector) {
-               ret = ASLC_BACKLIGHT_FAILED;
-               goto out;
-       }
-
        DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
-       intel_panel_set_backlight(intel_connector, bclp, 255);
+       list_for_each_entry(intel_connector, &dev->mode_config.connector_list, base.head)
+               intel_panel_set_backlight(intel_connector, bclp, 255);
        iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
 
-out:
        mutex_unlock(&dev->mode_config.mutex);
 
-       return ret;
+
+       return 0;
 }
 
 static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
index a98a990fbab3561368239ce7a7ac020c1d44f0c7..a759ecdb7a6ebaddee622ffd5a1d7900fcf5aee3 100644 (file)
@@ -1005,7 +1005,7 @@ static int intel_panel_fitter_pipe(struct drm_device *dev)
        u32  pfit_control;
 
        /* i830 doesn't have a panel fitter */
-       if (IS_I830(dev))
+       if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
                return -1;
 
        pfit_control = I915_READ(PFIT_CONTROL);
index f161ac02c4f6e613efbfc7f763cbb3566dc75248..350de359123af9cbd42354c182424f356281aa16 100644 (file)
@@ -325,203 +325,170 @@ out:
        pipe_config->gmch_pfit.lvds_border_bits = border;
 }
 
-static int is_backlight_combination_mode(struct drm_device *dev)
+static int i915_panel_invert_brightness;
+MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
+       "(-1 force normal, 0 machine defaults, 1 force inversion), please "
+       "report PCI device ID, subsystem vendor and subsystem device ID "
+       "to dri-devel@lists.freedesktop.org, if your machine needs it. "
+       "It will then be included in an upcoming module version.");
+module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
+static u32 intel_panel_compute_brightness(struct intel_connector *connector,
+                                         u32 val)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
 
-       if (IS_GEN4(dev))
-               return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
+       WARN_ON(panel->backlight.max == 0);
 
-       if (IS_GEN2(dev))
-               return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
+       if (i915_panel_invert_brightness < 0)
+               return val;
 
-       return 0;
+       if (i915_panel_invert_brightness > 0 ||
+           dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
+               return panel->backlight.max - val;
+       }
+
+       return val;
 }
 
-/* XXX: query mode clock or hardware clock and program max PWM appropriately
- * when it's 0.
- */
-static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe)
+static u32 bdw_get_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 val;
 
-       WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock));
-
-       /* Restore the CTL value if it lost, e.g. GPU reset */
-
-       if (HAS_PCH_SPLIT(dev_priv->dev)) {
-               val = I915_READ(BLC_PWM_PCH_CTL2);
-               if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL2 = val;
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL2;
-                       I915_WRITE(BLC_PWM_PCH_CTL2, val);
-               }
-       } else if (IS_VALLEYVIEW(dev)) {
-               val = I915_READ(VLV_BLC_PWM_CTL(pipe));
-               if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL = val;
-                       dev_priv->regfile.saveBLC_PWM_CTL2 =
-                               I915_READ(VLV_BLC_PWM_CTL2(pipe));
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL;
-                       I915_WRITE(VLV_BLC_PWM_CTL(pipe), val);
-                       I915_WRITE(VLV_BLC_PWM_CTL2(pipe),
-                                  dev_priv->regfile.saveBLC_PWM_CTL2);
-               }
+       return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
+}
 
-               if (!val)
-                       val = 0x0f42ffff;
-       } else {
-               val = I915_READ(BLC_PWM_CTL);
-               if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL = val;
-                       if (INTEL_INFO(dev)->gen >= 4)
-                               dev_priv->regfile.saveBLC_PWM_CTL2 =
-                                       I915_READ(BLC_PWM_CTL2);
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL;
-                       I915_WRITE(BLC_PWM_CTL, val);
-                       if (INTEL_INFO(dev)->gen >= 4)
-                               I915_WRITE(BLC_PWM_CTL2,
-                                          dev_priv->regfile.saveBLC_PWM_CTL2);
-               }
-       }
+static u32 pch_get_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
-       return val;
+       return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
 }
 
-static u32 intel_panel_get_max_backlight(struct drm_device *dev,
-                                        enum pipe pipe)
+static u32 i9xx_get_backlight(struct intel_connector *connector)
 {
-       u32 max;
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 val;
 
-       max = i915_read_blc_pwm_ctl(dev, pipe);
+       val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
+       if (INTEL_INFO(dev)->gen < 4)
+               val >>= 1;
 
-       if (HAS_PCH_SPLIT(dev)) {
-               max >>= 16;
-       } else {
-               if (INTEL_INFO(dev)->gen < 4)
-                       max >>= 17;
-               else
-                       max >>= 16;
+       if (panel->backlight.combination_mode) {
+               u8 lbpc;
 
-               if (is_backlight_combination_mode(dev))
-                       max *= 0xff;
+               pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
+               val *= lbpc;
        }
 
-       DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
-
-       return max;
+       return val;
 }
 
-static int i915_panel_invert_brightness;
-MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
-       "(-1 force normal, 0 machine defaults, 1 force inversion), please "
-       "report PCI device ID, subsystem vendor and subsystem device ID "
-       "to dri-devel@lists.freedesktop.org, if your machine needs it. "
-       "It will then be included in an upcoming module version.");
-module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
-static u32 intel_panel_compute_brightness(struct drm_device *dev,
-                                         enum pipe pipe, u32 val)
+static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (i915_panel_invert_brightness < 0)
-               return val;
+       return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
+}
 
-       if (i915_panel_invert_brightness > 0 ||
-           dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
-               u32 max = intel_panel_get_max_backlight(dev, pipe);
-               if (max)
-                       return max - val;
-       }
+static u32 vlv_get_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
 
-       return val;
+       return _vlv_get_backlight(dev, pipe);
 }
 
-static u32 intel_panel_get_backlight(struct drm_device *dev,
-                                    enum pipe pipe)
+static u32 intel_panel_get_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 val;
        unsigned long flags;
-       int reg;
-
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
-       if (HAS_PCH_SPLIT(dev)) {
-               val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
-       } else {
-               if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL(pipe);
-               else
-                       reg = BLC_PWM_CTL;
-
-               val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK;
-               if (INTEL_INFO(dev)->gen < 4)
-                       val >>= 1;
-
-               if (is_backlight_combination_mode(dev)) {
-                       u8 lbpc;
 
-                       pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
-                       val *= lbpc;
-               }
-       }
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       val = intel_panel_compute_brightness(dev, pipe, val);
+       val = dev_priv->display.get_backlight(connector);
+       val = intel_panel_compute_brightness(connector, val);
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 
        DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
        return val;
 }
 
-static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
+static void bdw_set_backlight(struct intel_connector *connector, u32 level)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
-       I915_WRITE(BLC_PWM_CPU_CTL, val | level);
+       u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
 }
 
-static void intel_panel_actually_set_backlight(struct drm_device *dev,
-                                              enum pipe pipe, u32 level)
+static void pch_set_backlight(struct intel_connector *connector, u32 level)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 tmp;
-       int reg;
 
-       DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
-       level = intel_panel_compute_brightness(dev, pipe, level);
+       tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
+}
 
-       if (HAS_PCH_SPLIT(dev))
-               return intel_pch_panel_set_backlight(dev, level);
+static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 tmp, mask;
 
-       if (is_backlight_combination_mode(dev)) {
-               u32 max = intel_panel_get_max_backlight(dev, pipe);
-               u8 lbpc;
+       WARN_ON(panel->backlight.max == 0);
 
-               /* we're screwed, but keep behaviour backwards compatible */
-               if (!max)
-                       max = 1;
+       if (panel->backlight.combination_mode) {
+               u8 lbpc;
 
-               lbpc = level * 0xfe / max + 1;
+               lbpc = level * 0xfe / panel->backlight.max + 1;
                level /= lbpc;
                pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
        }
 
-       if (IS_VALLEYVIEW(dev))
-               reg = VLV_BLC_PWM_CTL(pipe);
-       else
-               reg = BLC_PWM_CTL;
-
-       tmp = I915_READ(reg);
-       if (INTEL_INFO(dev)->gen < 4)
+       if (IS_GEN4(dev)) {
+               mask = BACKLIGHT_DUTY_CYCLE_MASK;
+       } else {
                level <<= 1;
-       tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
-       I915_WRITE(reg, tmp | level);
+               mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
+       }
+
+       tmp = I915_READ(BLC_PWM_CTL) & ~mask;
+       I915_WRITE(BLC_PWM_CTL, tmp | level);
+}
+
+static void vlv_set_backlight(struct intel_connector *connector, u32 level)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 tmp;
+
+       tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
+}
+
+static void
+intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
+
+       level = intel_panel_compute_brightness(connector, level);
+       dev_priv->display.set_backlight(connector, level);
 }
 
 /* set backlight brightness to level in range [0..max] */
@@ -530,45 +497,89 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        u32 freq;
        unsigned long flags;
 
-       if (pipe == INVALID_PIPE)
+       if (!panel->backlight.present || pipe == INVALID_PIPE)
                return;
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       freq = intel_panel_get_max_backlight(dev, pipe);
-       if (!freq) {
-               /* we are screwed, bail out */
-               goto out;
-       }
+       WARN_ON(panel->backlight.max == 0);
 
-       /* scale to hardware, but be careful to not overflow */
+       /* scale to hardware max, but be careful to not overflow */
+       freq = panel->backlight.max;
        if (freq < max)
                level = level * freq / max;
        else
                level = freq / max * level;
 
-       dev_priv->backlight.level = level;
-       if (dev_priv->backlight.device)
-               dev_priv->backlight.device->props.brightness = level;
+       panel->backlight.level = level;
+       if (panel->backlight.device)
+               panel->backlight.device->props.brightness = level;
 
-       if (dev_priv->backlight.enabled)
-               intel_panel_actually_set_backlight(dev, pipe, level);
-out:
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       if (panel->backlight.enabled)
+               intel_panel_actually_set_backlight(connector, level);
+
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+}
+
+static void pch_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(BLC_PWM_CPU_CTL2);
+       I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
+
+       tmp = I915_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
+}
+
+static void i9xx_disable_backlight(struct intel_connector *connector)
+{
+       intel_panel_actually_set_backlight(connector, 0);
+}
+
+static void i965_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(BLC_PWM_CTL2);
+       I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
+}
+
+static void vlv_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
 }
 
 void intel_panel_disable_backlight(struct intel_connector *connector)
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        unsigned long flags;
 
-       if (pipe == INVALID_PIPE)
+       if (!panel->backlight.present || pipe == INVALID_PIPE)
                return;
 
        /*
@@ -582,141 +593,215 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
                return;
        }
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       dev_priv->backlight.enabled = false;
-       intel_panel_actually_set_backlight(dev, pipe, 0);
+       panel->backlight.enabled = false;
+       dev_priv->display.disable_backlight(connector);
 
-       if (INTEL_INFO(dev)->gen >= 4) {
-               uint32_t reg, tmp;
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+}
 
-               if (HAS_PCH_SPLIT(dev))
-                       reg = BLC_PWM_CPU_CTL2;
-               else if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL2(pipe);
-               else
-                       reg = BLC_PWM_CTL2;
+static void bdw_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 pch_ctl1, pch_ctl2;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
+               DRM_DEBUG_KMS("pch backlight already enabled\n");
+               pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       }
 
-               I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE);
+       pch_ctl2 = panel->backlight.max << 16;
+       I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
 
-               if (HAS_PCH_SPLIT(dev)) {
-                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
-                       tmp &= ~BLM_PCH_PWM_ENABLE;
-                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
-               }
-       }
+       pch_ctl1 = 0;
+       if (panel->backlight.active_low_pwm)
+               pch_ctl1 |= BLM_PCH_POLARITY;
+
+       /* BDW always uses the pch pwm controls. */
+       pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       POSTING_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
+
+       /* This won't stick until the above enable. */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 }
 
-void intel_panel_enable_backlight(struct intel_connector *connector)
+static void pch_enable_backlight(struct intel_connector *connector)
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        enum transcoder cpu_transcoder =
                intel_pipe_to_cpu_transcoder(dev_priv, pipe);
-       unsigned long flags;
+       u32 cpu_ctl2, pch_ctl1, pch_ctl2;
 
-       if (pipe == INVALID_PIPE)
-               return;
+       cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
+       if (cpu_ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "cpu backlight already enabled\n");
+               cpu_ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
+       }
 
-       DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
+               DRM_DEBUG_KMS("pch backlight already enabled\n");
+               pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       }
+
+       if (cpu_transcoder == TRANSCODER_EDP)
+               cpu_ctl2 = BLM_TRANSCODER_EDP;
+       else
+               cpu_ctl2 = BLM_PIPE(cpu_transcoder);
+       I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
+       POSTING_READ(BLC_PWM_CPU_CTL2);
+       I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
+
+       /* This won't stick until the above enable. */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
+
+       pch_ctl2 = panel->backlight.max << 16;
+       I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
+
+       pch_ctl1 = 0;
+       if (panel->backlight.active_low_pwm)
+               pch_ctl1 |= BLM_PCH_POLARITY;
+
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       POSTING_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
+}
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+static void i9xx_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, freq;
 
-       if (dev_priv->backlight.level == 0) {
-               dev_priv->backlight.level = intel_panel_get_max_backlight(dev,
-                                                                         pipe);
-               if (dev_priv->backlight.device)
-                       dev_priv->backlight.device->props.brightness =
-                               dev_priv->backlight.level;
+       ctl = I915_READ(BLC_PWM_CTL);
+       if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
+               WARN(1, "backlight already enabled\n");
+               I915_WRITE(BLC_PWM_CTL, 0);
        }
 
-       if (INTEL_INFO(dev)->gen >= 4) {
-               uint32_t reg, tmp;
+       freq = panel->backlight.max;
+       if (panel->backlight.combination_mode)
+               freq /= 0xff;
 
-               if (HAS_PCH_SPLIT(dev))
-                       reg = BLC_PWM_CPU_CTL2;
-               else if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL2(pipe);
-               else
-                       reg = BLC_PWM_CTL2;
+       ctl = freq << 17;
+       if (IS_GEN2(dev) && panel->backlight.combination_mode)
+               ctl |= BLM_LEGACY_MODE;
+       if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
+               ctl |= BLM_POLARITY_PNV;
 
-               tmp = I915_READ(reg);
+       I915_WRITE(BLC_PWM_CTL, ctl);
+       POSTING_READ(BLC_PWM_CTL);
 
-               /* Note that this can also get called through dpms changes. And
-                * we don't track the backlight dpms state, hence check whether
-                * we have to do anything first. */
-               if (tmp & BLM_PWM_ENABLE)
-                       goto set_level;
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
+}
 
-               if (INTEL_INFO(dev)->num_pipes == 3)
-                       tmp &= ~BLM_PIPE_SELECT_IVB;
-               else
-                       tmp &= ~BLM_PIPE_SELECT;
+static void i965_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 ctl, ctl2, freq;
 
-               if (cpu_transcoder == TRANSCODER_EDP)
-                       tmp |= BLM_TRANSCODER_EDP;
-               else
-                       tmp |= BLM_PIPE(cpu_transcoder);
-               tmp &= ~BLM_PWM_ENABLE;
-
-               I915_WRITE(reg, tmp);
-               POSTING_READ(reg);
-               I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
-
-               if (HAS_PCH_SPLIT(dev) &&
-                   !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
-                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
-                       tmp |= BLM_PCH_PWM_ENABLE;
-                       tmp &= ~BLM_PCH_OVERRIDE_ENABLE;
-                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
-               }
+       ctl2 = I915_READ(BLC_PWM_CTL2);
+       if (ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "backlight already enabled\n");
+               ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_CTL2, ctl2);
        }
 
-set_level:
-       /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1.
-        * BLC_PWM_CPU_CTL may be cleared to zero automatically when these
-        * registers are set.
-        */
-       dev_priv->backlight.enabled = true;
-       intel_panel_actually_set_backlight(dev, pipe,
-                                          dev_priv->backlight.level);
+       freq = panel->backlight.max;
+       if (panel->backlight.combination_mode)
+               freq /= 0xff;
+
+       ctl = freq << 16;
+       I915_WRITE(BLC_PWM_CTL, ctl);
+
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       ctl2 = BLM_PIPE(pipe);
+       if (panel->backlight.combination_mode)
+               ctl2 |= BLM_COMBINATION_MODE;
+       if (panel->backlight.active_low_pwm)
+               ctl2 |= BLM_POLARITY_I965;
+       I915_WRITE(BLC_PWM_CTL2, ctl2);
+       POSTING_READ(BLC_PWM_CTL2);
+       I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
 }
 
-/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */
-static void intel_panel_init_backlight_regs(struct drm_device *dev)
+static void vlv_enable_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 ctl, ctl2;
 
-       if (IS_VALLEYVIEW(dev)) {
-               enum pipe pipe;
+       ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
+       if (ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "backlight already enabled\n");
+               ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
+       }
 
-               for_each_pipe(pipe) {
-                       u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
+       ctl = panel->backlight.max << 16;
+       I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
 
-                       /* Skip if the modulation freq is already set */
-                       if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
-                               continue;
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 
-                       cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
-                       I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
-                                  cur_val);
-               }
-       }
+       ctl2 = 0;
+       if (panel->backlight.active_low_pwm)
+               ctl2 |= BLM_POLARITY_I965;
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
+       POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
 }
 
-static void intel_panel_init_backlight(struct drm_device *dev)
+void intel_panel_enable_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       unsigned long flags;
+
+       if (!panel->backlight.present || pipe == INVALID_PIPE)
+               return;
+
+       DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
+
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
+
+       WARN_ON(panel->backlight.max == 0);
 
-       intel_panel_init_backlight_regs(dev);
+       if (panel->backlight.level == 0) {
+               panel->backlight.level = panel->backlight.max;
+               if (panel->backlight.device)
+                       panel->backlight.device->props.brightness =
+                               panel->backlight.level;
+       }
+
+       dev_priv->display.enable_backlight(connector);
+       panel->backlight.enabled = true;
 
-       dev_priv->backlight.level = intel_panel_get_backlight(dev, 0);
-       dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 }
 
 enum drm_connector_status
@@ -742,7 +827,7 @@ intel_panel_detect(struct drm_device *dev)
 }
 
 #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
-static int intel_panel_update_status(struct backlight_device *bd)
+static int intel_backlight_device_update_status(struct backlight_device *bd)
 {
        struct intel_connector *connector = bl_get_data(bd);
        struct drm_device *dev = connector->base.dev;
@@ -756,85 +841,362 @@ static int intel_panel_update_status(struct backlight_device *bd)
        return 0;
 }
 
-static int intel_panel_get_brightness(struct backlight_device *bd)
+static int intel_backlight_device_get_brightness(struct backlight_device *bd)
 {
        struct intel_connector *connector = bl_get_data(bd);
        struct drm_device *dev = connector->base.dev;
-       enum pipe pipe;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
 
+       intel_runtime_pm_get(dev_priv);
        mutex_lock(&dev->mode_config.mutex);
-       pipe = intel_get_pipe_from_connector(connector);
+       ret = intel_panel_get_backlight(connector);
        mutex_unlock(&dev->mode_config.mutex);
-       if (pipe == INVALID_PIPE)
-               return 0;
+       intel_runtime_pm_put(dev_priv);
 
-       return intel_panel_get_backlight(connector->base.dev, pipe);
+       return ret;
 }
 
-static const struct backlight_ops intel_panel_bl_ops = {
-       .update_status = intel_panel_update_status,
-       .get_brightness = intel_panel_get_brightness,
+static const struct backlight_ops intel_backlight_device_ops = {
+       .update_status = intel_backlight_device_update_status,
+       .get_brightness = intel_backlight_device_get_brightness,
 };
 
-int intel_panel_setup_backlight(struct drm_connector *connector)
+static int intel_backlight_device_register(struct intel_connector *connector)
 {
-       struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        struct backlight_properties props;
-       unsigned long flags;
 
-       intel_panel_init_backlight(dev);
-
-       if (WARN_ON(dev_priv->backlight.device))
+       if (WARN_ON(panel->backlight.device))
                return -ENODEV;
 
+       BUG_ON(panel->backlight.max == 0);
+
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
-       props.brightness = dev_priv->backlight.level;
+       props.brightness = panel->backlight.level;
+       props.max_brightness = panel->backlight.max;
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-       props.max_brightness = intel_panel_get_max_backlight(dev, 0);
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
-       if (props.max_brightness == 0) {
-               DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
-               return -ENODEV;
-       }
-       dev_priv->backlight.device =
+       /*
+        * Note: using the same name independent of the connector prevents
+        * registration of multiple backlight devices in the driver.
+        */
+       panel->backlight.device =
                backlight_device_register("intel_backlight",
-                                         connector->kdev,
-                                         to_intel_connector(connector),
-                                         &intel_panel_bl_ops, &props);
+                                         connector->base.kdev,
+                                         connector,
+                                         &intel_backlight_device_ops, &props);
 
-       if (IS_ERR(dev_priv->backlight.device)) {
+       if (IS_ERR(panel->backlight.device)) {
                DRM_ERROR("Failed to register backlight: %ld\n",
-                         PTR_ERR(dev_priv->backlight.device));
-               dev_priv->backlight.device = NULL;
+                         PTR_ERR(panel->backlight.device));
+               panel->backlight.device = NULL;
                return -ENODEV;
        }
        return 0;
 }
 
-void intel_panel_destroy_backlight(struct drm_device *dev)
+static void intel_backlight_device_unregister(struct intel_connector *connector)
+{
+       struct intel_panel *panel = &connector->panel;
+
+       if (panel->backlight.device) {
+               backlight_device_unregister(panel->backlight.device);
+               panel->backlight.device = NULL;
+       }
+}
+#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
+static int intel_backlight_device_register(struct intel_connector *connector)
+{
+       return 0;
+}
+static void intel_backlight_device_unregister(struct intel_connector *connector)
+{
+}
+#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
+
+/*
+ * Note: The setup hooks can't assume pipe is set!
+ *
+ * XXX: Query mode clock or hardware clock and program PWM modulation frequency
+ * appropriately when it's 0. Use VBT and/or sane defaults.
+ */
+static int bdw_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 pch_ctl1, pch_ctl2, val;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
+
+       pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
+       panel->backlight.max = pch_ctl2 >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = bdw_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int pch_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
+
+       pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
+       panel->backlight.max = pch_ctl2 >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = pch_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
+       panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
+               (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int i9xx_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, val;
+
+       ctl = I915_READ(BLC_PWM_CTL);
+
+       if (IS_GEN2(dev))
+               panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
+
+       if (IS_PINEVIEW(dev))
+               panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
+
+       panel->backlight.max = ctl >> 17;
+       if (panel->backlight.combination_mode)
+               panel->backlight.max *= 0xff;
+
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = i9xx_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int i965_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, ctl2, val;
+
+       ctl2 = I915_READ(BLC_PWM_CTL2);
+       panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
+       panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
+
+       ctl = I915_READ(BLC_PWM_CTL);
+       panel->backlight.max = ctl >> 16;
+       if (panel->backlight.combination_mode)
+               panel->backlight.max *= 0xff;
+
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = i9xx_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int vlv_setup_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       if (dev_priv->backlight.device) {
-               backlight_device_unregister(dev_priv->backlight.device);
-               dev_priv->backlight.device = NULL;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe;
+       u32 ctl, ctl2, val;
+
+       for_each_pipe(pipe) {
+               u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
+
+               /* Skip if the modulation freq is already set */
+               if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
+                       continue;
+
+               cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
+               I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
+                          cur_val);
        }
+
+       ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
+       panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
+
+       ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
+       panel->backlight.max = ctl >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = _vlv_get_backlight(dev, PIPE_A);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
 }
-#else
+
 int intel_panel_setup_backlight(struct drm_connector *connector)
 {
-       intel_panel_init_backlight(connector->dev);
+       struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_panel *panel = &intel_connector->panel;
+       unsigned long flags;
+       int ret;
+
+       /* set level and max in panel struct */
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
+       ret = dev_priv->display.setup_backlight(intel_connector);
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+
+       if (ret) {
+               DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
+                             drm_get_connector_name(connector));
+               return ret;
+       }
+
+       intel_backlight_device_register(intel_connector);
+
+       panel->backlight.present = true;
+
+       DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
+                     "sysfs interface %sregistered\n",
+                     panel->backlight.enabled ? "enabled" : "disabled",
+                     panel->backlight.level, panel->backlight.max,
+                     panel->backlight.device ? "" : "not ");
+
        return 0;
 }
 
-void intel_panel_destroy_backlight(struct drm_device *dev)
+void intel_panel_destroy_backlight(struct drm_connector *connector)
 {
-       return;
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_panel *panel = &intel_connector->panel;
+
+       panel->backlight.present = false;
+       intel_backlight_device_unregister(intel_connector);
+}
+
+/**
+ * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
+ * @dev: drm device
+ * @fixed_mode : panel native mode
+ * @connector: LVDS/eDP connector
+ *
+ * Return downclock_avail
+ * Find the reduced downclock for LVDS/eDP in EDID.
+ */
+struct drm_display_mode *
+intel_find_panel_downclock(struct drm_device *dev,
+                       struct drm_display_mode *fixed_mode,
+                       struct drm_connector *connector)
+{
+       struct drm_display_mode *scan, *tmp_mode;
+       int temp_downclock;
+
+       temp_downclock = fixed_mode->clock;
+       tmp_mode = NULL;
+
+       list_for_each_entry(scan, &connector->probed_modes, head) {
+               /*
+                * If one mode has the same resolution with the fixed_panel
+                * mode while they have the different refresh rate, it means
+                * that the reduced downclock is found. In such
+                * case we can set the different FPx0/1 to dynamically select
+                * between low and high frequency.
+                */
+               if (scan->hdisplay == fixed_mode->hdisplay &&
+                   scan->hsync_start == fixed_mode->hsync_start &&
+                   scan->hsync_end == fixed_mode->hsync_end &&
+                   scan->htotal == fixed_mode->htotal &&
+                   scan->vdisplay == fixed_mode->vdisplay &&
+                   scan->vsync_start == fixed_mode->vsync_start &&
+                   scan->vsync_end == fixed_mode->vsync_end &&
+                   scan->vtotal == fixed_mode->vtotal) {
+                       if (scan->clock < temp_downclock) {
+                               /*
+                                * The downclock is already found. But we
+                                * expect to find the lower downclock.
+                                */
+                               temp_downclock = scan->clock;
+                               tmp_mode = scan;
+                       }
+               }
+       }
+
+       if (temp_downclock < fixed_mode->clock)
+               return drm_mode_duplicate(dev, tmp_mode);
+       else
+               return NULL;
+}
+
+/* Set up chip specific backlight functions */
+void intel_panel_init_backlight_funcs(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (IS_BROADWELL(dev)) {
+               dev_priv->display.setup_backlight = bdw_setup_backlight;
+               dev_priv->display.enable_backlight = bdw_enable_backlight;
+               dev_priv->display.disable_backlight = pch_disable_backlight;
+               dev_priv->display.set_backlight = bdw_set_backlight;
+               dev_priv->display.get_backlight = bdw_get_backlight;
+       } else if (HAS_PCH_SPLIT(dev)) {
+               dev_priv->display.setup_backlight = pch_setup_backlight;
+               dev_priv->display.enable_backlight = pch_enable_backlight;
+               dev_priv->display.disable_backlight = pch_disable_backlight;
+               dev_priv->display.set_backlight = pch_set_backlight;
+               dev_priv->display.get_backlight = pch_get_backlight;
+       } else if (IS_VALLEYVIEW(dev)) {
+               dev_priv->display.setup_backlight = vlv_setup_backlight;
+               dev_priv->display.enable_backlight = vlv_enable_backlight;
+               dev_priv->display.disable_backlight = vlv_disable_backlight;
+               dev_priv->display.set_backlight = vlv_set_backlight;
+               dev_priv->display.get_backlight = vlv_get_backlight;
+       } else if (IS_GEN4(dev)) {
+               dev_priv->display.setup_backlight = i965_setup_backlight;
+               dev_priv->display.enable_backlight = i965_enable_backlight;
+               dev_priv->display.disable_backlight = i965_disable_backlight;
+               dev_priv->display.set_backlight = i9xx_set_backlight;
+               dev_priv->display.get_backlight = i9xx_get_backlight;
+       } else {
+               dev_priv->display.setup_backlight = i9xx_setup_backlight;
+               dev_priv->display.enable_backlight = i9xx_enable_backlight;
+               dev_priv->display.disable_backlight = i9xx_disable_backlight;
+               dev_priv->display.set_backlight = i9xx_set_backlight;
+               dev_priv->display.get_backlight = i9xx_get_backlight;
+       }
 }
-#endif
 
 int intel_panel_init(struct intel_panel *panel,
                     struct drm_display_mode *fixed_mode)
@@ -851,4 +1213,8 @@ void intel_panel_fini(struct intel_panel *panel)
 
        if (panel->fixed_mode)
                drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
+
+       if (panel->downclock_mode)
+               drm_mode_destroy(intel_connector->base.dev,
+                               panel->downclock_mode);
 }
index 6e0d5e075b15cb338694013450da3752b92442f2..d77cc81900f92100ba2f61d7130bc9b0b60454b5 100644 (file)
@@ -30,7 +30,9 @@
 #include "intel_drv.h"
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
+#include <linux/vgaarb.h>
 #include <drm/i915_powerwell.h>
+#include <linux/pm_runtime.h>
 
 /**
  * RC6 is a special power stage which allows the GPU to enter an very
@@ -86,7 +88,7 @@ static void i8xx_disable_fbc(struct drm_device *dev)
        DRM_DEBUG_KMS("disabled FBC\n");
 }
 
-static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void i8xx_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -96,32 +98,40 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int cfb_pitch;
        int plane, i;
-       u32 fbc_ctl, fbc_ctl2;
+       u32 fbc_ctl;
 
        cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE;
        if (fb->pitches[0] < cfb_pitch)
                cfb_pitch = fb->pitches[0];
 
-       /* FBC_CTL wants 64B units */
-       cfb_pitch = (cfb_pitch / 64) - 1;
+       /* FBC_CTL wants 32B or 64B units */
+       if (IS_GEN2(dev))
+               cfb_pitch = (cfb_pitch / 32) - 1;
+       else
+               cfb_pitch = (cfb_pitch / 64) - 1;
        plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB;
 
        /* Clear old tags */
        for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++)
                I915_WRITE(FBC_TAG + (i * 4), 0);
 
-       /* Set it up... */
-       fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
-       fbc_ctl2 |= plane;
-       I915_WRITE(FBC_CONTROL2, fbc_ctl2);
-       I915_WRITE(FBC_FENCE_OFF, crtc->y);
+       if (IS_GEN4(dev)) {
+               u32 fbc_ctl2;
+
+               /* Set it up... */
+               fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE;
+               fbc_ctl2 |= plane;
+               I915_WRITE(FBC_CONTROL2, fbc_ctl2);
+               I915_WRITE(FBC_FENCE_OFF, crtc->y);
+       }
 
        /* enable it... */
-       fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
+       fbc_ctl = I915_READ(FBC_CONTROL);
+       fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT;
+       fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
        if (IS_I945GM(dev))
                fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
        fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
-       fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
        fbc_ctl |= obj->fence_reg;
        I915_WRITE(FBC_CONTROL, fbc_ctl);
 
@@ -136,7 +146,7 @@ static bool i8xx_fbc_enabled(struct drm_device *dev)
        return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
 }
 
-static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void g4x_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -145,16 +155,12 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
-       unsigned long stall_watermark = 200;
        u32 dpfc_ctl;
 
        dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
        dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
        I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
 
-       I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
-                  (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
-                  (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
        I915_WRITE(DPFC_FENCE_YOFF, crtc->y);
 
        /* enable it... */
@@ -191,7 +197,11 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
        u32 blt_ecoskpd;
 
        /* Make sure blitter notifies FBC of writes */
-       gen6_gt_force_wake_get(dev_priv);
+
+       /* Blitter is part of Media powerwell on VLV. No impact of
+        * his param in other platforms for now */
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_MEDIA);
+
        blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
        blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
                GEN6_BLITTER_LOCK_SHIFT;
@@ -202,10 +212,11 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
                         GEN6_BLITTER_LOCK_SHIFT);
        I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
        POSTING_READ(GEN6_BLITTER_ECOSKPD);
-       gen6_gt_force_wake_put(dev_priv);
+
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA);
 }
 
-static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void ironlake_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -214,7 +225,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        struct drm_i915_gem_object *obj = intel_fb->obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
-       unsigned long stall_watermark = 200;
        u32 dpfc_ctl;
 
        dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
@@ -222,12 +232,11 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
        /* Set persistent mode for front-buffer rendering, ala X. */
        dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE;
-       dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg);
+       dpfc_ctl |= DPFC_CTL_FENCE_EN;
+       if (IS_GEN5(dev))
+               dpfc_ctl |= obj->fence_reg;
        I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
 
-       I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
-                  (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
-                  (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
        I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
        I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
        /* enable it... */
@@ -265,7 +274,7 @@ static bool ironlake_fbc_enabled(struct drm_device *dev)
        return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
 }
 
-static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void gen7_enable_fbc(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -295,7 +304,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 
        sandybridge_blit_fbc_update(dev);
 
-       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
+       DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane));
 }
 
 bool intel_fbc_enabled(struct drm_device *dev)
@@ -322,8 +331,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
                 * the prior work.
                 */
                if (work->crtc->fb == work->fb) {
-                       dev_priv->display.enable_fbc(work->crtc,
-                                                    work->interval);
+                       dev_priv->display.enable_fbc(work->crtc);
 
                        dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
                        dev_priv->fbc.fb_id = work->crtc->fb->base.id;
@@ -360,7 +368,7 @@ static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
        dev_priv->fbc.fbc_work = NULL;
 }
 
-static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+static void intel_enable_fbc(struct drm_crtc *crtc)
 {
        struct intel_fbc_work *work;
        struct drm_device *dev = crtc->dev;
@@ -374,13 +382,12 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        work = kzalloc(sizeof(*work), GFP_KERNEL);
        if (work == NULL) {
                DRM_ERROR("Failed to allocate FBC work structure\n");
-               dev_priv->display.enable_fbc(crtc, interval);
+               dev_priv->display.enable_fbc(crtc);
                return;
        }
 
        work->crtc = crtc;
        work->fb = crtc->fb;
-       work->interval = interval;
        INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
 
        dev_priv->fbc.fbc_work = work;
@@ -454,7 +461,7 @@ void intel_update_fbc(struct drm_device *dev)
        const struct drm_display_mode *adjusted_mode;
        unsigned int max_width, max_height;
 
-       if (!I915_HAS_FBC(dev)) {
+       if (!HAS_FBC(dev)) {
                set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED);
                return;
        }
@@ -530,10 +537,10 @@ void intel_update_fbc(struct drm_device *dev)
                        DRM_DEBUG_KMS("mode too large for compression, disabling\n");
                goto out_disable;
        }
-       if ((IS_I915GM(dev) || IS_I945GM(dev) || IS_HASWELL(dev)) &&
-           intel_crtc->plane != 0) {
+       if ((INTEL_INFO(dev)->gen < 4 || IS_HASWELL(dev)) &&
+           intel_crtc->plane != PLANE_A) {
                if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE))
-                       DRM_DEBUG_KMS("plane not 0, disabling compression\n");
+                       DRM_DEBUG_KMS("plane not A, disabling compression\n");
                goto out_disable;
        }
 
@@ -595,7 +602,7 @@ void intel_update_fbc(struct drm_device *dev)
                intel_disable_fbc(dev);
        }
 
-       intel_enable_fbc(crtc, 500);
+       intel_enable_fbc(crtc);
        dev_priv->fbc.no_fbc_reason = FBC_OK;
        return;
 
@@ -817,7 +824,7 @@ static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
        return size;
 }
 
-static int i85x_get_fifo_size(struct drm_device *dev, int plane)
+static int i830_get_fifo_size(struct drm_device *dev, int plane)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t dsparb = I915_READ(DSPARB);
@@ -850,21 +857,6 @@ static int i845_get_fifo_size(struct drm_device *dev, int plane)
        return size;
 }
 
-static int i830_get_fifo_size(struct drm_device *dev, int plane)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t dsparb = I915_READ(DSPARB);
-       int size;
-
-       size = dsparb & 0x7f;
-       size >>= 1; /* Convert to cachelines */
-
-       DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
-                     plane ? "B" : "A", size);
-
-       return size;
-}
-
 /* Pineview has different values for various configs */
 static const struct intel_watermark_params pineview_display_wm = {
        PINEVIEW_DISPLAY_FIFO,
@@ -943,14 +935,14 @@ static const struct intel_watermark_params i915_wm_info = {
        2,
        I915_FIFO_LINE_SIZE
 };
-static const struct intel_watermark_params i855_wm_info = {
+static const struct intel_watermark_params i830_wm_info = {
        I855GM_FIFO_SIZE,
        I915_MAX_WM,
        1,
        2,
        I830_FIFO_LINE_SIZE
 };
-static const struct intel_watermark_params i830_wm_info = {
+static const struct intel_watermark_params i845_wm_info = {
        I830_FIFO_SIZE,
        I915_MAX_WM,
        1,
@@ -958,65 +950,6 @@ static const struct intel_watermark_params i830_wm_info = {
        I830_FIFO_LINE_SIZE
 };
 
-static const struct intel_watermark_params ironlake_display_wm_info = {
-       ILK_DISPLAY_FIFO,
-       ILK_DISPLAY_MAXWM,
-       ILK_DISPLAY_DFTWM,
-       2,
-       ILK_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params ironlake_cursor_wm_info = {
-       ILK_CURSOR_FIFO,
-       ILK_CURSOR_MAXWM,
-       ILK_CURSOR_DFTWM,
-       2,
-       ILK_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params ironlake_display_srwm_info = {
-       ILK_DISPLAY_SR_FIFO,
-       ILK_DISPLAY_MAX_SRWM,
-       ILK_DISPLAY_DFT_SRWM,
-       2,
-       ILK_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params ironlake_cursor_srwm_info = {
-       ILK_CURSOR_SR_FIFO,
-       ILK_CURSOR_MAX_SRWM,
-       ILK_CURSOR_DFT_SRWM,
-       2,
-       ILK_FIFO_LINE_SIZE
-};
-
-static const struct intel_watermark_params sandybridge_display_wm_info = {
-       SNB_DISPLAY_FIFO,
-       SNB_DISPLAY_MAXWM,
-       SNB_DISPLAY_DFTWM,
-       2,
-       SNB_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params sandybridge_cursor_wm_info = {
-       SNB_CURSOR_FIFO,
-       SNB_CURSOR_MAXWM,
-       SNB_CURSOR_DFTWM,
-       2,
-       SNB_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params sandybridge_display_srwm_info = {
-       SNB_DISPLAY_SR_FIFO,
-       SNB_DISPLAY_MAX_SRWM,
-       SNB_DISPLAY_DFT_SRWM,
-       2,
-       SNB_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params sandybridge_cursor_srwm_info = {
-       SNB_CURSOR_SR_FIFO,
-       SNB_CURSOR_MAX_SRWM,
-       SNB_CURSOR_DFT_SRWM,
-       2,
-       SNB_FIFO_LINE_SIZE
-};
-
-
 /**
  * intel_calculate_wm - calculate watermark level
  * @clock_in_khz: pixel clock
@@ -1567,7 +1500,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
        else if (!IS_GEN2(dev))
                wm_info = &i915_wm_info;
        else
-               wm_info = &i855_wm_info;
+               wm_info = &i830_wm_info;
 
        fifo_size = dev_priv->display.get_fifo_size(dev, 0);
        crtc = intel_get_crtc_for_plane(dev, 0);
@@ -1615,7 +1548,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
        if (IS_I945G(dev) || IS_I945GM(dev))
                I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0);
        else if (IS_I915GM(dev))
-               I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
+               I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_SELF_EN));
 
        /* Calc sr entries for one plane configs */
        if (HAS_FW_BLC(dev) && enabled) {
@@ -1667,14 +1600,14 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
                                I915_WRITE(FW_BLC_SELF,
                                           FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
                        else if (IS_I915GM(dev))
-                               I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
+                               I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_SELF_EN));
                        DRM_DEBUG_KMS("memory self refresh enabled\n");
                } else
                        DRM_DEBUG_KMS("memory self refresh disabled\n");
        }
 }
 
-static void i830_update_wm(struct drm_crtc *unused_crtc)
+static void i845_update_wm(struct drm_crtc *unused_crtc)
 {
        struct drm_device *dev = unused_crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1689,7 +1622,7 @@ static void i830_update_wm(struct drm_crtc *unused_crtc)
 
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
-                                      &i830_wm_info,
+                                      &i845_wm_info,
                                       dev_priv->display.get_fifo_size(dev, 0),
                                       4, latency_ns);
        fwater_lo = I915_READ(FW_BLC) & ~0xfff;
@@ -1700,423 +1633,6 @@ static void i830_update_wm(struct drm_crtc *unused_crtc)
        I915_WRITE(FW_BLC, fwater_lo);
 }
 
-/*
- * Check the wm result.
- *
- * If any calculated watermark values is larger than the maximum value that
- * can be programmed into the associated watermark register, that watermark
- * must be disabled.
- */
-static bool ironlake_check_srwm(struct drm_device *dev, int level,
-                               int fbc_wm, int display_wm, int cursor_wm,
-                               const struct intel_watermark_params *display,
-                               const struct intel_watermark_params *cursor)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d,"
-                     " cursor %d\n", level, display_wm, fbc_wm, cursor_wm);
-
-       if (fbc_wm > SNB_FBC_MAX_SRWM) {
-               DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n",
-                             fbc_wm, SNB_FBC_MAX_SRWM, level);
-
-               /* fbc has it's own way to disable FBC WM */
-               I915_WRITE(DISP_ARB_CTL,
-                          I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS);
-               return false;
-       } else if (INTEL_INFO(dev)->gen >= 6) {
-               /* enable FBC WM (except on ILK, where it must remain off) */
-               I915_WRITE(DISP_ARB_CTL,
-                          I915_READ(DISP_ARB_CTL) & ~DISP_FBC_WM_DIS);
-       }
-
-       if (display_wm > display->max_wm) {
-               DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n",
-                             display_wm, SNB_DISPLAY_MAX_SRWM, level);
-               return false;
-       }
-
-       if (cursor_wm > cursor->max_wm) {
-               DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n",
-                             cursor_wm, SNB_CURSOR_MAX_SRWM, level);
-               return false;
-       }
-
-       if (!(fbc_wm || display_wm || cursor_wm)) {
-               DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level);
-               return false;
-       }
-
-       return true;
-}
-
-/*
- * Compute watermark values of WM[1-3],
- */
-static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
-                                 int latency_ns,
-                                 const struct intel_watermark_params *display,
-                                 const struct intel_watermark_params *cursor,
-                                 int *fbc_wm, int *display_wm, int *cursor_wm)
-{
-       struct drm_crtc *crtc;
-       const struct drm_display_mode *adjusted_mode;
-       unsigned long line_time_us;
-       int hdisplay, htotal, pixel_size, clock;
-       int line_count, line_size;
-       int small, large;
-       int entries;
-
-       if (!latency_ns) {
-               *fbc_wm = *display_wm = *cursor_wm = 0;
-               return false;
-       }
-
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
-       clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->crtc_htotal;
-       hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
-       pixel_size = crtc->fb->bits_per_pixel / 8;
-
-       line_time_us = (htotal * 1000) / clock;
-       line_count = (latency_ns / line_time_us + 1000) / 1000;
-       line_size = hdisplay * pixel_size;
-
-       /* Use the minimum of the small and large buffer method for primary */
-       small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
-       large = line_count * line_size;
-
-       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-       *display_wm = entries + display->guard_size;
-
-       /*
-        * Spec says:
-        * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2
-        */
-       *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2;
-
-       /* calculate the self-refresh watermark for display cursor */
-       entries = line_count * pixel_size * 64;
-       entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
-       *cursor_wm = entries + cursor->guard_size;
-
-       return ironlake_check_srwm(dev, level,
-                                  *fbc_wm, *display_wm, *cursor_wm,
-                                  display, cursor);
-}
-
-static void ironlake_update_wm(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int fbc_wm, plane_wm, cursor_wm;
-       unsigned int enabled;
-
-       enabled = 0;
-       if (g4x_compute_wm0(dev, PIPE_A,
-                           &ironlake_display_wm_info,
-                           dev_priv->wm.pri_latency[0] * 100,
-                           &ironlake_cursor_wm_info,
-                           dev_priv->wm.cur_latency[0] * 100,
-                           &plane_wm, &cursor_wm)) {
-               I915_WRITE(WM0_PIPEA_ILK,
-                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
-               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-                             " plane %d, " "cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_A;
-       }
-
-       if (g4x_compute_wm0(dev, PIPE_B,
-                           &ironlake_display_wm_info,
-                           dev_priv->wm.pri_latency[0] * 100,
-                           &ironlake_cursor_wm_info,
-                           dev_priv->wm.cur_latency[0] * 100,
-                           &plane_wm, &cursor_wm)) {
-               I915_WRITE(WM0_PIPEB_ILK,
-                          (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm);
-               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-                             " plane %d, cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_B;
-       }
-
-       /*
-        * Calculate and update the self-refresh watermark only when one
-        * display plane is used.
-        */
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
-
-       if (!single_plane_enabled(enabled))
-               return;
-       enabled = ffs(enabled) - 1;
-
-       /* WM1 */
-       if (!ironlake_compute_srwm(dev, 1, enabled,
-                                  dev_priv->wm.pri_latency[1] * 500,
-                                  &ironlake_display_srwm_info,
-                                  &ironlake_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM1_LP_ILK,
-                  WM1_LP_SR_EN |
-                  (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM2 */
-       if (!ironlake_compute_srwm(dev, 2, enabled,
-                                  dev_priv->wm.pri_latency[2] * 500,
-                                  &ironlake_display_srwm_info,
-                                  &ironlake_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM2_LP_ILK,
-                  WM2_LP_EN |
-                  (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /*
-        * WM3 is unsupported on ILK, probably because we don't have latency
-        * data for that power state
-        */
-}
-
-static void sandybridge_update_wm(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int latency = dev_priv->wm.pri_latency[0] * 100;        /* In unit 0.1us */
-       u32 val;
-       int fbc_wm, plane_wm, cursor_wm;
-       unsigned int enabled;
-
-       enabled = 0;
-       if (g4x_compute_wm0(dev, PIPE_A,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEA_ILK);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEA_ILK, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-                             " plane %d, " "cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_A;
-       }
-
-       if (g4x_compute_wm0(dev, PIPE_B,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEB_ILK);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEB_ILK, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-                             " plane %d, cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_B;
-       }
-
-       /*
-        * Calculate and update the self-refresh watermark only when one
-        * display plane is used.
-        *
-        * SNB support 3 levels of watermark.
-        *
-        * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
-        * and disabled in the descending order
-        *
-        */
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
-
-       if (!single_plane_enabled(enabled) ||
-           dev_priv->sprite_scaling_enabled)
-               return;
-       enabled = ffs(enabled) - 1;
-
-       /* WM1 */
-       if (!ironlake_compute_srwm(dev, 1, enabled,
-                                  dev_priv->wm.pri_latency[1] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM1_LP_ILK,
-                  WM1_LP_SR_EN |
-                  (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM2 */
-       if (!ironlake_compute_srwm(dev, 2, enabled,
-                                  dev_priv->wm.pri_latency[2] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM2_LP_ILK,
-                  WM2_LP_EN |
-                  (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM3 */
-       if (!ironlake_compute_srwm(dev, 3, enabled,
-                                  dev_priv->wm.pri_latency[3] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM3_LP_ILK,
-                  WM3_LP_EN |
-                  (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-}
-
-static void ivybridge_update_wm(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int latency = dev_priv->wm.pri_latency[0] * 100;        /* In unit 0.1us */
-       u32 val;
-       int fbc_wm, plane_wm, cursor_wm;
-       int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
-       unsigned int enabled;
-
-       enabled = 0;
-       if (g4x_compute_wm0(dev, PIPE_A,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEA_ILK);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEA_ILK, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
-                             " plane %d, " "cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_A;
-       }
-
-       if (g4x_compute_wm0(dev, PIPE_B,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEB_ILK);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEB_ILK, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
-                             " plane %d, cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_B;
-       }
-
-       if (g4x_compute_wm0(dev, PIPE_C,
-                           &sandybridge_display_wm_info, latency,
-                           &sandybridge_cursor_wm_info, latency,
-                           &plane_wm, &cursor_wm)) {
-               val = I915_READ(WM0_PIPEC_IVB);
-               val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
-               I915_WRITE(WM0_PIPEC_IVB, val |
-                          ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));
-               DRM_DEBUG_KMS("FIFO watermarks For pipe C -"
-                             " plane %d, cursor: %d\n",
-                             plane_wm, cursor_wm);
-               enabled |= 1 << PIPE_C;
-       }
-
-       /*
-        * Calculate and update the self-refresh watermark only when one
-        * display plane is used.
-        *
-        * SNB support 3 levels of watermark.
-        *
-        * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
-        * and disabled in the descending order
-        *
-        */
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
-
-       if (!single_plane_enabled(enabled) ||
-           dev_priv->sprite_scaling_enabled)
-               return;
-       enabled = ffs(enabled) - 1;
-
-       /* WM1 */
-       if (!ironlake_compute_srwm(dev, 1, enabled,
-                                  dev_priv->wm.pri_latency[1] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM1_LP_ILK,
-                  WM1_LP_SR_EN |
-                  (dev_priv->wm.pri_latency[1] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM2 */
-       if (!ironlake_compute_srwm(dev, 2, enabled,
-                                  dev_priv->wm.pri_latency[2] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM2_LP_ILK,
-                  WM2_LP_EN |
-                  (dev_priv->wm.pri_latency[2] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-
-       /* WM3, note we have to correct the cursor latency */
-       if (!ironlake_compute_srwm(dev, 3, enabled,
-                                  dev_priv->wm.pri_latency[3] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
-           !ironlake_compute_srwm(dev, 3, enabled,
-                                  dev_priv->wm.cur_latency[3] * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
-               return;
-
-       I915_WRITE(WM3_LP_ILK,
-                  WM3_LP_EN |
-                  (dev_priv->wm.pri_latency[3] << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-}
-
 static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
                                    struct drm_crtc *crtc)
 {
@@ -2185,7 +1701,7 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
        return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
 }
 
-struct hsw_pipe_wm_parameters {
+struct ilk_pipe_wm_parameters {
        bool active;
        uint32_t pipe_htotal;
        uint32_t pixel_rate;
@@ -2194,7 +1710,7 @@ struct hsw_pipe_wm_parameters {
        struct intel_plane_wm_parameters cur;
 };
 
-struct hsw_wm_maximums {
+struct ilk_wm_maximums {
        uint16_t pri;
        uint16_t spr;
        uint16_t cur;
@@ -2212,7 +1728,7 @@ struct intel_wm_config {
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_pri_wm(const struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_pri_wm(const struct ilk_pipe_wm_parameters *params,
                                   uint32_t mem_value,
                                   bool is_lp)
 {
@@ -2241,7 +1757,7 @@ static uint32_t ilk_compute_pri_wm(const struct hsw_pipe_wm_parameters *params,
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_spr_wm(const struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_spr_wm(const struct ilk_pipe_wm_parameters *params,
                                   uint32_t mem_value)
 {
        uint32_t method1, method2;
@@ -2264,7 +1780,7 @@ static uint32_t ilk_compute_spr_wm(const struct hsw_pipe_wm_parameters *params,
  * For both WM_PIPE and WM_LP.
  * mem_value must be in 0.1us units.
  */
-static uint32_t ilk_compute_cur_wm(const struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_cur_wm(const struct ilk_pipe_wm_parameters *params,
                                   uint32_t mem_value)
 {
        if (!params->active || !params->cur.enabled)
@@ -2278,7 +1794,7 @@ static uint32_t ilk_compute_cur_wm(const struct hsw_pipe_wm_parameters *params,
 }
 
 /* Only for WM_LP. */
-static uint32_t ilk_compute_fbc_wm(const struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_fbc_wm(const struct ilk_pipe_wm_parameters *params,
                                   uint32_t pri_val)
 {
        if (!params->active || !params->pri.enabled)
@@ -2383,7 +1899,7 @@ static void ilk_compute_wm_maximums(struct drm_device *dev,
                                    int level,
                                    const struct intel_wm_config *config,
                                    enum intel_ddb_partitioning ddb_partitioning,
-                                   struct hsw_wm_maximums *max)
+                                   struct ilk_wm_maximums *max)
 {
        max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
        max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
@@ -2392,7 +1908,7 @@ static void ilk_compute_wm_maximums(struct drm_device *dev,
 }
 
 static bool ilk_validate_wm_level(int level,
-                                 const struct hsw_wm_maximums *max,
+                                 const struct ilk_wm_maximums *max,
                                  struct intel_wm_level *result)
 {
        bool ret;
@@ -2434,7 +1950,7 @@ static bool ilk_validate_wm_level(int level,
 
 static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
                                 int level,
-                                const struct hsw_pipe_wm_parameters *p,
+                                const struct ilk_pipe_wm_parameters *p,
                                 struct intel_wm_level *result)
 {
        uint16_t pri_latency = dev_priv->wm.pri_latency[level];
@@ -2482,7 +1998,7 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5])
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (IS_HASWELL(dev)) {
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                uint64_t sskpd = I915_READ64(MCH_SSKPD);
 
                wm[0] = (sskpd >> 56) & 0xFF;
@@ -2530,7 +2046,7 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
 static int ilk_wm_max_level(const struct drm_device *dev)
 {
        /* how many WM levels are we expecting */
-       if (IS_HASWELL(dev))
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                return 4;
        else if (INTEL_INFO(dev)->gen >= 6)
                return 3;
@@ -2582,8 +2098,8 @@ static void intel_setup_wm_latency(struct drm_device *dev)
        intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
 }
 
-static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
-                                     struct hsw_pipe_wm_parameters *p,
+static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
+                                     struct ilk_pipe_wm_parameters *p,
                                      struct intel_wm_config *config)
 {
        struct drm_device *dev = crtc->dev;
@@ -2593,7 +2109,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
 
        p->active = intel_crtc_active(crtc);
        if (p->active) {
-               p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal;
+               p->pipe_htotal = intel_crtc->config.adjusted_mode.crtc_htotal;
                p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
                p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
                p->cur.bytes_per_pixel = 4;
@@ -2620,7 +2136,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc,
 
 /* Compute new watermarks for the pipe */
 static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
-                                 const struct hsw_pipe_wm_parameters *params,
+                                 const struct ilk_pipe_wm_parameters *params,
                                  struct intel_pipe_wm *pipe_wm)
 {
        struct drm_device *dev = crtc->dev;
@@ -2632,16 +2148,25 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc,
                .sprites_enabled = params->spr.enabled,
                .sprites_scaled = params->spr.scaled,
        };
-       struct hsw_wm_maximums max;
+       struct ilk_wm_maximums max;
 
        /* LP0 watermarks always use 1/2 DDB partitioning */
        ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
 
+       /* ILK/SNB: LP2+ watermarks only w/o sprites */
+       if (INTEL_INFO(dev)->gen <= 6 && params->spr.enabled)
+               max_level = 1;
+
+       /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
+       if (params->spr.scaled)
+               max_level = 0;
+
        for (level = 0; level <= max_level; level++)
                ilk_compute_wm_level(dev_priv, level, params,
                                     &pipe_wm->wm[level]);
 
-       pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc);
 
        /* At least LP0 must be valid */
        return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]);
@@ -2676,12 +2201,19 @@ static void ilk_merge_wm_level(struct drm_device *dev,
  * Merge all low power watermarks for all active pipes.
  */
 static void ilk_wm_merge(struct drm_device *dev,
-                        const struct hsw_wm_maximums *max,
+                        const struct intel_wm_config *config,
+                        const struct ilk_wm_maximums *max,
                         struct intel_pipe_wm *merged)
 {
        int level, max_level = ilk_wm_max_level(dev);
 
-       merged->fbc_wm_enabled = true;
+       /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
+       if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
+           config->num_pipes_active > 1)
+               return;
+
+       /* ILK: FBC WM must be disabled always */
+       merged->fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6;
 
        /* merge each WM1+ level */
        for (level = 1; level <= max_level; level++) {
@@ -2701,6 +2233,20 @@ static void ilk_wm_merge(struct drm_device *dev,
                        wm->fbc_val = 0;
                }
        }
+
+       /* ILK: LP2+ must be disabled when FBC WM is disabled but FBC enabled */
+       /*
+        * FIXME this is racy. FBC might get enabled later.
+        * What we should check here is whether FBC can be
+        * enabled sometime later.
+        */
+       if (IS_GEN5(dev) && !merged->fbc_wm_enabled && intel_fbc_enabled(dev)) {
+               for (level = 2; level <= max_level; level++) {
+                       struct intel_wm_level *wm = &merged->wm[level];
+
+                       wm->enable = false;
+               }
+       }
 }
 
 static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
@@ -2709,10 +2255,21 @@ static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm)
        return wm_lp + (wm_lp >= 2 && pipe_wm->wm[4].enable);
 }
 
-static void hsw_compute_wm_results(struct drm_device *dev,
+/* The value we need to program into the WM_LPx latency field */
+static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               return 2 * level;
+       else
+               return dev_priv->wm.pri_latency[level];
+}
+
+static void ilk_compute_wm_results(struct drm_device *dev,
                                   const struct intel_pipe_wm *merged,
                                   enum intel_ddb_partitioning partitioning,
-                                  struct hsw_wm_values *results)
+                                  struct ilk_wm_values *results)
 {
        struct intel_crtc *intel_crtc;
        int level, wm_lp;
@@ -2731,7 +2288,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
                        break;
 
                results->wm_lp[wm_lp - 1] = WM3_LP_EN |
-                       ((level * 2) << WM1_LP_LATENCY_SHIFT) |
+                       (ilk_wm_lp_latency(dev, level) << WM1_LP_LATENCY_SHIFT) |
                        (r->pri_val << WM1_LP_SR_SHIFT) |
                        r->cur_val;
 
@@ -2742,7 +2299,11 @@ static void hsw_compute_wm_results(struct drm_device *dev,
                        results->wm_lp[wm_lp - 1] |=
                                r->fbc_val << WM1_LP_FBC_SHIFT;
 
-               results->wm_lp_spr[wm_lp - 1] = r->spr_val;
+               if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
+                       WARN_ON(wm_lp != 1);
+                       results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
+               } else
+                       results->wm_lp_spr[wm_lp - 1] = r->spr_val;
        }
 
        /* LP0 register values */
@@ -2765,7 +2326,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
 
 /* Find the result with the highest level enabled. Check for enable_fbc_wm in
  * case both are at the same level. Prefer r1 in case they're the same. */
-static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
+static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev,
                                                  struct intel_pipe_wm *r1,
                                                  struct intel_pipe_wm *r2)
 {
@@ -2800,8 +2361,8 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev,
 #define WM_DIRTY_DDB (1 << 25)
 
 static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
-                                        const struct hsw_wm_values *old,
-                                        const struct hsw_wm_values *new)
+                                        const struct ilk_wm_values *old,
+                                        const struct ilk_wm_values *new)
 {
        unsigned int dirty = 0;
        enum pipe pipe;
@@ -2851,27 +2412,53 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev,
        return dirty;
 }
 
+static bool _ilk_disable_lp_wm(struct drm_i915_private *dev_priv,
+                              unsigned int dirty)
+{
+       struct ilk_wm_values *previous = &dev_priv->wm.hw;
+       bool changed = false;
+
+       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] & WM1_LP_SR_EN) {
+               previous->wm_lp[2] &= ~WM1_LP_SR_EN;
+               I915_WRITE(WM3_LP_ILK, previous->wm_lp[2]);
+               changed = true;
+       }
+       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] & WM1_LP_SR_EN) {
+               previous->wm_lp[1] &= ~WM1_LP_SR_EN;
+               I915_WRITE(WM2_LP_ILK, previous->wm_lp[1]);
+               changed = true;
+       }
+       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] & WM1_LP_SR_EN) {
+               previous->wm_lp[0] &= ~WM1_LP_SR_EN;
+               I915_WRITE(WM1_LP_ILK, previous->wm_lp[0]);
+               changed = true;
+       }
+
+       /*
+        * Don't touch WM1S_LP_EN here.
+        * Doing so could cause underruns.
+        */
+
+       return changed;
+}
+
 /*
  * The spec says we shouldn't write when we don't need, because every write
  * causes WMs to be re-evaluated, expending some power.
  */
-static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
-                               struct hsw_wm_values *results)
+static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
+                               struct ilk_wm_values *results)
 {
-       struct hsw_wm_values *previous = &dev_priv->wm.hw;
+       struct drm_device *dev = dev_priv->dev;
+       struct ilk_wm_values *previous = &dev_priv->wm.hw;
        unsigned int dirty;
        uint32_t val;
 
-       dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results);
+       dirty = ilk_compute_wm_dirty(dev, previous, results);
        if (!dirty)
                return;
 
-       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0)
-               I915_WRITE(WM3_LP_ILK, 0);
-       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0)
-               I915_WRITE(WM2_LP_ILK, 0);
-       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0)
-               I915_WRITE(WM1_LP_ILK, 0);
+       _ilk_disable_lp_wm(dev_priv, dirty);
 
        if (dirty & WM_DIRTY_PIPE(PIPE_A))
                I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
@@ -2888,12 +2475,21 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
                I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
 
        if (dirty & WM_DIRTY_DDB) {
-               val = I915_READ(WM_MISC);
-               if (results->partitioning == INTEL_DDB_PART_1_2)
-                       val &= ~WM_MISC_DATA_PARTITION_5_6;
-               else
-                       val |= WM_MISC_DATA_PARTITION_5_6;
-               I915_WRITE(WM_MISC, val);
+               if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+                       val = I915_READ(WM_MISC);
+                       if (results->partitioning == INTEL_DDB_PART_1_2)
+                               val &= ~WM_MISC_DATA_PARTITION_5_6;
+                       else
+                               val |= WM_MISC_DATA_PARTITION_5_6;
+                       I915_WRITE(WM_MISC, val);
+               } else {
+                       val = I915_READ(DISP_ARB_CTL2);
+                       if (results->partitioning == INTEL_DDB_PART_1_2)
+                               val &= ~DISP_DATA_PARTITION_5_6;
+                       else
+                               val |= DISP_DATA_PARTITION_5_6;
+                       I915_WRITE(DISP_ARB_CTL2, val);
+               }
        }
 
        if (dirty & WM_DIRTY_FBC) {
@@ -2905,37 +2501,48 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
                I915_WRITE(DISP_ARB_CTL, val);
        }
 
-       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
+       if (dirty & WM_DIRTY_LP(1) &&
+           previous->wm_lp_spr[0] != results->wm_lp_spr[0])
                I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
-       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
-               I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
-       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
-               I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
 
-       if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0)
+       if (INTEL_INFO(dev)->gen >= 7) {
+               if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
+                       I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
+               if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
+                       I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
+       }
+
+       if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != results->wm_lp[0])
                I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
-       if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0)
+       if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != results->wm_lp[1])
                I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
-       if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0)
+       if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2])
                I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
 
        dev_priv->wm.hw = *results;
 }
 
-static void haswell_update_wm(struct drm_crtc *crtc)
+static bool ilk_disable_lp_wm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
+}
+
+static void ilk_update_wm(struct drm_crtc *crtc)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct hsw_wm_maximums max;
-       struct hsw_pipe_wm_parameters params = {};
-       struct hsw_wm_values results = {};
+       struct ilk_wm_maximums max;
+       struct ilk_pipe_wm_parameters params = {};
+       struct ilk_wm_values results = {};
        enum intel_ddb_partitioning partitioning;
        struct intel_pipe_wm pipe_wm = {};
        struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
        struct intel_wm_config config = {};
 
-       hsw_compute_wm_parameters(crtc, &params, &config);
+       ilk_compute_wm_parameters(crtc, &params, &config);
 
        intel_compute_pipe_wm(crtc, &params, &pipe_wm);
 
@@ -2945,15 +2552,15 @@ static void haswell_update_wm(struct drm_crtc *crtc)
        intel_crtc->wm.active = pipe_wm;
 
        ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
-       ilk_wm_merge(dev, &max, &lp_wm_1_2);
+       ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
 
        /* 5/6 split only in single pipe config on IVB+ */
        if (INTEL_INFO(dev)->gen >= 7 &&
            config.num_pipes_active == 1 && config.sprites_enabled) {
                ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
-               ilk_wm_merge(dev, &max, &lp_wm_5_6);
+               ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
 
-               best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
+               best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
        } else {
                best_lp_wm = &lp_wm_1_2;
        }
@@ -2961,193 +2568,42 @@ static void haswell_update_wm(struct drm_crtc *crtc)
        partitioning = (best_lp_wm == &lp_wm_1_2) ?
                       INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6;
 
-       hsw_compute_wm_results(dev, best_lp_wm, partitioning, &results);
+       ilk_compute_wm_results(dev, best_lp_wm, partitioning, &results);
 
-       hsw_write_wm_values(dev_priv, &results);
+       ilk_write_wm_values(dev_priv, &results);
 }
 
-static void haswell_update_sprite_wm(struct drm_plane *plane,
+static void ilk_update_sprite_wm(struct drm_plane *plane,
                                     struct drm_crtc *crtc,
                                     uint32_t sprite_width, int pixel_size,
                                     bool enabled, bool scaled)
 {
+       struct drm_device *dev = plane->dev;
        struct intel_plane *intel_plane = to_intel_plane(plane);
 
        intel_plane->wm.enabled = enabled;
        intel_plane->wm.scaled = scaled;
        intel_plane->wm.horiz_pixels = sprite_width;
-       intel_plane->wm.bytes_per_pixel = pixel_size;
-
-       haswell_update_wm(crtc);
-}
-
-static bool
-sandybridge_compute_sprite_wm(struct drm_device *dev, int plane,
-                             uint32_t sprite_width, int pixel_size,
-                             const struct intel_watermark_params *display,
-                             int display_latency_ns, int *sprite_wm)
-{
-       struct drm_crtc *crtc;
-       int clock;
-       int entries, tlb_miss;
-
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       if (!intel_crtc_active(crtc)) {
-               *sprite_wm = display->guard_size;
-               return false;
-       }
-
-       clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
-
-       /* Use the small buffer method to calculate the sprite watermark */
-       entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
-       tlb_miss = display->fifo_size*display->cacheline_size -
-               sprite_width * 8;
-       if (tlb_miss > 0)
-               entries += tlb_miss;
-       entries = DIV_ROUND_UP(entries, display->cacheline_size);
-       *sprite_wm = entries + display->guard_size;
-       if (*sprite_wm > (int)display->max_wm)
-               *sprite_wm = display->max_wm;
-
-       return true;
-}
-
-static bool
-sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
-                               uint32_t sprite_width, int pixel_size,
-                               const struct intel_watermark_params *display,
-                               int latency_ns, int *sprite_wm)
-{
-       struct drm_crtc *crtc;
-       unsigned long line_time_us;
-       int clock;
-       int line_count, line_size;
-       int small, large;
-       int entries;
-
-       if (!latency_ns) {
-               *sprite_wm = 0;
-               return false;
-       }
-
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
-       if (!clock) {
-               *sprite_wm = 0;
-               return false;
-       }
-
-       line_time_us = (sprite_width * 1000) / clock;
-       if (!line_time_us) {
-               *sprite_wm = 0;
-               return false;
-       }
-
-       line_count = (latency_ns / line_time_us + 1000) / 1000;
-       line_size = sprite_width * pixel_size;
-
-       /* Use the minimum of the small and large buffer method for primary */
-       small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
-       large = line_count * line_size;
-
-       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-       *sprite_wm = entries + display->guard_size;
-
-       return *sprite_wm > 0x3ff ? false : true;
-}
-
-static void sandybridge_update_sprite_wm(struct drm_plane *plane,
-                                        struct drm_crtc *crtc,
-                                        uint32_t sprite_width, int pixel_size,
-                                        bool enabled, bool scaled)
-{
-       struct drm_device *dev = plane->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe = to_intel_plane(plane)->pipe;
-       int latency = dev_priv->wm.spr_latency[0] * 100;        /* In unit 0.1us */
-       u32 val;
-       int sprite_wm, reg;
-       int ret;
-
-       if (!enabled)
-               return;
-
-       switch (pipe) {
-       case 0:
-               reg = WM0_PIPEA_ILK;
-               break;
-       case 1:
-               reg = WM0_PIPEB_ILK;
-               break;
-       case 2:
-               reg = WM0_PIPEC_IVB;
-               break;
-       default:
-               return; /* bad pipe */
-       }
-
-       ret = sandybridge_compute_sprite_wm(dev, pipe, sprite_width, pixel_size,
-                                           &sandybridge_display_wm_info,
-                                           latency, &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite wm for pipe %c\n",
-                             pipe_name(pipe));
-               return;
-       }
-
-       val = I915_READ(reg);
-       val &= ~WM0_PIPE_SPRITE_MASK;
-       I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));
-       DRM_DEBUG_KMS("sprite watermarks For pipe %c - %d\n", pipe_name(pipe), sprite_wm);
-
-
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             dev_priv->wm.spr_latency[1] * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %c\n",
-                             pipe_name(pipe));
-               return;
-       }
-       I915_WRITE(WM1S_LP_ILK, sprite_wm);
-
-       /* Only IVB has two more LP watermarks for sprite */
-       if (!IS_IVYBRIDGE(dev))
-               return;
-
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             dev_priv->wm.spr_latency[2] * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %c\n",
-                             pipe_name(pipe));
-               return;
-       }
-       I915_WRITE(WM2S_LP_IVB, sprite_wm);
+       intel_plane->wm.bytes_per_pixel = pixel_size;
 
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             dev_priv->wm.spr_latency[3] * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %c\n",
-                             pipe_name(pipe));
-               return;
-       }
-       I915_WRITE(WM3S_LP_IVB, sprite_wm);
+       /*
+        * IVB workaround: must disable low power watermarks for at least
+        * one frame before enabling scaling.  LP watermarks can be re-enabled
+        * when scaling is disabled.
+        *
+        * WaCxSRDisabledForSpriteScaling:ivb
+        */
+       if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev))
+               intel_wait_for_vblank(dev, intel_plane->pipe);
+
+       ilk_update_wm(crtc);
 }
 
 static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct hsw_wm_values *hw = &dev_priv->wm.hw;
+       struct ilk_wm_values *hw = &dev_priv->wm.hw;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_pipe_wm *active = &intel_crtc->wm.active;
        enum pipe pipe = intel_crtc->pipe;
@@ -3158,7 +2614,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
        };
 
        hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
-       hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
 
        if (intel_crtc_active(crtc)) {
                u32 tmp = hw->wm_pipe[pipe];
@@ -3190,7 +2647,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
 void ilk_wm_get_hw_state(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct hsw_wm_values *hw = &dev_priv->wm.hw;
+       struct ilk_wm_values *hw = &dev_priv->wm.hw;
        struct drm_crtc *crtc;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
@@ -3204,8 +2661,12 @@ void ilk_wm_get_hw_state(struct drm_device *dev)
        hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
        hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
 
-       hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
-               INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
+                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
+       else if (IS_IVYBRIDGE(dev))
+               hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
+                       INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
 
        hw->enable_fbc_wm =
                !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS);
@@ -3430,26 +2891,19 @@ static void ironlake_disable_drps(struct drm_device *dev)
  * ourselves, instead of doing a rmw cycle (which might result in us clearing
  * all limits and the gpu stuck at whatever frequency it is at atm).
  */
-static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val)
+static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 val)
 {
        u32 limits;
 
-       limits = 0;
-
-       if (*val >= dev_priv->rps.max_delay)
-               *val = dev_priv->rps.max_delay;
-       limits |= dev_priv->rps.max_delay << 24;
-
        /* Only set the down limit when we've reached the lowest level to avoid
         * getting more interrupts, otherwise leave this clear. This prevents a
         * race in the hw when coming out of rc6: There's a tiny window where
         * the hw runs at the minimal clock before selecting the desired
         * frequency, if the down threshold expires in that window we will not
         * receive a down interrupt. */
-       if (*val <= dev_priv->rps.min_delay) {
-               *val = dev_priv->rps.min_delay;
+       limits = dev_priv->rps.max_delay << 24;
+       if (val <= dev_priv->rps.min_delay)
                limits |= dev_priv->rps.min_delay << 16;
-       }
 
        return limits;
 }
@@ -3549,7 +3003,6 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 void gen6_set_rps(struct drm_device *dev, u8 val)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 limits = gen6_rps_limits(dev_priv, &val);
 
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
        WARN_ON(val > dev_priv->rps.max_delay);
@@ -3572,7 +3025,8 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
        /* Make sure we continue to get interrupts
         * until we hit the minimum or maximum frequencies.
         */
-       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
+       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+                  gen6_rps_limits(dev_priv, val));
 
        POSTING_READ(GEN6_RPNSWREQ);
 
@@ -3583,9 +3037,11 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 
 void gen6_rps_idle(struct drm_i915_private *dev_priv)
 {
+       struct drm_device *dev = dev_priv->dev;
+
        mutex_lock(&dev_priv->rps.hw_lock);
        if (dev_priv->rps.enabled) {
-               if (dev_priv->info->is_valleyview)
+               if (IS_VALLEYVIEW(dev))
                        valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
                else
                        gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay);
@@ -3596,9 +3052,11 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
 
 void gen6_rps_boost(struct drm_i915_private *dev_priv)
 {
+       struct drm_device *dev = dev_priv->dev;
+
        mutex_lock(&dev_priv->rps.hw_lock);
        if (dev_priv->rps.enabled) {
-               if (dev_priv->info->is_valleyview)
+               if (IS_VALLEYVIEW(dev))
                        valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
                else
                        gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay);
@@ -3607,48 +3065,18 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv)
        mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
-/*
- * Wait until the previous freq change has completed,
- * or the timeout elapsed, and then update our notion
- * of the current GPU frequency.
- */
-static void vlv_update_rps_cur_delay(struct drm_i915_private *dev_priv)
-{
-       u32 pval;
-
-       WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-
-       if (wait_for(((pval = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS)) & GENFREQSTATUS) == 0, 10))
-               DRM_DEBUG_DRIVER("timed out waiting for Punit\n");
-
-       pval >>= 8;
-
-       if (pval != dev_priv->rps.cur_delay)
-               DRM_DEBUG_DRIVER("Punit overrode GPU freq: %d MHz (%u) requested, but got %d Mhz (%u)\n",
-                                vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.cur_delay),
-                                dev_priv->rps.cur_delay,
-                                vlv_gpu_freq(dev_priv->mem_freq, pval), pval);
-
-       dev_priv->rps.cur_delay = pval;
-}
-
 void valleyview_set_rps(struct drm_device *dev, u8 val)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       gen6_rps_limits(dev_priv, &val);
-
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
        WARN_ON(val > dev_priv->rps.max_delay);
        WARN_ON(val < dev_priv->rps.min_delay);
 
-       vlv_update_rps_cur_delay(dev_priv);
-
        DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.cur_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
                         dev_priv->rps.cur_delay,
-                        vlv_gpu_freq(dev_priv->mem_freq, val), val);
+                        vlv_gpu_freq(dev_priv, val), val);
 
        if (val == dev_priv->rps.cur_delay)
                return;
@@ -3657,7 +3085,7 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 
        dev_priv->rps.cur_delay = val;
 
-       trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val));
+       trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
 
 static void gen6_disable_rps_interrupts(struct drm_device *dev)
@@ -3775,7 +3203,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
        /* 1c & 1d: Get forcewake during program sequence. Although the driver
         * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        /* 2a: Disable RC states. */
        I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -3832,7 +3260,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
        gen6_enable_rps_interrupts(dev);
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 static void gen6_enable_rps(struct drm_device *dev)
@@ -3862,7 +3290,7 @@ static void gen6_enable_rps(struct drm_device *dev)
                I915_WRITE(GTFIFODBG, gtfifodbg);
        }
 
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
        gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
@@ -3954,7 +3382,7 @@ static void gen6_enable_rps(struct drm_device *dev)
                        DRM_ERROR("Couldn't fix incorrect rc6 voltage\n");
        }
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void gen6_update_ring_freq(struct drm_device *dev)
@@ -4116,7 +3544,8 @@ static void valleyview_enable_rps(struct drm_device *dev)
 
        valleyview_setup_pctx(dev);
 
-       gen6_gt_force_wake_get(dev_priv);
+       /* If VLV, Forcewake all wells, else re-direct to regular path */
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
        I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000);
@@ -4140,7 +3569,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
        for_each_ring(ring, dev_priv, i)
                I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
 
-       I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350);
+       I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
 
        /* allows RC6 residency counter to work */
        I915_WRITE(VLV_COUNTER_CONTROL,
@@ -4148,65 +3577,47 @@ static void valleyview_enable_rps(struct drm_device *dev)
                                      VLV_MEDIA_RC6_COUNT_EN |
                                      VLV_RENDER_RC6_COUNT_EN));
        if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
-               rc6_mode = GEN7_RC_CTL_TO_MODE;
+               rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL;
 
        intel_print_rc6_info(dev, rc6_mode);
 
        I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
 
        val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-       switch ((val >> 6) & 3) {
-       case 0:
-       case 1:
-               dev_priv->mem_freq = 800;
-               break;
-       case 2:
-               dev_priv->mem_freq = 1066;
-               break;
-       case 3:
-               dev_priv->mem_freq = 1333;
-               break;
-       }
-       DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
        DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
        DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
 
        dev_priv->rps.cur_delay = (val >> 8) & 0xff;
        DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.cur_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
                         dev_priv->rps.cur_delay);
 
        dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv);
        dev_priv->rps.hw_max = dev_priv->rps.max_delay;
        DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.max_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay),
                         dev_priv->rps.max_delay);
 
        dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv);
        DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.rpe_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
                         dev_priv->rps.rpe_delay);
 
        dev_priv->rps.min_delay = valleyview_rps_min_freq(dev_priv);
        DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.min_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay),
                         dev_priv->rps.min_delay);
 
        DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.rpe_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
                         dev_priv->rps.rpe_delay);
 
        valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
 
        gen6_enable_rps_interrupts(dev);
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void ironlake_teardown_rc6(struct drm_device *dev)
@@ -5019,6 +4430,20 @@ static void g4x_disable_trickle_feed(struct drm_device *dev)
        }
 }
 
+static void ilk_init_lp_watermarks(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN);
+       I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN);
+       I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN);
+
+       /*
+        * Don't touch WM1S_LP_EN here.
+        * Doing so could cause underruns.
+        */
+}
+
 static void ironlake_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5052,9 +4477,8 @@ static void ironlake_init_clock_gating(struct drm_device *dev)
        I915_WRITE(DISP_ARB_CTL,
                   (I915_READ(DISP_ARB_CTL) |
                    DISP_FBC_WM_DIS));
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+
+       ilk_init_lp_watermarks(dev);
 
        /*
         * Based on the document from hardware guys the following bits
@@ -5161,9 +4585,7 @@ static void gen6_init_clock_gating(struct drm_device *dev)
                I915_WRITE(GEN6_GT_MODE,
                           _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE));
 
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       ilk_init_lp_watermarks(dev);
 
        I915_WRITE(CACHE_MODE_0,
                   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
@@ -5304,28 +4726,40 @@ static void gen8_init_clock_gating(struct drm_device *dev)
        I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
                   _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE));
 
-       /* WaSwitchSolVfFArbitrationPriority */
+       /* WaSwitchSolVfFArbitrationPriority:bdw */
        I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
 
-       /* WaPsrDPAMaskVBlankInSRD */
+       /* WaPsrDPAMaskVBlankInSRD:bdw */
        I915_WRITE(CHICKEN_PAR1_1,
                   I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD);
 
-       /* WaPsrDPRSUnmaskVBlankInSRD */
+       /* WaPsrDPRSUnmaskVBlankInSRD:bdw */
        for_each_pipe(i) {
                I915_WRITE(CHICKEN_PIPESL_1(i),
                           I915_READ(CHICKEN_PIPESL_1(i) |
                                     DPRS_MASK_VBLANK_SRD));
        }
+
+       /* Use Force Non-Coherent whenever executing a 3D context. This is a
+        * workaround for for a possible hang in the unlikely event a TLB
+        * invalidation occurs during a PSD flush.
+        */
+       I915_WRITE(HDC_CHICKEN0,
+                  I915_READ(HDC_CHICKEN0) |
+                  _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT));
+
+       /* WaVSRefCountFullforceMissDisable:bdw */
+       /* WaDSRefCountFullforceMissDisable:bdw */
+       I915_WRITE(GEN7_FF_THREAD_MODE,
+                  I915_READ(GEN7_FF_THREAD_MODE) &
+                  ~(GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME));
 }
 
 static void haswell_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       ilk_init_lp_watermarks(dev);
 
        /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
         * This implements the WaDisableRCZUnitClockGating:hsw workaround.
@@ -5374,9 +4808,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t snpcr;
 
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       ilk_init_lp_watermarks(dev);
 
        I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
 
@@ -5463,6 +4895,26 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 static void valleyview_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val;
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+       mutex_unlock(&dev_priv->rps.hw_lock);
+       switch ((val >> 6) & 3) {
+       case 0:
+               dev_priv->mem_freq = 800;
+               break;
+       case 1:
+               dev_priv->mem_freq = 1066;
+               break;
+       case 2:
+               dev_priv->mem_freq = 1333;
+               break;
+       case 3:
+               dev_priv->mem_freq = 1333;
+               break;
+       }
+       DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
        I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
 
@@ -5642,51 +5094,137 @@ void intel_suspend_hw(struct drm_device *dev)
                lpt_suspend_hw(dev);
 }
 
-static bool is_always_on_power_domain(struct drm_device *dev,
-                                     enum intel_display_power_domain domain)
-{
-       unsigned long always_on_domains;
-
-       BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK);
-
-       if (IS_BROADWELL(dev)) {
-               always_on_domains = BDW_ALWAYS_ON_POWER_DOMAINS;
-       } else if (IS_HASWELL(dev)) {
-               always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS;
-       } else {
-               WARN_ON(1);
-               return true;
-       }
+#define for_each_power_well(i, power_well, domain_mask, power_domains) \
+       for (i = 0;                                                     \
+            i < (power_domains)->power_well_count &&                   \
+                ((power_well) = &(power_domains)->power_wells[i]);     \
+            i++)                                                       \
+               if ((power_well)->domains & (domain_mask))
 
-       return BIT(domain) & always_on_domains;
-}
+#define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
+       for (i = (power_domains)->power_well_count - 1;                  \
+            i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
+            i--)                                                        \
+               if ((power_well)->domains & (domain_mask))
 
 /**
  * We should only use the power well if we explicitly asked the hardware to
  * enable it, so check if it's enabled and also check if we've requested it to
  * be enabled.
  */
+static bool hsw_power_well_enabled(struct drm_device *dev,
+                                  struct i915_power_well *power_well)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       return I915_READ(HSW_PWR_WELL_DRIVER) ==
+                    (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
+}
+
+bool intel_display_power_enabled_sw(struct drm_device *dev,
+                                   enum intel_display_power_domain domain)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains;
+
+       power_domains = &dev_priv->power_domains;
+
+       return power_domains->domain_use_count[domain];
+}
+
 bool intel_display_power_enabled(struct drm_device *dev,
                                 enum intel_display_power_domain domain)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains;
+       struct i915_power_well *power_well;
+       bool is_enabled;
+       int i;
 
-       if (!HAS_POWER_WELL(dev))
-               return true;
+       power_domains = &dev_priv->power_domains;
 
-       if (is_always_on_power_domain(dev, domain))
-               return true;
+       is_enabled = true;
 
-       return I915_READ(HSW_PWR_WELL_DRIVER) ==
-                    (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
+       mutex_lock(&power_domains->lock);
+       for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
+               if (power_well->always_on)
+                       continue;
+
+               if (!power_well->is_enabled(dev, power_well)) {
+                       is_enabled = false;
+                       break;
+               }
+       }
+       mutex_unlock(&power_domains->lock);
+
+       return is_enabled;
+}
+
+static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       unsigned long irqflags;
+
+       /*
+        * After we re-enable the power well, if we touch VGA register 0x3d5
+        * we'll get unclaimed register interrupts. This stops after we write
+        * anything to the VGA MSR register. The vgacon module uses this
+        * register all the time, so if we unbind our driver and, as a
+        * consequence, bind vgacon, we'll get stuck in an infinite loop at
+        * console_unlock(). So make here we touch the VGA MSR register, making
+        * sure vgacon can keep working normally without triggering interrupts
+        * and error messages.
+        */
+       vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
+       outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
+       vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
+
+       if (IS_BROADWELL(dev)) {
+               spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+               I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
+                          dev_priv->de_irq_mask[PIPE_B]);
+               I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
+                          ~dev_priv->de_irq_mask[PIPE_B] |
+                          GEN8_PIPE_VBLANK);
+               I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
+                          dev_priv->de_irq_mask[PIPE_C]);
+               I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
+                          ~dev_priv->de_irq_mask[PIPE_C] |
+                          GEN8_PIPE_VBLANK);
+               POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
+               spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+       }
+}
+
+static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       enum pipe p;
+       unsigned long irqflags;
+
+       /*
+        * After this, the registers on the pipes that are part of the power
+        * well will become zero, so we have to adjust our counters according to
+        * that.
+        *
+        * FIXME: Should we do this in general in drm_vblank_post_modeset?
+        */
+       spin_lock_irqsave(&dev->vbl_lock, irqflags);
+       for_each_pipe(p)
+               if (p != PIPE_A)
+                       dev->vblank[p].last = 0;
+       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 
-static void __intel_set_power_well(struct drm_device *dev, bool enable)
+static void hsw_set_power_well(struct drm_device *dev,
+                              struct i915_power_well *power_well, bool enable)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        bool is_enabled, enable_requested;
        uint32_t tmp;
 
+       WARN_ON(dev_priv->pc8.enabled);
+
        tmp = I915_READ(HSW_PWR_WELL_DRIVER);
        is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
        enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
@@ -5702,28 +5240,15 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
                                      HSW_PWR_WELL_STATE_ENABLED), 20))
                                DRM_ERROR("Timeout enabling power well\n");
                }
+
+               hsw_power_well_post_enable(dev_priv);
        } else {
                if (enable_requested) {
-                       unsigned long irqflags;
-                       enum pipe p;
-
                        I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
                        POSTING_READ(HSW_PWR_WELL_DRIVER);
                        DRM_DEBUG_KMS("Requesting to disable the power well\n");
 
-                       /*
-                        * After this, the registers on the pipes that are part
-                        * of the power well will become zero, so we have to
-                        * adjust our counters according to that.
-                        *
-                        * FIXME: Should we do this in general in
-                        * drm_vblank_post_modeset?
-                        */
-                       spin_lock_irqsave(&dev->vbl_lock, irqflags);
-                       for_each_pipe(p)
-                               if (p != PIPE_A)
-                                       dev->vblank[p].last = 0;
-                       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+                       hsw_power_well_post_disable(dev_priv);
                }
        }
 }
@@ -5731,16 +5256,26 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 static void __intel_power_well_get(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
-       if (!power_well->count++)
-               __intel_set_power_well(dev, true);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!power_well->count++ && power_well->set) {
+               hsw_disable_package_c8(dev_priv);
+               power_well->set(dev, power_well, true);
+       }
 }
 
 static void __intel_power_well_put(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        WARN_ON(!power_well->count);
-       if (!--power_well->count && i915_disable_power_well)
-               __intel_set_power_well(dev, false);
+
+       if (!--power_well->count && power_well->set &&
+           i915_disable_power_well) {
+               power_well->set(dev, power_well, false);
+               hsw_enable_package_c8(dev_priv);
+       }
 }
 
 void intel_display_power_get(struct drm_device *dev,
@@ -5748,17 +5283,18 @@ void intel_display_power_get(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
-
-       if (is_always_on_power_domain(dev, domain))
-               return;
+       struct i915_power_well *power_well;
+       int i;
 
        power_domains = &dev_priv->power_domains;
 
        mutex_lock(&power_domains->lock);
-       __intel_power_well_get(dev, &power_domains->power_wells[0]);
+
+       for_each_power_well(i, power_well, BIT(domain), power_domains)
+               __intel_power_well_get(dev, power_well);
+
+       power_domains->domain_use_count[domain]++;
+
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5767,17 +5303,19 @@ void intel_display_power_put(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
-
-       if (is_always_on_power_domain(dev, domain))
-               return;
+       struct i915_power_well *power_well;
+       int i;
 
        power_domains = &dev_priv->power_domains;
 
        mutex_lock(&power_domains->lock);
-       __intel_power_well_put(dev, &power_domains->power_wells[0]);
+
+       WARN_ON(!power_domains->domain_use_count[domain]);
+       power_domains->domain_use_count[domain]--;
+
+       for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
+               __intel_power_well_put(dev, power_well);
+
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5793,10 +5331,7 @@ void i915_request_power_well(void)
 
        dev_priv = container_of(hsw_pwr, struct drm_i915_private,
                                power_domains);
-
-       mutex_lock(&hsw_pwr->lock);
-       __intel_power_well_get(dev_priv->dev, &hsw_pwr->power_wells[0]);
-       mutex_unlock(&hsw_pwr->lock);
+       intel_display_power_get(dev_priv->dev, POWER_DOMAIN_AUDIO);
 }
 EXPORT_SYMBOL_GPL(i915_request_power_well);
 
@@ -5810,24 +5345,71 @@ void i915_release_power_well(void)
 
        dev_priv = container_of(hsw_pwr, struct drm_i915_private,
                                power_domains);
-
-       mutex_lock(&hsw_pwr->lock);
-       __intel_power_well_put(dev_priv->dev, &hsw_pwr->power_wells[0]);
-       mutex_unlock(&hsw_pwr->lock);
+       intel_display_power_put(dev_priv->dev, POWER_DOMAIN_AUDIO);
 }
 EXPORT_SYMBOL_GPL(i915_release_power_well);
 
+static struct i915_power_well i9xx_always_on_power_well[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = POWER_DOMAIN_MASK,
+       },
+};
+
+static struct i915_power_well hsw_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = HSW_ALWAYS_ON_POWER_DOMAINS,
+       },
+       {
+               .name = "display",
+               .domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS,
+               .is_enabled = hsw_power_well_enabled,
+               .set = hsw_set_power_well,
+       },
+};
+
+static struct i915_power_well bdw_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = BDW_ALWAYS_ON_POWER_DOMAINS,
+       },
+       {
+               .name = "display",
+               .domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS,
+               .is_enabled = hsw_power_well_enabled,
+               .set = hsw_set_power_well,
+       },
+};
+
+#define set_power_wells(power_domains, __power_wells) ({               \
+       (power_domains)->power_wells = (__power_wells);                 \
+       (power_domains)->power_well_count = ARRAY_SIZE(__power_wells);  \
+})
+
 int intel_power_domains_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains = &dev_priv->power_domains;
-       struct i915_power_well *power_well;
 
        mutex_init(&power_domains->lock);
-       hsw_pwr = power_domains;
 
-       power_well = &power_domains->power_wells[0];
-       power_well->count = 0;
+       /*
+        * The enabling order will be from lower to higher indexed wells,
+        * the disabling order is reversed.
+        */
+       if (IS_HASWELL(dev)) {
+               set_power_wells(power_domains, hsw_power_wells);
+               hsw_pwr = power_domains;
+       } else if (IS_BROADWELL(dev)) {
+               set_power_wells(power_domains, bdw_power_wells);
+               hsw_pwr = power_domains;
+       } else {
+               set_power_wells(power_domains, i9xx_always_on_power_well);
+       }
 
        return 0;
 }
@@ -5842,15 +5424,13 @@ static void intel_power_domains_resume(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains = &dev_priv->power_domains;
        struct i915_power_well *power_well;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
+       int i;
 
        mutex_lock(&power_domains->lock);
-
-       power_well = &power_domains->power_wells[0];
-       __intel_set_power_well(dev, power_well->count > 0);
-
+       for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
+               if (power_well->set)
+                       power_well->set(dev, power_well, power_well->count > 0);
+       }
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5864,13 +5444,13 @@ void intel_power_domains_init_hw(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (!HAS_POWER_WELL(dev))
-               return;
-
        /* For now, we need the power well to be always enabled. */
        intel_display_set_init_power(dev, true);
        intel_power_domains_resume(dev);
 
+       if (!(IS_HASWELL(dev) || IS_BROADWELL(dev)))
+               return;
+
        /* We're taking over the BIOS, so clear any requests made by it since
         * the driver is in charge now. */
        if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
@@ -5888,31 +5468,86 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
        hsw_enable_package_c8(dev_priv);
 }
 
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_get_sync(device);
+       WARN(dev_priv->pm.suspended, "Device still suspended.\n");
+}
+
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_mark_last_busy(device);
+       pm_runtime_put_autosuspend(device);
+}
+
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       dev_priv->pm.suspended = false;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_set_active(device);
+
+       pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
+       pm_runtime_mark_last_busy(device);
+       pm_runtime_use_autosuspend(device);
+}
+
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       /* Make sure we're not suspended first. */
+       pm_runtime_get_sync(device);
+       pm_runtime_disable(device);
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (I915_HAS_FBC(dev)) {
-               if (HAS_PCH_SPLIT(dev)) {
+       if (HAS_FBC(dev)) {
+               if (INTEL_INFO(dev)->gen >= 7) {
                        dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
-                       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
-                               dev_priv->display.enable_fbc =
-                                       gen7_enable_fbc;
-                       else
-                               dev_priv->display.enable_fbc =
-                                       ironlake_enable_fbc;
+                       dev_priv->display.enable_fbc = gen7_enable_fbc;
+                       dev_priv->display.disable_fbc = ironlake_disable_fbc;
+               } else if (INTEL_INFO(dev)->gen >= 5) {
+                       dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
+                       dev_priv->display.enable_fbc = ironlake_enable_fbc;
                        dev_priv->display.disable_fbc = ironlake_disable_fbc;
                } else if (IS_GM45(dev)) {
                        dev_priv->display.fbc_enabled = g4x_fbc_enabled;
                        dev_priv->display.enable_fbc = g4x_enable_fbc;
                        dev_priv->display.disable_fbc = g4x_disable_fbc;
-               } else if (IS_CRESTLINE(dev)) {
+               } else {
                        dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
                        dev_priv->display.enable_fbc = i8xx_enable_fbc;
                        dev_priv->display.disable_fbc = i8xx_disable_fbc;
+
+                       /* This value was pulled out of someone's hat */
+                       I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
                }
-               /* 855GM needs testing */
        }
 
        /* For cxsr */
@@ -5925,58 +5560,27 @@ void intel_init_pm(struct drm_device *dev)
        if (HAS_PCH_SPLIT(dev)) {
                intel_setup_wm_latency(dev);
 
-               if (IS_GEN5(dev)) {
-                       if (dev_priv->wm.pri_latency[1] &&
-                           dev_priv->wm.spr_latency[1] &&
-                           dev_priv->wm.cur_latency[1])
-                               dev_priv->display.update_wm = ironlake_update_wm;
-                       else {
-                               DRM_DEBUG_KMS("Failed to get proper latency. "
-                                             "Disable CxSR\n");
-                               dev_priv->display.update_wm = NULL;
-                       }
+               if ((IS_GEN5(dev) && dev_priv->wm.pri_latency[1] &&
+                    dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
+                   (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
+                    dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
+                       dev_priv->display.update_wm = ilk_update_wm;
+                       dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
+               } else {
+                       DRM_DEBUG_KMS("Failed to read display plane latency. "
+                                     "Disable CxSR\n");
+               }
+
+               if (IS_GEN5(dev))
                        dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
-               } else if (IS_GEN6(dev)) {
-                       if (dev_priv->wm.pri_latency[0] &&
-                           dev_priv->wm.spr_latency[0] &&
-                           dev_priv->wm.cur_latency[0]) {
-                               dev_priv->display.update_wm = sandybridge_update_wm;
-                               dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
-                       } else {
-                               DRM_DEBUG_KMS("Failed to read display plane latency. "
-                                             "Disable CxSR\n");
-                               dev_priv->display.update_wm = NULL;
-                       }
+               else if (IS_GEN6(dev))
                        dev_priv->display.init_clock_gating = gen6_init_clock_gating;
-               } else if (IS_IVYBRIDGE(dev)) {
-                       if (dev_priv->wm.pri_latency[0] &&
-                           dev_priv->wm.spr_latency[0] &&
-                           dev_priv->wm.cur_latency[0]) {
-                               dev_priv->display.update_wm = ivybridge_update_wm;
-                               dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
-                       } else {
-                               DRM_DEBUG_KMS("Failed to read display plane latency. "
-                                             "Disable CxSR\n");
-                               dev_priv->display.update_wm = NULL;
-                       }
+               else if (IS_IVYBRIDGE(dev))
                        dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
-               } else if (IS_HASWELL(dev)) {
-                       if (dev_priv->wm.pri_latency[0] &&
-                           dev_priv->wm.spr_latency[0] &&
-                           dev_priv->wm.cur_latency[0]) {
-                               dev_priv->display.update_wm = haswell_update_wm;
-                               dev_priv->display.update_sprite_wm =
-                                       haswell_update_sprite_wm;
-                       } else {
-                               DRM_DEBUG_KMS("Failed to read display plane latency. "
-                                             "Disable CxSR\n");
-                               dev_priv->display.update_wm = NULL;
-                       }
+               else if (IS_HASWELL(dev))
                        dev_priv->display.init_clock_gating = haswell_init_clock_gating;
-               } else if (INTEL_INFO(dev)->gen == 8) {
+               else if (INTEL_INFO(dev)->gen == 8)
                        dev_priv->display.init_clock_gating = gen8_init_clock_gating;
-               } else
-                       dev_priv->display.update_wm = NULL;
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->display.update_wm = valleyview_update_wm;
                dev_priv->display.init_clock_gating =
@@ -6010,21 +5614,21 @@ void intel_init_pm(struct drm_device *dev)
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
                dev_priv->display.init_clock_gating = gen3_init_clock_gating;
-       } else if (IS_I865G(dev)) {
-               dev_priv->display.update_wm = i830_update_wm;
-               dev_priv->display.init_clock_gating = i85x_init_clock_gating;
-               dev_priv->display.get_fifo_size = i830_get_fifo_size;
-       } else if (IS_I85X(dev)) {
-               dev_priv->display.update_wm = i9xx_update_wm;
-               dev_priv->display.get_fifo_size = i85x_get_fifo_size;
-               dev_priv->display.init_clock_gating = i85x_init_clock_gating;
-       } else {
-               dev_priv->display.update_wm = i830_update_wm;
-               dev_priv->display.init_clock_gating = i830_init_clock_gating;
-               if (IS_845G(dev))
+       } else if (IS_GEN2(dev)) {
+               if (INTEL_INFO(dev)->num_pipes == 1) {
+                       dev_priv->display.update_wm = i845_update_wm;
                        dev_priv->display.get_fifo_size = i845_get_fifo_size;
-               else
+               } else {
+                       dev_priv->display.update_wm = i9xx_update_wm;
                        dev_priv->display.get_fifo_size = i830_get_fifo_size;
+               }
+
+               if (IS_I85X(dev) || IS_I865G(dev))
+                       dev_priv->display.init_clock_gating = i85x_init_clock_gating;
+               else
+                       dev_priv->display.init_clock_gating = i830_init_clock_gating;
+       } else {
+               DRM_ERROR("unexpected fall-through in intel_init_pm\n");
        }
 }
 
@@ -6075,65 +5679,63 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
        return 0;
 }
 
-int vlv_gpu_freq(int ddr_freq, int val)
+int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
-       int mult, base;
+       int div;
 
-       switch (ddr_freq) {
+       /* 4 x czclk */
+       switch (dev_priv->mem_freq) {
        case 800:
-               mult = 20;
-               base = 120;
+               div = 10;
                break;
        case 1066:
-               mult = 22;
-               base = 133;
+               div = 12;
                break;
        case 1333:
-               mult = 21;
-               base = 125;
+               div = 16;
                break;
        default:
                return -1;
        }
 
-       return ((val - 0xbd) * mult) + base;
+       return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div);
 }
 
-int vlv_freq_opcode(int ddr_freq, int val)
+int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
-       int mult, base;
+       int mul;
 
-       switch (ddr_freq) {
+       /* 4 x czclk */
+       switch (dev_priv->mem_freq) {
        case 800:
-               mult = 20;
-               base = 120;
+               mul = 10;
                break;
        case 1066:
-               mult = 22;
-               base = 133;
+               mul = 12;
                break;
        case 1333:
-               mult = 21;
-               base = 125;
+               mul = 16;
                break;
        default:
                return -1;
        }
 
-       val /= mult;
-       val -= base / mult;
-       val += 0xbd;
-
-       if (val > 0xea)
-               val = 0xea;
-
-       return val;
+       return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6;
 }
 
-void intel_pm_init(struct drm_device *dev)
+void intel_pm_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       mutex_init(&dev_priv->rps.hw_lock);
+
+       mutex_init(&dev_priv->pc8.lock);
+       dev_priv->pc8.requirements_met = false;
+       dev_priv->pc8.gpu_idle = false;
+       dev_priv->pc8.irqs_disabled = false;
+       dev_priv->pc8.enabled = false;
+       dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
+       INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
        INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
                          intel_gen6_powersave_work);
 }
index b620337e6d672c164448090016a27d1b713a2a24..b7f1742caf878250c3fb6dc98b5bdbe63ae4a601 100644 (file)
@@ -285,14 +285,16 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value)
        if (!ring->fbc_dirty)
                return 0;
 
-       ret = intel_ring_begin(ring, 4);
+       ret = intel_ring_begin(ring, 6);
        if (ret)
                return ret;
-       intel_ring_emit(ring, MI_NOOP);
        /* WaFbcNukeOn3DBlt:ivb/hsw */
        intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
        intel_ring_emit(ring, MSG_FBC_REND_STATE);
        intel_ring_emit(ring, value);
+       intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT);
+       intel_ring_emit(ring, MSG_FBC_REND_STATE);
+       intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
        intel_ring_advance(ring);
 
        ring->fbc_dirty = false;
@@ -354,7 +356,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring,
        intel_ring_emit(ring, 0);
        intel_ring_advance(ring);
 
-       if (flush_domains)
+       if (!invalidate_domains && flush_domains)
                return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
 
        return 0;
@@ -436,7 +438,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
        int ret = 0;
        u32 head;
 
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        if (I915_NEED_GFX_HWS(dev))
                intel_ring_setup_status_page(ring);
@@ -509,7 +511,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
        memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
 
 out:
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 
        return ret;
 }
@@ -661,19 +663,22 @@ gen6_add_request(struct intel_ring_buffer *ring)
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_ring_buffer *useless;
-       int i, ret;
+       int i, ret, num_dwords = 4;
 
-       ret = intel_ring_begin(ring, ((I915_NUM_RINGS-1) *
-                                     MBOX_UPDATE_DWORDS) +
-                                     4);
+       if (i915_semaphore_is_enabled(dev))
+               num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
+#undef MBOX_UPDATE_DWORDS
+
+       ret = intel_ring_begin(ring, num_dwords);
        if (ret)
                return ret;
-#undef MBOX_UPDATE_DWORDS
 
-       for_each_ring(useless, dev_priv, i) {
-               u32 mbox_reg = ring->signal_mbox[i];
-               if (mbox_reg != GEN6_NOSYNC)
-                       update_mboxes(ring, mbox_reg);
+       if (i915_semaphore_is_enabled(dev)) {
+               for_each_ring(useless, dev_priv, i) {
+                       u32 mbox_reg = ring->signal_mbox[i];
+                       if (mbox_reg != GEN6_NOSYNC)
+                               update_mboxes(ring, mbox_reg);
+               }
        }
 
        intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
@@ -965,6 +970,7 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
        } else if (IS_GEN6(ring->dev)) {
                mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
        } else {
+               /* XXX: gen8 returns to sanity */
                mmio = RING_HWS_PGA(ring->mmio_base);
        }
 
@@ -1029,11 +1035,6 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring)
        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. */
-       gen6_gt_force_wake_get(dev_priv);
-
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (ring->irq_refcount++ == 0) {
                if (HAS_L3_DPF(dev) && ring->id == RCS)
@@ -1065,8 +1066,6 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
                ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask);
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
-
-       gen6_gt_force_wake_put(dev_priv);
 }
 
 static bool
@@ -1610,8 +1609,8 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring)
        return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
 }
 
-static int __intel_ring_begin(struct intel_ring_buffer *ring,
-                             int bytes)
+static int __intel_ring_prepare(struct intel_ring_buffer *ring,
+                               int bytes)
 {
        int ret;
 
@@ -1627,7 +1626,6 @@ static int __intel_ring_begin(struct intel_ring_buffer *ring,
                        return ret;
        }
 
-       ring->space -= bytes;
        return 0;
 }
 
@@ -1642,12 +1640,17 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
        if (ret)
                return ret;
 
+       ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t));
+       if (ret)
+               return ret;
+
        /* Preallocate the olr before touching the ring */
        ret = intel_ring_alloc_seqno(ring);
        if (ret)
                return ret;
 
-       return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t));
+       ring->space -= num_dwords * sizeof(uint32_t);
+       return 0;
 }
 
 void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
@@ -1837,7 +1840,7 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring,
        }
        intel_ring_advance(ring);
 
-       if (IS_GEN7(dev) && flush)
+       if (IS_GEN7(dev) && !invalidate && flush)
                return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN);
 
        return 0;
index a583e8f718a7f0f4b87b4fe724336c73ad1a8198..95bdfb3c431c8467b105c616f6d5f9567505804f 100644 (file)
@@ -413,23 +413,34 @@ static const struct _sdvo_cmd_name {
 static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
                                   const void *args, int args_len)
 {
-       int i;
+       int i, pos = 0;
+#define BUF_LEN 256
+       char buffer[BUF_LEN];
+
+#define BUF_PRINT(args...) \
+       pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args)
+
 
-       DRM_DEBUG_KMS("%s: W: %02X ",
-                               SDVO_NAME(intel_sdvo), cmd);
-       for (i = 0; i < args_len; i++)
-               DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
-       for (; i < 8; i++)
-               DRM_LOG_KMS("   ");
+       for (i = 0; i < args_len; i++) {
+               BUF_PRINT("%02X ", ((u8 *)args)[i]);
+       }
+       for (; i < 8; i++) {
+               BUF_PRINT("   ");
+       }
        for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) {
                if (cmd == sdvo_cmd_names[i].cmd) {
-                       DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name);
+                       BUF_PRINT("(%s)", sdvo_cmd_names[i].name);
                        break;
                }
        }
-       if (i == ARRAY_SIZE(sdvo_cmd_names))
-               DRM_LOG_KMS("(%02X)", cmd);
-       DRM_LOG_KMS("\n");
+       if (i == ARRAY_SIZE(sdvo_cmd_names)) {
+               BUF_PRINT("(%02X)", cmd);
+       }
+       BUG_ON(pos >= BUF_LEN - 1);
+#undef BUF_PRINT
+#undef BUF_LEN
+
+       DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer);
 }
 
 static const char *cmd_status_names[] = {
@@ -512,9 +523,10 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
 {
        u8 retry = 15; /* 5 quick checks, followed by 10 long checks */
        u8 status;
-       int i;
+       int i, pos = 0;
+#define BUF_LEN 256
+       char buffer[BUF_LEN];
 
-       DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo));
 
        /*
         * The documentation states that all commands will be
@@ -551,10 +563,13 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
                        goto log_fail;
        }
 
+#define BUF_PRINT(args...) \
+       pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args)
+
        if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-               DRM_LOG_KMS("(%s)", cmd_status_names[status]);
+               BUF_PRINT("(%s)", cmd_status_names[status]);
        else
-               DRM_LOG_KMS("(??? %d)", status);
+               BUF_PRINT("(??? %d)", status);
 
        if (status != SDVO_CMD_STATUS_SUCCESS)
                goto log_fail;
@@ -565,13 +580,17 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
                                          SDVO_I2C_RETURN_0 + i,
                                          &((u8 *)response)[i]))
                        goto log_fail;
-               DRM_LOG_KMS(" %02X", ((u8 *)response)[i]);
+               BUF_PRINT(" %02X", ((u8 *)response)[i]);
        }
-       DRM_LOG_KMS("\n");
+       BUG_ON(pos >= BUF_LEN - 1);
+#undef BUF_PRINT
+#undef BUF_LEN
+
+       DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(intel_sdvo), buffer);
        return true;
 
 log_fail:
-       DRM_LOG_KMS("... failed\n");
+       DRM_DEBUG_KMS("%s: R: ... failed\n", SDVO_NAME(intel_sdvo));
        return false;
 }
 
@@ -933,7 +952,7 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 
 static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
                                       unsigned if_index, uint8_t tx_rate,
-                                      uint8_t *data, unsigned length)
+                                      const uint8_t *data, unsigned length)
 {
        uint8_t set_buf_index[2] = { if_index, 0 };
        uint8_t hbuf_size, tmp[8];
@@ -1517,8 +1536,9 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_sdvo_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_sdvo_mode_valid(struct drm_connector *connector,
+                     struct drm_display_mode *mode)
 {
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
 
index 770bdd6ecd9fb96b46365bbadd97ba3011c0ef96..2e2d4eb4a00d190b24c03c1998b4e9f0cd9f06c5 100644 (file)
@@ -59,7 +59,7 @@ struct intel_sdvo_caps {
        unsigned int stall_support:1;
        unsigned int pad:1;
        u16 output_flags;
-} __attribute__((packed));
+} __packed;
 
 /* Note: SDVO detailed timing flags match EDID misc flags. */
 #define DTD_FLAG_HSYNC_POSITIVE (1 << 1)
@@ -94,12 +94,12 @@ struct intel_sdvo_dtd {
                u8 v_sync_off_high;
                u8 reserved;
        } part2;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_pixel_clock_range {
        u16 min;        /**< pixel clock, in 10kHz units */
        u16 max;        /**< pixel clock, in 10kHz units */
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_preferred_input_timing_args {
        u16 clock;
@@ -108,7 +108,7 @@ struct intel_sdvo_preferred_input_timing_args {
        u8      interlace:1;
        u8      scaled:1;
        u8      pad:6;
-} __attribute__((packed));
+} __packed;
 
 /* I2C registers for SDVO */
 #define SDVO_I2C_ARG_0                         0x07
@@ -162,7 +162,7 @@ struct intel_sdvo_get_trained_inputs_response {
        unsigned int input0_trained:1;
        unsigned int input1_trained:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 /** Returns a struct intel_sdvo_output_flags of active outputs. */
 #define SDVO_CMD_GET_ACTIVE_OUTPUTS                    0x04
@@ -219,7 +219,7 @@ struct intel_sdvo_get_interrupt_event_source_response {
        unsigned int ambient_light_interrupt:1;
        unsigned int hdmi_audio_encrypt_change:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 /**
  * Selects which input is affected by future input commands.
@@ -232,7 +232,7 @@ struct intel_sdvo_get_interrupt_event_source_response {
 struct intel_sdvo_set_target_input_args {
        unsigned int target_1:1;
        unsigned int pad:7;
-} __attribute__((packed));
+} __packed;
 
 /**
  * Takes a struct intel_sdvo_output_flags of which outputs are targeted by
@@ -370,7 +370,7 @@ struct intel_sdvo_tv_format {
        unsigned int hdtv_std_eia_7702a_480i_60:1;
        unsigned int hdtv_std_eia_7702a_480p_60:1;
        unsigned int pad:3;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_TV_FORMAT                         0x28
 
@@ -401,7 +401,7 @@ struct intel_sdvo_sdtv_resolution_request {
        unsigned int secam_l:1;
        unsigned int secam_60:1;
        unsigned int pad:5;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_sdtv_resolution_reply {
        unsigned int res_320x200:1;
@@ -426,7 +426,7 @@ struct intel_sdvo_sdtv_resolution_reply {
        unsigned int res_1024x768:1;
        unsigned int res_1280x1024:1;
        unsigned int pad:5;
-} __attribute__((packed));
+} __packed;
 
 /* Get supported resolution with squire pixel aspect ratio that can be
    scaled for the requested HDTV format */
@@ -463,7 +463,7 @@ struct intel_sdvo_hdtv_resolution_request {
        unsigned int hdtv_std_eia_7702a_480i_60:1;
        unsigned int hdtv_std_eia_7702a_480p_60:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_hdtv_resolution_reply {
        unsigned int res_640x480:1;
@@ -517,7 +517,7 @@ struct intel_sdvo_hdtv_resolution_reply {
 
        unsigned int res_1280x768:1;
        unsigned int pad5:7;
-} __attribute__((packed));
+} __packed;
 
 /* Get supported power state returns info for encoder and monitor, rely on
    last SetTargetInput and SetTargetOutput calls */
@@ -557,13 +557,13 @@ struct sdvo_panel_power_sequencing {
 
        unsigned int t4_high:2;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL               0x30
 struct sdvo_max_backlight_reply {
        u8 max_value;
        u8 default_value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_BACKLIGHT_LEVEL                   0x31
 #define SDVO_CMD_SET_BACKLIGHT_LEVEL                   0x32
@@ -573,14 +573,14 @@ struct sdvo_get_ambient_light_reply {
        u16 trip_low;
        u16 trip_high;
        u16 value;
-} __attribute__((packed));
+} __packed;
 #define SDVO_CMD_SET_AMBIENT_LIGHT                     0x34
 struct sdvo_set_ambient_light_reply {
        u16 trip_low;
        u16 trip_high;
        unsigned int enable:1;
        unsigned int pad:7;
-} __attribute__((packed));
+} __packed;
 
 /* Set display power state */
 #define SDVO_CMD_SET_DISPLAY_POWER_STATE               0x7d
@@ -608,7 +608,7 @@ struct intel_sdvo_enhancements_reply {
        unsigned int dither:1;
        unsigned int tv_chroma_filter:1;
        unsigned int tv_luma_filter:1;
-} __attribute__((packed));
+} __packed;
 
 /* Picture enhancement limits below are dependent on the current TV format,
  * and thus need to be queried and set after it.
@@ -630,7 +630,7 @@ struct intel_sdvo_enhancements_reply {
 struct intel_sdvo_enhancement_limits_reply {
        u16 max_value;
        u16 default_value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_LVDS_PANEL_INFORMATION            0x7f
 #define SDVO_CMD_SET_LVDS_PANEL_INFORMATION            0x80
@@ -671,7 +671,7 @@ struct intel_sdvo_enhancement_limits_reply {
 #define SDVO_CMD_SET_TV_LUMA_FILTER                    0x79
 struct intel_sdvo_enhancements_arg {
        u16 value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_DOT_CRAWL                         0x70
 #define SDVO_CMD_SET_DOT_CRAWL                         0x71
@@ -727,4 +727,4 @@ struct intel_sdvo_enhancements_arg {
 struct intel_sdvo_encode {
        u8 dvi_rev;
        u8 hdmi_rev;
-} __attribute__ ((packed));
+} __packed;
index 9944d8135e87f88215d5d07d54a5fd87fcf4dc60..0954f132726ea0ae15593364ef976168fc2c909f 100644 (file)
@@ -90,6 +90,22 @@ void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val)
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
+u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+       u32 val = 0;
+
+       vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT,
+                       PUNIT_OPCODE_REG_READ, reg, &val);
+
+       return val;
+}
+
+void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+       vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT,
+                       PUNIT_OPCODE_REG_WRITE, reg, &val);
+}
+
 u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr)
 {
        u32 val = 0;
@@ -160,27 +176,18 @@ void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
                        PUNIT_OPCODE_REG_WRITE, reg, &val);
 }
 
-static u32 vlv_get_phy_port(enum pipe pipe)
-{
-       u32 port = IOSF_PORT_DPIO;
-
-       WARN_ON ((pipe != PIPE_A) && (pipe != PIPE_B));
-
-       return port;
-}
-
 u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg)
 {
        u32 val = 0;
 
-       vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe),
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
                        DPIO_OPCODE_REG_READ, reg, &val);
        return val;
 }
 
 void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val)
 {
-       vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe),
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
                        DPIO_OPCODE_REG_WRITE, reg, &val);
 }
 
@@ -242,3 +249,17 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
                return;
        }
 }
+
+u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+       u32 val = 0;
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI,
+                                       DPIO_OPCODE_REG_READ, reg, &val);
+       return val;
+}
+
+void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI,
+                                       DPIO_OPCODE_REG_WRITE, reg, &val);
+}
index b9fabf826f7de71f224bd9b808780f81ba1c9027..716a3c9c0751c18927cb1b10633b6effff584e7b 100644 (file)
@@ -104,6 +104,12 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
                break;
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       sprctl |= SP_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                sprctl |= SP_TILED;
 
@@ -135,8 +141,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 
        I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
        I915_WRITE(SPCNTR(pipe, plane), sprctl);
-       I915_MODIFY_DISPBASE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
-                            sprsurf_offset);
+       I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
+                  sprsurf_offset);
        POSTING_READ(SPSURF(pipe, plane));
 }
 
@@ -152,7 +158,7 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
        I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
                   ~SP_ENABLE);
        /* Activate double buffered register update */
-       I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
+       I915_WRITE(SPSURF(pipe, plane), 0);
        POSTING_READ(SPSURF(pipe, plane));
 
        intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
@@ -224,7 +230,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        u32 sprctl, sprscale = 0;
        unsigned long sprsurf_offset, linear_offset;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
-       bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
 
        sprctl = I915_READ(SPRCTL(pipe));
 
@@ -257,6 +262,12 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                BUG();
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       sprctl |= SPRITE_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                sprctl |= SPRITE_TILED;
 
@@ -279,21 +290,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        crtc_w--;
        crtc_h--;
 
-       /*
-        * IVB workaround: must disable low power watermarks for at least
-        * one frame before enabling scaling.  LP watermarks can be re-enabled
-        * when scaling is disabled.
-        */
-       if (crtc_w != src_w || crtc_h != src_h) {
-               dev_priv->sprite_scaling_enabled |= 1 << pipe;
-
-               if (!scaling_was_enabled) {
-                       intel_update_watermarks(crtc);
-                       intel_wait_for_vblank(dev, pipe);
-               }
+       if (crtc_w != src_w || crtc_h != src_h)
                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
-       } else
-               dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
 
        I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
        I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
@@ -317,13 +315,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        if (intel_plane->can_scale)
                I915_WRITE(SPRSCALE(pipe), sprscale);
        I915_WRITE(SPRCTL(pipe), sprctl);
-       I915_MODIFY_DISPBASE(SPRSURF(pipe),
-                            i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
+       I915_WRITE(SPRSURF(pipe),
+                  i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
        POSTING_READ(SPRSURF(pipe));
-
-       /* potentially re-enable LP watermarks */
-       if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
-               intel_update_watermarks(crtc);
 }
 
 static void
@@ -333,23 +327,22 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_plane *intel_plane = to_intel_plane(plane);
        int pipe = intel_plane->pipe;
-       bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
 
        I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
        /* Can't leave the scaler enabled... */
        if (intel_plane->can_scale)
                I915_WRITE(SPRSCALE(pipe), 0);
        /* Activate double buffered register update */
-       I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
+       I915_WRITE(SPRSURF(pipe), 0);
        POSTING_READ(SPRSURF(pipe));
 
-       dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
+       /*
+        * Avoid underruns when disabling the sprite.
+        * FIXME remove once watermark updates are done properly.
+        */
+       intel_wait_for_vblank(dev, pipe);
 
        intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
-
-       /* potentially re-enable LP watermarks */
-       if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
-               intel_update_watermarks(crtc);
 }
 
 static int
@@ -453,6 +446,12 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                BUG();
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       dvscntr |= DVS_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                dvscntr |= DVS_TILED;
 
@@ -470,7 +469,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        crtc_h--;
 
        dvsscale = 0;
-       if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
+       if (crtc_w != src_w || crtc_h != src_h)
                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
        I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
@@ -490,8 +489,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
        I915_WRITE(DVSSCALE(pipe), dvsscale);
        I915_WRITE(DVSCNTR(pipe), dvscntr);
-       I915_MODIFY_DISPBASE(DVSSURF(pipe),
-                            i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
+       I915_WRITE(DVSSURF(pipe),
+                  i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
        POSTING_READ(DVSSURF(pipe));
 }
 
@@ -507,9 +506,15 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
        /* Disable the scaler */
        I915_WRITE(DVSSCALE(pipe), 0);
        /* Flush double buffered register updates */
-       I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
+       I915_WRITE(DVSSURF(pipe), 0);
        POSTING_READ(DVSSURF(pipe));
 
+       /*
+        * Avoid underruns when disabling the sprite.
+        * FIXME remove once watermark updates are done properly.
+        */
+       intel_wait_for_vblank(dev, pipe);
+
        intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
 }
 
@@ -643,6 +648,15 @@ format_is_yuv(uint32_t format)
        }
 }
 
+static bool colorkey_enabled(struct intel_plane *intel_plane)
+{
+       struct drm_intel_sprite_colorkey key;
+
+       intel_plane->get_colorkey(&intel_plane->base, &key);
+
+       return key.flags != I915_SET_COLORKEY_NONE;
+}
+
 static int
 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -828,7 +842,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
         * If the sprite is completely covering the primary plane,
         * we can disable the primary and save power.
         */
-       disable_primary = drm_rect_equals(&dst, &clip);
+       disable_primary = drm_rect_equals(&dst, &clip) && !colorkey_enabled(intel_plane);
        WARN_ON(disable_primary && !visible && intel_crtc->active);
 
        mutex_lock(&dev->struct_mutex);
index 0b02078a0b848c4127385b1d3b5d3ab6be755c80..87df68f5f504b5a2dd352f503d1af4dbf06c30ba 100644 (file)
@@ -64,7 +64,8 @@ static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, ECOBUS);
 }
 
-static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1) == 0,
                            FORCEWAKE_ACK_TIMEOUT_MS))
@@ -89,7 +90,8 @@ static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, ECOBUS);
 }
 
-static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        u32 forcewake_ack;
 
@@ -121,12 +123,12 @@ static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
        u32 gtfifodbg;
 
        gtfifodbg = __raw_i915_read32(dev_priv, GTFIFODBG);
-       if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
-            "MMIO read or write has been dropped %x\n", gtfifodbg))
-               __raw_i915_write32(dev_priv, GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
+       if (WARN(gtfifodbg, "GT wake FIFO error 0x%x\n", gtfifodbg))
+               __raw_i915_write32(dev_priv, GTFIFODBG, gtfifodbg);
 }
 
-static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        __raw_i915_write32(dev_priv, FORCEWAKE, 0);
        /* something from same cacheline, but !FORCEWAKE */
@@ -134,7 +136,8 @@ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
        gen6_gt_check_fifodbg(dev_priv);
 }
 
-static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        __raw_i915_write32(dev_priv, FORCEWAKE_MT,
                           _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
@@ -147,12 +150,19 @@ static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 {
        int ret = 0;
 
+       /* On VLV, FIFO will be shared by both SW and HW.
+        * So, we need to read the FREE_ENTRIES everytime */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               dev_priv->uncore.fifo_count =
+                       __raw_i915_read32(dev_priv, GTFIFOCTL) &
+                                               GT_FIFO_FREE_ENTRIES_MASK;
+
        if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
                int loop = 500;
-               u32 fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+               u32 fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
                while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
                        udelay(10);
-                       fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+                       fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
                }
                if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
                        ++ret;
@@ -171,38 +181,112 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
 }
 
-static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
+static void __vlv_force_wake_get(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
 {
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0,
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
+       /* Check for Render Engine */
+       if (FORCEWAKE_RENDER & fw_engine) {
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_VLV) &
+                                               FORCEWAKE_KERNEL) == 0,
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: Render forcewake old ack to clear.\n");
 
-       __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
-                          _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-       __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
-                          _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+               __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+                                  _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
 
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL),
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for GT to ack forcewake request.\n");
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_VLV) &
+                                               FORCEWAKE_KERNEL),
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: waiting for Render to ack.\n");
+       }
 
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_MEDIA_VLV) &
-                            FORCEWAKE_KERNEL),
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for media to ack forcewake request.\n");
+       /* Check for Media Engine */
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_MEDIA_VLV) &
+                                               FORCEWAKE_KERNEL) == 0,
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: Media forcewake old ack to clear.\n");
+
+               __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+                                  _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_MEDIA_VLV) &
+                                               FORCEWAKE_KERNEL),
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: waiting for media to ack.\n");
+       }
 
        /* WaRsForcewakeWaitTC0:vlv */
        __gen6_gt_wait_for_thread_c0(dev_priv);
+
 }
 
-static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
+static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
+                                       int fw_engine)
 {
-       __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
-                          _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-       __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
-                          _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
+       /* Check for Render Engine */
+       if (FORCEWAKE_RENDER & fw_engine)
+               __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+                                       _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
+
+       /* Check for Media Engine */
+       if (FORCEWAKE_MEDIA & fw_engine)
+               __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+                               _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
        /* The below doubles as a POSTING_READ */
        gen6_gt_check_fifodbg(dev_priv);
+
+}
+
+void vlv_force_wake_get(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+       if (FORCEWAKE_RENDER & fw_engine) {
+               if (dev_priv->uncore.fw_rendercount++ == 0)
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv,
+                                                       FORCEWAKE_RENDER);
+       }
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               if (dev_priv->uncore.fw_mediacount++ == 0)
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv,
+                                                       FORCEWAKE_MEDIA);
+       }
+
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+void vlv_force_wake_put(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+       if (FORCEWAKE_RENDER & fw_engine) {
+               WARN_ON(dev_priv->uncore.fw_rendercount == 0);
+               if (--dev_priv->uncore.fw_rendercount == 0)
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv,
+                                                       FORCEWAKE_RENDER);
+       }
+
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               WARN_ON(dev_priv->uncore.fw_mediacount == 0);
+               if (--dev_priv->uncore.fw_mediacount == 0)
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv,
+                                                       FORCEWAKE_MEDIA);
+       }
+
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void gen6_force_wake_work(struct work_struct *work)
@@ -213,7 +297,7 @@ static void gen6_force_wake_work(struct work_struct *work)
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (--dev_priv->uncore.forcewake_count == 0)
-               dev_priv->uncore.funcs.force_wake_put(dev_priv);
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
@@ -248,6 +332,11 @@ void intel_uncore_early_sanitize(struct drm_device *dev)
                DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size);
        }
 
+       /* clear out old GT FIFO errors */
+       if (IS_GEN6(dev) || IS_GEN7(dev))
+               __raw_i915_write32(dev_priv, GTFIFODBG,
+                                  __raw_i915_read32(dev_priv, GTFIFODBG));
+
        intel_uncore_forcewake_reset(dev);
 }
 
@@ -256,8 +345,6 @@ void intel_uncore_sanitize(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 reg_val;
 
-       intel_uncore_forcewake_reset(dev);
-
        /* BIOS often leaves RC6 enabled, but disable it for hw init */
        intel_disable_gt_powersave(dev);
 
@@ -281,29 +368,40 @@ void intel_uncore_sanitize(struct drm_device *dev)
  * be called at the beginning of the sequence followed by a call to
  * gen6_gt_force_wake_put() at the end of the sequence.
  */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
 {
        unsigned long irqflags;
 
        if (!dev_priv->uncore.funcs.force_wake_get)
                return;
 
+       intel_runtime_pm_get(dev_priv);
+
+       /* Redirect to VLV specific routine */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               return vlv_force_wake_get(dev_priv, fw_engine);
+
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (dev_priv->uncore.forcewake_count++ == 0)
-               dev_priv->uncore.funcs.force_wake_get(dev_priv);
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 /*
  * see gen6_gt_force_wake_get()
  */
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
 {
        unsigned long irqflags;
 
        if (!dev_priv->uncore.funcs.force_wake_put)
                return;
 
+       /* Redirect to VLV specific routine */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               return vlv_force_wake_put(dev_priv, fw_engine);
+
+
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (--dev_priv->uncore.forcewake_count == 0) {
                dev_priv->uncore.forcewake_count++;
@@ -312,6 +410,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
                                 1);
        }
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 /* We give fast paths for the really cool registers */
@@ -346,6 +446,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
        }
 }
 
+static void
+assert_device_not_suspended(struct drm_i915_private *dev_priv)
+{
+       WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
+            "Device suspended\n");
+}
+
 #define REG_READ_HEADER(x) \
        unsigned long irqflags; \
        u##x val = 0; \
@@ -379,16 +486,51 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
        REG_READ_HEADER(x); \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                if (dev_priv->uncore.forcewake_count == 0) \
-                       dev_priv->uncore.funcs.force_wake_get(dev_priv); \
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv, \
+                                                       FORCEWAKE_ALL); \
                val = __raw_i915_read##x(dev_priv, reg); \
                if (dev_priv->uncore.forcewake_count == 0) \
-                       dev_priv->uncore.funcs.force_wake_put(dev_priv); \
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } else { \
                val = __raw_i915_read##x(dev_priv, reg); \
        } \
        REG_READ_FOOTER; \
 }
 
+#define __vlv_read(x) \
+static u##x \
+vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+       unsigned fwengine = 0; \
+       unsigned *fwcount; \
+       REG_READ_HEADER(x); \
+       if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) {   \
+               fwengine = FORCEWAKE_RENDER;            \
+               fwcount = &dev_priv->uncore.fw_rendercount;    \
+       }                                               \
+       else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) {       \
+               fwengine = FORCEWAKE_MEDIA;             \
+               fwcount = &dev_priv->uncore.fw_mediacount;     \
+       }  \
+       if (fwengine != 0) {            \
+               if ((*fwcount)++ == 0) \
+                       (dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+                                                               fwengine); \
+               val = __raw_i915_read##x(dev_priv, reg); \
+               if (--(*fwcount) == 0) \
+                       (dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+                                                       fwengine); \
+       } else { \
+               val = __raw_i915_read##x(dev_priv, reg); \
+       } \
+       REG_READ_FOOTER; \
+}
+
+
+__vlv_read(8)
+__vlv_read(16)
+__vlv_read(32)
+__vlv_read(64)
 __gen6_read(8)
 __gen6_read(16)
 __gen6_read(32)
@@ -402,6 +544,7 @@ __gen4_read(16)
 __gen4_read(32)
 __gen4_read(64)
 
+#undef __vlv_read
 #undef __gen6_read
 #undef __gen5_read
 #undef __gen4_read
@@ -413,12 +556,15 @@ __gen4_read(64)
        trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
+#define REG_WRITE_FOOTER \
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags)
+
 #define __gen4_write(x) \
 static void \
 gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
        REG_WRITE_HEADER; \
        __raw_i915_write##x(dev_priv, reg, val); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __gen5_write(x) \
@@ -427,7 +573,7 @@ gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
        REG_WRITE_HEADER; \
        ilk_dummy_write(dev_priv); \
        __raw_i915_write##x(dev_priv, reg, val); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __gen6_write(x) \
@@ -438,11 +584,12 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
+       assert_device_not_suspended(dev_priv); \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (unlikely(__fifo_ret)) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __hsw_write(x) \
@@ -453,13 +600,14 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
+       assert_device_not_suspended(dev_priv); \
        hsw_unclaimed_reg_clear(dev_priv, reg); \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (unlikely(__fifo_ret)) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
        hsw_unclaimed_reg_check(dev_priv, reg); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 static const u32 gen8_shadowed_regs[] = {
@@ -486,16 +634,18 @@ static bool is_gen8_shadowed(struct drm_i915_private *dev_priv, u32 reg)
 #define __gen8_write(x) \
 static void \
 gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
-       bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \
+       bool __needs_put = reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg); \
        REG_WRITE_HEADER; \
        if (__needs_put) { \
-               dev_priv->uncore.funcs.force_wake_get(dev_priv); \
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (__needs_put) { \
-               dev_priv->uncore.funcs.force_wake_put(dev_priv); \
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 __gen8_write(8)
@@ -524,6 +674,7 @@ __gen4_write(64)
 #undef __gen6_write
 #undef __gen5_write
 #undef __gen4_write
+#undef REG_WRITE_FOOTER
 #undef REG_WRITE_HEADER
 
 void intel_uncore_init(struct drm_device *dev)
@@ -534,8 +685,8 @@ void intel_uncore_init(struct drm_device *dev)
                          gen6_force_wake_work);
 
        if (IS_VALLEYVIEW(dev)) {
-               dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get;
-               dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put;
+               dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
+               dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put;
        } else if (IS_HASWELL(dev) || IS_GEN8(dev)) {
                dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get;
                dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put;
@@ -552,9 +703,9 @@ void intel_uncore_init(struct drm_device *dev)
                 * forcewake being disabled.
                 */
                mutex_lock(&dev->struct_mutex);
-               __gen6_gt_force_wake_mt_get(dev_priv);
+               __gen6_gt_force_wake_mt_get(dev_priv, FORCEWAKE_ALL);
                ecobus = __raw_i915_read32(dev_priv, ECOBUS);
-               __gen6_gt_force_wake_mt_put(dev_priv);
+               __gen6_gt_force_wake_mt_put(dev_priv, FORCEWAKE_ALL);
                mutex_unlock(&dev->struct_mutex);
 
                if (ecobus & FORCEWAKE_MT_ENABLE) {
@@ -601,10 +752,18 @@ void intel_uncore_init(struct drm_device *dev)
                        dev_priv->uncore.funcs.mmio_writel  = gen6_write32;
                        dev_priv->uncore.funcs.mmio_writeq  = gen6_write64;
                }
-               dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
-               dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
-               dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
-               dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+
+               if (IS_VALLEYVIEW(dev)) {
+                       dev_priv->uncore.funcs.mmio_readb  = vlv_read8;
+                       dev_priv->uncore.funcs.mmio_readw  = vlv_read16;
+                       dev_priv->uncore.funcs.mmio_readl  = vlv_read32;
+                       dev_priv->uncore.funcs.mmio_readq  = vlv_read64;
+               } else {
+                       dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
+                       dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
+                       dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
+                       dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+               }
                break;
        case 5:
                dev_priv->uncore.funcs.mmio_writeb  = gen5_write8;
@@ -646,7 +805,7 @@ static const struct register_whitelist {
        uint32_t size;
        uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
 } whitelist[] = {
-       { RING_TIMESTAMP(RENDER_RING_BASE), 8, 0xF0 },
+       { RING_TIMESTAMP(RENDER_RING_BASE), 8, 0x1F0 },
 };
 
 int i915_reg_read_ioctl(struct drm_device *dev,
@@ -687,6 +846,43 @@ int i915_reg_read_ioctl(struct drm_device *dev,
        return 0;
 }
 
+int i915_get_reset_stats_ioctl(struct drm_device *dev,
+                              void *data, struct drm_file *file)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_reset_stats *args = data;
+       struct i915_ctx_hang_stats *hs;
+       int ret;
+
+       if (args->flags || args->pad)
+               return -EINVAL;
+
+       if (args->ctx_id == DEFAULT_CONTEXT_ID && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       hs = i915_gem_context_get_hang_stats(dev, file, args->ctx_id);
+       if (IS_ERR(hs)) {
+               mutex_unlock(&dev->struct_mutex);
+               return PTR_ERR(hs);
+       }
+
+       if (capable(CAP_SYS_ADMIN))
+               args->reset_count = i915_reset_count(&dev_priv->gpu_error);
+       else
+               args->reset_count = 0;
+
+       args->batch_active = hs->batch_active;
+       args->batch_pending = hs->batch_pending;
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
 static int i965_reset_complete(struct drm_device *dev)
 {
        u8 gdrst;
@@ -770,12 +966,12 @@ static int gen6_do_reset(struct drm_device *dev)
 
        /* If reset with a user forcewake, try to restore, otherwise turn it off */
        if (dev_priv->uncore.forcewake_count)
-               dev_priv->uncore.funcs.force_wake_get(dev_priv);
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
        else
-               dev_priv->uncore.funcs.force_wake_put(dev_priv);
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
 
        /* Restore fifo count */
-       dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+       dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
        return ret;
@@ -784,6 +980,7 @@ static int gen6_do_reset(struct drm_device *dev)
 int intel_gpu_reset(struct drm_device *dev)
 {
        switch (INTEL_INFO(dev)->gen) {
+       case 8:
        case 7:
        case 6: return gen6_do_reset(dev);
        case 5: return ironlake_do_reset(dev);
@@ -792,15 +989,6 @@ int intel_gpu_reset(struct drm_device *dev)
        }
 }
 
-void intel_uncore_clear_errors(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       /* XXX needs spinlock around caller's grouping */
-       if (HAS_FPGA_DBG_UNCLAIMED(dev))
-               __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
-}
-
 void intel_uncore_check_errors(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
index 087db33f6cff19f8cdaa32f390c6c4dd52a8c79d..c3bf059ba720569540145f225222e0f2b444827c 100644 (file)
@@ -1075,10 +1075,10 @@ static int mga_dma_get_buffers(struct drm_device *dev,
 
                buf->file_priv = file_priv;
 
-               if (DRM_COPY_TO_USER(&d->request_indices[i],
+               if (copy_to_user(&d->request_indices[i],
                                     &buf->idx, sizeof(buf->idx)))
                        return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i],
+               if (copy_to_user(&d->request_sizes[i],
                                     &buf->total, sizeof(buf->total)))
                        return -EFAULT;
 
index ca4bc54ea2146303f4cedf7bdd879b3c3bc812fd..fe453213600ab728e57385e40b272e4e8b8ebc49 100644 (file)
@@ -186,14 +186,14 @@ extern void mga_disable_vblank(struct drm_device *dev, int crtc);
 extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence);
 extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t mga_driver_irq_handler(int irq, void *arg);
 extern void mga_driver_irq_preinstall(struct drm_device *dev);
 extern int mga_driver_irq_postinstall(struct drm_device *dev);
 extern void mga_driver_irq_uninstall(struct drm_device *dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
                             unsigned long arg);
 
-#define mga_flush_write_combine()      DRM_WRITEMEMORYBARRIER()
+#define mga_flush_write_combine()      wmb()
 
 #define MGA_READ8(reg)         DRM_READ8(dev_priv->mmio, (reg))
 #define MGA_READ(reg)          DRM_READ32(dev_priv->mmio, (reg))
index 709e90db8c4087dfcb782a51deab776271a7feb0..86b4bb80485200e1067c47574117fa1c46c17b8f 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <drm/drmP.h>
 #include <drm/mga_drm.h>
+#include "mga_drv.h"
 
 typedef struct drm32_mga_init {
        int func;
index 2b0ceb8dc11b8dce6894cf056998714603087a3d..1b071b8ff9dccec81e1d93376d0b6b09bc58521b 100644 (file)
@@ -47,7 +47,7 @@ u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
 }
 
 
-irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t mga_driver_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
@@ -79,7 +79,7 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
                        MGA_WRITE(MGA_PRIMEND, prim_end);
 
                atomic_inc(&dev_priv->last_fence_retired);
-               DRM_WAKEUP(&dev_priv->fence_queue);
+               wake_up(&dev_priv->fence_queue);
                handled = 1;
        }
 
@@ -128,7 +128,7 @@ int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence)
         * by about a day rather than she wants to wait for years
         * using fences.
         */
-       DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
+       DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * HZ,
                    (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
                      - *sequence) <= (1 << 23)));
 
@@ -151,7 +151,7 @@ int mga_driver_irq_postinstall(struct drm_device *dev)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
-       DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
+       init_waitqueue_head(&dev_priv->fence_queue);
 
        /* Turn on soft trap interrupt.  Vertical blank interrupts are enabled
         * in mga_enable_vblank.
index 37cc2fb4eadd9a033316f5951eddc81f8fb072e0..314685b7f41fc4acb21a2c9c0cad86ecbd1ccad2 100644 (file)
@@ -1029,7 +1029,7 @@ static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *fil
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+       if (copy_to_user(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
index 801731aeab61cddf3db56419dea57f5240ed5994..9f9780b7ddf0be7d3a82ba77205d21d29984b02f 100644 (file)
@@ -22,8 +22,10 @@ static void mga_hide_cursor(struct mga_device *mdev)
 {
        WREG8(MGA_CURPOSXL, 0);
        WREG8(MGA_CURPOSXH, 0);
-       mgag200_bo_unpin(mdev->cursor.pixels_1);
-       mgag200_bo_unpin(mdev->cursor.pixels_2);
+       if (mdev->cursor.pixels_1->pin_count)
+               mgag200_bo_unpin(mdev->cursor.pixels_1);
+       if (mdev->cursor.pixels_2->pin_count)
+               mgag200_bo_unpin(mdev->cursor.pixels_2);
 }
 
 int mga_crtc_cursor_set(struct drm_crtc *crtc,
@@ -32,7 +34,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
                        uint32_t width,
                        uint32_t height)
 {
-       struct drm_device *dev = (struct drm_device *)file_priv->minor->dev;
+       struct drm_device *dev = crtc->dev;
        struct mga_device *mdev = (struct mga_device *)dev->dev_private;
        struct mgag200_bo *pixels_1 = mdev->cursor.pixels_1;
        struct mgag200_bo *pixels_2 = mdev->cursor.pixels_2;
index 964f58cee5ea67b37f02e680b0f1ab7ebb3e5ed3..f9adc27ef32a05fdee5b66a23e35b7e6df21fd3d 100644 (file)
@@ -41,7 +41,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,
         * then the BO is being moved and we should
         * store up the damage until later.
         */
-       if (!in_interrupt())
+       if (!drm_can_sleep())
                ret = mgag200_bo_reserve(bo, true);
        if (ret) {
                if (ret != -EBUSY)
@@ -282,6 +282,11 @@ int mgag200_fbdev_init(struct mga_device *mdev)
 {
        struct mga_fbdev *mfbdev;
        int ret;
+       int bpp_sel = 32;
+
+       /* prefer 16bpp on low end gpus with limited VRAM */
+       if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
+               bpp_sel = 16;
 
        mfbdev = devm_kzalloc(mdev->dev->dev, sizeof(struct mga_fbdev), GFP_KERNEL);
        if (!mfbdev)
@@ -301,7 +306,7 @@ int mgag200_fbdev_init(struct mga_device *mdev)
        /* disable all the possible outputs/crtcs before entering KMS mode */
        drm_helper_disable_unused_functions(mdev->dev);
 
-       drm_fb_helper_initial_config(&mfbdev->helper, 32);
+       drm_fb_helper_initial_config(&mfbdev->helper, bpp_sel);
 
        return 0;
 }
index b1120cb1db6d76b76fd38afd3279a3684e6b188b..26868e5c55b076352188d34962b928a87a64d1a9 100644 (file)
@@ -217,7 +217,10 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
 
        drm_mode_config_init(dev);
        dev->mode_config.funcs = (void *)&mga_mode_funcs;
-       dev->mode_config.preferred_depth = 24;
+       if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024))
+               dev->mode_config.preferred_depth = 16;
+       else
+               dev->mode_config.preferred_depth = 24;
        dev->mode_config.prefer_shadow = 1;
 
        r = mgag200_modeset_init(mdev);
@@ -310,7 +313,7 @@ int mgag200_dumb_create(struct drm_file *file,
        return 0;
 }
 
-void mgag200_bo_unref(struct mgag200_bo **bo)
+static void mgag200_bo_unref(struct mgag200_bo **bo)
 {
        struct ttm_buffer_object *tbo;
 
index ee6ed633b7b1c1bb34ac6b59ec85db52c69a4f27..b8583f275e80519dd46d922d1f5c1a0ed9c8bcbf 100644 (file)
@@ -691,7 +691,7 @@ static void mga_g200wb_commit(struct drm_crtc *crtc)
    CRTCEXT0 has to be programmed last to trigger an update and make the
    new addr variable take effect.
  */
-void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
+static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
 {
        struct mga_device *mdev = crtc->dev->dev_private;
        u32 addr;
@@ -1398,7 +1398,7 @@ static void mga_encoder_commit(struct drm_encoder *encoder)
 {
 }
 
-void mga_encoder_destroy(struct drm_encoder *encoder)
+static void mga_encoder_destroy(struct drm_encoder *encoder)
 {
        struct mga_encoder *mga_encoder = to_mga_encoder(encoder);
        drm_encoder_cleanup(encoder);
@@ -1558,7 +1558,7 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-struct drm_encoder *mga_connector_best_encoder(struct drm_connector
+static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
                                                  *connector)
 {
        int enc_id = connector->encoder_ids[0];
index 07b192fe15c6c6f9d0c23434280972616693ca48..adb5166a5dfdbe3a77e4e7154411e5162df1abd3 100644 (file)
@@ -80,7 +80,7 @@ static int mgag200_ttm_global_init(struct mga_device *ast)
        return 0;
 }
 
-void
+static void
 mgag200_ttm_global_release(struct mga_device *ast)
 {
        if (ast->ttm.mem_global_ref.release == NULL)
@@ -102,7 +102,7 @@ static void mgag200_bo_ttm_destroy(struct ttm_buffer_object *tbo)
        kfree(bo);
 }
 
-bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo)
+static bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo)
 {
        if (bo->destroy == &mgag200_bo_ttm_destroy)
                return true;
@@ -208,7 +208,7 @@ static struct ttm_backend_func mgag200_tt_backend_func = {
 };
 
 
-struct ttm_tt *mgag200_ttm_tt_create(struct ttm_bo_device *bdev,
+static struct ttm_tt *mgag200_ttm_tt_create(struct ttm_bo_device *bdev,
                                 unsigned long size, uint32_t page_flags,
                                 struct page *dummy_read_page)
 {
index f39ab7554fc992175630831acf28bbf223cd9f50..bb103fb4519ead8c9c1e698a341d50273fc5da94 100644 (file)
@@ -2,8 +2,7 @@
 config DRM_MSM
        tristate "MSM DRM"
        depends on DRM
-       depends on ARCH_MSM
-       depends on ARCH_MSM8960
+       depends on (ARCH_MSM && ARCH_MSM8960) || (ARM && COMPILE_TEST)
        select DRM_KMS_HELPER
        select SHMEM
        select TMPFS
index e5fa12b0d21eca645a2cc5efa8f74bef595ad2bb..4f977a593bea13334aebca905c87be43223b2e06 100644 (file)
@@ -12,18 +12,27 @@ msm-y := \
        hdmi/hdmi_i2c.o \
        hdmi/hdmi_phy_8960.o \
        hdmi/hdmi_phy_8x60.o \
-       mdp4/mdp4_crtc.o \
-       mdp4/mdp4_dtv_encoder.o \
-       mdp4/mdp4_format.o \
-       mdp4/mdp4_irq.o \
-       mdp4/mdp4_kms.o \
-       mdp4/mdp4_plane.o \
+       hdmi/hdmi_phy_8x74.o \
+       mdp/mdp_format.o \
+       mdp/mdp_kms.o \
+       mdp/mdp4/mdp4_crtc.o \
+       mdp/mdp4/mdp4_dtv_encoder.o \
+       mdp/mdp4/mdp4_irq.o \
+       mdp/mdp4/mdp4_kms.o \
+       mdp/mdp4/mdp4_plane.o \
+       mdp/mdp5/mdp5_crtc.o \
+       mdp/mdp5/mdp5_encoder.o \
+       mdp/mdp5/mdp5_irq.o \
+       mdp/mdp5/mdp5_kms.o \
+       mdp/mdp5/mdp5_plane.o \
+       mdp/mdp5/mdp5_smp.o \
        msm_drv.o \
        msm_fb.o \
        msm_gem.o \
        msm_gem_prime.o \
        msm_gem_submit.o \
        msm_gpu.o \
+       msm_iommu.o \
        msm_ringbuffer.o
 
 msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
index e036f6c1db9447180ddca1a518174ec692d94738..9c4255b980218c229ae5f40a7c89c8445435d43a 100644 (file)
@@ -4,7 +4,7 @@ In the current snapdragon SoC's, we have (at least) 3 different
 display controller blocks at play:
  + MDP3 - ?? seems to be what is on geeksphone peak device
  + MDP4 - S3 (APQ8060, touchpad), S4-pro (APQ8064, nexus4 & ifc6410)
- + MDSS - snapdragon 800
+ + MDP5 - snapdragon 800
 
 (I don't have a completely clear picture on which display controller
 maps to which part #)
@@ -46,6 +46,24 @@ and treat the MDP4 block's irq as "the" irq.  Even though the connectors
 may have their own irqs which they install themselves.  For this reason
 the display controller is the "master" device.
 
+For MDP5, the mapping is:
+
+  plane   -> PIPE{RGBn,VIGn}             \
+  crtc    -> LM (layer mixer)            |-> MDP "device"
+  encoder -> INTF                        /
+  connector -> HDMI/DSI/eDP/etc          --> other device(s)
+
+Unlike MDP4, it appears we can get by with a single encoder, rather
+than needing a different implementation for DTV, DSI, etc.  (Ie. the
+register interface is same, just different bases.)
+
+Also unlike MDP4, with MDP5 all the IRQs for other blocks (HDMI, DSI,
+etc) are routed through MDP.
+
+And finally, MDP5 has this "Shared Memory Pool" (called "SMP"), from
+which blocks need to be allocated to the active pipes based on fetch
+stride.
+
 Each connector probably ends up being a separate device, just for the
 logistics of finding/mapping io region, irq, etc.  Idealy we would
 have a better way than just stashing the platform device in a global
index 9588098741b5b7f76e379d715eb358bfa78d92f0..85d615e7d62fb75789a127fcc021c111a0baa74e 100644 (file)
@@ -8,12 +8,13 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml              (    327 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/a2xx/a2xx.xml           (  31003 bytes, from 2013-09-19 18:50:16)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_common.xml       (   8983 bytes, from 2013-07-24 01:38:36)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_pm4.xml          (   9759 bytes, from 2013-09-10 00:52:33)
-- /home/robclark/src/freedreno/envytools/rnndb/a3xx/a3xx.xml           (  51983 bytes, from 2013-09-10 00:52:32)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -202,6 +203,12 @@ enum a2xx_rb_copy_sample_select {
        SAMPLE_0123 = 6,
 };
 
+enum adreno_mmu_clnt_beh {
+       BEH_NEVR = 0,
+       BEH_TRAN_RNG = 1,
+       BEH_TRAN_FLT = 2,
+};
+
 enum sq_tex_clamp {
        SQ_TEX_WRAP = 0,
        SQ_TEX_MIRROR = 1,
@@ -238,6 +245,92 @@ enum sq_tex_filter {
 
 #define REG_A2XX_CP_PFP_UCODE_DATA                             0x000000c1
 
+#define REG_A2XX_MH_MMU_CONFIG                                 0x00000040
+#define A2XX_MH_MMU_CONFIG_MMU_ENABLE                          0x00000001
+#define A2XX_MH_MMU_CONFIG_SPLIT_MODE_ENABLE                   0x00000002
+#define A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK            0x00000030
+#define A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT           4
+static inline uint32_t A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK            0x000000c0
+#define A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT           6
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK           0x00000300
+#define A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT          8
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK           0x00000c00
+#define A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT          10
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK           0x00003000
+#define A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT          12
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK           0x0000c000
+#define A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT          14
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK           0x00030000
+#define A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT          16
+static inline uint32_t A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK          0x000c0000
+#define A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT         18
+static inline uint32_t A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK          0x00300000
+#define A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT         20
+static inline uint32_t A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK            0x00c00000
+#define A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT           22
+static inline uint32_t A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK;
+}
+#define A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK            0x03000000
+#define A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT           24
+static inline uint32_t A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
+{
+       return ((val) << A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT) & A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK;
+}
+
+#define REG_A2XX_MH_MMU_VA_RANGE                               0x00000041
+
+#define REG_A2XX_MH_MMU_PT_BASE                                        0x00000042
+
+#define REG_A2XX_MH_MMU_PAGE_FAULT                             0x00000043
+
+#define REG_A2XX_MH_MMU_TRAN_ERROR                             0x00000044
+
+#define REG_A2XX_MH_MMU_INVALIDATE                             0x00000045
+
+#define REG_A2XX_MH_MMU_MPU_BASE                               0x00000046
+
+#define REG_A2XX_MH_MMU_MPU_END                                        0x00000047
+
+#define REG_A2XX_NQWAIT_UNTIL                                  0x00000394
+
 #define REG_A2XX_RBBM_PERFCOUNTER1_SELECT                      0x00000395
 
 #define REG_A2XX_RBBM_PERFCOUNTER1_LO                          0x00000397
@@ -276,20 +369,6 @@ enum sq_tex_filter {
 
 #define REG_A2XX_CP_PERFCOUNTER_HI                             0x00000447
 
-#define REG_A2XX_CP_ST_BASE                                    0x0000044d
-
-#define REG_A2XX_CP_ST_BUFSZ                                   0x0000044e
-
-#define REG_A2XX_CP_IB1_BASE                                   0x00000458
-
-#define REG_A2XX_CP_IB1_BUFSZ                                  0x00000459
-
-#define REG_A2XX_CP_IB2_BASE                                   0x0000045a
-
-#define REG_A2XX_CP_IB2_BUFSZ                                  0x0000045b
-
-#define REG_A2XX_CP_STAT                                       0x0000047f
-
 #define REG_A2XX_RBBM_STATUS                                   0x000005d0
 #define A2XX_RBBM_STATUS_CMDFIFO_AVAIL__MASK                   0x0000001f
 #define A2XX_RBBM_STATUS_CMDFIFO_AVAIL__SHIFT                  0
@@ -808,6 +887,12 @@ static inline uint32_t A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS(uint32_t val)
 
 #define REG_A2XX_SQ_VS_PROGRAM                                 0x000021f7
 
+#define REG_A2XX_VGT_EVENT_INITIATOR                           0x000021f9
+
+#define REG_A2XX_VGT_DRAW_INITIATOR                            0x000021fc
+
+#define REG_A2XX_VGT_IMMED_DATA                                        0x000021fd
+
 #define REG_A2XX_RB_DEPTHCONTROL                               0x00002200
 #define A2XX_RB_DEPTHCONTROL_STENCIL_ENABLE                    0x00000001
 #define A2XX_RB_DEPTHCONTROL_Z_ENABLE                          0x00000002
index d4afdf6575597f0dd4d06ed2eac5fc09b2cad076..a7be56163d2324f4a24ae7e4836168f95db967a2 100644 (file)
@@ -8,12 +8,13 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml              (    327 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/a2xx/a2xx.xml           (  31003 bytes, from 2013-09-19 18:50:16)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_common.xml       (   8983 bytes, from 2013-07-24 01:38:36)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_pm4.xml          (   9759 bytes, from 2013-09-10 00:52:33)
-- /home/robclark/src/freedreno/envytools/rnndb/a3xx/a3xx.xml           (  51983 bytes, from 2013-09-10 00:52:32)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -292,6 +293,8 @@ enum a3xx_tex_type {
 #define A3XX_RBBM_STATUS_GPU_BUSY_NOHC                         0x40000000
 #define A3XX_RBBM_STATUS_GPU_BUSY                              0x80000000
 
+#define REG_A3XX_RBBM_NQWAIT_UNTIL                             0x00000040
+
 #define REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL                     0x00000033
 
 #define REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL                   0x00000050
@@ -304,6 +307,8 @@ enum a3xx_tex_type {
 
 #define REG_A3XX_RBBM_INTERFACE_HANG_MASK_CTL3                 0x0000005a
 
+#define REG_A3XX_RBBM_INT_SET_CMD                              0x00000060
+
 #define REG_A3XX_RBBM_INT_CLEAR_CMD                            0x00000061
 
 #define REG_A3XX_RBBM_INT_0_MASK                               0x00000063
@@ -937,13 +942,13 @@ static inline uint32_t A3XX_RB_BLEND_ALPHA_FLOAT(float val)
        return ((util_float_to_half(val)) << A3XX_RB_BLEND_ALPHA_FLOAT__SHIFT) & A3XX_RB_BLEND_ALPHA_FLOAT__MASK;
 }
 
-#define REG_A3XX_UNKNOWN_20E8                                  0x000020e8
+#define REG_A3XX_RB_CLEAR_COLOR_DW0                            0x000020e8
 
-#define REG_A3XX_UNKNOWN_20E9                                  0x000020e9
+#define REG_A3XX_RB_CLEAR_COLOR_DW1                            0x000020e9
 
-#define REG_A3XX_UNKNOWN_20EA                                  0x000020ea
+#define REG_A3XX_RB_CLEAR_COLOR_DW2                            0x000020ea
 
-#define REG_A3XX_UNKNOWN_20EB                                  0x000020eb
+#define REG_A3XX_RB_CLEAR_COLOR_DW3                            0x000020eb
 
 #define REG_A3XX_RB_COPY_CONTROL                               0x000020ec
 #define A3XX_RB_COPY_CONTROL_MSAA_RESOLVE__MASK                        0x00000003
@@ -1026,7 +1031,7 @@ static inline uint32_t A3XX_RB_DEPTH_CONTROL_ZFUNC(enum adreno_compare_func val)
 #define A3XX_RB_DEPTH_CONTROL_BF_ENABLE                                0x00000080
 #define A3XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE                    0x80000000
 
-#define REG_A3XX_UNKNOWN_2101                                  0x00002101
+#define REG_A3XX_RB_DEPTH_CLEAR                                        0x00002101
 
 #define REG_A3XX_RB_DEPTH_INFO                                 0x00002102
 #define A3XX_RB_DEPTH_INFO_DEPTH_FORMAT__MASK                  0x00000001
@@ -1103,11 +1108,11 @@ static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op v
        return ((val) << A3XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT) & A3XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK;
 }
 
-#define REG_A3XX_UNKNOWN_2105                                  0x00002105
+#define REG_A3XX_RB_STENCIL_CLEAR                              0x00002105
 
-#define REG_A3XX_UNKNOWN_2106                                  0x00002106
+#define REG_A3XX_RB_STENCIL_BUF_INFO                           0x00002106
 
-#define REG_A3XX_UNKNOWN_2107                                  0x00002107
+#define REG_A3XX_RB_STENCIL_BUF_PITCH                          0x00002107
 
 #define REG_A3XX_RB_STENCILREFMASK                             0x00002108
 #define A3XX_RB_STENCILREFMASK_STENCILREF__MASK                        0x000000ff
@@ -1149,20 +1154,31 @@ static inline uint32_t A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(uint32_t val)
        return ((val) << A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__SHIFT) & A3XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK__MASK;
 }
 
-#define REG_A3XX_PA_SC_WINDOW_OFFSET                           0x0000210e
-#define A3XX_PA_SC_WINDOW_OFFSET_X__MASK                       0x0000ffff
-#define A3XX_PA_SC_WINDOW_OFFSET_X__SHIFT                      0
-static inline uint32_t A3XX_PA_SC_WINDOW_OFFSET_X(uint32_t val)
+#define REG_A3XX_RB_LRZ_VSC_CONTROL                            0x0000210c
+#define A3XX_RB_LRZ_VSC_CONTROL_BINNING_ENABLE                 0x00000002
+
+#define REG_A3XX_RB_WINDOW_OFFSET                              0x0000210e
+#define A3XX_RB_WINDOW_OFFSET_X__MASK                          0x0000ffff
+#define A3XX_RB_WINDOW_OFFSET_X__SHIFT                         0
+static inline uint32_t A3XX_RB_WINDOW_OFFSET_X(uint32_t val)
 {
-       return ((val) << A3XX_PA_SC_WINDOW_OFFSET_X__SHIFT) & A3XX_PA_SC_WINDOW_OFFSET_X__MASK;
+       return ((val) << A3XX_RB_WINDOW_OFFSET_X__SHIFT) & A3XX_RB_WINDOW_OFFSET_X__MASK;
 }
-#define A3XX_PA_SC_WINDOW_OFFSET_Y__MASK                       0xffff0000
-#define A3XX_PA_SC_WINDOW_OFFSET_Y__SHIFT                      16
-static inline uint32_t A3XX_PA_SC_WINDOW_OFFSET_Y(uint32_t val)
+#define A3XX_RB_WINDOW_OFFSET_Y__MASK                          0xffff0000
+#define A3XX_RB_WINDOW_OFFSET_Y__SHIFT                         16
+static inline uint32_t A3XX_RB_WINDOW_OFFSET_Y(uint32_t val)
 {
-       return ((val) << A3XX_PA_SC_WINDOW_OFFSET_Y__SHIFT) & A3XX_PA_SC_WINDOW_OFFSET_Y__MASK;
+       return ((val) << A3XX_RB_WINDOW_OFFSET_Y__SHIFT) & A3XX_RB_WINDOW_OFFSET_Y__MASK;
 }
 
+#define REG_A3XX_RB_SAMPLE_COUNT_CONTROL                       0x00002110
+
+#define REG_A3XX_RB_SAMPLE_COUNT_ADDR                          0x00002111
+
+#define REG_A3XX_RB_Z_CLAMP_MIN                                        0x00002114
+
+#define REG_A3XX_RB_Z_CLAMP_MAX                                        0x00002115
+
 #define REG_A3XX_PC_VSTREAM_CONTROL                            0x000021e4
 
 #define REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL                    0x000021ea
@@ -1309,6 +1325,8 @@ static inline uint32_t A3XX_HLSQ_CONST_FSPRESV_RANGE_REG_ENDENTRY(uint32_t val)
 
 #define REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG                    0x00002215
 
+#define REG_A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG                    0x00002216
+
 #define REG_A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG                    0x00002217
 
 #define REG_A3XX_HLSQ_CL_WG_OFFSET_REG                         0x0000221a
@@ -1491,12 +1509,13 @@ static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0
 
 #define REG_A3XX_SP_SP_CTRL_REG                                        0x000022c0
 #define A3XX_SP_SP_CTRL_REG_RESOLVE                            0x00010000
-#define A3XX_SP_SP_CTRL_REG_CONSTMODE__MASK                    0x000c0000
+#define A3XX_SP_SP_CTRL_REG_CONSTMODE__MASK                    0x00040000
 #define A3XX_SP_SP_CTRL_REG_CONSTMODE__SHIFT                   18
 static inline uint32_t A3XX_SP_SP_CTRL_REG_CONSTMODE(uint32_t val)
 {
        return ((val) << A3XX_SP_SP_CTRL_REG_CONSTMODE__SHIFT) & A3XX_SP_SP_CTRL_REG_CONSTMODE__MASK;
 }
+#define A3XX_SP_SP_CTRL_REG_BINNING                            0x00080000
 #define A3XX_SP_SP_CTRL_REG_SLEEPMODE__MASK                    0x00300000
 #define A3XX_SP_SP_CTRL_REG_SLEEPMODE__SHIFT                   20
 static inline uint32_t A3XX_SP_SP_CTRL_REG_SLEEPMODE(uint32_t val)
@@ -1669,7 +1688,7 @@ static inline uint32_t A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 
 #define REG_A3XX_SP_VS_OBJ_START_REG                           0x000022d5
 
-#define REG_A3XX_SP_VS_PVT_MEM_CTRL_REG                                0x000022d6
+#define REG_A3XX_SP_VS_PVT_MEM_PARAM_REG                       0x000022d6
 
 #define REG_A3XX_SP_VS_PVT_MEM_ADDR_REG                                0x000022d7
 
@@ -1772,7 +1791,7 @@ static inline uint32_t A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
 
 #define REG_A3XX_SP_FS_OBJ_START_REG                           0x000022e3
 
-#define REG_A3XX_SP_FS_PVT_MEM_CTRL_REG                                0x000022e4
+#define REG_A3XX_SP_FS_PVT_MEM_PARAM_REG                       0x000022e4
 
 #define REG_A3XX_SP_FS_PVT_MEM_ADDR_REG                                0x000022e5
 
@@ -1943,6 +1962,9 @@ static inline uint32_t REG_A3XX_VSC_PIPE_DATA_ADDRESS(uint32_t i0) { return 0x00
 
 static inline uint32_t REG_A3XX_VSC_PIPE_DATA_LENGTH(uint32_t i0) { return 0x00000c08 + 0x3*i0; }
 
+#define REG_A3XX_VSC_BIN_CONTROL                               0x00000c3c
+#define A3XX_VSC_BIN_CONTROL_BINNING_ENABLE                    0x00000001
+
 #define REG_A3XX_UNKNOWN_0C3D                                  0x00000c3d
 
 #define REG_A3XX_PC_PERFCOUNTER0_SELECT                                0x00000c48
@@ -1953,7 +1975,7 @@ static inline uint32_t REG_A3XX_VSC_PIPE_DATA_LENGTH(uint32_t i0) { return 0x000
 
 #define REG_A3XX_PC_PERFCOUNTER3_SELECT                                0x00000c4b
 
-#define REG_A3XX_UNKNOWN_0C81                                  0x00000c81
+#define REG_A3XX_GRAS_TSE_DEBUG_ECO                            0x00000c81
 
 #define REG_A3XX_GRAS_PERFCOUNTER0_SELECT                      0x00000c88
 
@@ -1975,22 +1997,24 @@ static inline uint32_t REG_A3XX_GRAS_CL_USER_PLANE_W(uint32_t i0) { return 0x000
 
 #define REG_A3XX_RB_GMEM_BASE_ADDR                             0x00000cc0
 
+#define REG_A3XX_RB_DEBUG_ECO_CONTROLS_ADDR                    0x00000cc1
+
 #define REG_A3XX_RB_PERFCOUNTER0_SELECT                                0x00000cc6
 
 #define REG_A3XX_RB_PERFCOUNTER1_SELECT                                0x00000cc7
 
-#define REG_A3XX_RB_WINDOW_SIZE                                        0x00000ce0
-#define A3XX_RB_WINDOW_SIZE_WIDTH__MASK                                0x00003fff
-#define A3XX_RB_WINDOW_SIZE_WIDTH__SHIFT                       0
-static inline uint32_t A3XX_RB_WINDOW_SIZE_WIDTH(uint32_t val)
+#define REG_A3XX_RB_FRAME_BUFFER_DIMENSION                     0x00000ce0
+#define A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__MASK             0x00003fff
+#define A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__SHIFT            0
+static inline uint32_t A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(uint32_t val)
 {
-       return ((val) << A3XX_RB_WINDOW_SIZE_WIDTH__SHIFT) & A3XX_RB_WINDOW_SIZE_WIDTH__MASK;
+       return ((val) << A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__SHIFT) & A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH__MASK;
 }
-#define A3XX_RB_WINDOW_SIZE_HEIGHT__MASK                       0x0fffc000
-#define A3XX_RB_WINDOW_SIZE_HEIGHT__SHIFT                      14
-static inline uint32_t A3XX_RB_WINDOW_SIZE_HEIGHT(uint32_t val)
+#define A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__MASK            0x0fffc000
+#define A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__SHIFT           14
+static inline uint32_t A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT(uint32_t val)
 {
-       return ((val) << A3XX_RB_WINDOW_SIZE_HEIGHT__SHIFT) & A3XX_RB_WINDOW_SIZE_HEIGHT__MASK;
+       return ((val) << A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__SHIFT) & A3XX_RB_FRAME_BUFFER_DIMENSION_HEIGHT__MASK;
 }
 
 #define REG_A3XX_HLSQ_PERFCOUNTER0_SELECT                      0x00000e00
@@ -2088,6 +2112,14 @@ static inline uint32_t A3XX_UCHE_CACHE_INVALIDATE1_REG_OPCODE(enum a3xx_cache_op
 
 #define REG_A3XX_TP_PERFCOUNTER5_SELECT                                0x00000f09
 
+#define REG_A3XX_VGT_CL_INITIATOR                              0x000021f0
+
+#define REG_A3XX_VGT_EVENT_INITIATOR                           0x000021f9
+
+#define REG_A3XX_VGT_DRAW_INITIATOR                            0x000021fc
+
+#define REG_A3XX_VGT_IMMED_DATA                                        0x000021fd
+
 #define REG_A3XX_TEX_SAMP_0                                    0x00000000
 #define A3XX_TEX_SAMP_0_MIPFILTER_LINEAR                       0x00000002
 #define A3XX_TEX_SAMP_0_XY_MAG__MASK                           0x0000000c
@@ -2123,6 +2155,18 @@ static inline uint32_t A3XX_TEX_SAMP_0_WRAP_R(enum a3xx_tex_clamp val)
 #define A3XX_TEX_SAMP_0_UNNORM_COORDS                          0x80000000
 
 #define REG_A3XX_TEX_SAMP_1                                    0x00000001
+#define A3XX_TEX_SAMP_1_MAX_LOD__MASK                          0x003ff000
+#define A3XX_TEX_SAMP_1_MAX_LOD__SHIFT                         12
+static inline uint32_t A3XX_TEX_SAMP_1_MAX_LOD(float val)
+{
+       return ((((uint32_t)(val * 12.0))) << A3XX_TEX_SAMP_1_MAX_LOD__SHIFT) & A3XX_TEX_SAMP_1_MAX_LOD__MASK;
+}
+#define A3XX_TEX_SAMP_1_MIN_LOD__MASK                          0xffc00000
+#define A3XX_TEX_SAMP_1_MIN_LOD__SHIFT                         22
+static inline uint32_t A3XX_TEX_SAMP_1_MIN_LOD(float val)
+{
+       return ((((uint32_t)(val * 12.0))) << A3XX_TEX_SAMP_1_MIN_LOD__SHIFT) & A3XX_TEX_SAMP_1_MIN_LOD__MASK;
+}
 
 #define REG_A3XX_TEX_CONST_0                                   0x00000000
 #define A3XX_TEX_CONST_0_TILED                                 0x00000001
index 035bd13dc8bdc3ab039bc2f1bab291cbf4c9bf17..461df93e825edf81e98d22683cfbf4fe7b4404aa 100644 (file)
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifdef CONFIG_MSM_OCMEM
+#  include <mach/ocmem.h>
+#endif
+
 #include "a3xx_gpu.h"
 
 #define A3XX_INT0_MASK \
@@ -63,6 +67,7 @@ static void a3xx_me_init(struct msm_gpu *gpu)
 static int a3xx_hw_init(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+       struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
        uint32_t *ptr, len;
        int i, ret;
 
@@ -105,6 +110,21 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
                gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff);
                gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
 
+       } else if (adreno_is_a330v2(adreno_gpu)) {
+               /*
+                * Most of the VBIF registers on 8974v2 have the correct
+                * values at power on, so we won't modify those if we don't
+                * need to
+                */
+               /* Enable 1k sort: */
+               gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
+               gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
+               /* Enable WR-REQ: */
+               gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
+               gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
+               /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
+               gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
+
        } else if (adreno_is_a330(adreno_gpu)) {
                /* Set up 16 deep read/write request queues: */
                gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
@@ -121,10 +141,10 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
                /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
                gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
                /* Set up AOOO: */
-               gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000ffff);
-               gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0xffffffff);
+               gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f);
+               gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f);
                /* Enable 1K sort: */
-               gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001ffff);
+               gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
                gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
                /* Disable VBIF clock gating. This is to enable AXI running
                 * higher frequency than GPU:
@@ -162,14 +182,23 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
 
        /* Enable Clock gating: */
-       gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
-
-       /* Set the OCMEM base address for A330 */
-//TODO:
-//     if (adreno_is_a330(adreno_gpu)) {
-//             gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
-//                     (unsigned int)(a3xx_gpu->ocmem_base >> 14));
-//     }
+       if (adreno_is_a320(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
+       else if (adreno_is_a330v2(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
+       else if (adreno_is_a330(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff);
+
+       if (adreno_is_a330v2(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455);
+       else if (adreno_is_a330(adreno_gpu))
+               gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000);
+
+       /* Set the OCMEM base address for A330, etc */
+       if (a3xx_gpu->ocmem_hdl) {
+               gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
+                       (unsigned int)(a3xx_gpu->ocmem_base >> 14));
+       }
 
        /* Turn on performance counters: */
        gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
@@ -219,7 +248,7 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        /* Load PM4: */
        ptr = (uint32_t *)(adreno_gpu->pm4->data);
        len = adreno_gpu->pm4->size / 4;
-       DBG("loading PM4 ucode version: %u", ptr[0]);
+       DBG("loading PM4 ucode version: %x", ptr[1]);
 
        gpu_write(gpu, REG_AXXX_CP_DEBUG,
                        AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE |
@@ -231,19 +260,26 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        /* Load PFP: */
        ptr = (uint32_t *)(adreno_gpu->pfp->data);
        len = adreno_gpu->pfp->size / 4;
-       DBG("loading PFP ucode version: %u", ptr[0]);
+       DBG("loading PFP ucode version: %x", ptr[5]);
 
        gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);
        for (i = 1; i < len; i++)
                gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
 
        /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
-       if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu))
+       if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) {
                gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
                                AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
                                AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
                                AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14));
-
+       } else if (adreno_is_a330(adreno_gpu)) {
+               /* NOTE: this (value take from downstream android driver)
+                * includes some bits outside of the known bitfields.  But
+                * A330 has this "MERCIU queue" thing too, which might
+                * explain a new bitfield or reshuffling:
+                */
+               gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008);
+       }
 
        /* clear ME_HALT to start micro engine */
        gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
@@ -253,6 +289,14 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
        return 0;
 }
 
+static void a3xx_recover(struct msm_gpu *gpu)
+{
+       gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
+       gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
+       gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
+       adreno_recover(gpu);
+}
+
 static void a3xx_destroy(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -261,6 +305,12 @@ static void a3xx_destroy(struct msm_gpu *gpu)
        DBG("%s", gpu->name);
 
        adreno_gpu_cleanup(adreno_gpu);
+
+#ifdef CONFIG_MSM_OCMEM
+       if (a3xx_gpu->ocmem_base)
+               ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
+#endif
+
        put_device(&a3xx_gpu->pdev->dev);
        kfree(a3xx_gpu);
 }
@@ -371,7 +421,7 @@ static const struct adreno_gpu_funcs funcs = {
                .hw_init = a3xx_hw_init,
                .pm_suspend = msm_gpu_pm_suspend,
                .pm_resume = msm_gpu_pm_resume,
-               .recover = adreno_recover,
+               .recover = a3xx_recover,
                .last_fence = adreno_last_fence,
                .submit = adreno_submit,
                .flush = adreno_flush,
@@ -387,6 +437,7 @@ static const struct adreno_gpu_funcs funcs = {
 struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
 {
        struct a3xx_gpu *a3xx_gpu = NULL;
+       struct adreno_gpu *adreno_gpu;
        struct msm_gpu *gpu;
        struct platform_device *pdev = a3xx_pdev;
        struct adreno_platform_config *config;
@@ -406,7 +457,8 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
                goto fail;
        }
 
-       gpu = &a3xx_gpu->base.base;
+       adreno_gpu = &a3xx_gpu->base;
+       gpu = &adreno_gpu->base;
 
        get_device(&pdev->dev);
        a3xx_gpu->pdev = pdev;
@@ -414,16 +466,46 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
        gpu->fast_rate = config->fast_rate;
        gpu->slow_rate = config->slow_rate;
        gpu->bus_freq  = config->bus_freq;
+#ifdef CONFIG_MSM_BUS_SCALING
+       gpu->bus_scale_table = config->bus_scale_table;
+#endif
 
        DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u",
                        gpu->fast_rate, gpu->slow_rate, gpu->bus_freq);
 
-       ret = adreno_gpu_init(dev, pdev, &a3xx_gpu->base,
-                       &funcs, config->rev);
+       ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, config->rev);
        if (ret)
                goto fail;
 
-       return &a3xx_gpu->base.base;
+       /* if needed, allocate gmem: */
+       if (adreno_is_a330(adreno_gpu)) {
+#ifdef CONFIG_MSM_OCMEM
+               /* TODO this is different/missing upstream: */
+               struct ocmem_buf *ocmem_hdl =
+                               ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
+
+               a3xx_gpu->ocmem_hdl = ocmem_hdl;
+               a3xx_gpu->ocmem_base = ocmem_hdl->addr;
+               adreno_gpu->gmem = ocmem_hdl->len;
+               DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
+                               a3xx_gpu->ocmem_base);
+#endif
+       }
+
+       if (!gpu->mmu) {
+               /* TODO we think it is possible to configure the GPU to
+                * restrict access to VRAM carveout.  But the required
+                * registers are unknown.  For now just bail out and
+                * limp along with just modesetting.  If it turns out
+                * to not be possible to restrict access, then we must
+                * implement a cmdstream validator.
+                */
+               dev_err(dev->dev, "No memory protection without IOMMU\n");
+               ret = -ENXIO;
+               goto fail;
+       }
+
+       return gpu;
 
 fail:
        if (a3xx_gpu)
@@ -436,19 +518,59 @@ fail:
  * The a3xx device:
  */
 
+#if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
+#  include <mach/kgsl.h>
+#endif
+
 static int a3xx_probe(struct platform_device *pdev)
 {
        static struct adreno_platform_config config = {};
 #ifdef CONFIG_OF
-       /* TODO */
+       struct device_node *child, *node = pdev->dev.of_node;
+       u32 val;
+       int ret;
+
+       ret = of_property_read_u32(node, "qcom,chipid", &val);
+       if (ret) {
+               dev_err(&pdev->dev, "could not find chipid: %d\n", ret);
+               return ret;
+       }
+
+       config.rev = ADRENO_REV((val >> 24) & 0xff,
+                       (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
+
+       /* find clock rates: */
+       config.fast_rate = 0;
+       config.slow_rate = ~0;
+       for_each_child_of_node(node, child) {
+               if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) {
+                       struct device_node *pwrlvl;
+                       for_each_child_of_node(child, pwrlvl) {
+                               ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
+                               if (ret) {
+                                       dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret);
+                                       return ret;
+                               }
+                               config.fast_rate = max(config.fast_rate, val);
+                               config.slow_rate = min(config.slow_rate, val);
+                       }
+               }
+       }
+
+       if (!config.fast_rate) {
+               dev_err(&pdev->dev, "could not find clk rates\n");
+               return -ENXIO;
+       }
+
 #else
+       struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
        uint32_t version = socinfo_get_version();
        if (cpu_is_apq8064ab()) {
                config.fast_rate = 450000000;
                config.slow_rate = 27000000;
                config.bus_freq  = 4;
                config.rev = ADRENO_REV(3, 2, 1, 0);
-       } else if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
+       } else if (cpu_is_apq8064()) {
                config.fast_rate = 400000000;
                config.slow_rate = 27000000;
                config.bus_freq  = 4;
@@ -461,6 +583,16 @@ static int a3xx_probe(struct platform_device *pdev)
                else
                        config.rev = ADRENO_REV(3, 2, 0, 0);
 
+       } else if (cpu_is_msm8960ab()) {
+               config.fast_rate = 400000000;
+               config.slow_rate = 320000000;
+               config.bus_freq  = 4;
+
+               if (SOCINFO_VERSION_MINOR(version) == 0)
+                       config.rev = ADRENO_REV(3, 2, 1, 0);
+               else
+                       config.rev = ADRENO_REV(3, 2, 1, 1);
+
        } else if (cpu_is_msm8930()) {
                config.fast_rate = 400000000;
                config.slow_rate = 27000000;
@@ -473,6 +605,9 @@ static int a3xx_probe(struct platform_device *pdev)
                        config.rev = ADRENO_REV(3, 0, 5, 0);
 
        }
+#  ifdef CONFIG_MSM_BUS_SCALING
+       config.bus_scale_table = pdata->bus_scale_table;
+#  endif
 #endif
        pdev->dev.platform_data = &config;
        a3xx_pdev = pdev;
@@ -485,10 +620,19 @@ static int a3xx_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id dt_match[] = {
+       { .compatible = "qcom,kgsl-3d0" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
 static struct platform_driver a3xx_driver = {
        .probe = a3xx_probe,
        .remove = a3xx_remove,
-       .driver.name = "kgsl-3d0",
+       .driver = {
+               .name = "kgsl-3d0",
+               .of_match_table = dt_match,
+       },
 };
 
 void __init a3xx_register(void)
index 32c398c2d00a7103a64a0e76f248b0ce4a712db0..bb9a8ca0507b3cdf4a16be9d59383459d6ff4c13 100644 (file)
 struct a3xx_gpu {
        struct adreno_gpu base;
        struct platform_device *pdev;
+
+       /* if OCMEM is used for GMEM: */
+       uint32_t ocmem_base;
+       void *ocmem_hdl;
 };
 #define to_a3xx_gpu(x) container_of(x, struct a3xx_gpu, base)
 
index 33dcc606c7c556a55a8e463d87bf56a0368c6363..d6e6ce2d1abde84742d02a0e950911fb1a401f8d 100644 (file)
@@ -8,12 +8,13 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml              (    327 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/a2xx/a2xx.xml           (  31003 bytes, from 2013-09-19 18:50:16)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_common.xml       (   8983 bytes, from 2013-07-24 01:38:36)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_pm4.xml          (   9759 bytes, from 2013-09-10 00:52:33)
-- /home/robclark/src/freedreno/envytools/rnndb/a3xx/a3xx.xml           (  51983 bytes, from 2013-09-10 00:52:32)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -115,96 +116,6 @@ enum adreno_rb_depth_format {
        DEPTHX_24_8 = 1,
 };
 
-enum adreno_mmu_clnt_beh {
-       BEH_NEVR = 0,
-       BEH_TRAN_RNG = 1,
-       BEH_TRAN_FLT = 2,
-};
-
-#define REG_AXXX_MH_MMU_CONFIG                                 0x00000040
-#define AXXX_MH_MMU_CONFIG_MMU_ENABLE                          0x00000001
-#define AXXX_MH_MMU_CONFIG_SPLIT_MODE_ENABLE                   0x00000002
-#define AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK            0x00000030
-#define AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT           4
-static inline uint32_t AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK            0x000000c0
-#define AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT           6
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK           0x00000300
-#define AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT          8
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK           0x00000c00
-#define AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT          10
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK           0x00003000
-#define AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT          12
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK           0x0000c000
-#define AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT          14
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK           0x00030000
-#define AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT          16
-static inline uint32_t AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK          0x000c0000
-#define AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT         18
-static inline uint32_t AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK          0x00300000
-#define AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT         20
-static inline uint32_t AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK            0x00c00000
-#define AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT           22
-static inline uint32_t AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR__MASK;
-}
-#define AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK            0x03000000
-#define AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT           24
-static inline uint32_t AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(enum adreno_mmu_clnt_beh val)
-{
-       return ((val) << AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__SHIFT) & AXXX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR__MASK;
-}
-
-#define REG_AXXX_MH_MMU_VA_RANGE                               0x00000041
-
-#define REG_AXXX_MH_MMU_PT_BASE                                        0x00000042
-
-#define REG_AXXX_MH_MMU_PAGE_FAULT                             0x00000043
-
-#define REG_AXXX_MH_MMU_TRAN_ERROR                             0x00000044
-
-#define REG_AXXX_MH_MMU_INVALIDATE                             0x00000045
-
-#define REG_AXXX_MH_MMU_MPU_BASE                               0x00000046
-
-#define REG_AXXX_MH_MMU_MPU_END                                        0x00000047
-
 #define REG_AXXX_CP_RB_BASE                                    0x000001c0
 
 #define REG_AXXX_CP_RB_CNTL                                    0x000001c1
@@ -275,6 +186,18 @@ static inline uint32_t AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(uint32_t val)
 }
 
 #define REG_AXXX_CP_MEQ_THRESHOLDS                             0x000001d6
+#define AXXX_CP_MEQ_THRESHOLDS_MEQ_END__MASK                   0x001f0000
+#define AXXX_CP_MEQ_THRESHOLDS_MEQ_END__SHIFT                  16
+static inline uint32_t AXXX_CP_MEQ_THRESHOLDS_MEQ_END(uint32_t val)
+{
+       return ((val) << AXXX_CP_MEQ_THRESHOLDS_MEQ_END__SHIFT) & AXXX_CP_MEQ_THRESHOLDS_MEQ_END__MASK;
+}
+#define AXXX_CP_MEQ_THRESHOLDS_ROQ_END__MASK                   0x1f000000
+#define AXXX_CP_MEQ_THRESHOLDS_ROQ_END__SHIFT                  24
+static inline uint32_t AXXX_CP_MEQ_THRESHOLDS_ROQ_END(uint32_t val)
+{
+       return ((val) << AXXX_CP_MEQ_THRESHOLDS_ROQ_END__SHIFT) & AXXX_CP_MEQ_THRESHOLDS_ROQ_END__MASK;
+}
 
 #define REG_AXXX_CP_CSQ_AVAIL                                  0x000001d7
 #define AXXX_CP_CSQ_AVAIL_RING__MASK                           0x0000007f
@@ -402,6 +325,36 @@ static inline uint32_t AXXX_CP_CSQ_IB2_STAT_WPTR(uint32_t val)
        return ((val) << AXXX_CP_CSQ_IB2_STAT_WPTR__SHIFT) & AXXX_CP_CSQ_IB2_STAT_WPTR__MASK;
 }
 
+#define REG_AXXX_CP_NON_PREFETCH_CNTRS                         0x00000440
+
+#define REG_AXXX_CP_STQ_ST_STAT                                        0x00000443
+
+#define REG_AXXX_CP_ST_BASE                                    0x0000044d
+
+#define REG_AXXX_CP_ST_BUFSZ                                   0x0000044e
+
+#define REG_AXXX_CP_MEQ_STAT                                   0x0000044f
+
+#define REG_AXXX_CP_MIU_TAG_STAT                               0x00000452
+
+#define REG_AXXX_CP_BIN_MASK_LO                                        0x00000454
+
+#define REG_AXXX_CP_BIN_MASK_HI                                        0x00000455
+
+#define REG_AXXX_CP_BIN_SELECT_LO                              0x00000456
+
+#define REG_AXXX_CP_BIN_SELECT_HI                              0x00000457
+
+#define REG_AXXX_CP_IB1_BASE                                   0x00000458
+
+#define REG_AXXX_CP_IB1_BUFSZ                                  0x00000459
+
+#define REG_AXXX_CP_IB2_BASE                                   0x0000045a
+
+#define REG_AXXX_CP_IB2_BUFSZ                                  0x0000045b
+
+#define REG_AXXX_CP_STAT                                       0x0000047f
+
 #define REG_AXXX_CP_SCRATCH_REG0                               0x00000578
 
 #define REG_AXXX_CP_SCRATCH_REG1                               0x00000579
@@ -418,6 +371,26 @@ static inline uint32_t AXXX_CP_CSQ_IB2_STAT_WPTR(uint32_t val)
 
 #define REG_AXXX_CP_SCRATCH_REG7                               0x0000057f
 
+#define REG_AXXX_CP_ME_VS_EVENT_SRC                            0x00000600
+
+#define REG_AXXX_CP_ME_VS_EVENT_ADDR                           0x00000601
+
+#define REG_AXXX_CP_ME_VS_EVENT_DATA                           0x00000602
+
+#define REG_AXXX_CP_ME_VS_EVENT_ADDR_SWM                       0x00000603
+
+#define REG_AXXX_CP_ME_VS_EVENT_DATA_SWM                       0x00000604
+
+#define REG_AXXX_CP_ME_PS_EVENT_SRC                            0x00000605
+
+#define REG_AXXX_CP_ME_PS_EVENT_ADDR                           0x00000606
+
+#define REG_AXXX_CP_ME_PS_EVENT_DATA                           0x00000607
+
+#define REG_AXXX_CP_ME_PS_EVENT_ADDR_SWM                       0x00000608
+
+#define REG_AXXX_CP_ME_PS_EVENT_DATA_SWM                       0x00000609
+
 #define REG_AXXX_CP_ME_CF_EVENT_SRC                            0x0000060a
 
 #define REG_AXXX_CP_ME_CF_EVENT_ADDR                           0x0000060b
@@ -428,5 +401,11 @@ static inline uint32_t AXXX_CP_CSQ_IB2_STAT_WPTR(uint32_t val)
 
 #define REG_AXXX_CP_ME_NRT_DATA                                        0x0000060e
 
+#define REG_AXXX_CP_ME_VS_FETCH_DONE_SRC                       0x00000612
+
+#define REG_AXXX_CP_ME_VS_FETCH_DONE_ADDR                      0x00000613
+
+#define REG_AXXX_CP_ME_VS_FETCH_DONE_DATA                      0x00000614
+
 
 #endif /* ADRENO_COMMON_XML */
index a0b9d8a95b16c17ad6b11ae1b6da662e80484b04..d321099abdd45ac17b37bc32ae8399ce95bc6f32 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "adreno_gpu.h"
 #include "msm_gem.h"
+#include "msm_mmu.h"
 
 struct adreno_info {
        struct adreno_rev rev;
@@ -44,7 +45,7 @@ static const struct adreno_info gpulist[] = {
                .pfpfw = "a300_pfp.fw",
                .gmem  = SZ_512K,
        }, {
-               .rev   = ADRENO_REV(3, 3, 0, 0),
+               .rev   = ADRENO_REV(3, 3, 0, ANY_ID),
                .revn  = 330,
                .name  = "A330",
                .pm4fw = "a330_pm4.fw",
@@ -53,6 +54,11 @@ static const struct adreno_info gpulist[] = {
        },
 };
 
+MODULE_FIRMWARE("a300_pm4.fw");
+MODULE_FIRMWARE("a300_pfp.fw");
+MODULE_FIRMWARE("a330_pm4.fw");
+MODULE_FIRMWARE("a330_pfp.fw");
+
 #define RB_SIZE    SZ_32K
 #define RB_BLKSIZE 16
 
@@ -65,7 +71,7 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
                *value = adreno_gpu->info->revn;
                return 0;
        case MSM_PARAM_GMEM_SIZE:
-               *value = adreno_gpu->info->gmem;
+               *value = adreno_gpu->gmem;
                return 0;
        default:
                DBG("%s: invalid param: %u", gpu->name, param);
@@ -86,7 +92,7 @@ int adreno_hw_init(struct msm_gpu *gpu)
        gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
                        /* size is log2(quad-words): */
                        AXXX_CP_RB_CNTL_BUFSZ(ilog2(gpu->rb->size / 8)) |
-                       AXXX_CP_RB_CNTL_BLKSZ(RB_BLKSIZE));
+                       AXXX_CP_RB_CNTL_BLKSZ(ilog2(RB_BLKSIZE / 8)));
 
        /* Setup ringbuffer address: */
        gpu_write(gpu, REG_AXXX_CP_RB_BASE, gpu->rb_iova);
@@ -286,6 +292,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs,
                struct adreno_rev rev)
 {
+       struct msm_mmu *mmu;
        int i, ret;
 
        /* identify gpu: */
@@ -311,6 +318,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                        rev.core, rev.major, rev.minor, rev.patchid);
 
        gpu->funcs = funcs;
+       gpu->gmem = gpu->info->gmem;
        gpu->rev = rev;
 
        ret = request_firmware(&gpu->pm4, gpu->info->pm4fw, drm->dev);
@@ -333,10 +341,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        if (ret)
                return ret;
 
-       ret = msm_iommu_attach(drm, gpu->base.iommu,
-                       iommu_ports, ARRAY_SIZE(iommu_ports));
-       if (ret)
-               return ret;
+       mmu = gpu->base.mmu;
+       if (mmu) {
+               ret = mmu->funcs->attach(mmu, iommu_ports,
+                               ARRAY_SIZE(iommu_ports));
+               if (ret)
+                       return ret;
+       }
 
        gpu->memptrs_bo = msm_gem_new(drm, sizeof(*gpu->memptrs),
                        MSM_BO_UNCACHED);
index f73abfba7c22eb03b4aa0c7f1e962ade219edf1f..ca11ea4da165082fd3ab2f2ecae981d5cd7543ad 100644 (file)
@@ -51,6 +51,7 @@ struct adreno_gpu {
        struct msm_gpu base;
        struct adreno_rev rev;
        const struct adreno_info *info;
+       uint32_t gmem;  /* actual gmem size */
        uint32_t revn;  /* numeric revision name */
        const struct adreno_gpu_funcs *funcs;
 
@@ -70,6 +71,9 @@ struct adreno_gpu {
 struct adreno_platform_config {
        struct adreno_rev rev;
        uint32_t fast_rate, slow_rate, bus_freq;
+#ifdef CONFIG_MSM_BUS_SCALING
+       struct msm_bus_scale_pdata *bus_scale_table;
+#endif
 };
 
 #define ADRENO_IDLE_TIMEOUT (20 * 1000)
@@ -94,6 +98,11 @@ static inline bool adreno_is_a330(struct adreno_gpu *gpu)
        return gpu->revn == 330;
 }
 
+static inline bool adreno_is_a330v2(struct adreno_gpu *gpu)
+{
+       return adreno_is_a330(gpu) && (gpu->rev.patchid > 0);
+}
+
 int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
 int adreno_hw_init(struct msm_gpu *gpu);
 uint32_t adreno_last_fence(struct msm_gpu *gpu);
index 259ad709b0cc0467d1a4e6a55435e63ea4cb3415..ae992c71703f1ccc5151b1cf72b904c89e1cd8ec 100644 (file)
@@ -8,12 +8,13 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml              (    327 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/a2xx/a2xx.xml           (  31003 bytes, from 2013-09-19 18:50:16)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_common.xml       (   8983 bytes, from 2013-07-24 01:38:36)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno_pm4.xml          (   9759 bytes, from 2013-09-10 00:52:33)
-- /home/robclark/src/freedreno/envytools/rnndb/a3xx/a3xx.xml           (  51983 bytes, from 2013-09-10 00:52:32)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    364 bytes, from 2013-11-30 14:47:15)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32814 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (   8900 bytes, from 2013-10-22 23:57:49)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  10574 bytes, from 2013-11-13 05:44:45)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  53644 bytes, from 2013-11-30 15:07:33)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          (   8344 bytes, from 2013-11-30 14:49:47)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -66,13 +67,15 @@ enum vgt_event_type {
 
 enum pc_di_primtype {
        DI_PT_NONE = 0,
-       DI_PT_POINTLIST = 1,
+       DI_PT_POINTLIST_A2XX = 1,
        DI_PT_LINELIST = 2,
        DI_PT_LINESTRIP = 3,
        DI_PT_TRILIST = 4,
        DI_PT_TRIFAN = 5,
        DI_PT_TRISTRIP = 6,
+       DI_PT_LINELOOP = 7,
        DI_PT_RECTLIST = 8,
+       DI_PT_POINTLIST_A3XX = 9,
        DI_PT_QUADLIST = 13,
        DI_PT_QUADSTRIP = 14,
        DI_PT_POLYGON = 15,
@@ -119,7 +122,7 @@ enum adreno_pm4_type3_packets {
        CP_WAIT_FOR_IDLE = 38,
        CP_WAIT_REG_MEM = 60,
        CP_WAIT_REG_EQ = 82,
-       CP_WAT_REG_GTE = 83,
+       CP_WAIT_REG_GTE = 83,
        CP_WAIT_UNTIL_READ = 92,
        CP_WAIT_IB_PFD_COMPLETE = 93,
        CP_REG_RMW = 33,
@@ -151,7 +154,6 @@ enum adreno_pm4_type3_packets {
        CP_CONTEXT_UPDATE = 94,
        CP_INTERRUPT = 64,
        CP_IM_STORE = 44,
-       CP_SET_BIN_BASE_OFFSET = 75,
        CP_SET_DRAW_INIT_FLAGS = 75,
        CP_SET_PROTECTED_MODE = 95,
        CP_LOAD_STATE = 48,
@@ -159,6 +161,16 @@ enum adreno_pm4_type3_packets {
        CP_COND_INDIRECT_BUFFER_PFD = 50,
        CP_INDIRECT_BUFFER_PFE = 63,
        CP_SET_BIN = 76,
+       CP_TEST_TWO_MEMS = 113,
+       CP_WAIT_FOR_ME = 19,
+       IN_IB_PREFETCH_END = 23,
+       IN_SUBBLK_PREFETCH = 31,
+       IN_INSTR_PREFETCH = 32,
+       IN_INSTR_MATCH = 71,
+       IN_CONST_PREFETCH = 73,
+       IN_INCR_UPDT_STATE = 85,
+       IN_INCR_UPDT_CONST = 86,
+       IN_INCR_UPDT_INSTR = 87,
 };
 
 enum adreno_state_block {
index 6d4c62bf70dc482cf9f38ea1739046cb19732943..87be647e3825f0ad96491f5df5b8cf271158f848 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
index d1df38bf574783bf98c39253315e3810527d1377..747a6ef4211f71748e759343213ce7ecdc5fb335 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
index 0030a111302dae44c6a4ecc0e21d5aa9e7364032..48e03acf19bf5bdf61659c96acd4444e6c716c73 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
index 50d11df35b21f1cac9ac15d41f649015a664cfbf..6f1588aa9071f8db8642dcb8b32e46642381b38d 100644 (file)
@@ -41,7 +41,7 @@ void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
                        power_on ? "Enable" : "Disable", ctrl);
 }
 
-static irqreturn_t hdmi_irq(int irq, void *dev_id)
+irqreturn_t hdmi_irq(int irq, void *dev_id)
 {
        struct hdmi *hdmi = dev_id;
 
@@ -71,13 +71,13 @@ void hdmi_destroy(struct kref *kref)
 }
 
 /* initialize connector */
-int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
+struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
 {
        struct hdmi *hdmi = NULL;
        struct msm_drm_private *priv = dev->dev_private;
        struct platform_device *pdev = hdmi_pdev;
        struct hdmi_platform_config *config;
-       int ret;
+       int i, ret;
 
        if (!pdev) {
                dev_err(dev->dev, "no hdmi device\n");
@@ -99,6 +99,7 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
 
        hdmi->dev = dev;
        hdmi->pdev = pdev;
+       hdmi->config = config;
        hdmi->encoder = encoder;
 
        /* not sure about which phy maps to which msm.. probably I miss some */
@@ -114,44 +115,70 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
                goto fail;
        }
 
-       hdmi->mmio = msm_ioremap(pdev, "hdmi_msm_hdmi_addr", "HDMI");
+       hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI");
        if (IS_ERR(hdmi->mmio)) {
                ret = PTR_ERR(hdmi->mmio);
                goto fail;
        }
 
-       hdmi->mvs = devm_regulator_get(&pdev->dev, "8901_hdmi_mvs");
-       if (IS_ERR(hdmi->mvs))
-               hdmi->mvs = devm_regulator_get(&pdev->dev, "hdmi_mvs");
-       if (IS_ERR(hdmi->mvs)) {
-               ret = PTR_ERR(hdmi->mvs);
-               dev_err(dev->dev, "failed to get mvs regulator: %d\n", ret);
-               goto fail;
+       BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs));
+       for (i = 0; i < config->hpd_reg_cnt; i++) {
+               struct regulator *reg;
+
+               reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]);
+               if (IS_ERR(reg)) {
+                       ret = PTR_ERR(reg);
+                       dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n",
+                                       config->hpd_reg_names[i], ret);
+                       goto fail;
+               }
+
+               hdmi->hpd_regs[i] = reg;
        }
 
-       hdmi->mpp0 = devm_regulator_get(&pdev->dev, "8901_mpp0");
-       if (IS_ERR(hdmi->mpp0))
-               hdmi->mpp0 = NULL;
+       BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs));
+       for (i = 0; i < config->pwr_reg_cnt; i++) {
+               struct regulator *reg;
 
-       hdmi->clk = devm_clk_get(&pdev->dev, "core_clk");
-       if (IS_ERR(hdmi->clk)) {
-               ret = PTR_ERR(hdmi->clk);
-               dev_err(dev->dev, "failed to get 'clk': %d\n", ret);
-               goto fail;
+               reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]);
+               if (IS_ERR(reg)) {
+                       ret = PTR_ERR(reg);
+                       dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n",
+                                       config->pwr_reg_names[i], ret);
+                       goto fail;
+               }
+
+               hdmi->pwr_regs[i] = reg;
        }
 
-       hdmi->m_pclk = devm_clk_get(&pdev->dev, "master_iface_clk");
-       if (IS_ERR(hdmi->m_pclk)) {
-               ret = PTR_ERR(hdmi->m_pclk);
-               dev_err(dev->dev, "failed to get 'm_pclk': %d\n", ret);
-               goto fail;
+       BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks));
+       for (i = 0; i < config->hpd_clk_cnt; i++) {
+               struct clk *clk;
+
+               clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]);
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err(dev->dev, "failed to get hpd clk: %s (%d)\n",
+                                       config->hpd_clk_names[i], ret);
+                       goto fail;
+               }
+
+               hdmi->hpd_clks[i] = clk;
        }
 
-       hdmi->s_pclk = devm_clk_get(&pdev->dev, "slave_iface_clk");
-       if (IS_ERR(hdmi->s_pclk)) {
-               ret = PTR_ERR(hdmi->s_pclk);
-               dev_err(dev->dev, "failed to get 's_pclk': %d\n", ret);
-               goto fail;
+       BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks));
+       for (i = 0; i < config->pwr_clk_cnt; i++) {
+               struct clk *clk;
+
+               clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]);
+               if (IS_ERR(clk)) {
+                       ret = PTR_ERR(clk);
+                       dev_err(dev->dev, "failed to get pwr clk: %s (%d)\n",
+                                       config->pwr_clk_names[i], ret);
+                       goto fail;
+               }
+
+               hdmi->pwr_clks[i] = clk;
        }
 
        hdmi->i2c = hdmi_i2c_init(hdmi);
@@ -178,20 +205,22 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
                goto fail;
        }
 
-       hdmi->irq = platform_get_irq(pdev, 0);
-       if (hdmi->irq < 0) {
-               ret = hdmi->irq;
-               dev_err(dev->dev, "failed to get irq: %d\n", ret);
-               goto fail;
-       }
+       if (!config->shared_irq) {
+               hdmi->irq = platform_get_irq(pdev, 0);
+               if (hdmi->irq < 0) {
+                       ret = hdmi->irq;
+                       dev_err(dev->dev, "failed to get irq: %d\n", ret);
+                       goto fail;
+               }
 
-       ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
-                       NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-                       "hdmi_isr", hdmi);
-       if (ret < 0) {
-               dev_err(dev->dev, "failed to request IRQ%u: %d\n",
-                               hdmi->irq, ret);
-               goto fail;
+               ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq,
+                               NULL, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                               "hdmi_isr", hdmi);
+               if (ret < 0) {
+                       dev_err(dev->dev, "failed to request IRQ%u: %d\n",
+                                       hdmi->irq, ret);
+                       goto fail;
+               }
        }
 
        encoder->bridge = hdmi->bridge;
@@ -199,7 +228,7 @@ int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
        priv->bridges[priv->num_bridges++]       = hdmi->bridge;
        priv->connectors[priv->num_connectors++] = hdmi->connector;
 
-       return 0;
+       return hdmi;
 
 fail:
        if (hdmi) {
@@ -211,37 +240,100 @@ fail:
                hdmi_destroy(&hdmi->refcount);
        }
 
-       return ret;
+       return ERR_PTR(ret);
 }
 
 /*
  * The hdmi device:
  */
 
+#include <linux/of_gpio.h>
+
 static int hdmi_dev_probe(struct platform_device *pdev)
 {
        static struct hdmi_platform_config config = {};
 #ifdef CONFIG_OF
-       /* TODO */
+       struct device_node *of_node = pdev->dev.of_node;
+
+       int get_gpio(const char *name)
+       {
+               int gpio = of_get_named_gpio(of_node, name, 0);
+               if (gpio < 0) {
+                       dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n",
+                                       name, gpio);
+                       gpio = -1;
+               }
+               return gpio;
+       }
+
+       /* TODO actually use DT.. */
+       static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
+       static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
+       static const char *hpd_clk_names[] = {"iface_clk", "core_clk", "mdp_core_clk"};
+       static const char *pwr_clk_names[] = {"extp_clk", "alt_iface_clk"};
+
+       config.phy_init      = hdmi_phy_8x74_init;
+       config.mmio_name     = "core_physical";
+       config.hpd_reg_names = hpd_reg_names;
+       config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+       config.pwr_reg_names = pwr_reg_names;
+       config.pwr_reg_cnt   = ARRAY_SIZE(pwr_reg_names);
+       config.hpd_clk_names = hpd_clk_names;
+       config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
+       config.pwr_clk_names = pwr_clk_names;
+       config.pwr_clk_cnt   = ARRAY_SIZE(pwr_clk_names);
+       config.ddc_clk_gpio  = get_gpio("qcom,hdmi-tx-ddc-clk");
+       config.ddc_data_gpio = get_gpio("qcom,hdmi-tx-ddc-data");
+       config.hpd_gpio      = get_gpio("qcom,hdmi-tx-hpd");
+       config.mux_en_gpio   = get_gpio("qcom,hdmi-tx-mux-en");
+       config.mux_sel_gpio  = get_gpio("qcom,hdmi-tx-mux-sel");
+       config.shared_irq    = true;
+
 #else
+       static const char *hpd_clk_names[] = {
+                       "core_clk", "master_iface_clk", "slave_iface_clk",
+       };
        if (cpu_is_apq8064()) {
+               static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
                config.phy_init      = hdmi_phy_8960_init;
+               config.mmio_name     = "hdmi_msm_hdmi_addr";
+               config.hpd_reg_names = hpd_reg_names;
+               config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+               config.hpd_clk_names = hpd_clk_names;
+               config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
                config.ddc_clk_gpio  = 70;
                config.ddc_data_gpio = 71;
                config.hpd_gpio      = 72;
-               config.pmic_gpio     = 13 + NR_GPIO_IRQS;
-       } else if (cpu_is_msm8960()) {
+               config.mux_en_gpio   = -1;
+               config.mux_sel_gpio  = 13 + NR_GPIO_IRQS;
+       } else if (cpu_is_msm8960() || cpu_is_msm8960ab()) {
+               static const char *hpd_reg_names[] = {"8921_hdmi_mvs"};
                config.phy_init      = hdmi_phy_8960_init;
+               config.mmio_name     = "hdmi_msm_hdmi_addr";
+               config.hpd_reg_names = hpd_reg_names;
+               config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+               config.hpd_clk_names = hpd_clk_names;
+               config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
                config.ddc_clk_gpio  = 100;
                config.ddc_data_gpio = 101;
                config.hpd_gpio      = 102;
-               config.pmic_gpio     = -1;
+               config.mux_en_gpio   = -1;
+               config.mux_sel_gpio  = -1;
        } else if (cpu_is_msm8x60()) {
+               static const char *hpd_reg_names[] = {
+                               "8901_hdmi_mvs", "8901_mpp0"
+               };
                config.phy_init      = hdmi_phy_8x60_init;
+               config.mmio_name     = "hdmi_msm_hdmi_addr";
+               config.hpd_reg_names = hpd_reg_names;
+               config.hpd_reg_cnt   = ARRAY_SIZE(hpd_reg_names);
+               config.hpd_clk_names = hpd_clk_names;
+               config.hpd_clk_cnt   = ARRAY_SIZE(hpd_clk_names);
                config.ddc_clk_gpio  = 170;
                config.ddc_data_gpio = 171;
                config.hpd_gpio      = 172;
-               config.pmic_gpio     = -1;
+               config.mux_en_gpio   = -1;
+               config.mux_sel_gpio  = -1;
        }
 #endif
        pdev->dev.platform_data = &config;
@@ -255,10 +347,19 @@ static int hdmi_dev_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id dt_match[] = {
+       { .compatible = "qcom,hdmi-tx" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
 static struct platform_driver hdmi_driver = {
        .probe = hdmi_dev_probe,
        .remove = hdmi_dev_remove,
-       .driver.name = "hdmi_msm",
+       .driver = {
+               .name = "hdmi_msm",
+               .of_match_table = dt_match,
+       },
 };
 
 void __init hdmi_register(void)
index 2c2ec566394c7ac314c9bf3e97b70071bfce4d48..41b29add70b1be7a19b480d5a84ba25aeb79518b 100644 (file)
@@ -28,6 +28,7 @@
 
 
 struct hdmi_phy;
+struct hdmi_platform_config;
 
 struct hdmi {
        struct kref refcount;
@@ -35,14 +36,14 @@ struct hdmi {
        struct drm_device *dev;
        struct platform_device *pdev;
 
-       void __iomem *mmio;
+       const struct hdmi_platform_config *config;
 
-       struct regulator *mvs;        /* HDMI_5V */
-       struct regulator *mpp0;       /* External 5V */
+       void __iomem *mmio;
 
-       struct clk *clk;
-       struct clk *m_pclk;
-       struct clk *s_pclk;
+       struct regulator *hpd_regs[2];
+       struct regulator *pwr_regs[2];
+       struct clk *hpd_clks[3];
+       struct clk *pwr_clks[2];
 
        struct hdmi_phy *phy;
        struct i2c_adapter *i2c;
@@ -60,7 +61,29 @@ struct hdmi {
 /* platform config data (ie. from DT, or pdata) */
 struct hdmi_platform_config {
        struct hdmi_phy *(*phy_init)(struct hdmi *hdmi);
-       int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, pmic_gpio;
+       const char *mmio_name;
+
+       /* regulators that need to be on for hpd: */
+       const char **hpd_reg_names;
+       int hpd_reg_cnt;
+
+       /* regulators that need to be on for screen pwr: */
+       const char **pwr_reg_names;
+       int pwr_reg_cnt;
+
+       /* clks that need to be on for hpd: */
+       const char **hpd_clk_names;
+       int hpd_clk_cnt;
+
+       /* clks that need to be on for screen pwr (ie pixel clk): */
+       const char **pwr_clk_names;
+       int pwr_clk_cnt;
+
+       /* gpio's: */
+       int ddc_clk_gpio, ddc_data_gpio, hpd_gpio, mux_en_gpio, mux_sel_gpio;
+
+       /* older devices had their own irq, mdp5+ it is shared w/ mdp: */
+       bool shared_irq;
 };
 
 void hdmi_set_mode(struct hdmi *hdmi, bool power_on);
@@ -106,6 +129,7 @@ struct hdmi_phy {
 
 struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi);
 struct hdmi_phy *hdmi_phy_8x60_init(struct hdmi *hdmi);
+struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi);
 
 /*
  * hdmi bridge:
index 4e939f82918c68daee08cc95253eeb25f31c24b8..e2636582cfd753bc2443659ee615db428530e2dc 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -212,6 +214,20 @@ static inline uint32_t HDMI_HDCP_LINK0_STATUS_KEY_STATE(enum hdmi_hdcp_key_state
 #define REG_HDMI_HDCP_RESET                                    0x00000130
 #define HDMI_HDCP_RESET_LINK0_DEAUTHENTICATE                   0x00000001
 
+#define REG_HDMI_VENSPEC_INFO0                                 0x0000016c
+
+#define REG_HDMI_VENSPEC_INFO1                                 0x00000170
+
+#define REG_HDMI_VENSPEC_INFO2                                 0x00000174
+
+#define REG_HDMI_VENSPEC_INFO3                                 0x00000178
+
+#define REG_HDMI_VENSPEC_INFO4                                 0x0000017c
+
+#define REG_HDMI_VENSPEC_INFO5                                 0x00000180
+
+#define REG_HDMI_VENSPEC_INFO6                                 0x00000184
+
 #define REG_HDMI_AUDIO_CFG                                     0x000001d0
 #define HDMI_AUDIO_CFG_ENGINE_ENABLE                           0x00000001
 #define HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK                    0x000000f0
@@ -235,6 +251,9 @@ static inline uint32_t HDMI_DDC_CTRL_TRANSACTION_CNT(uint32_t val)
        return ((val) << HDMI_DDC_CTRL_TRANSACTION_CNT__SHIFT) & HDMI_DDC_CTRL_TRANSACTION_CNT__MASK;
 }
 
+#define REG_HDMI_DDC_ARBITRATION                               0x00000210
+#define HDMI_DDC_ARBITRATION_HW_ARBITRATION                    0x00000010
+
 #define REG_HDMI_DDC_INT_CTRL                                  0x00000214
 #define HDMI_DDC_INT_CTRL_SW_DONE_INT                          0x00000001
 #define HDMI_DDC_INT_CTRL_SW_DONE_ACK                          0x00000002
@@ -340,6 +359,20 @@ static inline uint32_t HDMI_DDC_REF_REFTIMER(uint32_t val)
        return ((val) << HDMI_DDC_REF_REFTIMER__SHIFT) & HDMI_DDC_REF_REFTIMER__MASK;
 }
 
+#define REG_HDMI_CEC_STATUS                                    0x00000298
+
+#define REG_HDMI_CEC_INT                                       0x0000029c
+
+#define REG_HDMI_CEC_ADDR                                      0x000002a0
+
+#define REG_HDMI_CEC_TIME                                      0x000002a4
+
+#define REG_HDMI_CEC_REFTIMER                                  0x000002a8
+
+#define REG_HDMI_CEC_RD_DATA                                   0x000002ac
+
+#define REG_HDMI_CEC_RD_FILTER                                 0x000002b0
+
 #define REG_HDMI_ACTIVE_HSYNC                                  0x000002b4
 #define HDMI_ACTIVE_HSYNC_START__MASK                          0x00000fff
 #define HDMI_ACTIVE_HSYNC_START__SHIFT                         0
@@ -410,17 +443,33 @@ static inline uint32_t HDMI_VSYNC_TOTAL_F2_V_TOTAL(uint32_t val)
 #define HDMI_FRAME_CTRL_HSYNC_LOW                              0x20000000
 #define HDMI_FRAME_CTRL_INTERLACED_EN                          0x80000000
 
+#define REG_HDMI_AUD_INT                                       0x000002cc
+#define HDMI_AUD_INT_AUD_FIFO_URUN_INT                         0x00000001
+#define HDMI_AUD_INT_AUD_FIFO_URAN_MASK                                0x00000002
+#define HDMI_AUD_INT_AUD_SAM_DROP_INT                          0x00000004
+#define HDMI_AUD_INT_AUD_SAM_DROP_MASK                         0x00000008
+
 #define REG_HDMI_PHY_CTRL                                      0x000002d4
 #define HDMI_PHY_CTRL_SW_RESET_PLL                             0x00000001
 #define HDMI_PHY_CTRL_SW_RESET_PLL_LOW                         0x00000002
 #define HDMI_PHY_CTRL_SW_RESET                                 0x00000004
 #define HDMI_PHY_CTRL_SW_RESET_LOW                             0x00000008
 
-#define REG_HDMI_AUD_INT                                       0x000002cc
-#define HDMI_AUD_INT_AUD_FIFO_URUN_INT                         0x00000001
-#define HDMI_AUD_INT_AUD_FIFO_URAN_MASK                                0x00000002
-#define HDMI_AUD_INT_AUD_SAM_DROP_INT                          0x00000004
-#define HDMI_AUD_INT_AUD_SAM_DROP_MASK                         0x00000008
+#define REG_HDMI_CEC_WR_RANGE                                  0x000002dc
+
+#define REG_HDMI_CEC_RD_RANGE                                  0x000002e0
+
+#define REG_HDMI_VERSION                                       0x000002e4
+
+#define REG_HDMI_CEC_COMPL_CTL                                 0x00000360
+
+#define REG_HDMI_CEC_RD_START_RANGE                            0x00000364
+
+#define REG_HDMI_CEC_RD_TOTAL_RANGE                            0x00000368
+
+#define REG_HDMI_CEC_RD_ERR_RESP_LO                            0x0000036c
+
+#define REG_HDMI_CEC_WR_CHECK_CONFIG                           0x00000370
 
 #define REG_HDMI_8x60_PHY_REG0                                 0x00000300
 #define HDMI_8x60_PHY_REG0_DESER_DEL_CTRL__MASK                        0x0000001c
@@ -504,5 +553,23 @@ static inline uint32_t HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(uint32_t val)
 
 #define REG_HDMI_8960_PHY_REG12                                        0x00000430
 
+#define REG_HDMI_8x74_ANA_CFG0                                 0x00000000
+
+#define REG_HDMI_8x74_ANA_CFG1                                 0x00000004
+
+#define REG_HDMI_8x74_PD_CTRL0                                 0x00000010
+
+#define REG_HDMI_8x74_PD_CTRL1                                 0x00000014
+
+#define REG_HDMI_8x74_BIST_CFG0                                        0x00000034
+
+#define REG_HDMI_8x74_BIST_PATN0                               0x0000003c
+
+#define REG_HDMI_8x74_BIST_PATN1                               0x00000040
+
+#define REG_HDMI_8x74_BIST_PATN2                               0x00000044
+
+#define REG_HDMI_8x74_BIST_PATN3                               0x00000048
+
 
 #endif /* HDMI_XML */
index 5a8ee3473cf5e0e229ec5c94743e4f7749950ea7..7d10e55403c61da733c1e60c7922799063eef79f 100644 (file)
@@ -21,6 +21,7 @@ struct hdmi_bridge {
        struct drm_bridge base;
 
        struct hdmi *hdmi;
+       bool power_on;
 
        unsigned long int pixclock;
 };
@@ -34,6 +35,65 @@ static void hdmi_bridge_destroy(struct drm_bridge *bridge)
        kfree(hdmi_bridge);
 }
 
+static void power_on(struct drm_bridge *bridge)
+{
+       struct drm_device *dev = bridge->dev;
+       struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+       struct hdmi *hdmi = hdmi_bridge->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
+       int i, ret;
+
+       for (i = 0; i < config->pwr_reg_cnt; i++) {
+               ret = regulator_enable(hdmi->pwr_regs[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable pwr regulator: %s (%d)\n",
+                                       config->pwr_reg_names[i], ret);
+               }
+       }
+
+       if (config->pwr_clk_cnt > 0) {
+               DBG("pixclock: %lu", hdmi_bridge->pixclock);
+               ret = clk_set_rate(hdmi->pwr_clks[0], hdmi_bridge->pixclock);
+               if (ret) {
+                       dev_err(dev->dev, "failed to set pixel clk: %s (%d)\n",
+                                       config->pwr_clk_names[0], ret);
+               }
+       }
+
+       for (i = 0; i < config->pwr_clk_cnt; i++) {
+               ret = clk_prepare_enable(hdmi->pwr_clks[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable pwr clk: %s (%d)\n",
+                                       config->pwr_clk_names[i], ret);
+               }
+       }
+}
+
+static void power_off(struct drm_bridge *bridge)
+{
+       struct drm_device *dev = bridge->dev;
+       struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+       struct hdmi *hdmi = hdmi_bridge->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
+       int i, ret;
+
+       /* TODO do we need to wait for final vblank somewhere before
+        * cutting the clocks?
+        */
+       mdelay(16 + 4);
+
+       for (i = 0; i < config->pwr_clk_cnt; i++)
+               clk_disable_unprepare(hdmi->pwr_clks[i]);
+
+       for (i = 0; i < config->pwr_reg_cnt; i++) {
+               ret = regulator_disable(hdmi->pwr_regs[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to disable pwr regulator: %s (%d)\n",
+                                       config->pwr_reg_names[i], ret);
+               }
+       }
+}
+
 static void hdmi_bridge_pre_enable(struct drm_bridge *bridge)
 {
        struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
@@ -41,6 +101,12 @@ static void hdmi_bridge_pre_enable(struct drm_bridge *bridge)
        struct hdmi_phy *phy = hdmi->phy;
 
        DBG("power up");
+
+       if (!hdmi_bridge->power_on) {
+               power_on(bridge);
+               hdmi_bridge->power_on = true;
+       }
+
        phy->funcs->powerup(phy, hdmi_bridge->pixclock);
        hdmi_set_mode(hdmi, true);
 }
@@ -62,6 +128,11 @@ static void hdmi_bridge_post_disable(struct drm_bridge *bridge)
        DBG("power down");
        hdmi_set_mode(hdmi, false);
        phy->funcs->powerdown(phy);
+
+       if (hdmi_bridge->power_on) {
+               power_off(bridge);
+               hdmi_bridge->power_on = false;
+       }
 }
 
 static void hdmi_bridge_mode_set(struct drm_bridge *bridge,
index 823eee521a31b523e04e7470ab01612cdeb0887e..7dedfdd120759d51c7bd5a940bb01e874b87f579 100644 (file)
 
 #include <linux/gpio.h>
 
+#include "msm_kms.h"
 #include "hdmi.h"
 
 struct hdmi_connector {
        struct drm_connector base;
        struct hdmi *hdmi;
+       struct work_struct hpd_work;
 };
 #define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base)
 
 static int gpio_config(struct hdmi *hdmi, bool on)
 {
        struct drm_device *dev = hdmi->dev;
-       struct hdmi_platform_config *config =
-                       hdmi->pdev->dev.platform_data;
+       const struct hdmi_platform_config *config = hdmi->config;
        int ret;
 
        if (on) {
@@ -39,26 +40,43 @@ static int gpio_config(struct hdmi *hdmi, bool on)
                                "HDMI_DDC_CLK", config->ddc_clk_gpio, ret);
                        goto error1;
                }
+               gpio_set_value_cansleep(config->ddc_clk_gpio, 1);
+
                ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA");
                if (ret) {
                        dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
                                "HDMI_DDC_DATA", config->ddc_data_gpio, ret);
                        goto error2;
                }
+               gpio_set_value_cansleep(config->ddc_data_gpio, 1);
+
                ret = gpio_request(config->hpd_gpio, "HDMI_HPD");
                if (ret) {
                        dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
                                "HDMI_HPD", config->hpd_gpio, ret);
                        goto error3;
                }
-               if (config->pmic_gpio != -1) {
-                       ret = gpio_request(config->pmic_gpio, "PMIC_HDMI_MUX_SEL");
+               gpio_direction_input(config->hpd_gpio);
+               gpio_set_value_cansleep(config->hpd_gpio, 1);
+
+               if (config->mux_en_gpio != -1) {
+                       ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");
                        if (ret) {
                                dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
-                                       "PMIC_HDMI_MUX_SEL", config->pmic_gpio, ret);
+                                       "HDMI_MUX_SEL", config->mux_en_gpio, ret);
                                goto error4;
                        }
-                       gpio_set_value_cansleep(config->pmic_gpio, 0);
+                       gpio_set_value_cansleep(config->mux_en_gpio, 1);
+               }
+
+               if (config->mux_sel_gpio != -1) {
+                       ret = gpio_request(config->mux_sel_gpio, "HDMI_MUX_SEL");
+                       if (ret) {
+                               dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+                                       "HDMI_MUX_SEL", config->mux_sel_gpio, ret);
+                               goto error5;
+                       }
+                       gpio_set_value_cansleep(config->mux_sel_gpio, 0);
                }
                DBG("gpio on");
        } else {
@@ -66,15 +84,23 @@ static int gpio_config(struct hdmi *hdmi, bool on)
                gpio_free(config->ddc_data_gpio);
                gpio_free(config->hpd_gpio);
 
-               if (config->pmic_gpio != -1) {
-                       gpio_set_value_cansleep(config->pmic_gpio, 1);
-                       gpio_free(config->pmic_gpio);
+               if (config->mux_en_gpio != -1) {
+                       gpio_set_value_cansleep(config->mux_en_gpio, 0);
+                       gpio_free(config->mux_en_gpio);
+               }
+
+               if (config->mux_sel_gpio != -1) {
+                       gpio_set_value_cansleep(config->mux_sel_gpio, 1);
+                       gpio_free(config->mux_sel_gpio);
                }
                DBG("gpio off");
        }
 
        return 0;
 
+error5:
+       if (config->mux_en_gpio != -1)
+               gpio_free(config->mux_en_gpio);
 error4:
        gpio_free(config->hpd_gpio);
 error3:
@@ -88,10 +114,11 @@ error1:
 static int hpd_enable(struct hdmi_connector *hdmi_connector)
 {
        struct hdmi *hdmi = hdmi_connector->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
        struct drm_device *dev = hdmi_connector->base.dev;
        struct hdmi_phy *phy = hdmi->phy;
        uint32_t hpd_ctrl;
-       int ret;
+       int i, ret;
 
        ret = gpio_config(hdmi, true);
        if (ret) {
@@ -99,31 +126,22 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
                goto fail;
        }
 
-       ret = clk_prepare_enable(hdmi->clk);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable 'clk': %d\n", ret);
-               goto fail;
-       }
-
-       ret = clk_prepare_enable(hdmi->m_pclk);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable 'm_pclk': %d\n", ret);
-               goto fail;
-       }
-
-       ret = clk_prepare_enable(hdmi->s_pclk);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable 's_pclk': %d\n", ret);
-               goto fail;
+       for (i = 0; i < config->hpd_clk_cnt; i++) {
+               ret = clk_prepare_enable(hdmi->hpd_clks[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n",
+                                       config->hpd_clk_names[i], ret);
+                       goto fail;
+               }
        }
 
-       if (hdmi->mpp0)
-               ret = regulator_enable(hdmi->mpp0);
-       if (!ret)
-               ret = regulator_enable(hdmi->mvs);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable regulators: %d\n", ret);
-               goto fail;
+       for (i = 0; i < config->hpd_reg_cnt; i++) {
+               ret = regulator_enable(hdmi->hpd_regs[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n",
+                                       config->hpd_reg_names[i], ret);
+                       goto fail;
+               }
        }
 
        hdmi_set_mode(hdmi, false);
@@ -156,26 +174,26 @@ fail:
 static int hdp_disable(struct hdmi_connector *hdmi_connector)
 {
        struct hdmi *hdmi = hdmi_connector->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
        struct drm_device *dev = hdmi_connector->base.dev;
-       int ret = 0;
+       int i, ret = 0;
 
        /* Disable HPD interrupt */
        hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
 
        hdmi_set_mode(hdmi, false);
 
-       if (hdmi->mpp0)
-               ret = regulator_disable(hdmi->mpp0);
-       if (!ret)
-               ret = regulator_disable(hdmi->mvs);
-       if (ret) {
-               dev_err(dev->dev, "failed to enable regulators: %d\n", ret);
-               goto fail;
+       for (i = 0; i < config->hpd_reg_cnt; i++) {
+               ret = regulator_disable(hdmi->hpd_regs[i]);
+               if (ret) {
+                       dev_err(dev->dev, "failed to disable hpd regulator: %s (%d)\n",
+                                       config->hpd_reg_names[i], ret);
+                       goto fail;
+               }
        }
 
-       clk_disable_unprepare(hdmi->clk);
-       clk_disable_unprepare(hdmi->m_pclk);
-       clk_disable_unprepare(hdmi->s_pclk);
+       for (i = 0; i < config->hpd_clk_cnt; i++)
+               clk_disable_unprepare(hdmi->hpd_clks[i]);
 
        ret = gpio_config(hdmi, false);
        if (ret) {
@@ -189,9 +207,19 @@ fail:
        return ret;
 }
 
+static void
+hotplug_work(struct work_struct *work)
+{
+       struct hdmi_connector *hdmi_connector =
+               container_of(work, struct hdmi_connector, hpd_work);
+       struct drm_connector *connector = &hdmi_connector->base;
+       drm_helper_hpd_irq_event(connector->dev);
+}
+
 void hdmi_connector_irq(struct drm_connector *connector)
 {
        struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
+       struct msm_drm_private *priv = connector->dev->dev_private;
        struct hdmi *hdmi = hdmi_connector->hdmi;
        uint32_t hpd_int_status, hpd_int_ctrl;
 
@@ -209,13 +237,13 @@ void hdmi_connector_irq(struct drm_connector *connector)
                hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
                                hpd_int_ctrl | HDMI_HPD_INT_CTRL_INT_ACK);
 
-               drm_helper_hpd_irq_event(connector->dev);
-
                /* detect disconnect if we are connected or visa versa: */
                hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN;
                if (!detected)
                        hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
                hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
+
+               queue_work(priv->wq, &hdmi_connector->hpd_work);
        }
 }
 
@@ -224,6 +252,7 @@ static enum drm_connector_status hdmi_connector_detect(
 {
        struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
        struct hdmi *hdmi = hdmi_connector->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
        uint32_t hpd_int_status;
        int retry = 20;
 
@@ -233,6 +262,14 @@ static enum drm_connector_status hdmi_connector_detect(
         * let that trick us into thinking the monitor is gone:
         */
        while (retry-- && !(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED)) {
+               /* hdmi debounce logic seems to get stuck sometimes,
+                * read directly the gpio to get a second opinion:
+                */
+               if (gpio_get_value(config->hpd_gpio)) {
+                       DBG("gpio tells us we are connected!");
+                       hpd_int_status |= HDMI_HPD_INT_STATUS_CABLE_DETECTED;
+                       break;
+               }
                mdelay(10);
                hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
                DBG("status=%08x", hpd_int_status);
@@ -285,6 +322,8 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector,
                                 struct drm_display_mode *mode)
 {
        struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
+       struct hdmi *hdmi = hdmi_connector->hdmi;
+       const struct hdmi_platform_config *config = hdmi->config;
        struct msm_drm_private *priv = connector->dev->dev_private;
        struct msm_kms *kms = priv->kms;
        long actual, requested;
@@ -293,6 +332,13 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector,
        actual = kms->funcs->round_pixclk(kms,
                        requested, hdmi_connector->hdmi->encoder);
 
+       /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
+        * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
+        * instead):
+        */
+       if (config->pwr_clk_cnt > 0)
+               actual = clk_round_rate(hdmi->pwr_clks[0], actual);
+
        DBG("requested=%ld, actual=%ld", requested, actual);
 
        if (actual != requested)
@@ -335,6 +381,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
        }
 
        hdmi_connector->hdmi = hdmi_reference(hdmi);
+       INIT_WORK(&hdmi_connector->hpd_work, hotplug_work);
 
        connector = &hdmi_connector->base;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c
new file mode 100644 (file)
index 0000000..59fa6cd
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "hdmi.h"
+
+struct hdmi_phy_8x74 {
+       struct hdmi_phy base;
+       struct hdmi *hdmi;
+       void __iomem *mmio;
+};
+#define to_hdmi_phy_8x74(x) container_of(x, struct hdmi_phy_8x74, base)
+
+
+static void phy_write(struct hdmi_phy_8x74 *phy, u32 reg, u32 data)
+{
+       msm_writel(data, phy->mmio + reg);
+}
+
+//static u32 phy_read(struct hdmi_phy_8x74 *phy, u32 reg)
+//{
+//     return msm_readl(phy->mmio + reg);
+//}
+
+static void hdmi_phy_8x74_destroy(struct hdmi_phy *phy)
+{
+       struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
+       kfree(phy_8x74);
+}
+
+static void hdmi_phy_8x74_reset(struct hdmi_phy *phy)
+{
+       struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
+       struct hdmi *hdmi = phy_8x74->hdmi;
+       unsigned int val;
+
+       /* NOTE that HDMI_PHY_CTL is in core mmio, not phy mmio: */
+
+       val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET);
+       } else {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET);
+       }
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
+       } else {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET_PLL);
+       }
+
+       msleep(100);
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET);
+       } else {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET);
+       }
+
+       if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
+               /* pull high */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val | HDMI_PHY_CTRL_SW_RESET_PLL);
+       } else {
+               /* pull low */
+               hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
+                               val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
+       }
+}
+
+static void hdmi_phy_8x74_powerup(struct hdmi_phy *phy,
+               unsigned long int pixclock)
+{
+       struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
+
+       phy_write(phy_8x74, REG_HDMI_8x74_ANA_CFG0,   0x1b);
+       phy_write(phy_8x74, REG_HDMI_8x74_ANA_CFG1,   0xf2);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_CFG0,  0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN0, 0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN1, 0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN2, 0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_BIST_PATN3, 0x0);
+       phy_write(phy_8x74, REG_HDMI_8x74_PD_CTRL1,   0x20);
+}
+
+static void hdmi_phy_8x74_powerdown(struct hdmi_phy *phy)
+{
+       struct hdmi_phy_8x74 *phy_8x74 = to_hdmi_phy_8x74(phy);
+       phy_write(phy_8x74, REG_HDMI_8x74_PD_CTRL0, 0x7f);
+}
+
+static const struct hdmi_phy_funcs hdmi_phy_8x74_funcs = {
+               .destroy = hdmi_phy_8x74_destroy,
+               .reset = hdmi_phy_8x74_reset,
+               .powerup = hdmi_phy_8x74_powerup,
+               .powerdown = hdmi_phy_8x74_powerdown,
+};
+
+struct hdmi_phy *hdmi_phy_8x74_init(struct hdmi *hdmi)
+{
+       struct hdmi_phy_8x74 *phy_8x74;
+       struct hdmi_phy *phy = NULL;
+       int ret;
+
+       phy_8x74 = kzalloc(sizeof(*phy_8x74), GFP_KERNEL);
+       if (!phy_8x74) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       phy = &phy_8x74->base;
+
+       phy->funcs = &hdmi_phy_8x74_funcs;
+
+       phy_8x74->hdmi = hdmi;
+
+       /* for 8x74, the phy mmio is mapped separately: */
+       phy_8x74->mmio = msm_ioremap(hdmi->pdev,
+                       "phy_physical", "HDMI_8x74");
+       if (IS_ERR(phy_8x74->mmio)) {
+               ret = PTR_ERR(phy_8x74->mmio);
+               goto fail;
+       }
+
+       return phy;
+
+fail:
+       if (phy)
+               hdmi_phy_8x74_destroy(phy);
+       return ERR_PTR(ret);
+}
index dbde4f6339b9f82b257c2d3ba24cc534d066760e..d591567173c405226eea5fc9d06b4591887f29d1 100644 (file)
@@ -8,14 +8,16 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
 - /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
 
 Copyright (C) 2013 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
new file mode 100644 (file)
index 0000000..416a26e
--- /dev/null
@@ -0,0 +1,1033 @@
+#ifndef MDP4_XML
+#define MDP4_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+
+Copyright (C) 2013 by the following authors:
+- Rob Clark <robdclark@gmail.com> (robclark)
+
+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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+*/
+
+
+enum mdp4_pipe {
+       VG1 = 0,
+       VG2 = 1,
+       RGB1 = 2,
+       RGB2 = 3,
+       RGB3 = 4,
+       VG3 = 5,
+       VG4 = 6,
+};
+
+enum mdp4_mixer {
+       MIXER0 = 0,
+       MIXER1 = 1,
+       MIXER2 = 2,
+};
+
+enum mdp4_intf {
+       INTF_LCDC_DTV = 0,
+       INTF_DSI_VIDEO = 1,
+       INTF_DSI_CMD = 2,
+       INTF_EBI2_TV = 3,
+};
+
+enum mdp4_cursor_format {
+       CURSOR_ARGB = 1,
+       CURSOR_XRGB = 2,
+};
+
+enum mdp4_dma {
+       DMA_P = 0,
+       DMA_S = 1,
+       DMA_E = 2,
+};
+
+#define MDP4_IRQ_OVERLAY0_DONE                                 0x00000001
+#define MDP4_IRQ_OVERLAY1_DONE                                 0x00000002
+#define MDP4_IRQ_DMA_S_DONE                                    0x00000004
+#define MDP4_IRQ_DMA_E_DONE                                    0x00000008
+#define MDP4_IRQ_DMA_P_DONE                                    0x00000010
+#define MDP4_IRQ_VG1_HISTOGRAM                                 0x00000020
+#define MDP4_IRQ_VG2_HISTOGRAM                                 0x00000040
+#define MDP4_IRQ_PRIMARY_VSYNC                                 0x00000080
+#define MDP4_IRQ_PRIMARY_INTF_UDERRUN                          0x00000100
+#define MDP4_IRQ_EXTERNAL_VSYNC                                        0x00000200
+#define MDP4_IRQ_EXTERNAL_INTF_UDERRUN                         0x00000400
+#define MDP4_IRQ_PRIMARY_RDPTR                                 0x00000800
+#define MDP4_IRQ_DMA_P_HISTOGRAM                               0x00020000
+#define MDP4_IRQ_DMA_S_HISTOGRAM                               0x04000000
+#define MDP4_IRQ_OVERLAY2_DONE                                 0x40000000
+#define REG_MDP4_VERSION                                       0x00000000
+#define MDP4_VERSION_MINOR__MASK                               0x00ff0000
+#define MDP4_VERSION_MINOR__SHIFT                              16
+static inline uint32_t MDP4_VERSION_MINOR(uint32_t val)
+{
+       return ((val) << MDP4_VERSION_MINOR__SHIFT) & MDP4_VERSION_MINOR__MASK;
+}
+#define MDP4_VERSION_MAJOR__MASK                               0xff000000
+#define MDP4_VERSION_MAJOR__SHIFT                              24
+static inline uint32_t MDP4_VERSION_MAJOR(uint32_t val)
+{
+       return ((val) << MDP4_VERSION_MAJOR__SHIFT) & MDP4_VERSION_MAJOR__MASK;
+}
+
+#define REG_MDP4_OVLP0_KICK                                    0x00000004
+
+#define REG_MDP4_OVLP1_KICK                                    0x00000008
+
+#define REG_MDP4_OVLP2_KICK                                    0x000000d0
+
+#define REG_MDP4_DMA_P_KICK                                    0x0000000c
+
+#define REG_MDP4_DMA_S_KICK                                    0x00000010
+
+#define REG_MDP4_DMA_E_KICK                                    0x00000014
+
+#define REG_MDP4_DISP_STATUS                                   0x00000018
+
+#define REG_MDP4_DISP_INTF_SEL                                 0x00000038
+#define MDP4_DISP_INTF_SEL_PRIM__MASK                          0x00000003
+#define MDP4_DISP_INTF_SEL_PRIM__SHIFT                         0
+static inline uint32_t MDP4_DISP_INTF_SEL_PRIM(enum mdp4_intf val)
+{
+       return ((val) << MDP4_DISP_INTF_SEL_PRIM__SHIFT) & MDP4_DISP_INTF_SEL_PRIM__MASK;
+}
+#define MDP4_DISP_INTF_SEL_SEC__MASK                           0x0000000c
+#define MDP4_DISP_INTF_SEL_SEC__SHIFT                          2
+static inline uint32_t MDP4_DISP_INTF_SEL_SEC(enum mdp4_intf val)
+{
+       return ((val) << MDP4_DISP_INTF_SEL_SEC__SHIFT) & MDP4_DISP_INTF_SEL_SEC__MASK;
+}
+#define MDP4_DISP_INTF_SEL_EXT__MASK                           0x00000030
+#define MDP4_DISP_INTF_SEL_EXT__SHIFT                          4
+static inline uint32_t MDP4_DISP_INTF_SEL_EXT(enum mdp4_intf val)
+{
+       return ((val) << MDP4_DISP_INTF_SEL_EXT__SHIFT) & MDP4_DISP_INTF_SEL_EXT__MASK;
+}
+#define MDP4_DISP_INTF_SEL_DSI_VIDEO                           0x00000040
+#define MDP4_DISP_INTF_SEL_DSI_CMD                             0x00000080
+
+#define REG_MDP4_RESET_STATUS                                  0x0000003c
+
+#define REG_MDP4_READ_CNFG                                     0x0000004c
+
+#define REG_MDP4_INTR_ENABLE                                   0x00000050
+
+#define REG_MDP4_INTR_STATUS                                   0x00000054
+
+#define REG_MDP4_INTR_CLEAR                                    0x00000058
+
+#define REG_MDP4_EBI2_LCD0                                     0x00000060
+
+#define REG_MDP4_EBI2_LCD1                                     0x00000064
+
+#define REG_MDP4_PORTMAP_MODE                                  0x00000070
+
+#define REG_MDP4_CS_CONTROLLER0                                        0x000000c0
+
+#define REG_MDP4_CS_CONTROLLER1                                        0x000000c4
+
+#define REG_MDP4_LAYERMIXER2_IN_CFG                            0x000100f0
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE0__MASK                    0x00000007
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE0__SHIFT                   0
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE0(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE0__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE0__MASK;
+}
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE0_MIXER1                   0x00000008
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE1__MASK                    0x00000070
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE1__SHIFT                   4
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE1(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE1__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE1__MASK;
+}
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE1_MIXER1                   0x00000080
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE2__MASK                    0x00000700
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE2__SHIFT                   8
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE2(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE2__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE2__MASK;
+}
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE2_MIXER1                   0x00000800
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE3__MASK                    0x00007000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE3__SHIFT                   12
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE3(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE3__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE3__MASK;
+}
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE3_MIXER1                   0x00008000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE4__MASK                    0x00070000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE4__SHIFT                   16
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE4(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE4__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE4__MASK;
+}
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE4_MIXER1                   0x00080000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE5__MASK                    0x00700000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE5__SHIFT                   20
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE5(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE5__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE5__MASK;
+}
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE5_MIXER1                   0x00800000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE6__MASK                    0x07000000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE6__SHIFT                   24
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE6(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE6__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE6__MASK;
+}
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE6_MIXER1                   0x08000000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE7__MASK                    0x70000000
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE7__SHIFT                   28
+static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE7(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE7__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE7__MASK;
+}
+#define MDP4_LAYERMIXER2_IN_CFG_PIPE7_MIXER1                   0x80000000
+
+#define REG_MDP4_LAYERMIXER_IN_CFG_UPDATE_METHOD               0x000100fc
+
+#define REG_MDP4_LAYERMIXER_IN_CFG                             0x00010100
+#define MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK                     0x00000007
+#define MDP4_LAYERMIXER_IN_CFG_PIPE0__SHIFT                    0
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE0(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE0__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK;
+}
+#define MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1                    0x00000008
+#define MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK                     0x00000070
+#define MDP4_LAYERMIXER_IN_CFG_PIPE1__SHIFT                    4
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE1(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE1__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK;
+}
+#define MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1                    0x00000080
+#define MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK                     0x00000700
+#define MDP4_LAYERMIXER_IN_CFG_PIPE2__SHIFT                    8
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE2(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE2__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK;
+}
+#define MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1                    0x00000800
+#define MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK                     0x00007000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE3__SHIFT                    12
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE3(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE3__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK;
+}
+#define MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1                    0x00008000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK                     0x00070000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE4__SHIFT                    16
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE4(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE4__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK;
+}
+#define MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1                    0x00080000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK                     0x00700000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE5__SHIFT                    20
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE5(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE5__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK;
+}
+#define MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1                    0x00800000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK                     0x07000000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE6__SHIFT                    24
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE6(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE6__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK;
+}
+#define MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1                    0x08000000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE7__MASK                     0x70000000
+#define MDP4_LAYERMIXER_IN_CFG_PIPE7__SHIFT                    28
+static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE7(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE7__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE7__MASK;
+}
+#define MDP4_LAYERMIXER_IN_CFG_PIPE7_MIXER1                    0x80000000
+
+#define REG_MDP4_VG2_SRC_FORMAT                                        0x00030050
+
+#define REG_MDP4_VG2_CONST_COLOR                               0x00031008
+
+#define REG_MDP4_OVERLAY_FLUSH                                 0x00018000
+#define MDP4_OVERLAY_FLUSH_OVLP0                               0x00000001
+#define MDP4_OVERLAY_FLUSH_OVLP1                               0x00000002
+#define MDP4_OVERLAY_FLUSH_VG1                                 0x00000004
+#define MDP4_OVERLAY_FLUSH_VG2                                 0x00000008
+#define MDP4_OVERLAY_FLUSH_RGB1                                        0x00000010
+#define MDP4_OVERLAY_FLUSH_RGB2                                        0x00000020
+
+static inline uint32_t __offset_OVLP(uint32_t idx)
+{
+       switch (idx) {
+               case 0: return 0x00010000;
+               case 1: return 0x00018000;
+               case 2: return 0x00088000;
+               default: return INVALID_IDX(idx);
+       }
+}
+static inline uint32_t REG_MDP4_OVLP(uint32_t i0) { return 0x00000000 + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_CFG(uint32_t i0) { return 0x00000004 + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_SIZE(uint32_t i0) { return 0x00000008 + __offset_OVLP(i0); }
+#define MDP4_OVLP_SIZE_HEIGHT__MASK                            0xffff0000
+#define MDP4_OVLP_SIZE_HEIGHT__SHIFT                           16
+static inline uint32_t MDP4_OVLP_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP4_OVLP_SIZE_HEIGHT__SHIFT) & MDP4_OVLP_SIZE_HEIGHT__MASK;
+}
+#define MDP4_OVLP_SIZE_WIDTH__MASK                             0x0000ffff
+#define MDP4_OVLP_SIZE_WIDTH__SHIFT                            0
+static inline uint32_t MDP4_OVLP_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP4_OVLP_SIZE_WIDTH__SHIFT) & MDP4_OVLP_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP4_OVLP_BASE(uint32_t i0) { return 0x0000000c + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_STRIDE(uint32_t i0) { return 0x00000010 + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_OPMODE(uint32_t i0) { return 0x00000014 + __offset_OVLP(i0); }
+
+static inline uint32_t __offset_STAGE(uint32_t idx)
+{
+       switch (idx) {
+               case 0: return 0x00000104;
+               case 1: return 0x00000124;
+               case 2: return 0x00000144;
+               case 3: return 0x00000160;
+               default: return INVALID_IDX(idx);
+       }
+}
+static inline uint32_t REG_MDP4_OVLP_STAGE(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE(i1); }
+
+static inline uint32_t REG_MDP4_OVLP_STAGE_OP(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE(i1); }
+#define MDP4_OVLP_STAGE_OP_FG_ALPHA__MASK                      0x00000003
+#define MDP4_OVLP_STAGE_OP_FG_ALPHA__SHIFT                     0
+static inline uint32_t MDP4_OVLP_STAGE_OP_FG_ALPHA(enum mdp_alpha_type val)
+{
+       return ((val) << MDP4_OVLP_STAGE_OP_FG_ALPHA__SHIFT) & MDP4_OVLP_STAGE_OP_FG_ALPHA__MASK;
+}
+#define MDP4_OVLP_STAGE_OP_FG_INV_ALPHA                                0x00000004
+#define MDP4_OVLP_STAGE_OP_FG_MOD_ALPHA                                0x00000008
+#define MDP4_OVLP_STAGE_OP_BG_ALPHA__MASK                      0x00000030
+#define MDP4_OVLP_STAGE_OP_BG_ALPHA__SHIFT                     4
+static inline uint32_t MDP4_OVLP_STAGE_OP_BG_ALPHA(enum mdp_alpha_type val)
+{
+       return ((val) << MDP4_OVLP_STAGE_OP_BG_ALPHA__SHIFT) & MDP4_OVLP_STAGE_OP_BG_ALPHA__MASK;
+}
+#define MDP4_OVLP_STAGE_OP_BG_INV_ALPHA                                0x00000040
+#define MDP4_OVLP_STAGE_OP_BG_MOD_ALPHA                                0x00000080
+#define MDP4_OVLP_STAGE_OP_FG_TRANSP                           0x00000100
+#define MDP4_OVLP_STAGE_OP_BG_TRANSP                           0x00000200
+
+static inline uint32_t REG_MDP4_OVLP_STAGE_FG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00000004 + __offset_OVLP(i0) + __offset_STAGE(i1); }
+
+static inline uint32_t REG_MDP4_OVLP_STAGE_BG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00000008 + __offset_OVLP(i0) + __offset_STAGE(i1); }
+
+static inline uint32_t REG_MDP4_OVLP_STAGE_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000000c + __offset_OVLP(i0) + __offset_STAGE(i1); }
+
+static inline uint32_t REG_MDP4_OVLP_STAGE_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00000010 + __offset_OVLP(i0) + __offset_STAGE(i1); }
+
+static inline uint32_t REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00000014 + __offset_OVLP(i0) + __offset_STAGE(i1); }
+
+static inline uint32_t REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00000018 + __offset_OVLP(i0) + __offset_STAGE(i1); }
+
+static inline uint32_t __offset_STAGE_CO3(uint32_t idx)
+{
+       switch (idx) {
+               case 0: return 0x00001004;
+               case 1: return 0x00001404;
+               case 2: return 0x00001804;
+               case 3: return 0x00001b84;
+               default: return INVALID_IDX(idx);
+       }
+}
+static inline uint32_t REG_MDP4_OVLP_STAGE_CO3(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE_CO3(i1); }
+
+static inline uint32_t REG_MDP4_OVLP_STAGE_CO3_SEL(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE_CO3(i1); }
+#define MDP4_OVLP_STAGE_CO3_SEL_FG_ALPHA                       0x00000001
+
+static inline uint32_t REG_MDP4_OVLP_TRANSP_LOW0(uint32_t i0) { return 0x00000180 + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_TRANSP_LOW1(uint32_t i0) { return 0x00000184 + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_TRANSP_HIGH0(uint32_t i0) { return 0x00000188 + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_TRANSP_HIGH1(uint32_t i0) { return 0x0000018c + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_CONFIG(uint32_t i0) { return 0x00000200 + __offset_OVLP(i0); }
+
+static inline uint32_t REG_MDP4_OVLP_CSC(uint32_t i0) { return 0x00002000 + __offset_OVLP(i0); }
+
+
+static inline uint32_t REG_MDP4_OVLP_CSC_MV(uint32_t i0, uint32_t i1) { return 0x00002400 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_MV_VAL(uint32_t i0, uint32_t i1) { return 0x00002400 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_PRE_BV(uint32_t i0, uint32_t i1) { return 0x00002500 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_PRE_BV_VAL(uint32_t i0, uint32_t i1) { return 0x00002500 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_POST_BV(uint32_t i0, uint32_t i1) { return 0x00002580 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_POST_BV_VAL(uint32_t i0, uint32_t i1) { return 0x00002580 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_PRE_LV(uint32_t i0, uint32_t i1) { return 0x00002600 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_PRE_LV_VAL(uint32_t i0, uint32_t i1) { return 0x00002600 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_POST_LV(uint32_t i0, uint32_t i1) { return 0x00002680 + __offset_OVLP(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_OVLP_CSC_POST_LV_VAL(uint32_t i0, uint32_t i1) { return 0x00002680 + __offset_OVLP(i0) + 0x4*i1; }
+
+#define REG_MDP4_DMA_P_OP_MODE                                 0x00090070
+
+static inline uint32_t REG_MDP4_LUTN(uint32_t i0) { return 0x00094800 + 0x400*i0; }
+
+static inline uint32_t REG_MDP4_LUTN_LUT(uint32_t i0, uint32_t i1) { return 0x00094800 + 0x400*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_LUTN_LUT_VAL(uint32_t i0, uint32_t i1) { return 0x00094800 + 0x400*i0 + 0x4*i1; }
+
+#define REG_MDP4_DMA_S_OP_MODE                                 0x000a0028
+
+static inline uint32_t REG_MDP4_DMA_E_QUANT(uint32_t i0) { return 0x000b0070 + 0x4*i0; }
+
+static inline uint32_t __offset_DMA(enum mdp4_dma idx)
+{
+       switch (idx) {
+               case DMA_P: return 0x00090000;
+               case DMA_S: return 0x000a0000;
+               case DMA_E: return 0x000b0000;
+               default: return INVALID_IDX(idx);
+       }
+}
+static inline uint32_t REG_MDP4_DMA(enum mdp4_dma i0) { return 0x00000000 + __offset_DMA(i0); }
+
+static inline uint32_t REG_MDP4_DMA_CONFIG(enum mdp4_dma i0) { return 0x00000000 + __offset_DMA(i0); }
+#define MDP4_DMA_CONFIG_G_BPC__MASK                            0x00000003
+#define MDP4_DMA_CONFIG_G_BPC__SHIFT                           0
+static inline uint32_t MDP4_DMA_CONFIG_G_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP4_DMA_CONFIG_G_BPC__SHIFT) & MDP4_DMA_CONFIG_G_BPC__MASK;
+}
+#define MDP4_DMA_CONFIG_B_BPC__MASK                            0x0000000c
+#define MDP4_DMA_CONFIG_B_BPC__SHIFT                           2
+static inline uint32_t MDP4_DMA_CONFIG_B_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP4_DMA_CONFIG_B_BPC__SHIFT) & MDP4_DMA_CONFIG_B_BPC__MASK;
+}
+#define MDP4_DMA_CONFIG_R_BPC__MASK                            0x00000030
+#define MDP4_DMA_CONFIG_R_BPC__SHIFT                           4
+static inline uint32_t MDP4_DMA_CONFIG_R_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP4_DMA_CONFIG_R_BPC__SHIFT) & MDP4_DMA_CONFIG_R_BPC__MASK;
+}
+#define MDP4_DMA_CONFIG_PACK_ALIGN_MSB                         0x00000080
+#define MDP4_DMA_CONFIG_PACK__MASK                             0x0000ff00
+#define MDP4_DMA_CONFIG_PACK__SHIFT                            8
+static inline uint32_t MDP4_DMA_CONFIG_PACK(uint32_t val)
+{
+       return ((val) << MDP4_DMA_CONFIG_PACK__SHIFT) & MDP4_DMA_CONFIG_PACK__MASK;
+}
+#define MDP4_DMA_CONFIG_DEFLKR_EN                              0x01000000
+#define MDP4_DMA_CONFIG_DITHER_EN                              0x01000000
+
+static inline uint32_t REG_MDP4_DMA_SRC_SIZE(enum mdp4_dma i0) { return 0x00000004 + __offset_DMA(i0); }
+#define MDP4_DMA_SRC_SIZE_HEIGHT__MASK                         0xffff0000
+#define MDP4_DMA_SRC_SIZE_HEIGHT__SHIFT                                16
+static inline uint32_t MDP4_DMA_SRC_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP4_DMA_SRC_SIZE_HEIGHT__SHIFT) & MDP4_DMA_SRC_SIZE_HEIGHT__MASK;
+}
+#define MDP4_DMA_SRC_SIZE_WIDTH__MASK                          0x0000ffff
+#define MDP4_DMA_SRC_SIZE_WIDTH__SHIFT                         0
+static inline uint32_t MDP4_DMA_SRC_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP4_DMA_SRC_SIZE_WIDTH__SHIFT) & MDP4_DMA_SRC_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP4_DMA_SRC_BASE(enum mdp4_dma i0) { return 0x00000008 + __offset_DMA(i0); }
+
+static inline uint32_t REG_MDP4_DMA_SRC_STRIDE(enum mdp4_dma i0) { return 0x0000000c + __offset_DMA(i0); }
+
+static inline uint32_t REG_MDP4_DMA_DST_SIZE(enum mdp4_dma i0) { return 0x00000010 + __offset_DMA(i0); }
+#define MDP4_DMA_DST_SIZE_HEIGHT__MASK                         0xffff0000
+#define MDP4_DMA_DST_SIZE_HEIGHT__SHIFT                                16
+static inline uint32_t MDP4_DMA_DST_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP4_DMA_DST_SIZE_HEIGHT__SHIFT) & MDP4_DMA_DST_SIZE_HEIGHT__MASK;
+}
+#define MDP4_DMA_DST_SIZE_WIDTH__MASK                          0x0000ffff
+#define MDP4_DMA_DST_SIZE_WIDTH__SHIFT                         0
+static inline uint32_t MDP4_DMA_DST_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP4_DMA_DST_SIZE_WIDTH__SHIFT) & MDP4_DMA_DST_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP4_DMA_CURSOR_SIZE(enum mdp4_dma i0) { return 0x00000044 + __offset_DMA(i0); }
+#define MDP4_DMA_CURSOR_SIZE_WIDTH__MASK                       0x0000007f
+#define MDP4_DMA_CURSOR_SIZE_WIDTH__SHIFT                      0
+static inline uint32_t MDP4_DMA_CURSOR_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP4_DMA_CURSOR_SIZE_WIDTH__SHIFT) & MDP4_DMA_CURSOR_SIZE_WIDTH__MASK;
+}
+#define MDP4_DMA_CURSOR_SIZE_HEIGHT__MASK                      0x007f0000
+#define MDP4_DMA_CURSOR_SIZE_HEIGHT__SHIFT                     16
+static inline uint32_t MDP4_DMA_CURSOR_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP4_DMA_CURSOR_SIZE_HEIGHT__SHIFT) & MDP4_DMA_CURSOR_SIZE_HEIGHT__MASK;
+}
+
+static inline uint32_t REG_MDP4_DMA_CURSOR_BASE(enum mdp4_dma i0) { return 0x00000048 + __offset_DMA(i0); }
+
+static inline uint32_t REG_MDP4_DMA_CURSOR_POS(enum mdp4_dma i0) { return 0x0000004c + __offset_DMA(i0); }
+#define MDP4_DMA_CURSOR_POS_X__MASK                            0x0000ffff
+#define MDP4_DMA_CURSOR_POS_X__SHIFT                           0
+static inline uint32_t MDP4_DMA_CURSOR_POS_X(uint32_t val)
+{
+       return ((val) << MDP4_DMA_CURSOR_POS_X__SHIFT) & MDP4_DMA_CURSOR_POS_X__MASK;
+}
+#define MDP4_DMA_CURSOR_POS_Y__MASK                            0xffff0000
+#define MDP4_DMA_CURSOR_POS_Y__SHIFT                           16
+static inline uint32_t MDP4_DMA_CURSOR_POS_Y(uint32_t val)
+{
+       return ((val) << MDP4_DMA_CURSOR_POS_Y__SHIFT) & MDP4_DMA_CURSOR_POS_Y__MASK;
+}
+
+static inline uint32_t REG_MDP4_DMA_CURSOR_BLEND_CONFIG(enum mdp4_dma i0) { return 0x00000060 + __offset_DMA(i0); }
+#define MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN                 0x00000001
+#define MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT__MASK              0x00000006
+#define MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT__SHIFT             1
+static inline uint32_t MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(enum mdp4_cursor_format val)
+{
+       return ((val) << MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT__SHIFT) & MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT__MASK;
+}
+#define MDP4_DMA_CURSOR_BLEND_CONFIG_TRANSP_EN                 0x00000008
+
+static inline uint32_t REG_MDP4_DMA_CURSOR_BLEND_PARAM(enum mdp4_dma i0) { return 0x00000064 + __offset_DMA(i0); }
+
+static inline uint32_t REG_MDP4_DMA_BLEND_TRANS_LOW(enum mdp4_dma i0) { return 0x00000068 + __offset_DMA(i0); }
+
+static inline uint32_t REG_MDP4_DMA_BLEND_TRANS_HIGH(enum mdp4_dma i0) { return 0x0000006c + __offset_DMA(i0); }
+
+static inline uint32_t REG_MDP4_DMA_FETCH_CONFIG(enum mdp4_dma i0) { return 0x00001004 + __offset_DMA(i0); }
+
+static inline uint32_t REG_MDP4_DMA_CSC(enum mdp4_dma i0) { return 0x00003000 + __offset_DMA(i0); }
+
+
+static inline uint32_t REG_MDP4_DMA_CSC_MV(enum mdp4_dma i0, uint32_t i1) { return 0x00003400 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_MV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003400 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_PRE_BV(enum mdp4_dma i0, uint32_t i1) { return 0x00003500 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_PRE_BV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003500 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_POST_BV(enum mdp4_dma i0, uint32_t i1) { return 0x00003580 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_POST_BV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003580 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_PRE_LV(enum mdp4_dma i0, uint32_t i1) { return 0x00003600 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_PRE_LV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003600 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_POST_LV(enum mdp4_dma i0, uint32_t i1) { return 0x00003680 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_DMA_CSC_POST_LV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003680 + __offset_DMA(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE(enum mdp4_pipe i0) { return 0x00020000 + 0x10000*i0; }
+
+static inline uint32_t REG_MDP4_PIPE_SRC_SIZE(enum mdp4_pipe i0) { return 0x00020000 + 0x10000*i0; }
+#define MDP4_PIPE_SRC_SIZE_HEIGHT__MASK                                0xffff0000
+#define MDP4_PIPE_SRC_SIZE_HEIGHT__SHIFT                       16
+static inline uint32_t MDP4_PIPE_SRC_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_SRC_SIZE_HEIGHT__MASK;
+}
+#define MDP4_PIPE_SRC_SIZE_WIDTH__MASK                         0x0000ffff
+#define MDP4_PIPE_SRC_SIZE_WIDTH__SHIFT                                0
+static inline uint32_t MDP4_PIPE_SRC_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_SIZE_WIDTH__SHIFT) & MDP4_PIPE_SRC_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP4_PIPE_SRC_XY(enum mdp4_pipe i0) { return 0x00020004 + 0x10000*i0; }
+#define MDP4_PIPE_SRC_XY_Y__MASK                               0xffff0000
+#define MDP4_PIPE_SRC_XY_Y__SHIFT                              16
+static inline uint32_t MDP4_PIPE_SRC_XY_Y(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_XY_Y__SHIFT) & MDP4_PIPE_SRC_XY_Y__MASK;
+}
+#define MDP4_PIPE_SRC_XY_X__MASK                               0x0000ffff
+#define MDP4_PIPE_SRC_XY_X__SHIFT                              0
+static inline uint32_t MDP4_PIPE_SRC_XY_X(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_XY_X__SHIFT) & MDP4_PIPE_SRC_XY_X__MASK;
+}
+
+static inline uint32_t REG_MDP4_PIPE_DST_SIZE(enum mdp4_pipe i0) { return 0x00020008 + 0x10000*i0; }
+#define MDP4_PIPE_DST_SIZE_HEIGHT__MASK                                0xffff0000
+#define MDP4_PIPE_DST_SIZE_HEIGHT__SHIFT                       16
+static inline uint32_t MDP4_PIPE_DST_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_DST_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_DST_SIZE_HEIGHT__MASK;
+}
+#define MDP4_PIPE_DST_SIZE_WIDTH__MASK                         0x0000ffff
+#define MDP4_PIPE_DST_SIZE_WIDTH__SHIFT                                0
+static inline uint32_t MDP4_PIPE_DST_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_DST_SIZE_WIDTH__SHIFT) & MDP4_PIPE_DST_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP4_PIPE_DST_XY(enum mdp4_pipe i0) { return 0x0002000c + 0x10000*i0; }
+#define MDP4_PIPE_DST_XY_Y__MASK                               0xffff0000
+#define MDP4_PIPE_DST_XY_Y__SHIFT                              16
+static inline uint32_t MDP4_PIPE_DST_XY_Y(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_DST_XY_Y__SHIFT) & MDP4_PIPE_DST_XY_Y__MASK;
+}
+#define MDP4_PIPE_DST_XY_X__MASK                               0x0000ffff
+#define MDP4_PIPE_DST_XY_X__SHIFT                              0
+static inline uint32_t MDP4_PIPE_DST_XY_X(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_DST_XY_X__SHIFT) & MDP4_PIPE_DST_XY_X__MASK;
+}
+
+static inline uint32_t REG_MDP4_PIPE_SRCP0_BASE(enum mdp4_pipe i0) { return 0x00020010 + 0x10000*i0; }
+
+static inline uint32_t REG_MDP4_PIPE_SRCP1_BASE(enum mdp4_pipe i0) { return 0x00020014 + 0x10000*i0; }
+
+static inline uint32_t REG_MDP4_PIPE_SRCP2_BASE(enum mdp4_pipe i0) { return 0x00020018 + 0x10000*i0; }
+
+static inline uint32_t REG_MDP4_PIPE_SRC_STRIDE_A(enum mdp4_pipe i0) { return 0x00020040 + 0x10000*i0; }
+#define MDP4_PIPE_SRC_STRIDE_A_P0__MASK                                0x0000ffff
+#define MDP4_PIPE_SRC_STRIDE_A_P0__SHIFT                       0
+static inline uint32_t MDP4_PIPE_SRC_STRIDE_A_P0(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_STRIDE_A_P0__SHIFT) & MDP4_PIPE_SRC_STRIDE_A_P0__MASK;
+}
+#define MDP4_PIPE_SRC_STRIDE_A_P1__MASK                                0xffff0000
+#define MDP4_PIPE_SRC_STRIDE_A_P1__SHIFT                       16
+static inline uint32_t MDP4_PIPE_SRC_STRIDE_A_P1(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_STRIDE_A_P1__SHIFT) & MDP4_PIPE_SRC_STRIDE_A_P1__MASK;
+}
+
+static inline uint32_t REG_MDP4_PIPE_SRC_STRIDE_B(enum mdp4_pipe i0) { return 0x00020044 + 0x10000*i0; }
+#define MDP4_PIPE_SRC_STRIDE_B_P2__MASK                                0x0000ffff
+#define MDP4_PIPE_SRC_STRIDE_B_P2__SHIFT                       0
+static inline uint32_t MDP4_PIPE_SRC_STRIDE_B_P2(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_STRIDE_B_P2__SHIFT) & MDP4_PIPE_SRC_STRIDE_B_P2__MASK;
+}
+#define MDP4_PIPE_SRC_STRIDE_B_P3__MASK                                0xffff0000
+#define MDP4_PIPE_SRC_STRIDE_B_P3__SHIFT                       16
+static inline uint32_t MDP4_PIPE_SRC_STRIDE_B_P3(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP4_PIPE_SRC_STRIDE_B_P3__MASK;
+}
+
+static inline uint32_t REG_MDP4_PIPE_FRAME_SIZE(enum mdp4_pipe i0) { return 0x00020048 + 0x10000*i0; }
+#define MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK                      0xffff0000
+#define MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT                     16
+static inline uint32_t MDP4_PIPE_FRAME_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK;
+}
+#define MDP4_PIPE_FRAME_SIZE_WIDTH__MASK                       0x0000ffff
+#define MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT                      0
+static inline uint32_t MDP4_PIPE_FRAME_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT) & MDP4_PIPE_FRAME_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP4_PIPE_SRC_FORMAT(enum mdp4_pipe i0) { return 0x00020050 + 0x10000*i0; }
+#define MDP4_PIPE_SRC_FORMAT_G_BPC__MASK                       0x00000003
+#define MDP4_PIPE_SRC_FORMAT_G_BPC__SHIFT                      0
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_G_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP4_PIPE_SRC_FORMAT_G_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_G_BPC__MASK;
+}
+#define MDP4_PIPE_SRC_FORMAT_B_BPC__MASK                       0x0000000c
+#define MDP4_PIPE_SRC_FORMAT_B_BPC__SHIFT                      2
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_B_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP4_PIPE_SRC_FORMAT_B_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_B_BPC__MASK;
+}
+#define MDP4_PIPE_SRC_FORMAT_R_BPC__MASK                       0x00000030
+#define MDP4_PIPE_SRC_FORMAT_R_BPC__SHIFT                      4
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_R_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP4_PIPE_SRC_FORMAT_R_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_R_BPC__MASK;
+}
+#define MDP4_PIPE_SRC_FORMAT_A_BPC__MASK                       0x000000c0
+#define MDP4_PIPE_SRC_FORMAT_A_BPC__SHIFT                      6
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_A_BPC(enum mdp_bpc_alpha val)
+{
+       return ((val) << MDP4_PIPE_SRC_FORMAT_A_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_A_BPC__MASK;
+}
+#define MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE                      0x00000100
+#define MDP4_PIPE_SRC_FORMAT_CPP__MASK                         0x00000600
+#define MDP4_PIPE_SRC_FORMAT_CPP__SHIFT                                9
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_CPP(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_FORMAT_CPP__SHIFT) & MDP4_PIPE_SRC_FORMAT_CPP__MASK;
+}
+#define MDP4_PIPE_SRC_FORMAT_ROTATED_90                                0x00001000
+#define MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT__MASK                        0x00006000
+#define MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT__SHIFT               13
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT__SHIFT) & MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT__MASK;
+}
+#define MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT                      0x00020000
+#define MDP4_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB                  0x00040000
+#define MDP4_PIPE_SRC_FORMAT_SOLID_FILL                                0x00400000
+
+static inline uint32_t REG_MDP4_PIPE_SRC_UNPACK(enum mdp4_pipe i0) { return 0x00020054 + 0x10000*i0; }
+#define MDP4_PIPE_SRC_UNPACK_ELEM0__MASK                       0x000000ff
+#define MDP4_PIPE_SRC_UNPACK_ELEM0__SHIFT                      0
+static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM0(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_UNPACK_ELEM0__SHIFT) & MDP4_PIPE_SRC_UNPACK_ELEM0__MASK;
+}
+#define MDP4_PIPE_SRC_UNPACK_ELEM1__MASK                       0x0000ff00
+#define MDP4_PIPE_SRC_UNPACK_ELEM1__SHIFT                      8
+static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM1(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_UNPACK_ELEM1__SHIFT) & MDP4_PIPE_SRC_UNPACK_ELEM1__MASK;
+}
+#define MDP4_PIPE_SRC_UNPACK_ELEM2__MASK                       0x00ff0000
+#define MDP4_PIPE_SRC_UNPACK_ELEM2__SHIFT                      16
+static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM2(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_UNPACK_ELEM2__SHIFT) & MDP4_PIPE_SRC_UNPACK_ELEM2__MASK;
+}
+#define MDP4_PIPE_SRC_UNPACK_ELEM3__MASK                       0xff000000
+#define MDP4_PIPE_SRC_UNPACK_ELEM3__SHIFT                      24
+static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM3(uint32_t val)
+{
+       return ((val) << MDP4_PIPE_SRC_UNPACK_ELEM3__SHIFT) & MDP4_PIPE_SRC_UNPACK_ELEM3__MASK;
+}
+
+static inline uint32_t REG_MDP4_PIPE_OP_MODE(enum mdp4_pipe i0) { return 0x00020058 + 0x10000*i0; }
+#define MDP4_PIPE_OP_MODE_SCALEX_EN                            0x00000001
+#define MDP4_PIPE_OP_MODE_SCALEY_EN                            0x00000002
+#define MDP4_PIPE_OP_MODE_SRC_YCBCR                            0x00000200
+#define MDP4_PIPE_OP_MODE_DST_YCBCR                            0x00000400
+#define MDP4_PIPE_OP_MODE_CSC_EN                               0x00000800
+#define MDP4_PIPE_OP_MODE_FLIP_LR                              0x00002000
+#define MDP4_PIPE_OP_MODE_FLIP_UD                              0x00004000
+#define MDP4_PIPE_OP_MODE_DITHER_EN                            0x00008000
+#define MDP4_PIPE_OP_MODE_IGC_LUT_EN                           0x00010000
+#define MDP4_PIPE_OP_MODE_DEINT_EN                             0x00040000
+#define MDP4_PIPE_OP_MODE_DEINT_ODD_REF                                0x00080000
+
+static inline uint32_t REG_MDP4_PIPE_PHASEX_STEP(enum mdp4_pipe i0) { return 0x0002005c + 0x10000*i0; }
+
+static inline uint32_t REG_MDP4_PIPE_PHASEY_STEP(enum mdp4_pipe i0) { return 0x00020060 + 0x10000*i0; }
+
+static inline uint32_t REG_MDP4_PIPE_FETCH_CONFIG(enum mdp4_pipe i0) { return 0x00021004 + 0x10000*i0; }
+
+static inline uint32_t REG_MDP4_PIPE_SOLID_COLOR(enum mdp4_pipe i0) { return 0x00021008 + 0x10000*i0; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC(enum mdp4_pipe i0) { return 0x00024000 + 0x10000*i0; }
+
+
+static inline uint32_t REG_MDP4_PIPE_CSC_MV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024400 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_MV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024400 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_PRE_BV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024500 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_PRE_BV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024500 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_POST_BV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024580 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_POST_BV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024580 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_PRE_LV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024600 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_PRE_LV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024600 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_POST_LV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024680 + 0x10000*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP4_PIPE_CSC_POST_LV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024680 + 0x10000*i0 + 0x4*i1; }
+
+#define REG_MDP4_LCDC                                          0x000c0000
+
+#define REG_MDP4_LCDC_ENABLE                                   0x000c0000
+
+#define REG_MDP4_LCDC_HSYNC_CTRL                               0x000c0004
+#define MDP4_LCDC_HSYNC_CTRL_PULSEW__MASK                      0x0000ffff
+#define MDP4_LCDC_HSYNC_CTRL_PULSEW__SHIFT                     0
+static inline uint32_t MDP4_LCDC_HSYNC_CTRL_PULSEW(uint32_t val)
+{
+       return ((val) << MDP4_LCDC_HSYNC_CTRL_PULSEW__SHIFT) & MDP4_LCDC_HSYNC_CTRL_PULSEW__MASK;
+}
+#define MDP4_LCDC_HSYNC_CTRL_PERIOD__MASK                      0xffff0000
+#define MDP4_LCDC_HSYNC_CTRL_PERIOD__SHIFT                     16
+static inline uint32_t MDP4_LCDC_HSYNC_CTRL_PERIOD(uint32_t val)
+{
+       return ((val) << MDP4_LCDC_HSYNC_CTRL_PERIOD__SHIFT) & MDP4_LCDC_HSYNC_CTRL_PERIOD__MASK;
+}
+
+#define REG_MDP4_LCDC_VSYNC_PERIOD                             0x000c0008
+
+#define REG_MDP4_LCDC_VSYNC_LEN                                        0x000c000c
+
+#define REG_MDP4_LCDC_DISPLAY_HCTRL                            0x000c0010
+#define MDP4_LCDC_DISPLAY_HCTRL_START__MASK                    0x0000ffff
+#define MDP4_LCDC_DISPLAY_HCTRL_START__SHIFT                   0
+static inline uint32_t MDP4_LCDC_DISPLAY_HCTRL_START(uint32_t val)
+{
+       return ((val) << MDP4_LCDC_DISPLAY_HCTRL_START__SHIFT) & MDP4_LCDC_DISPLAY_HCTRL_START__MASK;
+}
+#define MDP4_LCDC_DISPLAY_HCTRL_END__MASK                      0xffff0000
+#define MDP4_LCDC_DISPLAY_HCTRL_END__SHIFT                     16
+static inline uint32_t MDP4_LCDC_DISPLAY_HCTRL_END(uint32_t val)
+{
+       return ((val) << MDP4_LCDC_DISPLAY_HCTRL_END__SHIFT) & MDP4_LCDC_DISPLAY_HCTRL_END__MASK;
+}
+
+#define REG_MDP4_LCDC_DISPLAY_VSTART                           0x000c0014
+
+#define REG_MDP4_LCDC_DISPLAY_VEND                             0x000c0018
+
+#define REG_MDP4_LCDC_ACTIVE_HCTL                              0x000c001c
+#define MDP4_LCDC_ACTIVE_HCTL_START__MASK                      0x00007fff
+#define MDP4_LCDC_ACTIVE_HCTL_START__SHIFT                     0
+static inline uint32_t MDP4_LCDC_ACTIVE_HCTL_START(uint32_t val)
+{
+       return ((val) << MDP4_LCDC_ACTIVE_HCTL_START__SHIFT) & MDP4_LCDC_ACTIVE_HCTL_START__MASK;
+}
+#define MDP4_LCDC_ACTIVE_HCTL_END__MASK                                0x7fff0000
+#define MDP4_LCDC_ACTIVE_HCTL_END__SHIFT                       16
+static inline uint32_t MDP4_LCDC_ACTIVE_HCTL_END(uint32_t val)
+{
+       return ((val) << MDP4_LCDC_ACTIVE_HCTL_END__SHIFT) & MDP4_LCDC_ACTIVE_HCTL_END__MASK;
+}
+#define MDP4_LCDC_ACTIVE_HCTL_ACTIVE_START_X                   0x80000000
+
+#define REG_MDP4_LCDC_ACTIVE_VSTART                            0x000c0020
+
+#define REG_MDP4_LCDC_ACTIVE_VEND                              0x000c0024
+
+#define REG_MDP4_LCDC_BORDER_CLR                               0x000c0028
+
+#define REG_MDP4_LCDC_UNDERFLOW_CLR                            0x000c002c
+#define MDP4_LCDC_UNDERFLOW_CLR_COLOR__MASK                    0x00ffffff
+#define MDP4_LCDC_UNDERFLOW_CLR_COLOR__SHIFT                   0
+static inline uint32_t MDP4_LCDC_UNDERFLOW_CLR_COLOR(uint32_t val)
+{
+       return ((val) << MDP4_LCDC_UNDERFLOW_CLR_COLOR__SHIFT) & MDP4_LCDC_UNDERFLOW_CLR_COLOR__MASK;
+}
+#define MDP4_LCDC_UNDERFLOW_CLR_ENABLE_RECOVERY                        0x80000000
+
+#define REG_MDP4_LCDC_HSYNC_SKEW                               0x000c0030
+
+#define REG_MDP4_LCDC_TEST_CNTL                                        0x000c0034
+
+#define REG_MDP4_LCDC_CTRL_POLARITY                            0x000c0038
+#define MDP4_LCDC_CTRL_POLARITY_HSYNC_LOW                      0x00000001
+#define MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW                      0x00000002
+#define MDP4_LCDC_CTRL_POLARITY_DATA_EN_LOW                    0x00000004
+
+#define REG_MDP4_DTV                                           0x000d0000
+
+#define REG_MDP4_DTV_ENABLE                                    0x000d0000
+
+#define REG_MDP4_DTV_HSYNC_CTRL                                        0x000d0004
+#define MDP4_DTV_HSYNC_CTRL_PULSEW__MASK                       0x0000ffff
+#define MDP4_DTV_HSYNC_CTRL_PULSEW__SHIFT                      0
+static inline uint32_t MDP4_DTV_HSYNC_CTRL_PULSEW(uint32_t val)
+{
+       return ((val) << MDP4_DTV_HSYNC_CTRL_PULSEW__SHIFT) & MDP4_DTV_HSYNC_CTRL_PULSEW__MASK;
+}
+#define MDP4_DTV_HSYNC_CTRL_PERIOD__MASK                       0xffff0000
+#define MDP4_DTV_HSYNC_CTRL_PERIOD__SHIFT                      16
+static inline uint32_t MDP4_DTV_HSYNC_CTRL_PERIOD(uint32_t val)
+{
+       return ((val) << MDP4_DTV_HSYNC_CTRL_PERIOD__SHIFT) & MDP4_DTV_HSYNC_CTRL_PERIOD__MASK;
+}
+
+#define REG_MDP4_DTV_VSYNC_PERIOD                              0x000d0008
+
+#define REG_MDP4_DTV_VSYNC_LEN                                 0x000d000c
+
+#define REG_MDP4_DTV_DISPLAY_HCTRL                             0x000d0018
+#define MDP4_DTV_DISPLAY_HCTRL_START__MASK                     0x0000ffff
+#define MDP4_DTV_DISPLAY_HCTRL_START__SHIFT                    0
+static inline uint32_t MDP4_DTV_DISPLAY_HCTRL_START(uint32_t val)
+{
+       return ((val) << MDP4_DTV_DISPLAY_HCTRL_START__SHIFT) & MDP4_DTV_DISPLAY_HCTRL_START__MASK;
+}
+#define MDP4_DTV_DISPLAY_HCTRL_END__MASK                       0xffff0000
+#define MDP4_DTV_DISPLAY_HCTRL_END__SHIFT                      16
+static inline uint32_t MDP4_DTV_DISPLAY_HCTRL_END(uint32_t val)
+{
+       return ((val) << MDP4_DTV_DISPLAY_HCTRL_END__SHIFT) & MDP4_DTV_DISPLAY_HCTRL_END__MASK;
+}
+
+#define REG_MDP4_DTV_DISPLAY_VSTART                            0x000d001c
+
+#define REG_MDP4_DTV_DISPLAY_VEND                              0x000d0020
+
+#define REG_MDP4_DTV_ACTIVE_HCTL                               0x000d002c
+#define MDP4_DTV_ACTIVE_HCTL_START__MASK                       0x00007fff
+#define MDP4_DTV_ACTIVE_HCTL_START__SHIFT                      0
+static inline uint32_t MDP4_DTV_ACTIVE_HCTL_START(uint32_t val)
+{
+       return ((val) << MDP4_DTV_ACTIVE_HCTL_START__SHIFT) & MDP4_DTV_ACTIVE_HCTL_START__MASK;
+}
+#define MDP4_DTV_ACTIVE_HCTL_END__MASK                         0x7fff0000
+#define MDP4_DTV_ACTIVE_HCTL_END__SHIFT                                16
+static inline uint32_t MDP4_DTV_ACTIVE_HCTL_END(uint32_t val)
+{
+       return ((val) << MDP4_DTV_ACTIVE_HCTL_END__SHIFT) & MDP4_DTV_ACTIVE_HCTL_END__MASK;
+}
+#define MDP4_DTV_ACTIVE_HCTL_ACTIVE_START_X                    0x80000000
+
+#define REG_MDP4_DTV_ACTIVE_VSTART                             0x000d0030
+
+#define REG_MDP4_DTV_ACTIVE_VEND                               0x000d0038
+
+#define REG_MDP4_DTV_BORDER_CLR                                        0x000d0040
+
+#define REG_MDP4_DTV_UNDERFLOW_CLR                             0x000d0044
+#define MDP4_DTV_UNDERFLOW_CLR_COLOR__MASK                     0x00ffffff
+#define MDP4_DTV_UNDERFLOW_CLR_COLOR__SHIFT                    0
+static inline uint32_t MDP4_DTV_UNDERFLOW_CLR_COLOR(uint32_t val)
+{
+       return ((val) << MDP4_DTV_UNDERFLOW_CLR_COLOR__SHIFT) & MDP4_DTV_UNDERFLOW_CLR_COLOR__MASK;
+}
+#define MDP4_DTV_UNDERFLOW_CLR_ENABLE_RECOVERY                 0x80000000
+
+#define REG_MDP4_DTV_HSYNC_SKEW                                        0x000d0048
+
+#define REG_MDP4_DTV_TEST_CNTL                                 0x000d004c
+
+#define REG_MDP4_DTV_CTRL_POLARITY                             0x000d0050
+#define MDP4_DTV_CTRL_POLARITY_HSYNC_LOW                       0x00000001
+#define MDP4_DTV_CTRL_POLARITY_VSYNC_LOW                       0x00000002
+#define MDP4_DTV_CTRL_POLARITY_DATA_EN_LOW                     0x00000004
+
+#define REG_MDP4_DSI                                           0x000e0000
+
+#define REG_MDP4_DSI_ENABLE                                    0x000e0000
+
+#define REG_MDP4_DSI_HSYNC_CTRL                                        0x000e0004
+#define MDP4_DSI_HSYNC_CTRL_PULSEW__MASK                       0x0000ffff
+#define MDP4_DSI_HSYNC_CTRL_PULSEW__SHIFT                      0
+static inline uint32_t MDP4_DSI_HSYNC_CTRL_PULSEW(uint32_t val)
+{
+       return ((val) << MDP4_DSI_HSYNC_CTRL_PULSEW__SHIFT) & MDP4_DSI_HSYNC_CTRL_PULSEW__MASK;
+}
+#define MDP4_DSI_HSYNC_CTRL_PERIOD__MASK                       0xffff0000
+#define MDP4_DSI_HSYNC_CTRL_PERIOD__SHIFT                      16
+static inline uint32_t MDP4_DSI_HSYNC_CTRL_PERIOD(uint32_t val)
+{
+       return ((val) << MDP4_DSI_HSYNC_CTRL_PERIOD__SHIFT) & MDP4_DSI_HSYNC_CTRL_PERIOD__MASK;
+}
+
+#define REG_MDP4_DSI_VSYNC_PERIOD                              0x000e0008
+
+#define REG_MDP4_DSI_VSYNC_LEN                                 0x000e000c
+
+#define REG_MDP4_DSI_DISPLAY_HCTRL                             0x000e0010
+#define MDP4_DSI_DISPLAY_HCTRL_START__MASK                     0x0000ffff
+#define MDP4_DSI_DISPLAY_HCTRL_START__SHIFT                    0
+static inline uint32_t MDP4_DSI_DISPLAY_HCTRL_START(uint32_t val)
+{
+       return ((val) << MDP4_DSI_DISPLAY_HCTRL_START__SHIFT) & MDP4_DSI_DISPLAY_HCTRL_START__MASK;
+}
+#define MDP4_DSI_DISPLAY_HCTRL_END__MASK                       0xffff0000
+#define MDP4_DSI_DISPLAY_HCTRL_END__SHIFT                      16
+static inline uint32_t MDP4_DSI_DISPLAY_HCTRL_END(uint32_t val)
+{
+       return ((val) << MDP4_DSI_DISPLAY_HCTRL_END__SHIFT) & MDP4_DSI_DISPLAY_HCTRL_END__MASK;
+}
+
+#define REG_MDP4_DSI_DISPLAY_VSTART                            0x000e0014
+
+#define REG_MDP4_DSI_DISPLAY_VEND                              0x000e0018
+
+#define REG_MDP4_DSI_ACTIVE_HCTL                               0x000e001c
+#define MDP4_DSI_ACTIVE_HCTL_START__MASK                       0x00007fff
+#define MDP4_DSI_ACTIVE_HCTL_START__SHIFT                      0
+static inline uint32_t MDP4_DSI_ACTIVE_HCTL_START(uint32_t val)
+{
+       return ((val) << MDP4_DSI_ACTIVE_HCTL_START__SHIFT) & MDP4_DSI_ACTIVE_HCTL_START__MASK;
+}
+#define MDP4_DSI_ACTIVE_HCTL_END__MASK                         0x7fff0000
+#define MDP4_DSI_ACTIVE_HCTL_END__SHIFT                                16
+static inline uint32_t MDP4_DSI_ACTIVE_HCTL_END(uint32_t val)
+{
+       return ((val) << MDP4_DSI_ACTIVE_HCTL_END__SHIFT) & MDP4_DSI_ACTIVE_HCTL_END__MASK;
+}
+#define MDP4_DSI_ACTIVE_HCTL_ACTIVE_START_X                    0x80000000
+
+#define REG_MDP4_DSI_ACTIVE_VSTART                             0x000e0020
+
+#define REG_MDP4_DSI_ACTIVE_VEND                               0x000e0024
+
+#define REG_MDP4_DSI_BORDER_CLR                                        0x000e0028
+
+#define REG_MDP4_DSI_UNDERFLOW_CLR                             0x000e002c
+#define MDP4_DSI_UNDERFLOW_CLR_COLOR__MASK                     0x00ffffff
+#define MDP4_DSI_UNDERFLOW_CLR_COLOR__SHIFT                    0
+static inline uint32_t MDP4_DSI_UNDERFLOW_CLR_COLOR(uint32_t val)
+{
+       return ((val) << MDP4_DSI_UNDERFLOW_CLR_COLOR__SHIFT) & MDP4_DSI_UNDERFLOW_CLR_COLOR__MASK;
+}
+#define MDP4_DSI_UNDERFLOW_CLR_ENABLE_RECOVERY                 0x80000000
+
+#define REG_MDP4_DSI_HSYNC_SKEW                                        0x000e0030
+
+#define REG_MDP4_DSI_TEST_CNTL                                 0x000e0034
+
+#define REG_MDP4_DSI_CTRL_POLARITY                             0x000e0038
+#define MDP4_DSI_CTRL_POLARITY_HSYNC_LOW                       0x00000001
+#define MDP4_DSI_CTRL_POLARITY_VSYNC_LOW                       0x00000002
+#define MDP4_DSI_CTRL_POLARITY_DATA_EN_LOW                     0x00000004
+
+
+#endif /* MDP4_XML */
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
new file mode 100644 (file)
index 0000000..1964f4f
--- /dev/null
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "mdp4_kms.h"
+
+#include <drm/drm_mode.h>
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "drm_flip_work.h"
+
+struct mdp4_crtc {
+       struct drm_crtc base;
+       char name[8];
+       struct drm_plane *plane;
+       struct drm_plane *planes[8];
+       int id;
+       int ovlp;
+       enum mdp4_dma dma;
+       bool enabled;
+
+       /* which mixer/encoder we route output to: */
+       int mixer;
+
+       struct {
+               spinlock_t lock;
+               bool stale;
+               uint32_t width, height;
+
+               /* next cursor to scan-out: */
+               uint32_t next_iova;
+               struct drm_gem_object *next_bo;
+
+               /* current cursor being scanned out: */
+               struct drm_gem_object *scanout_bo;
+       } cursor;
+
+
+       /* if there is a pending flip, these will be non-null: */
+       struct drm_pending_vblank_event *event;
+       struct msm_fence_cb pageflip_cb;
+
+#define PENDING_CURSOR 0x1
+#define PENDING_FLIP   0x2
+       atomic_t pending;
+
+       /* the fb that we currently hold a scanout ref to: */
+       struct drm_framebuffer *fb;
+
+       /* for unref'ing framebuffers after scanout completes: */
+       struct drm_flip_work unref_fb_work;
+
+       /* for unref'ing cursor bo's after scanout completes: */
+       struct drm_flip_work unref_cursor_work;
+
+       struct mdp_irq vblank;
+       struct mdp_irq err;
+};
+#define to_mdp4_crtc(x) container_of(x, struct mdp4_crtc, base)
+
+static struct mdp4_kms *get_kms(struct drm_crtc *crtc)
+{
+       struct msm_drm_private *priv = crtc->dev->dev_private;
+       return to_mdp4_kms(to_mdp_kms(priv->kms));
+}
+
+static void update_fb(struct drm_crtc *crtc, bool async,
+               struct drm_framebuffer *new_fb)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct drm_framebuffer *old_fb = mdp4_crtc->fb;
+
+       if (old_fb)
+               drm_flip_work_queue(&mdp4_crtc->unref_fb_work, old_fb);
+
+       /* grab reference to incoming scanout fb: */
+       drm_framebuffer_reference(new_fb);
+       mdp4_crtc->base.fb = new_fb;
+       mdp4_crtc->fb = new_fb;
+
+       if (!async) {
+               /* enable vblank to pick up the old_fb */
+               mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank);
+       }
+}
+
+/* if file!=NULL, this is preclose potential cancel-flip path */
+static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_pending_vblank_event *event;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       event = mdp4_crtc->event;
+       if (event) {
+               /* if regular vblank case (!file) or if cancel-flip from
+                * preclose on file that requested flip, then send the
+                * event:
+                */
+               if (!file || (event->base.file_priv == file)) {
+                       mdp4_crtc->event = NULL;
+                       drm_send_vblank_event(dev, mdp4_crtc->id, event);
+               }
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static void crtc_flush(struct drm_crtc *crtc)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       uint32_t i, flush = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
+               struct drm_plane *plane = mdp4_crtc->planes[i];
+               if (plane) {
+                       enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
+                       flush |= pipe2flush(pipe_id);
+               }
+       }
+       flush |= ovlp2flush(mdp4_crtc->ovlp);
+
+       DBG("%s: flush=%08x", mdp4_crtc->name, flush);
+
+       mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
+}
+
+static void request_pending(struct drm_crtc *crtc, uint32_t pending)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+
+       atomic_or(pending, &mdp4_crtc->pending);
+       mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank);
+}
+
+static void pageflip_cb(struct msm_fence_cb *cb)
+{
+       struct mdp4_crtc *mdp4_crtc =
+               container_of(cb, struct mdp4_crtc, pageflip_cb);
+       struct drm_crtc *crtc = &mdp4_crtc->base;
+       struct drm_framebuffer *fb = crtc->fb;
+
+       if (!fb)
+               return;
+
+       mdp4_plane_set_scanout(mdp4_crtc->plane, fb);
+       crtc_flush(crtc);
+
+       /* enable vblank to complete flip: */
+       request_pending(crtc, PENDING_FLIP);
+}
+
+static void unref_fb_worker(struct drm_flip_work *work, void *val)
+{
+       struct mdp4_crtc *mdp4_crtc =
+               container_of(work, struct mdp4_crtc, unref_fb_work);
+       struct drm_device *dev = mdp4_crtc->base.dev;
+
+       mutex_lock(&dev->mode_config.mutex);
+       drm_framebuffer_unreference(val);
+       mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void unref_cursor_worker(struct drm_flip_work *work, void *val)
+{
+       struct mdp4_crtc *mdp4_crtc =
+               container_of(work, struct mdp4_crtc, unref_cursor_work);
+       struct mdp4_kms *mdp4_kms = get_kms(&mdp4_crtc->base);
+
+       msm_gem_put_iova(val, mdp4_kms->id);
+       drm_gem_object_unreference_unlocked(val);
+}
+
+static void mdp4_crtc_destroy(struct drm_crtc *crtc)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+
+       mdp4_crtc->plane->funcs->destroy(mdp4_crtc->plane);
+
+       drm_crtc_cleanup(crtc);
+       drm_flip_work_cleanup(&mdp4_crtc->unref_fb_work);
+       drm_flip_work_cleanup(&mdp4_crtc->unref_cursor_work);
+
+       kfree(mdp4_crtc);
+}
+
+static void mdp4_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       bool enabled = (mode == DRM_MODE_DPMS_ON);
+
+       DBG("%s: mode=%d", mdp4_crtc->name, mode);
+
+       if (enabled != mdp4_crtc->enabled) {
+               if (enabled) {
+                       mdp4_enable(mdp4_kms);
+                       mdp_irq_register(&mdp4_kms->base, &mdp4_crtc->err);
+               } else {
+                       mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err);
+                       mdp4_disable(mdp4_kms);
+               }
+               mdp4_crtc->enabled = enabled;
+       }
+}
+
+static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc,
+               const struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void blend_setup(struct drm_crtc *crtc)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       int i, ovlp = mdp4_crtc->ovlp;
+       uint32_t mixer_cfg = 0;
+       static const enum mdp_mixer_stage_id stages[] = {
+                       STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3,
+       };
+       /* statically (for now) map planes to mixer stage (z-order): */
+       static const int idxs[] = {
+                       [VG1]  = 1,
+                       [VG2]  = 2,
+                       [RGB1] = 0,
+                       [RGB2] = 0,
+                       [RGB3] = 0,
+                       [VG3]  = 3,
+                       [VG4]  = 4,
+
+       };
+       bool alpha[4]= { false, false, false, false };
+
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0);
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0);
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0);
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0);
+
+       /* TODO single register for all CRTCs, so this won't work properly
+        * when multiple CRTCs are active..
+        */
+       for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
+               struct drm_plane *plane = mdp4_crtc->planes[i];
+               if (plane) {
+                       enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
+                       int idx = idxs[pipe_id];
+                       if (idx > 0) {
+                               const struct mdp_format *format =
+                                       to_mdp_format(msm_framebuffer_format(plane->fb));
+                               alpha[idx-1] = format->alpha_enable;
+                       }
+                       mixer_cfg |= mixercfg(mdp4_crtc->mixer, pipe_id, stages[idx]);
+               }
+       }
+
+       /* this shouldn't happen.. and seems to cause underflow: */
+       WARN_ON(!mixer_cfg);
+
+       for (i = 0; i < 4; i++) {
+               uint32_t op;
+
+               if (alpha[i]) {
+                       op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_PIXEL) |
+                                       MDP4_OVLP_STAGE_OP_BG_ALPHA(FG_PIXEL) |
+                                       MDP4_OVLP_STAGE_OP_BG_INV_ALPHA;
+               } else {
+                       op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) |
+                                       MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST);
+               }
+
+               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0xff);
+               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0x00);
+               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), op);
+               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 1);
+               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp, i), 0);
+               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp, i), 0);
+               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp, i), 0);
+               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0);
+       }
+
+       mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
+}
+
+static int mdp4_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 mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       enum mdp4_dma dma = mdp4_crtc->dma;
+       int ret, ovlp = mdp4_crtc->ovlp;
+
+       mode = adjusted_mode;
+
+       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+                       mdp4_crtc->name, mode->base.id, mode->name,
+                       mode->vrefresh, mode->clock,
+                       mode->hdisplay, mode->hsync_start,
+                       mode->hsync_end, mode->htotal,
+                       mode->vdisplay, mode->vsync_start,
+                       mode->vsync_end, mode->vtotal,
+                       mode->type, mode->flags);
+
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_SIZE(dma),
+                       MDP4_DMA_SRC_SIZE_WIDTH(mode->hdisplay) |
+                       MDP4_DMA_SRC_SIZE_HEIGHT(mode->vdisplay));
+
+       /* take data from pipe: */
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0);
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma),
+                       crtc->fb->pitches[0]);
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma),
+                       MDP4_DMA_DST_SIZE_WIDTH(0) |
+                       MDP4_DMA_DST_SIZE_HEIGHT(0));
+
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_BASE(ovlp), 0);
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_SIZE(ovlp),
+                       MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) |
+                       MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay));
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp),
+                       crtc->fb->pitches[0]);
+
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
+
+       update_fb(crtc, false, crtc->fb);
+
+       ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       x << 16, y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16);
+       if (ret) {
+               dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
+                               mdp4_crtc->name, ret);
+               return ret;
+       }
+
+       if (dma == DMA_E) {
+               mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(0), 0x00ff0000);
+               mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(1), 0x00ff0000);
+               mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
+       }
+
+       return 0;
+}
+
+static void mdp4_crtc_prepare(struct drm_crtc *crtc)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       DBG("%s", mdp4_crtc->name);
+       /* make sure we hold a ref to mdp clks while setting up mode: */
+       mdp4_enable(get_kms(crtc));
+       mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void mdp4_crtc_commit(struct drm_crtc *crtc)
+{
+       mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+       crtc_flush(crtc);
+       /* drop the ref to mdp clk's that we got in prepare: */
+       mdp4_disable(get_kms(crtc));
+}
+
+static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+               struct drm_framebuffer *old_fb)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct drm_plane *plane = mdp4_crtc->plane;
+       struct drm_display_mode *mode = &crtc->mode;
+
+       update_fb(crtc, false, crtc->fb);
+
+       return mdp4_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 mdp4_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+static int mdp4_crtc_page_flip(struct drm_crtc *crtc,
+               struct drm_framebuffer *new_fb,
+               struct drm_pending_vblank_event *event,
+               uint32_t page_flip_flags)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_gem_object *obj;
+       unsigned long flags;
+
+       if (mdp4_crtc->event) {
+               dev_err(dev->dev, "already pending flip!\n");
+               return -EBUSY;
+       }
+
+       obj = msm_framebuffer_bo(new_fb, 0);
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       mdp4_crtc->event = event;
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       update_fb(crtc, true, new_fb);
+
+       return msm_gem_queue_inactive_cb(obj, &mdp4_crtc->pageflip_cb);
+}
+
+static int mdp4_crtc_set_property(struct drm_crtc *crtc,
+               struct drm_property *property, uint64_t val)
+{
+       // XXX
+       return -EINVAL;
+}
+
+#define CURSOR_WIDTH 64
+#define CURSOR_HEIGHT 64
+
+/* called from IRQ to update cursor related registers (if needed).  The
+ * cursor registers, other than x/y position, appear not to be double
+ * buffered, and changing them other than from vblank seems to trigger
+ * underflow.
+ */
+static void update_cursor(struct drm_crtc *crtc)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       enum mdp4_dma dma = mdp4_crtc->dma;
+       unsigned long flags;
+
+       spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags);
+       if (mdp4_crtc->cursor.stale) {
+               struct mdp4_kms *mdp4_kms = get_kms(crtc);
+               struct drm_gem_object *next_bo = mdp4_crtc->cursor.next_bo;
+               struct drm_gem_object *prev_bo = mdp4_crtc->cursor.scanout_bo;
+               uint32_t iova = mdp4_crtc->cursor.next_iova;
+
+               if (next_bo) {
+                       /* take a obj ref + iova ref when we start scanning out: */
+                       drm_gem_object_reference(next_bo);
+                       msm_gem_get_iova_locked(next_bo, mdp4_kms->id, &iova);
+
+                       /* enable cursor: */
+                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_SIZE(dma),
+                                       MDP4_DMA_CURSOR_SIZE_WIDTH(mdp4_crtc->cursor.width) |
+                                       MDP4_DMA_CURSOR_SIZE_HEIGHT(mdp4_crtc->cursor.height));
+                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma), iova);
+                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma),
+                                       MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB) |
+                                       MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN);
+               } else {
+                       /* disable cursor: */
+                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma), 0);
+                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma),
+                                       MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB));
+               }
+
+               /* and drop the iova ref + obj rev when done scanning out: */
+               if (prev_bo)
+                       drm_flip_work_queue(&mdp4_crtc->unref_cursor_work, prev_bo);
+
+               mdp4_crtc->cursor.scanout_bo = next_bo;
+               mdp4_crtc->cursor.stale = false;
+       }
+       spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags);
+}
+
+static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
+               struct drm_file *file_priv, uint32_t handle,
+               uint32_t width, uint32_t height)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_gem_object *cursor_bo, *old_bo;
+       unsigned long flags;
+       uint32_t iova;
+       int ret;
+
+       if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
+               dev_err(dev->dev, "bad cursor size: %dx%d\n", width, height);
+               return -EINVAL;
+       }
+
+       if (handle) {
+               cursor_bo = drm_gem_object_lookup(dev, file_priv, handle);
+               if (!cursor_bo)
+                       return -ENOENT;
+       } else {
+               cursor_bo = NULL;
+       }
+
+       if (cursor_bo) {
+               ret = msm_gem_get_iova(cursor_bo, mdp4_kms->id, &iova);
+               if (ret)
+                       goto fail;
+       } else {
+               iova = 0;
+       }
+
+       spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags);
+       old_bo = mdp4_crtc->cursor.next_bo;
+       mdp4_crtc->cursor.next_bo   = cursor_bo;
+       mdp4_crtc->cursor.next_iova = iova;
+       mdp4_crtc->cursor.width     = width;
+       mdp4_crtc->cursor.height    = height;
+       mdp4_crtc->cursor.stale     = true;
+       spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags);
+
+       if (old_bo) {
+               /* drop our previous reference: */
+               msm_gem_put_iova(old_bo, mdp4_kms->id);
+               drm_gem_object_unreference_unlocked(old_bo);
+       }
+
+       request_pending(crtc, PENDING_CURSOR);
+
+       return 0;
+
+fail:
+       drm_gem_object_unreference_unlocked(cursor_bo);
+       return ret;
+}
+
+static int mdp4_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       enum mdp4_dma dma = mdp4_crtc->dma;
+
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_POS(dma),
+                       MDP4_DMA_CURSOR_POS_X(x) |
+                       MDP4_DMA_CURSOR_POS_Y(y));
+
+       return 0;
+}
+
+static const struct drm_crtc_funcs mdp4_crtc_funcs = {
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = mdp4_crtc_destroy,
+       .page_flip = mdp4_crtc_page_flip,
+       .set_property = mdp4_crtc_set_property,
+       .cursor_set = mdp4_crtc_cursor_set,
+       .cursor_move = mdp4_crtc_cursor_move,
+};
+
+static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = {
+       .dpms = mdp4_crtc_dpms,
+       .mode_fixup = mdp4_crtc_mode_fixup,
+       .mode_set = mdp4_crtc_mode_set,
+       .prepare = mdp4_crtc_prepare,
+       .commit = mdp4_crtc_commit,
+       .mode_set_base = mdp4_crtc_mode_set_base,
+       .load_lut = mdp4_crtc_load_lut,
+};
+
+static void mdp4_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       struct mdp4_crtc *mdp4_crtc = container_of(irq, struct mdp4_crtc, vblank);
+       struct drm_crtc *crtc = &mdp4_crtc->base;
+       struct msm_drm_private *priv = crtc->dev->dev_private;
+       unsigned pending;
+
+       mdp_irq_unregister(&get_kms(crtc)->base, &mdp4_crtc->vblank);
+
+       pending = atomic_xchg(&mdp4_crtc->pending, 0);
+
+       if (pending & PENDING_FLIP) {
+               complete_flip(crtc, NULL);
+               drm_flip_work_commit(&mdp4_crtc->unref_fb_work, priv->wq);
+       }
+
+       if (pending & PENDING_CURSOR) {
+               update_cursor(crtc);
+               drm_flip_work_commit(&mdp4_crtc->unref_cursor_work, priv->wq);
+       }
+}
+
+static void mdp4_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       struct mdp4_crtc *mdp4_crtc = container_of(irq, struct mdp4_crtc, err);
+       struct drm_crtc *crtc = &mdp4_crtc->base;
+       DBG("%s: error: %08x", mdp4_crtc->name, irqstatus);
+       crtc_flush(crtc);
+}
+
+uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       return mdp4_crtc->vblank.irqmask;
+}
+
+void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+       DBG("cancel: %p", file);
+       complete_flip(crtc, file);
+}
+
+/* set dma config, ie. the format the encoder wants. */
+void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_CONFIG(mdp4_crtc->dma), config);
+}
+
+/* set interface for routing crtc->encoder: */
+void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       uint32_t intf_sel;
+
+       intf_sel = mdp4_read(mdp4_kms, REG_MDP4_DISP_INTF_SEL);
+
+       switch (mdp4_crtc->dma) {
+       case DMA_P:
+               intf_sel &= ~MDP4_DISP_INTF_SEL_PRIM__MASK;
+               intf_sel |= MDP4_DISP_INTF_SEL_PRIM(intf);
+               break;
+       case DMA_S:
+               intf_sel &= ~MDP4_DISP_INTF_SEL_SEC__MASK;
+               intf_sel |= MDP4_DISP_INTF_SEL_SEC(intf);
+               break;
+       case DMA_E:
+               intf_sel &= ~MDP4_DISP_INTF_SEL_EXT__MASK;
+               intf_sel |= MDP4_DISP_INTF_SEL_EXT(intf);
+               break;
+       }
+
+       if (intf == INTF_DSI_VIDEO) {
+               intf_sel &= ~MDP4_DISP_INTF_SEL_DSI_CMD;
+               intf_sel |= MDP4_DISP_INTF_SEL_DSI_VIDEO;
+               mdp4_crtc->mixer = 0;
+       } else if (intf == INTF_DSI_CMD) {
+               intf_sel &= ~MDP4_DISP_INTF_SEL_DSI_VIDEO;
+               intf_sel |= MDP4_DISP_INTF_SEL_DSI_CMD;
+               mdp4_crtc->mixer = 0;
+       } else if (intf == INTF_LCDC_DTV){
+               mdp4_crtc->mixer = 1;
+       }
+
+       blend_setup(crtc);
+
+       DBG("%s: intf_sel=%08x", mdp4_crtc->name, intf_sel);
+
+       mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
+}
+
+static void set_attach(struct drm_crtc *crtc, enum mdp4_pipe pipe_id,
+               struct drm_plane *plane)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+
+       BUG_ON(pipe_id >= ARRAY_SIZE(mdp4_crtc->planes));
+
+       if (mdp4_crtc->planes[pipe_id] == plane)
+               return;
+
+       mdp4_crtc->planes[pipe_id] = plane;
+       blend_setup(crtc);
+       if (mdp4_crtc->enabled && (plane != mdp4_crtc->plane))
+               crtc_flush(crtc);
+}
+
+void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
+{
+       set_attach(crtc, mdp4_plane_pipe(plane), plane);
+}
+
+void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
+{
+       set_attach(crtc, mdp4_plane_pipe(plane), NULL);
+}
+
+static const char *dma_names[] = {
+               "DMA_P", "DMA_S", "DMA_E",
+};
+
+/* initialize crtc */
+struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
+               struct drm_plane *plane, int id, int ovlp_id,
+               enum mdp4_dma dma_id)
+{
+       struct drm_crtc *crtc = NULL;
+       struct mdp4_crtc *mdp4_crtc;
+       int ret;
+
+       mdp4_crtc = kzalloc(sizeof(*mdp4_crtc), GFP_KERNEL);
+       if (!mdp4_crtc) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       crtc = &mdp4_crtc->base;
+
+       mdp4_crtc->plane = plane;
+
+       mdp4_crtc->ovlp = ovlp_id;
+       mdp4_crtc->dma = dma_id;
+
+       mdp4_crtc->vblank.irqmask = dma2irq(mdp4_crtc->dma);
+       mdp4_crtc->vblank.irq = mdp4_crtc_vblank_irq;
+
+       mdp4_crtc->err.irqmask = dma2err(mdp4_crtc->dma);
+       mdp4_crtc->err.irq = mdp4_crtc_err_irq;
+
+       snprintf(mdp4_crtc->name, sizeof(mdp4_crtc->name), "%s:%d",
+                       dma_names[dma_id], ovlp_id);
+
+       spin_lock_init(&mdp4_crtc->cursor.lock);
+
+       ret = drm_flip_work_init(&mdp4_crtc->unref_fb_work, 16,
+                       "unref fb", unref_fb_worker);
+       if (ret)
+               goto fail;
+
+       ret = drm_flip_work_init(&mdp4_crtc->unref_cursor_work, 64,
+                       "unref cursor", unref_cursor_worker);
+
+       INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
+
+       drm_crtc_init(dev, crtc, &mdp4_crtc_funcs);
+       drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);
+
+       mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base);
+
+       return crtc;
+
+fail:
+       if (crtc)
+               mdp4_crtc_destroy(crtc);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
new file mode 100644 (file)
index 0000000..067ed03
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "mdp4_kms.h"
+
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+
+struct mdp4_dtv_encoder {
+       struct drm_encoder base;
+       struct clk *src_clk;
+       struct clk *hdmi_clk;
+       struct clk *mdp_clk;
+       unsigned long int pixclock;
+       bool enabled;
+       uint32_t bsc;
+};
+#define to_mdp4_dtv_encoder(x) container_of(x, struct mdp4_dtv_encoder, base)
+
+static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
+{
+       struct msm_drm_private *priv = encoder->dev->dev_private;
+       return to_mdp4_kms(to_mdp_kms(priv->kms));
+}
+
+#ifdef CONFIG_MSM_BUS_SCALING
+#include <mach/board.h>
+/* not ironically named at all.. no, really.. */
+static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder)
+{
+       struct drm_device *dev = mdp4_dtv_encoder->base.dev;
+       struct lcdc_platform_data *dtv_pdata = mdp4_find_pdata("dtv.0");
+
+       if (!dtv_pdata) {
+               dev_err(dev->dev, "could not find dtv pdata\n");
+               return;
+       }
+
+       if (dtv_pdata->bus_scale_table) {
+               mdp4_dtv_encoder->bsc = msm_bus_scale_register_client(
+                               dtv_pdata->bus_scale_table);
+               DBG("bus scale client: %08x", mdp4_dtv_encoder->bsc);
+               DBG("lcdc_power_save: %p", dtv_pdata->lcdc_power_save);
+               if (dtv_pdata->lcdc_power_save)
+                       dtv_pdata->lcdc_power_save(1);
+       }
+}
+
+static void bs_fini(struct mdp4_dtv_encoder *mdp4_dtv_encoder)
+{
+       if (mdp4_dtv_encoder->bsc) {
+               msm_bus_scale_unregister_client(mdp4_dtv_encoder->bsc);
+               mdp4_dtv_encoder->bsc = 0;
+       }
+}
+
+static void bs_set(struct mdp4_dtv_encoder *mdp4_dtv_encoder, int idx)
+{
+       if (mdp4_dtv_encoder->bsc) {
+               DBG("set bus scaling: %d", idx);
+               msm_bus_scale_client_update_request(mdp4_dtv_encoder->bsc, idx);
+       }
+}
+#else
+static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder) {}
+static void bs_fini(struct mdp4_dtv_encoder *mdp4_dtv_encoder) {}
+static void bs_set(struct mdp4_dtv_encoder *mdp4_dtv_encoder, int idx) {}
+#endif
+
+static void mdp4_dtv_encoder_destroy(struct drm_encoder *encoder)
+{
+       struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
+       bs_fini(mdp4_dtv_encoder);
+       drm_encoder_cleanup(encoder);
+       kfree(mdp4_dtv_encoder);
+}
+
+static const struct drm_encoder_funcs mdp4_dtv_encoder_funcs = {
+       .destroy = mdp4_dtv_encoder_destroy,
+};
+
+static void mdp4_dtv_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
+       struct mdp4_kms *mdp4_kms = get_kms(encoder);
+       bool enabled = (mode == DRM_MODE_DPMS_ON);
+
+       DBG("mode=%d", mode);
+
+       if (enabled == mdp4_dtv_encoder->enabled)
+               return;
+
+       if (enabled) {
+               unsigned long pc = mdp4_dtv_encoder->pixclock;
+               int ret;
+
+               bs_set(mdp4_dtv_encoder, 1);
+
+               DBG("setting src_clk=%lu", pc);
+
+               ret = clk_set_rate(mdp4_dtv_encoder->src_clk, pc);
+               if (ret)
+                       dev_err(dev->dev, "failed to set src_clk to %lu: %d\n", pc, ret);
+               clk_prepare_enable(mdp4_dtv_encoder->src_clk);
+               ret = clk_prepare_enable(mdp4_dtv_encoder->hdmi_clk);
+               if (ret)
+                       dev_err(dev->dev, "failed to enable hdmi_clk: %d\n", ret);
+               ret = clk_prepare_enable(mdp4_dtv_encoder->mdp_clk);
+               if (ret)
+                       dev_err(dev->dev, "failed to enabled mdp_clk: %d\n", ret);
+
+               mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 1);
+       } else {
+               mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0);
+
+               /*
+                * Wait for a vsync so we know the ENABLE=0 latched before
+                * the (connector) source of the vsync's gets disabled,
+                * otherwise we end up in a funny state if we re-enable
+                * before the disable latches, which results that some of
+                * the settings changes for the new modeset (like new
+                * scanout buffer) don't latch properly..
+                */
+               mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_EXTERNAL_VSYNC);
+
+               clk_disable_unprepare(mdp4_dtv_encoder->src_clk);
+               clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk);
+               clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk);
+
+               bs_set(mdp4_dtv_encoder, 0);
+       }
+
+       mdp4_dtv_encoder->enabled = enabled;
+}
+
+static bool mdp4_dtv_encoder_mode_fixup(struct drm_encoder *encoder,
+               const struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder,
+               struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
+       struct mdp4_kms *mdp4_kms = get_kms(encoder);
+       uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
+       uint32_t display_v_start, display_v_end;
+       uint32_t hsync_start_x, hsync_end_x;
+
+       mode = adjusted_mode;
+
+       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+                       mode->base.id, mode->name,
+                       mode->vrefresh, mode->clock,
+                       mode->hdisplay, mode->hsync_start,
+                       mode->hsync_end, mode->htotal,
+                       mode->vdisplay, mode->vsync_start,
+                       mode->vsync_end, mode->vtotal,
+                       mode->type, mode->flags);
+
+       mdp4_dtv_encoder->pixclock = mode->clock * 1000;
+
+       DBG("pixclock=%lu", mdp4_dtv_encoder->pixclock);
+
+       ctrl_pol = 0;
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               ctrl_pol |= MDP4_DTV_CTRL_POLARITY_HSYNC_LOW;
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               ctrl_pol |= MDP4_DTV_CTRL_POLARITY_VSYNC_LOW;
+       /* probably need to get DATA_EN polarity from panel.. */
+
+       dtv_hsync_skew = 0;  /* get this from panel? */
+
+       hsync_start_x = (mode->htotal - mode->hsync_start);
+       hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
+
+       vsync_period = mode->vtotal * mode->htotal;
+       vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
+       display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew;
+       display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1;
+
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_HSYNC_CTRL,
+                       MDP4_DTV_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
+                       MDP4_DTV_HSYNC_CTRL_PERIOD(mode->htotal));
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_VSYNC_PERIOD, vsync_period);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_VSYNC_LEN, vsync_len);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_HCTRL,
+                       MDP4_DTV_DISPLAY_HCTRL_START(hsync_start_x) |
+                       MDP4_DTV_DISPLAY_HCTRL_END(hsync_end_x));
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_VSTART, display_v_start);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_VEND, display_v_end);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_BORDER_CLR, 0);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_UNDERFLOW_CLR,
+                       MDP4_DTV_UNDERFLOW_CLR_ENABLE_RECOVERY |
+                       MDP4_DTV_UNDERFLOW_CLR_COLOR(0xff));
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_HSYNC_SKEW, dtv_hsync_skew);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_CTRL_POLARITY, ctrl_pol);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_HCTL,
+                       MDP4_DTV_ACTIVE_HCTL_START(0) |
+                       MDP4_DTV_ACTIVE_HCTL_END(0));
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VSTART, 0);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VEND, 0);
+}
+
+static void mdp4_dtv_encoder_prepare(struct drm_encoder *encoder)
+{
+       mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void mdp4_dtv_encoder_commit(struct drm_encoder *encoder)
+{
+       mdp4_crtc_set_config(encoder->crtc,
+                       MDP4_DMA_CONFIG_R_BPC(BPC8) |
+                       MDP4_DMA_CONFIG_G_BPC(BPC8) |
+                       MDP4_DMA_CONFIG_B_BPC(BPC8) |
+                       MDP4_DMA_CONFIG_PACK(0x21));
+       mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV);
+       mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = {
+       .dpms = mdp4_dtv_encoder_dpms,
+       .mode_fixup = mdp4_dtv_encoder_mode_fixup,
+       .mode_set = mdp4_dtv_encoder_mode_set,
+       .prepare = mdp4_dtv_encoder_prepare,
+       .commit = mdp4_dtv_encoder_commit,
+};
+
+long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
+{
+       struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
+       return clk_round_rate(mdp4_dtv_encoder->src_clk, rate);
+}
+
+/* initialize encoder */
+struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev)
+{
+       struct drm_encoder *encoder = NULL;
+       struct mdp4_dtv_encoder *mdp4_dtv_encoder;
+       int ret;
+
+       mdp4_dtv_encoder = kzalloc(sizeof(*mdp4_dtv_encoder), GFP_KERNEL);
+       if (!mdp4_dtv_encoder) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       encoder = &mdp4_dtv_encoder->base;
+
+       drm_encoder_init(dev, encoder, &mdp4_dtv_encoder_funcs,
+                        DRM_MODE_ENCODER_TMDS);
+       drm_encoder_helper_add(encoder, &mdp4_dtv_encoder_helper_funcs);
+
+       mdp4_dtv_encoder->src_clk = devm_clk_get(dev->dev, "src_clk");
+       if (IS_ERR(mdp4_dtv_encoder->src_clk)) {
+               dev_err(dev->dev, "failed to get src_clk\n");
+               ret = PTR_ERR(mdp4_dtv_encoder->src_clk);
+               goto fail;
+       }
+
+       mdp4_dtv_encoder->hdmi_clk = devm_clk_get(dev->dev, "hdmi_clk");
+       if (IS_ERR(mdp4_dtv_encoder->hdmi_clk)) {
+               dev_err(dev->dev, "failed to get hdmi_clk\n");
+               ret = PTR_ERR(mdp4_dtv_encoder->hdmi_clk);
+               goto fail;
+       }
+
+       mdp4_dtv_encoder->mdp_clk = devm_clk_get(dev->dev, "mdp_clk");
+       if (IS_ERR(mdp4_dtv_encoder->mdp_clk)) {
+               dev_err(dev->dev, "failed to get mdp_clk\n");
+               ret = PTR_ERR(mdp4_dtv_encoder->mdp_clk);
+               goto fail;
+       }
+
+       bs_init(mdp4_dtv_encoder);
+
+       return encoder;
+
+fail:
+       if (encoder)
+               mdp4_dtv_encoder_destroy(encoder);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
new file mode 100644 (file)
index 0000000..c740ccd
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
+#include "mdp4_kms.h"
+
+void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask)
+{
+       mdp4_write(to_mdp4_kms(mdp_kms), REG_MDP4_INTR_ENABLE, irqmask);
+}
+
+static void mdp4_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       DRM_ERROR("errors: %08x\n", irqstatus);
+}
+
+void mdp4_irq_preinstall(struct msm_kms *kms)
+{
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, 0xffffffff);
+}
+
+int mdp4_irq_postinstall(struct msm_kms *kms)
+{
+       struct mdp_kms *mdp_kms = to_mdp_kms(kms);
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(mdp_kms);
+       struct mdp_irq *error_handler = &mdp4_kms->error_handler;
+
+       error_handler->irq = mdp4_irq_error_handler;
+       error_handler->irqmask = MDP4_IRQ_PRIMARY_INTF_UDERRUN |
+                       MDP4_IRQ_EXTERNAL_INTF_UDERRUN;
+
+       mdp_irq_register(mdp_kms, error_handler);
+
+       return 0;
+}
+
+void mdp4_irq_uninstall(struct msm_kms *kms)
+{
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000);
+}
+
+irqreturn_t mdp4_irq(struct msm_kms *kms)
+{
+       struct mdp_kms *mdp_kms = to_mdp_kms(kms);
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(mdp_kms);
+       struct drm_device *dev = mdp4_kms->dev;
+       struct msm_drm_private *priv = dev->dev_private;
+       unsigned int id;
+       uint32_t status;
+
+       status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS);
+       mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, status);
+
+       VERB("status=%08x", status);
+
+       for (id = 0; id < priv->num_crtcs; id++)
+               if (status & mdp4_crtc_vblank(priv->crtcs[id]))
+                       drm_handle_vblank(dev, id);
+
+       mdp_dispatch_irqs(mdp_kms, status);
+
+       return IRQ_HANDLED;
+}
+
+int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
+{
+       mdp_update_vblank_mask(to_mdp_kms(kms),
+                       mdp4_crtc_vblank(crtc), true);
+       return 0;
+}
+
+void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
+{
+       mdp_update_vblank_mask(to_mdp_kms(kms),
+                       mdp4_crtc_vblank(crtc), false);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
new file mode 100644 (file)
index 0000000..272e707
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
+#include "msm_mmu.h"
+#include "mdp4_kms.h"
+
+static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev);
+
+static int mdp4_hw_init(struct msm_kms *kms)
+{
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       struct drm_device *dev = mdp4_kms->dev;
+       uint32_t version, major, minor, dmap_cfg, vg_cfg;
+       unsigned long clk;
+       int ret = 0;
+
+       pm_runtime_get_sync(dev->dev);
+
+       mdp4_enable(mdp4_kms);
+       version = mdp4_read(mdp4_kms, REG_MDP4_VERSION);
+       mdp4_disable(mdp4_kms);
+
+       major = FIELD(version, MDP4_VERSION_MAJOR);
+       minor = FIELD(version, MDP4_VERSION_MINOR);
+
+       DBG("found MDP4 version v%d.%d", major, minor);
+
+       if (major != 4) {
+               dev_err(dev->dev, "unexpected MDP version: v%d.%d\n",
+                               major, minor);
+               ret = -ENXIO;
+               goto out;
+       }
+
+       mdp4_kms->rev = minor;
+
+       if (mdp4_kms->dsi_pll_vdda) {
+               if ((mdp4_kms->rev == 2) || (mdp4_kms->rev == 4)) {
+                       ret = regulator_set_voltage(mdp4_kms->dsi_pll_vdda,
+                                       1200000, 1200000);
+                       if (ret) {
+                               dev_err(dev->dev,
+                                       "failed to set dsi_pll_vdda voltage: %d\n", ret);
+                               goto out;
+                       }
+               }
+       }
+
+       if (mdp4_kms->dsi_pll_vddio) {
+               if (mdp4_kms->rev == 2) {
+                       ret = regulator_set_voltage(mdp4_kms->dsi_pll_vddio,
+                                       1800000, 1800000);
+                       if (ret) {
+                               dev_err(dev->dev,
+                                       "failed to set dsi_pll_vddio voltage: %d\n", ret);
+                               goto out;
+                       }
+               }
+       }
+
+       if (mdp4_kms->rev > 1) {
+               mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER0, 0x0707ffff);
+               mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER1, 0x03073f3f);
+       }
+
+       mdp4_write(mdp4_kms, REG_MDP4_PORTMAP_MODE, 0x3);
+
+       /* max read pending cmd config, 3 pending requests: */
+       mdp4_write(mdp4_kms, REG_MDP4_READ_CNFG, 0x02222);
+
+       clk = clk_get_rate(mdp4_kms->clk);
+
+       if ((mdp4_kms->rev >= 1) || (clk >= 90000000)) {
+               dmap_cfg = 0x47;     /* 16 bytes-burst x 8 req */
+               vg_cfg = 0x47;       /* 16 bytes-burs x 8 req */
+       } else {
+               dmap_cfg = 0x27;     /* 8 bytes-burst x 8 req */
+               vg_cfg = 0x43;       /* 16 bytes-burst x 4 req */
+       }
+
+       DBG("fetch config: dmap=%02x, vg=%02x", dmap_cfg, vg_cfg);
+
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_FETCH_CONFIG(DMA_P), dmap_cfg);
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_FETCH_CONFIG(DMA_E), dmap_cfg);
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(VG1), vg_cfg);
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(VG2), vg_cfg);
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(RGB1), vg_cfg);
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(RGB2), vg_cfg);
+
+       if (mdp4_kms->rev >= 2)
+               mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG_UPDATE_METHOD, 1);
+
+       /* disable CSC matrix / YUV by default: */
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(VG1), 0);
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(VG2), 0);
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_P_OP_MODE, 0);
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_S_OP_MODE, 0);
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_CSC_CONFIG(1), 0);
+       mdp4_write(mdp4_kms, REG_MDP4_OVLP_CSC_CONFIG(2), 0);
+
+       if (mdp4_kms->rev > 1)
+               mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1);
+
+out:
+       pm_runtime_put_sync(dev->dev);
+
+       return ret;
+}
+
+static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
+               struct drm_encoder *encoder)
+{
+       /* if we had >1 encoder, we'd need something more clever: */
+       return mdp4_dtv_round_pixclk(encoder, rate);
+}
+
+static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)
+{
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       struct msm_drm_private *priv = mdp4_kms->dev->dev_private;
+       unsigned i;
+
+       for (i = 0; i < priv->num_crtcs; i++)
+               mdp4_crtc_cancel_pending_flip(priv->crtcs[i], file);
+}
+
+static void mdp4_destroy(struct msm_kms *kms)
+{
+       struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       kfree(mdp4_kms);
+}
+
+static const struct mdp_kms_funcs kms_funcs = {
+       .base = {
+               .hw_init         = mdp4_hw_init,
+               .irq_preinstall  = mdp4_irq_preinstall,
+               .irq_postinstall = mdp4_irq_postinstall,
+               .irq_uninstall   = mdp4_irq_uninstall,
+               .irq             = mdp4_irq,
+               .enable_vblank   = mdp4_enable_vblank,
+               .disable_vblank  = mdp4_disable_vblank,
+               .get_format      = mdp_get_format,
+               .round_pixclk    = mdp4_round_pixclk,
+               .preclose        = mdp4_preclose,
+               .destroy         = mdp4_destroy,
+       },
+       .set_irqmask         = mdp4_set_irqmask,
+};
+
+int mdp4_disable(struct mdp4_kms *mdp4_kms)
+{
+       DBG("");
+
+       clk_disable_unprepare(mdp4_kms->clk);
+       if (mdp4_kms->pclk)
+               clk_disable_unprepare(mdp4_kms->pclk);
+       clk_disable_unprepare(mdp4_kms->lut_clk);
+
+       return 0;
+}
+
+int mdp4_enable(struct mdp4_kms *mdp4_kms)
+{
+       DBG("");
+
+       clk_prepare_enable(mdp4_kms->clk);
+       if (mdp4_kms->pclk)
+               clk_prepare_enable(mdp4_kms->pclk);
+       clk_prepare_enable(mdp4_kms->lut_clk);
+
+       return 0;
+}
+
+static int modeset_init(struct mdp4_kms *mdp4_kms)
+{
+       struct drm_device *dev = mdp4_kms->dev;
+       struct msm_drm_private *priv = dev->dev_private;
+       struct drm_plane *plane;
+       struct drm_crtc *crtc;
+       struct drm_encoder *encoder;
+       struct hdmi *hdmi;
+       int ret;
+
+       /*
+        *  NOTE: this is a bit simplistic until we add support
+        * for more than just RGB1->DMA_E->DTV->HDMI
+        */
+
+       /* construct non-private planes: */
+       plane = mdp4_plane_init(dev, VG1, false);
+       if (IS_ERR(plane)) {
+               dev_err(dev->dev, "failed to construct plane for VG1\n");
+               ret = PTR_ERR(plane);
+               goto fail;
+       }
+       priv->planes[priv->num_planes++] = plane;
+
+       plane = mdp4_plane_init(dev, VG2, false);
+       if (IS_ERR(plane)) {
+               dev_err(dev->dev, "failed to construct plane for VG2\n");
+               ret = PTR_ERR(plane);
+               goto fail;
+       }
+       priv->planes[priv->num_planes++] = plane;
+
+       /* the CRTCs get constructed with a private plane: */
+       plane = mdp4_plane_init(dev, RGB1, true);
+       if (IS_ERR(plane)) {
+               dev_err(dev->dev, "failed to construct plane for RGB1\n");
+               ret = PTR_ERR(plane);
+               goto fail;
+       }
+
+       crtc  = mdp4_crtc_init(dev, plane, priv->num_crtcs, 1, DMA_E);
+       if (IS_ERR(crtc)) {
+               dev_err(dev->dev, "failed to construct crtc for DMA_E\n");
+               ret = PTR_ERR(crtc);
+               goto fail;
+       }
+       priv->crtcs[priv->num_crtcs++] = crtc;
+
+       encoder = mdp4_dtv_encoder_init(dev);
+       if (IS_ERR(encoder)) {
+               dev_err(dev->dev, "failed to construct DTV encoder\n");
+               ret = PTR_ERR(encoder);
+               goto fail;
+       }
+       encoder->possible_crtcs = 0x1;     /* DTV can be hooked to DMA_E */
+       priv->encoders[priv->num_encoders++] = encoder;
+
+       hdmi = hdmi_init(dev, encoder);
+       if (IS_ERR(hdmi)) {
+               ret = PTR_ERR(hdmi);
+               dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       return ret;
+}
+
+static const char *iommu_ports[] = {
+               "mdp_port0_cb0", "mdp_port1_cb0",
+};
+
+struct msm_kms *mdp4_kms_init(struct drm_device *dev)
+{
+       struct platform_device *pdev = dev->platformdev;
+       struct mdp4_platform_config *config = mdp4_get_config(pdev);
+       struct mdp4_kms *mdp4_kms;
+       struct msm_kms *kms = NULL;
+       struct msm_mmu *mmu;
+       int ret;
+
+       mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
+       if (!mdp4_kms) {
+               dev_err(dev->dev, "failed to allocate kms\n");
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       mdp_kms_init(&mdp4_kms->base, &kms_funcs);
+
+       kms = &mdp4_kms->base.base;
+
+       mdp4_kms->dev = dev;
+
+       mdp4_kms->mmio = msm_ioremap(pdev, NULL, "MDP4");
+       if (IS_ERR(mdp4_kms->mmio)) {
+               ret = PTR_ERR(mdp4_kms->mmio);
+               goto fail;
+       }
+
+       mdp4_kms->dsi_pll_vdda = devm_regulator_get(&pdev->dev, "dsi_pll_vdda");
+       if (IS_ERR(mdp4_kms->dsi_pll_vdda))
+               mdp4_kms->dsi_pll_vdda = NULL;
+
+       mdp4_kms->dsi_pll_vddio = devm_regulator_get(&pdev->dev, "dsi_pll_vddio");
+       if (IS_ERR(mdp4_kms->dsi_pll_vddio))
+               mdp4_kms->dsi_pll_vddio = NULL;
+
+       mdp4_kms->vdd = devm_regulator_get(&pdev->dev, "vdd");
+       if (IS_ERR(mdp4_kms->vdd))
+               mdp4_kms->vdd = NULL;
+
+       if (mdp4_kms->vdd) {
+               ret = regulator_enable(mdp4_kms->vdd);
+               if (ret) {
+                       dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret);
+                       goto fail;
+               }
+       }
+
+       mdp4_kms->clk = devm_clk_get(&pdev->dev, "core_clk");
+       if (IS_ERR(mdp4_kms->clk)) {
+               dev_err(dev->dev, "failed to get core_clk\n");
+               ret = PTR_ERR(mdp4_kms->clk);
+               goto fail;
+       }
+
+       mdp4_kms->pclk = devm_clk_get(&pdev->dev, "iface_clk");
+       if (IS_ERR(mdp4_kms->pclk))
+               mdp4_kms->pclk = NULL;
+
+       // XXX if (rev >= MDP_REV_42) { ???
+       mdp4_kms->lut_clk = devm_clk_get(&pdev->dev, "lut_clk");
+       if (IS_ERR(mdp4_kms->lut_clk)) {
+               dev_err(dev->dev, "failed to get lut_clk\n");
+               ret = PTR_ERR(mdp4_kms->lut_clk);
+               goto fail;
+       }
+
+       clk_set_rate(mdp4_kms->clk, config->max_clk);
+       clk_set_rate(mdp4_kms->lut_clk, config->max_clk);
+
+       /* make sure things are off before attaching iommu (bootloader could
+        * have left things on, in which case we'll start getting faults if
+        * we don't disable):
+        */
+       mdp4_enable(mdp4_kms);
+       mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0);
+       mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
+       mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0);
+       mdp4_disable(mdp4_kms);
+       mdelay(16);
+
+       if (config->iommu) {
+               mmu = msm_iommu_new(dev, config->iommu);
+               if (IS_ERR(mmu)) {
+                       ret = PTR_ERR(mmu);
+                       goto fail;
+               }
+               ret = mmu->funcs->attach(mmu, iommu_ports,
+                               ARRAY_SIZE(iommu_ports));
+               if (ret)
+                       goto fail;
+       } else {
+               dev_info(dev->dev, "no iommu, fallback to phys "
+                               "contig buffers for scanout\n");
+               mmu = NULL;
+       }
+
+       mdp4_kms->id = msm_register_mmu(dev, mmu);
+       if (mdp4_kms->id < 0) {
+               ret = mdp4_kms->id;
+               dev_err(dev->dev, "failed to register mdp4 iommu: %d\n", ret);
+               goto fail;
+       }
+
+       ret = modeset_init(mdp4_kms);
+       if (ret) {
+               dev_err(dev->dev, "modeset_init failed: %d\n", ret);
+               goto fail;
+       }
+
+       return kms;
+
+fail:
+       if (kms)
+               mdp4_destroy(kms);
+       return ERR_PTR(ret);
+}
+
+static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev)
+{
+       static struct mdp4_platform_config config = {};
+#ifdef CONFIG_OF
+       /* TODO */
+#else
+       if (cpu_is_apq8064())
+               config.max_clk = 266667000;
+       else
+               config.max_clk = 200000000;
+
+       config.iommu = msm_get_iommu_domain(DISPLAY_READ_DOMAIN);
+#endif
+       return &config;
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
new file mode 100644 (file)
index 0000000..66a4d31
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MDP4_KMS_H__
+#define __MDP4_KMS_H__
+
+#include "msm_drv.h"
+#include "msm_kms.h"
+#include "mdp/mdp_kms.h"
+#include "mdp4.xml.h"
+
+struct mdp4_kms {
+       struct mdp_kms base;
+
+       struct drm_device *dev;
+
+       int rev;
+
+       /* mapper-id used to request GEM buffer mapped for scanout: */
+       int id;
+
+       void __iomem *mmio;
+
+       struct regulator *dsi_pll_vdda;
+       struct regulator *dsi_pll_vddio;
+       struct regulator *vdd;
+
+       struct clk *clk;
+       struct clk *pclk;
+       struct clk *lut_clk;
+
+       struct mdp_irq error_handler;
+};
+#define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
+
+/* platform config data (ie. from DT, or pdata) */
+struct mdp4_platform_config {
+       struct iommu_domain *iommu;
+       uint32_t max_clk;
+};
+
+static inline void mdp4_write(struct mdp4_kms *mdp4_kms, u32 reg, u32 data)
+{
+       msm_writel(data, mdp4_kms->mmio + reg);
+}
+
+static inline u32 mdp4_read(struct mdp4_kms *mdp4_kms, u32 reg)
+{
+       return msm_readl(mdp4_kms->mmio + reg);
+}
+
+static inline uint32_t pipe2flush(enum mdp4_pipe pipe)
+{
+       switch (pipe) {
+       case VG1:      return MDP4_OVERLAY_FLUSH_VG1;
+       case VG2:      return MDP4_OVERLAY_FLUSH_VG2;
+       case RGB1:     return MDP4_OVERLAY_FLUSH_RGB1;
+       case RGB2:     return MDP4_OVERLAY_FLUSH_RGB1;
+       default:       return 0;
+       }
+}
+
+static inline uint32_t ovlp2flush(int ovlp)
+{
+       switch (ovlp) {
+       case 0:        return MDP4_OVERLAY_FLUSH_OVLP0;
+       case 1:        return MDP4_OVERLAY_FLUSH_OVLP1;
+       default:       return 0;
+       }
+}
+
+static inline uint32_t dma2irq(enum mdp4_dma dma)
+{
+       switch (dma) {
+       case DMA_P:    return MDP4_IRQ_DMA_P_DONE;
+       case DMA_S:    return MDP4_IRQ_DMA_S_DONE;
+       case DMA_E:    return MDP4_IRQ_DMA_E_DONE;
+       default:       return 0;
+       }
+}
+
+static inline uint32_t dma2err(enum mdp4_dma dma)
+{
+       switch (dma) {
+       case DMA_P:    return MDP4_IRQ_PRIMARY_INTF_UDERRUN;
+       case DMA_S:    return 0;  // ???
+       case DMA_E:    return MDP4_IRQ_EXTERNAL_INTF_UDERRUN;
+       default:       return 0;
+       }
+}
+
+static inline uint32_t mixercfg(int mixer, enum mdp4_pipe pipe,
+               enum mdp_mixer_stage_id stage)
+{
+       uint32_t mixer_cfg = 0;
+
+       switch (pipe) {
+       case VG1:
+               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE0(stage) |
+                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1);
+               break;
+       case VG2:
+               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE1(stage) |
+                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1);
+               break;
+       case RGB1:
+               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE2(stage) |
+                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1);
+               break;
+       case RGB2:
+               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE3(stage) |
+                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1);
+               break;
+       case RGB3:
+               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE4(stage) |
+                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1);
+               break;
+       case VG3:
+               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE5(stage) |
+                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1);
+               break;
+       case VG4:
+               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE6(stage) |
+                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1);
+               break;
+       default:
+               WARN_ON("invalid pipe");
+               break;
+       }
+
+       return mixer_cfg;
+}
+
+int mdp4_disable(struct mdp4_kms *mdp4_kms);
+int mdp4_enable(struct mdp4_kms *mdp4_kms);
+
+void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask);
+void mdp4_irq_preinstall(struct msm_kms *kms);
+int mdp4_irq_postinstall(struct msm_kms *kms);
+void mdp4_irq_uninstall(struct msm_kms *kms);
+irqreturn_t mdp4_irq(struct msm_kms *kms);
+int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
+void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
+
+static inline
+uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
+               uint32_t max_formats)
+{
+       /* TODO when we have YUV, we need to filter supported formats
+        * based on pipe_id..
+        */
+       return mdp_get_formats(pixel_formats, max_formats);
+}
+
+void mdp4_plane_install_properties(struct drm_plane *plane,
+               struct drm_mode_object *obj);
+void mdp4_plane_set_scanout(struct drm_plane *plane,
+               struct drm_framebuffer *fb);
+int mdp4_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);
+enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane);
+struct drm_plane *mdp4_plane_init(struct drm_device *dev,
+               enum mdp4_pipe pipe_id, bool private_plane);
+
+uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);
+void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
+void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config);
+void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf);
+void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane);
+void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane);
+struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
+               struct drm_plane *plane, int id, int ovlp_id,
+               enum mdp4_dma dma_id);
+
+long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate);
+struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev);
+
+#ifdef CONFIG_MSM_BUS_SCALING
+static inline int match_dev_name(struct device *dev, void *data)
+{
+       return !strcmp(dev_name(dev), data);
+}
+/* bus scaling data is associated with extra pointless platform devices,
+ * "dtv", etc.. this is a bit of a hack, but we need a way for encoders
+ * to find their pdata to make the bus-scaling stuff work.
+ */
+static inline void *mdp4_find_pdata(const char *devname)
+{
+       struct device *dev;
+       dev = bus_find_device(&platform_bus_type, NULL,
+                       (void *)devname, match_dev_name);
+       return dev ? dev->platform_data : NULL;
+}
+#endif
+
+#endif /* __MDP4_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
new file mode 100644 (file)
index 0000000..2406027
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "mdp4_kms.h"
+
+
+struct mdp4_plane {
+       struct drm_plane base;
+       const char *name;
+
+       enum mdp4_pipe pipe;
+
+       uint32_t nformats;
+       uint32_t formats[32];
+
+       bool enabled;
+};
+#define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base)
+
+static struct mdp4_kms *get_kms(struct drm_plane *plane)
+{
+       struct msm_drm_private *priv = plane->dev->dev_private;
+       return to_mdp4_kms(to_mdp_kms(priv->kms));
+}
+
+static int mdp4_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)
+{
+       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
+
+       mdp4_plane->enabled = true;
+
+       if (plane->fb)
+               drm_framebuffer_unreference(plane->fb);
+
+       drm_framebuffer_reference(fb);
+
+       return mdp4_plane_mode_set(plane, crtc, fb,
+                       crtc_x, crtc_y, crtc_w, crtc_h,
+                       src_x, src_y, src_w, src_h);
+}
+
+static int mdp4_plane_disable(struct drm_plane *plane)
+{
+       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
+       DBG("%s: disable", mdp4_plane->name);
+       if (plane->crtc)
+               mdp4_crtc_detach(plane->crtc, plane);
+       return 0;
+}
+
+static void mdp4_plane_destroy(struct drm_plane *plane)
+{
+       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
+
+       mdp4_plane_disable(plane);
+       drm_plane_cleanup(plane);
+
+       kfree(mdp4_plane);
+}
+
+/* helper to install properties which are common to planes and crtcs */
+void mdp4_plane_install_properties(struct drm_plane *plane,
+               struct drm_mode_object *obj)
+{
+       // XXX
+}
+
+int mdp4_plane_set_property(struct drm_plane *plane,
+               struct drm_property *property, uint64_t val)
+{
+       // XXX
+       return -EINVAL;
+}
+
+static const struct drm_plane_funcs mdp4_plane_funcs = {
+               .update_plane = mdp4_plane_update,
+               .disable_plane = mdp4_plane_disable,
+               .destroy = mdp4_plane_destroy,
+               .set_property = mdp4_plane_set_property,
+};
+
+void mdp4_plane_set_scanout(struct drm_plane *plane,
+               struct drm_framebuffer *fb)
+{
+       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
+       struct mdp4_kms *mdp4_kms = get_kms(plane);
+       enum mdp4_pipe pipe = mdp4_plane->pipe;
+       uint32_t iova;
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe),
+                       MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
+                       MDP4_PIPE_SRC_STRIDE_A_P1(fb->pitches[1]));
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_B(pipe),
+                       MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) |
+                       MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3]));
+
+       msm_gem_get_iova(msm_framebuffer_bo(fb, 0), mdp4_kms->id, &iova);
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), iova);
+
+       plane->fb = fb;
+}
+
+#define MDP4_VG_PHASE_STEP_DEFAULT     0x20000000
+
+int mdp4_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 mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
+       struct mdp4_kms *mdp4_kms = get_kms(plane);
+       enum mdp4_pipe pipe = mdp4_plane->pipe;
+       const struct mdp_format *format;
+       uint32_t op_mode = 0;
+       uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
+       uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
+
+       /* 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;
+
+       DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp4_plane->name,
+                       fb->base.id, src_x, src_y, src_w, src_h,
+                       crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
+
+       if (src_w != crtc_w) {
+               op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN;
+               /* TODO calc phasex_step */
+       }
+
+       if (src_h != crtc_h) {
+               op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN;
+               /* TODO calc phasey_step */
+       }
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe),
+                       MDP4_PIPE_SRC_SIZE_WIDTH(src_w) |
+                       MDP4_PIPE_SRC_SIZE_HEIGHT(src_h));
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_XY(pipe),
+                       MDP4_PIPE_SRC_XY_X(src_x) |
+                       MDP4_PIPE_SRC_XY_Y(src_y));
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_SIZE(pipe),
+                       MDP4_PIPE_DST_SIZE_WIDTH(crtc_w) |
+                       MDP4_PIPE_DST_SIZE_HEIGHT(crtc_h));
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_XY(pipe),
+                       MDP4_PIPE_SRC_XY_X(crtc_x) |
+                       MDP4_PIPE_SRC_XY_Y(crtc_y));
+
+       mdp4_plane_set_scanout(plane, fb);
+
+       format = to_mdp_format(msm_framebuffer_format(fb));
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe),
+                       MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
+                       MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
+                       MDP4_PIPE_SRC_FORMAT_G_BPC(format->bpc_g) |
+                       MDP4_PIPE_SRC_FORMAT_B_BPC(format->bpc_b) |
+                       COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) |
+                       MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
+                       MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
+                       COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),
+                       MDP4_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
+                       MDP4_PIPE_SRC_UNPACK_ELEM1(format->unpack[1]) |
+                       MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) |
+                       MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));
+
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode);
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);
+       mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);
+
+       /* TODO detach from old crtc (if we had more than one) */
+       mdp4_crtc_attach(crtc, plane);
+
+       return 0;
+}
+
+static const char *pipe_names[] = {
+               "VG1", "VG2",
+               "RGB1", "RGB2", "RGB3",
+               "VG3", "VG4",
+};
+
+enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane)
+{
+       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
+       return mdp4_plane->pipe;
+}
+
+/* initialize plane */
+struct drm_plane *mdp4_plane_init(struct drm_device *dev,
+               enum mdp4_pipe pipe_id, bool private_plane)
+{
+       struct drm_plane *plane = NULL;
+       struct mdp4_plane *mdp4_plane;
+       int ret;
+
+       mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL);
+       if (!mdp4_plane) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       plane = &mdp4_plane->base;
+
+       mdp4_plane->pipe = pipe_id;
+       mdp4_plane->name = pipe_names[pipe_id];
+
+       mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats,
+                       ARRAY_SIZE(mdp4_plane->formats));
+
+       drm_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
+                       mdp4_plane->formats, mdp4_plane->nformats,
+                       private_plane);
+
+       mdp4_plane_install_properties(plane, &plane->base);
+
+       return plane;
+
+fail:
+       if (plane)
+               mdp4_plane_destroy(plane);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
new file mode 100644 (file)
index 0000000..0aa5151
--- /dev/null
@@ -0,0 +1,1036 @@
+#ifndef MDP5_XML
+#define MDP5_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+
+Copyright (C) 2013 by the following authors:
+- Rob Clark <robdclark@gmail.com> (robclark)
+
+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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+*/
+
+
+enum mdp5_intf {
+       INTF_DSI = 1,
+       INTF_HDMI = 3,
+       INTF_LCDC = 5,
+       INTF_eDP = 9,
+};
+
+enum mdp5_intfnum {
+       NO_INTF = 0,
+       INTF0 = 1,
+       INTF1 = 2,
+       INTF2 = 3,
+       INTF3 = 4,
+};
+
+enum mdp5_pipe {
+       SSPP_VIG0 = 0,
+       SSPP_VIG1 = 1,
+       SSPP_VIG2 = 2,
+       SSPP_RGB0 = 3,
+       SSPP_RGB1 = 4,
+       SSPP_RGB2 = 5,
+       SSPP_DMA0 = 6,
+       SSPP_DMA1 = 7,
+};
+
+enum mdp5_ctl_mode {
+       MODE_NONE = 0,
+       MODE_ROT0 = 1,
+       MODE_ROT1 = 2,
+       MODE_WB0 = 3,
+       MODE_WB1 = 4,
+       MODE_WFD = 5,
+};
+
+enum mdp5_pack_3d {
+       PACK_3D_FRAME_INT = 0,
+       PACK_3D_H_ROW_INT = 1,
+       PACK_3D_V_ROW_INT = 2,
+       PACK_3D_COL_INT = 3,
+};
+
+enum mdp5_chroma_samp_type {
+       CHROMA_RGB = 0,
+       CHROMA_H2V1 = 1,
+       CHROMA_H1V2 = 2,
+       CHROMA_420 = 3,
+};
+
+enum mdp5_scale_filter {
+       SCALE_FILTER_NEAREST = 0,
+       SCALE_FILTER_BIL = 1,
+       SCALE_FILTER_PCMN = 2,
+       SCALE_FILTER_CA = 3,
+};
+
+enum mdp5_pipe_bwc {
+       BWC_LOSSLESS = 0,
+       BWC_Q_HIGH = 1,
+       BWC_Q_MED = 2,
+};
+
+enum mdp5_client_id {
+       CID_UNUSED = 0,
+       CID_VIG0_Y = 1,
+       CID_VIG0_CR = 2,
+       CID_VIG0_CB = 3,
+       CID_VIG1_Y = 4,
+       CID_VIG1_CR = 5,
+       CID_VIG1_CB = 6,
+       CID_VIG2_Y = 7,
+       CID_VIG2_CR = 8,
+       CID_VIG2_CB = 9,
+       CID_DMA0_Y = 10,
+       CID_DMA0_CR = 11,
+       CID_DMA0_CB = 12,
+       CID_DMA1_Y = 13,
+       CID_DMA1_CR = 14,
+       CID_DMA1_CB = 15,
+       CID_RGB0 = 16,
+       CID_RGB1 = 17,
+       CID_RGB2 = 18,
+       CID_MAX = 19,
+};
+
+enum mdp5_igc_type {
+       IGC_VIG = 0,
+       IGC_RGB = 1,
+       IGC_DMA = 2,
+       IGC_DSPP = 3,
+};
+
+#define MDP5_IRQ_INTF0_WB_ROT_COMP                             0x00000001
+#define MDP5_IRQ_INTF1_WB_ROT_COMP                             0x00000002
+#define MDP5_IRQ_INTF2_WB_ROT_COMP                             0x00000004
+#define MDP5_IRQ_INTF3_WB_ROT_COMP                             0x00000008
+#define MDP5_IRQ_INTF0_WB_WFD                                  0x00000010
+#define MDP5_IRQ_INTF1_WB_WFD                                  0x00000020
+#define MDP5_IRQ_INTF2_WB_WFD                                  0x00000040
+#define MDP5_IRQ_INTF3_WB_WFD                                  0x00000080
+#define MDP5_IRQ_INTF0_PING_PONG_COMP                          0x00000100
+#define MDP5_IRQ_INTF1_PING_PONG_COMP                          0x00000200
+#define MDP5_IRQ_INTF2_PING_PONG_COMP                          0x00000400
+#define MDP5_IRQ_INTF3_PING_PONG_COMP                          0x00000800
+#define MDP5_IRQ_INTF0_PING_PONG_RD_PTR                                0x00001000
+#define MDP5_IRQ_INTF1_PING_PONG_RD_PTR                                0x00002000
+#define MDP5_IRQ_INTF2_PING_PONG_RD_PTR                                0x00004000
+#define MDP5_IRQ_INTF3_PING_PONG_RD_PTR                                0x00008000
+#define MDP5_IRQ_INTF0_PING_PONG_WR_PTR                                0x00010000
+#define MDP5_IRQ_INTF1_PING_PONG_WR_PTR                                0x00020000
+#define MDP5_IRQ_INTF2_PING_PONG_WR_PTR                                0x00040000
+#define MDP5_IRQ_INTF3_PING_PONG_WR_PTR                                0x00080000
+#define MDP5_IRQ_INTF0_PING_PONG_AUTO_REF                      0x00100000
+#define MDP5_IRQ_INTF1_PING_PONG_AUTO_REF                      0x00200000
+#define MDP5_IRQ_INTF2_PING_PONG_AUTO_REF                      0x00400000
+#define MDP5_IRQ_INTF3_PING_PONG_AUTO_REF                      0x00800000
+#define MDP5_IRQ_INTF0_UNDER_RUN                               0x01000000
+#define MDP5_IRQ_INTF0_VSYNC                                   0x02000000
+#define MDP5_IRQ_INTF1_UNDER_RUN                               0x04000000
+#define MDP5_IRQ_INTF1_VSYNC                                   0x08000000
+#define MDP5_IRQ_INTF2_UNDER_RUN                               0x10000000
+#define MDP5_IRQ_INTF2_VSYNC                                   0x20000000
+#define MDP5_IRQ_INTF3_UNDER_RUN                               0x40000000
+#define MDP5_IRQ_INTF3_VSYNC                                   0x80000000
+#define REG_MDP5_HW_VERSION                                    0x00000000
+
+#define REG_MDP5_HW_INTR_STATUS                                        0x00000010
+#define MDP5_HW_INTR_STATUS_INTR_MDP                           0x00000001
+#define MDP5_HW_INTR_STATUS_INTR_DSI0                          0x00000010
+#define MDP5_HW_INTR_STATUS_INTR_DSI1                          0x00000020
+#define MDP5_HW_INTR_STATUS_INTR_HDMI                          0x00000100
+#define MDP5_HW_INTR_STATUS_INTR_EDP                           0x00001000
+
+#define REG_MDP5_MDP_VERSION                                   0x00000100
+#define MDP5_MDP_VERSION_MINOR__MASK                           0x00ff0000
+#define MDP5_MDP_VERSION_MINOR__SHIFT                          16
+static inline uint32_t MDP5_MDP_VERSION_MINOR(uint32_t val)
+{
+       return ((val) << MDP5_MDP_VERSION_MINOR__SHIFT) & MDP5_MDP_VERSION_MINOR__MASK;
+}
+#define MDP5_MDP_VERSION_MAJOR__MASK                           0xf0000000
+#define MDP5_MDP_VERSION_MAJOR__SHIFT                          28
+static inline uint32_t MDP5_MDP_VERSION_MAJOR(uint32_t val)
+{
+       return ((val) << MDP5_MDP_VERSION_MAJOR__SHIFT) & MDP5_MDP_VERSION_MAJOR__MASK;
+}
+
+#define REG_MDP5_DISP_INTF_SEL                                 0x00000104
+#define MDP5_DISP_INTF_SEL_INTF0__MASK                         0x000000ff
+#define MDP5_DISP_INTF_SEL_INTF0__SHIFT                                0
+static inline uint32_t MDP5_DISP_INTF_SEL_INTF0(enum mdp5_intf val)
+{
+       return ((val) << MDP5_DISP_INTF_SEL_INTF0__SHIFT) & MDP5_DISP_INTF_SEL_INTF0__MASK;
+}
+#define MDP5_DISP_INTF_SEL_INTF1__MASK                         0x0000ff00
+#define MDP5_DISP_INTF_SEL_INTF1__SHIFT                                8
+static inline uint32_t MDP5_DISP_INTF_SEL_INTF1(enum mdp5_intf val)
+{
+       return ((val) << MDP5_DISP_INTF_SEL_INTF1__SHIFT) & MDP5_DISP_INTF_SEL_INTF1__MASK;
+}
+#define MDP5_DISP_INTF_SEL_INTF2__MASK                         0x00ff0000
+#define MDP5_DISP_INTF_SEL_INTF2__SHIFT                                16
+static inline uint32_t MDP5_DISP_INTF_SEL_INTF2(enum mdp5_intf val)
+{
+       return ((val) << MDP5_DISP_INTF_SEL_INTF2__SHIFT) & MDP5_DISP_INTF_SEL_INTF2__MASK;
+}
+#define MDP5_DISP_INTF_SEL_INTF3__MASK                         0xff000000
+#define MDP5_DISP_INTF_SEL_INTF3__SHIFT                                24
+static inline uint32_t MDP5_DISP_INTF_SEL_INTF3(enum mdp5_intf val)
+{
+       return ((val) << MDP5_DISP_INTF_SEL_INTF3__SHIFT) & MDP5_DISP_INTF_SEL_INTF3__MASK;
+}
+
+#define REG_MDP5_INTR_EN                                       0x00000110
+
+#define REG_MDP5_INTR_STATUS                                   0x00000114
+
+#define REG_MDP5_INTR_CLEAR                                    0x00000118
+
+#define REG_MDP5_HIST_INTR_EN                                  0x0000011c
+
+#define REG_MDP5_HIST_INTR_STATUS                              0x00000120
+
+#define REG_MDP5_HIST_INTR_CLEAR                               0x00000124
+
+static inline uint32_t REG_MDP5_SMP_ALLOC_W(uint32_t i0) { return 0x00000180 + 0x4*i0; }
+
+static inline uint32_t REG_MDP5_SMP_ALLOC_W_REG(uint32_t i0) { return 0x00000180 + 0x4*i0; }
+#define MDP5_SMP_ALLOC_W_REG_CLIENT0__MASK                     0x000000ff
+#define MDP5_SMP_ALLOC_W_REG_CLIENT0__SHIFT                    0
+static inline uint32_t MDP5_SMP_ALLOC_W_REG_CLIENT0(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_W_REG_CLIENT0__SHIFT) & MDP5_SMP_ALLOC_W_REG_CLIENT0__MASK;
+}
+#define MDP5_SMP_ALLOC_W_REG_CLIENT1__MASK                     0x0000ff00
+#define MDP5_SMP_ALLOC_W_REG_CLIENT1__SHIFT                    8
+static inline uint32_t MDP5_SMP_ALLOC_W_REG_CLIENT1(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_W_REG_CLIENT1__SHIFT) & MDP5_SMP_ALLOC_W_REG_CLIENT1__MASK;
+}
+#define MDP5_SMP_ALLOC_W_REG_CLIENT2__MASK                     0x00ff0000
+#define MDP5_SMP_ALLOC_W_REG_CLIENT2__SHIFT                    16
+static inline uint32_t MDP5_SMP_ALLOC_W_REG_CLIENT2(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_W_REG_CLIENT2__SHIFT) & MDP5_SMP_ALLOC_W_REG_CLIENT2__MASK;
+}
+
+static inline uint32_t REG_MDP5_SMP_ALLOC_R(uint32_t i0) { return 0x00000230 + 0x4*i0; }
+
+static inline uint32_t REG_MDP5_SMP_ALLOC_R_REG(uint32_t i0) { return 0x00000230 + 0x4*i0; }
+#define MDP5_SMP_ALLOC_R_REG_CLIENT0__MASK                     0x000000ff
+#define MDP5_SMP_ALLOC_R_REG_CLIENT0__SHIFT                    0
+static inline uint32_t MDP5_SMP_ALLOC_R_REG_CLIENT0(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_R_REG_CLIENT0__SHIFT) & MDP5_SMP_ALLOC_R_REG_CLIENT0__MASK;
+}
+#define MDP5_SMP_ALLOC_R_REG_CLIENT1__MASK                     0x0000ff00
+#define MDP5_SMP_ALLOC_R_REG_CLIENT1__SHIFT                    8
+static inline uint32_t MDP5_SMP_ALLOC_R_REG_CLIENT1(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_R_REG_CLIENT1__SHIFT) & MDP5_SMP_ALLOC_R_REG_CLIENT1__MASK;
+}
+#define MDP5_SMP_ALLOC_R_REG_CLIENT2__MASK                     0x00ff0000
+#define MDP5_SMP_ALLOC_R_REG_CLIENT2__SHIFT                    16
+static inline uint32_t MDP5_SMP_ALLOC_R_REG_CLIENT2(enum mdp5_client_id val)
+{
+       return ((val) << MDP5_SMP_ALLOC_R_REG_CLIENT2__SHIFT) & MDP5_SMP_ALLOC_R_REG_CLIENT2__MASK;
+}
+
+static inline uint32_t __offset_IGC(enum mdp5_igc_type idx)
+{
+       switch (idx) {
+               case IGC_VIG: return 0x00000300;
+               case IGC_RGB: return 0x00000310;
+               case IGC_DMA: return 0x00000320;
+               case IGC_DSPP: return 0x00000400;
+               default: return INVALID_IDX(idx);
+       }
+}
+static inline uint32_t REG_MDP5_IGC(enum mdp5_igc_type i0) { return 0x00000000 + __offset_IGC(i0); }
+
+static inline uint32_t REG_MDP5_IGC_LUT(enum mdp5_igc_type i0, uint32_t i1) { return 0x00000000 + __offset_IGC(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_IGC_LUT_REG(enum mdp5_igc_type i0, uint32_t i1) { return 0x00000000 + __offset_IGC(i0) + 0x4*i1; }
+#define MDP5_IGC_LUT_REG_VAL__MASK                             0x00000fff
+#define MDP5_IGC_LUT_REG_VAL__SHIFT                            0
+static inline uint32_t MDP5_IGC_LUT_REG_VAL(uint32_t val)
+{
+       return ((val) << MDP5_IGC_LUT_REG_VAL__SHIFT) & MDP5_IGC_LUT_REG_VAL__MASK;
+}
+#define MDP5_IGC_LUT_REG_INDEX_UPDATE                          0x02000000
+#define MDP5_IGC_LUT_REG_DISABLE_PIPE_0                                0x10000000
+#define MDP5_IGC_LUT_REG_DISABLE_PIPE_1                                0x20000000
+#define MDP5_IGC_LUT_REG_DISABLE_PIPE_2                                0x40000000
+
+static inline uint32_t REG_MDP5_CTL(uint32_t i0) { return 0x00000600 + 0x100*i0; }
+
+static inline uint32_t REG_MDP5_CTL_LAYER(uint32_t i0, uint32_t i1) { return 0x00000600 + 0x100*i0 + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_CTL_LAYER_REG(uint32_t i0, uint32_t i1) { return 0x00000600 + 0x100*i0 + 0x4*i1; }
+#define MDP5_CTL_LAYER_REG_VIG0__MASK                          0x00000007
+#define MDP5_CTL_LAYER_REG_VIG0__SHIFT                         0
+static inline uint32_t MDP5_CTL_LAYER_REG_VIG0(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_VIG0__SHIFT) & MDP5_CTL_LAYER_REG_VIG0__MASK;
+}
+#define MDP5_CTL_LAYER_REG_VIG1__MASK                          0x00000038
+#define MDP5_CTL_LAYER_REG_VIG1__SHIFT                         3
+static inline uint32_t MDP5_CTL_LAYER_REG_VIG1(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_VIG1__SHIFT) & MDP5_CTL_LAYER_REG_VIG1__MASK;
+}
+#define MDP5_CTL_LAYER_REG_VIG2__MASK                          0x000001c0
+#define MDP5_CTL_LAYER_REG_VIG2__SHIFT                         6
+static inline uint32_t MDP5_CTL_LAYER_REG_VIG2(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_VIG2__SHIFT) & MDP5_CTL_LAYER_REG_VIG2__MASK;
+}
+#define MDP5_CTL_LAYER_REG_RGB0__MASK                          0x00000e00
+#define MDP5_CTL_LAYER_REG_RGB0__SHIFT                         9
+static inline uint32_t MDP5_CTL_LAYER_REG_RGB0(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_RGB0__SHIFT) & MDP5_CTL_LAYER_REG_RGB0__MASK;
+}
+#define MDP5_CTL_LAYER_REG_RGB1__MASK                          0x00007000
+#define MDP5_CTL_LAYER_REG_RGB1__SHIFT                         12
+static inline uint32_t MDP5_CTL_LAYER_REG_RGB1(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_RGB1__SHIFT) & MDP5_CTL_LAYER_REG_RGB1__MASK;
+}
+#define MDP5_CTL_LAYER_REG_RGB2__MASK                          0x00038000
+#define MDP5_CTL_LAYER_REG_RGB2__SHIFT                         15
+static inline uint32_t MDP5_CTL_LAYER_REG_RGB2(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_RGB2__SHIFT) & MDP5_CTL_LAYER_REG_RGB2__MASK;
+}
+#define MDP5_CTL_LAYER_REG_DMA0__MASK                          0x001c0000
+#define MDP5_CTL_LAYER_REG_DMA0__SHIFT                         18
+static inline uint32_t MDP5_CTL_LAYER_REG_DMA0(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_DMA0__SHIFT) & MDP5_CTL_LAYER_REG_DMA0__MASK;
+}
+#define MDP5_CTL_LAYER_REG_DMA1__MASK                          0x00e00000
+#define MDP5_CTL_LAYER_REG_DMA1__SHIFT                         21
+static inline uint32_t MDP5_CTL_LAYER_REG_DMA1(enum mdp_mixer_stage_id val)
+{
+       return ((val) << MDP5_CTL_LAYER_REG_DMA1__SHIFT) & MDP5_CTL_LAYER_REG_DMA1__MASK;
+}
+#define MDP5_CTL_LAYER_REG_BORDER_COLOR                                0x01000000
+#define MDP5_CTL_LAYER_REG_CURSOR_OUT                          0x02000000
+
+static inline uint32_t REG_MDP5_CTL_OP(uint32_t i0) { return 0x00000614 + 0x100*i0; }
+#define MDP5_CTL_OP_MODE__MASK                                 0x0000000f
+#define MDP5_CTL_OP_MODE__SHIFT                                        0
+static inline uint32_t MDP5_CTL_OP_MODE(enum mdp5_ctl_mode val)
+{
+       return ((val) << MDP5_CTL_OP_MODE__SHIFT) & MDP5_CTL_OP_MODE__MASK;
+}
+#define MDP5_CTL_OP_INTF_NUM__MASK                             0x00000070
+#define MDP5_CTL_OP_INTF_NUM__SHIFT                            4
+static inline uint32_t MDP5_CTL_OP_INTF_NUM(enum mdp5_intfnum val)
+{
+       return ((val) << MDP5_CTL_OP_INTF_NUM__SHIFT) & MDP5_CTL_OP_INTF_NUM__MASK;
+}
+#define MDP5_CTL_OP_CMD_MODE                                   0x00020000
+#define MDP5_CTL_OP_PACK_3D_ENABLE                             0x00080000
+#define MDP5_CTL_OP_PACK_3D__MASK                              0x00300000
+#define MDP5_CTL_OP_PACK_3D__SHIFT                             20
+static inline uint32_t MDP5_CTL_OP_PACK_3D(enum mdp5_pack_3d val)
+{
+       return ((val) << MDP5_CTL_OP_PACK_3D__SHIFT) & MDP5_CTL_OP_PACK_3D__MASK;
+}
+
+static inline uint32_t REG_MDP5_CTL_FLUSH(uint32_t i0) { return 0x00000618 + 0x100*i0; }
+#define MDP5_CTL_FLUSH_VIG0                                    0x00000001
+#define MDP5_CTL_FLUSH_VIG1                                    0x00000002
+#define MDP5_CTL_FLUSH_VIG2                                    0x00000004
+#define MDP5_CTL_FLUSH_RGB0                                    0x00000008
+#define MDP5_CTL_FLUSH_RGB1                                    0x00000010
+#define MDP5_CTL_FLUSH_RGB2                                    0x00000020
+#define MDP5_CTL_FLUSH_LM0                                     0x00000040
+#define MDP5_CTL_FLUSH_LM1                                     0x00000080
+#define MDP5_CTL_FLUSH_LM2                                     0x00000100
+#define MDP5_CTL_FLUSH_DMA0                                    0x00000800
+#define MDP5_CTL_FLUSH_DMA1                                    0x00001000
+#define MDP5_CTL_FLUSH_DSPP0                                   0x00002000
+#define MDP5_CTL_FLUSH_DSPP1                                   0x00004000
+#define MDP5_CTL_FLUSH_DSPP2                                   0x00008000
+#define MDP5_CTL_FLUSH_CTL                                     0x00020000
+
+static inline uint32_t REG_MDP5_CTL_START(uint32_t i0) { return 0x0000061c + 0x100*i0; }
+
+static inline uint32_t REG_MDP5_CTL_PACK_3D(uint32_t i0) { return 0x00000620 + 0x100*i0; }
+
+static inline uint32_t REG_MDP5_PIPE(enum mdp5_pipe i0) { return 0x00001200 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_HIST_CTL_BASE(enum mdp5_pipe i0) { return 0x000014c4 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_HIST_LUT_BASE(enum mdp5_pipe i0) { return 0x000014f0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_HIST_LUT_SWAP(enum mdp5_pipe i0) { return 0x00001500 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC_SIZE(enum mdp5_pipe i0) { return 0x00001200 + 0x400*i0; }
+#define MDP5_PIPE_SRC_SIZE_HEIGHT__MASK                                0xffff0000
+#define MDP5_PIPE_SRC_SIZE_HEIGHT__SHIFT                       16
+static inline uint32_t MDP5_PIPE_SRC_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_SIZE_HEIGHT__SHIFT) & MDP5_PIPE_SRC_SIZE_HEIGHT__MASK;
+}
+#define MDP5_PIPE_SRC_SIZE_WIDTH__MASK                         0x0000ffff
+#define MDP5_PIPE_SRC_SIZE_WIDTH__SHIFT                                0
+static inline uint32_t MDP5_PIPE_SRC_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_SIZE_WIDTH__SHIFT) & MDP5_PIPE_SRC_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_IMG_SIZE(enum mdp5_pipe i0) { return 0x00001204 + 0x400*i0; }
+#define MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__MASK                    0xffff0000
+#define MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__SHIFT                   16
+static inline uint32_t MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__SHIFT) & MDP5_PIPE_SRC_IMG_SIZE_HEIGHT__MASK;
+}
+#define MDP5_PIPE_SRC_IMG_SIZE_WIDTH__MASK                     0x0000ffff
+#define MDP5_PIPE_SRC_IMG_SIZE_WIDTH__SHIFT                    0
+static inline uint32_t MDP5_PIPE_SRC_IMG_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_IMG_SIZE_WIDTH__SHIFT) & MDP5_PIPE_SRC_IMG_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_XY(enum mdp5_pipe i0) { return 0x00001208 + 0x400*i0; }
+#define MDP5_PIPE_SRC_XY_Y__MASK                               0xffff0000
+#define MDP5_PIPE_SRC_XY_Y__SHIFT                              16
+static inline uint32_t MDP5_PIPE_SRC_XY_Y(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_XY_Y__SHIFT) & MDP5_PIPE_SRC_XY_Y__MASK;
+}
+#define MDP5_PIPE_SRC_XY_X__MASK                               0x0000ffff
+#define MDP5_PIPE_SRC_XY_X__SHIFT                              0
+static inline uint32_t MDP5_PIPE_SRC_XY_X(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_XY_X__SHIFT) & MDP5_PIPE_SRC_XY_X__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_OUT_SIZE(enum mdp5_pipe i0) { return 0x0000120c + 0x400*i0; }
+#define MDP5_PIPE_OUT_SIZE_HEIGHT__MASK                                0xffff0000
+#define MDP5_PIPE_OUT_SIZE_HEIGHT__SHIFT                       16
+static inline uint32_t MDP5_PIPE_OUT_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_OUT_SIZE_HEIGHT__SHIFT) & MDP5_PIPE_OUT_SIZE_HEIGHT__MASK;
+}
+#define MDP5_PIPE_OUT_SIZE_WIDTH__MASK                         0x0000ffff
+#define MDP5_PIPE_OUT_SIZE_WIDTH__SHIFT                                0
+static inline uint32_t MDP5_PIPE_OUT_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_OUT_SIZE_WIDTH__SHIFT) & MDP5_PIPE_OUT_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_OUT_XY(enum mdp5_pipe i0) { return 0x00001210 + 0x400*i0; }
+#define MDP5_PIPE_OUT_XY_Y__MASK                               0xffff0000
+#define MDP5_PIPE_OUT_XY_Y__SHIFT                              16
+static inline uint32_t MDP5_PIPE_OUT_XY_Y(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_OUT_XY_Y__SHIFT) & MDP5_PIPE_OUT_XY_Y__MASK;
+}
+#define MDP5_PIPE_OUT_XY_X__MASK                               0x0000ffff
+#define MDP5_PIPE_OUT_XY_X__SHIFT                              0
+static inline uint32_t MDP5_PIPE_OUT_XY_X(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_OUT_XY_X__SHIFT) & MDP5_PIPE_OUT_XY_X__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC0_ADDR(enum mdp5_pipe i0) { return 0x00001214 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC1_ADDR(enum mdp5_pipe i0) { return 0x00001218 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC2_ADDR(enum mdp5_pipe i0) { return 0x0000121c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC3_ADDR(enum mdp5_pipe i0) { return 0x00001220 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_A(enum mdp5_pipe i0) { return 0x00001224 + 0x400*i0; }
+#define MDP5_PIPE_SRC_STRIDE_A_P0__MASK                                0x0000ffff
+#define MDP5_PIPE_SRC_STRIDE_A_P0__SHIFT                       0
+static inline uint32_t MDP5_PIPE_SRC_STRIDE_A_P0(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_STRIDE_A_P0__SHIFT) & MDP5_PIPE_SRC_STRIDE_A_P0__MASK;
+}
+#define MDP5_PIPE_SRC_STRIDE_A_P1__MASK                                0xffff0000
+#define MDP5_PIPE_SRC_STRIDE_A_P1__SHIFT                       16
+static inline uint32_t MDP5_PIPE_SRC_STRIDE_A_P1(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_STRIDE_A_P1__SHIFT) & MDP5_PIPE_SRC_STRIDE_A_P1__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_STRIDE_B(enum mdp5_pipe i0) { return 0x00001228 + 0x400*i0; }
+#define MDP5_PIPE_SRC_STRIDE_B_P2__MASK                                0x0000ffff
+#define MDP5_PIPE_SRC_STRIDE_B_P2__SHIFT                       0
+static inline uint32_t MDP5_PIPE_SRC_STRIDE_B_P2(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_STRIDE_B_P2__SHIFT) & MDP5_PIPE_SRC_STRIDE_B_P2__MASK;
+}
+#define MDP5_PIPE_SRC_STRIDE_B_P3__MASK                                0xffff0000
+#define MDP5_PIPE_SRC_STRIDE_B_P3__SHIFT                       16
+static inline uint32_t MDP5_PIPE_SRC_STRIDE_B_P3(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP5_PIPE_SRC_STRIDE_B_P3__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_STILE_FRAME_SIZE(enum mdp5_pipe i0) { return 0x0000122c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC_FORMAT(enum mdp5_pipe i0) { return 0x00001230 + 0x400*i0; }
+#define MDP5_PIPE_SRC_FORMAT_G_BPC__MASK                       0x00000003
+#define MDP5_PIPE_SRC_FORMAT_G_BPC__SHIFT                      0
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_G_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_G_BPC__SHIFT) & MDP5_PIPE_SRC_FORMAT_G_BPC__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_B_BPC__MASK                       0x0000000c
+#define MDP5_PIPE_SRC_FORMAT_B_BPC__SHIFT                      2
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_B_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_B_BPC__SHIFT) & MDP5_PIPE_SRC_FORMAT_B_BPC__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_R_BPC__MASK                       0x00000030
+#define MDP5_PIPE_SRC_FORMAT_R_BPC__SHIFT                      4
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_R_BPC(enum mdp_bpc val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_R_BPC__SHIFT) & MDP5_PIPE_SRC_FORMAT_R_BPC__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_A_BPC__MASK                       0x000000c0
+#define MDP5_PIPE_SRC_FORMAT_A_BPC__SHIFT                      6
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_A_BPC(enum mdp_bpc_alpha val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_A_BPC__SHIFT) & MDP5_PIPE_SRC_FORMAT_A_BPC__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_ALPHA_ENABLE                      0x00000100
+#define MDP5_PIPE_SRC_FORMAT_CPP__MASK                         0x00000600
+#define MDP5_PIPE_SRC_FORMAT_CPP__SHIFT                                9
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_CPP(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_CPP__SHIFT) & MDP5_PIPE_SRC_FORMAT_CPP__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_ROT90                             0x00000800
+#define MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT__MASK                        0x00003000
+#define MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT__SHIFT               12
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT__SHIFT) & MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT                      0x00020000
+#define MDP5_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB                  0x00040000
+#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK                  0x00780000
+#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT                 19
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT) & MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK;
+}
+#define MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK                 0x01800000
+#define MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT                        23
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(enum mdp5_chroma_samp_type val)
+{
+       return ((val) << MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT) & MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_UNPACK(enum mdp5_pipe i0) { return 0x00001234 + 0x400*i0; }
+#define MDP5_PIPE_SRC_UNPACK_ELEM0__MASK                       0x000000ff
+#define MDP5_PIPE_SRC_UNPACK_ELEM0__SHIFT                      0
+static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM0(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM0__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM0__MASK;
+}
+#define MDP5_PIPE_SRC_UNPACK_ELEM1__MASK                       0x0000ff00
+#define MDP5_PIPE_SRC_UNPACK_ELEM1__SHIFT                      8
+static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM1(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM1__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM1__MASK;
+}
+#define MDP5_PIPE_SRC_UNPACK_ELEM2__MASK                       0x00ff0000
+#define MDP5_PIPE_SRC_UNPACK_ELEM2__SHIFT                      16
+static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM2(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM2__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM2__MASK;
+}
+#define MDP5_PIPE_SRC_UNPACK_ELEM3__MASK                       0xff000000
+#define MDP5_PIPE_SRC_UNPACK_ELEM3__SHIFT                      24
+static inline uint32_t MDP5_PIPE_SRC_UNPACK_ELEM3(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_SRC_UNPACK_ELEM3__SHIFT) & MDP5_PIPE_SRC_UNPACK_ELEM3__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SRC_OP_MODE(enum mdp5_pipe i0) { return 0x00001238 + 0x400*i0; }
+#define MDP5_PIPE_SRC_OP_MODE_BWC_EN                           0x00000001
+#define MDP5_PIPE_SRC_OP_MODE_BWC__MASK                                0x00000006
+#define MDP5_PIPE_SRC_OP_MODE_BWC__SHIFT                       1
+static inline uint32_t MDP5_PIPE_SRC_OP_MODE_BWC(enum mdp5_pipe_bwc val)
+{
+       return ((val) << MDP5_PIPE_SRC_OP_MODE_BWC__SHIFT) & MDP5_PIPE_SRC_OP_MODE_BWC__MASK;
+}
+#define MDP5_PIPE_SRC_OP_MODE_FLIP_LR                          0x00002000
+#define MDP5_PIPE_SRC_OP_MODE_FLIP_UD                          0x00004000
+#define MDP5_PIPE_SRC_OP_MODE_IGC_EN                           0x00010000
+#define MDP5_PIPE_SRC_OP_MODE_IGC_ROM_0                                0x00020000
+#define MDP5_PIPE_SRC_OP_MODE_IGC_ROM_1                                0x00040000
+#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE                      0x00400000
+#define MDP5_PIPE_SRC_OP_MODE_DEINTERLACE_ODD                  0x00800000
+
+static inline uint32_t REG_MDP5_PIPE_SRC_CONSTANT_COLOR(enum mdp5_pipe i0) { return 0x0000123c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_FETCH_CONFIG(enum mdp5_pipe i0) { return 0x00001248 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_VC1_RANGE(enum mdp5_pipe i0) { return 0x0000124c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(enum mdp5_pipe i0) { return 0x00001250 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(enum mdp5_pipe i0) { return 0x00001254 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(enum mdp5_pipe i0) { return 0x00001258 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(enum mdp5_pipe i0) { return 0x00001270 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC0_ADDR(enum mdp5_pipe i0) { return 0x000012a4 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC1_ADDR(enum mdp5_pipe i0) { return 0x000012a8 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC2_ADDR(enum mdp5_pipe i0) { return 0x000012ac + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_CURRENT_SRC3_ADDR(enum mdp5_pipe i0) { return 0x000012b0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_DECIMATION(enum mdp5_pipe i0) { return 0x000012b4 + 0x400*i0; }
+#define MDP5_PIPE_DECIMATION_VERT__MASK                                0x000000ff
+#define MDP5_PIPE_DECIMATION_VERT__SHIFT                       0
+static inline uint32_t MDP5_PIPE_DECIMATION_VERT(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_DECIMATION_VERT__SHIFT) & MDP5_PIPE_DECIMATION_VERT__MASK;
+}
+#define MDP5_PIPE_DECIMATION_HORZ__MASK                                0x0000ff00
+#define MDP5_PIPE_DECIMATION_HORZ__SHIFT                       8
+static inline uint32_t MDP5_PIPE_DECIMATION_HORZ(uint32_t val)
+{
+       return ((val) << MDP5_PIPE_DECIMATION_HORZ__SHIFT) & MDP5_PIPE_DECIMATION_HORZ__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_CONFIG(enum mdp5_pipe i0) { return 0x00001404 + 0x400*i0; }
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_EN                       0x00000001
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_EN                       0x00000002
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__MASK         0x00000300
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__SHIFT                8
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER__MASK         0x00000c00
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER__SHIFT                10
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER__MASK          0x00003000
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER__SHIFT         12
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER__MASK          0x0000c000
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER__SHIFT         14
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER__MASK         0x00030000
+#define MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER__SHIFT                16
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER__MASK;
+}
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__MASK         0x000c0000
+#define MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__SHIFT                18
+static inline uint32_t MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(enum mdp5_scale_filter val)
+{
+       return ((val) << MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__SHIFT) & MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER__MASK;
+}
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_X(enum mdp5_pipe i0) { return 0x00001410 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(enum mdp5_pipe i0) { return 0x00001414 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_X(enum mdp5_pipe i0) { return 0x00001420 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_PIPE_SCALE_INIT_PHASE_Y(enum mdp5_pipe i0) { return 0x00001424 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM(uint32_t i0) { return 0x00003200 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_COLOR_OUT(uint32_t i0) { return 0x00003200 + 0x400*i0; }
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA                        0x00000002
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA                        0x00000004
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA                        0x00000008
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA                        0x00000010
+
+static inline uint32_t REG_MDP5_LM_OUT_SIZE(uint32_t i0) { return 0x00003204 + 0x400*i0; }
+#define MDP5_LM_OUT_SIZE_HEIGHT__MASK                          0xffff0000
+#define MDP5_LM_OUT_SIZE_HEIGHT__SHIFT                         16
+static inline uint32_t MDP5_LM_OUT_SIZE_HEIGHT(uint32_t val)
+{
+       return ((val) << MDP5_LM_OUT_SIZE_HEIGHT__SHIFT) & MDP5_LM_OUT_SIZE_HEIGHT__MASK;
+}
+#define MDP5_LM_OUT_SIZE_WIDTH__MASK                           0x0000ffff
+#define MDP5_LM_OUT_SIZE_WIDTH__SHIFT                          0
+static inline uint32_t MDP5_LM_OUT_SIZE_WIDTH(uint32_t val)
+{
+       return ((val) << MDP5_LM_OUT_SIZE_WIDTH__SHIFT) & MDP5_LM_OUT_SIZE_WIDTH__MASK;
+}
+
+static inline uint32_t REG_MDP5_LM_BORDER_COLOR_0(uint32_t i0) { return 0x00003208 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_BORDER_COLOR_1(uint32_t i0) { return 0x00003210 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_BLEND(uint32_t i0, uint32_t i1) { return 0x00003220 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_OP_MODE(uint32_t i0, uint32_t i1) { return 0x00003220 + 0x400*i0 + 0x30*i1; }
+#define MDP5_LM_BLEND_OP_MODE_FG_ALPHA__MASK                   0x00000003
+#define MDP5_LM_BLEND_OP_MODE_FG_ALPHA__SHIFT                  0
+static inline uint32_t MDP5_LM_BLEND_OP_MODE_FG_ALPHA(enum mdp_alpha_type val)
+{
+       return ((val) << MDP5_LM_BLEND_OP_MODE_FG_ALPHA__SHIFT) & MDP5_LM_BLEND_OP_MODE_FG_ALPHA__MASK;
+}
+#define MDP5_LM_BLEND_OP_MODE_FG_INV_ALPHA                     0x00000004
+#define MDP5_LM_BLEND_OP_MODE_FG_MOD_ALPHA                     0x00000008
+#define MDP5_LM_BLEND_OP_MODE_FG_INV_MOD_ALPHA                 0x00000010
+#define MDP5_LM_BLEND_OP_MODE_FG_TRANSP_EN                     0x00000020
+#define MDP5_LM_BLEND_OP_MODE_BG_ALPHA__MASK                   0x00000300
+#define MDP5_LM_BLEND_OP_MODE_BG_ALPHA__SHIFT                  8
+static inline uint32_t MDP5_LM_BLEND_OP_MODE_BG_ALPHA(enum mdp_alpha_type val)
+{
+       return ((val) << MDP5_LM_BLEND_OP_MODE_BG_ALPHA__SHIFT) & MDP5_LM_BLEND_OP_MODE_BG_ALPHA__MASK;
+}
+#define MDP5_LM_BLEND_OP_MODE_BG_INV_ALPHA                     0x00000400
+#define MDP5_LM_BLEND_OP_MODE_BG_MOD_ALPHA                     0x00000800
+#define MDP5_LM_BLEND_OP_MODE_BG_INV_MOD_ALPHA                 0x00001000
+#define MDP5_LM_BLEND_OP_MODE_BG_TRANSP_EN                     0x00002000
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00003224 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00003228 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000322c + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00003230 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00003234 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_FG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00003238 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000323c + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00003240 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00003244 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_BLEND_BG_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00003248 + 0x400*i0 + 0x30*i1; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_IMG_SIZE(uint32_t i0) { return 0x000032e0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_SIZE(uint32_t i0) { return 0x000032e4 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_XY(uint32_t i0) { return 0x000032e8 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_STRIDE(uint32_t i0) { return 0x000032dc + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_FORMAT(uint32_t i0) { return 0x000032ec + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BASE_ADDR(uint32_t i0) { return 0x000032f0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_START_XY(uint32_t i0) { return 0x000032f4 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_CONFIG(uint32_t i0) { return 0x000032f8 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_PARAM(uint32_t i0) { return 0x000032fc + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW0(uint32_t i0) { return 0x00003300 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_LOW1(uint32_t i0) { return 0x00003304 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH0(uint32_t i0) { return 0x00003308 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_CURSOR_BLEND_TRANSP_HIGH1(uint32_t i0) { return 0x0000330c + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_LM_GC_LUT_BASE(uint32_t i0) { return 0x00003310 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP(uint32_t i0) { return 0x00004600 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_OP_MODE(uint32_t i0) { return 0x00004600 + 0x400*i0; }
+#define MDP5_DSPP_OP_MODE_IGC_LUT_EN                           0x00000001
+#define MDP5_DSPP_OP_MODE_IGC_TBL_IDX__MASK                    0x0000000e
+#define MDP5_DSPP_OP_MODE_IGC_TBL_IDX__SHIFT                   1
+static inline uint32_t MDP5_DSPP_OP_MODE_IGC_TBL_IDX(uint32_t val)
+{
+       return ((val) << MDP5_DSPP_OP_MODE_IGC_TBL_IDX__SHIFT) & MDP5_DSPP_OP_MODE_IGC_TBL_IDX__MASK;
+}
+#define MDP5_DSPP_OP_MODE_PCC_EN                               0x00000010
+#define MDP5_DSPP_OP_MODE_DITHER_EN                            0x00000100
+#define MDP5_DSPP_OP_MODE_HIST_EN                              0x00010000
+#define MDP5_DSPP_OP_MODE_AUTO_CLEAR                           0x00020000
+#define MDP5_DSPP_OP_MODE_HIST_LUT_EN                          0x00080000
+#define MDP5_DSPP_OP_MODE_PA_EN                                        0x00100000
+#define MDP5_DSPP_OP_MODE_GAMUT_EN                             0x00800000
+#define MDP5_DSPP_OP_MODE_GAMUT_ORDER                          0x01000000
+
+static inline uint32_t REG_MDP5_DSPP_PCC_BASE(uint32_t i0) { return 0x00004630 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_DITHER_DEPTH(uint32_t i0) { return 0x00004750 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_HIST_CTL_BASE(uint32_t i0) { return 0x00004810 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_HIST_LUT_BASE(uint32_t i0) { return 0x00004830 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_HIST_LUT_SWAP(uint32_t i0) { return 0x00004834 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_PA_BASE(uint32_t i0) { return 0x00004838 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_GAMUT_BASE(uint32_t i0) { return 0x000048dc + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_DSPP_GC_BASE(uint32_t i0) { return 0x000048b0 + 0x400*i0; }
+
+static inline uint32_t REG_MDP5_INTF(uint32_t i0) { return 0x00012500 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TIMING_ENGINE_EN(uint32_t i0) { return 0x00012500 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_CONFIG(uint32_t i0) { return 0x00012504 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_HSYNC_CTL(uint32_t i0) { return 0x00012508 + 0x200*i0; }
+#define MDP5_INTF_HSYNC_CTL_PULSEW__MASK                       0x0000ffff
+#define MDP5_INTF_HSYNC_CTL_PULSEW__SHIFT                      0
+static inline uint32_t MDP5_INTF_HSYNC_CTL_PULSEW(uint32_t val)
+{
+       return ((val) << MDP5_INTF_HSYNC_CTL_PULSEW__SHIFT) & MDP5_INTF_HSYNC_CTL_PULSEW__MASK;
+}
+#define MDP5_INTF_HSYNC_CTL_PERIOD__MASK                       0xffff0000
+#define MDP5_INTF_HSYNC_CTL_PERIOD__SHIFT                      16
+static inline uint32_t MDP5_INTF_HSYNC_CTL_PERIOD(uint32_t val)
+{
+       return ((val) << MDP5_INTF_HSYNC_CTL_PERIOD__SHIFT) & MDP5_INTF_HSYNC_CTL_PERIOD__MASK;
+}
+
+static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F0(uint32_t i0) { return 0x0001250c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_VSYNC_PERIOD_F1(uint32_t i0) { return 0x00012510 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F0(uint32_t i0) { return 0x00012514 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_VSYNC_LEN_F1(uint32_t i0) { return 0x00012518 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F0(uint32_t i0) { return 0x0001251c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VSTART_F1(uint32_t i0) { return 0x00012520 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F0(uint32_t i0) { return 0x00012524 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_VEND_F1(uint32_t i0) { return 0x00012528 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F0(uint32_t i0) { return 0x0001252c + 0x200*i0; }
+#define MDP5_INTF_ACTIVE_VSTART_F0_VAL__MASK                   0x7fffffff
+#define MDP5_INTF_ACTIVE_VSTART_F0_VAL__SHIFT                  0
+static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F0_VAL(uint32_t val)
+{
+       return ((val) << MDP5_INTF_ACTIVE_VSTART_F0_VAL__SHIFT) & MDP5_INTF_ACTIVE_VSTART_F0_VAL__MASK;
+}
+#define MDP5_INTF_ACTIVE_VSTART_F0_ACTIVE_V_ENABLE             0x80000000
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VSTART_F1(uint32_t i0) { return 0x00012530 + 0x200*i0; }
+#define MDP5_INTF_ACTIVE_VSTART_F1_VAL__MASK                   0x7fffffff
+#define MDP5_INTF_ACTIVE_VSTART_F1_VAL__SHIFT                  0
+static inline uint32_t MDP5_INTF_ACTIVE_VSTART_F1_VAL(uint32_t val)
+{
+       return ((val) << MDP5_INTF_ACTIVE_VSTART_F1_VAL__SHIFT) & MDP5_INTF_ACTIVE_VSTART_F1_VAL__MASK;
+}
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F0(uint32_t i0) { return 0x00012534 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_VEND_F1(uint32_t i0) { return 0x00012538 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DISPLAY_HCTL(uint32_t i0) { return 0x0001253c + 0x200*i0; }
+#define MDP5_INTF_DISPLAY_HCTL_START__MASK                     0x0000ffff
+#define MDP5_INTF_DISPLAY_HCTL_START__SHIFT                    0
+static inline uint32_t MDP5_INTF_DISPLAY_HCTL_START(uint32_t val)
+{
+       return ((val) << MDP5_INTF_DISPLAY_HCTL_START__SHIFT) & MDP5_INTF_DISPLAY_HCTL_START__MASK;
+}
+#define MDP5_INTF_DISPLAY_HCTL_END__MASK                       0xffff0000
+#define MDP5_INTF_DISPLAY_HCTL_END__SHIFT                      16
+static inline uint32_t MDP5_INTF_DISPLAY_HCTL_END(uint32_t val)
+{
+       return ((val) << MDP5_INTF_DISPLAY_HCTL_END__SHIFT) & MDP5_INTF_DISPLAY_HCTL_END__MASK;
+}
+
+static inline uint32_t REG_MDP5_INTF_ACTIVE_HCTL(uint32_t i0) { return 0x00012540 + 0x200*i0; }
+#define MDP5_INTF_ACTIVE_HCTL_START__MASK                      0x00007fff
+#define MDP5_INTF_ACTIVE_HCTL_START__SHIFT                     0
+static inline uint32_t MDP5_INTF_ACTIVE_HCTL_START(uint32_t val)
+{
+       return ((val) << MDP5_INTF_ACTIVE_HCTL_START__SHIFT) & MDP5_INTF_ACTIVE_HCTL_START__MASK;
+}
+#define MDP5_INTF_ACTIVE_HCTL_END__MASK                                0x7fff0000
+#define MDP5_INTF_ACTIVE_HCTL_END__SHIFT                       16
+static inline uint32_t MDP5_INTF_ACTIVE_HCTL_END(uint32_t val)
+{
+       return ((val) << MDP5_INTF_ACTIVE_HCTL_END__SHIFT) & MDP5_INTF_ACTIVE_HCTL_END__MASK;
+}
+#define MDP5_INTF_ACTIVE_HCTL_ACTIVE_H_ENABLE                  0x80000000
+
+static inline uint32_t REG_MDP5_INTF_BORDER_COLOR(uint32_t i0) { return 0x00012544 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_UNDERFLOW_COLOR(uint32_t i0) { return 0x00012548 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_HSYNC_SKEW(uint32_t i0) { return 0x0001254c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_POLARITY_CTL(uint32_t i0) { return 0x00012550 + 0x200*i0; }
+#define MDP5_INTF_POLARITY_CTL_HSYNC_LOW                       0x00000001
+#define MDP5_INTF_POLARITY_CTL_VSYNC_LOW                       0x00000002
+#define MDP5_INTF_POLARITY_CTL_DATA_EN_LOW                     0x00000004
+
+static inline uint32_t REG_MDP5_INTF_TEST_CTL(uint32_t i0) { return 0x00012554 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TP_COLOR0(uint32_t i0) { return 0x00012558 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TP_COLOR1(uint32_t i0) { return 0x0001255c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DSI_CMD_MODE_TRIGGER_EN(uint32_t i0) { return 0x00012584 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_PANEL_FORMAT(uint32_t i0) { return 0x00012590 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_FRAME_LINE_COUNT_EN(uint32_t i0) { return 0x000125a8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_FRAME_COUNT(uint32_t i0) { return 0x000125ac + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_LINE_COUNT(uint32_t i0) { return 0x000125b0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_CONFIG(uint32_t i0) { return 0x000125f0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_STRNG_COEFF(uint32_t i0) { return 0x000125f4 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_DEFLICKER_WEAK_COEFF(uint32_t i0) { return 0x000125f8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_ENABLE(uint32_t i0) { return 0x00012600 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_MAIN_CONTROL(uint32_t i0) { return 0x00012604 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_VIDEO_CONFIG(uint32_t i0) { return 0x00012608 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_COMPONENT_LIMITS(uint32_t i0) { return 0x0001260c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_RECTANGLE(uint32_t i0) { return 0x00012610 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_INITIAL_VALUE(uint32_t i0) { return 0x00012614 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_BLK_WHITE_PATTERN_FRAME(uint32_t i0) { return 0x00012618 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_INTF_TPG_RGB_MAPPING(uint32_t i0) { return 0x0001261c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD(uint32_t i0) { return 0x00013100 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BYPASS(uint32_t i0) { return 0x00013100 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CTRL_0(uint32_t i0) { return 0x00013104 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CTRL_1(uint32_t i0) { return 0x00013108 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_FRAME_SIZE(uint32_t i0) { return 0x0001310c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CON_CTRL_0(uint32_t i0) { return 0x00013110 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CON_CTRL_1(uint32_t i0) { return 0x00013114 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_STR_MAN(uint32_t i0) { return 0x00013118 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_VAR(uint32_t i0) { return 0x0001311c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_DITH(uint32_t i0) { return 0x00013120 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_DITH_CTRL(uint32_t i0) { return 0x00013124 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_AMP_LIM(uint32_t i0) { return 0x00013128 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_SLOPE(uint32_t i0) { return 0x0001312c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BW_LVL(uint32_t i0) { return 0x00013130 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_LOGO_POS(uint32_t i0) { return 0x00013134 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_LUT_FI(uint32_t i0) { return 0x00013138 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_LUT_CC(uint32_t i0) { return 0x0001317c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_STR_LIM(uint32_t i0) { return 0x000131c8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CALIB_AB(uint32_t i0) { return 0x000131cc + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CALIB_CD(uint32_t i0) { return 0x000131d0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_MODE_SEL(uint32_t i0) { return 0x000131d4 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_TFILT_CTRL(uint32_t i0) { return 0x000131d8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BL_MINMAX(uint32_t i0) { return 0x000131dc + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BL(uint32_t i0) { return 0x000131e0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BL_MAX(uint32_t i0) { return 0x000131e8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_AL(uint32_t i0) { return 0x000131ec + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_AL_MIN(uint32_t i0) { return 0x000131f0 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_AL_FILT(uint32_t i0) { return 0x000131f4 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CFG_BUF(uint32_t i0) { return 0x000131f8 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_LUT_AL(uint32_t i0) { return 0x00013200 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_TARG_STR(uint32_t i0) { return 0x00013244 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_START_CALC(uint32_t i0) { return 0x00013248 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_STR_OUT(uint32_t i0) { return 0x0001324c + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_BL_OUT(uint32_t i0) { return 0x00013254 + 0x200*i0; }
+
+static inline uint32_t REG_MDP5_AD_CALC_DONE(uint32_t i0) { return 0x00013258 + 0x200*i0; }
+
+
+#endif /* MDP5_XML */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
new file mode 100644 (file)
index 0000000..71a3b23
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "mdp5_kms.h"
+
+#include <drm/drm_mode.h>
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "drm_flip_work.h"
+
+struct mdp5_crtc {
+       struct drm_crtc base;
+       char name[8];
+       struct drm_plane *plane;
+       struct drm_plane *planes[8];
+       int id;
+       bool enabled;
+
+       /* which mixer/encoder we route output to: */
+       int mixer;
+
+       /* if there is a pending flip, these will be non-null: */
+       struct drm_pending_vblank_event *event;
+       struct msm_fence_cb pageflip_cb;
+
+#define PENDING_CURSOR 0x1
+#define PENDING_FLIP   0x2
+       atomic_t pending;
+
+       /* the fb that we logically (from PoV of KMS API) hold a ref
+        * to.  Which we may not yet be scanning out (we may still
+        * be scanning out previous in case of page_flip while waiting
+        * for gpu rendering to complete:
+        */
+       struct drm_framebuffer *fb;
+
+       /* the fb that we currently hold a scanout ref to: */
+       struct drm_framebuffer *scanout_fb;
+
+       /* for unref'ing framebuffers after scanout completes: */
+       struct drm_flip_work unref_fb_work;
+
+       struct mdp_irq vblank;
+       struct mdp_irq err;
+};
+#define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
+
+static struct mdp5_kms *get_kms(struct drm_crtc *crtc)
+{
+       struct msm_drm_private *priv = crtc->dev->dev_private;
+       return to_mdp5_kms(to_mdp_kms(priv->kms));
+}
+
+static void request_pending(struct drm_crtc *crtc, uint32_t pending)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+       atomic_or(pending, &mdp5_crtc->pending);
+       mdp_irq_register(&get_kms(crtc)->base, &mdp5_crtc->vblank);
+}
+
+static void crtc_flush(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       int id = mdp5_crtc->id;
+       uint32_t i, flush = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mdp5_crtc->planes); i++) {
+               struct drm_plane *plane = mdp5_crtc->planes[i];
+               if (plane) {
+                       enum mdp5_pipe pipe = mdp5_plane_pipe(plane);
+                       flush |= pipe2flush(pipe);
+               }
+       }
+       flush |= mixer2flush(mdp5_crtc->id);
+       flush |= MDP5_CTL_FLUSH_CTL;
+
+       DBG("%s: flush=%08x", mdp5_crtc->name, flush);
+
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_FLUSH(id), flush);
+}
+
+static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct drm_framebuffer *old_fb = mdp5_crtc->fb;
+
+       /* grab reference to incoming scanout fb: */
+       drm_framebuffer_reference(new_fb);
+       mdp5_crtc->base.fb = new_fb;
+       mdp5_crtc->fb = new_fb;
+
+       if (old_fb)
+               drm_flip_work_queue(&mdp5_crtc->unref_fb_work, old_fb);
+}
+
+/* unlike update_fb(), take a ref to the new scanout fb *before* updating
+ * plane, then call this.  Needed to ensure we don't unref the buffer that
+ * is actually still being scanned out.
+ *
+ * Note that this whole thing goes away with atomic.. since we can defer
+ * calling into driver until rendering is done.
+ */
+static void update_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+       /* flush updates, to make sure hw is updated to new scanout fb,
+        * so that we can safely queue unref to current fb (ie. next
+        * vblank we know hw is done w/ previous scanout_fb).
+        */
+       crtc_flush(crtc);
+
+       if (mdp5_crtc->scanout_fb)
+               drm_flip_work_queue(&mdp5_crtc->unref_fb_work,
+                               mdp5_crtc->scanout_fb);
+
+       mdp5_crtc->scanout_fb = fb;
+
+       /* enable vblank to complete flip: */
+       request_pending(crtc, PENDING_FLIP);
+}
+
+/* if file!=NULL, this is preclose potential cancel-flip path */
+static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_pending_vblank_event *event;
+       unsigned long flags, i;
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       event = mdp5_crtc->event;
+       if (event) {
+               /* if regular vblank case (!file) or if cancel-flip from
+                * preclose on file that requested flip, then send the
+                * event:
+                */
+               if (!file || (event->base.file_priv == file)) {
+                       mdp5_crtc->event = NULL;
+                       drm_send_vblank_event(dev, mdp5_crtc->id, event);
+               }
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       for (i = 0; i < ARRAY_SIZE(mdp5_crtc->planes); i++) {
+               struct drm_plane *plane = mdp5_crtc->planes[i];
+               if (plane)
+                       mdp5_plane_complete_flip(plane);
+       }
+}
+
+static void pageflip_cb(struct msm_fence_cb *cb)
+{
+       struct mdp5_crtc *mdp5_crtc =
+               container_of(cb, struct mdp5_crtc, pageflip_cb);
+       struct drm_crtc *crtc = &mdp5_crtc->base;
+       struct drm_framebuffer *fb = mdp5_crtc->fb;
+
+       if (!fb)
+               return;
+
+       drm_framebuffer_reference(fb);
+       mdp5_plane_set_scanout(mdp5_crtc->plane, fb);
+       update_scanout(crtc, fb);
+}
+
+static void unref_fb_worker(struct drm_flip_work *work, void *val)
+{
+       struct mdp5_crtc *mdp5_crtc =
+               container_of(work, struct mdp5_crtc, unref_fb_work);
+       struct drm_device *dev = mdp5_crtc->base.dev;
+
+       mutex_lock(&dev->mode_config.mutex);
+       drm_framebuffer_unreference(val);
+       mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void mdp5_crtc_destroy(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+       mdp5_crtc->plane->funcs->destroy(mdp5_crtc->plane);
+
+       drm_crtc_cleanup(crtc);
+       drm_flip_work_cleanup(&mdp5_crtc->unref_fb_work);
+
+       kfree(mdp5_crtc);
+}
+
+static void mdp5_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       bool enabled = (mode == DRM_MODE_DPMS_ON);
+
+       DBG("%s: mode=%d", mdp5_crtc->name, mode);
+
+       if (enabled != mdp5_crtc->enabled) {
+               if (enabled) {
+                       mdp5_enable(mdp5_kms);
+                       mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
+               } else {
+                       mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
+                       mdp5_disable(mdp5_kms);
+               }
+               mdp5_crtc->enabled = enabled;
+       }
+}
+
+static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc,
+               const struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void blend_setup(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       int id = mdp5_crtc->id;
+
+       /*
+        * Hard-coded setup for now until I figure out how the
+        * layer-mixer works
+        */
+
+       /* LM[id]: */
+       mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(id),
+                       MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA);
+       mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_OP_MODE(id, 0),
+                       MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) |
+                       MDP5_LM_BLEND_OP_MODE_BG_ALPHA(FG_PIXEL) |
+                       MDP5_LM_BLEND_OP_MODE_BG_INV_ALPHA);
+       mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_FG_ALPHA(id, 0), 0xff);
+       mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_BG_ALPHA(id, 0), 0x00);
+
+       /* NOTE: seems that LM[n] and CTL[m], we do not need n==m.. but
+        * we want to be setting CTL[m].LAYER[n].  Not sure what the
+        * point of having CTL[m].LAYER[o] (for o!=n).. maybe that is
+        * used when chaining up mixers for high resolution displays?
+        */
+
+       /* CTL[id]: */
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 0),
+                       MDP5_CTL_LAYER_REG_RGB0(STAGE0) |
+                       MDP5_CTL_LAYER_REG_BORDER_COLOR);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 1), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 2), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 3), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_LAYER_REG(id, 4), 0);
+}
+
+static int mdp5_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 mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       int ret;
+
+       mode = adjusted_mode;
+
+       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+                       mdp5_crtc->name, mode->base.id, mode->name,
+                       mode->vrefresh, mode->clock,
+                       mode->hdisplay, mode->hsync_start,
+                       mode->hsync_end, mode->htotal,
+                       mode->vdisplay, mode->vsync_start,
+                       mode->vsync_end, mode->vtotal,
+                       mode->type, mode->flags);
+
+       /* grab extra ref for update_scanout() */
+       drm_framebuffer_reference(crtc->fb);
+
+       ret = mdp5_plane_mode_set(mdp5_crtc->plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       x << 16, y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16);
+       if (ret) {
+               dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
+                               mdp5_crtc->name, ret);
+               return ret;
+       }
+
+       mdp5_write(mdp5_kms, REG_MDP5_LM_OUT_SIZE(mdp5_crtc->id),
+                       MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
+                       MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
+
+       update_fb(crtc, crtc->fb);
+       update_scanout(crtc, crtc->fb);
+
+       return 0;
+}
+
+static void mdp5_crtc_prepare(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       DBG("%s", mdp5_crtc->name);
+       /* make sure we hold a ref to mdp clks while setting up mode: */
+       mdp5_enable(get_kms(crtc));
+       mdp5_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void mdp5_crtc_commit(struct drm_crtc *crtc)
+{
+       mdp5_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+       crtc_flush(crtc);
+       /* drop the ref to mdp clk's that we got in prepare: */
+       mdp5_disable(get_kms(crtc));
+}
+
+static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+               struct drm_framebuffer *old_fb)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct drm_plane *plane = mdp5_crtc->plane;
+       struct drm_display_mode *mode = &crtc->mode;
+       int ret;
+
+       /* grab extra ref for update_scanout() */
+       drm_framebuffer_reference(crtc->fb);
+
+       ret = mdp5_plane_mode_set(plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       x << 16, y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16);
+
+       update_fb(crtc, crtc->fb);
+       update_scanout(crtc, crtc->fb);
+
+       return ret;
+}
+
+static void mdp5_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+static int mdp5_crtc_page_flip(struct drm_crtc *crtc,
+               struct drm_framebuffer *new_fb,
+               struct drm_pending_vblank_event *event,
+               uint32_t page_flip_flags)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_gem_object *obj;
+       unsigned long flags;
+
+       if (mdp5_crtc->event) {
+               dev_err(dev->dev, "already pending flip!\n");
+               return -EBUSY;
+       }
+
+       obj = msm_framebuffer_bo(new_fb, 0);
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       mdp5_crtc->event = event;
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       update_fb(crtc, new_fb);
+
+       return msm_gem_queue_inactive_cb(obj, &mdp5_crtc->pageflip_cb);
+}
+
+static int mdp5_crtc_set_property(struct drm_crtc *crtc,
+               struct drm_property *property, uint64_t val)
+{
+       // XXX
+       return -EINVAL;
+}
+
+static const struct drm_crtc_funcs mdp5_crtc_funcs = {
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = mdp5_crtc_destroy,
+       .page_flip = mdp5_crtc_page_flip,
+       .set_property = mdp5_crtc_set_property,
+};
+
+static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
+       .dpms = mdp5_crtc_dpms,
+       .mode_fixup = mdp5_crtc_mode_fixup,
+       .mode_set = mdp5_crtc_mode_set,
+       .prepare = mdp5_crtc_prepare,
+       .commit = mdp5_crtc_commit,
+       .mode_set_base = mdp5_crtc_mode_set_base,
+       .load_lut = mdp5_crtc_load_lut,
+};
+
+static void mdp5_crtc_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, vblank);
+       struct drm_crtc *crtc = &mdp5_crtc->base;
+       struct msm_drm_private *priv = crtc->dev->dev_private;
+       unsigned pending;
+
+       mdp_irq_unregister(&get_kms(crtc)->base, &mdp5_crtc->vblank);
+
+       pending = atomic_xchg(&mdp5_crtc->pending, 0);
+
+       if (pending & PENDING_FLIP) {
+               complete_flip(crtc, NULL);
+               drm_flip_work_commit(&mdp5_crtc->unref_fb_work, priv->wq);
+       }
+}
+
+static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, err);
+       struct drm_crtc *crtc = &mdp5_crtc->base;
+       DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);
+       crtc_flush(crtc);
+}
+
+uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       return mdp5_crtc->vblank.irqmask;
+}
+
+void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+       DBG("cancel: %p", file);
+       complete_flip(crtc, file);
+}
+
+/* set interface for routing crtc->encoder: */
+void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf,
+               enum mdp5_intf intf_id)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       static const enum mdp5_intfnum intfnum[] = {
+                       INTF0, INTF1, INTF2, INTF3,
+       };
+       uint32_t intf_sel;
+
+       /* now that we know what irq's we want: */
+       mdp5_crtc->err.irqmask = intf2err(intf);
+       mdp5_crtc->vblank.irqmask = intf2vblank(intf);
+
+       /* when called from modeset_init(), skip the rest until later: */
+       if (!mdp5_kms)
+               return;
+
+       intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL);
+
+       switch (intf) {
+       case 0:
+               intf_sel &= ~MDP5_DISP_INTF_SEL_INTF0__MASK;
+               intf_sel |= MDP5_DISP_INTF_SEL_INTF0(intf_id);
+               break;
+       case 1:
+               intf_sel &= ~MDP5_DISP_INTF_SEL_INTF1__MASK;
+               intf_sel |= MDP5_DISP_INTF_SEL_INTF1(intf_id);
+               break;
+       case 2:
+               intf_sel &= ~MDP5_DISP_INTF_SEL_INTF2__MASK;
+               intf_sel |= MDP5_DISP_INTF_SEL_INTF2(intf_id);
+               break;
+       case 3:
+               intf_sel &= ~MDP5_DISP_INTF_SEL_INTF3__MASK;
+               intf_sel |= MDP5_DISP_INTF_SEL_INTF3(intf_id);
+               break;
+       default:
+               BUG();
+               break;
+       }
+
+       blend_setup(crtc);
+
+       DBG("%s: intf_sel=%08x", mdp5_crtc->name, intf_sel);
+
+       mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, intf_sel);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(mdp5_crtc->id),
+                       MDP5_CTL_OP_MODE(MODE_NONE) |
+                       MDP5_CTL_OP_INTF_NUM(intfnum[intf]));
+
+       crtc_flush(crtc);
+}
+
+static void set_attach(struct drm_crtc *crtc, enum mdp5_pipe pipe_id,
+               struct drm_plane *plane)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+       BUG_ON(pipe_id >= ARRAY_SIZE(mdp5_crtc->planes));
+
+       if (mdp5_crtc->planes[pipe_id] == plane)
+               return;
+
+       mdp5_crtc->planes[pipe_id] = plane;
+       blend_setup(crtc);
+       if (mdp5_crtc->enabled && (plane != mdp5_crtc->plane))
+               crtc_flush(crtc);
+}
+
+void mdp5_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
+{
+       set_attach(crtc, mdp5_plane_pipe(plane), plane);
+}
+
+void mdp5_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
+{
+       set_attach(crtc, mdp5_plane_pipe(plane), NULL);
+}
+
+/* initialize crtc */
+struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
+               struct drm_plane *plane, int id)
+{
+       struct drm_crtc *crtc = NULL;
+       struct mdp5_crtc *mdp5_crtc;
+       int ret;
+
+       mdp5_crtc = kzalloc(sizeof(*mdp5_crtc), GFP_KERNEL);
+       if (!mdp5_crtc) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       crtc = &mdp5_crtc->base;
+
+       mdp5_crtc->plane = plane;
+       mdp5_crtc->id = id;
+
+       mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
+       mdp5_crtc->err.irq = mdp5_crtc_err_irq;
+
+       snprintf(mdp5_crtc->name, sizeof(mdp5_crtc->name), "%s:%d",
+                       pipe2name(mdp5_plane_pipe(plane)), id);
+
+       ret = drm_flip_work_init(&mdp5_crtc->unref_fb_work, 16,
+                       "unref fb", unref_fb_worker);
+       if (ret)
+               goto fail;
+
+       INIT_FENCE_CB(&mdp5_crtc->pageflip_cb, pageflip_cb);
+
+       drm_crtc_init(dev, crtc, &mdp5_crtc_funcs);
+       drm_crtc_helper_add(crtc, &mdp5_crtc_helper_funcs);
+
+       mdp5_plane_install_properties(mdp5_crtc->plane, &crtc->base);
+
+       return crtc;
+
+fail:
+       if (crtc)
+               mdp5_crtc_destroy(crtc);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
new file mode 100644 (file)
index 0000000..edec7bf
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "mdp5_kms.h"
+
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+
+struct mdp5_encoder {
+       struct drm_encoder base;
+       int intf;
+       enum mdp5_intf intf_id;
+       bool enabled;
+       uint32_t bsc;
+};
+#define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base)
+
+static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
+{
+       struct msm_drm_private *priv = encoder->dev->dev_private;
+       return to_mdp5_kms(to_mdp_kms(priv->kms));
+}
+
+#ifdef CONFIG_MSM_BUS_SCALING
+#include <mach/board.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)           \
+       {                                               \
+               .src = MSM_BUS_MASTER_MDP_PORT0,        \
+               .dst = MSM_BUS_SLAVE_EBI_CH0,           \
+               .ab = (ab_val),                         \
+               .ib = (ib_val),                         \
+       }
+
+static struct msm_bus_vectors mdp_bus_vectors[] = {
+       MDP_BUS_VECTOR_ENTRY(0, 0),
+       MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000),
+};
+static struct msm_bus_paths mdp_bus_usecases[] = { {
+               .num_paths = 1,
+               .vectors = &mdp_bus_vectors[0],
+}, {
+               .num_paths = 1,
+               .vectors = &mdp_bus_vectors[1],
+} };
+static struct msm_bus_scale_pdata mdp_bus_scale_table = {
+       .usecase = mdp_bus_usecases,
+       .num_usecases = ARRAY_SIZE(mdp_bus_usecases),
+       .name = "mdss_mdp",
+};
+
+static void bs_init(struct mdp5_encoder *mdp5_encoder)
+{
+       mdp5_encoder->bsc = msm_bus_scale_register_client(
+                       &mdp_bus_scale_table);
+       DBG("bus scale client: %08x", mdp5_encoder->bsc);
+}
+
+static void bs_fini(struct mdp5_encoder *mdp5_encoder)
+{
+       if (mdp5_encoder->bsc) {
+               msm_bus_scale_unregister_client(mdp5_encoder->bsc);
+               mdp5_encoder->bsc = 0;
+       }
+}
+
+static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx)
+{
+       if (mdp5_encoder->bsc) {
+               DBG("set bus scaling: %d", idx);
+               /* HACK: scaling down, and then immediately back up
+                * seems to leave things broken (underflow).. so
+                * never disable:
+                */
+               idx = 1;
+               msm_bus_scale_client_update_request(mdp5_encoder->bsc, idx);
+       }
+}
+#else
+static void bs_init(struct mdp5_encoder *mdp5_encoder) {}
+static void bs_fini(struct mdp5_encoder *mdp5_encoder) {}
+static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx) {}
+#endif
+
+static void mdp5_encoder_destroy(struct drm_encoder *encoder)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       bs_fini(mdp5_encoder);
+       drm_encoder_cleanup(encoder);
+       kfree(mdp5_encoder);
+}
+
+static const struct drm_encoder_funcs mdp5_encoder_funcs = {
+       .destroy = mdp5_encoder_destroy,
+};
+
+static void mdp5_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       struct mdp5_kms *mdp5_kms = get_kms(encoder);
+       int intf = mdp5_encoder->intf;
+       bool enabled = (mode == DRM_MODE_DPMS_ON);
+
+       DBG("mode=%d", mode);
+
+       if (enabled == mdp5_encoder->enabled)
+               return;
+
+       if (enabled) {
+               bs_set(mdp5_encoder, 1);
+               mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1);
+       } else {
+               mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0);
+               bs_set(mdp5_encoder, 0);
+       }
+
+       mdp5_encoder->enabled = enabled;
+}
+
+static bool mdp5_encoder_mode_fixup(struct drm_encoder *encoder,
+               const struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       return true;
+}
+
+static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
+               struct drm_display_mode *mode,
+               struct drm_display_mode *adjusted_mode)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       struct mdp5_kms *mdp5_kms = get_kms(encoder);
+       int intf = mdp5_encoder->intf;
+       uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
+       uint32_t display_v_start, display_v_end;
+       uint32_t hsync_start_x, hsync_end_x;
+       uint32_t format;
+
+       mode = adjusted_mode;
+
+       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+                       mode->base.id, mode->name,
+                       mode->vrefresh, mode->clock,
+                       mode->hdisplay, mode->hsync_start,
+                       mode->hsync_end, mode->htotal,
+                       mode->vdisplay, mode->vsync_start,
+                       mode->vsync_end, mode->vtotal,
+                       mode->type, mode->flags);
+
+       ctrl_pol = 0;
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
+       /* probably need to get DATA_EN polarity from panel.. */
+
+       dtv_hsync_skew = 0;  /* get this from panel? */
+       format = 0x213f;     /* get this from panel? */
+
+       hsync_start_x = (mode->htotal - mode->hsync_start);
+       hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
+
+       vsync_period = mode->vtotal * mode->htotal;
+       vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
+       display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew;
+       display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1;
+
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf),
+                       MDP5_INTF_HSYNC_CTL_PULSEW(mode->hsync_end - mode->hsync_start) |
+                       MDP5_INTF_HSYNC_CTL_PERIOD(mode->htotal));
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_PERIOD_F0(intf), vsync_period);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_LEN_F0(intf), vsync_len);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_HCTL(intf),
+                       MDP5_INTF_DISPLAY_HCTL_START(hsync_start_x) |
+                       MDP5_INTF_DISPLAY_HCTL_END(hsync_end_x));
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VSTART_F0(intf), display_v_start);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VEND_F0(intf), display_v_end);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_BORDER_COLOR(intf), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_UNDERFLOW_COLOR(intf), 0xff);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_SKEW(intf), dtv_hsync_skew);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_POLARITY_CTL(intf), ctrl_pol);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_HCTL(intf),
+                       MDP5_INTF_ACTIVE_HCTL_START(0) |
+                       MDP5_INTF_ACTIVE_HCTL_END(0));
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VSTART_F0(intf), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VEND_F0(intf), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_PANEL_FORMAT(intf), format);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(intf), 0x3);  /* frame+line? */
+}
+
+static void mdp5_encoder_prepare(struct drm_encoder *encoder)
+{
+       mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void mdp5_encoder_commit(struct drm_encoder *encoder)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf,
+                       mdp5_encoder->intf_id);
+       mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
+       .dpms = mdp5_encoder_dpms,
+       .mode_fixup = mdp5_encoder_mode_fixup,
+       .mode_set = mdp5_encoder_mode_set,
+       .prepare = mdp5_encoder_prepare,
+       .commit = mdp5_encoder_commit,
+};
+
+/* initialize encoder */
+struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf,
+               enum mdp5_intf intf_id)
+{
+       struct drm_encoder *encoder = NULL;
+       struct mdp5_encoder *mdp5_encoder;
+       int ret;
+
+       mdp5_encoder = kzalloc(sizeof(*mdp5_encoder), GFP_KERNEL);
+       if (!mdp5_encoder) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       mdp5_encoder->intf = intf;
+       mdp5_encoder->intf_id = intf_id;
+       encoder = &mdp5_encoder->base;
+
+       drm_encoder_init(dev, encoder, &mdp5_encoder_funcs,
+                        DRM_MODE_ENCODER_TMDS);
+       drm_encoder_helper_add(encoder, &mdp5_encoder_helper_funcs);
+
+       bs_init(mdp5_encoder);
+
+       return encoder;
+
+fail:
+       if (encoder)
+               mdp5_encoder_destroy(encoder);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
new file mode 100644 (file)
index 0000000..353d494
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
+#include "mdp5_kms.h"
+
+void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask)
+{
+       mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_INTR_EN, irqmask);
+}
+
+static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       DRM_ERROR("errors: %08x\n", irqstatus);
+}
+
+void mdp5_irq_preinstall(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff);
+}
+
+int mdp5_irq_postinstall(struct msm_kms *kms)
+{
+       struct mdp_kms *mdp_kms = to_mdp_kms(kms);
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
+       struct mdp_irq *error_handler = &mdp5_kms->error_handler;
+
+       error_handler->irq = mdp5_irq_error_handler;
+       error_handler->irqmask = MDP5_IRQ_INTF0_UNDER_RUN |
+                       MDP5_IRQ_INTF1_UNDER_RUN |
+                       MDP5_IRQ_INTF2_UNDER_RUN |
+                       MDP5_IRQ_INTF3_UNDER_RUN;
+
+       mdp_irq_register(mdp_kms, error_handler);
+
+       return 0;
+}
+
+void mdp5_irq_uninstall(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
+}
+
+static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
+       struct drm_device *dev = mdp5_kms->dev;
+       struct msm_drm_private *priv = dev->dev_private;
+       unsigned int id;
+       uint32_t status;
+
+       status = mdp5_read(mdp5_kms, REG_MDP5_INTR_STATUS);
+       mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, status);
+
+       VERB("status=%08x", status);
+
+       for (id = 0; id < priv->num_crtcs; id++)
+               if (status & mdp5_crtc_vblank(priv->crtcs[id]))
+                       drm_handle_vblank(dev, id);
+
+       mdp_dispatch_irqs(mdp_kms, status);
+}
+
+irqreturn_t mdp5_irq(struct msm_kms *kms)
+{
+       struct mdp_kms *mdp_kms = to_mdp_kms(kms);
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
+       uint32_t intr;
+
+       intr = mdp5_read(mdp5_kms, REG_MDP5_HW_INTR_STATUS);
+
+       VERB("intr=%08x", intr);
+
+       if (intr & MDP5_HW_INTR_STATUS_INTR_MDP)
+               mdp5_irq_mdp(mdp_kms);
+
+       if (intr & MDP5_HW_INTR_STATUS_INTR_HDMI)
+               hdmi_irq(0, mdp5_kms->hdmi);
+
+       return IRQ_HANDLED;
+}
+
+int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
+{
+       mdp_update_vblank_mask(to_mdp_kms(kms),
+                       mdp5_crtc_vblank(crtc), true);
+       return 0;
+}
+
+void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
+{
+       mdp_update_vblank_mask(to_mdp_kms(kms),
+                       mdp5_crtc_vblank(crtc), false);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
new file mode 100644 (file)
index 0000000..ee8446c
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
+#include "msm_mmu.h"
+#include "mdp5_kms.h"
+
+static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev);
+
+static int mdp5_hw_init(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       struct drm_device *dev = mdp5_kms->dev;
+       uint32_t version, major, minor;
+       int ret = 0;
+
+       pm_runtime_get_sync(dev->dev);
+
+       mdp5_enable(mdp5_kms);
+       version = mdp5_read(mdp5_kms, REG_MDP5_MDP_VERSION);
+       mdp5_disable(mdp5_kms);
+
+       major = FIELD(version, MDP5_MDP_VERSION_MAJOR);
+       minor = FIELD(version, MDP5_MDP_VERSION_MINOR);
+
+       DBG("found MDP5 version v%d.%d", major, minor);
+
+       if ((major != 1) || ((minor != 0) && (minor != 2))) {
+               dev_err(dev->dev, "unexpected MDP version: v%d.%d\n",
+                               major, minor);
+               ret = -ENXIO;
+               goto out;
+       }
+
+       mdp5_kms->rev = minor;
+
+       /* Magic unknown register writes:
+        *
+        *    W VBIF:0x004 00000001      (mdss_mdp.c:839)
+        *    W MDP5:0x2e0 0xe9          (mdss_mdp.c:839)
+        *    W MDP5:0x2e4 0x55          (mdss_mdp.c:839)
+        *    W MDP5:0x3ac 0xc0000ccc    (mdss_mdp.c:839)
+        *    W MDP5:0x3b4 0xc0000ccc    (mdss_mdp.c:839)
+        *    W MDP5:0x3bc 0xcccccc      (mdss_mdp.c:839)
+        *    W MDP5:0x4a8 0xcccc0c0     (mdss_mdp.c:839)
+        *    W MDP5:0x4b0 0xccccc0c0    (mdss_mdp.c:839)
+        *    W MDP5:0x4b8 0xccccc000    (mdss_mdp.c:839)
+        *
+        * Downstream fbdev driver gets these register offsets/values
+        * from DT.. not really sure what these registers are or if
+        * different values for different boards/SoC's, etc.  I guess
+        * they are the golden registers.
+        *
+        * Not setting these does not seem to cause any problem.  But
+        * we may be getting lucky with the bootloader initializing
+        * them for us.  OTOH, if we can always count on the bootloader
+        * setting the golden registers, then perhaps we don't need to
+        * care.
+        */
+
+       mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(0), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(1), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(2), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(3), 0);
+
+out:
+       pm_runtime_put_sync(dev->dev);
+
+       return ret;
+}
+
+static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,
+               struct drm_encoder *encoder)
+{
+       return rate;
+}
+
+static void mdp5_preclose(struct msm_kms *kms, struct drm_file *file)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       struct msm_drm_private *priv = mdp5_kms->dev->dev_private;
+       unsigned i;
+
+       for (i = 0; i < priv->num_crtcs; i++)
+               mdp5_crtc_cancel_pending_flip(priv->crtcs[i], file);
+}
+
+static void mdp5_destroy(struct msm_kms *kms)
+{
+       struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       kfree(mdp5_kms);
+}
+
+static const struct mdp_kms_funcs kms_funcs = {
+       .base = {
+               .hw_init         = mdp5_hw_init,
+               .irq_preinstall  = mdp5_irq_preinstall,
+               .irq_postinstall = mdp5_irq_postinstall,
+               .irq_uninstall   = mdp5_irq_uninstall,
+               .irq             = mdp5_irq,
+               .enable_vblank   = mdp5_enable_vblank,
+               .disable_vblank  = mdp5_disable_vblank,
+               .get_format      = mdp_get_format,
+               .round_pixclk    = mdp5_round_pixclk,
+               .preclose        = mdp5_preclose,
+               .destroy         = mdp5_destroy,
+       },
+       .set_irqmask         = mdp5_set_irqmask,
+};
+
+int mdp5_disable(struct mdp5_kms *mdp5_kms)
+{
+       DBG("");
+
+       clk_disable_unprepare(mdp5_kms->ahb_clk);
+       clk_disable_unprepare(mdp5_kms->axi_clk);
+       clk_disable_unprepare(mdp5_kms->core_clk);
+       clk_disable_unprepare(mdp5_kms->lut_clk);
+
+       return 0;
+}
+
+int mdp5_enable(struct mdp5_kms *mdp5_kms)
+{
+       DBG("");
+
+       clk_prepare_enable(mdp5_kms->ahb_clk);
+       clk_prepare_enable(mdp5_kms->axi_clk);
+       clk_prepare_enable(mdp5_kms->core_clk);
+       clk_prepare_enable(mdp5_kms->lut_clk);
+
+       return 0;
+}
+
+static int modeset_init(struct mdp5_kms *mdp5_kms)
+{
+       static const enum mdp5_pipe crtcs[] = {
+                       SSPP_RGB0, SSPP_RGB1, SSPP_RGB2,
+       };
+       struct drm_device *dev = mdp5_kms->dev;
+       struct msm_drm_private *priv = dev->dev_private;
+       struct drm_encoder *encoder;
+       int i, ret;
+
+       /* construct CRTCs: */
+       for (i = 0; i < ARRAY_SIZE(crtcs); i++) {
+               struct drm_plane *plane;
+               struct drm_crtc *crtc;
+
+               plane = mdp5_plane_init(dev, crtcs[i], true);
+               if (IS_ERR(plane)) {
+                       ret = PTR_ERR(plane);
+                       dev_err(dev->dev, "failed to construct plane for %s (%d)\n",
+                                       pipe2name(crtcs[i]), ret);
+                       goto fail;
+               }
+
+               crtc  = mdp5_crtc_init(dev, plane, i);
+               if (IS_ERR(crtc)) {
+                       ret = PTR_ERR(crtc);
+                       dev_err(dev->dev, "failed to construct crtc for %s (%d)\n",
+                                       pipe2name(crtcs[i]), ret);
+                       goto fail;
+               }
+               priv->crtcs[priv->num_crtcs++] = crtc;
+       }
+
+       /* Construct encoder for HDMI: */
+       encoder = mdp5_encoder_init(dev, 3, INTF_HDMI);
+       if (IS_ERR(encoder)) {
+               dev_err(dev->dev, "failed to construct encoder\n");
+               ret = PTR_ERR(encoder);
+               goto fail;
+       }
+
+       /* NOTE: the vsync and error irq's are actually associated with
+        * the INTF/encoder.. the easiest way to deal with this (ie. what
+        * we do now) is assume a fixed relationship between crtc's and
+        * encoders.  I'm not sure if there is ever a need to more freely
+        * assign crtcs to encoders, but if there is then we need to take
+        * care of error and vblank irq's that the crtc has registered,
+        * and also update user-requested vblank_mask.
+        */
+       encoder->possible_crtcs = BIT(0);
+       mdp5_crtc_set_intf(priv->crtcs[0], 3, INTF_HDMI);
+
+       priv->encoders[priv->num_encoders++] = encoder;
+
+       /* Construct bridge/connector for HDMI: */
+       mdp5_kms->hdmi = hdmi_init(dev, encoder);
+       if (IS_ERR(mdp5_kms->hdmi)) {
+               ret = PTR_ERR(mdp5_kms->hdmi);
+               dev_err(dev->dev, "failed to initialize HDMI: %d\n", ret);
+               goto fail;
+       }
+
+       return 0;
+
+fail:
+       return ret;
+}
+
+static const char *iommu_ports[] = {
+               "mdp_0",
+};
+
+static int get_clk(struct platform_device *pdev, struct clk **clkp,
+               const char *name)
+{
+       struct device *dev = &pdev->dev;
+       struct clk *clk = devm_clk_get(dev, name);
+       if (IS_ERR(clk)) {
+               dev_err(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk));
+               return PTR_ERR(clk);
+       }
+       *clkp = clk;
+       return 0;
+}
+
+struct msm_kms *mdp5_kms_init(struct drm_device *dev)
+{
+       struct platform_device *pdev = dev->platformdev;
+       struct mdp5_platform_config *config = mdp5_get_config(pdev);
+       struct mdp5_kms *mdp5_kms;
+       struct msm_kms *kms = NULL;
+       struct msm_mmu *mmu;
+       int ret;
+
+       mdp5_kms = kzalloc(sizeof(*mdp5_kms), GFP_KERNEL);
+       if (!mdp5_kms) {
+               dev_err(dev->dev, "failed to allocate kms\n");
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       mdp_kms_init(&mdp5_kms->base, &kms_funcs);
+
+       kms = &mdp5_kms->base.base;
+
+       mdp5_kms->dev = dev;
+       mdp5_kms->smp_blk_cnt = config->smp_blk_cnt;
+
+       mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5");
+       if (IS_ERR(mdp5_kms->mmio)) {
+               ret = PTR_ERR(mdp5_kms->mmio);
+               goto fail;
+       }
+
+       mdp5_kms->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF");
+       if (IS_ERR(mdp5_kms->vbif)) {
+               ret = PTR_ERR(mdp5_kms->vbif);
+               goto fail;
+       }
+
+       mdp5_kms->vdd = devm_regulator_get(&pdev->dev, "vdd");
+       if (IS_ERR(mdp5_kms->vdd)) {
+               ret = PTR_ERR(mdp5_kms->vdd);
+               goto fail;
+       }
+
+       ret = regulator_enable(mdp5_kms->vdd);
+       if (ret) {
+               dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret);
+               goto fail;
+       }
+
+       ret = get_clk(pdev, &mdp5_kms->axi_clk, "bus_clk") ||
+                       get_clk(pdev, &mdp5_kms->ahb_clk, "iface_clk") ||
+                       get_clk(pdev, &mdp5_kms->src_clk, "core_clk_src") ||
+                       get_clk(pdev, &mdp5_kms->core_clk, "core_clk") ||
+                       get_clk(pdev, &mdp5_kms->lut_clk, "lut_clk") ||
+                       get_clk(pdev, &mdp5_kms->vsync_clk, "vsync_clk");
+       if (ret)
+               goto fail;
+
+       ret = clk_set_rate(mdp5_kms->src_clk, config->max_clk);
+
+       /* make sure things are off before attaching iommu (bootloader could
+        * have left things on, in which case we'll start getting faults if
+        * we don't disable):
+        */
+       mdp5_enable(mdp5_kms);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(0), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(1), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(2), 0);
+       mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(3), 0);
+       mdp5_disable(mdp5_kms);
+       mdelay(16);
+
+       if (config->iommu) {
+               mmu = msm_iommu_new(dev, config->iommu);
+               if (IS_ERR(mmu)) {
+                       ret = PTR_ERR(mmu);
+                       goto fail;
+               }
+               ret = mmu->funcs->attach(mmu, iommu_ports,
+                               ARRAY_SIZE(iommu_ports));
+               if (ret)
+                       goto fail;
+       } else {
+               dev_info(dev->dev, "no iommu, fallback to phys "
+                               "contig buffers for scanout\n");
+               mmu = NULL;
+       }
+
+       mdp5_kms->id = msm_register_mmu(dev, mmu);
+       if (mdp5_kms->id < 0) {
+               ret = mdp5_kms->id;
+               dev_err(dev->dev, "failed to register mdp5 iommu: %d\n", ret);
+               goto fail;
+       }
+
+       ret = modeset_init(mdp5_kms);
+       if (ret) {
+               dev_err(dev->dev, "modeset_init failed: %d\n", ret);
+               goto fail;
+       }
+
+       return kms;
+
+fail:
+       if (kms)
+               mdp5_destroy(kms);
+       return ERR_PTR(ret);
+}
+
+static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev)
+{
+       static struct mdp5_platform_config config = {};
+#ifdef CONFIG_OF
+       /* TODO */
+#endif
+       return &config;
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
new file mode 100644 (file)
index 0000000..c8b1a25
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MDP5_KMS_H__
+#define __MDP5_KMS_H__
+
+#include "msm_drv.h"
+#include "msm_kms.h"
+#include "mdp/mdp_kms.h"
+#include "mdp5.xml.h"
+#include "mdp5_smp.h"
+
+struct mdp5_kms {
+       struct mdp_kms base;
+
+       struct drm_device *dev;
+
+       int rev;
+
+       /* mapper-id used to request GEM buffer mapped for scanout: */
+       int id;
+
+       /* for tracking smp allocation amongst pipes: */
+       mdp5_smp_state_t smp_state;
+       struct mdp5_client_smp_state smp_client_state[CID_MAX];
+       int smp_blk_cnt;
+
+       /* io/register spaces: */
+       void __iomem *mmio, *vbif;
+
+       struct regulator *vdd;
+
+       struct clk *axi_clk;
+       struct clk *ahb_clk;
+       struct clk *src_clk;
+       struct clk *core_clk;
+       struct clk *lut_clk;
+       struct clk *vsync_clk;
+
+       struct hdmi *hdmi;
+
+       struct mdp_irq error_handler;
+};
+#define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
+
+/* platform config data (ie. from DT, or pdata) */
+struct mdp5_platform_config {
+       struct iommu_domain *iommu;
+       uint32_t max_clk;
+       int smp_blk_cnt;
+};
+
+static inline void mdp5_write(struct mdp5_kms *mdp5_kms, u32 reg, u32 data)
+{
+       msm_writel(data, mdp5_kms->mmio + reg);
+}
+
+static inline u32 mdp5_read(struct mdp5_kms *mdp5_kms, u32 reg)
+{
+       return msm_readl(mdp5_kms->mmio + reg);
+}
+
+static inline const char *pipe2name(enum mdp5_pipe pipe)
+{
+       static const char *names[] = {
+#define NAME(n) [SSPP_ ## n] = #n
+               NAME(VIG0), NAME(VIG1), NAME(VIG2),
+               NAME(RGB0), NAME(RGB1), NAME(RGB2),
+               NAME(DMA0), NAME(DMA1),
+#undef NAME
+       };
+       return names[pipe];
+}
+
+static inline uint32_t pipe2flush(enum mdp5_pipe pipe)
+{
+       switch (pipe) {
+       case SSPP_VIG0: return MDP5_CTL_FLUSH_VIG0;
+       case SSPP_VIG1: return MDP5_CTL_FLUSH_VIG1;
+       case SSPP_VIG2: return MDP5_CTL_FLUSH_VIG2;
+       case SSPP_RGB0: return MDP5_CTL_FLUSH_RGB0;
+       case SSPP_RGB1: return MDP5_CTL_FLUSH_RGB1;
+       case SSPP_RGB2: return MDP5_CTL_FLUSH_RGB2;
+       case SSPP_DMA0: return MDP5_CTL_FLUSH_DMA0;
+       case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
+       default:        return 0;
+       }
+}
+
+static inline int pipe2nclients(enum mdp5_pipe pipe)
+{
+       switch (pipe) {
+       case SSPP_RGB0:
+       case SSPP_RGB1:
+       case SSPP_RGB2:
+               return 1;
+       default:
+               return 3;
+       }
+}
+
+static inline enum mdp5_client_id pipe2client(enum mdp5_pipe pipe, int plane)
+{
+       WARN_ON(plane >= pipe2nclients(pipe));
+       switch (pipe) {
+       case SSPP_VIG0: return CID_VIG0_Y + plane;
+       case SSPP_VIG1: return CID_VIG1_Y + plane;
+       case SSPP_VIG2: return CID_VIG2_Y + plane;
+       case SSPP_RGB0: return CID_RGB0;
+       case SSPP_RGB1: return CID_RGB1;
+       case SSPP_RGB2: return CID_RGB2;
+       case SSPP_DMA0: return CID_DMA0_Y + plane;
+       case SSPP_DMA1: return CID_DMA1_Y + plane;
+       default:        return CID_UNUSED;
+       }
+}
+
+static inline uint32_t mixer2flush(int lm)
+{
+       switch (lm) {
+       case 0:  return MDP5_CTL_FLUSH_LM0;
+       case 1:  return MDP5_CTL_FLUSH_LM1;
+       case 2:  return MDP5_CTL_FLUSH_LM2;
+       default: return 0;
+       }
+}
+
+static inline uint32_t intf2err(int intf)
+{
+       switch (intf) {
+       case 0:  return MDP5_IRQ_INTF0_UNDER_RUN;
+       case 1:  return MDP5_IRQ_INTF1_UNDER_RUN;
+       case 2:  return MDP5_IRQ_INTF2_UNDER_RUN;
+       case 3:  return MDP5_IRQ_INTF3_UNDER_RUN;
+       default: return 0;
+       }
+}
+
+static inline uint32_t intf2vblank(int intf)
+{
+       switch (intf) {
+       case 0:  return MDP5_IRQ_INTF0_VSYNC;
+       case 1:  return MDP5_IRQ_INTF1_VSYNC;
+       case 2:  return MDP5_IRQ_INTF2_VSYNC;
+       case 3:  return MDP5_IRQ_INTF3_VSYNC;
+       default: return 0;
+       }
+}
+
+int mdp5_disable(struct mdp5_kms *mdp5_kms);
+int mdp5_enable(struct mdp5_kms *mdp5_kms);
+
+void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask);
+void mdp5_irq_preinstall(struct msm_kms *kms);
+int mdp5_irq_postinstall(struct msm_kms *kms);
+void mdp5_irq_uninstall(struct msm_kms *kms);
+irqreturn_t mdp5_irq(struct msm_kms *kms);
+int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
+void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
+
+static inline
+uint32_t mdp5_get_formats(enum mdp5_pipe pipe, uint32_t *pixel_formats,
+               uint32_t max_formats)
+{
+       /* TODO when we have YUV, we need to filter supported formats
+        * based on pipe id..
+        */
+       return mdp_get_formats(pixel_formats, max_formats);
+}
+
+void mdp5_plane_install_properties(struct drm_plane *plane,
+               struct drm_mode_object *obj);
+void mdp5_plane_set_scanout(struct drm_plane *plane,
+               struct drm_framebuffer *fb);
+int mdp5_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);
+void mdp5_plane_complete_flip(struct drm_plane *plane);
+enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+               enum mdp5_pipe pipe, bool private_plane);
+
+uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
+
+void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
+void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf,
+               enum mdp5_intf intf_id);
+void mdp5_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane);
+void mdp5_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane);
+struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
+               struct drm_plane *plane, int id);
+
+struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, int intf,
+               enum mdp5_intf intf_id);
+
+#endif /* __MDP5_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
new file mode 100644 (file)
index 0000000..0ac8bb5
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "mdp5_kms.h"
+
+
+struct mdp5_plane {
+       struct drm_plane base;
+       const char *name;
+
+       enum mdp5_pipe pipe;
+
+       uint32_t nformats;
+       uint32_t formats[32];
+
+       bool enabled;
+};
+#define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base)
+
+static struct mdp5_kms *get_kms(struct drm_plane *plane)
+{
+       struct msm_drm_private *priv = plane->dev->dev_private;
+       return to_mdp5_kms(to_mdp_kms(priv->kms));
+}
+
+static int mdp5_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)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+
+       mdp5_plane->enabled = true;
+
+       if (plane->fb)
+               drm_framebuffer_unreference(plane->fb);
+
+       drm_framebuffer_reference(fb);
+
+       return mdp5_plane_mode_set(plane, crtc, fb,
+                       crtc_x, crtc_y, crtc_w, crtc_h,
+                       src_x, src_y, src_w, src_h);
+}
+
+static int mdp5_plane_disable(struct drm_plane *plane)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       int i;
+
+       DBG("%s: disable", mdp5_plane->name);
+
+       /* update our SMP request to zero (release all our blks): */
+       for (i = 0; i < pipe2nclients(pipe); i++)
+               mdp5_smp_request(mdp5_kms, pipe2client(pipe, i), 0);
+
+       /* TODO detaching now will cause us not to get the last
+        * vblank and mdp5_smp_commit().. so other planes will
+        * still see smp blocks previously allocated to us as
+        * in-use..
+        */
+       if (plane->crtc)
+               mdp5_crtc_detach(plane->crtc, plane);
+
+       return 0;
+}
+
+static void mdp5_plane_destroy(struct drm_plane *plane)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+
+       mdp5_plane_disable(plane);
+       drm_plane_cleanup(plane);
+
+       kfree(mdp5_plane);
+}
+
+/* helper to install properties which are common to planes and crtcs */
+void mdp5_plane_install_properties(struct drm_plane *plane,
+               struct drm_mode_object *obj)
+{
+       // XXX
+}
+
+int mdp5_plane_set_property(struct drm_plane *plane,
+               struct drm_property *property, uint64_t val)
+{
+       // XXX
+       return -EINVAL;
+}
+
+static const struct drm_plane_funcs mdp5_plane_funcs = {
+               .update_plane = mdp5_plane_update,
+               .disable_plane = mdp5_plane_disable,
+               .destroy = mdp5_plane_destroy,
+               .set_property = mdp5_plane_set_property,
+};
+
+void mdp5_plane_set_scanout(struct drm_plane *plane,
+               struct drm_framebuffer *fb)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       uint32_t nplanes = drm_format_num_planes(fb->pixel_format);
+       uint32_t iova[4];
+       int i;
+
+       for (i = 0; i < nplanes; i++) {
+               struct drm_gem_object *bo = msm_framebuffer_bo(fb, i);
+               msm_gem_get_iova(bo, mdp5_kms->id, &iova[i]);
+       }
+       for (; i < 4; i++)
+               iova[i] = 0;
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_A(pipe),
+                       MDP5_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
+                       MDP5_PIPE_SRC_STRIDE_A_P1(fb->pitches[1]));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_B(pipe),
+                       MDP5_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) |
+                       MDP5_PIPE_SRC_STRIDE_B_P3(fb->pitches[3]));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC0_ADDR(pipe), iova[0]);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC1_ADDR(pipe), iova[1]);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC2_ADDR(pipe), iova[2]);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC3_ADDR(pipe), iova[3]);
+
+       plane->fb = fb;
+}
+
+/* NOTE: looks like if horizontal decimation is used (if we supported that)
+ * then the width used to calculate SMP block requirements is the post-
+ * decimated width.  Ie. SMP buffering sits downstream of decimation (which
+ * presumably happens during the dma from scanout buffer).
+ */
+static int request_smp_blocks(struct drm_plane *plane, uint32_t format,
+               uint32_t nplanes, uint32_t width)
+{
+       struct drm_device *dev = plane->dev;
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       int i, hsub, nlines, nblks, ret;
+
+       hsub = drm_format_horz_chroma_subsampling(format);
+
+       /* different if BWC (compressed framebuffer?) enabled: */
+       nlines = 2;
+
+       for (i = 0, nblks = 0; i < nplanes; i++) {
+               int n, fetch_stride, cpp;
+
+               cpp = drm_format_plane_cpp(format, i);
+               fetch_stride = width * cpp / (i ? hsub : 1);
+
+               n = DIV_ROUND_UP(fetch_stride * nlines, SMP_BLK_SIZE);
+
+               /* for hw rev v1.00 */
+               if (mdp5_kms->rev == 0)
+                       n = roundup_pow_of_two(n);
+
+               DBG("%s[%d]: request %d SMP blocks", mdp5_plane->name, i, n);
+               ret = mdp5_smp_request(mdp5_kms, pipe2client(pipe, i), n);
+               if (ret) {
+                       dev_err(dev->dev, "Could not allocate %d SMP blocks: %d\n",
+                                       n, ret);
+                       return ret;
+               }
+
+               nblks += n;
+       }
+
+       /* in success case, return total # of blocks allocated: */
+       return nblks;
+}
+
+static void set_fifo_thresholds(struct drm_plane *plane, int nblks)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       uint32_t val;
+
+       /* 1/4 of SMP pool that is being fetched */
+       val = (nblks * SMP_ENTRIES_PER_BLK) / 4;
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(pipe), val * 1);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(pipe), val * 2);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(pipe), val * 3);
+
+}
+
+int mdp5_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 mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = mdp5_plane->pipe;
+       const struct mdp_format *format;
+       uint32_t nplanes, config = 0;
+       uint32_t phasex_step = 0, phasey_step = 0;
+       uint32_t hdecm = 0, vdecm = 0;
+       int i, nblks;
+
+       nplanes = drm_format_num_planes(fb->pixel_format);
+
+       /* bad formats should already be rejected: */
+       if (WARN_ON(nplanes > pipe2nclients(pipe)))
+               return -EINVAL;
+
+       /* 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;
+
+       DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp5_plane->name,
+                       fb->base.id, src_x, src_y, src_w, src_h,
+                       crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
+
+       /*
+        * Calculate and request required # of smp blocks:
+        */
+       nblks = request_smp_blocks(plane, fb->pixel_format, nplanes, src_w);
+       if (nblks < 0)
+               return nblks;
+
+       /*
+        * Currently we update the hw for allocations/requests immediately,
+        * but once atomic modeset/pageflip is in place, the allocation
+        * would move into atomic->check_plane_state(), while updating the
+        * hw would remain here:
+        */
+       for (i = 0; i < pipe2nclients(pipe); i++)
+               mdp5_smp_configure(mdp5_kms, pipe2client(pipe, i));
+
+       if (src_w != crtc_w) {
+               config |= MDP5_PIPE_SCALE_CONFIG_SCALEX_EN;
+               /* TODO calc phasex_step, hdecm */
+       }
+
+       if (src_h != crtc_h) {
+               config |= MDP5_PIPE_SCALE_CONFIG_SCALEY_EN;
+               /* TODO calc phasey_step, vdecm */
+       }
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_IMG_SIZE(pipe),
+                       MDP5_PIPE_SRC_IMG_SIZE_WIDTH(src_w) |
+                       MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(src_h));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_SIZE(pipe),
+                       MDP5_PIPE_SRC_SIZE_WIDTH(src_w) |
+                       MDP5_PIPE_SRC_SIZE_HEIGHT(src_h));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_XY(pipe),
+                       MDP5_PIPE_SRC_XY_X(src_x) |
+                       MDP5_PIPE_SRC_XY_Y(src_y));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_OUT_SIZE(pipe),
+                       MDP5_PIPE_OUT_SIZE_WIDTH(crtc_w) |
+                       MDP5_PIPE_OUT_SIZE_HEIGHT(crtc_h));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_OUT_XY(pipe),
+                       MDP5_PIPE_OUT_XY_X(crtc_x) |
+                       MDP5_PIPE_OUT_XY_Y(crtc_y));
+
+       mdp5_plane_set_scanout(plane, fb);
+
+       format = to_mdp_format(msm_framebuffer_format(fb));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_FORMAT(pipe),
+                       MDP5_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
+                       MDP5_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
+                       MDP5_PIPE_SRC_FORMAT_G_BPC(format->bpc_g) |
+                       MDP5_PIPE_SRC_FORMAT_B_BPC(format->bpc_b) |
+                       COND(format->alpha_enable, MDP5_PIPE_SRC_FORMAT_ALPHA_ENABLE) |
+                       MDP5_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
+                       MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
+                       COND(format->unpack_tight, MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT) |
+                       MDP5_PIPE_SRC_FORMAT_NUM_PLANES(nplanes - 1) |
+                       MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(CHROMA_RGB));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_UNPACK(pipe),
+                       MDP5_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
+                       MDP5_PIPE_SRC_UNPACK_ELEM1(format->unpack[1]) |
+                       MDP5_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) |
+                       MDP5_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_OP_MODE(pipe),
+                       MDP5_PIPE_SRC_OP_MODE_BWC(BWC_LOSSLESS));
+
+       /* not using secure mode: */
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
+
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe), phasex_step);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe), phasey_step);
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
+                       MDP5_PIPE_DECIMATION_VERT(vdecm) |
+                       MDP5_PIPE_DECIMATION_HORZ(hdecm));
+       mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe),
+                       MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(SCALE_FILTER_NEAREST) |
+                       MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(SCALE_FILTER_NEAREST));
+
+       set_fifo_thresholds(plane, nblks);
+
+       /* TODO detach from old crtc (if we had more than one) */
+       mdp5_crtc_attach(crtc, plane);
+
+       return 0;
+}
+
+void mdp5_plane_complete_flip(struct drm_plane *plane)
+{
+       struct mdp5_kms *mdp5_kms = get_kms(plane);
+       enum mdp5_pipe pipe = to_mdp5_plane(plane)->pipe;
+       int i;
+
+       for (i = 0; i < pipe2nclients(pipe); i++)
+               mdp5_smp_commit(mdp5_kms, pipe2client(pipe, i));
+}
+
+enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
+{
+       struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+       return mdp5_plane->pipe;
+}
+
+/* initialize plane */
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+               enum mdp5_pipe pipe, bool private_plane)
+{
+       struct drm_plane *plane = NULL;
+       struct mdp5_plane *mdp5_plane;
+       int ret;
+
+       mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
+       if (!mdp5_plane) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       plane = &mdp5_plane->base;
+
+       mdp5_plane->pipe = pipe;
+       mdp5_plane->name = pipe2name(pipe);
+
+       mdp5_plane->nformats = mdp5_get_formats(pipe, mdp5_plane->formats,
+                       ARRAY_SIZE(mdp5_plane->formats));
+
+       drm_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
+                       mdp5_plane->formats, mdp5_plane->nformats,
+                       private_plane);
+
+       mdp5_plane_install_properties(plane, &plane->base);
+
+       return plane;
+
+fail:
+       if (plane)
+               mdp5_plane_destroy(plane);
+
+       return ERR_PTR(ret);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
new file mode 100644 (file)
index 0000000..2d0236b
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "mdp5_kms.h"
+#include "mdp5_smp.h"
+
+
+/* SMP - Shared Memory Pool
+ *
+ * These are shared between all the clients, where each plane in a
+ * scanout buffer is a SMP client.  Ie. scanout of 3 plane I420 on
+ * pipe VIG0 => 3 clients: VIG0_Y, VIG0_CB, VIG0_CR.
+ *
+ * Based on the size of the attached scanout buffer, a certain # of
+ * blocks must be allocated to that client out of the shared pool.
+ *
+ * For each block, it can be either free, or pending/in-use by a
+ * client.  The updates happen in three steps:
+ *
+ *  1) mdp5_smp_request():
+ *     When plane scanout is setup, calculate required number of
+ *     blocks needed per client, and request.  Blocks not inuse or
+ *     pending by any other client are added to client's pending
+ *     set.
+ *
+ *  2) mdp5_smp_configure():
+ *     As hw is programmed, before FLUSH, MDP5_SMP_ALLOC registers
+ *     are configured for the union(pending, inuse)
+ *
+ *  3) mdp5_smp_commit():
+ *     After next vblank, copy pending -> inuse.  Optionally update
+ *     MDP5_SMP_ALLOC registers if there are newly unused blocks
+ *
+ * On the next vblank after changes have been committed to hw, the
+ * client's pending blocks become it's in-use blocks (and no-longer
+ * in-use blocks become available to other clients).
+ *
+ * btw, hurray for confusing overloaded acronyms!  :-/
+ *
+ * NOTE: for atomic modeset/pageflip NONBLOCK operations, step #1
+ * should happen at (or before)? atomic->check().  And we'd need
+ * an API to discard previous requests if update is aborted or
+ * (test-only).
+ *
+ * TODO would perhaps be nice to have debugfs to dump out kernel
+ * inuse and pending state of all clients..
+ */
+
+static DEFINE_SPINLOCK(smp_lock);
+
+
+/* step #1: update # of blocks pending for the client: */
+int mdp5_smp_request(struct mdp5_kms *mdp5_kms,
+               enum mdp5_client_id cid, int nblks)
+{
+       struct mdp5_client_smp_state *ps = &mdp5_kms->smp_client_state[cid];
+       int i, ret, avail, cur_nblks, cnt = mdp5_kms->smp_blk_cnt;
+       unsigned long flags;
+
+       spin_lock_irqsave(&smp_lock, flags);
+
+       avail = cnt - bitmap_weight(mdp5_kms->smp_state, cnt);
+       if (nblks > avail) {
+               ret = -ENOSPC;
+               goto fail;
+       }
+
+       cur_nblks = bitmap_weight(ps->pending, cnt);
+       if (nblks > cur_nblks) {
+               /* grow the existing pending reservation: */
+               for (i = cur_nblks; i < nblks; i++) {
+                       int blk = find_first_zero_bit(mdp5_kms->smp_state, cnt);
+                       set_bit(blk, ps->pending);
+                       set_bit(blk, mdp5_kms->smp_state);
+               }
+       } else {
+               /* shrink the existing pending reservation: */
+               for (i = cur_nblks; i > nblks; i--) {
+                       int blk = find_first_bit(ps->pending, cnt);
+                       clear_bit(blk, ps->pending);
+                       /* don't clear in global smp_state until _commit() */
+               }
+       }
+
+fail:
+       spin_unlock_irqrestore(&smp_lock, flags);
+       return 0;
+}
+
+static void update_smp_state(struct mdp5_kms *mdp5_kms,
+               enum mdp5_client_id cid, mdp5_smp_state_t *assigned)
+{
+       int cnt = mdp5_kms->smp_blk_cnt;
+       uint32_t blk, val;
+
+       for_each_set_bit(blk, *assigned, cnt) {
+               int idx = blk / 3;
+               int fld = blk % 3;
+
+               val = mdp5_read(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(idx));
+
+               switch (fld) {
+               case 0:
+                       val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT0__MASK;
+                       val |= MDP5_SMP_ALLOC_W_REG_CLIENT0(cid);
+                       break;
+               case 1:
+                       val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT1__MASK;
+                       val |= MDP5_SMP_ALLOC_W_REG_CLIENT1(cid);
+                       break;
+               case 2:
+                       val &= ~MDP5_SMP_ALLOC_W_REG_CLIENT2__MASK;
+                       val |= MDP5_SMP_ALLOC_W_REG_CLIENT2(cid);
+                       break;
+               }
+
+               mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(idx), val);
+               mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_R_REG(idx), val);
+       }
+}
+
+/* step #2: configure hw for union(pending, inuse): */
+void mdp5_smp_configure(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid)
+{
+       struct mdp5_client_smp_state *ps = &mdp5_kms->smp_client_state[cid];
+       int cnt = mdp5_kms->smp_blk_cnt;
+       mdp5_smp_state_t assigned;
+
+       bitmap_or(assigned, ps->inuse, ps->pending, cnt);
+       update_smp_state(mdp5_kms, cid, &assigned);
+}
+
+/* step #3: after vblank, copy pending -> inuse: */
+void mdp5_smp_commit(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid)
+{
+       struct mdp5_client_smp_state *ps = &mdp5_kms->smp_client_state[cid];
+       int cnt = mdp5_kms->smp_blk_cnt;
+       mdp5_smp_state_t released;
+
+       /*
+        * Figure out if there are any blocks we where previously
+        * using, which can be released and made available to other
+        * clients:
+        */
+       if (bitmap_andnot(released, ps->inuse, ps->pending, cnt)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&smp_lock, flags);
+               /* clear released blocks: */
+               bitmap_andnot(mdp5_kms->smp_state, mdp5_kms->smp_state,
+                               released, cnt);
+               spin_unlock_irqrestore(&smp_lock, flags);
+
+               update_smp_state(mdp5_kms, CID_UNUSED, &released);
+       }
+
+       bitmap_copy(ps->inuse, ps->pending, cnt);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
new file mode 100644 (file)
index 0000000..0ab739e
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MDP5_SMP_H__
+#define __MDP5_SMP_H__
+
+#include "msm_drv.h"
+
+#define MAX_SMP_BLOCKS  22
+#define SMP_BLK_SIZE    4096
+#define SMP_ENTRIES_PER_BLK (SMP_BLK_SIZE / 16)
+
+typedef DECLARE_BITMAP(mdp5_smp_state_t, MAX_SMP_BLOCKS);
+
+struct mdp5_client_smp_state {
+       mdp5_smp_state_t inuse;
+       mdp5_smp_state_t pending;
+};
+
+struct mdp5_kms;
+
+int mdp5_smp_request(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid, int nblks);
+void mdp5_smp_configure(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid);
+void mdp5_smp_commit(struct mdp5_kms *mdp5_kms, enum mdp5_client_id cid);
+
+
+#endif /* __MDP5_SMP_H__ */
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
new file mode 100644 (file)
index 0000000..a9629b8
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef MDP_COMMON_XML
+#define MDP_COMMON_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2013-12-03 20:59:13)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  20932 bytes, from 2013-12-01 15:13:04)
+
+Copyright (C) 2013 by the following authors:
+- Rob Clark <robdclark@gmail.com> (robclark)
+
+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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+*/
+
+
+enum mdp_mixer_stage_id {
+       STAGE_UNUSED = 0,
+       STAGE_BASE = 1,
+       STAGE0 = 2,
+       STAGE1 = 3,
+       STAGE2 = 4,
+       STAGE3 = 5,
+};
+
+enum mdp_alpha_type {
+       FG_CONST = 0,
+       BG_CONST = 1,
+       FG_PIXEL = 2,
+       BG_PIXEL = 3,
+};
+
+enum mdp_bpc {
+       BPC1 = 0,
+       BPC5 = 1,
+       BPC6 = 2,
+       BPC8 = 3,
+};
+
+enum mdp_bpc_alpha {
+       BPC1A = 0,
+       BPC4A = 1,
+       BPC6A = 2,
+       BPC8A = 3,
+};
+
+
+#endif /* MDP_COMMON_XML */
diff --git a/drivers/gpu/drm/msm/mdp/mdp_format.c b/drivers/gpu/drm/msm/mdp/mdp_format.c
new file mode 100644 (file)
index 0000000..e0a6ffb
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
+#include "mdp_kms.h"
+
+#define FMT(name, a, r, g, b, e0, e1, e2, e3, alpha, tight, c, cnt) { \
+               .base = { .pixel_format = DRM_FORMAT_ ## name }, \
+               .bpc_a = BPC ## a ## A,                          \
+               .bpc_r = BPC ## r,                               \
+               .bpc_g = BPC ## g,                               \
+               .bpc_b = BPC ## b,                               \
+               .unpack = { e0, e1, e2, e3 },                    \
+               .alpha_enable = alpha,                           \
+               .unpack_tight = tight,                           \
+               .cpp = c,                                        \
+               .unpack_count = cnt,                             \
+       }
+
+#define BPC0A 0
+
+static const struct mdp_format formats[] = {
+       /*  name      a  r  g  b   e0 e1 e2 e3  alpha   tight  cpp cnt */
+       FMT(ARGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  true,   true,  4,  4),
+       FMT(XRGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  false,  true,  4,  4),
+       FMT(RGB888,   0, 8, 8, 8,  1, 0, 2, 0,  false,  true,  3,  3),
+       FMT(BGR888,   0, 8, 8, 8,  2, 0, 1, 0,  false,  true,  3,  3),
+       FMT(RGB565,   0, 5, 6, 5,  1, 0, 2, 0,  false,  true,  2,  3),
+       FMT(BGR565,   0, 5, 6, 5,  2, 0, 1, 0,  false,  true,  2,  3),
+};
+
+uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats)
+{
+       uint32_t i;
+       for (i = 0; i < ARRAY_SIZE(formats); i++) {
+               const struct mdp_format *f = &formats[i];
+
+               if (i == max_formats)
+                       break;
+
+               pixel_formats[i] = f->base.pixel_format;
+       }
+
+       return i;
+}
+
+const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(formats); i++) {
+               const struct mdp_format *f = &formats[i];
+               if (f->base.pixel_format == format)
+                       return &f->base;
+       }
+       return NULL;
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c b/drivers/gpu/drm/msm/mdp/mdp_kms.c
new file mode 100644 (file)
index 0000000..3be48f7
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
+#include "mdp_kms.h"
+
+
+struct mdp_irq_wait {
+       struct mdp_irq irq;
+       int count;
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(wait_event);
+
+static DEFINE_SPINLOCK(list_lock);
+
+static void update_irq(struct mdp_kms *mdp_kms)
+{
+       struct mdp_irq *irq;
+       uint32_t irqmask = mdp_kms->vblank_mask;
+
+       BUG_ON(!spin_is_locked(&list_lock));
+
+       list_for_each_entry(irq, &mdp_kms->irq_list, node)
+               irqmask |= irq->irqmask;
+
+       mdp_kms->funcs->set_irqmask(mdp_kms, irqmask);
+}
+
+static void update_irq_unlocked(struct mdp_kms *mdp_kms)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&list_lock, flags);
+       update_irq(mdp_kms);
+       spin_unlock_irqrestore(&list_lock, flags);
+}
+
+void mdp_dispatch_irqs(struct mdp_kms *mdp_kms, uint32_t status)
+{
+       struct mdp_irq *handler, *n;
+       unsigned long flags;
+
+       spin_lock_irqsave(&list_lock, flags);
+       mdp_kms->in_irq = true;
+       list_for_each_entry_safe(handler, n, &mdp_kms->irq_list, node) {
+               if (handler->irqmask & status) {
+                       spin_unlock_irqrestore(&list_lock, flags);
+                       handler->irq(handler, handler->irqmask & status);
+                       spin_lock_irqsave(&list_lock, flags);
+               }
+       }
+       mdp_kms->in_irq = false;
+       update_irq(mdp_kms);
+       spin_unlock_irqrestore(&list_lock, flags);
+
+}
+
+void mdp_update_vblank_mask(struct mdp_kms *mdp_kms, uint32_t mask, bool enable)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&list_lock, flags);
+       if (enable)
+               mdp_kms->vblank_mask |= mask;
+       else
+               mdp_kms->vblank_mask &= ~mask;
+       update_irq(mdp_kms);
+       spin_unlock_irqrestore(&list_lock, flags);
+}
+
+static void wait_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+       struct mdp_irq_wait *wait =
+                       container_of(irq, struct mdp_irq_wait, irq);
+       wait->count--;
+       wake_up_all(&wait_event);
+}
+
+void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask)
+{
+       struct mdp_irq_wait wait = {
+               .irq = {
+                       .irq = wait_irq,
+                       .irqmask = irqmask,
+               },
+               .count = 1,
+       };
+       mdp_irq_register(mdp_kms, &wait.irq);
+       wait_event(wait_event, (wait.count <= 0));
+       mdp_irq_unregister(mdp_kms, &wait.irq);
+}
+
+void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq)
+{
+       unsigned long flags;
+       bool needs_update = false;
+
+       spin_lock_irqsave(&list_lock, flags);
+
+       if (!irq->registered) {
+               irq->registered = true;
+               list_add(&irq->node, &mdp_kms->irq_list);
+               needs_update = !mdp_kms->in_irq;
+       }
+
+       spin_unlock_irqrestore(&list_lock, flags);
+
+       if (needs_update)
+               update_irq_unlocked(mdp_kms);
+}
+
+void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq)
+{
+       unsigned long flags;
+       bool needs_update = false;
+
+       spin_lock_irqsave(&list_lock, flags);
+
+       if (irq->registered) {
+               irq->registered = false;
+               list_del(&irq->node);
+               needs_update = !mdp_kms->in_irq;
+       }
+
+       spin_unlock_irqrestore(&list_lock, flags);
+
+       if (needs_update)
+               update_irq_unlocked(mdp_kms);
+}
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
new file mode 100644 (file)
index 0000000..99557b5
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MDP_KMS_H__
+#define __MDP_KMS_H__
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include "msm_drv.h"
+#include "msm_kms.h"
+#include "mdp_common.xml.h"
+
+struct mdp_kms;
+
+struct mdp_kms_funcs {
+       struct msm_kms_funcs base;
+       void (*set_irqmask)(struct mdp_kms *mdp_kms, uint32_t irqmask);
+};
+
+struct mdp_kms {
+       struct msm_kms base;
+
+       const struct mdp_kms_funcs *funcs;
+
+       /* irq handling: */
+       bool in_irq;
+       struct list_head irq_list;    /* list of mdp4_irq */
+       uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+};
+#define to_mdp_kms(x) container_of(x, struct mdp_kms, base)
+
+static inline void mdp_kms_init(struct mdp_kms *mdp_kms,
+               const struct mdp_kms_funcs *funcs)
+{
+       mdp_kms->funcs = funcs;
+       INIT_LIST_HEAD(&mdp_kms->irq_list);
+       msm_kms_init(&mdp_kms->base, &funcs->base);
+}
+
+/*
+ * irq helpers:
+ */
+
+/* For transiently registering for different MDP irqs that various parts
+ * of the KMS code need during setup/configuration.  These are not
+ * necessarily the same as what drm_vblank_get/put() are requesting, and
+ * the hysteresis in drm_vblank_put() is not necessarily desirable for
+ * internal housekeeping related irq usage.
+ */
+struct mdp_irq {
+       struct list_head node;
+       uint32_t irqmask;
+       bool registered;
+       void (*irq)(struct mdp_irq *irq, uint32_t irqstatus);
+};
+
+void mdp_dispatch_irqs(struct mdp_kms *mdp_kms, uint32_t status);
+void mdp_update_vblank_mask(struct mdp_kms *mdp_kms, uint32_t mask, bool enable);
+void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask);
+void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq);
+void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq);
+
+
+/*
+ * pixel format helpers:
+ */
+
+struct mdp_format {
+       struct msm_format base;
+       enum mdp_bpc bpc_r, bpc_g, bpc_b;
+       enum mdp_bpc_alpha bpc_a;
+       uint8_t unpack[4];
+       bool alpha_enable, unpack_tight;
+       uint8_t cpp, unpack_count;
+};
+#define to_mdp_format(x) container_of(x, struct mdp_format, base)
+
+uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats);
+const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
+
+#endif /* __MDP_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp4/mdp4.xml.h
deleted file mode 100644 (file)
index 9908ffe..0000000
+++ /dev/null
@@ -1,1061 +0,0 @@
-#ifndef MDP4_XML
-#define MDP4_XML
-
-/* Autogenerated file, DO NOT EDIT manually!
-
-This file was generated by the rules-ng-ng headergen tool in this git repository:
-http://github.com/freedreno/envytools/
-git clone https://github.com/freedreno/envytools.git
-
-The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    595 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp4/mdp4.xml           (  19332 bytes, from 2013-10-07 16:36:48)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  19288 bytes, from 2013-08-11 18:14:15)
-
-Copyright (C) 2013 by the following authors:
-- Rob Clark <robdclark@gmail.com> (robclark)
-
-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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
-*/
-
-
-enum mdp4_bpc {
-       BPC1 = 0,
-       BPC5 = 1,
-       BPC6 = 2,
-       BPC8 = 3,
-};
-
-enum mdp4_bpc_alpha {
-       BPC1A = 0,
-       BPC4A = 1,
-       BPC6A = 2,
-       BPC8A = 3,
-};
-
-enum mdp4_alpha_type {
-       FG_CONST = 0,
-       BG_CONST = 1,
-       FG_PIXEL = 2,
-       BG_PIXEL = 3,
-};
-
-enum mdp4_pipe {
-       VG1 = 0,
-       VG2 = 1,
-       RGB1 = 2,
-       RGB2 = 3,
-       RGB3 = 4,
-       VG3 = 5,
-       VG4 = 6,
-};
-
-enum mdp4_mixer {
-       MIXER0 = 0,
-       MIXER1 = 1,
-       MIXER2 = 2,
-};
-
-enum mdp4_mixer_stage_id {
-       STAGE_UNUSED = 0,
-       STAGE_BASE = 1,
-       STAGE0 = 2,
-       STAGE1 = 3,
-       STAGE2 = 4,
-       STAGE3 = 5,
-};
-
-enum mdp4_intf {
-       INTF_LCDC_DTV = 0,
-       INTF_DSI_VIDEO = 1,
-       INTF_DSI_CMD = 2,
-       INTF_EBI2_TV = 3,
-};
-
-enum mdp4_cursor_format {
-       CURSOR_ARGB = 1,
-       CURSOR_XRGB = 2,
-};
-
-enum mdp4_dma {
-       DMA_P = 0,
-       DMA_S = 1,
-       DMA_E = 2,
-};
-
-#define MDP4_IRQ_OVERLAY0_DONE                                 0x00000001
-#define MDP4_IRQ_OVERLAY1_DONE                                 0x00000002
-#define MDP4_IRQ_DMA_S_DONE                                    0x00000004
-#define MDP4_IRQ_DMA_E_DONE                                    0x00000008
-#define MDP4_IRQ_DMA_P_DONE                                    0x00000010
-#define MDP4_IRQ_VG1_HISTOGRAM                                 0x00000020
-#define MDP4_IRQ_VG2_HISTOGRAM                                 0x00000040
-#define MDP4_IRQ_PRIMARY_VSYNC                                 0x00000080
-#define MDP4_IRQ_PRIMARY_INTF_UDERRUN                          0x00000100
-#define MDP4_IRQ_EXTERNAL_VSYNC                                        0x00000200
-#define MDP4_IRQ_EXTERNAL_INTF_UDERRUN                         0x00000400
-#define MDP4_IRQ_PRIMARY_RDPTR                                 0x00000800
-#define MDP4_IRQ_DMA_P_HISTOGRAM                               0x00020000
-#define MDP4_IRQ_DMA_S_HISTOGRAM                               0x04000000
-#define MDP4_IRQ_OVERLAY2_DONE                                 0x40000000
-#define REG_MDP4_VERSION                                       0x00000000
-#define MDP4_VERSION_MINOR__MASK                               0x00ff0000
-#define MDP4_VERSION_MINOR__SHIFT                              16
-static inline uint32_t MDP4_VERSION_MINOR(uint32_t val)
-{
-       return ((val) << MDP4_VERSION_MINOR__SHIFT) & MDP4_VERSION_MINOR__MASK;
-}
-#define MDP4_VERSION_MAJOR__MASK                               0xff000000
-#define MDP4_VERSION_MAJOR__SHIFT                              24
-static inline uint32_t MDP4_VERSION_MAJOR(uint32_t val)
-{
-       return ((val) << MDP4_VERSION_MAJOR__SHIFT) & MDP4_VERSION_MAJOR__MASK;
-}
-
-#define REG_MDP4_OVLP0_KICK                                    0x00000004
-
-#define REG_MDP4_OVLP1_KICK                                    0x00000008
-
-#define REG_MDP4_OVLP2_KICK                                    0x000000d0
-
-#define REG_MDP4_DMA_P_KICK                                    0x0000000c
-
-#define REG_MDP4_DMA_S_KICK                                    0x00000010
-
-#define REG_MDP4_DMA_E_KICK                                    0x00000014
-
-#define REG_MDP4_DISP_STATUS                                   0x00000018
-
-#define REG_MDP4_DISP_INTF_SEL                                 0x00000038
-#define MDP4_DISP_INTF_SEL_PRIM__MASK                          0x00000003
-#define MDP4_DISP_INTF_SEL_PRIM__SHIFT                         0
-static inline uint32_t MDP4_DISP_INTF_SEL_PRIM(enum mdp4_intf val)
-{
-       return ((val) << MDP4_DISP_INTF_SEL_PRIM__SHIFT) & MDP4_DISP_INTF_SEL_PRIM__MASK;
-}
-#define MDP4_DISP_INTF_SEL_SEC__MASK                           0x0000000c
-#define MDP4_DISP_INTF_SEL_SEC__SHIFT                          2
-static inline uint32_t MDP4_DISP_INTF_SEL_SEC(enum mdp4_intf val)
-{
-       return ((val) << MDP4_DISP_INTF_SEL_SEC__SHIFT) & MDP4_DISP_INTF_SEL_SEC__MASK;
-}
-#define MDP4_DISP_INTF_SEL_EXT__MASK                           0x00000030
-#define MDP4_DISP_INTF_SEL_EXT__SHIFT                          4
-static inline uint32_t MDP4_DISP_INTF_SEL_EXT(enum mdp4_intf val)
-{
-       return ((val) << MDP4_DISP_INTF_SEL_EXT__SHIFT) & MDP4_DISP_INTF_SEL_EXT__MASK;
-}
-#define MDP4_DISP_INTF_SEL_DSI_VIDEO                           0x00000040
-#define MDP4_DISP_INTF_SEL_DSI_CMD                             0x00000080
-
-#define REG_MDP4_RESET_STATUS                                  0x0000003c
-
-#define REG_MDP4_READ_CNFG                                     0x0000004c
-
-#define REG_MDP4_INTR_ENABLE                                   0x00000050
-
-#define REG_MDP4_INTR_STATUS                                   0x00000054
-
-#define REG_MDP4_INTR_CLEAR                                    0x00000058
-
-#define REG_MDP4_EBI2_LCD0                                     0x00000060
-
-#define REG_MDP4_EBI2_LCD1                                     0x00000064
-
-#define REG_MDP4_PORTMAP_MODE                                  0x00000070
-
-#define REG_MDP4_CS_CONTROLLER0                                        0x000000c0
-
-#define REG_MDP4_CS_CONTROLLER1                                        0x000000c4
-
-#define REG_MDP4_LAYERMIXER2_IN_CFG                            0x000100f0
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE0__MASK                    0x00000007
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE0__SHIFT                   0
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE0(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE0__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE0__MASK;
-}
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE0_MIXER1                   0x00000008
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE1__MASK                    0x00000070
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE1__SHIFT                   4
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE1(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE1__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE1__MASK;
-}
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE1_MIXER1                   0x00000080
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE2__MASK                    0x00000700
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE2__SHIFT                   8
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE2(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE2__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE2__MASK;
-}
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE2_MIXER1                   0x00000800
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE3__MASK                    0x00007000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE3__SHIFT                   12
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE3(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE3__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE3__MASK;
-}
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE3_MIXER1                   0x00008000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE4__MASK                    0x00070000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE4__SHIFT                   16
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE4(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE4__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE4__MASK;
-}
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE4_MIXER1                   0x00080000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE5__MASK                    0x00700000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE5__SHIFT                   20
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE5(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE5__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE5__MASK;
-}
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE5_MIXER1                   0x00800000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE6__MASK                    0x07000000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE6__SHIFT                   24
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE6(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE6__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE6__MASK;
-}
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE6_MIXER1                   0x08000000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE7__MASK                    0x70000000
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE7__SHIFT                   28
-static inline uint32_t MDP4_LAYERMIXER2_IN_CFG_PIPE7(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER2_IN_CFG_PIPE7__SHIFT) & MDP4_LAYERMIXER2_IN_CFG_PIPE7__MASK;
-}
-#define MDP4_LAYERMIXER2_IN_CFG_PIPE7_MIXER1                   0x80000000
-
-#define REG_MDP4_LAYERMIXER_IN_CFG_UPDATE_METHOD               0x000100fc
-
-#define REG_MDP4_LAYERMIXER_IN_CFG                             0x00010100
-#define MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK                     0x00000007
-#define MDP4_LAYERMIXER_IN_CFG_PIPE0__SHIFT                    0
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE0(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE0__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK;
-}
-#define MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1                    0x00000008
-#define MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK                     0x00000070
-#define MDP4_LAYERMIXER_IN_CFG_PIPE1__SHIFT                    4
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE1(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE1__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK;
-}
-#define MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1                    0x00000080
-#define MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK                     0x00000700
-#define MDP4_LAYERMIXER_IN_CFG_PIPE2__SHIFT                    8
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE2(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE2__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK;
-}
-#define MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1                    0x00000800
-#define MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK                     0x00007000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE3__SHIFT                    12
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE3(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE3__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK;
-}
-#define MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1                    0x00008000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK                     0x00070000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE4__SHIFT                    16
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE4(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE4__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK;
-}
-#define MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1                    0x00080000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK                     0x00700000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE5__SHIFT                    20
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE5(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE5__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK;
-}
-#define MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1                    0x00800000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK                     0x07000000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE6__SHIFT                    24
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE6(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE6__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK;
-}
-#define MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1                    0x08000000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE7__MASK                     0x70000000
-#define MDP4_LAYERMIXER_IN_CFG_PIPE7__SHIFT                    28
-static inline uint32_t MDP4_LAYERMIXER_IN_CFG_PIPE7(enum mdp4_mixer_stage_id val)
-{
-       return ((val) << MDP4_LAYERMIXER_IN_CFG_PIPE7__SHIFT) & MDP4_LAYERMIXER_IN_CFG_PIPE7__MASK;
-}
-#define MDP4_LAYERMIXER_IN_CFG_PIPE7_MIXER1                    0x80000000
-
-#define REG_MDP4_VG2_SRC_FORMAT                                        0x00030050
-
-#define REG_MDP4_VG2_CONST_COLOR                               0x00031008
-
-#define REG_MDP4_OVERLAY_FLUSH                                 0x00018000
-#define MDP4_OVERLAY_FLUSH_OVLP0                               0x00000001
-#define MDP4_OVERLAY_FLUSH_OVLP1                               0x00000002
-#define MDP4_OVERLAY_FLUSH_VG1                                 0x00000004
-#define MDP4_OVERLAY_FLUSH_VG2                                 0x00000008
-#define MDP4_OVERLAY_FLUSH_RGB1                                        0x00000010
-#define MDP4_OVERLAY_FLUSH_RGB2                                        0x00000020
-
-static inline uint32_t __offset_OVLP(uint32_t idx)
-{
-       switch (idx) {
-               case 0: return 0x00010000;
-               case 1: return 0x00018000;
-               case 2: return 0x00088000;
-               default: return INVALID_IDX(idx);
-       }
-}
-static inline uint32_t REG_MDP4_OVLP(uint32_t i0) { return 0x00000000 + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_CFG(uint32_t i0) { return 0x00000004 + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_SIZE(uint32_t i0) { return 0x00000008 + __offset_OVLP(i0); }
-#define MDP4_OVLP_SIZE_HEIGHT__MASK                            0xffff0000
-#define MDP4_OVLP_SIZE_HEIGHT__SHIFT                           16
-static inline uint32_t MDP4_OVLP_SIZE_HEIGHT(uint32_t val)
-{
-       return ((val) << MDP4_OVLP_SIZE_HEIGHT__SHIFT) & MDP4_OVLP_SIZE_HEIGHT__MASK;
-}
-#define MDP4_OVLP_SIZE_WIDTH__MASK                             0x0000ffff
-#define MDP4_OVLP_SIZE_WIDTH__SHIFT                            0
-static inline uint32_t MDP4_OVLP_SIZE_WIDTH(uint32_t val)
-{
-       return ((val) << MDP4_OVLP_SIZE_WIDTH__SHIFT) & MDP4_OVLP_SIZE_WIDTH__MASK;
-}
-
-static inline uint32_t REG_MDP4_OVLP_BASE(uint32_t i0) { return 0x0000000c + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_STRIDE(uint32_t i0) { return 0x00000010 + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_OPMODE(uint32_t i0) { return 0x00000014 + __offset_OVLP(i0); }
-
-static inline uint32_t __offset_STAGE(uint32_t idx)
-{
-       switch (idx) {
-               case 0: return 0x00000104;
-               case 1: return 0x00000124;
-               case 2: return 0x00000144;
-               case 3: return 0x00000160;
-               default: return INVALID_IDX(idx);
-       }
-}
-static inline uint32_t REG_MDP4_OVLP_STAGE(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE(i1); }
-
-static inline uint32_t REG_MDP4_OVLP_STAGE_OP(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE(i1); }
-#define MDP4_OVLP_STAGE_OP_FG_ALPHA__MASK                      0x00000003
-#define MDP4_OVLP_STAGE_OP_FG_ALPHA__SHIFT                     0
-static inline uint32_t MDP4_OVLP_STAGE_OP_FG_ALPHA(enum mdp4_alpha_type val)
-{
-       return ((val) << MDP4_OVLP_STAGE_OP_FG_ALPHA__SHIFT) & MDP4_OVLP_STAGE_OP_FG_ALPHA__MASK;
-}
-#define MDP4_OVLP_STAGE_OP_FG_INV_ALPHA                                0x00000004
-#define MDP4_OVLP_STAGE_OP_FG_MOD_ALPHA                                0x00000008
-#define MDP4_OVLP_STAGE_OP_BG_ALPHA__MASK                      0x00000030
-#define MDP4_OVLP_STAGE_OP_BG_ALPHA__SHIFT                     4
-static inline uint32_t MDP4_OVLP_STAGE_OP_BG_ALPHA(enum mdp4_alpha_type val)
-{
-       return ((val) << MDP4_OVLP_STAGE_OP_BG_ALPHA__SHIFT) & MDP4_OVLP_STAGE_OP_BG_ALPHA__MASK;
-}
-#define MDP4_OVLP_STAGE_OP_BG_INV_ALPHA                                0x00000040
-#define MDP4_OVLP_STAGE_OP_BG_MOD_ALPHA                                0x00000080
-#define MDP4_OVLP_STAGE_OP_FG_TRANSP                           0x00000100
-#define MDP4_OVLP_STAGE_OP_BG_TRANSP                           0x00000200
-
-static inline uint32_t REG_MDP4_OVLP_STAGE_FG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00000004 + __offset_OVLP(i0) + __offset_STAGE(i1); }
-
-static inline uint32_t REG_MDP4_OVLP_STAGE_BG_ALPHA(uint32_t i0, uint32_t i1) { return 0x00000008 + __offset_OVLP(i0) + __offset_STAGE(i1); }
-
-static inline uint32_t REG_MDP4_OVLP_STAGE_TRANSP_LOW0(uint32_t i0, uint32_t i1) { return 0x0000000c + __offset_OVLP(i0) + __offset_STAGE(i1); }
-
-static inline uint32_t REG_MDP4_OVLP_STAGE_TRANSP_LOW1(uint32_t i0, uint32_t i1) { return 0x00000010 + __offset_OVLP(i0) + __offset_STAGE(i1); }
-
-static inline uint32_t REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(uint32_t i0, uint32_t i1) { return 0x00000014 + __offset_OVLP(i0) + __offset_STAGE(i1); }
-
-static inline uint32_t REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(uint32_t i0, uint32_t i1) { return 0x00000018 + __offset_OVLP(i0) + __offset_STAGE(i1); }
-
-static inline uint32_t __offset_STAGE_CO3(uint32_t idx)
-{
-       switch (idx) {
-               case 0: return 0x00001004;
-               case 1: return 0x00001404;
-               case 2: return 0x00001804;
-               case 3: return 0x00001b84;
-               default: return INVALID_IDX(idx);
-       }
-}
-static inline uint32_t REG_MDP4_OVLP_STAGE_CO3(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE_CO3(i1); }
-
-static inline uint32_t REG_MDP4_OVLP_STAGE_CO3_SEL(uint32_t i0, uint32_t i1) { return 0x00000000 + __offset_OVLP(i0) + __offset_STAGE_CO3(i1); }
-#define MDP4_OVLP_STAGE_CO3_SEL_FG_ALPHA                       0x00000001
-
-static inline uint32_t REG_MDP4_OVLP_TRANSP_LOW0(uint32_t i0) { return 0x00000180 + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_TRANSP_LOW1(uint32_t i0) { return 0x00000184 + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_TRANSP_HIGH0(uint32_t i0) { return 0x00000188 + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_TRANSP_HIGH1(uint32_t i0) { return 0x0000018c + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_CONFIG(uint32_t i0) { return 0x00000200 + __offset_OVLP(i0); }
-
-static inline uint32_t REG_MDP4_OVLP_CSC(uint32_t i0) { return 0x00002000 + __offset_OVLP(i0); }
-
-
-static inline uint32_t REG_MDP4_OVLP_CSC_MV(uint32_t i0, uint32_t i1) { return 0x00002400 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_MV_VAL(uint32_t i0, uint32_t i1) { return 0x00002400 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_PRE_BV(uint32_t i0, uint32_t i1) { return 0x00002500 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_PRE_BV_VAL(uint32_t i0, uint32_t i1) { return 0x00002500 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_POST_BV(uint32_t i0, uint32_t i1) { return 0x00002580 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_POST_BV_VAL(uint32_t i0, uint32_t i1) { return 0x00002580 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_PRE_LV(uint32_t i0, uint32_t i1) { return 0x00002600 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_PRE_LV_VAL(uint32_t i0, uint32_t i1) { return 0x00002600 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_POST_LV(uint32_t i0, uint32_t i1) { return 0x00002680 + __offset_OVLP(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_OVLP_CSC_POST_LV_VAL(uint32_t i0, uint32_t i1) { return 0x00002680 + __offset_OVLP(i0) + 0x4*i1; }
-
-#define REG_MDP4_DMA_P_OP_MODE                                 0x00090070
-
-static inline uint32_t REG_MDP4_LUTN(uint32_t i0) { return 0x00094800 + 0x400*i0; }
-
-static inline uint32_t REG_MDP4_LUTN_LUT(uint32_t i0, uint32_t i1) { return 0x00094800 + 0x400*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_LUTN_LUT_VAL(uint32_t i0, uint32_t i1) { return 0x00094800 + 0x400*i0 + 0x4*i1; }
-
-#define REG_MDP4_DMA_S_OP_MODE                                 0x000a0028
-
-static inline uint32_t REG_MDP4_DMA_E_QUANT(uint32_t i0) { return 0x000b0070 + 0x4*i0; }
-
-static inline uint32_t __offset_DMA(enum mdp4_dma idx)
-{
-       switch (idx) {
-               case DMA_P: return 0x00090000;
-               case DMA_S: return 0x000a0000;
-               case DMA_E: return 0x000b0000;
-               default: return INVALID_IDX(idx);
-       }
-}
-static inline uint32_t REG_MDP4_DMA(enum mdp4_dma i0) { return 0x00000000 + __offset_DMA(i0); }
-
-static inline uint32_t REG_MDP4_DMA_CONFIG(enum mdp4_dma i0) { return 0x00000000 + __offset_DMA(i0); }
-#define MDP4_DMA_CONFIG_G_BPC__MASK                            0x00000003
-#define MDP4_DMA_CONFIG_G_BPC__SHIFT                           0
-static inline uint32_t MDP4_DMA_CONFIG_G_BPC(enum mdp4_bpc val)
-{
-       return ((val) << MDP4_DMA_CONFIG_G_BPC__SHIFT) & MDP4_DMA_CONFIG_G_BPC__MASK;
-}
-#define MDP4_DMA_CONFIG_B_BPC__MASK                            0x0000000c
-#define MDP4_DMA_CONFIG_B_BPC__SHIFT                           2
-static inline uint32_t MDP4_DMA_CONFIG_B_BPC(enum mdp4_bpc val)
-{
-       return ((val) << MDP4_DMA_CONFIG_B_BPC__SHIFT) & MDP4_DMA_CONFIG_B_BPC__MASK;
-}
-#define MDP4_DMA_CONFIG_R_BPC__MASK                            0x00000030
-#define MDP4_DMA_CONFIG_R_BPC__SHIFT                           4
-static inline uint32_t MDP4_DMA_CONFIG_R_BPC(enum mdp4_bpc val)
-{
-       return ((val) << MDP4_DMA_CONFIG_R_BPC__SHIFT) & MDP4_DMA_CONFIG_R_BPC__MASK;
-}
-#define MDP4_DMA_CONFIG_PACK_ALIGN_MSB                         0x00000080
-#define MDP4_DMA_CONFIG_PACK__MASK                             0x0000ff00
-#define MDP4_DMA_CONFIG_PACK__SHIFT                            8
-static inline uint32_t MDP4_DMA_CONFIG_PACK(uint32_t val)
-{
-       return ((val) << MDP4_DMA_CONFIG_PACK__SHIFT) & MDP4_DMA_CONFIG_PACK__MASK;
-}
-#define MDP4_DMA_CONFIG_DEFLKR_EN                              0x01000000
-#define MDP4_DMA_CONFIG_DITHER_EN                              0x01000000
-
-static inline uint32_t REG_MDP4_DMA_SRC_SIZE(enum mdp4_dma i0) { return 0x00000004 + __offset_DMA(i0); }
-#define MDP4_DMA_SRC_SIZE_HEIGHT__MASK                         0xffff0000
-#define MDP4_DMA_SRC_SIZE_HEIGHT__SHIFT                                16
-static inline uint32_t MDP4_DMA_SRC_SIZE_HEIGHT(uint32_t val)
-{
-       return ((val) << MDP4_DMA_SRC_SIZE_HEIGHT__SHIFT) & MDP4_DMA_SRC_SIZE_HEIGHT__MASK;
-}
-#define MDP4_DMA_SRC_SIZE_WIDTH__MASK                          0x0000ffff
-#define MDP4_DMA_SRC_SIZE_WIDTH__SHIFT                         0
-static inline uint32_t MDP4_DMA_SRC_SIZE_WIDTH(uint32_t val)
-{
-       return ((val) << MDP4_DMA_SRC_SIZE_WIDTH__SHIFT) & MDP4_DMA_SRC_SIZE_WIDTH__MASK;
-}
-
-static inline uint32_t REG_MDP4_DMA_SRC_BASE(enum mdp4_dma i0) { return 0x00000008 + __offset_DMA(i0); }
-
-static inline uint32_t REG_MDP4_DMA_SRC_STRIDE(enum mdp4_dma i0) { return 0x0000000c + __offset_DMA(i0); }
-
-static inline uint32_t REG_MDP4_DMA_DST_SIZE(enum mdp4_dma i0) { return 0x00000010 + __offset_DMA(i0); }
-#define MDP4_DMA_DST_SIZE_HEIGHT__MASK                         0xffff0000
-#define MDP4_DMA_DST_SIZE_HEIGHT__SHIFT                                16
-static inline uint32_t MDP4_DMA_DST_SIZE_HEIGHT(uint32_t val)
-{
-       return ((val) << MDP4_DMA_DST_SIZE_HEIGHT__SHIFT) & MDP4_DMA_DST_SIZE_HEIGHT__MASK;
-}
-#define MDP4_DMA_DST_SIZE_WIDTH__MASK                          0x0000ffff
-#define MDP4_DMA_DST_SIZE_WIDTH__SHIFT                         0
-static inline uint32_t MDP4_DMA_DST_SIZE_WIDTH(uint32_t val)
-{
-       return ((val) << MDP4_DMA_DST_SIZE_WIDTH__SHIFT) & MDP4_DMA_DST_SIZE_WIDTH__MASK;
-}
-
-static inline uint32_t REG_MDP4_DMA_CURSOR_SIZE(enum mdp4_dma i0) { return 0x00000044 + __offset_DMA(i0); }
-#define MDP4_DMA_CURSOR_SIZE_WIDTH__MASK                       0x0000007f
-#define MDP4_DMA_CURSOR_SIZE_WIDTH__SHIFT                      0
-static inline uint32_t MDP4_DMA_CURSOR_SIZE_WIDTH(uint32_t val)
-{
-       return ((val) << MDP4_DMA_CURSOR_SIZE_WIDTH__SHIFT) & MDP4_DMA_CURSOR_SIZE_WIDTH__MASK;
-}
-#define MDP4_DMA_CURSOR_SIZE_HEIGHT__MASK                      0x007f0000
-#define MDP4_DMA_CURSOR_SIZE_HEIGHT__SHIFT                     16
-static inline uint32_t MDP4_DMA_CURSOR_SIZE_HEIGHT(uint32_t val)
-{
-       return ((val) << MDP4_DMA_CURSOR_SIZE_HEIGHT__SHIFT) & MDP4_DMA_CURSOR_SIZE_HEIGHT__MASK;
-}
-
-static inline uint32_t REG_MDP4_DMA_CURSOR_BASE(enum mdp4_dma i0) { return 0x00000048 + __offset_DMA(i0); }
-
-static inline uint32_t REG_MDP4_DMA_CURSOR_POS(enum mdp4_dma i0) { return 0x0000004c + __offset_DMA(i0); }
-#define MDP4_DMA_CURSOR_POS_X__MASK                            0x0000ffff
-#define MDP4_DMA_CURSOR_POS_X__SHIFT                           0
-static inline uint32_t MDP4_DMA_CURSOR_POS_X(uint32_t val)
-{
-       return ((val) << MDP4_DMA_CURSOR_POS_X__SHIFT) & MDP4_DMA_CURSOR_POS_X__MASK;
-}
-#define MDP4_DMA_CURSOR_POS_Y__MASK                            0xffff0000
-#define MDP4_DMA_CURSOR_POS_Y__SHIFT                           16
-static inline uint32_t MDP4_DMA_CURSOR_POS_Y(uint32_t val)
-{
-       return ((val) << MDP4_DMA_CURSOR_POS_Y__SHIFT) & MDP4_DMA_CURSOR_POS_Y__MASK;
-}
-
-static inline uint32_t REG_MDP4_DMA_CURSOR_BLEND_CONFIG(enum mdp4_dma i0) { return 0x00000060 + __offset_DMA(i0); }
-#define MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN                 0x00000001
-#define MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT__MASK              0x00000006
-#define MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT__SHIFT             1
-static inline uint32_t MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(enum mdp4_cursor_format val)
-{
-       return ((val) << MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT__SHIFT) & MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT__MASK;
-}
-#define MDP4_DMA_CURSOR_BLEND_CONFIG_TRANSP_EN                 0x00000008
-
-static inline uint32_t REG_MDP4_DMA_CURSOR_BLEND_PARAM(enum mdp4_dma i0) { return 0x00000064 + __offset_DMA(i0); }
-
-static inline uint32_t REG_MDP4_DMA_BLEND_TRANS_LOW(enum mdp4_dma i0) { return 0x00000068 + __offset_DMA(i0); }
-
-static inline uint32_t REG_MDP4_DMA_BLEND_TRANS_HIGH(enum mdp4_dma i0) { return 0x0000006c + __offset_DMA(i0); }
-
-static inline uint32_t REG_MDP4_DMA_FETCH_CONFIG(enum mdp4_dma i0) { return 0x00001004 + __offset_DMA(i0); }
-
-static inline uint32_t REG_MDP4_DMA_CSC(enum mdp4_dma i0) { return 0x00003000 + __offset_DMA(i0); }
-
-
-static inline uint32_t REG_MDP4_DMA_CSC_MV(enum mdp4_dma i0, uint32_t i1) { return 0x00003400 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_MV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003400 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_PRE_BV(enum mdp4_dma i0, uint32_t i1) { return 0x00003500 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_PRE_BV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003500 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_POST_BV(enum mdp4_dma i0, uint32_t i1) { return 0x00003580 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_POST_BV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003580 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_PRE_LV(enum mdp4_dma i0, uint32_t i1) { return 0x00003600 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_PRE_LV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003600 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_POST_LV(enum mdp4_dma i0, uint32_t i1) { return 0x00003680 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_DMA_CSC_POST_LV_VAL(enum mdp4_dma i0, uint32_t i1) { return 0x00003680 + __offset_DMA(i0) + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE(enum mdp4_pipe i0) { return 0x00020000 + 0x10000*i0; }
-
-static inline uint32_t REG_MDP4_PIPE_SRC_SIZE(enum mdp4_pipe i0) { return 0x00020000 + 0x10000*i0; }
-#define MDP4_PIPE_SRC_SIZE_HEIGHT__MASK                                0xffff0000
-#define MDP4_PIPE_SRC_SIZE_HEIGHT__SHIFT                       16
-static inline uint32_t MDP4_PIPE_SRC_SIZE_HEIGHT(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_SRC_SIZE_HEIGHT__MASK;
-}
-#define MDP4_PIPE_SRC_SIZE_WIDTH__MASK                         0x0000ffff
-#define MDP4_PIPE_SRC_SIZE_WIDTH__SHIFT                                0
-static inline uint32_t MDP4_PIPE_SRC_SIZE_WIDTH(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_SIZE_WIDTH__SHIFT) & MDP4_PIPE_SRC_SIZE_WIDTH__MASK;
-}
-
-static inline uint32_t REG_MDP4_PIPE_SRC_XY(enum mdp4_pipe i0) { return 0x00020004 + 0x10000*i0; }
-#define MDP4_PIPE_SRC_XY_Y__MASK                               0xffff0000
-#define MDP4_PIPE_SRC_XY_Y__SHIFT                              16
-static inline uint32_t MDP4_PIPE_SRC_XY_Y(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_XY_Y__SHIFT) & MDP4_PIPE_SRC_XY_Y__MASK;
-}
-#define MDP4_PIPE_SRC_XY_X__MASK                               0x0000ffff
-#define MDP4_PIPE_SRC_XY_X__SHIFT                              0
-static inline uint32_t MDP4_PIPE_SRC_XY_X(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_XY_X__SHIFT) & MDP4_PIPE_SRC_XY_X__MASK;
-}
-
-static inline uint32_t REG_MDP4_PIPE_DST_SIZE(enum mdp4_pipe i0) { return 0x00020008 + 0x10000*i0; }
-#define MDP4_PIPE_DST_SIZE_HEIGHT__MASK                                0xffff0000
-#define MDP4_PIPE_DST_SIZE_HEIGHT__SHIFT                       16
-static inline uint32_t MDP4_PIPE_DST_SIZE_HEIGHT(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_DST_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_DST_SIZE_HEIGHT__MASK;
-}
-#define MDP4_PIPE_DST_SIZE_WIDTH__MASK                         0x0000ffff
-#define MDP4_PIPE_DST_SIZE_WIDTH__SHIFT                                0
-static inline uint32_t MDP4_PIPE_DST_SIZE_WIDTH(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_DST_SIZE_WIDTH__SHIFT) & MDP4_PIPE_DST_SIZE_WIDTH__MASK;
-}
-
-static inline uint32_t REG_MDP4_PIPE_DST_XY(enum mdp4_pipe i0) { return 0x0002000c + 0x10000*i0; }
-#define MDP4_PIPE_DST_XY_Y__MASK                               0xffff0000
-#define MDP4_PIPE_DST_XY_Y__SHIFT                              16
-static inline uint32_t MDP4_PIPE_DST_XY_Y(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_DST_XY_Y__SHIFT) & MDP4_PIPE_DST_XY_Y__MASK;
-}
-#define MDP4_PIPE_DST_XY_X__MASK                               0x0000ffff
-#define MDP4_PIPE_DST_XY_X__SHIFT                              0
-static inline uint32_t MDP4_PIPE_DST_XY_X(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_DST_XY_X__SHIFT) & MDP4_PIPE_DST_XY_X__MASK;
-}
-
-static inline uint32_t REG_MDP4_PIPE_SRCP0_BASE(enum mdp4_pipe i0) { return 0x00020010 + 0x10000*i0; }
-
-static inline uint32_t REG_MDP4_PIPE_SRCP1_BASE(enum mdp4_pipe i0) { return 0x00020014 + 0x10000*i0; }
-
-static inline uint32_t REG_MDP4_PIPE_SRCP2_BASE(enum mdp4_pipe i0) { return 0x00020018 + 0x10000*i0; }
-
-static inline uint32_t REG_MDP4_PIPE_SRC_STRIDE_A(enum mdp4_pipe i0) { return 0x00020040 + 0x10000*i0; }
-#define MDP4_PIPE_SRC_STRIDE_A_P0__MASK                                0x0000ffff
-#define MDP4_PIPE_SRC_STRIDE_A_P0__SHIFT                       0
-static inline uint32_t MDP4_PIPE_SRC_STRIDE_A_P0(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_STRIDE_A_P0__SHIFT) & MDP4_PIPE_SRC_STRIDE_A_P0__MASK;
-}
-#define MDP4_PIPE_SRC_STRIDE_A_P1__MASK                                0xffff0000
-#define MDP4_PIPE_SRC_STRIDE_A_P1__SHIFT                       16
-static inline uint32_t MDP4_PIPE_SRC_STRIDE_A_P1(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_STRIDE_A_P1__SHIFT) & MDP4_PIPE_SRC_STRIDE_A_P1__MASK;
-}
-
-static inline uint32_t REG_MDP4_PIPE_SRC_STRIDE_B(enum mdp4_pipe i0) { return 0x00020044 + 0x10000*i0; }
-#define MDP4_PIPE_SRC_STRIDE_B_P2__MASK                                0x0000ffff
-#define MDP4_PIPE_SRC_STRIDE_B_P2__SHIFT                       0
-static inline uint32_t MDP4_PIPE_SRC_STRIDE_B_P2(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_STRIDE_B_P2__SHIFT) & MDP4_PIPE_SRC_STRIDE_B_P2__MASK;
-}
-#define MDP4_PIPE_SRC_STRIDE_B_P3__MASK                                0xffff0000
-#define MDP4_PIPE_SRC_STRIDE_B_P3__SHIFT                       16
-static inline uint32_t MDP4_PIPE_SRC_STRIDE_B_P3(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP4_PIPE_SRC_STRIDE_B_P3__MASK;
-}
-
-static inline uint32_t REG_MDP4_PIPE_FRAME_SIZE(enum mdp4_pipe i0) { return 0x00020048 + 0x10000*i0; }
-#define MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK                      0xffff0000
-#define MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT                     16
-static inline uint32_t MDP4_PIPE_FRAME_SIZE_HEIGHT(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK;
-}
-#define MDP4_PIPE_FRAME_SIZE_WIDTH__MASK                       0x0000ffff
-#define MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT                      0
-static inline uint32_t MDP4_PIPE_FRAME_SIZE_WIDTH(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT) & MDP4_PIPE_FRAME_SIZE_WIDTH__MASK;
-}
-
-static inline uint32_t REG_MDP4_PIPE_SRC_FORMAT(enum mdp4_pipe i0) { return 0x00020050 + 0x10000*i0; }
-#define MDP4_PIPE_SRC_FORMAT_G_BPC__MASK                       0x00000003
-#define MDP4_PIPE_SRC_FORMAT_G_BPC__SHIFT                      0
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_G_BPC(enum mdp4_bpc val)
-{
-       return ((val) << MDP4_PIPE_SRC_FORMAT_G_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_G_BPC__MASK;
-}
-#define MDP4_PIPE_SRC_FORMAT_B_BPC__MASK                       0x0000000c
-#define MDP4_PIPE_SRC_FORMAT_B_BPC__SHIFT                      2
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_B_BPC(enum mdp4_bpc val)
-{
-       return ((val) << MDP4_PIPE_SRC_FORMAT_B_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_B_BPC__MASK;
-}
-#define MDP4_PIPE_SRC_FORMAT_R_BPC__MASK                       0x00000030
-#define MDP4_PIPE_SRC_FORMAT_R_BPC__SHIFT                      4
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_R_BPC(enum mdp4_bpc val)
-{
-       return ((val) << MDP4_PIPE_SRC_FORMAT_R_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_R_BPC__MASK;
-}
-#define MDP4_PIPE_SRC_FORMAT_A_BPC__MASK                       0x000000c0
-#define MDP4_PIPE_SRC_FORMAT_A_BPC__SHIFT                      6
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_A_BPC(enum mdp4_bpc_alpha val)
-{
-       return ((val) << MDP4_PIPE_SRC_FORMAT_A_BPC__SHIFT) & MDP4_PIPE_SRC_FORMAT_A_BPC__MASK;
-}
-#define MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE                      0x00000100
-#define MDP4_PIPE_SRC_FORMAT_CPP__MASK                         0x00000600
-#define MDP4_PIPE_SRC_FORMAT_CPP__SHIFT                                9
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_CPP(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_FORMAT_CPP__SHIFT) & MDP4_PIPE_SRC_FORMAT_CPP__MASK;
-}
-#define MDP4_PIPE_SRC_FORMAT_ROTATED_90                                0x00001000
-#define MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT__MASK                        0x00006000
-#define MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT__SHIFT               13
-static inline uint32_t MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT__SHIFT) & MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT__MASK;
-}
-#define MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT                      0x00020000
-#define MDP4_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB                  0x00040000
-#define MDP4_PIPE_SRC_FORMAT_SOLID_FILL                                0x00400000
-
-static inline uint32_t REG_MDP4_PIPE_SRC_UNPACK(enum mdp4_pipe i0) { return 0x00020054 + 0x10000*i0; }
-#define MDP4_PIPE_SRC_UNPACK_ELEM0__MASK                       0x000000ff
-#define MDP4_PIPE_SRC_UNPACK_ELEM0__SHIFT                      0
-static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM0(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_UNPACK_ELEM0__SHIFT) & MDP4_PIPE_SRC_UNPACK_ELEM0__MASK;
-}
-#define MDP4_PIPE_SRC_UNPACK_ELEM1__MASK                       0x0000ff00
-#define MDP4_PIPE_SRC_UNPACK_ELEM1__SHIFT                      8
-static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM1(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_UNPACK_ELEM1__SHIFT) & MDP4_PIPE_SRC_UNPACK_ELEM1__MASK;
-}
-#define MDP4_PIPE_SRC_UNPACK_ELEM2__MASK                       0x00ff0000
-#define MDP4_PIPE_SRC_UNPACK_ELEM2__SHIFT                      16
-static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM2(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_UNPACK_ELEM2__SHIFT) & MDP4_PIPE_SRC_UNPACK_ELEM2__MASK;
-}
-#define MDP4_PIPE_SRC_UNPACK_ELEM3__MASK                       0xff000000
-#define MDP4_PIPE_SRC_UNPACK_ELEM3__SHIFT                      24
-static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM3(uint32_t val)
-{
-       return ((val) << MDP4_PIPE_SRC_UNPACK_ELEM3__SHIFT) & MDP4_PIPE_SRC_UNPACK_ELEM3__MASK;
-}
-
-static inline uint32_t REG_MDP4_PIPE_OP_MODE(enum mdp4_pipe i0) { return 0x00020058 + 0x10000*i0; }
-#define MDP4_PIPE_OP_MODE_SCALEX_EN                            0x00000001
-#define MDP4_PIPE_OP_MODE_SCALEY_EN                            0x00000002
-#define MDP4_PIPE_OP_MODE_SRC_YCBCR                            0x00000200
-#define MDP4_PIPE_OP_MODE_DST_YCBCR                            0x00000400
-#define MDP4_PIPE_OP_MODE_CSC_EN                               0x00000800
-#define MDP4_PIPE_OP_MODE_FLIP_LR                              0x00002000
-#define MDP4_PIPE_OP_MODE_FLIP_UD                              0x00004000
-#define MDP4_PIPE_OP_MODE_DITHER_EN                            0x00008000
-#define MDP4_PIPE_OP_MODE_IGC_LUT_EN                           0x00010000
-#define MDP4_PIPE_OP_MODE_DEINT_EN                             0x00040000
-#define MDP4_PIPE_OP_MODE_DEINT_ODD_REF                                0x00080000
-
-static inline uint32_t REG_MDP4_PIPE_PHASEX_STEP(enum mdp4_pipe i0) { return 0x0002005c + 0x10000*i0; }
-
-static inline uint32_t REG_MDP4_PIPE_PHASEY_STEP(enum mdp4_pipe i0) { return 0x00020060 + 0x10000*i0; }
-
-static inline uint32_t REG_MDP4_PIPE_FETCH_CONFIG(enum mdp4_pipe i0) { return 0x00021004 + 0x10000*i0; }
-
-static inline uint32_t REG_MDP4_PIPE_SOLID_COLOR(enum mdp4_pipe i0) { return 0x00021008 + 0x10000*i0; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC(enum mdp4_pipe i0) { return 0x00024000 + 0x10000*i0; }
-
-
-static inline uint32_t REG_MDP4_PIPE_CSC_MV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024400 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_MV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024400 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_PRE_BV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024500 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_PRE_BV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024500 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_POST_BV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024580 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_POST_BV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024580 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_PRE_LV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024600 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_PRE_LV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024600 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_POST_LV(enum mdp4_pipe i0, uint32_t i1) { return 0x00024680 + 0x10000*i0 + 0x4*i1; }
-
-static inline uint32_t REG_MDP4_PIPE_CSC_POST_LV_VAL(enum mdp4_pipe i0, uint32_t i1) { return 0x00024680 + 0x10000*i0 + 0x4*i1; }
-
-#define REG_MDP4_LCDC                                          0x000c0000
-
-#define REG_MDP4_LCDC_ENABLE                                   0x000c0000
-
-#define REG_MDP4_LCDC_HSYNC_CTRL                               0x000c0004
-#define MDP4_LCDC_HSYNC_CTRL_PULSEW__MASK                      0x0000ffff
-#define MDP4_LCDC_HSYNC_CTRL_PULSEW__SHIFT                     0
-static inline uint32_t MDP4_LCDC_HSYNC_CTRL_PULSEW(uint32_t val)
-{
-       return ((val) << MDP4_LCDC_HSYNC_CTRL_PULSEW__SHIFT) & MDP4_LCDC_HSYNC_CTRL_PULSEW__MASK;
-}
-#define MDP4_LCDC_HSYNC_CTRL_PERIOD__MASK                      0xffff0000
-#define MDP4_LCDC_HSYNC_CTRL_PERIOD__SHIFT                     16
-static inline uint32_t MDP4_LCDC_HSYNC_CTRL_PERIOD(uint32_t val)
-{
-       return ((val) << MDP4_LCDC_HSYNC_CTRL_PERIOD__SHIFT) & MDP4_LCDC_HSYNC_CTRL_PERIOD__MASK;
-}
-
-#define REG_MDP4_LCDC_VSYNC_PERIOD                             0x000c0008
-
-#define REG_MDP4_LCDC_VSYNC_LEN                                        0x000c000c
-
-#define REG_MDP4_LCDC_DISPLAY_HCTRL                            0x000c0010
-#define MDP4_LCDC_DISPLAY_HCTRL_START__MASK                    0x0000ffff
-#define MDP4_LCDC_DISPLAY_HCTRL_START__SHIFT                   0
-static inline uint32_t MDP4_LCDC_DISPLAY_HCTRL_START(uint32_t val)
-{
-       return ((val) << MDP4_LCDC_DISPLAY_HCTRL_START__SHIFT) & MDP4_LCDC_DISPLAY_HCTRL_START__MASK;
-}
-#define MDP4_LCDC_DISPLAY_HCTRL_END__MASK                      0xffff0000
-#define MDP4_LCDC_DISPLAY_HCTRL_END__SHIFT                     16
-static inline uint32_t MDP4_LCDC_DISPLAY_HCTRL_END(uint32_t val)
-{
-       return ((val) << MDP4_LCDC_DISPLAY_HCTRL_END__SHIFT) & MDP4_LCDC_DISPLAY_HCTRL_END__MASK;
-}
-
-#define REG_MDP4_LCDC_DISPLAY_VSTART                           0x000c0014
-
-#define REG_MDP4_LCDC_DISPLAY_VEND                             0x000c0018
-
-#define REG_MDP4_LCDC_ACTIVE_HCTL                              0x000c001c
-#define MDP4_LCDC_ACTIVE_HCTL_START__MASK                      0x00007fff
-#define MDP4_LCDC_ACTIVE_HCTL_START__SHIFT                     0
-static inline uint32_t MDP4_LCDC_ACTIVE_HCTL_START(uint32_t val)
-{
-       return ((val) << MDP4_LCDC_ACTIVE_HCTL_START__SHIFT) & MDP4_LCDC_ACTIVE_HCTL_START__MASK;
-}
-#define MDP4_LCDC_ACTIVE_HCTL_END__MASK                                0x7fff0000
-#define MDP4_LCDC_ACTIVE_HCTL_END__SHIFT                       16
-static inline uint32_t MDP4_LCDC_ACTIVE_HCTL_END(uint32_t val)
-{
-       return ((val) << MDP4_LCDC_ACTIVE_HCTL_END__SHIFT) & MDP4_LCDC_ACTIVE_HCTL_END__MASK;
-}
-#define MDP4_LCDC_ACTIVE_HCTL_ACTIVE_START_X                   0x80000000
-
-#define REG_MDP4_LCDC_ACTIVE_VSTART                            0x000c0020
-
-#define REG_MDP4_LCDC_ACTIVE_VEND                              0x000c0024
-
-#define REG_MDP4_LCDC_BORDER_CLR                               0x000c0028
-
-#define REG_MDP4_LCDC_UNDERFLOW_CLR                            0x000c002c
-#define MDP4_LCDC_UNDERFLOW_CLR_COLOR__MASK                    0x00ffffff
-#define MDP4_LCDC_UNDERFLOW_CLR_COLOR__SHIFT                   0
-static inline uint32_t MDP4_LCDC_UNDERFLOW_CLR_COLOR(uint32_t val)
-{
-       return ((val) << MDP4_LCDC_UNDERFLOW_CLR_COLOR__SHIFT) & MDP4_LCDC_UNDERFLOW_CLR_COLOR__MASK;
-}
-#define MDP4_LCDC_UNDERFLOW_CLR_ENABLE_RECOVERY                        0x80000000
-
-#define REG_MDP4_LCDC_HSYNC_SKEW                               0x000c0030
-
-#define REG_MDP4_LCDC_TEST_CNTL                                        0x000c0034
-
-#define REG_MDP4_LCDC_CTRL_POLARITY                            0x000c0038
-#define MDP4_LCDC_CTRL_POLARITY_HSYNC_LOW                      0x00000001
-#define MDP4_LCDC_CTRL_POLARITY_VSYNC_LOW                      0x00000002
-#define MDP4_LCDC_CTRL_POLARITY_DATA_EN_LOW                    0x00000004
-
-#define REG_MDP4_DTV                                           0x000d0000
-
-#define REG_MDP4_DTV_ENABLE                                    0x000d0000
-
-#define REG_MDP4_DTV_HSYNC_CTRL                                        0x000d0004
-#define MDP4_DTV_HSYNC_CTRL_PULSEW__MASK                       0x0000ffff
-#define MDP4_DTV_HSYNC_CTRL_PULSEW__SHIFT                      0
-static inline uint32_t MDP4_DTV_HSYNC_CTRL_PULSEW(uint32_t val)
-{
-       return ((val) << MDP4_DTV_HSYNC_CTRL_PULSEW__SHIFT) & MDP4_DTV_HSYNC_CTRL_PULSEW__MASK;
-}
-#define MDP4_DTV_HSYNC_CTRL_PERIOD__MASK                       0xffff0000
-#define MDP4_DTV_HSYNC_CTRL_PERIOD__SHIFT                      16
-static inline uint32_t MDP4_DTV_HSYNC_CTRL_PERIOD(uint32_t val)
-{
-       return ((val) << MDP4_DTV_HSYNC_CTRL_PERIOD__SHIFT) & MDP4_DTV_HSYNC_CTRL_PERIOD__MASK;
-}
-
-#define REG_MDP4_DTV_VSYNC_PERIOD                              0x000d0008
-
-#define REG_MDP4_DTV_VSYNC_LEN                                 0x000d000c
-
-#define REG_MDP4_DTV_DISPLAY_HCTRL                             0x000d0018
-#define MDP4_DTV_DISPLAY_HCTRL_START__MASK                     0x0000ffff
-#define MDP4_DTV_DISPLAY_HCTRL_START__SHIFT                    0
-static inline uint32_t MDP4_DTV_DISPLAY_HCTRL_START(uint32_t val)
-{
-       return ((val) << MDP4_DTV_DISPLAY_HCTRL_START__SHIFT) & MDP4_DTV_DISPLAY_HCTRL_START__MASK;
-}
-#define MDP4_DTV_DISPLAY_HCTRL_END__MASK                       0xffff0000
-#define MDP4_DTV_DISPLAY_HCTRL_END__SHIFT                      16
-static inline uint32_t MDP4_DTV_DISPLAY_HCTRL_END(uint32_t val)
-{
-       return ((val) << MDP4_DTV_DISPLAY_HCTRL_END__SHIFT) & MDP4_DTV_DISPLAY_HCTRL_END__MASK;
-}
-
-#define REG_MDP4_DTV_DISPLAY_VSTART                            0x000d001c
-
-#define REG_MDP4_DTV_DISPLAY_VEND                              0x000d0020
-
-#define REG_MDP4_DTV_ACTIVE_HCTL                               0x000d002c
-#define MDP4_DTV_ACTIVE_HCTL_START__MASK                       0x00007fff
-#define MDP4_DTV_ACTIVE_HCTL_START__SHIFT                      0
-static inline uint32_t MDP4_DTV_ACTIVE_HCTL_START(uint32_t val)
-{
-       return ((val) << MDP4_DTV_ACTIVE_HCTL_START__SHIFT) & MDP4_DTV_ACTIVE_HCTL_START__MASK;
-}
-#define MDP4_DTV_ACTIVE_HCTL_END__MASK                         0x7fff0000
-#define MDP4_DTV_ACTIVE_HCTL_END__SHIFT                                16
-static inline uint32_t MDP4_DTV_ACTIVE_HCTL_END(uint32_t val)
-{
-       return ((val) << MDP4_DTV_ACTIVE_HCTL_END__SHIFT) & MDP4_DTV_ACTIVE_HCTL_END__MASK;
-}
-#define MDP4_DTV_ACTIVE_HCTL_ACTIVE_START_X                    0x80000000
-
-#define REG_MDP4_DTV_ACTIVE_VSTART                             0x000d0030
-
-#define REG_MDP4_DTV_ACTIVE_VEND                               0x000d0038
-
-#define REG_MDP4_DTV_BORDER_CLR                                        0x000d0040
-
-#define REG_MDP4_DTV_UNDERFLOW_CLR                             0x000d0044
-#define MDP4_DTV_UNDERFLOW_CLR_COLOR__MASK                     0x00ffffff
-#define MDP4_DTV_UNDERFLOW_CLR_COLOR__SHIFT                    0
-static inline uint32_t MDP4_DTV_UNDERFLOW_CLR_COLOR(uint32_t val)
-{
-       return ((val) << MDP4_DTV_UNDERFLOW_CLR_COLOR__SHIFT) & MDP4_DTV_UNDERFLOW_CLR_COLOR__MASK;
-}
-#define MDP4_DTV_UNDERFLOW_CLR_ENABLE_RECOVERY                 0x80000000
-
-#define REG_MDP4_DTV_HSYNC_SKEW                                        0x000d0048
-
-#define REG_MDP4_DTV_TEST_CNTL                                 0x000d004c
-
-#define REG_MDP4_DTV_CTRL_POLARITY                             0x000d0050
-#define MDP4_DTV_CTRL_POLARITY_HSYNC_LOW                       0x00000001
-#define MDP4_DTV_CTRL_POLARITY_VSYNC_LOW                       0x00000002
-#define MDP4_DTV_CTRL_POLARITY_DATA_EN_LOW                     0x00000004
-
-#define REG_MDP4_DSI                                           0x000e0000
-
-#define REG_MDP4_DSI_ENABLE                                    0x000e0000
-
-#define REG_MDP4_DSI_HSYNC_CTRL                                        0x000e0004
-#define MDP4_DSI_HSYNC_CTRL_PULSEW__MASK                       0x0000ffff
-#define MDP4_DSI_HSYNC_CTRL_PULSEW__SHIFT                      0
-static inline uint32_t MDP4_DSI_HSYNC_CTRL_PULSEW(uint32_t val)
-{
-       return ((val) << MDP4_DSI_HSYNC_CTRL_PULSEW__SHIFT) & MDP4_DSI_HSYNC_CTRL_PULSEW__MASK;
-}
-#define MDP4_DSI_HSYNC_CTRL_PERIOD__MASK                       0xffff0000
-#define MDP4_DSI_HSYNC_CTRL_PERIOD__SHIFT                      16
-static inline uint32_t MDP4_DSI_HSYNC_CTRL_PERIOD(uint32_t val)
-{
-       return ((val) << MDP4_DSI_HSYNC_CTRL_PERIOD__SHIFT) & MDP4_DSI_HSYNC_CTRL_PERIOD__MASK;
-}
-
-#define REG_MDP4_DSI_VSYNC_PERIOD                              0x000e0008
-
-#define REG_MDP4_DSI_VSYNC_LEN                                 0x000e000c
-
-#define REG_MDP4_DSI_DISPLAY_HCTRL                             0x000e0010
-#define MDP4_DSI_DISPLAY_HCTRL_START__MASK                     0x0000ffff
-#define MDP4_DSI_DISPLAY_HCTRL_START__SHIFT                    0
-static inline uint32_t MDP4_DSI_DISPLAY_HCTRL_START(uint32_t val)
-{
-       return ((val) << MDP4_DSI_DISPLAY_HCTRL_START__SHIFT) & MDP4_DSI_DISPLAY_HCTRL_START__MASK;
-}
-#define MDP4_DSI_DISPLAY_HCTRL_END__MASK                       0xffff0000
-#define MDP4_DSI_DISPLAY_HCTRL_END__SHIFT                      16
-static inline uint32_t MDP4_DSI_DISPLAY_HCTRL_END(uint32_t val)
-{
-       return ((val) << MDP4_DSI_DISPLAY_HCTRL_END__SHIFT) & MDP4_DSI_DISPLAY_HCTRL_END__MASK;
-}
-
-#define REG_MDP4_DSI_DISPLAY_VSTART                            0x000e0014
-
-#define REG_MDP4_DSI_DISPLAY_VEND                              0x000e0018
-
-#define REG_MDP4_DSI_ACTIVE_HCTL                               0x000e001c
-#define MDP4_DSI_ACTIVE_HCTL_START__MASK                       0x00007fff
-#define MDP4_DSI_ACTIVE_HCTL_START__SHIFT                      0
-static inline uint32_t MDP4_DSI_ACTIVE_HCTL_START(uint32_t val)
-{
-       return ((val) << MDP4_DSI_ACTIVE_HCTL_START__SHIFT) & MDP4_DSI_ACTIVE_HCTL_START__MASK;
-}
-#define MDP4_DSI_ACTIVE_HCTL_END__MASK                         0x7fff0000
-#define MDP4_DSI_ACTIVE_HCTL_END__SHIFT                                16
-static inline uint32_t MDP4_DSI_ACTIVE_HCTL_END(uint32_t val)
-{
-       return ((val) << MDP4_DSI_ACTIVE_HCTL_END__SHIFT) & MDP4_DSI_ACTIVE_HCTL_END__MASK;
-}
-#define MDP4_DSI_ACTIVE_HCTL_ACTIVE_START_X                    0x80000000
-
-#define REG_MDP4_DSI_ACTIVE_VSTART                             0x000e0020
-
-#define REG_MDP4_DSI_ACTIVE_VEND                               0x000e0024
-
-#define REG_MDP4_DSI_BORDER_CLR                                        0x000e0028
-
-#define REG_MDP4_DSI_UNDERFLOW_CLR                             0x000e002c
-#define MDP4_DSI_UNDERFLOW_CLR_COLOR__MASK                     0x00ffffff
-#define MDP4_DSI_UNDERFLOW_CLR_COLOR__SHIFT                    0
-static inline uint32_t MDP4_DSI_UNDERFLOW_CLR_COLOR(uint32_t val)
-{
-       return ((val) << MDP4_DSI_UNDERFLOW_CLR_COLOR__SHIFT) & MDP4_DSI_UNDERFLOW_CLR_COLOR__MASK;
-}
-#define MDP4_DSI_UNDERFLOW_CLR_ENABLE_RECOVERY                 0x80000000
-
-#define REG_MDP4_DSI_HSYNC_SKEW                                        0x000e0030
-
-#define REG_MDP4_DSI_TEST_CNTL                                 0x000e0034
-
-#define REG_MDP4_DSI_CTRL_POLARITY                             0x000e0038
-#define MDP4_DSI_CTRL_POLARITY_HSYNC_LOW                       0x00000001
-#define MDP4_DSI_CTRL_POLARITY_VSYNC_LOW                       0x00000002
-#define MDP4_DSI_CTRL_POLARITY_DATA_EN_LOW                     0x00000004
-
-
-#endif /* MDP4_XML */
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
deleted file mode 100644 (file)
index 019d530..0000000
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as 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 "mdp4_kms.h"
-
-#include <drm/drm_mode.h>
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-#include "drm_flip_work.h"
-
-struct mdp4_crtc {
-       struct drm_crtc base;
-       char name[8];
-       struct drm_plane *plane;
-       struct drm_plane *planes[8];
-       int id;
-       int ovlp;
-       enum mdp4_dma dma;
-       bool enabled;
-
-       /* which mixer/encoder we route output to: */
-       int mixer;
-
-       struct {
-               spinlock_t lock;
-               bool stale;
-               uint32_t width, height;
-
-               /* next cursor to scan-out: */
-               uint32_t next_iova;
-               struct drm_gem_object *next_bo;
-
-               /* current cursor being scanned out: */
-               struct drm_gem_object *scanout_bo;
-       } cursor;
-
-
-       /* if there is a pending flip, these will be non-null: */
-       struct drm_pending_vblank_event *event;
-       struct msm_fence_cb pageflip_cb;
-
-#define PENDING_CURSOR 0x1
-#define PENDING_FLIP   0x2
-       atomic_t pending;
-
-       /* the fb that we currently hold a scanout ref to: */
-       struct drm_framebuffer *fb;
-
-       /* for unref'ing framebuffers after scanout completes: */
-       struct drm_flip_work unref_fb_work;
-
-       /* for unref'ing cursor bo's after scanout completes: */
-       struct drm_flip_work unref_cursor_work;
-
-       struct mdp4_irq vblank;
-       struct mdp4_irq err;
-};
-#define to_mdp4_crtc(x) container_of(x, struct mdp4_crtc, base)
-
-static struct mdp4_kms *get_kms(struct drm_crtc *crtc)
-{
-       struct msm_drm_private *priv = crtc->dev->dev_private;
-       return to_mdp4_kms(priv->kms);
-}
-
-static void update_fb(struct drm_crtc *crtc, bool async,
-               struct drm_framebuffer *new_fb)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct drm_framebuffer *old_fb = mdp4_crtc->fb;
-
-       if (old_fb)
-               drm_flip_work_queue(&mdp4_crtc->unref_fb_work, old_fb);
-
-       /* grab reference to incoming scanout fb: */
-       drm_framebuffer_reference(new_fb);
-       mdp4_crtc->base.fb = new_fb;
-       mdp4_crtc->fb = new_fb;
-
-       if (!async) {
-               /* enable vblank to pick up the old_fb */
-               mdp4_irq_register(get_kms(crtc), &mdp4_crtc->vblank);
-       }
-}
-
-/* if file!=NULL, this is preclose potential cancel-flip path */
-static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct drm_pending_vblank_event *event;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->event_lock, flags);
-       event = mdp4_crtc->event;
-       if (event) {
-               /* if regular vblank case (!file) or if cancel-flip from
-                * preclose on file that requested flip, then send the
-                * event:
-                */
-               if (!file || (event->base.file_priv == file)) {
-                       mdp4_crtc->event = NULL;
-                       drm_send_vblank_event(dev, mdp4_crtc->id, event);
-               }
-       }
-       spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-static void crtc_flush(struct drm_crtc *crtc)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       uint32_t i, flush = 0;
-
-       for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
-               struct drm_plane *plane = mdp4_crtc->planes[i];
-               if (plane) {
-                       enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
-                       flush |= pipe2flush(pipe_id);
-               }
-       }
-       flush |= ovlp2flush(mdp4_crtc->ovlp);
-
-       DBG("%s: flush=%08x", mdp4_crtc->name, flush);
-
-       mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
-}
-
-static void request_pending(struct drm_crtc *crtc, uint32_t pending)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-
-       atomic_or(pending, &mdp4_crtc->pending);
-       mdp4_irq_register(get_kms(crtc), &mdp4_crtc->vblank);
-}
-
-static void pageflip_cb(struct msm_fence_cb *cb)
-{
-       struct mdp4_crtc *mdp4_crtc =
-               container_of(cb, struct mdp4_crtc, pageflip_cb);
-       struct drm_crtc *crtc = &mdp4_crtc->base;
-       struct drm_framebuffer *fb = crtc->fb;
-
-       if (!fb)
-               return;
-
-       mdp4_plane_set_scanout(mdp4_crtc->plane, fb);
-       crtc_flush(crtc);
-
-       /* enable vblank to complete flip: */
-       request_pending(crtc, PENDING_FLIP);
-}
-
-static void unref_fb_worker(struct drm_flip_work *work, void *val)
-{
-       struct mdp4_crtc *mdp4_crtc =
-               container_of(work, struct mdp4_crtc, unref_fb_work);
-       struct drm_device *dev = mdp4_crtc->base.dev;
-
-       mutex_lock(&dev->mode_config.mutex);
-       drm_framebuffer_unreference(val);
-       mutex_unlock(&dev->mode_config.mutex);
-}
-
-static void unref_cursor_worker(struct drm_flip_work *work, void *val)
-{
-       struct mdp4_crtc *mdp4_crtc =
-               container_of(work, struct mdp4_crtc, unref_cursor_work);
-       struct mdp4_kms *mdp4_kms = get_kms(&mdp4_crtc->base);
-
-       msm_gem_put_iova(val, mdp4_kms->id);
-       drm_gem_object_unreference_unlocked(val);
-}
-
-static void mdp4_crtc_destroy(struct drm_crtc *crtc)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-
-       mdp4_crtc->plane->funcs->destroy(mdp4_crtc->plane);
-
-       drm_crtc_cleanup(crtc);
-       drm_flip_work_cleanup(&mdp4_crtc->unref_fb_work);
-       drm_flip_work_cleanup(&mdp4_crtc->unref_cursor_work);
-
-       kfree(mdp4_crtc);
-}
-
-static void mdp4_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       bool enabled = (mode == DRM_MODE_DPMS_ON);
-
-       DBG("%s: mode=%d", mdp4_crtc->name, mode);
-
-       if (enabled != mdp4_crtc->enabled) {
-               if (enabled) {
-                       mdp4_enable(mdp4_kms);
-                       mdp4_irq_register(mdp4_kms, &mdp4_crtc->err);
-               } else {
-                       mdp4_irq_unregister(mdp4_kms, &mdp4_crtc->err);
-                       mdp4_disable(mdp4_kms);
-               }
-               mdp4_crtc->enabled = enabled;
-       }
-}
-
-static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc,
-               const struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-static void blend_setup(struct drm_crtc *crtc)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       int i, ovlp = mdp4_crtc->ovlp;
-       uint32_t mixer_cfg = 0;
-       static const enum mdp4_mixer_stage_id stages[] = {
-                       STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3,
-       };
-       /* statically (for now) map planes to mixer stage (z-order): */
-       static const int idxs[] = {
-                       [VG1]  = 1,
-                       [VG2]  = 2,
-                       [RGB1] = 0,
-                       [RGB2] = 0,
-                       [RGB3] = 0,
-                       [VG3]  = 3,
-                       [VG4]  = 4,
-
-       };
-       bool alpha[4]= { false, false, false, false };
-
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0);
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0);
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0);
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0);
-
-       /* TODO single register for all CRTCs, so this won't work properly
-        * when multiple CRTCs are active..
-        */
-       for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
-               struct drm_plane *plane = mdp4_crtc->planes[i];
-               if (plane) {
-                       enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
-                       int idx = idxs[pipe_id];
-                       if (idx > 0) {
-                               const struct mdp4_format *format =
-                                       to_mdp4_format(msm_framebuffer_format(plane->fb));
-                               alpha[idx-1] = format->alpha_enable;
-                       }
-                       mixer_cfg |= mixercfg(mdp4_crtc->mixer, pipe_id, stages[idx]);
-               }
-       }
-
-       /* this shouldn't happen.. and seems to cause underflow: */
-       WARN_ON(!mixer_cfg);
-
-       for (i = 0; i < 4; i++) {
-               uint32_t op;
-
-               if (alpha[i]) {
-                       op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_PIXEL) |
-                                       MDP4_OVLP_STAGE_OP_BG_ALPHA(FG_PIXEL) |
-                                       MDP4_OVLP_STAGE_OP_BG_INV_ALPHA;
-               } else {
-                       op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) |
-                                       MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST);
-               }
-
-               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0xff);
-               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0x00);
-               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), op);
-               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 1);
-               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp, i), 0);
-               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp, i), 0);
-               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp, i), 0);
-               mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0);
-       }
-
-       mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
-}
-
-static int mdp4_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 mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       enum mdp4_dma dma = mdp4_crtc->dma;
-       int ret, ovlp = mdp4_crtc->ovlp;
-
-       mode = adjusted_mode;
-
-       DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mdp4_crtc->name, mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
-
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_SIZE(dma),
-                       MDP4_DMA_SRC_SIZE_WIDTH(mode->hdisplay) |
-                       MDP4_DMA_SRC_SIZE_HEIGHT(mode->vdisplay));
-
-       /* take data from pipe: */
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_BASE(dma), 0);
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_STRIDE(dma),
-                       crtc->fb->pitches[0]);
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_DST_SIZE(dma),
-                       MDP4_DMA_DST_SIZE_WIDTH(0) |
-                       MDP4_DMA_DST_SIZE_HEIGHT(0));
-
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_BASE(ovlp), 0);
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_SIZE(ovlp),
-                       MDP4_OVLP_SIZE_WIDTH(mode->hdisplay) |
-                       MDP4_OVLP_SIZE_HEIGHT(mode->vdisplay));
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_STRIDE(ovlp),
-                       crtc->fb->pitches[0]);
-
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
-
-       update_fb(crtc, false, crtc->fb);
-
-       ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
-                       0, 0, mode->hdisplay, mode->vdisplay,
-                       x << 16, y << 16,
-                       mode->hdisplay << 16, mode->vdisplay << 16);
-       if (ret) {
-               dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
-                               mdp4_crtc->name, ret);
-               return ret;
-       }
-
-       if (dma == DMA_E) {
-               mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(0), 0x00ff0000);
-               mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(1), 0x00ff0000);
-               mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
-       }
-
-       return 0;
-}
-
-static void mdp4_crtc_prepare(struct drm_crtc *crtc)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       DBG("%s", mdp4_crtc->name);
-       /* make sure we hold a ref to mdp clks while setting up mode: */
-       mdp4_enable(get_kms(crtc));
-       mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void mdp4_crtc_commit(struct drm_crtc *crtc)
-{
-       mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-       crtc_flush(crtc);
-       /* drop the ref to mdp clk's that we got in prepare: */
-       mdp4_disable(get_kms(crtc));
-}
-
-static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-               struct drm_framebuffer *old_fb)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct drm_plane *plane = mdp4_crtc->plane;
-       struct drm_display_mode *mode = &crtc->mode;
-
-       update_fb(crtc, false, crtc->fb);
-
-       return mdp4_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 mdp4_crtc_load_lut(struct drm_crtc *crtc)
-{
-}
-
-static int mdp4_crtc_page_flip(struct drm_crtc *crtc,
-               struct drm_framebuffer *new_fb,
-               struct drm_pending_vblank_event *event,
-               uint32_t page_flip_flags)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct drm_gem_object *obj;
-       unsigned long flags;
-
-       if (mdp4_crtc->event) {
-               dev_err(dev->dev, "already pending flip!\n");
-               return -EBUSY;
-       }
-
-       obj = msm_framebuffer_bo(new_fb, 0);
-
-       spin_lock_irqsave(&dev->event_lock, flags);
-       mdp4_crtc->event = event;
-       spin_unlock_irqrestore(&dev->event_lock, flags);
-
-       update_fb(crtc, true, new_fb);
-
-       return msm_gem_queue_inactive_cb(obj, &mdp4_crtc->pageflip_cb);
-}
-
-static int mdp4_crtc_set_property(struct drm_crtc *crtc,
-               struct drm_property *property, uint64_t val)
-{
-       // XXX
-       return -EINVAL;
-}
-
-#define CURSOR_WIDTH 64
-#define CURSOR_HEIGHT 64
-
-/* called from IRQ to update cursor related registers (if needed).  The
- * cursor registers, other than x/y position, appear not to be double
- * buffered, and changing them other than from vblank seems to trigger
- * underflow.
- */
-static void update_cursor(struct drm_crtc *crtc)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       enum mdp4_dma dma = mdp4_crtc->dma;
-       unsigned long flags;
-
-       spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags);
-       if (mdp4_crtc->cursor.stale) {
-               struct mdp4_kms *mdp4_kms = get_kms(crtc);
-               struct drm_gem_object *next_bo = mdp4_crtc->cursor.next_bo;
-               struct drm_gem_object *prev_bo = mdp4_crtc->cursor.scanout_bo;
-               uint32_t iova = mdp4_crtc->cursor.next_iova;
-
-               if (next_bo) {
-                       /* take a obj ref + iova ref when we start scanning out: */
-                       drm_gem_object_reference(next_bo);
-                       msm_gem_get_iova_locked(next_bo, mdp4_kms->id, &iova);
-
-                       /* enable cursor: */
-                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_SIZE(dma),
-                                       MDP4_DMA_CURSOR_SIZE_WIDTH(mdp4_crtc->cursor.width) |
-                                       MDP4_DMA_CURSOR_SIZE_HEIGHT(mdp4_crtc->cursor.height));
-                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma), iova);
-                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma),
-                                       MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB) |
-                                       MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN);
-               } else {
-                       /* disable cursor: */
-                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma), 0);
-                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma),
-                                       MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB));
-               }
-
-               /* and drop the iova ref + obj rev when done scanning out: */
-               if (prev_bo)
-                       drm_flip_work_queue(&mdp4_crtc->unref_cursor_work, prev_bo);
-
-               mdp4_crtc->cursor.scanout_bo = next_bo;
-               mdp4_crtc->cursor.stale = false;
-       }
-       spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags);
-}
-
-static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
-               struct drm_file *file_priv, uint32_t handle,
-               uint32_t width, uint32_t height)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct drm_gem_object *cursor_bo, *old_bo;
-       unsigned long flags;
-       uint32_t iova;
-       int ret;
-
-       if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
-               dev_err(dev->dev, "bad cursor size: %dx%d\n", width, height);
-               return -EINVAL;
-       }
-
-       if (handle) {
-               cursor_bo = drm_gem_object_lookup(dev, file_priv, handle);
-               if (!cursor_bo)
-                       return -ENOENT;
-       } else {
-               cursor_bo = NULL;
-       }
-
-       if (cursor_bo) {
-               ret = msm_gem_get_iova(cursor_bo, mdp4_kms->id, &iova);
-               if (ret)
-                       goto fail;
-       } else {
-               iova = 0;
-       }
-
-       spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags);
-       old_bo = mdp4_crtc->cursor.next_bo;
-       mdp4_crtc->cursor.next_bo   = cursor_bo;
-       mdp4_crtc->cursor.next_iova = iova;
-       mdp4_crtc->cursor.width     = width;
-       mdp4_crtc->cursor.height    = height;
-       mdp4_crtc->cursor.stale     = true;
-       spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags);
-
-       if (old_bo) {
-               /* drop our previous reference: */
-               msm_gem_put_iova(old_bo, mdp4_kms->id);
-               drm_gem_object_unreference_unlocked(old_bo);
-       }
-
-       request_pending(crtc, PENDING_CURSOR);
-
-       return 0;
-
-fail:
-       drm_gem_object_unreference_unlocked(cursor_bo);
-       return ret;
-}
-
-static int mdp4_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       enum mdp4_dma dma = mdp4_crtc->dma;
-
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_POS(dma),
-                       MDP4_DMA_CURSOR_POS_X(x) |
-                       MDP4_DMA_CURSOR_POS_Y(y));
-
-       return 0;
-}
-
-static const struct drm_crtc_funcs mdp4_crtc_funcs = {
-       .set_config = drm_crtc_helper_set_config,
-       .destroy = mdp4_crtc_destroy,
-       .page_flip = mdp4_crtc_page_flip,
-       .set_property = mdp4_crtc_set_property,
-       .cursor_set = mdp4_crtc_cursor_set,
-       .cursor_move = mdp4_crtc_cursor_move,
-};
-
-static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = {
-       .dpms = mdp4_crtc_dpms,
-       .mode_fixup = mdp4_crtc_mode_fixup,
-       .mode_set = mdp4_crtc_mode_set,
-       .prepare = mdp4_crtc_prepare,
-       .commit = mdp4_crtc_commit,
-       .mode_set_base = mdp4_crtc_mode_set_base,
-       .load_lut = mdp4_crtc_load_lut,
-};
-
-static void mdp4_crtc_vblank_irq(struct mdp4_irq *irq, uint32_t irqstatus)
-{
-       struct mdp4_crtc *mdp4_crtc = container_of(irq, struct mdp4_crtc, vblank);
-       struct drm_crtc *crtc = &mdp4_crtc->base;
-       struct msm_drm_private *priv = crtc->dev->dev_private;
-       unsigned pending;
-
-       mdp4_irq_unregister(get_kms(crtc), &mdp4_crtc->vblank);
-
-       pending = atomic_xchg(&mdp4_crtc->pending, 0);
-
-       if (pending & PENDING_FLIP) {
-               complete_flip(crtc, NULL);
-               drm_flip_work_commit(&mdp4_crtc->unref_fb_work, priv->wq);
-       }
-
-       if (pending & PENDING_CURSOR) {
-               update_cursor(crtc);
-               drm_flip_work_commit(&mdp4_crtc->unref_cursor_work, priv->wq);
-       }
-}
-
-static void mdp4_crtc_err_irq(struct mdp4_irq *irq, uint32_t irqstatus)
-{
-       struct mdp4_crtc *mdp4_crtc = container_of(irq, struct mdp4_crtc, err);
-       struct drm_crtc *crtc = &mdp4_crtc->base;
-       DBG("%s: error: %08x", mdp4_crtc->name, irqstatus);
-       crtc_flush(crtc);
-}
-
-uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       return mdp4_crtc->vblank.irqmask;
-}
-
-void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
-{
-       DBG("cancel: %p", file);
-       complete_flip(crtc, file);
-}
-
-/* set dma config, ie. the format the encoder wants. */
-void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_CONFIG(mdp4_crtc->dma), config);
-}
-
-/* set interface for routing crtc->encoder: */
-void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       uint32_t intf_sel;
-
-       intf_sel = mdp4_read(mdp4_kms, REG_MDP4_DISP_INTF_SEL);
-
-       switch (mdp4_crtc->dma) {
-       case DMA_P:
-               intf_sel &= ~MDP4_DISP_INTF_SEL_PRIM__MASK;
-               intf_sel |= MDP4_DISP_INTF_SEL_PRIM(intf);
-               break;
-       case DMA_S:
-               intf_sel &= ~MDP4_DISP_INTF_SEL_SEC__MASK;
-               intf_sel |= MDP4_DISP_INTF_SEL_SEC(intf);
-               break;
-       case DMA_E:
-               intf_sel &= ~MDP4_DISP_INTF_SEL_EXT__MASK;
-               intf_sel |= MDP4_DISP_INTF_SEL_EXT(intf);
-               break;
-       }
-
-       if (intf == INTF_DSI_VIDEO) {
-               intf_sel &= ~MDP4_DISP_INTF_SEL_DSI_CMD;
-               intf_sel |= MDP4_DISP_INTF_SEL_DSI_VIDEO;
-               mdp4_crtc->mixer = 0;
-       } else if (intf == INTF_DSI_CMD) {
-               intf_sel &= ~MDP4_DISP_INTF_SEL_DSI_VIDEO;
-               intf_sel |= MDP4_DISP_INTF_SEL_DSI_CMD;
-               mdp4_crtc->mixer = 0;
-       } else if (intf == INTF_LCDC_DTV){
-               mdp4_crtc->mixer = 1;
-       }
-
-       blend_setup(crtc);
-
-       DBG("%s: intf_sel=%08x", mdp4_crtc->name, intf_sel);
-
-       mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
-}
-
-static void set_attach(struct drm_crtc *crtc, enum mdp4_pipe pipe_id,
-               struct drm_plane *plane)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-
-       BUG_ON(pipe_id >= ARRAY_SIZE(mdp4_crtc->planes));
-
-       if (mdp4_crtc->planes[pipe_id] == plane)
-               return;
-
-       mdp4_crtc->planes[pipe_id] = plane;
-       blend_setup(crtc);
-       if (mdp4_crtc->enabled && (plane != mdp4_crtc->plane))
-               crtc_flush(crtc);
-}
-
-void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane)
-{
-       set_attach(crtc, mdp4_plane_pipe(plane), plane);
-}
-
-void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane)
-{
-       set_attach(crtc, mdp4_plane_pipe(plane), NULL);
-}
-
-static const char *dma_names[] = {
-               "DMA_P", "DMA_S", "DMA_E",
-};
-
-/* initialize crtc */
-struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
-               struct drm_plane *plane, int id, int ovlp_id,
-               enum mdp4_dma dma_id)
-{
-       struct drm_crtc *crtc = NULL;
-       struct mdp4_crtc *mdp4_crtc;
-       int ret;
-
-       mdp4_crtc = kzalloc(sizeof(*mdp4_crtc), GFP_KERNEL);
-       if (!mdp4_crtc) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       crtc = &mdp4_crtc->base;
-
-       mdp4_crtc->plane = plane;
-
-       mdp4_crtc->ovlp = ovlp_id;
-       mdp4_crtc->dma = dma_id;
-
-       mdp4_crtc->vblank.irqmask = dma2irq(mdp4_crtc->dma);
-       mdp4_crtc->vblank.irq = mdp4_crtc_vblank_irq;
-
-       mdp4_crtc->err.irqmask = dma2err(mdp4_crtc->dma);
-       mdp4_crtc->err.irq = mdp4_crtc_err_irq;
-
-       snprintf(mdp4_crtc->name, sizeof(mdp4_crtc->name), "%s:%d",
-                       dma_names[dma_id], ovlp_id);
-
-       spin_lock_init(&mdp4_crtc->cursor.lock);
-
-       ret = drm_flip_work_init(&mdp4_crtc->unref_fb_work, 16,
-                       "unref fb", unref_fb_worker);
-       if (ret)
-               goto fail;
-
-       ret = drm_flip_work_init(&mdp4_crtc->unref_cursor_work, 64,
-                       "unref cursor", unref_cursor_worker);
-
-       INIT_FENCE_CB(&mdp4_crtc->pageflip_cb, pageflip_cb);
-
-       drm_crtc_init(dev, crtc, &mdp4_crtc_funcs);
-       drm_crtc_helper_add(crtc, &mdp4_crtc_helper_funcs);
-
-       mdp4_plane_install_properties(mdp4_crtc->plane, &crtc->base);
-
-       return crtc;
-
-fail:
-       if (crtc)
-               mdp4_crtc_destroy(crtc);
-
-       return ERR_PTR(ret);
-}
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c
deleted file mode 100644 (file)
index 5e0dcae..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as 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 <mach/clk.h>
-
-#include "mdp4_kms.h"
-
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-
-
-struct mdp4_dtv_encoder {
-       struct drm_encoder base;
-       struct clk *src_clk;
-       struct clk *hdmi_clk;
-       struct clk *mdp_clk;
-       unsigned long int pixclock;
-       bool enabled;
-       uint32_t bsc;
-};
-#define to_mdp4_dtv_encoder(x) container_of(x, struct mdp4_dtv_encoder, base)
-
-static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
-{
-       struct msm_drm_private *priv = encoder->dev->dev_private;
-       return to_mdp4_kms(priv->kms);
-}
-
-#ifdef CONFIG_MSM_BUS_SCALING
-#include <mach/board.h>
-/* not ironically named at all.. no, really.. */
-static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder)
-{
-       struct drm_device *dev = mdp4_dtv_encoder->base.dev;
-       struct lcdc_platform_data *dtv_pdata = mdp4_find_pdata("dtv.0");
-
-       if (!dtv_pdata) {
-               dev_err(dev->dev, "could not find dtv pdata\n");
-               return;
-       }
-
-       if (dtv_pdata->bus_scale_table) {
-               mdp4_dtv_encoder->bsc = msm_bus_scale_register_client(
-                               dtv_pdata->bus_scale_table);
-               DBG("bus scale client: %08x", mdp4_dtv_encoder->bsc);
-               DBG("lcdc_power_save: %p", dtv_pdata->lcdc_power_save);
-               if (dtv_pdata->lcdc_power_save)
-                       dtv_pdata->lcdc_power_save(1);
-       }
-}
-
-static void bs_fini(struct mdp4_dtv_encoder *mdp4_dtv_encoder)
-{
-       if (mdp4_dtv_encoder->bsc) {
-               msm_bus_scale_unregister_client(mdp4_dtv_encoder->bsc);
-               mdp4_dtv_encoder->bsc = 0;
-       }
-}
-
-static void bs_set(struct mdp4_dtv_encoder *mdp4_dtv_encoder, int idx)
-{
-       if (mdp4_dtv_encoder->bsc) {
-               DBG("set bus scaling: %d", idx);
-               msm_bus_scale_client_update_request(mdp4_dtv_encoder->bsc, idx);
-       }
-}
-#else
-static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder) {}
-static void bs_fini(struct mdp4_dtv_encoder *mdp4_dtv_encoder) {}
-static void bs_set(struct mdp4_dtv_encoder *mdp4_dtv_encoder, int idx) {}
-#endif
-
-static void mdp4_dtv_encoder_destroy(struct drm_encoder *encoder)
-{
-       struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
-       bs_fini(mdp4_dtv_encoder);
-       drm_encoder_cleanup(encoder);
-       kfree(mdp4_dtv_encoder);
-}
-
-static const struct drm_encoder_funcs mdp4_dtv_encoder_funcs = {
-       .destroy = mdp4_dtv_encoder_destroy,
-};
-
-static void mdp4_dtv_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
-       struct mdp4_kms *mdp4_kms = get_kms(encoder);
-       bool enabled = (mode == DRM_MODE_DPMS_ON);
-
-       DBG("mode=%d", mode);
-
-       if (enabled == mdp4_dtv_encoder->enabled)
-               return;
-
-       if (enabled) {
-               unsigned long pc = mdp4_dtv_encoder->pixclock;
-               int ret;
-
-               bs_set(mdp4_dtv_encoder, 1);
-
-               DBG("setting src_clk=%lu", pc);
-
-               ret = clk_set_rate(mdp4_dtv_encoder->src_clk, pc);
-               if (ret)
-                       dev_err(dev->dev, "failed to set src_clk to %lu: %d\n", pc, ret);
-               clk_prepare_enable(mdp4_dtv_encoder->src_clk);
-               ret = clk_prepare_enable(mdp4_dtv_encoder->hdmi_clk);
-               if (ret)
-                       dev_err(dev->dev, "failed to enable hdmi_clk: %d\n", ret);
-               ret = clk_prepare_enable(mdp4_dtv_encoder->mdp_clk);
-               if (ret)
-                       dev_err(dev->dev, "failed to enabled mdp_clk: %d\n", ret);
-
-               mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 1);
-       } else {
-               mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0);
-
-               /*
-                * Wait for a vsync so we know the ENABLE=0 latched before
-                * the (connector) source of the vsync's gets disabled,
-                * otherwise we end up in a funny state if we re-enable
-                * before the disable latches, which results that some of
-                * the settings changes for the new modeset (like new
-                * scanout buffer) don't latch properly..
-                */
-               mdp4_irq_wait(mdp4_kms, MDP4_IRQ_EXTERNAL_VSYNC);
-
-               clk_disable_unprepare(mdp4_dtv_encoder->src_clk);
-               clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk);
-               clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk);
-
-               bs_set(mdp4_dtv_encoder, 0);
-       }
-
-       mdp4_dtv_encoder->enabled = enabled;
-}
-
-static bool mdp4_dtv_encoder_mode_fixup(struct drm_encoder *encoder,
-               const struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder,
-               struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
-{
-       struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
-       struct mdp4_kms *mdp4_kms = get_kms(encoder);
-       uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
-       uint32_t display_v_start, display_v_end;
-       uint32_t hsync_start_x, hsync_end_x;
-
-       mode = adjusted_mode;
-
-       DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-                       mode->base.id, mode->name,
-                       mode->vrefresh, mode->clock,
-                       mode->hdisplay, mode->hsync_start,
-                       mode->hsync_end, mode->htotal,
-                       mode->vdisplay, mode->vsync_start,
-                       mode->vsync_end, mode->vtotal,
-                       mode->type, mode->flags);
-
-       mdp4_dtv_encoder->pixclock = mode->clock * 1000;
-
-       DBG("pixclock=%lu", mdp4_dtv_encoder->pixclock);
-
-       ctrl_pol = 0;
-       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-               ctrl_pol |= MDP4_DTV_CTRL_POLARITY_HSYNC_LOW;
-       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-               ctrl_pol |= MDP4_DTV_CTRL_POLARITY_VSYNC_LOW;
-       /* probably need to get DATA_EN polarity from panel.. */
-
-       dtv_hsync_skew = 0;  /* get this from panel? */
-
-       hsync_start_x = (mode->htotal - mode->hsync_start);
-       hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
-
-       vsync_period = mode->vtotal * mode->htotal;
-       vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
-       display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew;
-       display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1;
-
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_HSYNC_CTRL,
-                       MDP4_DTV_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
-                       MDP4_DTV_HSYNC_CTRL_PERIOD(mode->htotal));
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_VSYNC_PERIOD, vsync_period);
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_VSYNC_LEN, vsync_len);
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_HCTRL,
-                       MDP4_DTV_DISPLAY_HCTRL_START(hsync_start_x) |
-                       MDP4_DTV_DISPLAY_HCTRL_END(hsync_end_x));
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_VSTART, display_v_start);
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_VEND, display_v_end);
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_BORDER_CLR, 0);
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_UNDERFLOW_CLR,
-                       MDP4_DTV_UNDERFLOW_CLR_ENABLE_RECOVERY |
-                       MDP4_DTV_UNDERFLOW_CLR_COLOR(0xff));
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_HSYNC_SKEW, dtv_hsync_skew);
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_CTRL_POLARITY, ctrl_pol);
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_HCTL,
-                       MDP4_DTV_ACTIVE_HCTL_START(0) |
-                       MDP4_DTV_ACTIVE_HCTL_END(0));
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VSTART, 0);
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VEND, 0);
-}
-
-static void mdp4_dtv_encoder_prepare(struct drm_encoder *encoder)
-{
-       mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-static void mdp4_dtv_encoder_commit(struct drm_encoder *encoder)
-{
-       mdp4_crtc_set_config(encoder->crtc,
-                       MDP4_DMA_CONFIG_R_BPC(BPC8) |
-                       MDP4_DMA_CONFIG_G_BPC(BPC8) |
-                       MDP4_DMA_CONFIG_B_BPC(BPC8) |
-                       MDP4_DMA_CONFIG_PACK(0x21));
-       mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV);
-       mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
-static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = {
-       .dpms = mdp4_dtv_encoder_dpms,
-       .mode_fixup = mdp4_dtv_encoder_mode_fixup,
-       .mode_set = mdp4_dtv_encoder_mode_set,
-       .prepare = mdp4_dtv_encoder_prepare,
-       .commit = mdp4_dtv_encoder_commit,
-};
-
-long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
-{
-       struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
-       return clk_round_rate(mdp4_dtv_encoder->src_clk, rate);
-}
-
-/* initialize encoder */
-struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev)
-{
-       struct drm_encoder *encoder = NULL;
-       struct mdp4_dtv_encoder *mdp4_dtv_encoder;
-       int ret;
-
-       mdp4_dtv_encoder = kzalloc(sizeof(*mdp4_dtv_encoder), GFP_KERNEL);
-       if (!mdp4_dtv_encoder) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       encoder = &mdp4_dtv_encoder->base;
-
-       drm_encoder_init(dev, encoder, &mdp4_dtv_encoder_funcs,
-                        DRM_MODE_ENCODER_TMDS);
-       drm_encoder_helper_add(encoder, &mdp4_dtv_encoder_helper_funcs);
-
-       mdp4_dtv_encoder->src_clk = devm_clk_get(dev->dev, "src_clk");
-       if (IS_ERR(mdp4_dtv_encoder->src_clk)) {
-               dev_err(dev->dev, "failed to get src_clk\n");
-               ret = PTR_ERR(mdp4_dtv_encoder->src_clk);
-               goto fail;
-       }
-
-       mdp4_dtv_encoder->hdmi_clk = devm_clk_get(dev->dev, "hdmi_clk");
-       if (IS_ERR(mdp4_dtv_encoder->hdmi_clk)) {
-               dev_err(dev->dev, "failed to get hdmi_clk\n");
-               ret = PTR_ERR(mdp4_dtv_encoder->hdmi_clk);
-               goto fail;
-       }
-
-       mdp4_dtv_encoder->mdp_clk = devm_clk_get(dev->dev, "mdp_clk");
-       if (IS_ERR(mdp4_dtv_encoder->mdp_clk)) {
-               dev_err(dev->dev, "failed to get mdp_clk\n");
-               ret = PTR_ERR(mdp4_dtv_encoder->mdp_clk);
-               goto fail;
-       }
-
-       bs_init(mdp4_dtv_encoder);
-
-       return encoder;
-
-fail:
-       if (encoder)
-               mdp4_dtv_encoder_destroy(encoder);
-
-       return ERR_PTR(ret);
-}
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_format.c b/drivers/gpu/drm/msm/mdp4/mdp4_format.c
deleted file mode 100644 (file)
index 17330b0..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
-#include "mdp4_kms.h"
-
-#define FMT(name, a, r, g, b, e0, e1, e2, e3, alpha, tight, c, cnt) { \
-               .base = { .pixel_format = DRM_FORMAT_ ## name }, \
-               .bpc_a = BPC ## a ## A,                          \
-               .bpc_r = BPC ## r,                               \
-               .bpc_g = BPC ## g,                               \
-               .bpc_b = BPC ## b,                               \
-               .unpack = { e0, e1, e2, e3 },                    \
-               .alpha_enable = alpha,                           \
-               .unpack_tight = tight,                           \
-               .cpp = c,                                        \
-               .unpack_count = cnt,                             \
-       }
-
-#define BPC0A 0
-
-static const struct mdp4_format formats[] = {
-       /*  name      a  r  g  b   e0 e1 e2 e3  alpha   tight  cpp cnt */
-       FMT(ARGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  true,   true,  4,  4),
-       FMT(XRGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  false,  true,  4,  4),
-       FMT(RGB888,   0, 8, 8, 8,  1, 0, 2, 0,  false,  true,  3,  3),
-       FMT(BGR888,   0, 8, 8, 8,  2, 0, 1, 0,  false,  true,  3,  3),
-       FMT(RGB565,   0, 5, 6, 5,  1, 0, 2, 0,  false,  true,  2,  3),
-       FMT(BGR565,   0, 5, 6, 5,  2, 0, 1, 0,  false,  true,  2,  3),
-};
-
-uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
-               uint32_t max_formats)
-{
-       uint32_t i;
-       for (i = 0; i < ARRAY_SIZE(formats); i++) {
-               const struct mdp4_format *f = &formats[i];
-
-               if (i == max_formats)
-                       break;
-
-               pixel_formats[i] = f->base.pixel_format;
-       }
-
-       return i;
-}
-
-const struct msm_format *mdp4_get_format(struct msm_kms *kms, uint32_t format)
-{
-       int i;
-       for (i = 0; i < ARRAY_SIZE(formats); i++) {
-               const struct mdp4_format *f = &formats[i];
-               if (f->base.pixel_format == format)
-                       return &f->base;
-       }
-       return NULL;
-}
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_irq.c b/drivers/gpu/drm/msm/mdp4/mdp4_irq.c
deleted file mode 100644 (file)
index 5c6b7fc..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
-#include "mdp4_kms.h"
-
-
-struct mdp4_irq_wait {
-       struct mdp4_irq irq;
-       int count;
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(wait_event);
-
-static DEFINE_SPINLOCK(list_lock);
-
-static void update_irq(struct mdp4_kms *mdp4_kms)
-{
-       struct mdp4_irq *irq;
-       uint32_t irqmask = mdp4_kms->vblank_mask;
-
-       BUG_ON(!spin_is_locked(&list_lock));
-
-       list_for_each_entry(irq, &mdp4_kms->irq_list, node)
-               irqmask |= irq->irqmask;
-
-       mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, irqmask);
-}
-
-static void update_irq_unlocked(struct mdp4_kms *mdp4_kms)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&list_lock, flags);
-       update_irq(mdp4_kms);
-       spin_unlock_irqrestore(&list_lock, flags);
-}
-
-static void mdp4_irq_error_handler(struct mdp4_irq *irq, uint32_t irqstatus)
-{
-       DRM_ERROR("errors: %08x\n", irqstatus);
-}
-
-void mdp4_irq_preinstall(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, 0xffffffff);
-}
-
-int mdp4_irq_postinstall(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       struct mdp4_irq *error_handler = &mdp4_kms->error_handler;
-
-       INIT_LIST_HEAD(&mdp4_kms->irq_list);
-
-       error_handler->irq = mdp4_irq_error_handler;
-       error_handler->irqmask = MDP4_IRQ_PRIMARY_INTF_UDERRUN |
-                       MDP4_IRQ_EXTERNAL_INTF_UDERRUN;
-
-       mdp4_irq_register(mdp4_kms, error_handler);
-
-       return 0;
-}
-
-void mdp4_irq_uninstall(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000);
-}
-
-irqreturn_t mdp4_irq(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       struct drm_device *dev = mdp4_kms->dev;
-       struct msm_drm_private *priv = dev->dev_private;
-       struct mdp4_irq *handler, *n;
-       unsigned long flags;
-       unsigned int id;
-       uint32_t status;
-
-       status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS);
-       mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, status);
-
-       VERB("status=%08x", status);
-
-       for (id = 0; id < priv->num_crtcs; id++)
-               if (status & mdp4_crtc_vblank(priv->crtcs[id]))
-                       drm_handle_vblank(dev, id);
-
-       spin_lock_irqsave(&list_lock, flags);
-       mdp4_kms->in_irq = true;
-       list_for_each_entry_safe(handler, n, &mdp4_kms->irq_list, node) {
-               if (handler->irqmask & status) {
-                       spin_unlock_irqrestore(&list_lock, flags);
-                       handler->irq(handler, handler->irqmask & status);
-                       spin_lock_irqsave(&list_lock, flags);
-               }
-       }
-       mdp4_kms->in_irq = false;
-       update_irq(mdp4_kms);
-       spin_unlock_irqrestore(&list_lock, flags);
-
-       return IRQ_HANDLED;
-}
-
-int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       unsigned long flags;
-
-       spin_lock_irqsave(&list_lock, flags);
-       mdp4_kms->vblank_mask |= mdp4_crtc_vblank(crtc);
-       update_irq(mdp4_kms);
-       spin_unlock_irqrestore(&list_lock, flags);
-
-       return 0;
-}
-
-void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       unsigned long flags;
-
-       spin_lock_irqsave(&list_lock, flags);
-       mdp4_kms->vblank_mask &= ~mdp4_crtc_vblank(crtc);
-       update_irq(mdp4_kms);
-       spin_unlock_irqrestore(&list_lock, flags);
-}
-
-static void wait_irq(struct mdp4_irq *irq, uint32_t irqstatus)
-{
-       struct mdp4_irq_wait *wait =
-                       container_of(irq, struct mdp4_irq_wait, irq);
-       wait->count--;
-       wake_up_all(&wait_event);
-}
-
-void mdp4_irq_wait(struct mdp4_kms *mdp4_kms, uint32_t irqmask)
-{
-       struct mdp4_irq_wait wait = {
-               .irq = {
-                       .irq = wait_irq,
-                       .irqmask = irqmask,
-               },
-               .count = 1,
-       };
-       mdp4_irq_register(mdp4_kms, &wait.irq);
-       wait_event(wait_event, (wait.count <= 0));
-       mdp4_irq_unregister(mdp4_kms, &wait.irq);
-}
-
-void mdp4_irq_register(struct mdp4_kms *mdp4_kms, struct mdp4_irq *irq)
-{
-       unsigned long flags;
-       bool needs_update = false;
-
-       spin_lock_irqsave(&list_lock, flags);
-
-       if (!irq->registered) {
-               irq->registered = true;
-               list_add(&irq->node, &mdp4_kms->irq_list);
-               needs_update = !mdp4_kms->in_irq;
-       }
-
-       spin_unlock_irqrestore(&list_lock, flags);
-
-       if (needs_update)
-               update_irq_unlocked(mdp4_kms);
-}
-
-void mdp4_irq_unregister(struct mdp4_kms *mdp4_kms, struct mdp4_irq *irq)
-{
-       unsigned long flags;
-       bool needs_update = false;
-
-       spin_lock_irqsave(&list_lock, flags);
-
-       if (irq->registered) {
-               irq->registered = false;
-               list_del(&irq->node);
-               needs_update = !mdp4_kms->in_irq;
-       }
-
-       spin_unlock_irqrestore(&list_lock, flags);
-
-       if (needs_update)
-               update_irq_unlocked(mdp4_kms);
-}
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp4/mdp4_kms.c
deleted file mode 100644 (file)
index 8972ac3..0000000
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
-#include "mdp4_kms.h"
-
-static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev);
-
-static int mdp4_hw_init(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       struct drm_device *dev = mdp4_kms->dev;
-       uint32_t version, major, minor, dmap_cfg, vg_cfg;
-       unsigned long clk;
-       int ret = 0;
-
-       pm_runtime_get_sync(dev->dev);
-
-       version = mdp4_read(mdp4_kms, REG_MDP4_VERSION);
-
-       major = FIELD(version, MDP4_VERSION_MAJOR);
-       minor = FIELD(version, MDP4_VERSION_MINOR);
-
-       DBG("found MDP version v%d.%d", major, minor);
-
-       if (major != 4) {
-               dev_err(dev->dev, "unexpected MDP version: v%d.%d\n",
-                               major, minor);
-               ret = -ENXIO;
-               goto out;
-       }
-
-       mdp4_kms->rev = minor;
-
-       if (mdp4_kms->dsi_pll_vdda) {
-               if ((mdp4_kms->rev == 2) || (mdp4_kms->rev == 4)) {
-                       ret = regulator_set_voltage(mdp4_kms->dsi_pll_vdda,
-                                       1200000, 1200000);
-                       if (ret) {
-                               dev_err(dev->dev,
-                                       "failed to set dsi_pll_vdda voltage: %d\n", ret);
-                               goto out;
-                       }
-               }
-       }
-
-       if (mdp4_kms->dsi_pll_vddio) {
-               if (mdp4_kms->rev == 2) {
-                       ret = regulator_set_voltage(mdp4_kms->dsi_pll_vddio,
-                                       1800000, 1800000);
-                       if (ret) {
-                               dev_err(dev->dev,
-                                       "failed to set dsi_pll_vddio voltage: %d\n", ret);
-                               goto out;
-                       }
-               }
-       }
-
-       if (mdp4_kms->rev > 1) {
-               mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER0, 0x0707ffff);
-               mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER1, 0x03073f3f);
-       }
-
-       mdp4_write(mdp4_kms, REG_MDP4_PORTMAP_MODE, 0x3);
-
-       /* max read pending cmd config, 3 pending requests: */
-       mdp4_write(mdp4_kms, REG_MDP4_READ_CNFG, 0x02222);
-
-       clk = clk_get_rate(mdp4_kms->clk);
-
-       if ((mdp4_kms->rev >= 1) || (clk >= 90000000)) {
-               dmap_cfg = 0x47;     /* 16 bytes-burst x 8 req */
-               vg_cfg = 0x47;       /* 16 bytes-burs x 8 req */
-       } else {
-               dmap_cfg = 0x27;     /* 8 bytes-burst x 8 req */
-               vg_cfg = 0x43;       /* 16 bytes-burst x 4 req */
-       }
-
-       DBG("fetch config: dmap=%02x, vg=%02x", dmap_cfg, vg_cfg);
-
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_FETCH_CONFIG(DMA_P), dmap_cfg);
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_FETCH_CONFIG(DMA_E), dmap_cfg);
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(VG1), vg_cfg);
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(VG2), vg_cfg);
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(RGB1), vg_cfg);
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_FETCH_CONFIG(RGB2), vg_cfg);
-
-       if (mdp4_kms->rev >= 2)
-               mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG_UPDATE_METHOD, 1);
-
-       /* disable CSC matrix / YUV by default: */
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(VG1), 0);
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(VG2), 0);
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_P_OP_MODE, 0);
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_S_OP_MODE, 0);
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_CSC_CONFIG(1), 0);
-       mdp4_write(mdp4_kms, REG_MDP4_OVLP_CSC_CONFIG(2), 0);
-
-       if (mdp4_kms->rev > 1)
-               mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1);
-
-out:
-       pm_runtime_put_sync(dev->dev);
-
-       return ret;
-}
-
-static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
-               struct drm_encoder *encoder)
-{
-       /* if we had >1 encoder, we'd need something more clever: */
-       return mdp4_dtv_round_pixclk(encoder, rate);
-}
-
-static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       struct msm_drm_private *priv = mdp4_kms->dev->dev_private;
-       unsigned i;
-
-       for (i = 0; i < priv->num_crtcs; i++)
-               mdp4_crtc_cancel_pending_flip(priv->crtcs[i], file);
-}
-
-static void mdp4_destroy(struct msm_kms *kms)
-{
-       struct mdp4_kms *mdp4_kms = to_mdp4_kms(kms);
-       kfree(mdp4_kms);
-}
-
-static const struct msm_kms_funcs kms_funcs = {
-               .hw_init         = mdp4_hw_init,
-               .irq_preinstall  = mdp4_irq_preinstall,
-               .irq_postinstall = mdp4_irq_postinstall,
-               .irq_uninstall   = mdp4_irq_uninstall,
-               .irq             = mdp4_irq,
-               .enable_vblank   = mdp4_enable_vblank,
-               .disable_vblank  = mdp4_disable_vblank,
-               .get_format      = mdp4_get_format,
-               .round_pixclk    = mdp4_round_pixclk,
-               .preclose        = mdp4_preclose,
-               .destroy         = mdp4_destroy,
-};
-
-int mdp4_disable(struct mdp4_kms *mdp4_kms)
-{
-       DBG("");
-
-       clk_disable_unprepare(mdp4_kms->clk);
-       if (mdp4_kms->pclk)
-               clk_disable_unprepare(mdp4_kms->pclk);
-       clk_disable_unprepare(mdp4_kms->lut_clk);
-
-       return 0;
-}
-
-int mdp4_enable(struct mdp4_kms *mdp4_kms)
-{
-       DBG("");
-
-       clk_prepare_enable(mdp4_kms->clk);
-       if (mdp4_kms->pclk)
-               clk_prepare_enable(mdp4_kms->pclk);
-       clk_prepare_enable(mdp4_kms->lut_clk);
-
-       return 0;
-}
-
-static int modeset_init(struct mdp4_kms *mdp4_kms)
-{
-       struct drm_device *dev = mdp4_kms->dev;
-       struct msm_drm_private *priv = dev->dev_private;
-       struct drm_plane *plane;
-       struct drm_crtc *crtc;
-       struct drm_encoder *encoder;
-       int ret;
-
-       /*
-        *  NOTE: this is a bit simplistic until we add support
-        * for more than just RGB1->DMA_E->DTV->HDMI
-        */
-
-       /* construct non-private planes: */
-       plane = mdp4_plane_init(dev, VG1, false);
-       if (IS_ERR(plane)) {
-               dev_err(dev->dev, "failed to construct plane for VG1\n");
-               ret = PTR_ERR(plane);
-               goto fail;
-       }
-       priv->planes[priv->num_planes++] = plane;
-
-       plane = mdp4_plane_init(dev, VG2, false);
-       if (IS_ERR(plane)) {
-               dev_err(dev->dev, "failed to construct plane for VG2\n");
-               ret = PTR_ERR(plane);
-               goto fail;
-       }
-       priv->planes[priv->num_planes++] = plane;
-
-       /* the CRTCs get constructed with a private plane: */
-       plane = mdp4_plane_init(dev, RGB1, true);
-       if (IS_ERR(plane)) {
-               dev_err(dev->dev, "failed to construct plane for RGB1\n");
-               ret = PTR_ERR(plane);
-               goto fail;
-       }
-
-       crtc  = mdp4_crtc_init(dev, plane, priv->num_crtcs, 1, DMA_E);
-       if (IS_ERR(crtc)) {
-               dev_err(dev->dev, "failed to construct crtc for DMA_E\n");
-               ret = PTR_ERR(crtc);
-               goto fail;
-       }
-       priv->crtcs[priv->num_crtcs++] = crtc;
-
-       encoder = mdp4_dtv_encoder_init(dev);
-       if (IS_ERR(encoder)) {
-               dev_err(dev->dev, "failed to construct DTV encoder\n");
-               ret = PTR_ERR(encoder);
-               goto fail;
-       }
-       encoder->possible_crtcs = 0x1;     /* DTV can be hooked to DMA_E */
-       priv->encoders[priv->num_encoders++] = encoder;
-
-       ret = hdmi_init(dev, encoder);
-       if (ret) {
-               dev_err(dev->dev, "failed to initialize HDMI\n");
-               goto fail;
-       }
-
-       return 0;
-
-fail:
-       return ret;
-}
-
-static const char *iommu_ports[] = {
-               "mdp_port0_cb0", "mdp_port1_cb0",
-};
-
-struct msm_kms *mdp4_kms_init(struct drm_device *dev)
-{
-       struct platform_device *pdev = dev->platformdev;
-       struct mdp4_platform_config *config = mdp4_get_config(pdev);
-       struct mdp4_kms *mdp4_kms;
-       struct msm_kms *kms = NULL;
-       int ret;
-
-       mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
-       if (!mdp4_kms) {
-               dev_err(dev->dev, "failed to allocate kms\n");
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       kms = &mdp4_kms->base;
-       kms->funcs = &kms_funcs;
-
-       mdp4_kms->dev = dev;
-
-       mdp4_kms->mmio = msm_ioremap(pdev, NULL, "MDP4");
-       if (IS_ERR(mdp4_kms->mmio)) {
-               ret = PTR_ERR(mdp4_kms->mmio);
-               goto fail;
-       }
-
-       mdp4_kms->dsi_pll_vdda = devm_regulator_get(&pdev->dev, "dsi_pll_vdda");
-       if (IS_ERR(mdp4_kms->dsi_pll_vdda))
-               mdp4_kms->dsi_pll_vdda = NULL;
-
-       mdp4_kms->dsi_pll_vddio = devm_regulator_get(&pdev->dev, "dsi_pll_vddio");
-       if (IS_ERR(mdp4_kms->dsi_pll_vddio))
-               mdp4_kms->dsi_pll_vddio = NULL;
-
-       mdp4_kms->vdd = devm_regulator_get(&pdev->dev, "vdd");
-       if (IS_ERR(mdp4_kms->vdd))
-               mdp4_kms->vdd = NULL;
-
-       if (mdp4_kms->vdd) {
-               ret = regulator_enable(mdp4_kms->vdd);
-               if (ret) {
-                       dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret);
-                       goto fail;
-               }
-       }
-
-       mdp4_kms->clk = devm_clk_get(&pdev->dev, "core_clk");
-       if (IS_ERR(mdp4_kms->clk)) {
-               dev_err(dev->dev, "failed to get core_clk\n");
-               ret = PTR_ERR(mdp4_kms->clk);
-               goto fail;
-       }
-
-       mdp4_kms->pclk = devm_clk_get(&pdev->dev, "iface_clk");
-       if (IS_ERR(mdp4_kms->pclk))
-               mdp4_kms->pclk = NULL;
-
-       // XXX if (rev >= MDP_REV_42) { ???
-       mdp4_kms->lut_clk = devm_clk_get(&pdev->dev, "lut_clk");
-       if (IS_ERR(mdp4_kms->lut_clk)) {
-               dev_err(dev->dev, "failed to get lut_clk\n");
-               ret = PTR_ERR(mdp4_kms->lut_clk);
-               goto fail;
-       }
-
-       clk_set_rate(mdp4_kms->clk, config->max_clk);
-       clk_set_rate(mdp4_kms->lut_clk, config->max_clk);
-
-       if (!config->iommu) {
-               dev_err(dev->dev, "no iommu\n");
-               ret = -ENXIO;
-               goto fail;
-       }
-
-       /* make sure things are off before attaching iommu (bootloader could
-        * have left things on, in which case we'll start getting faults if
-        * we don't disable):
-        */
-       mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0);
-       mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
-       mdp4_write(mdp4_kms, REG_MDP4_DSI_ENABLE, 0);
-       mdelay(16);
-
-       ret = msm_iommu_attach(dev, config->iommu,
-                       iommu_ports, ARRAY_SIZE(iommu_ports));
-       if (ret)
-               goto fail;
-
-       mdp4_kms->id = msm_register_iommu(dev, config->iommu);
-       if (mdp4_kms->id < 0) {
-               ret = mdp4_kms->id;
-               dev_err(dev->dev, "failed to register mdp4 iommu: %d\n", ret);
-               goto fail;
-       }
-
-       ret = modeset_init(mdp4_kms);
-       if (ret) {
-               dev_err(dev->dev, "modeset_init failed: %d\n", ret);
-               goto fail;
-       }
-
-       return kms;
-
-fail:
-       if (kms)
-               mdp4_destroy(kms);
-       return ERR_PTR(ret);
-}
-
-static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev)
-{
-       static struct mdp4_platform_config config = {};
-#ifdef CONFIG_OF
-       /* TODO */
-#else
-       if (cpu_is_apq8064())
-               config.max_clk = 266667000;
-       else
-               config.max_clk = 200000000;
-
-       config.iommu = msm_get_iommu_domain(DISPLAY_READ_DOMAIN);
-#endif
-       return &config;
-}
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp4/mdp4_kms.h
deleted file mode 100644 (file)
index eb015c8..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __MDP4_KMS_H__
-#define __MDP4_KMS_H__
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-
-#include "msm_drv.h"
-#include "mdp4.xml.h"
-
-
-/* For transiently registering for different MDP4 irqs that various parts
- * of the KMS code need during setup/configuration.  We these are not
- * necessarily the same as what drm_vblank_get/put() are requesting, and
- * the hysteresis in drm_vblank_put() is not necessarily desirable for
- * internal housekeeping related irq usage.
- */
-struct mdp4_irq {
-       struct list_head node;
-       uint32_t irqmask;
-       bool registered;
-       void (*irq)(struct mdp4_irq *irq, uint32_t irqstatus);
-};
-
-struct mdp4_kms {
-       struct msm_kms base;
-
-       struct drm_device *dev;
-
-       int rev;
-
-       /* mapper-id used to request GEM buffer mapped for scanout: */
-       int id;
-
-       void __iomem *mmio;
-
-       struct regulator *dsi_pll_vdda;
-       struct regulator *dsi_pll_vddio;
-       struct regulator *vdd;
-
-       struct clk *clk;
-       struct clk *pclk;
-       struct clk *lut_clk;
-
-       /* irq handling: */
-       bool in_irq;
-       struct list_head irq_list;    /* list of mdp4_irq */
-       uint32_t vblank_mask;         /* irq bits set for userspace vblank */
-       struct mdp4_irq error_handler;
-};
-#define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
-
-/* platform config data (ie. from DT, or pdata) */
-struct mdp4_platform_config {
-       struct iommu_domain *iommu;
-       uint32_t max_clk;
-};
-
-struct mdp4_format {
-       struct msm_format base;
-       enum mdp4_bpc bpc_r, bpc_g, bpc_b;
-       enum mdp4_bpc_alpha bpc_a;
-       uint8_t unpack[4];
-       bool alpha_enable, unpack_tight;
-       uint8_t cpp, unpack_count;
-};
-#define to_mdp4_format(x) container_of(x, struct mdp4_format, base)
-
-static inline void mdp4_write(struct mdp4_kms *mdp4_kms, u32 reg, u32 data)
-{
-       msm_writel(data, mdp4_kms->mmio + reg);
-}
-
-static inline u32 mdp4_read(struct mdp4_kms *mdp4_kms, u32 reg)
-{
-       return msm_readl(mdp4_kms->mmio + reg);
-}
-
-static inline uint32_t pipe2flush(enum mdp4_pipe pipe)
-{
-       switch (pipe) {
-       case VG1:      return MDP4_OVERLAY_FLUSH_VG1;
-       case VG2:      return MDP4_OVERLAY_FLUSH_VG2;
-       case RGB1:     return MDP4_OVERLAY_FLUSH_RGB1;
-       case RGB2:     return MDP4_OVERLAY_FLUSH_RGB1;
-       default:       return 0;
-       }
-}
-
-static inline uint32_t ovlp2flush(int ovlp)
-{
-       switch (ovlp) {
-       case 0:        return MDP4_OVERLAY_FLUSH_OVLP0;
-       case 1:        return MDP4_OVERLAY_FLUSH_OVLP1;
-       default:       return 0;
-       }
-}
-
-static inline uint32_t dma2irq(enum mdp4_dma dma)
-{
-       switch (dma) {
-       case DMA_P:    return MDP4_IRQ_DMA_P_DONE;
-       case DMA_S:    return MDP4_IRQ_DMA_S_DONE;
-       case DMA_E:    return MDP4_IRQ_DMA_E_DONE;
-       default:       return 0;
-       }
-}
-
-static inline uint32_t dma2err(enum mdp4_dma dma)
-{
-       switch (dma) {
-       case DMA_P:    return MDP4_IRQ_PRIMARY_INTF_UDERRUN;
-       case DMA_S:    return 0;  // ???
-       case DMA_E:    return MDP4_IRQ_EXTERNAL_INTF_UDERRUN;
-       default:       return 0;
-       }
-}
-
-static inline uint32_t mixercfg(int mixer, enum mdp4_pipe pipe,
-               enum mdp4_mixer_stage_id stage)
-{
-       uint32_t mixer_cfg = 0;
-
-       switch (pipe) {
-       case VG1:
-               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE0(stage) |
-                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1);
-               break;
-       case VG2:
-               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE1(stage) |
-                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1);
-               break;
-       case RGB1:
-               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE2(stage) |
-                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1);
-               break;
-       case RGB2:
-               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE3(stage) |
-                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1);
-               break;
-       case RGB3:
-               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE4(stage) |
-                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1);
-               break;
-       case VG3:
-               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE5(stage) |
-                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1);
-               break;
-       case VG4:
-               mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE6(stage) |
-                       COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1);
-               break;
-       default:
-               WARN_ON("invalid pipe");
-               break;
-       }
-
-       return mixer_cfg;
-}
-
-int mdp4_disable(struct mdp4_kms *mdp4_kms);
-int mdp4_enable(struct mdp4_kms *mdp4_kms);
-
-void mdp4_irq_preinstall(struct msm_kms *kms);
-int mdp4_irq_postinstall(struct msm_kms *kms);
-void mdp4_irq_uninstall(struct msm_kms *kms);
-irqreturn_t mdp4_irq(struct msm_kms *kms);
-void mdp4_irq_wait(struct mdp4_kms *mdp4_kms, uint32_t irqmask);
-void mdp4_irq_register(struct mdp4_kms *mdp4_kms, struct mdp4_irq *irq);
-void mdp4_irq_unregister(struct mdp4_kms *mdp4_kms, struct mdp4_irq *irq);
-int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
-void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
-
-uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *formats,
-               uint32_t max_formats);
-const struct msm_format *mdp4_get_format(struct msm_kms *kms, uint32_t format);
-
-void mdp4_plane_install_properties(struct drm_plane *plane,
-               struct drm_mode_object *obj);
-void mdp4_plane_set_scanout(struct drm_plane *plane,
-               struct drm_framebuffer *fb);
-int mdp4_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);
-enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane);
-struct drm_plane *mdp4_plane_init(struct drm_device *dev,
-               enum mdp4_pipe pipe_id, bool private_plane);
-
-uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);
-void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
-void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config);
-void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf);
-void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane);
-void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane);
-struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
-               struct drm_plane *plane, int id, int ovlp_id,
-               enum mdp4_dma dma_id);
-
-long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate);
-struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev);
-
-#ifdef CONFIG_MSM_BUS_SCALING
-static inline int match_dev_name(struct device *dev, void *data)
-{
-       return !strcmp(dev_name(dev), data);
-}
-/* bus scaling data is associated with extra pointless platform devices,
- * "dtv", etc.. this is a bit of a hack, but we need a way for encoders
- * to find their pdata to make the bus-scaling stuff work.
- */
-static inline void *mdp4_find_pdata(const char *devname)
-{
-       struct device *dev;
-       dev = bus_find_device(&platform_bus_type, NULL,
-                       (void *)devname, match_dev_name);
-       return dev ? dev->platform_data : NULL;
-}
-#endif
-
-#endif /* __MDP4_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp4/mdp4_plane.c
deleted file mode 100644 (file)
index 0f0af24..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as 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 "mdp4_kms.h"
-
-
-struct mdp4_plane {
-       struct drm_plane base;
-       const char *name;
-
-       enum mdp4_pipe pipe;
-
-       uint32_t nformats;
-       uint32_t formats[32];
-
-       bool enabled;
-};
-#define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base)
-
-static struct mdp4_kms *get_kms(struct drm_plane *plane)
-{
-       struct msm_drm_private *priv = plane->dev->dev_private;
-       return to_mdp4_kms(priv->kms);
-}
-
-static int mdp4_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)
-{
-       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
-
-       mdp4_plane->enabled = true;
-
-       if (plane->fb)
-               drm_framebuffer_unreference(plane->fb);
-
-       drm_framebuffer_reference(fb);
-
-       return mdp4_plane_mode_set(plane, crtc, fb,
-                       crtc_x, crtc_y, crtc_w, crtc_h,
-                       src_x, src_y, src_w, src_h);
-}
-
-static int mdp4_plane_disable(struct drm_plane *plane)
-{
-       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
-       DBG("%s: disable", mdp4_plane->name);
-       if (plane->crtc)
-               mdp4_crtc_detach(plane->crtc, plane);
-       return 0;
-}
-
-static void mdp4_plane_destroy(struct drm_plane *plane)
-{
-       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
-
-       mdp4_plane_disable(plane);
-       drm_plane_cleanup(plane);
-
-       kfree(mdp4_plane);
-}
-
-/* helper to install properties which are common to planes and crtcs */
-void mdp4_plane_install_properties(struct drm_plane *plane,
-               struct drm_mode_object *obj)
-{
-       // XXX
-}
-
-int mdp4_plane_set_property(struct drm_plane *plane,
-               struct drm_property *property, uint64_t val)
-{
-       // XXX
-       return -EINVAL;
-}
-
-static const struct drm_plane_funcs mdp4_plane_funcs = {
-               .update_plane = mdp4_plane_update,
-               .disable_plane = mdp4_plane_disable,
-               .destroy = mdp4_plane_destroy,
-               .set_property = mdp4_plane_set_property,
-};
-
-void mdp4_plane_set_scanout(struct drm_plane *plane,
-               struct drm_framebuffer *fb)
-{
-       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
-       struct mdp4_kms *mdp4_kms = get_kms(plane);
-       enum mdp4_pipe pipe = mdp4_plane->pipe;
-       uint32_t iova;
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe),
-                       MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
-                       MDP4_PIPE_SRC_STRIDE_A_P1(fb->pitches[1]));
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_B(pipe),
-                       MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) |
-                       MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3]));
-
-       msm_gem_get_iova(msm_framebuffer_bo(fb, 0), mdp4_kms->id, &iova);
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), iova);
-
-       plane->fb = fb;
-}
-
-#define MDP4_VG_PHASE_STEP_DEFAULT     0x20000000
-
-int mdp4_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 mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
-       struct mdp4_kms *mdp4_kms = get_kms(plane);
-       enum mdp4_pipe pipe = mdp4_plane->pipe;
-       const struct mdp4_format *format;
-       uint32_t op_mode = 0;
-       uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
-       uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
-
-       /* 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;
-
-       DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp4_plane->name,
-                       fb->base.id, src_x, src_y, src_w, src_h,
-                       crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
-
-       if (src_w != crtc_w) {
-               op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN;
-               /* TODO calc phasex_step */
-       }
-
-       if (src_h != crtc_h) {
-               op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN;
-               /* TODO calc phasey_step */
-       }
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe),
-                       MDP4_PIPE_SRC_SIZE_WIDTH(src_w) |
-                       MDP4_PIPE_SRC_SIZE_HEIGHT(src_h));
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_XY(pipe),
-                       MDP4_PIPE_SRC_XY_X(src_x) |
-                       MDP4_PIPE_SRC_XY_Y(src_y));
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_SIZE(pipe),
-                       MDP4_PIPE_DST_SIZE_WIDTH(crtc_w) |
-                       MDP4_PIPE_DST_SIZE_HEIGHT(crtc_h));
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_XY(pipe),
-                       MDP4_PIPE_SRC_XY_X(crtc_x) |
-                       MDP4_PIPE_SRC_XY_Y(crtc_y));
-
-       mdp4_plane_set_scanout(plane, fb);
-
-       format = to_mdp4_format(msm_framebuffer_format(fb));
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe),
-                       MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
-                       MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
-                       MDP4_PIPE_SRC_FORMAT_G_BPC(format->bpc_g) |
-                       MDP4_PIPE_SRC_FORMAT_B_BPC(format->bpc_b) |
-                       COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) |
-                       MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
-                       MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
-                       COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),
-                       MDP4_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
-                       MDP4_PIPE_SRC_UNPACK_ELEM1(format->unpack[1]) |
-                       MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) |
-                       MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));
-
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode);
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);
-       mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);
-
-       /* TODO detach from old crtc (if we had more than one) */
-       mdp4_crtc_attach(crtc, plane);
-
-       return 0;
-}
-
-static const char *pipe_names[] = {
-               "VG1", "VG2",
-               "RGB1", "RGB2", "RGB3",
-               "VG3", "VG4",
-};
-
-enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane)
-{
-       struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
-       return mdp4_plane->pipe;
-}
-
-/* initialize plane */
-struct drm_plane *mdp4_plane_init(struct drm_device *dev,
-               enum mdp4_pipe pipe_id, bool private_plane)
-{
-       struct drm_plane *plane = NULL;
-       struct mdp4_plane *mdp4_plane;
-       int ret;
-
-       mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL);
-       if (!mdp4_plane) {
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       plane = &mdp4_plane->base;
-
-       mdp4_plane->pipe = pipe_id;
-       mdp4_plane->name = pipe_names[pipe_id];
-
-       mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats,
-                       ARRAY_SIZE(mdp4_plane->formats));
-
-       drm_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
-                       mdp4_plane->formats, mdp4_plane->nformats,
-                       private_plane);
-
-       mdp4_plane_install_properties(plane, &plane->base);
-
-       return plane;
-
-fail:
-       if (plane)
-               mdp4_plane_destroy(plane);
-
-       return ERR_PTR(ret);
-}
index 86537692e45c4efaeae162d32753cf5613216954..e6adafc7eff3177b789395f6bc81f4ab62042e11 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "msm_drv.h"
 #include "msm_gpu.h"
+#include "msm_kms.h"
 
 static void msm_fb_output_poll_changed(struct drm_device *dev)
 {
@@ -30,50 +31,19 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
        .output_poll_changed = msm_fb_output_poll_changed,
 };
 
-static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
-               unsigned long iova, int flags, void *arg)
-{
-       DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
-       return 0;
-}
-
-int msm_register_iommu(struct drm_device *dev, struct iommu_domain *iommu)
+int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu)
 {
        struct msm_drm_private *priv = dev->dev_private;
-       int idx = priv->num_iommus++;
+       int idx = priv->num_mmus++;
 
-       if (WARN_ON(idx >= ARRAY_SIZE(priv->iommus)))
+       if (WARN_ON(idx >= ARRAY_SIZE(priv->mmus)))
                return -EINVAL;
 
-       priv->iommus[idx] = iommu;
-
-       iommu_set_fault_handler(iommu, msm_fault_handler, dev);
-
-       /* need to iommu_attach_device() somewhere??  on resume?? */
+       priv->mmus[idx] = mmu;
 
        return idx;
 }
 
-int msm_iommu_attach(struct drm_device *dev, struct iommu_domain *iommu,
-               const char **names, int cnt)
-{
-       int i, ret;
-
-       for (i = 0; i < cnt; i++) {
-               /* TODO maybe some day msm iommu won't require this hack: */
-               struct device *msm_iommu_get_ctx(const char *ctx_name);
-               struct device *ctx = msm_iommu_get_ctx(names[i]);
-               if (!ctx)
-                       continue;
-               ret = iommu_attach_device(iommu, ctx);
-               if (ret) {
-                       dev_warn(dev->dev, "could not attach iommu to %s", names[i]);
-                       return ret;
-               }
-       }
-       return 0;
-}
-
 #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
 static bool reglog = false;
 MODULE_PARM_DESC(reglog, "Enable register read/write logging");
@@ -82,6 +52,10 @@ module_param(reglog, bool, 0600);
 #define reglog 0
 #endif
 
+static char *vram;
+MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
+module_param(vram, charp, 0);
+
 void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
                const char *dbgname)
 {
@@ -161,6 +135,14 @@ static int msm_unload(struct drm_device *dev)
                mutex_unlock(&dev->struct_mutex);
        }
 
+       if (priv->vram.paddr) {
+               DEFINE_DMA_ATTRS(attrs);
+               dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+               drm_mm_takedown(&priv->vram.mm);
+               dma_free_attrs(dev->dev, priv->vram.size, NULL,
+                               priv->vram.paddr, &attrs);
+       }
+
        dev->dev_private = NULL;
 
        kfree(priv);
@@ -168,6 +150,24 @@ static int msm_unload(struct drm_device *dev)
        return 0;
 }
 
+static int get_mdp_ver(struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+       const static struct of_device_id match_types[] = { {
+               .compatible = "qcom,mdss_mdp",
+               .data   = (void *)5,
+       }, {
+               /* end node */
+       } };
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *match;
+       match = of_match_node(match_types, dev->of_node);
+       if (match)
+               return (int)match->data;
+#endif
+       return 4;
+}
+
 static int msm_load(struct drm_device *dev, unsigned long flags)
 {
        struct platform_device *pdev = dev->platformdev;
@@ -191,7 +191,53 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
 
        drm_mode_config_init(dev);
 
-       kms = mdp4_kms_init(dev);
+       /* if we have no IOMMU, then we need to use carveout allocator.
+        * Grab the entire CMA chunk carved out in early startup in
+        * mach-msm:
+        */
+       if (!iommu_present(&platform_bus_type)) {
+               DEFINE_DMA_ATTRS(attrs);
+               unsigned long size;
+               void *p;
+
+               DBG("using %s VRAM carveout", vram);
+               size = memparse(vram, NULL);
+               priv->vram.size = size;
+
+               drm_mm_init(&priv->vram.mm, 0, (size >> PAGE_SHIFT) - 1);
+
+               dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+               dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+
+               /* note that for no-kernel-mapping, the vaddr returned
+                * is bogus, but non-null if allocation succeeded:
+                */
+               p = dma_alloc_attrs(dev->dev, size,
+                               &priv->vram.paddr, 0, &attrs);
+               if (!p) {
+                       dev_err(dev->dev, "failed to allocate VRAM\n");
+                       priv->vram.paddr = 0;
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+
+               dev_info(dev->dev, "VRAM: %08x->%08x\n",
+                               (uint32_t)priv->vram.paddr,
+                               (uint32_t)(priv->vram.paddr + size));
+       }
+
+       switch (get_mdp_ver(pdev)) {
+       case 4:
+               kms = mdp4_kms_init(dev);
+               break;
+       case 5:
+               kms = mdp5_kms_init(dev);
+               break;
+       default:
+               kms = ERR_PTR(-ENODEV);
+               break;
+       }
+
        if (IS_ERR(kms)) {
                /*
                 * NOTE: once we have GPU support, having no kms should not
@@ -326,7 +372,7 @@ static void msm_lastclose(struct drm_device *dev)
        }
 }
 
-static irqreturn_t msm_irq(DRM_IRQ_ARGS)
+static irqreturn_t msm_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
        struct msm_drm_private *priv = dev->dev_private;
@@ -415,7 +461,7 @@ static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
 
 static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
 {
-       return drm_mm_dump_table(m, dev->mm_private);
+       return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
 }
 
 static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
@@ -778,12 +824,13 @@ static const struct dev_pm_ops msm_pm_ops = {
 
 static int msm_pdev_probe(struct platform_device *pdev)
 {
+       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
        return drm_platform_init(&msm_driver, pdev);
 }
 
 static int msm_pdev_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&msm_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
 
        return 0;
 }
@@ -793,12 +840,19 @@ static const struct platform_device_id msm_id[] = {
        { }
 };
 
+static const struct of_device_id dt_match[] = {
+       { .compatible = "qcom,mdss_mdp" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
 static struct platform_driver msm_platform_driver = {
        .probe      = msm_pdev_probe,
        .remove     = msm_pdev_remove,
        .driver     = {
                .owner  = THIS_MODULE,
                .name   = "msm",
+               .of_match_table = dt_match,
                .pm     = &msm_pm_ops,
        },
        .id_table   = msm_id,
index d39f0862b19ebe8db2a74fdcedbb8a52086df3a7..3d63269c5b29c51e69bc0dfe7714dddae71e4fee 100644 (file)
 #include <linux/types.h>
 #include <asm/sizes.h>
 
+
+#if defined(CONFIG_COMPILE_TEST) && !defined(CONFIG_ARCH_MSM)
+/* stubs we need for compile-test: */
+static inline struct device *msm_iommu_get_ctx(const char *ctx_name)
+{
+       return NULL;
+}
+#endif
+
 #ifndef CONFIG_OF
 #include <mach/board.h>
 #include <mach/socinfo.h>
@@ -44,6 +53,7 @@
 
 struct msm_kms;
 struct msm_gpu;
+struct msm_mmu;
 
 #define NUM_DOMAINS 2    /* one for KMS, then one per gpu core (?) */
 
@@ -76,9 +86,9 @@ struct msm_drm_private {
        /* callbacks deferred until bo is inactive: */
        struct list_head fence_cbs;
 
-       /* registered IOMMU domains: */
-       unsigned int num_iommus;
-       struct iommu_domain *iommus[NUM_DOMAINS];
+       /* registered MMUs: */
+       unsigned int num_mmus;
+       struct msm_mmu *mmus[NUM_DOMAINS];
 
        unsigned int num_planes;
        struct drm_plane *planes[8];
@@ -94,6 +104,16 @@ struct msm_drm_private {
 
        unsigned int num_connectors;
        struct drm_connector *connectors[8];
+
+       /* VRAM carveout, used when no IOMMU: */
+       struct {
+               unsigned long size;
+               dma_addr_t paddr;
+               /* NOTE: mm managed at the page level, size is in # of pages
+                * and position mm_node->start is in # of pages:
+                */
+               struct drm_mm mm;
+       } vram;
 };
 
 struct msm_format {
@@ -114,39 +134,7 @@ void __msm_fence_worker(struct work_struct *work);
                (_cb)->func = _func;                         \
        } while (0)
 
-/* As there are different display controller blocks depending on the
- * snapdragon version, the kms support is split out and the appropriate
- * implementation is loaded at runtime.  The kms module is responsible
- * for constructing the appropriate planes/crtcs/encoders/connectors.
- */
-struct msm_kms_funcs {
-       /* hw initialization: */
-       int (*hw_init)(struct msm_kms *kms);
-       /* irq handling: */
-       void (*irq_preinstall)(struct msm_kms *kms);
-       int (*irq_postinstall)(struct msm_kms *kms);
-       void (*irq_uninstall)(struct msm_kms *kms);
-       irqreturn_t (*irq)(struct msm_kms *kms);
-       int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
-       void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
-       /* misc: */
-       const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);
-       long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
-                       struct drm_encoder *encoder);
-       /* cleanup: */
-       void (*preclose)(struct msm_kms *kms, struct drm_file *file);
-       void (*destroy)(struct msm_kms *kms);
-};
-
-struct msm_kms {
-       const struct msm_kms_funcs *funcs;
-};
-
-struct msm_kms *mdp4_kms_init(struct drm_device *dev);
-
-int msm_register_iommu(struct drm_device *dev, struct iommu_domain *iommu);
-int msm_iommu_attach(struct drm_device *dev, struct iommu_domain *iommu,
-               const char **names, int cnt);
+int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
 
 int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
                struct timespec *timeout);
@@ -202,7 +190,9 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
 
 struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev);
 
-int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder);
+struct hdmi;
+struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder);
+irqreturn_t hdmi_irq(int irq, void *dev_id);
 void __init hdmi_register(void);
 void __exit hdmi_unregister(void);
 
index 0286c0eeb10ca1e967c27bf559928de58d14358f..81bafdf19ab39fc32428e6f5be692c597a6a8276 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "msm_drv.h"
+#include "msm_kms.h"
 
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
index e587d251c5900cd4532cdbff584d0683131616ed..d8d60c969ac7858bce0e6114f092a5f1aad450aa 100644 (file)
 #include "msm_drv.h"
 #include "msm_gem.h"
 #include "msm_gpu.h"
+#include "msm_mmu.h"
 
+static dma_addr_t physaddr(struct drm_gem_object *obj)
+{
+       struct msm_gem_object *msm_obj = to_msm_bo(obj);
+       struct msm_drm_private *priv = obj->dev->dev_private;
+       return (((dma_addr_t)msm_obj->vram_node->start) << PAGE_SHIFT) +
+                       priv->vram.paddr;
+}
+
+/* allocate pages from VRAM carveout, used when no IOMMU: */
+static struct page **get_pages_vram(struct drm_gem_object *obj,
+               int npages)
+{
+       struct msm_gem_object *msm_obj = to_msm_bo(obj);
+       struct msm_drm_private *priv = obj->dev->dev_private;
+       dma_addr_t paddr;
+       struct page **p;
+       int ret, i;
+
+       p = drm_malloc_ab(npages, sizeof(struct page *));
+       if (!p)
+               return ERR_PTR(-ENOMEM);
+
+       ret = drm_mm_insert_node(&priv->vram.mm, msm_obj->vram_node,
+                       npages, 0, DRM_MM_SEARCH_DEFAULT);
+       if (ret) {
+               drm_free_large(p);
+               return ERR_PTR(ret);
+       }
+
+       paddr = physaddr(obj);
+       for (i = 0; i < npages; i++) {
+               p[i] = phys_to_page(paddr);
+               paddr += PAGE_SIZE;
+       }
+
+       return p;
+}
 
 /* called with dev->struct_mutex held */
 static struct page **get_pages(struct drm_gem_object *obj)
@@ -31,9 +69,14 @@ static struct page **get_pages(struct drm_gem_object *obj)
 
        if (!msm_obj->pages) {
                struct drm_device *dev = obj->dev;
-               struct page **p = drm_gem_get_pages(obj, 0);
+               struct page **p;
                int npages = obj->size >> PAGE_SHIFT;
 
+               if (iommu_present(&platform_bus_type))
+                       p = drm_gem_get_pages(obj, 0);
+               else
+                       p = get_pages_vram(obj, npages);
+
                if (IS_ERR(p)) {
                        dev_err(dev->dev, "could not get pages: %ld\n",
                                        PTR_ERR(p));
@@ -73,7 +116,11 @@ static void put_pages(struct drm_gem_object *obj)
                sg_free_table(msm_obj->sgt);
                kfree(msm_obj->sgt);
 
-               drm_gem_put_pages(obj, msm_obj->pages, true, false);
+               if (iommu_present(&platform_bus_type))
+                       drm_gem_put_pages(obj, msm_obj->pages, true, false);
+               else
+                       drm_mm_remove_node(msm_obj->vram_node);
+
                msm_obj->pages = NULL;
        }
 }
@@ -138,7 +185,6 @@ int msm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_gem_object *obj = vma->vm_private_data;
-       struct msm_gem_object *msm_obj = to_msm_bo(obj);
        struct drm_device *dev = obj->dev;
        struct page **pages;
        unsigned long pfn;
@@ -163,7 +209,7 @@ int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        pgoff = ((unsigned long)vmf->virtual_address -
                        vma->vm_start) >> PAGE_SHIFT;
 
-       pfn = page_to_pfn(msm_obj->pages[pgoff]);
+       pfn = page_to_pfn(pages[pgoff]);
 
        VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
                        pfn, pfn << PAGE_SHIFT);
@@ -219,67 +265,6 @@ uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj)
        return offset;
 }
 
-/* helpers for dealing w/ iommu: */
-static int map_range(struct iommu_domain *domain, unsigned int iova,
-               struct sg_table *sgt, unsigned int len, int prot)
-{
-       struct scatterlist *sg;
-       unsigned int da = iova;
-       unsigned int i, j;
-       int ret;
-
-       if (!domain || !sgt)
-               return -EINVAL;
-
-       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-               u32 pa = sg_phys(sg) - sg->offset;
-               size_t bytes = sg->length + sg->offset;
-
-               VERB("map[%d]: %08x %08x(%x)", i, iova, pa, bytes);
-
-               ret = iommu_map(domain, da, pa, bytes, prot);
-               if (ret)
-                       goto fail;
-
-               da += bytes;
-       }
-
-       return 0;
-
-fail:
-       da = iova;
-
-       for_each_sg(sgt->sgl, sg, i, j) {
-               size_t bytes = sg->length + sg->offset;
-               iommu_unmap(domain, da, bytes);
-               da += bytes;
-       }
-       return ret;
-}
-
-static void unmap_range(struct iommu_domain *domain, unsigned int iova,
-               struct sg_table *sgt, unsigned int len)
-{
-       struct scatterlist *sg;
-       unsigned int da = iova;
-       int i;
-
-       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-               size_t bytes = sg->length + sg->offset;
-               size_t unmapped;
-
-               unmapped = iommu_unmap(domain, da, bytes);
-               if (unmapped < bytes)
-                       break;
-
-               VERB("unmap[%d]: %08x(%x)", i, iova, bytes);
-
-               BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
-
-               da += bytes;
-       }
-}
-
 /* should be called under struct_mutex.. although it can be called
  * from atomic context without struct_mutex to acquire an extra
  * iova ref if you know one is already held.
@@ -295,15 +280,20 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
 
        if (!msm_obj->domain[id].iova) {
                struct msm_drm_private *priv = obj->dev->dev_private;
-               uint32_t offset = (uint32_t)mmap_offset(obj);
-               struct page **pages;
-               pages = get_pages(obj);
+               struct msm_mmu *mmu = priv->mmus[id];
+               struct page **pages = get_pages(obj);
+
                if (IS_ERR(pages))
                        return PTR_ERR(pages);
-               // XXX ideally we would not map buffers writable when not needed...
-               ret = map_range(priv->iommus[id], offset, msm_obj->sgt,
-                               obj->size, IOMMU_READ | IOMMU_WRITE);
-               msm_obj->domain[id].iova = offset;
+
+               if (iommu_present(&platform_bus_type)) {
+                       uint32_t offset = (uint32_t)mmap_offset(obj);
+                       ret = mmu->funcs->map(mmu, offset, msm_obj->sgt,
+                                       obj->size, IOMMU_READ | IOMMU_WRITE);
+                       msm_obj->domain[id].iova = offset;
+               } else {
+                       msm_obj->domain[id].iova = physaddr(obj);
+               }
        }
 
        if (!ret)
@@ -514,6 +504,7 @@ void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
 void msm_gem_free_object(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
+       struct msm_drm_private *priv = obj->dev->dev_private;
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
        int id;
 
@@ -525,11 +516,10 @@ void msm_gem_free_object(struct drm_gem_object *obj)
        list_del(&msm_obj->mm_list);
 
        for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) {
-               if (msm_obj->domain[id].iova) {
-                       struct msm_drm_private *priv = obj->dev->dev_private;
+               struct msm_mmu *mmu = priv->mmus[id];
+               if (mmu && msm_obj->domain[id].iova) {
                        uint32_t offset = (uint32_t)mmap_offset(obj);
-                       unmap_range(priv->iommus[id], offset,
-                                       msm_obj->sgt, obj->size);
+                       mmu->funcs->unmap(mmu, offset, msm_obj->sgt, obj->size);
                }
        }
 
@@ -591,6 +581,7 @@ static int msm_gem_new_impl(struct drm_device *dev,
 {
        struct msm_drm_private *priv = dev->dev_private;
        struct msm_gem_object *msm_obj;
+       unsigned sz;
 
        switch (flags & MSM_BO_CACHE_MASK) {
        case MSM_BO_UNCACHED:
@@ -603,10 +594,17 @@ static int msm_gem_new_impl(struct drm_device *dev,
                return -EINVAL;
        }
 
-       msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL);
+       sz = sizeof(*msm_obj);
+       if (!iommu_present(&platform_bus_type))
+               sz += sizeof(struct drm_mm_node);
+
+       msm_obj = kzalloc(sz, GFP_KERNEL);
        if (!msm_obj)
                return -ENOMEM;
 
+       if (!iommu_present(&platform_bus_type))
+               msm_obj->vram_node = (void *)&msm_obj[1];
+
        msm_obj->flags = flags;
 
        msm_obj->resv = &msm_obj->_resv;
@@ -623,7 +621,7 @@ static int msm_gem_new_impl(struct drm_device *dev,
 struct drm_gem_object *msm_gem_new(struct drm_device *dev,
                uint32_t size, uint32_t flags)
 {
-       struct drm_gem_object *obj;
+       struct drm_gem_object *obj = NULL;
        int ret;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -634,9 +632,13 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev,
        if (ret)
                goto fail;
 
-       ret = drm_gem_object_init(dev, obj, size);
-       if (ret)
-               goto fail;
+       if (iommu_present(&platform_bus_type)) {
+               ret = drm_gem_object_init(dev, obj, size);
+               if (ret)
+                       goto fail;
+       } else {
+               drm_gem_private_object_init(dev, obj, size);
+       }
 
        return obj;
 
@@ -654,6 +656,12 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
        struct drm_gem_object *obj;
        int ret, npages;
 
+       /* if we don't have IOMMU, don't bother pretending we can import: */
+       if (!iommu_present(&platform_bus_type)) {
+               dev_err(dev->dev, "cannot import without IOMMU\n");
+               return ERR_PTR(-EINVAL);
+       }
+
        size = PAGE_ALIGN(size);
 
        ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj);
index f4f23a578d9dc76fe4b7d03498729b099471694a..3246bb46c4f2add0636bca94b1b4c726542b1178 100644 (file)
@@ -57,6 +57,11 @@ struct msm_gem_object {
        /* normally (resv == &_resv) except for imported bo's */
        struct reservation_object *resv;
        struct reservation_object _resv;
+
+       /* For physically contiguous buffers.  Used when we don't have
+        * an IOMMU.
+        */
+       struct drm_mm_node *vram_node;
 };
 #define to_msm_bo(x) container_of(x, struct msm_gem_object, base)
 
index 4583d61556f5bed5c7d9cf9d26988d1160ddb386..4ebce8be489db6cdf51f6ba88fb8f7bfd1dbd5ce 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "msm_gpu.h"
 #include "msm_gem.h"
+#include "msm_mmu.h"
 
 
 /*
 
 #ifdef CONFIG_MSM_BUS_SCALING
 #include <mach/board.h>
-#include <mach/kgsl.h>
-static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev)
+static void bs_init(struct msm_gpu *gpu)
 {
-       struct drm_device *dev = gpu->dev;
-       struct kgsl_device_platform_data *pdata;
-
-       if (!pdev) {
-               dev_err(dev->dev, "could not find dtv pdata\n");
-               return;
-       }
-
-       pdata = pdev->dev.platform_data;
-       if (pdata->bus_scale_table) {
-               gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table);
+       if (gpu->bus_scale_table) {
+               gpu->bsc = msm_bus_scale_register_client(gpu->bus_scale_table);
                DBG("bus scale client: %08x", gpu->bsc);
        }
 }
@@ -59,7 +50,7 @@ static void bs_set(struct msm_gpu *gpu, int idx)
        }
 }
 #else
-static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev) {}
+static void bs_init(struct msm_gpu *gpu) {}
 static void bs_fini(struct msm_gpu *gpu) {}
 static void bs_set(struct msm_gpu *gpu, int idx) {}
 #endif
@@ -363,6 +354,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
                const char *name, const char *ioname, const char *irqname, int ringsz)
 {
+       struct iommu_domain *iommu;
        int i, ret;
 
        gpu->dev = drm;
@@ -428,13 +420,14 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
         * and have separate page tables per context.  For now, to keep things
         * simple and to get something working, just use a single address space:
         */
-       gpu->iommu = iommu_domain_alloc(&platform_bus_type);
-       if (!gpu->iommu) {
-               dev_err(drm->dev, "failed to allocate IOMMU\n");
-               ret = -ENOMEM;
-               goto fail;
+       iommu = iommu_domain_alloc(&platform_bus_type);
+       if (iommu) {
+               dev_info(drm->dev, "%s: using IOMMU\n", name);
+               gpu->mmu = msm_iommu_new(drm, iommu);
+       } else {
+               dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
        }
-       gpu->id = msm_register_iommu(drm, gpu->iommu);
+       gpu->id = msm_register_mmu(drm, gpu->mmu);
 
        /* Create ringbuffer: */
        gpu->rb = msm_ringbuffer_new(gpu, ringsz);
@@ -452,7 +445,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                goto fail;
        }
 
-       bs_init(gpu, pdev);
+       bs_init(gpu);
 
        return 0;
 
@@ -474,6 +467,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
                msm_ringbuffer_destroy(gpu->rb);
        }
 
-       if (gpu->iommu)
-               iommu_domain_free(gpu->iommu);
+       if (gpu->mmu)
+               gpu->mmu->funcs->destroy(gpu->mmu);
 }
index 8cd829e520bb84b6bfa10d90fce8236cf9fbd3c5..458db8c64c28873f260aa59b44bbd96da7a3b18f 100644 (file)
@@ -78,14 +78,18 @@ struct msm_gpu {
        void __iomem *mmio;
        int irq;
 
-       struct iommu_domain *iommu;
+       struct msm_mmu *mmu;
        int id;
 
        /* Power Control: */
        struct regulator *gpu_reg, *gpu_cx;
        struct clk *ebi1_clk, *grp_clks[5];
        uint32_t fast_rate, slow_rate, bus_freq;
+
+#ifdef CONFIG_MSM_BUS_SCALING
+       struct msm_bus_scale_pdata *bus_scale_table;
        uint32_t bsc;
+#endif
 
        /* Hang Detction: */
 #define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
new file mode 100644 (file)
index 0000000..92b7459
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as 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 "msm_drv.h"
+#include "msm_mmu.h"
+
+struct msm_iommu {
+       struct msm_mmu base;
+       struct iommu_domain *domain;
+};
+#define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
+
+static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
+               unsigned long iova, int flags, void *arg)
+{
+       DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
+       return 0;
+}
+
+static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
+{
+       struct drm_device *dev = mmu->dev;
+       struct msm_iommu *iommu = to_msm_iommu(mmu);
+       int i, ret;
+
+       for (i = 0; i < cnt; i++) {
+               struct device *msm_iommu_get_ctx(const char *ctx_name);
+               struct device *ctx = msm_iommu_get_ctx(names[i]);
+               if (IS_ERR_OR_NULL(ctx))
+                       continue;
+               ret = iommu_attach_device(iommu->domain, ctx);
+               if (ret) {
+                       dev_warn(dev->dev, "could not attach iommu to %s", names[i]);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
+               struct sg_table *sgt, unsigned len, int prot)
+{
+       struct msm_iommu *iommu = to_msm_iommu(mmu);
+       struct iommu_domain *domain = iommu->domain;
+       struct scatterlist *sg;
+       unsigned int da = iova;
+       unsigned int i, j;
+       int ret;
+
+       if (!domain || !sgt)
+               return -EINVAL;
+
+       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+               u32 pa = sg_phys(sg) - sg->offset;
+               size_t bytes = sg->length + sg->offset;
+
+               VERB("map[%d]: %08x %08x(%x)", i, iova, pa, bytes);
+
+               ret = iommu_map(domain, da, pa, bytes, prot);
+               if (ret)
+                       goto fail;
+
+               da += bytes;
+       }
+
+       return 0;
+
+fail:
+       da = iova;
+
+       for_each_sg(sgt->sgl, sg, i, j) {
+               size_t bytes = sg->length + sg->offset;
+               iommu_unmap(domain, da, bytes);
+               da += bytes;
+       }
+       return ret;
+}
+
+static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova,
+               struct sg_table *sgt, unsigned len)
+{
+       struct msm_iommu *iommu = to_msm_iommu(mmu);
+       struct iommu_domain *domain = iommu->domain;
+       struct scatterlist *sg;
+       unsigned int da = iova;
+       int i;
+
+       for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+               size_t bytes = sg->length + sg->offset;
+               size_t unmapped;
+
+               unmapped = iommu_unmap(domain, da, bytes);
+               if (unmapped < bytes)
+                       return unmapped;
+
+               VERB("unmap[%d]: %08x(%x)", i, iova, bytes);
+
+               BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
+
+               da += bytes;
+       }
+
+       return 0;
+}
+
+static void msm_iommu_destroy(struct msm_mmu *mmu)
+{
+       struct msm_iommu *iommu = to_msm_iommu(mmu);
+       iommu_domain_free(iommu->domain);
+       kfree(iommu);
+}
+
+static const struct msm_mmu_funcs funcs = {
+               .attach = msm_iommu_attach,
+               .map = msm_iommu_map,
+               .unmap = msm_iommu_unmap,
+               .destroy = msm_iommu_destroy,
+};
+
+struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain)
+{
+       struct msm_iommu *iommu;
+
+       iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+       if (!iommu)
+               return ERR_PTR(-ENOMEM);
+
+       iommu->domain = domain;
+       msm_mmu_init(&iommu->base, dev, &funcs);
+       iommu_set_fault_handler(domain, msm_fault_handler, dev);
+
+       return &iommu->base;
+}
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
new file mode 100644 (file)
index 0000000..0643774
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MSM_KMS_H__
+#define __MSM_KMS_H__
+
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+#include "msm_drv.h"
+
+/* As there are different display controller blocks depending on the
+ * snapdragon version, the kms support is split out and the appropriate
+ * implementation is loaded at runtime.  The kms module is responsible
+ * for constructing the appropriate planes/crtcs/encoders/connectors.
+ */
+struct msm_kms_funcs {
+       /* hw initialization: */
+       int (*hw_init)(struct msm_kms *kms);
+       /* irq handling: */
+       void (*irq_preinstall)(struct msm_kms *kms);
+       int (*irq_postinstall)(struct msm_kms *kms);
+       void (*irq_uninstall)(struct msm_kms *kms);
+       irqreturn_t (*irq)(struct msm_kms *kms);
+       int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
+       void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
+       /* misc: */
+       const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);
+       long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
+                       struct drm_encoder *encoder);
+       /* cleanup: */
+       void (*preclose)(struct msm_kms *kms, struct drm_file *file);
+       void (*destroy)(struct msm_kms *kms);
+};
+
+struct msm_kms {
+       const struct msm_kms_funcs *funcs;
+
+       /* irq handling: */
+       bool in_irq;
+       struct list_head irq_list;    /* list of mdp4_irq */
+       uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+};
+
+static inline void msm_kms_init(struct msm_kms *kms,
+               const struct msm_kms_funcs *funcs)
+{
+       kms->funcs = funcs;
+}
+
+struct msm_kms *mdp4_kms_init(struct drm_device *dev);
+struct msm_kms *mdp5_kms_init(struct drm_device *dev);
+
+#endif /* __MSM_KMS_H__ */
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
new file mode 100644 (file)
index 0000000..0303244
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MSM_MMU_H__
+#define __MSM_MMU_H__
+
+#include <linux/iommu.h>
+
+struct msm_mmu_funcs {
+       int (*attach)(struct msm_mmu *mmu, const char **names, int cnt);
+       int (*map)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
+                       unsigned len, int prot);
+       int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
+                       unsigned len);
+       void (*destroy)(struct msm_mmu *mmu);
+};
+
+struct msm_mmu {
+       const struct msm_mmu_funcs *funcs;
+       struct drm_device *dev;
+};
+
+static inline void msm_mmu_init(struct msm_mmu *mmu, struct drm_device *dev,
+               const struct msm_mmu_funcs *funcs)
+{
+       mmu->dev = dev;
+       mmu->funcs = funcs;
+}
+
+struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain);
+struct msm_mmu *msm_gpummu_new(struct drm_device *dev, struct msm_gpu *gpu);
+
+#endif /* __MSM_MMU_H__ */
index b3fa1ba191b7115be412894936c3633bf9221188..e88145ba1bf515429a3b85753bde5df7d28bde70 100644 (file)
@@ -41,6 +41,7 @@ nouveau-y += core/subdev/bios/init.o
 nouveau-y += core/subdev/bios/mxm.o
 nouveau-y += core/subdev/bios/perf.o
 nouveau-y += core/subdev/bios/pll.o
+nouveau-y += core/subdev/bios/ramcfg.o
 nouveau-y += core/subdev/bios/rammap.o
 nouveau-y += core/subdev/bios/timing.o
 nouveau-y += core/subdev/bios/therm.o
@@ -71,7 +72,10 @@ nouveau-y += core/subdev/devinit/nv10.o
 nouveau-y += core/subdev/devinit/nv1a.o
 nouveau-y += core/subdev/devinit/nv20.o
 nouveau-y += core/subdev/devinit/nv50.o
+nouveau-y += core/subdev/devinit/nv84.o
+nouveau-y += core/subdev/devinit/nv98.o
 nouveau-y += core/subdev/devinit/nva3.o
+nouveau-y += core/subdev/devinit/nvaf.o
 nouveau-y += core/subdev/devinit/nvc0.o
 nouveau-y += core/subdev/fb/base.o
 nouveau-y += core/subdev/fb/nv04.o
@@ -232,6 +236,7 @@ nouveau-y += core/engine/fifo/nv50.o
 nouveau-y += core/engine/fifo/nv84.o
 nouveau-y += core/engine/fifo/nvc0.o
 nouveau-y += core/engine/fifo/nve0.o
+nouveau-y += core/engine/fifo/nv108.o
 nouveau-y += core/engine/graph/ctxnv40.o
 nouveau-y += core/engine/graph/ctxnv50.o
 nouveau-y += core/engine/graph/ctxnvc0.o
@@ -242,6 +247,7 @@ nouveau-y += core/engine/graph/ctxnvd7.o
 nouveau-y += core/engine/graph/ctxnvd9.o
 nouveau-y += core/engine/graph/ctxnve4.o
 nouveau-y += core/engine/graph/ctxnvf0.o
+nouveau-y += core/engine/graph/ctxnv108.o
 nouveau-y += core/engine/graph/nv04.o
 nouveau-y += core/engine/graph/nv10.o
 nouveau-y += core/engine/graph/nv20.o
@@ -260,6 +266,7 @@ nouveau-y += core/engine/graph/nvd7.o
 nouveau-y += core/engine/graph/nvd9.o
 nouveau-y += core/engine/graph/nve4.o
 nouveau-y += core/engine/graph/nvf0.o
+nouveau-y += core/engine/graph/nv108.o
 nouveau-y += core/engine/mpeg/nv31.o
 nouveau-y += core/engine/mpeg/nv40.o
 nouveau-y += core/engine/mpeg/nv44.o
index c8bed4a2683339072786a0b4d146b06c9594cc5b..1f6954ae9dd36e51141a9b810d91e49f1ddad2b2 100644 (file)
@@ -42,11 +42,24 @@ nouveau_engine_create_(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       if ( parent &&
-           !nouveau_boolopt(nv_device(parent)->cfgopt, iname, enable)) {
-               if (!enable)
-                       nv_warn(engine, "disabled, %s=1 to enable\n", iname);
-               return -ENODEV;
+       if (parent) {
+               struct nouveau_device *device = nv_device(parent);
+               int engidx = nv_engidx(nv_object(engine));
+
+               if (device->disable_mask & (1ULL << engidx)) {
+                       if (!nouveau_boolopt(device->cfgopt, iname, false)) {
+                               nv_debug(engine, "engine disabled by hw/fw\n");
+                               return -ENODEV;
+                       }
+
+                       nv_warn(engine, "ignoring hw/fw engine disable\n");
+               }
+
+               if (!nouveau_boolopt(device->cfgopt, iname, enable)) {
+                       if (!enable)
+                               nv_warn(engine, "disabled, %s=1 to enable\n", iname);
+                       return -ENODEV;
+               }
        }
 
        INIT_LIST_HEAD(&engine->contexts);
index 48f06378d3f9d5f9e09e03291a11d6e26527f674..2ea5568b6cf59be811fa6777612eca8b8180736b 100644 (file)
@@ -104,11 +104,8 @@ nouveau_subdev_create_(struct nouveau_object *parent,
 
        if (parent) {
                struct nouveau_device *device = nv_device(parent);
-               int subidx = nv_hclass(subdev) & 0xff;
-
                subdev->debug = nouveau_dbgopt(device->dbgopt, subname);
                subdev->mmio  = nv_subdev(device)->mmio;
-               device->subdev[subidx] = *pobject;
        }
 
        return 0;
index 993df09ad64386e51ab7316e1dbc57de5cba5409..ac3291f781f6e4c204506e02d39d8ca521cf8917 100644 (file)
@@ -105,9 +105,6 @@ nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_copy_priv *priv;
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000100)
-               return -ENODEV;
-
        ret = nouveau_falcon_create(parent, engine, oclass, 0x104000, true,
                                    "PCE0", "copy0", &priv);
        *pobject = nv_object(priv);
@@ -133,9 +130,6 @@ nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_copy_priv *priv;
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000200)
-               return -ENODEV;
-
        ret = nouveau_falcon_create(parent, engine, oclass, 0x105000, true,
                                    "PCE1", "copy1", &priv);
        *pobject = nv_object(priv);
index 30f1ef1edcc59db83deb0e12a41f6d1f399e23c6..748a61eb3c6f25fe4c08bed0a374b2148852e0f5 100644 (file)
@@ -88,9 +88,6 @@ nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nve0_copy_priv *priv;
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000100)
-               return -ENODEV;
-
        ret = nouveau_engine_create(parent, engine, oclass, true,
                                    "PCE0", "copy0", &priv);
        *pobject = nv_object(priv);
@@ -112,9 +109,6 @@ nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nve0_copy_priv *priv;
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000200)
-               return -ENODEV;
-
        ret = nouveau_engine_create(parent, engine, oclass, true,
                                    "PCE1", "copy1", &priv);
        *pobject = nv_object(priv);
index 9135b25a29d09a4e82e57e1c9a1a27608eee6a99..dd01c6c435d6e2e01ecb92ccbd57cf09e7346660 100644 (file)
@@ -268,6 +268,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
                if (ret)
                        return ret;
 
+               device->subdev[i] = devobj->subdev[i];
+
                /* note: can't init *any* subdevs until devinit has been run
                 * due to not knowing exactly what the vbios init tables will
                 * mess with.  devinit also can't be run until all of its
index dbd2dde7b7e7649d2873c513d69a263b59329b77..32113b08c4d5fb16e401e871ec65080d61a63e7c 100644 (file)
@@ -49,12 +49,12 @@ nv04_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv04_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
@@ -67,12 +67,12 @@ nv04_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv05_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass;
index 6e03dd6abeea51da34fe9e1046e50075fc481070..744f15d7e1315a6a3b9406f364d0a8bf78231cd5 100644 (file)
@@ -51,12 +51,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass;
@@ -68,12 +68,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -87,12 +87,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -106,12 +106,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -125,12 +125,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass;
@@ -144,12 +144,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -163,12 +163,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -182,12 +182,12 @@ nv10_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
index dcde53b9f07f7cd77f2886b8c8b927054691f289..27ba61fb271045c1efa9acd2982c48ce7b60f278 100644 (file)
@@ -52,12 +52,12 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv20_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -71,12 +71,12 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -90,12 +90,12 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -109,12 +109,12 @@ nv20_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
index 7b8662ef4f59193a91246ad074c8e87d84bb9019..fd47ace67543cd15f6be3c6b6799aefe497e4dcf 100644 (file)
@@ -52,12 +52,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -71,12 +71,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv35_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -90,12 +90,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -110,12 +110,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv36_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
@@ -130,12 +130,12 @@ nv30_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass;
index c8c41e93695ee3d0f83da140f0615cb737c14472..1b653dd74a7046ceaae41bca181f3097827dcccd 100644 (file)
@@ -57,12 +57,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -80,12 +80,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -103,12 +103,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -126,12 +126,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -149,12 +149,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -172,12 +172,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv47_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -195,12 +195,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -218,12 +218,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -241,12 +241,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -264,12 +264,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -287,12 +287,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -310,12 +310,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -333,12 +333,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv4e_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -356,12 +356,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -379,12 +379,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
@@ -402,12 +402,12 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass;
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
index db3fc7be856a733d07f8431a182326e3f20b4182..81d5c26643d50dcff2067abdf0f2bb7a227621ad 100644 (file)
@@ -65,12 +65,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv50_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv50_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -90,12 +90,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -118,12 +118,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -146,12 +146,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -174,12 +174,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -202,12 +202,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -230,12 +230,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -258,12 +258,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -286,12 +286,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvaa_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -314,12 +314,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvaa_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
@@ -342,12 +342,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -372,12 +372,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -401,12 +401,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
@@ -430,12 +430,12 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvaf_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvaf_fb_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass;
index 8d06eef2b9ee02f7b3d895c8d7a37bfd6e022924..b7d66b59f43d4c7cc3ea0c733f809f966c37aa3d 100644 (file)
@@ -65,14 +65,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -97,14 +97,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -129,14 +129,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -160,14 +160,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -192,14 +192,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -224,14 +224,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -255,14 +255,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass;
@@ -287,14 +287,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -318,14 +318,14 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
index 3900104976fc7bfc2ca3df441318254bdae3bf97..987edbc30a0917cc2db2a035c749f42c5818b5b9 100644 (file)
@@ -65,14 +65,14 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -98,14 +98,14 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -131,14 +131,14 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -164,14 +164,14 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
@@ -199,29 +199,27 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
-               device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
                device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
                device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass;
                device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
-               device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
                device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
                device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
                device->oclass[NVDEV_SUBDEV_PWR    ] = &nv108_pwr_oclass;
                device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
-#if 0
-               device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
+               device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
-               device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass;
-#endif
+               device->oclass[NVDEV_ENGINE_GR     ] =  nv108_graph_oclass;
                device->oclass[NVDEV_ENGINE_DISP   ] = &nvf0_disp_oclass;
-#if 0
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
+#if 0
                device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
index 378a015091d2bf22d9a2ba5e49cd095b3ac774c7..d52c0f50a1a9b0076682a01171418da974625bfb 100644 (file)
@@ -967,9 +967,6 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int heads = nv_rd32(parent, 0x022448);
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000001)
-               return -ENODEV;
-
        ret = nouveau_disp_create(parent, engine, oclass, heads,
                                  "PDISP", "display", &priv);
        *pobject = nv_object(priv);
index fb1fe6ae5e74ddbd6f3336a3d34de8eb58757b5b..20725b363d582b3485b55f5ef4692247d20adce2 100644 (file)
@@ -54,9 +54,6 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int heads = nv_rd32(parent, 0x022448);
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000001)
-               return -ENODEV;
-
        ret = nouveau_disp_create(parent, engine, oclass, heads,
                                  "PDISP", "display", &priv);
        *pobject = nv_object(priv);
index 42aa6b97dbea3c5867676f0209151a1ead3a849d..a488c36e40f9dc0d7923362dd1c09e346b37b7dd 100644 (file)
@@ -54,9 +54,6 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int heads = nv_rd32(parent, 0x022448);
        int ret;
 
-       if (nv_rd32(parent, 0x022500) & 0x00000001)
-               return -ENODEV;
-
        ret = nouveau_disp_create(parent, engine, oclass, heads,
                                  "PDISP", "display", &priv);
        *pobject = nv_object(priv);
index 5a1c68474597cbc979eb216735941714b1ce4901..8836c3cb99c3862a84ed2b946e6c3e34c47e520d 100644 (file)
@@ -138,10 +138,15 @@ nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value)
 bool
 nv_lockvgac(void *obj, bool lock)
 {
+       struct nouveau_device *dev = nv_device(obj);
+
        bool locked = !nv_rdvgac(obj, 0, 0x1f);
        u8 data = lock ? 0x99 : 0x57;
-       nv_wrvgac(obj, 0, 0x1f, data);
-       if (nv_device(obj)->chipset == 0x11) {
+       if (dev->card_type < NV_50)
+               nv_wrvgac(obj, 0, 0x1f, data);
+       else
+               nv_wrvgac(obj, 0, 0x3f, data);
+       if (dev->chipset == 0x11) {
                if (!(nv_rd32(obj, 0x001084) & 0x10000000))
                        nv_wrvgac(obj, 1, 0x1f, data);
        }
index e03fc8e4dc1dac8c8262a93b2b0b812dcae60841..5e077e4ed7f6aa23d0e8ed3fde50ad58c2fd99d7 100644 (file)
@@ -56,6 +56,16 @@ _nouveau_falcon_wr32(struct nouveau_object *object, u64 addr, u32 data)
        nv_wr32(falcon, falcon->addr + addr, data);
 }
 
+static void *
+vmemdup(const void *src, size_t len)
+{
+       void *p = vmalloc(len);
+
+       if (p)
+               memcpy(p, src, len);
+       return p;
+}
+
 int
 _nouveau_falcon_init(struct nouveau_object *object)
 {
@@ -111,7 +121,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
 
                ret = request_firmware(&fw, name, &device->pdev->dev);
                if (ret == 0) {
-                       falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+                       falcon->code.data = vmemdup(fw->data, fw->size);
                        falcon->code.size = fw->size;
                        falcon->data.data = NULL;
                        falcon->data.size = 0;
@@ -134,7 +144,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
                        return ret;
                }
 
-               falcon->data.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+               falcon->data.data = vmemdup(fw->data, fw->size);
                falcon->data.size = fw->size;
                release_firmware(fw);
                if (!falcon->data.data)
@@ -149,7 +159,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
                        return ret;
                }
 
-               falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+               falcon->code.data = vmemdup(fw->data, fw->size);
                falcon->code.size = fw->size;
                release_firmware(fw);
                if (!falcon->code.data)
@@ -235,8 +245,8 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
        if (!suspend) {
                nouveau_gpuobj_ref(NULL, &falcon->core);
                if (falcon->external) {
-                       kfree(falcon->data.data);
-                       kfree(falcon->code.data);
+                       vfree(falcon->data.data);
+                       vfree(falcon->code.data);
                        falcon->code.data = NULL;
                }
        }
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c
new file mode 100644 (file)
index 0000000..09362a5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nve0.h"
+
+struct nouveau_oclass *
+nv108_fifo_oclass = &(struct nve0_fifo_impl) {
+       .base.handle = NV_ENGINE(FIFO, 0x08),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nve0_fifo_ctor,
+               .dtor = nve0_fifo_dtor,
+               .init = nve0_fifo_init,
+               .fini = _nouveau_fifo_fini,
+       },
+       .channels = 1024,
+}.base;
index 9ac94d4e5646d2cd24579f3b47777f2e17f5e9fe..b22a33f0702dd0159ed01f79edb00b7349f6b561 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <subdev/timer.h>
 #include <subdev/bar.h>
+#include <subdev/fb.h>
 #include <subdev/vm.h>
 
 #include <engine/dmaobj.h>
index 04f412922d2d43f5a5fbce11185fc2f9f4196e7e..9a850fe19515fe2ddcd513c3497c7d87c86cba8a 100644 (file)
 
 #include <subdev/timer.h>
 #include <subdev/bar.h>
+#include <subdev/fb.h>
 #include <subdev/vm.h>
 
 #include <engine/dmaobj.h>
-#include <engine/fifo.h>
+
+#include "nve0.h"
 
 #define _(a,b) { (a), ((1ULL << (a)) | (b)) }
 static const struct {
@@ -56,8 +58,8 @@ static const struct {
 #define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)
 
 struct nve0_fifo_engn {
-       struct nouveau_gpuobj *playlist[2];
-       int cur_playlist;
+       struct nouveau_gpuobj *runlist[2];
+       int cur_runlist;
 };
 
 struct nve0_fifo_priv {
@@ -86,7 +88,7 @@ struct nve0_fifo_chan {
  ******************************************************************************/
 
 static void
-nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
+nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
 {
        struct nouveau_bar *bar = nouveau_bar(priv);
        struct nve0_fifo_engn *engn = &priv->engine[engine];
@@ -95,8 +97,8 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
        int i, p;
 
        mutex_lock(&nv_subdev(priv)->mutex);
-       cur = engn->playlist[engn->cur_playlist];
-       engn->cur_playlist = !engn->cur_playlist;
+       cur = engn->runlist[engn->cur_runlist];
+       engn->cur_runlist = !engn->cur_runlist;
 
        for (i = 0, p = 0; i < priv->base.max; i++) {
                u32 ctrl = nv_rd32(priv, 0x800004 + (i * 8)) & 0x001f0001;
@@ -111,7 +113,7 @@ nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine)
        nv_wr32(priv, 0x002270, cur->addr >> 12);
        nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
        if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
-               nv_error(priv, "playlist %d update timeout\n", engine);
+               nv_error(priv, "runlist %d update timeout\n", engine);
        mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
@@ -278,7 +280,7 @@ nve0_fifo_chan_init(struct nouveau_object *object)
        nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);
        nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
        nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
-       nve0_fifo_playlist_update(priv, chan->engine);
+       nve0_fifo_runlist_update(priv, chan->engine);
        nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
        return 0;
 }
@@ -291,7 +293,7 @@ nve0_fifo_chan_fini(struct nouveau_object *object, bool suspend)
        u32 chid = chan->base.chid;
 
        nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
-       nve0_fifo_playlist_update(priv, chan->engine);
+       nve0_fifo_runlist_update(priv, chan->engine);
        nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
 
        return nouveau_fifo_channel_fini(&chan->base, suspend);
@@ -375,54 +377,189 @@ nve0_fifo_cclass = {
  * PFIFO engine
  ******************************************************************************/
 
-static const struct nouveau_enum nve0_fifo_fault_unit[] = {
+static const struct nouveau_enum nve0_fifo_sched_reason[] = {
+       { 0x0a, "CTXSW_TIMEOUT" },
+       {}
+};
+
+static const struct nouveau_enum nve0_fifo_fault_engine[] = {
+       { 0x00, "GR", NULL, NVDEV_ENGINE_GR },
+       { 0x03, "IFB" },
+       { 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR },
+       { 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },
+       { 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO },
+       { 0x08, "PBDMA1", NULL, NVDEV_ENGINE_FIFO },
+       { 0x09, "PBDMA2", NULL, NVDEV_ENGINE_FIFO },
+       { 0x10, "MSVLD", NULL, NVDEV_ENGINE_BSP },
+       { 0x11, "MSPPP", NULL, NVDEV_ENGINE_PPP },
+       { 0x13, "PERF" },
+       { 0x14, "MSPDEC", NULL, NVDEV_ENGINE_VP },
+       { 0x15, "CE0", NULL, NVDEV_ENGINE_COPY0 },
+       { 0x16, "CE1", NULL, NVDEV_ENGINE_COPY1 },
+       { 0x17, "PMU" },
+       { 0x19, "MSENC", NULL, NVDEV_ENGINE_VENC },
+       { 0x1b, "CE2", NULL, NVDEV_ENGINE_COPY2 },
        {}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_reason[] = {
-       { 0x00, "PT_NOT_PRESENT" },
-       { 0x01, "PT_TOO_SHORT" },
-       { 0x02, "PAGE_NOT_PRESENT" },
-       { 0x03, "VM_LIMIT_EXCEEDED" },
-       { 0x04, "NO_CHANNEL" },
-       { 0x05, "PAGE_SYSTEM_ONLY" },
-       { 0x06, "PAGE_READ_ONLY" },
-       { 0x0a, "COMPRESSED_SYSRAM" },
-       { 0x0c, "INVALID_STORAGE_TYPE" },
+       { 0x00, "PDE" },
+       { 0x01, "PDE_SIZE" },
+       { 0x02, "PTE" },
+       { 0x03, "VA_LIMIT_VIOLATION" },
+       { 0x04, "UNBOUND_INST_BLOCK" },
+       { 0x05, "PRIV_VIOLATION" },
+       { 0x06, "RO_VIOLATION" },
+       { 0x07, "WO_VIOLATION" },
+       { 0x08, "PITCH_MASK_VIOLATION" },
+       { 0x09, "WORK_CREATION" },
+       { 0x0a, "UNSUPPORTED_APERTURE" },
+       { 0x0b, "COMPRESSION_FAILURE" },
+       { 0x0c, "UNSUPPORTED_KIND" },
+       { 0x0d, "REGION_VIOLATION" },
+       { 0x0e, "BOTH_PTES_VALID" },
+       { 0x0f, "INFO_TYPE_POISONED" },
        {}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_hubclient[] = {
+       { 0x00, "VIP" },
+       { 0x01, "CE0" },
+       { 0x02, "CE1" },
+       { 0x03, "DNISO" },
+       { 0x04, "FE" },
+       { 0x05, "FECS" },
+       { 0x06, "HOST" },
+       { 0x07, "HOST_CPU" },
+       { 0x08, "HOST_CPU_NB" },
+       { 0x09, "ISO" },
+       { 0x0a, "MMU" },
+       { 0x0b, "MSPDEC" },
+       { 0x0c, "MSPPP" },
+       { 0x0d, "MSVLD" },
+       { 0x0e, "NISO" },
+       { 0x0f, "P2P" },
+       { 0x10, "PD" },
+       { 0x11, "PERF" },
+       { 0x12, "PMU" },
+       { 0x13, "RASTERTWOD" },
+       { 0x14, "SCC" },
+       { 0x15, "SCC_NB" },
+       { 0x16, "SEC" },
+       { 0x17, "SSYNC" },
+       { 0x18, "GR_COPY" },
+       { 0x19, "CE2" },
+       { 0x1a, "XV" },
+       { 0x1b, "MMU_NB" },
+       { 0x1c, "MSENC" },
+       { 0x1d, "DFALCON" },
+       { 0x1e, "SKED" },
+       { 0x1f, "AFALCON" },
        {}
 };
 
 static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = {
+       { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
+       { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
+       { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
+       { 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" },
+       { 0x0c, "RAST" },
+       { 0x0d, "GCC" },
+       { 0x0e, "GPCCS" },
+       { 0x0f, "PROP_0" },
+       { 0x10, "PROP_1" },
+       { 0x11, "PROP_2" },
+       { 0x12, "PROP_3" },
+       { 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" },
+       { 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" },
+       { 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" },
+       { 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" },
+       { 0x1f, "GPM" },
+       { 0x20, "LTP_UTLB_0" },
+       { 0x21, "LTP_UTLB_1" },
+       { 0x22, "LTP_UTLB_2" },
+       { 0x23, "LTP_UTLB_3" },
+       { 0x24, "GPC_RGG_UTLB" },
        {}
 };
 
-static const struct nouveau_bitfield nve0_fifo_subfifo_intr[] = {
-       { 0x00200000, "ILLEGAL_MTHD" },
-       { 0x00800000, "EMPTY_SUBC" },
+static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = {
+       { 0x00000001, "MEMREQ" },
+       { 0x00000002, "MEMACK_TIMEOUT" },
+       { 0x00000004, "MEMACK_EXTRA" },
+       { 0x00000008, "MEMDAT_TIMEOUT" },
+       { 0x00000010, "MEMDAT_EXTRA" },
+       { 0x00000020, "MEMFLUSH" },
+       { 0x00000040, "MEMOP" },
+       { 0x00000080, "LBCONNECT" },
+       { 0x00000100, "LBREQ" },
+       { 0x00000200, "LBACK_TIMEOUT" },
+       { 0x00000400, "LBACK_EXTRA" },
+       { 0x00000800, "LBDAT_TIMEOUT" },
+       { 0x00001000, "LBDAT_EXTRA" },
+       { 0x00002000, "GPFIFO" },
+       { 0x00004000, "GPPTR" },
+       { 0x00008000, "GPENTRY" },
+       { 0x00010000, "GPCRC" },
+       { 0x00020000, "PBPTR" },
+       { 0x00040000, "PBENTRY" },
+       { 0x00080000, "PBCRC" },
+       { 0x00100000, "XBARCONNECT" },
+       { 0x00200000, "METHOD" },
+       { 0x00400000, "METHODCRC" },
+       { 0x00800000, "DEVICE" },
+       { 0x02000000, "SEMAPHORE" },
+       { 0x04000000, "ACQUIRE" },
+       { 0x08000000, "PRI" },
+       { 0x20000000, "NO_CTXSW_SEG" },
+       { 0x40000000, "PBSEG" },
+       { 0x80000000, "SIGNATURE" },
        {}
 };
 
 static void
-nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit)
+nve0_fifo_intr_sched(struct nve0_fifo_priv *priv)
+{
+       u32 intr = nv_rd32(priv, 0x00254c);
+       u32 code = intr & 0x000000ff;
+       nv_error(priv, "SCHED_ERROR [");
+       nouveau_enum_print(nve0_fifo_sched_reason, code);
+       pr_cont("]\n");
+}
+
+static void
+nve0_fifo_intr_chsw(struct nve0_fifo_priv *priv)
+{
+       u32 stat = nv_rd32(priv, 0x00256c);
+       nv_error(priv, "CHSW_ERROR 0x%08x\n", stat);
+       nv_wr32(priv, 0x00256c, stat);
+}
+
+static void
+nve0_fifo_intr_dropped_fault(struct nve0_fifo_priv *priv)
+{
+       u32 stat = nv_rd32(priv, 0x00259c);
+       nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat);
+}
+
+static void
+nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
 {
        u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10));
        u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10));
        u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10));
        u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10));
        u32 client = (stat & 0x00001f00) >> 8;
-       const struct nouveau_enum *en;
-       struct nouveau_engine *engine;
+       struct nouveau_engine *engine = NULL;
        struct nouveau_object *engctx = NULL;
+       const struct nouveau_enum *en;
+       const char *name = "unknown";
 
        nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ?
                       "write" : "read", (u64)vahi << 32 | valo);
        nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f);
        pr_cont("] from ");
-       en = nouveau_enum_print(nve0_fifo_fault_unit, unit);
+       en = nouveau_enum_print(nve0_fifo_fault_engine, unit);
        if (stat & 0x00000040) {
                pr_cont("/");
                nouveau_enum_print(nve0_fifo_fault_hubclient, client);
@@ -432,14 +569,22 @@ nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit)
        }
 
        if (en && en->data2) {
-               engine = nouveau_engine(priv, en->data2);
-               if (engine)
-                       engctx = nouveau_engctx_get(engine, inst);
-
+               if (en->data2 == NVDEV_SUBDEV_BAR) {
+                       nv_mask(priv, 0x001704, 0x00000000, 0x00000000);
+                       name = "BAR1";
+               } else
+               if (en->data2 == NVDEV_SUBDEV_INSTMEM) {
+                       nv_mask(priv, 0x001714, 0x00000000, 0x00000000);
+                       name = "BAR3";
+               } else {
+                       engine = nouveau_engine(priv, en->data2);
+                       if (engine) {
+                               engctx = nouveau_engctx_get(engine, inst);
+                               name   = nouveau_client_name(engctx);
+                       }
+               }
        }
-
-       pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12,
-                       nouveau_client_name(engctx));
+       pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, name);
 
        nouveau_engctx_put(engctx);
 }
@@ -471,7 +616,7 @@ out:
 }
 
 static void
-nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)
+nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit)
 {
        u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));
        u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000));
@@ -487,11 +632,11 @@ nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)
        }
 
        if (show) {
-               nv_error(priv, "SUBFIFO%d:", unit);
-               nouveau_bitfield_print(nve0_fifo_subfifo_intr, show);
+               nv_error(priv, "PBDMA%d:", unit);
+               nouveau_bitfield_print(nve0_fifo_pbdma_intr, show);
                pr_cont("\n");
                nv_error(priv,
-                        "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
+                        "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
                         unit, chid,
                         nouveau_client_name_for_fifo_chid(&priv->base, chid),
                         subc, mthd, data);
@@ -508,19 +653,56 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
        u32 mask = nv_rd32(priv, 0x002140);
        u32 stat = nv_rd32(priv, 0x002100) & mask;
 
+       if (stat & 0x00000001) {
+               u32 stat = nv_rd32(priv, 0x00252c);
+               nv_error(priv, "BIND_ERROR 0x%08x\n", stat);
+               nv_wr32(priv, 0x002100, 0x00000001);
+               stat &= ~0x00000001;
+       }
+
+       if (stat & 0x00000010) {
+               nv_error(priv, "PIO_ERROR\n");
+               nv_wr32(priv, 0x002100, 0x00000010);
+               stat &= ~0x00000010;
+       }
+
        if (stat & 0x00000100) {
-               nv_warn(priv, "unknown status 0x00000100\n");
+               nve0_fifo_intr_sched(priv);
                nv_wr32(priv, 0x002100, 0x00000100);
                stat &= ~0x00000100;
        }
 
+       if (stat & 0x00010000) {
+               nve0_fifo_intr_chsw(priv);
+               nv_wr32(priv, 0x002100, 0x00010000);
+               stat &= ~0x00010000;
+       }
+
+       if (stat & 0x00800000) {
+               nv_error(priv, "FB_FLUSH_TIMEOUT\n");
+               nv_wr32(priv, 0x002100, 0x00800000);
+               stat &= ~0x00800000;
+       }
+
+       if (stat & 0x01000000) {
+               nv_error(priv, "LB_ERROR\n");
+               nv_wr32(priv, 0x002100, 0x01000000);
+               stat &= ~0x01000000;
+       }
+
+       if (stat & 0x08000000) {
+               nve0_fifo_intr_dropped_fault(priv);
+               nv_wr32(priv, 0x002100, 0x08000000);
+               stat &= ~0x08000000;
+       }
+
        if (stat & 0x10000000) {
                u32 units = nv_rd32(priv, 0x00259c);
                u32 u = units;
 
                while (u) {
                        int i = ffs(u) - 1;
-                       nve0_fifo_isr_vm_fault(priv, i);
+                       nve0_fifo_intr_fault(priv, i);
                        u &= ~(1 << i);
                }
 
@@ -529,22 +711,28 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
        }
 
        if (stat & 0x20000000) {
-               u32 units = nv_rd32(priv, 0x0025a0);
-               u32 u = units;
+               u32 mask = nv_rd32(priv, 0x0025a0);
+               u32 temp = mask;
 
-               while (u) {
-                       int i = ffs(u) - 1;
-                       nve0_fifo_isr_subfifo_intr(priv, i);
-                       u &= ~(1 << i);
+               while (temp) {
+                       u32 unit = ffs(temp) - 1;
+                       nve0_fifo_intr_pbdma(priv, unit);
+                       temp &= ~(1 << unit);
                }
 
-               nv_wr32(priv, 0x0025a0, units);
+               nv_wr32(priv, 0x0025a0, mask);
                stat &= ~0x20000000;
        }
 
        if (stat & 0x40000000) {
-               nv_warn(priv, "unknown status 0x40000000\n");
-               nv_mask(priv, 0x002a00, 0x00000000, 0x00000000);
+               u32 mask = nv_mask(priv, 0x002a00, 0x00000000, 0x00000000);
+
+               while (mask) {
+                       u32 engn = ffs(mask) - 1;
+                       /* runlist event, not currently used */
+                       mask &= ~(1 << engn);
+               }
+
                stat &= ~0x40000000;
        }
 
@@ -575,53 +763,52 @@ nve0_fifo_uevent_disable(struct nouveau_event *event, int index)
        nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
 }
 
-static int
-nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-              struct nouveau_oclass *oclass, void *data, u32 size,
-              struct nouveau_object **pobject)
+int
+nve0_fifo_fini(struct nouveau_object *object, bool suspend)
 {
-       struct nve0_fifo_priv *priv;
-       int ret, i;
+       struct nve0_fifo_priv *priv = (void *)object;
+       int ret;
 
-       ret = nouveau_fifo_create(parent, engine, oclass, 0, 4095, &priv);
-       *pobject = nv_object(priv);
+       ret = nouveau_fifo_fini(&priv->base, suspend);
        if (ret)
                return ret;
 
-       for (i = 0; i < FIFO_ENGINE_NR; i++) {
-               ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
-                                        0, &priv->engine[i].playlist[0]);
-               if (ret)
-                       return ret;
+       /* allow mmu fault interrupts, even when we're not using fifo */
+       nv_mask(priv, 0x002140, 0x10000000, 0x10000000);
+       return 0;
+}
 
-               ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
-                                        0, &priv->engine[i].playlist[1]);
-               if (ret)
-                       return ret;
-       }
+int
+nve0_fifo_init(struct nouveau_object *object)
+{
+       struct nve0_fifo_priv *priv = (void *)object;
+       int ret, i;
 
-       ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000,
-                                NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
+       ret = nouveau_fifo_init(&priv->base);
        if (ret)
                return ret;
 
-       ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW,
-                               &priv->user.bar);
-       if (ret)
-               return ret;
+       /* enable all available PBDMA units */
+       nv_wr32(priv, 0x000204, 0xffffffff);
+       priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204));
+       nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr);
 
-       priv->base.uevent->enable = nve0_fifo_uevent_enable;
-       priv->base.uevent->disable = nve0_fifo_uevent_disable;
-       priv->base.uevent->priv = priv;
+       /* PBDMA[n] */
+       for (i = 0; i < priv->spoon_nr; i++) {
+               nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
+               nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
+               nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
+       }
 
-       nv_subdev(priv)->unit = 0x00000100;
-       nv_subdev(priv)->intr = nve0_fifo_intr;
-       nv_engine(priv)->cclass = &nve0_fifo_cclass;
-       nv_engine(priv)->sclass = nve0_fifo_sclass;
+       nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
+
+       nv_wr32(priv, 0x002a00, 0xffffffff);
+       nv_wr32(priv, 0x002100, 0xffffffff);
+       nv_wr32(priv, 0x002140, 0x3fffffff);
        return 0;
 }
 
-static void
+void
 nve0_fifo_dtor(struct nouveau_object *object)
 {
        struct nve0_fifo_priv *priv = (void *)object;
@@ -631,50 +818,69 @@ nve0_fifo_dtor(struct nouveau_object *object)
        nouveau_gpuobj_ref(NULL, &priv->user.mem);
 
        for (i = 0; i < FIFO_ENGINE_NR; i++) {
-               nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[1]);
-               nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]);
+               nouveau_gpuobj_ref(NULL, &priv->engine[i].runlist[1]);
+               nouveau_gpuobj_ref(NULL, &priv->engine[i].runlist[0]);
        }
 
        nouveau_fifo_destroy(&priv->base);
 }
 
-static int
-nve0_fifo_init(struct nouveau_object *object)
+int
+nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+              struct nouveau_oclass *oclass, void *data, u32 size,
+              struct nouveau_object **pobject)
 {
-       struct nve0_fifo_priv *priv = (void *)object;
+       struct nve0_fifo_impl *impl = (void *)oclass;
+       struct nve0_fifo_priv *priv;
        int ret, i;
 
-       ret = nouveau_fifo_init(&priv->base);
+       ret = nouveau_fifo_create(parent, engine, oclass, 0,
+                                 impl->channels - 1, &priv);
+       *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       /* enable all available PSUBFIFOs */
-       nv_wr32(priv, 0x000204, 0xffffffff);
-       priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204));
-       nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr);
+       for (i = 0; i < FIFO_ENGINE_NR; i++) {
+               ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
+                                        0, &priv->engine[i].runlist[0]);
+               if (ret)
+                       return ret;
 
-       /* PSUBFIFO[n] */
-       for (i = 0; i < priv->spoon_nr; i++) {
-               nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
-               nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
-               nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
+               ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000,
+                                        0, &priv->engine[i].runlist[1]);
+               if (ret)
+                       return ret;
        }
 
-       nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12);
+       ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000,
+                                NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem);
+       if (ret)
+               return ret;
 
-       nv_wr32(priv, 0x002a00, 0xffffffff);
-       nv_wr32(priv, 0x002100, 0xffffffff);
-       nv_wr32(priv, 0x002140, 0x3fffffff);
+       ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW,
+                               &priv->user.bar);
+       if (ret)
+               return ret;
+
+       priv->base.uevent->enable = nve0_fifo_uevent_enable;
+       priv->base.uevent->disable = nve0_fifo_uevent_disable;
+       priv->base.uevent->priv = priv;
+
+       nv_subdev(priv)->unit = 0x00000100;
+       nv_subdev(priv)->intr = nve0_fifo_intr;
+       nv_engine(priv)->cclass = &nve0_fifo_cclass;
+       nv_engine(priv)->sclass = nve0_fifo_sclass;
        return 0;
 }
 
 struct nouveau_oclass *
-nve0_fifo_oclass = &(struct nouveau_oclass) {
-       .handle = NV_ENGINE(FIFO, 0xe0),
-       .ofuncs = &(struct nouveau_ofuncs) {
+nve0_fifo_oclass = &(struct nve0_fifo_impl) {
+       .base.handle = NV_ENGINE(FIFO, 0xe0),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nve0_fifo_ctor,
                .dtor = nve0_fifo_dtor,
                .init = nve0_fifo_init,
-               .fini = _nouveau_fifo_fini,
+               .fini = nve0_fifo_fini,
        },
-};
+       .channels = 4096,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h
new file mode 100644 (file)
index 0000000..014344e
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __NVKM_FIFO_NVE0_H__
+#define __NVKM_FIFO_NVE0_H__
+
+#include <engine/fifo.h>
+
+int  nve0_fifo_ctor(struct nouveau_object *, struct nouveau_object *,
+                   struct nouveau_oclass *, void *, u32,
+                   struct nouveau_object **);
+void nve0_fifo_dtor(struct nouveau_object *);
+int  nve0_fifo_init(struct nouveau_object *);
+
+struct nve0_fifo_impl {
+       struct nouveau_oclass base;
+       u32 channels;
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
new file mode 100644 (file)
index 0000000..a86bd33
--- /dev/null
@@ -0,0 +1,1408 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nvc0.h"
+
+static struct nvc0_graph_init
+nv108_grctx_init_icmd[] = {
+       { 0x001000,   1, 0x01, 0x00000004 },
+       { 0x000039,   3, 0x01, 0x00000000 },
+       { 0x0000a9,   1, 0x01, 0x0000ffff },
+       { 0x000038,   1, 0x01, 0x0fac6881 },
+       { 0x00003d,   1, 0x01, 0x00000001 },
+       { 0x0000e8,   8, 0x01, 0x00000400 },
+       { 0x000078,   8, 0x01, 0x00000300 },
+       { 0x000050,   1, 0x01, 0x00000011 },
+       { 0x000058,   8, 0x01, 0x00000008 },
+       { 0x000208,   8, 0x01, 0x00000001 },
+       { 0x000081,   1, 0x01, 0x00000001 },
+       { 0x000085,   1, 0x01, 0x00000004 },
+       { 0x000088,   1, 0x01, 0x00000400 },
+       { 0x000090,   1, 0x01, 0x00000300 },
+       { 0x000098,   1, 0x01, 0x00001001 },
+       { 0x0000e3,   1, 0x01, 0x00000001 },
+       { 0x0000da,   1, 0x01, 0x00000001 },
+       { 0x0000f8,   1, 0x01, 0x00000003 },
+       { 0x0000fa,   1, 0x01, 0x00000001 },
+       { 0x00009f,   4, 0x01, 0x0000ffff },
+       { 0x0000b1,   1, 0x01, 0x00000001 },
+       { 0x0000ad,   1, 0x01, 0x0000013e },
+       { 0x0000e1,   1, 0x01, 0x00000010 },
+       { 0x000290,  16, 0x01, 0x00000000 },
+       { 0x0003b0,  16, 0x01, 0x00000000 },
+       { 0x0002a0,  16, 0x01, 0x00000000 },
+       { 0x000420,  16, 0x01, 0x00000000 },
+       { 0x0002b0,  16, 0x01, 0x00000000 },
+       { 0x000430,  16, 0x01, 0x00000000 },
+       { 0x0002c0,  16, 0x01, 0x00000000 },
+       { 0x0004d0,  16, 0x01, 0x00000000 },
+       { 0x000720,  16, 0x01, 0x00000000 },
+       { 0x0008c0,  16, 0x01, 0x00000000 },
+       { 0x000890,  16, 0x01, 0x00000000 },
+       { 0x0008e0,  16, 0x01, 0x00000000 },
+       { 0x0008a0,  16, 0x01, 0x00000000 },
+       { 0x0008f0,  16, 0x01, 0x00000000 },
+       { 0x00094c,   1, 0x01, 0x000000ff },
+       { 0x00094d,   1, 0x01, 0xffffffff },
+       { 0x00094e,   1, 0x01, 0x00000002 },
+       { 0x0002ec,   1, 0x01, 0x00000001 },
+       { 0x0002f2,   2, 0x01, 0x00000001 },
+       { 0x0002f5,   1, 0x01, 0x00000001 },
+       { 0x0002f7,   1, 0x01, 0x00000001 },
+       { 0x000303,   1, 0x01, 0x00000001 },
+       { 0x0002e6,   1, 0x01, 0x00000001 },
+       { 0x000466,   1, 0x01, 0x00000052 },
+       { 0x000301,   1, 0x01, 0x3f800000 },
+       { 0x000304,   1, 0x01, 0x30201000 },
+       { 0x000305,   1, 0x01, 0x70605040 },
+       { 0x000306,   1, 0x01, 0xb8a89888 },
+       { 0x000307,   1, 0x01, 0xf8e8d8c8 },
+       { 0x00030a,   1, 0x01, 0x00ffff00 },
+       { 0x00030b,   1, 0x01, 0x0000001a },
+       { 0x00030c,   1, 0x01, 0x00000001 },
+       { 0x000318,   1, 0x01, 0x00000001 },
+       { 0x000340,   1, 0x01, 0x00000000 },
+       { 0x000375,   1, 0x01, 0x00000001 },
+       { 0x00037d,   1, 0x01, 0x00000006 },
+       { 0x0003a0,   1, 0x01, 0x00000002 },
+       { 0x0003aa,   1, 0x01, 0x00000001 },
+       { 0x0003a9,   1, 0x01, 0x00000001 },
+       { 0x000380,   1, 0x01, 0x00000001 },
+       { 0x000383,   1, 0x01, 0x00000011 },
+       { 0x000360,   1, 0x01, 0x00000040 },
+       { 0x000366,   2, 0x01, 0x00000000 },
+       { 0x000368,   1, 0x01, 0x00000fff },
+       { 0x000370,   2, 0x01, 0x00000000 },
+       { 0x000372,   1, 0x01, 0x000fffff },
+       { 0x00037a,   1, 0x01, 0x00000012 },
+       { 0x000619,   1, 0x01, 0x00000003 },
+       { 0x000811,   1, 0x01, 0x00000003 },
+       { 0x000812,   1, 0x01, 0x00000004 },
+       { 0x000813,   1, 0x01, 0x00000006 },
+       { 0x000814,   1, 0x01, 0x00000008 },
+       { 0x000815,   1, 0x01, 0x0000000b },
+       { 0x000800,   6, 0x01, 0x00000001 },
+       { 0x000632,   1, 0x01, 0x00000001 },
+       { 0x000633,   1, 0x01, 0x00000002 },
+       { 0x000634,   1, 0x01, 0x00000003 },
+       { 0x000635,   1, 0x01, 0x00000004 },
+       { 0x000654,   1, 0x01, 0x3f800000 },
+       { 0x000657,   1, 0x01, 0x3f800000 },
+       { 0x000655,   2, 0x01, 0x3f800000 },
+       { 0x0006cd,   1, 0x01, 0x3f800000 },
+       { 0x0007f5,   1, 0x01, 0x3f800000 },
+       { 0x0007dc,   1, 0x01, 0x39291909 },
+       { 0x0007dd,   1, 0x01, 0x79695949 },
+       { 0x0007de,   1, 0x01, 0xb9a99989 },
+       { 0x0007df,   1, 0x01, 0xf9e9d9c9 },
+       { 0x0007e8,   1, 0x01, 0x00003210 },
+       { 0x0007e9,   1, 0x01, 0x00007654 },
+       { 0x0007ea,   1, 0x01, 0x00000098 },
+       { 0x0007ec,   1, 0x01, 0x39291909 },
+       { 0x0007ed,   1, 0x01, 0x79695949 },
+       { 0x0007ee,   1, 0x01, 0xb9a99989 },
+       { 0x0007ef,   1, 0x01, 0xf9e9d9c9 },
+       { 0x0007f0,   1, 0x01, 0x00003210 },
+       { 0x0007f1,   1, 0x01, 0x00007654 },
+       { 0x0007f2,   1, 0x01, 0x00000098 },
+       { 0x0005a5,   1, 0x01, 0x00000001 },
+       { 0x000980, 128, 0x01, 0x00000000 },
+       { 0x000468,   1, 0x01, 0x00000004 },
+       { 0x00046c,   1, 0x01, 0x00000001 },
+       { 0x000470,  96, 0x01, 0x00000000 },
+       { 0x000510,  16, 0x01, 0x3f800000 },
+       { 0x000520,   1, 0x01, 0x000002b6 },
+       { 0x000529,   1, 0x01, 0x00000001 },
+       { 0x000530,  16, 0x01, 0xffff0000 },
+       { 0x000585,   1, 0x01, 0x0000003f },
+       { 0x000576,   1, 0x01, 0x00000003 },
+       { 0x00057b,   1, 0x01, 0x00000059 },
+       { 0x000586,   1, 0x01, 0x00000040 },
+       { 0x000582,   2, 0x01, 0x00000080 },
+       { 0x0005c2,   1, 0x01, 0x00000001 },
+       { 0x000638,   2, 0x01, 0x00000001 },
+       { 0x00063a,   1, 0x01, 0x00000002 },
+       { 0x00063b,   2, 0x01, 0x00000001 },
+       { 0x00063d,   1, 0x01, 0x00000002 },
+       { 0x00063e,   1, 0x01, 0x00000001 },
+       { 0x0008b8,   8, 0x01, 0x00000001 },
+       { 0x000900,   8, 0x01, 0x00000001 },
+       { 0x000908,   8, 0x01, 0x00000002 },
+       { 0x000910,  16, 0x01, 0x00000001 },
+       { 0x000920,   8, 0x01, 0x00000002 },
+       { 0x000928,   8, 0x01, 0x00000001 },
+       { 0x000662,   1, 0x01, 0x00000001 },
+       { 0x000648,   9, 0x01, 0x00000001 },
+       { 0x000658,   1, 0x01, 0x0000000f },
+       { 0x0007ff,   1, 0x01, 0x0000000a },
+       { 0x00066a,   1, 0x01, 0x40000000 },
+       { 0x00066b,   1, 0x01, 0x10000000 },
+       { 0x00066c,   2, 0x01, 0xffff0000 },
+       { 0x0007af,   2, 0x01, 0x00000008 },
+       { 0x0007f6,   1, 0x01, 0x00000001 },
+       { 0x00080b,   1, 0x01, 0x00000002 },
+       { 0x0006b2,   1, 0x01, 0x00000055 },
+       { 0x0007ad,   1, 0x01, 0x00000003 },
+       { 0x000937,   1, 0x01, 0x00000001 },
+       { 0x000971,   1, 0x01, 0x00000008 },
+       { 0x000972,   1, 0x01, 0x00000040 },
+       { 0x000973,   1, 0x01, 0x0000012c },
+       { 0x00097c,   1, 0x01, 0x00000040 },
+       { 0x000979,   1, 0x01, 0x00000003 },
+       { 0x000975,   1, 0x01, 0x00000020 },
+       { 0x000976,   1, 0x01, 0x00000001 },
+       { 0x000977,   1, 0x01, 0x00000020 },
+       { 0x000978,   1, 0x01, 0x00000001 },
+       { 0x000957,   1, 0x01, 0x00000003 },
+       { 0x00095e,   1, 0x01, 0x20164010 },
+       { 0x00095f,   1, 0x01, 0x00000020 },
+       { 0x000a0d,   1, 0x01, 0x00000006 },
+       { 0x00097d,   1, 0x01, 0x00000020 },
+       { 0x000683,   1, 0x01, 0x00000006 },
+       { 0x000685,   1, 0x01, 0x003fffff },
+       { 0x000687,   1, 0x01, 0x003fffff },
+       { 0x0006a0,   1, 0x01, 0x00000005 },
+       { 0x000840,   1, 0x01, 0x00400008 },
+       { 0x000841,   1, 0x01, 0x08000080 },
+       { 0x000842,   1, 0x01, 0x00400008 },
+       { 0x000843,   1, 0x01, 0x08000080 },
+       { 0x0006aa,   1, 0x01, 0x00000001 },
+       { 0x0006ab,   1, 0x01, 0x00000002 },
+       { 0x0006ac,   1, 0x01, 0x00000080 },
+       { 0x0006ad,   2, 0x01, 0x00000100 },
+       { 0x0006b1,   1, 0x01, 0x00000011 },
+       { 0x0006bb,   1, 0x01, 0x000000cf },
+       { 0x0006ce,   1, 0x01, 0x2a712488 },
+       { 0x000739,   1, 0x01, 0x4085c000 },
+       { 0x00073a,   1, 0x01, 0x00000080 },
+       { 0x000786,   1, 0x01, 0x80000100 },
+       { 0x00073c,   1, 0x01, 0x00010100 },
+       { 0x00073d,   1, 0x01, 0x02800000 },
+       { 0x000787,   1, 0x01, 0x000000cf },
+       { 0x00078c,   1, 0x01, 0x00000008 },
+       { 0x000792,   1, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
+       { 0x000797,   1, 0x01, 0x000000cf },
+       { 0x000836,   1, 0x01, 0x00000001 },
+       { 0x00079a,   1, 0x01, 0x00000002 },
+       { 0x000833,   1, 0x01, 0x04444480 },
+       { 0x0007a1,   1, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
+       { 0x000831,   1, 0x01, 0x00000004 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x000a04,   1, 0x01, 0x000000ff },
+       { 0x000a0b,   1, 0x01, 0x00000040 },
+       { 0x00097f,   1, 0x01, 0x00000100 },
+       { 0x000a02,   1, 0x01, 0x00000001 },
+       { 0x000809,   1, 0x01, 0x00000007 },
+       { 0x00c221,   1, 0x01, 0x00000040 },
+       { 0x00c1b0,   8, 0x01, 0x0000000f },
+       { 0x00c1b8,   1, 0x01, 0x0fac6881 },
+       { 0x00c1b9,   1, 0x01, 0x00fac688 },
+       { 0x00c401,   1, 0x01, 0x00000001 },
+       { 0x00c402,   1, 0x01, 0x00010001 },
+       { 0x00c403,   2, 0x01, 0x00000001 },
+       { 0x00c40e,   1, 0x01, 0x00000020 },
+       { 0x00c500,   1, 0x01, 0x00000003 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000002 },
+       { 0x0006aa,   1, 0x01, 0x00000001 },
+       { 0x0006ad,   2, 0x01, 0x00000100 },
+       { 0x0006b1,   1, 0x01, 0x00000011 },
+       { 0x00078c,   1, 0x01, 0x00000008 },
+       { 0x000792,   1, 0x01, 0x00000001 },
+       { 0x000794,   3, 0x01, 0x00000001 },
+       { 0x000797,   1, 0x01, 0x000000cf },
+       { 0x00079a,   1, 0x01, 0x00000002 },
+       { 0x0007a1,   1, 0x01, 0x00000001 },
+       { 0x0007a3,   3, 0x01, 0x00000001 },
+       { 0x000831,   1, 0x01, 0x00000004 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000008 },
+       { 0x000039,   3, 0x01, 0x00000000 },
+       { 0x000380,   1, 0x01, 0x00000001 },
+       { 0x000366,   2, 0x01, 0x00000000 },
+       { 0x000368,   1, 0x01, 0x00000fff },
+       { 0x000370,   2, 0x01, 0x00000000 },
+       { 0x000372,   1, 0x01, 0x000fffff },
+       { 0x000813,   1, 0x01, 0x00000006 },
+       { 0x000814,   1, 0x01, 0x00000008 },
+       { 0x000957,   1, 0x01, 0x00000003 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x000a04,   1, 0x01, 0x000000ff },
+       { 0x000a0b,   1, 0x01, 0x00000040 },
+       { 0x00097f,   1, 0x01, 0x00000100 },
+       { 0x000a02,   1, 0x01, 0x00000001 },
+       { 0x000809,   1, 0x01, 0x00000007 },
+       { 0x00c221,   1, 0x01, 0x00000040 },
+       { 0x00c401,   1, 0x01, 0x00000001 },
+       { 0x00c402,   1, 0x01, 0x00010001 },
+       { 0x00c403,   2, 0x01, 0x00000001 },
+       { 0x00c40e,   1, 0x01, 0x00000020 },
+       { 0x00c500,   1, 0x01, 0x00000003 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       { 0x001000,   1, 0x01, 0x00000001 },
+       { 0x000b07,   1, 0x01, 0x00000002 },
+       { 0x000b08,   2, 0x01, 0x00000100 },
+       { 0x000b0a,   1, 0x01, 0x00000001 },
+       { 0x01e100,   1, 0x01, 0x00000001 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_a197[] = {
+       { 0x000800,   1, 0x04, 0x00000000 },
+       { 0x000840,   1, 0x04, 0x00000000 },
+       { 0x000880,   1, 0x04, 0x00000000 },
+       { 0x0008c0,   1, 0x04, 0x00000000 },
+       { 0x000900,   1, 0x04, 0x00000000 },
+       { 0x000940,   1, 0x04, 0x00000000 },
+       { 0x000980,   1, 0x04, 0x00000000 },
+       { 0x0009c0,   1, 0x04, 0x00000000 },
+       { 0x000804,   1, 0x04, 0x00000000 },
+       { 0x000844,   1, 0x04, 0x00000000 },
+       { 0x000884,   1, 0x04, 0x00000000 },
+       { 0x0008c4,   1, 0x04, 0x00000000 },
+       { 0x000904,   1, 0x04, 0x00000000 },
+       { 0x000944,   1, 0x04, 0x00000000 },
+       { 0x000984,   1, 0x04, 0x00000000 },
+       { 0x0009c4,   1, 0x04, 0x00000000 },
+       { 0x000808,   1, 0x04, 0x00000400 },
+       { 0x000848,   1, 0x04, 0x00000400 },
+       { 0x000888,   1, 0x04, 0x00000400 },
+       { 0x0008c8,   1, 0x04, 0x00000400 },
+       { 0x000908,   1, 0x04, 0x00000400 },
+       { 0x000948,   1, 0x04, 0x00000400 },
+       { 0x000988,   1, 0x04, 0x00000400 },
+       { 0x0009c8,   1, 0x04, 0x00000400 },
+       { 0x00080c,   1, 0x04, 0x00000300 },
+       { 0x00084c,   1, 0x04, 0x00000300 },
+       { 0x00088c,   1, 0x04, 0x00000300 },
+       { 0x0008cc,   1, 0x04, 0x00000300 },
+       { 0x00090c,   1, 0x04, 0x00000300 },
+       { 0x00094c,   1, 0x04, 0x00000300 },
+       { 0x00098c,   1, 0x04, 0x00000300 },
+       { 0x0009cc,   1, 0x04, 0x00000300 },
+       { 0x000810,   1, 0x04, 0x000000cf },
+       { 0x000850,   1, 0x04, 0x00000000 },
+       { 0x000890,   1, 0x04, 0x00000000 },
+       { 0x0008d0,   1, 0x04, 0x00000000 },
+       { 0x000910,   1, 0x04, 0x00000000 },
+       { 0x000950,   1, 0x04, 0x00000000 },
+       { 0x000990,   1, 0x04, 0x00000000 },
+       { 0x0009d0,   1, 0x04, 0x00000000 },
+       { 0x000814,   1, 0x04, 0x00000040 },
+       { 0x000854,   1, 0x04, 0x00000040 },
+       { 0x000894,   1, 0x04, 0x00000040 },
+       { 0x0008d4,   1, 0x04, 0x00000040 },
+       { 0x000914,   1, 0x04, 0x00000040 },
+       { 0x000954,   1, 0x04, 0x00000040 },
+       { 0x000994,   1, 0x04, 0x00000040 },
+       { 0x0009d4,   1, 0x04, 0x00000040 },
+       { 0x000818,   1, 0x04, 0x00000001 },
+       { 0x000858,   1, 0x04, 0x00000001 },
+       { 0x000898,   1, 0x04, 0x00000001 },
+       { 0x0008d8,   1, 0x04, 0x00000001 },
+       { 0x000918,   1, 0x04, 0x00000001 },
+       { 0x000958,   1, 0x04, 0x00000001 },
+       { 0x000998,   1, 0x04, 0x00000001 },
+       { 0x0009d8,   1, 0x04, 0x00000001 },
+       { 0x00081c,   1, 0x04, 0x00000000 },
+       { 0x00085c,   1, 0x04, 0x00000000 },
+       { 0x00089c,   1, 0x04, 0x00000000 },
+       { 0x0008dc,   1, 0x04, 0x00000000 },
+       { 0x00091c,   1, 0x04, 0x00000000 },
+       { 0x00095c,   1, 0x04, 0x00000000 },
+       { 0x00099c,   1, 0x04, 0x00000000 },
+       { 0x0009dc,   1, 0x04, 0x00000000 },
+       { 0x000820,   1, 0x04, 0x00000000 },
+       { 0x000860,   1, 0x04, 0x00000000 },
+       { 0x0008a0,   1, 0x04, 0x00000000 },
+       { 0x0008e0,   1, 0x04, 0x00000000 },
+       { 0x000920,   1, 0x04, 0x00000000 },
+       { 0x000960,   1, 0x04, 0x00000000 },
+       { 0x0009a0,   1, 0x04, 0x00000000 },
+       { 0x0009e0,   1, 0x04, 0x00000000 },
+       { 0x001c00,   1, 0x04, 0x00000000 },
+       { 0x001c10,   1, 0x04, 0x00000000 },
+       { 0x001c20,   1, 0x04, 0x00000000 },
+       { 0x001c30,   1, 0x04, 0x00000000 },
+       { 0x001c40,   1, 0x04, 0x00000000 },
+       { 0x001c50,   1, 0x04, 0x00000000 },
+       { 0x001c60,   1, 0x04, 0x00000000 },
+       { 0x001c70,   1, 0x04, 0x00000000 },
+       { 0x001c80,   1, 0x04, 0x00000000 },
+       { 0x001c90,   1, 0x04, 0x00000000 },
+       { 0x001ca0,   1, 0x04, 0x00000000 },
+       { 0x001cb0,   1, 0x04, 0x00000000 },
+       { 0x001cc0,   1, 0x04, 0x00000000 },
+       { 0x001cd0,   1, 0x04, 0x00000000 },
+       { 0x001ce0,   1, 0x04, 0x00000000 },
+       { 0x001cf0,   1, 0x04, 0x00000000 },
+       { 0x001c04,   1, 0x04, 0x00000000 },
+       { 0x001c14,   1, 0x04, 0x00000000 },
+       { 0x001c24,   1, 0x04, 0x00000000 },
+       { 0x001c34,   1, 0x04, 0x00000000 },
+       { 0x001c44,   1, 0x04, 0x00000000 },
+       { 0x001c54,   1, 0x04, 0x00000000 },
+       { 0x001c64,   1, 0x04, 0x00000000 },
+       { 0x001c74,   1, 0x04, 0x00000000 },
+       { 0x001c84,   1, 0x04, 0x00000000 },
+       { 0x001c94,   1, 0x04, 0x00000000 },
+       { 0x001ca4,   1, 0x04, 0x00000000 },
+       { 0x001cb4,   1, 0x04, 0x00000000 },
+       { 0x001cc4,   1, 0x04, 0x00000000 },
+       { 0x001cd4,   1, 0x04, 0x00000000 },
+       { 0x001ce4,   1, 0x04, 0x00000000 },
+       { 0x001cf4,   1, 0x04, 0x00000000 },
+       { 0x001c08,   1, 0x04, 0x00000000 },
+       { 0x001c18,   1, 0x04, 0x00000000 },
+       { 0x001c28,   1, 0x04, 0x00000000 },
+       { 0x001c38,   1, 0x04, 0x00000000 },
+       { 0x001c48,   1, 0x04, 0x00000000 },
+       { 0x001c58,   1, 0x04, 0x00000000 },
+       { 0x001c68,   1, 0x04, 0x00000000 },
+       { 0x001c78,   1, 0x04, 0x00000000 },
+       { 0x001c88,   1, 0x04, 0x00000000 },
+       { 0x001c98,   1, 0x04, 0x00000000 },
+       { 0x001ca8,   1, 0x04, 0x00000000 },
+       { 0x001cb8,   1, 0x04, 0x00000000 },
+       { 0x001cc8,   1, 0x04, 0x00000000 },
+       { 0x001cd8,   1, 0x04, 0x00000000 },
+       { 0x001ce8,   1, 0x04, 0x00000000 },
+       { 0x001cf8,   1, 0x04, 0x00000000 },
+       { 0x001c0c,   1, 0x04, 0x00000000 },
+       { 0x001c1c,   1, 0x04, 0x00000000 },
+       { 0x001c2c,   1, 0x04, 0x00000000 },
+       { 0x001c3c,   1, 0x04, 0x00000000 },
+       { 0x001c4c,   1, 0x04, 0x00000000 },
+       { 0x001c5c,   1, 0x04, 0x00000000 },
+       { 0x001c6c,   1, 0x04, 0x00000000 },
+       { 0x001c7c,   1, 0x04, 0x00000000 },
+       { 0x001c8c,   1, 0x04, 0x00000000 },
+       { 0x001c9c,   1, 0x04, 0x00000000 },
+       { 0x001cac,   1, 0x04, 0x00000000 },
+       { 0x001cbc,   1, 0x04, 0x00000000 },
+       { 0x001ccc,   1, 0x04, 0x00000000 },
+       { 0x001cdc,   1, 0x04, 0x00000000 },
+       { 0x001cec,   1, 0x04, 0x00000000 },
+       { 0x001cfc,   2, 0x04, 0x00000000 },
+       { 0x001d10,   1, 0x04, 0x00000000 },
+       { 0x001d20,   1, 0x04, 0x00000000 },
+       { 0x001d30,   1, 0x04, 0x00000000 },
+       { 0x001d40,   1, 0x04, 0x00000000 },
+       { 0x001d50,   1, 0x04, 0x00000000 },
+       { 0x001d60,   1, 0x04, 0x00000000 },
+       { 0x001d70,   1, 0x04, 0x00000000 },
+       { 0x001d80,   1, 0x04, 0x00000000 },
+       { 0x001d90,   1, 0x04, 0x00000000 },
+       { 0x001da0,   1, 0x04, 0x00000000 },
+       { 0x001db0,   1, 0x04, 0x00000000 },
+       { 0x001dc0,   1, 0x04, 0x00000000 },
+       { 0x001dd0,   1, 0x04, 0x00000000 },
+       { 0x001de0,   1, 0x04, 0x00000000 },
+       { 0x001df0,   1, 0x04, 0x00000000 },
+       { 0x001d04,   1, 0x04, 0x00000000 },
+       { 0x001d14,   1, 0x04, 0x00000000 },
+       { 0x001d24,   1, 0x04, 0x00000000 },
+       { 0x001d34,   1, 0x04, 0x00000000 },
+       { 0x001d44,   1, 0x04, 0x00000000 },
+       { 0x001d54,   1, 0x04, 0x00000000 },
+       { 0x001d64,   1, 0x04, 0x00000000 },
+       { 0x001d74,   1, 0x04, 0x00000000 },
+       { 0x001d84,   1, 0x04, 0x00000000 },
+       { 0x001d94,   1, 0x04, 0x00000000 },
+       { 0x001da4,   1, 0x04, 0x00000000 },
+       { 0x001db4,   1, 0x04, 0x00000000 },
+       { 0x001dc4,   1, 0x04, 0x00000000 },
+       { 0x001dd4,   1, 0x04, 0x00000000 },
+       { 0x001de4,   1, 0x04, 0x00000000 },
+       { 0x001df4,   1, 0x04, 0x00000000 },
+       { 0x001d08,   1, 0x04, 0x00000000 },
+       { 0x001d18,   1, 0x04, 0x00000000 },
+       { 0x001d28,   1, 0x04, 0x00000000 },
+       { 0x001d38,   1, 0x04, 0x00000000 },
+       { 0x001d48,   1, 0x04, 0x00000000 },
+       { 0x001d58,   1, 0x04, 0x00000000 },
+       { 0x001d68,   1, 0x04, 0x00000000 },
+       { 0x001d78,   1, 0x04, 0x00000000 },
+       { 0x001d88,   1, 0x04, 0x00000000 },
+       { 0x001d98,   1, 0x04, 0x00000000 },
+       { 0x001da8,   1, 0x04, 0x00000000 },
+       { 0x001db8,   1, 0x04, 0x00000000 },
+       { 0x001dc8,   1, 0x04, 0x00000000 },
+       { 0x001dd8,   1, 0x04, 0x00000000 },
+       { 0x001de8,   1, 0x04, 0x00000000 },
+       { 0x001df8,   1, 0x04, 0x00000000 },
+       { 0x001d0c,   1, 0x04, 0x00000000 },
+       { 0x001d1c,   1, 0x04, 0x00000000 },
+       { 0x001d2c,   1, 0x04, 0x00000000 },
+       { 0x001d3c,   1, 0x04, 0x00000000 },
+       { 0x001d4c,   1, 0x04, 0x00000000 },
+       { 0x001d5c,   1, 0x04, 0x00000000 },
+       { 0x001d6c,   1, 0x04, 0x00000000 },
+       { 0x001d7c,   1, 0x04, 0x00000000 },
+       { 0x001d8c,   1, 0x04, 0x00000000 },
+       { 0x001d9c,   1, 0x04, 0x00000000 },
+       { 0x001dac,   1, 0x04, 0x00000000 },
+       { 0x001dbc,   1, 0x04, 0x00000000 },
+       { 0x001dcc,   1, 0x04, 0x00000000 },
+       { 0x001ddc,   1, 0x04, 0x00000000 },
+       { 0x001dec,   1, 0x04, 0x00000000 },
+       { 0x001dfc,   1, 0x04, 0x00000000 },
+       { 0x001f00,   1, 0x04, 0x00000000 },
+       { 0x001f08,   1, 0x04, 0x00000000 },
+       { 0x001f10,   1, 0x04, 0x00000000 },
+       { 0x001f18,   1, 0x04, 0x00000000 },
+       { 0x001f20,   1, 0x04, 0x00000000 },
+       { 0x001f28,   1, 0x04, 0x00000000 },
+       { 0x001f30,   1, 0x04, 0x00000000 },
+       { 0x001f38,   1, 0x04, 0x00000000 },
+       { 0x001f40,   1, 0x04, 0x00000000 },
+       { 0x001f48,   1, 0x04, 0x00000000 },
+       { 0x001f50,   1, 0x04, 0x00000000 },
+       { 0x001f58,   1, 0x04, 0x00000000 },
+       { 0x001f60,   1, 0x04, 0x00000000 },
+       { 0x001f68,   1, 0x04, 0x00000000 },
+       { 0x001f70,   1, 0x04, 0x00000000 },
+       { 0x001f78,   1, 0x04, 0x00000000 },
+       { 0x001f04,   1, 0x04, 0x00000000 },
+       { 0x001f0c,   1, 0x04, 0x00000000 },
+       { 0x001f14,   1, 0x04, 0x00000000 },
+       { 0x001f1c,   1, 0x04, 0x00000000 },
+       { 0x001f24,   1, 0x04, 0x00000000 },
+       { 0x001f2c,   1, 0x04, 0x00000000 },
+       { 0x001f34,   1, 0x04, 0x00000000 },
+       { 0x001f3c,   1, 0x04, 0x00000000 },
+       { 0x001f44,   1, 0x04, 0x00000000 },
+       { 0x001f4c,   1, 0x04, 0x00000000 },
+       { 0x001f54,   1, 0x04, 0x00000000 },
+       { 0x001f5c,   1, 0x04, 0x00000000 },
+       { 0x001f64,   1, 0x04, 0x00000000 },
+       { 0x001f6c,   1, 0x04, 0x00000000 },
+       { 0x001f74,   1, 0x04, 0x00000000 },
+       { 0x001f7c,   2, 0x04, 0x00000000 },
+       { 0x001f88,   1, 0x04, 0x00000000 },
+       { 0x001f90,   1, 0x04, 0x00000000 },
+       { 0x001f98,   1, 0x04, 0x00000000 },
+       { 0x001fa0,   1, 0x04, 0x00000000 },
+       { 0x001fa8,   1, 0x04, 0x00000000 },
+       { 0x001fb0,   1, 0x04, 0x00000000 },
+       { 0x001fb8,   1, 0x04, 0x00000000 },
+       { 0x001fc0,   1, 0x04, 0x00000000 },
+       { 0x001fc8,   1, 0x04, 0x00000000 },
+       { 0x001fd0,   1, 0x04, 0x00000000 },
+       { 0x001fd8,   1, 0x04, 0x00000000 },
+       { 0x001fe0,   1, 0x04, 0x00000000 },
+       { 0x001fe8,   1, 0x04, 0x00000000 },
+       { 0x001ff0,   1, 0x04, 0x00000000 },
+       { 0x001ff8,   1, 0x04, 0x00000000 },
+       { 0x001f84,   1, 0x04, 0x00000000 },
+       { 0x001f8c,   1, 0x04, 0x00000000 },
+       { 0x001f94,   1, 0x04, 0x00000000 },
+       { 0x001f9c,   1, 0x04, 0x00000000 },
+       { 0x001fa4,   1, 0x04, 0x00000000 },
+       { 0x001fac,   1, 0x04, 0x00000000 },
+       { 0x001fb4,   1, 0x04, 0x00000000 },
+       { 0x001fbc,   1, 0x04, 0x00000000 },
+       { 0x001fc4,   1, 0x04, 0x00000000 },
+       { 0x001fcc,   1, 0x04, 0x00000000 },
+       { 0x001fd4,   1, 0x04, 0x00000000 },
+       { 0x001fdc,   1, 0x04, 0x00000000 },
+       { 0x001fe4,   1, 0x04, 0x00000000 },
+       { 0x001fec,   1, 0x04, 0x00000000 },
+       { 0x001ff4,   1, 0x04, 0x00000000 },
+       { 0x001ffc,   2, 0x04, 0x00000000 },
+       { 0x002040,   1, 0x04, 0x00000011 },
+       { 0x002080,   1, 0x04, 0x00000020 },
+       { 0x0020c0,   1, 0x04, 0x00000030 },
+       { 0x002100,   1, 0x04, 0x00000040 },
+       { 0x002140,   1, 0x04, 0x00000051 },
+       { 0x00200c,   1, 0x04, 0x00000001 },
+       { 0x00204c,   1, 0x04, 0x00000001 },
+       { 0x00208c,   1, 0x04, 0x00000001 },
+       { 0x0020cc,   1, 0x04, 0x00000001 },
+       { 0x00210c,   1, 0x04, 0x00000001 },
+       { 0x00214c,   1, 0x04, 0x00000001 },
+       { 0x002010,   1, 0x04, 0x00000000 },
+       { 0x002050,   1, 0x04, 0x00000000 },
+       { 0x002090,   1, 0x04, 0x00000001 },
+       { 0x0020d0,   1, 0x04, 0x00000002 },
+       { 0x002110,   1, 0x04, 0x00000003 },
+       { 0x002150,   1, 0x04, 0x00000004 },
+       { 0x000380,   1, 0x04, 0x00000000 },
+       { 0x0003a0,   1, 0x04, 0x00000000 },
+       { 0x0003c0,   1, 0x04, 0x00000000 },
+       { 0x0003e0,   1, 0x04, 0x00000000 },
+       { 0x000384,   1, 0x04, 0x00000000 },
+       { 0x0003a4,   1, 0x04, 0x00000000 },
+       { 0x0003c4,   1, 0x04, 0x00000000 },
+       { 0x0003e4,   1, 0x04, 0x00000000 },
+       { 0x000388,   1, 0x04, 0x00000000 },
+       { 0x0003a8,   1, 0x04, 0x00000000 },
+       { 0x0003c8,   1, 0x04, 0x00000000 },
+       { 0x0003e8,   1, 0x04, 0x00000000 },
+       { 0x00038c,   1, 0x04, 0x00000000 },
+       { 0x0003ac,   1, 0x04, 0x00000000 },
+       { 0x0003cc,   1, 0x04, 0x00000000 },
+       { 0x0003ec,   1, 0x04, 0x00000000 },
+       { 0x000700,   1, 0x04, 0x00000000 },
+       { 0x000710,   1, 0x04, 0x00000000 },
+       { 0x000720,   1, 0x04, 0x00000000 },
+       { 0x000730,   1, 0x04, 0x00000000 },
+       { 0x000704,   1, 0x04, 0x00000000 },
+       { 0x000714,   1, 0x04, 0x00000000 },
+       { 0x000724,   1, 0x04, 0x00000000 },
+       { 0x000734,   1, 0x04, 0x00000000 },
+       { 0x000708,   1, 0x04, 0x00000000 },
+       { 0x000718,   1, 0x04, 0x00000000 },
+       { 0x000728,   1, 0x04, 0x00000000 },
+       { 0x000738,   1, 0x04, 0x00000000 },
+       { 0x002800, 128, 0x04, 0x00000000 },
+       { 0x000a00,   1, 0x04, 0x00000000 },
+       { 0x000a20,   1, 0x04, 0x00000000 },
+       { 0x000a40,   1, 0x04, 0x00000000 },
+       { 0x000a60,   1, 0x04, 0x00000000 },
+       { 0x000a80,   1, 0x04, 0x00000000 },
+       { 0x000aa0,   1, 0x04, 0x00000000 },
+       { 0x000ac0,   1, 0x04, 0x00000000 },
+       { 0x000ae0,   1, 0x04, 0x00000000 },
+       { 0x000b00,   1, 0x04, 0x00000000 },
+       { 0x000b20,   1, 0x04, 0x00000000 },
+       { 0x000b40,   1, 0x04, 0x00000000 },
+       { 0x000b60,   1, 0x04, 0x00000000 },
+       { 0x000b80,   1, 0x04, 0x00000000 },
+       { 0x000ba0,   1, 0x04, 0x00000000 },
+       { 0x000bc0,   1, 0x04, 0x00000000 },
+       { 0x000be0,   1, 0x04, 0x00000000 },
+       { 0x000a04,   1, 0x04, 0x00000000 },
+       { 0x000a24,   1, 0x04, 0x00000000 },
+       { 0x000a44,   1, 0x04, 0x00000000 },
+       { 0x000a64,   1, 0x04, 0x00000000 },
+       { 0x000a84,   1, 0x04, 0x00000000 },
+       { 0x000aa4,   1, 0x04, 0x00000000 },
+       { 0x000ac4,   1, 0x04, 0x00000000 },
+       { 0x000ae4,   1, 0x04, 0x00000000 },
+       { 0x000b04,   1, 0x04, 0x00000000 },
+       { 0x000b24,   1, 0x04, 0x00000000 },
+       { 0x000b44,   1, 0x04, 0x00000000 },
+       { 0x000b64,   1, 0x04, 0x00000000 },
+       { 0x000b84,   1, 0x04, 0x00000000 },
+       { 0x000ba4,   1, 0x04, 0x00000000 },
+       { 0x000bc4,   1, 0x04, 0x00000000 },
+       { 0x000be4,   1, 0x04, 0x00000000 },
+       { 0x000a08,   1, 0x04, 0x00000000 },
+       { 0x000a28,   1, 0x04, 0x00000000 },
+       { 0x000a48,   1, 0x04, 0x00000000 },
+       { 0x000a68,   1, 0x04, 0x00000000 },
+       { 0x000a88,   1, 0x04, 0x00000000 },
+       { 0x000aa8,   1, 0x04, 0x00000000 },
+       { 0x000ac8,   1, 0x04, 0x00000000 },
+       { 0x000ae8,   1, 0x04, 0x00000000 },
+       { 0x000b08,   1, 0x04, 0x00000000 },
+       { 0x000b28,   1, 0x04, 0x00000000 },
+       { 0x000b48,   1, 0x04, 0x00000000 },
+       { 0x000b68,   1, 0x04, 0x00000000 },
+       { 0x000b88,   1, 0x04, 0x00000000 },
+       { 0x000ba8,   1, 0x04, 0x00000000 },
+       { 0x000bc8,   1, 0x04, 0x00000000 },
+       { 0x000be8,   1, 0x04, 0x00000000 },
+       { 0x000a0c,   1, 0x04, 0x00000000 },
+       { 0x000a2c,   1, 0x04, 0x00000000 },
+       { 0x000a4c,   1, 0x04, 0x00000000 },
+       { 0x000a6c,   1, 0x04, 0x00000000 },
+       { 0x000a8c,   1, 0x04, 0x00000000 },
+       { 0x000aac,   1, 0x04, 0x00000000 },
+       { 0x000acc,   1, 0x04, 0x00000000 },
+       { 0x000aec,   1, 0x04, 0x00000000 },
+       { 0x000b0c,   1, 0x04, 0x00000000 },
+       { 0x000b2c,   1, 0x04, 0x00000000 },
+       { 0x000b4c,   1, 0x04, 0x00000000 },
+       { 0x000b6c,   1, 0x04, 0x00000000 },
+       { 0x000b8c,   1, 0x04, 0x00000000 },
+       { 0x000bac,   1, 0x04, 0x00000000 },
+       { 0x000bcc,   1, 0x04, 0x00000000 },
+       { 0x000bec,   1, 0x04, 0x00000000 },
+       { 0x000a10,   1, 0x04, 0x00000000 },
+       { 0x000a30,   1, 0x04, 0x00000000 },
+       { 0x000a50,   1, 0x04, 0x00000000 },
+       { 0x000a70,   1, 0x04, 0x00000000 },
+       { 0x000a90,   1, 0x04, 0x00000000 },
+       { 0x000ab0,   1, 0x04, 0x00000000 },
+       { 0x000ad0,   1, 0x04, 0x00000000 },
+       { 0x000af0,   1, 0x04, 0x00000000 },
+       { 0x000b10,   1, 0x04, 0x00000000 },
+       { 0x000b30,   1, 0x04, 0x00000000 },
+       { 0x000b50,   1, 0x04, 0x00000000 },
+       { 0x000b70,   1, 0x04, 0x00000000 },
+       { 0x000b90,   1, 0x04, 0x00000000 },
+       { 0x000bb0,   1, 0x04, 0x00000000 },
+       { 0x000bd0,   1, 0x04, 0x00000000 },
+       { 0x000bf0,   1, 0x04, 0x00000000 },
+       { 0x000a14,   1, 0x04, 0x00000000 },
+       { 0x000a34,   1, 0x04, 0x00000000 },
+       { 0x000a54,   1, 0x04, 0x00000000 },
+       { 0x000a74,   1, 0x04, 0x00000000 },
+       { 0x000a94,   1, 0x04, 0x00000000 },
+       { 0x000ab4,   1, 0x04, 0x00000000 },
+       { 0x000ad4,   1, 0x04, 0x00000000 },
+       { 0x000af4,   1, 0x04, 0x00000000 },
+       { 0x000b14,   1, 0x04, 0x00000000 },
+       { 0x000b34,   1, 0x04, 0x00000000 },
+       { 0x000b54,   1, 0x04, 0x00000000 },
+       { 0x000b74,   1, 0x04, 0x00000000 },
+       { 0x000b94,   1, 0x04, 0x00000000 },
+       { 0x000bb4,   1, 0x04, 0x00000000 },
+       { 0x000bd4,   1, 0x04, 0x00000000 },
+       { 0x000bf4,   1, 0x04, 0x00000000 },
+       { 0x000c00,   1, 0x04, 0x00000000 },
+       { 0x000c10,   1, 0x04, 0x00000000 },
+       { 0x000c20,   1, 0x04, 0x00000000 },
+       { 0x000c30,   1, 0x04, 0x00000000 },
+       { 0x000c40,   1, 0x04, 0x00000000 },
+       { 0x000c50,   1, 0x04, 0x00000000 },
+       { 0x000c60,   1, 0x04, 0x00000000 },
+       { 0x000c70,   1, 0x04, 0x00000000 },
+       { 0x000c80,   1, 0x04, 0x00000000 },
+       { 0x000c90,   1, 0x04, 0x00000000 },
+       { 0x000ca0,   1, 0x04, 0x00000000 },
+       { 0x000cb0,   1, 0x04, 0x00000000 },
+       { 0x000cc0,   1, 0x04, 0x00000000 },
+       { 0x000cd0,   1, 0x04, 0x00000000 },
+       { 0x000ce0,   1, 0x04, 0x00000000 },
+       { 0x000cf0,   1, 0x04, 0x00000000 },
+       { 0x000c04,   1, 0x04, 0x00000000 },
+       { 0x000c14,   1, 0x04, 0x00000000 },
+       { 0x000c24,   1, 0x04, 0x00000000 },
+       { 0x000c34,   1, 0x04, 0x00000000 },
+       { 0x000c44,   1, 0x04, 0x00000000 },
+       { 0x000c54,   1, 0x04, 0x00000000 },
+       { 0x000c64,   1, 0x04, 0x00000000 },
+       { 0x000c74,   1, 0x04, 0x00000000 },
+       { 0x000c84,   1, 0x04, 0x00000000 },
+       { 0x000c94,   1, 0x04, 0x00000000 },
+       { 0x000ca4,   1, 0x04, 0x00000000 },
+       { 0x000cb4,   1, 0x04, 0x00000000 },
+       { 0x000cc4,   1, 0x04, 0x00000000 },
+       { 0x000cd4,   1, 0x04, 0x00000000 },
+       { 0x000ce4,   1, 0x04, 0x00000000 },
+       { 0x000cf4,   1, 0x04, 0x00000000 },
+       { 0x000c08,   1, 0x04, 0x00000000 },
+       { 0x000c18,   1, 0x04, 0x00000000 },
+       { 0x000c28,   1, 0x04, 0x00000000 },
+       { 0x000c38,   1, 0x04, 0x00000000 },
+       { 0x000c48,   1, 0x04, 0x00000000 },
+       { 0x000c58,   1, 0x04, 0x00000000 },
+       { 0x000c68,   1, 0x04, 0x00000000 },
+       { 0x000c78,   1, 0x04, 0x00000000 },
+       { 0x000c88,   1, 0x04, 0x00000000 },
+       { 0x000c98,   1, 0x04, 0x00000000 },
+       { 0x000ca8,   1, 0x04, 0x00000000 },
+       { 0x000cb8,   1, 0x04, 0x00000000 },
+       { 0x000cc8,   1, 0x04, 0x00000000 },
+       { 0x000cd8,   1, 0x04, 0x00000000 },
+       { 0x000ce8,   1, 0x04, 0x00000000 },
+       { 0x000cf8,   1, 0x04, 0x00000000 },
+       { 0x000c0c,   1, 0x04, 0x3f800000 },
+       { 0x000c1c,   1, 0x04, 0x3f800000 },
+       { 0x000c2c,   1, 0x04, 0x3f800000 },
+       { 0x000c3c,   1, 0x04, 0x3f800000 },
+       { 0x000c4c,   1, 0x04, 0x3f800000 },
+       { 0x000c5c,   1, 0x04, 0x3f800000 },
+       { 0x000c6c,   1, 0x04, 0x3f800000 },
+       { 0x000c7c,   1, 0x04, 0x3f800000 },
+       { 0x000c8c,   1, 0x04, 0x3f800000 },
+       { 0x000c9c,   1, 0x04, 0x3f800000 },
+       { 0x000cac,   1, 0x04, 0x3f800000 },
+       { 0x000cbc,   1, 0x04, 0x3f800000 },
+       { 0x000ccc,   1, 0x04, 0x3f800000 },
+       { 0x000cdc,   1, 0x04, 0x3f800000 },
+       { 0x000cec,   1, 0x04, 0x3f800000 },
+       { 0x000cfc,   1, 0x04, 0x3f800000 },
+       { 0x000d00,   1, 0x04, 0xffff0000 },
+       { 0x000d08,   1, 0x04, 0xffff0000 },
+       { 0x000d10,   1, 0x04, 0xffff0000 },
+       { 0x000d18,   1, 0x04, 0xffff0000 },
+       { 0x000d20,   1, 0x04, 0xffff0000 },
+       { 0x000d28,   1, 0x04, 0xffff0000 },
+       { 0x000d30,   1, 0x04, 0xffff0000 },
+       { 0x000d38,   1, 0x04, 0xffff0000 },
+       { 0x000d04,   1, 0x04, 0xffff0000 },
+       { 0x000d0c,   1, 0x04, 0xffff0000 },
+       { 0x000d14,   1, 0x04, 0xffff0000 },
+       { 0x000d1c,   1, 0x04, 0xffff0000 },
+       { 0x000d24,   1, 0x04, 0xffff0000 },
+       { 0x000d2c,   1, 0x04, 0xffff0000 },
+       { 0x000d34,   1, 0x04, 0xffff0000 },
+       { 0x000d3c,   1, 0x04, 0xffff0000 },
+       { 0x000e00,   1, 0x04, 0x00000000 },
+       { 0x000e10,   1, 0x04, 0x00000000 },
+       { 0x000e20,   1, 0x04, 0x00000000 },
+       { 0x000e30,   1, 0x04, 0x00000000 },
+       { 0x000e40,   1, 0x04, 0x00000000 },
+       { 0x000e50,   1, 0x04, 0x00000000 },
+       { 0x000e60,   1, 0x04, 0x00000000 },
+       { 0x000e70,   1, 0x04, 0x00000000 },
+       { 0x000e80,   1, 0x04, 0x00000000 },
+       { 0x000e90,   1, 0x04, 0x00000000 },
+       { 0x000ea0,   1, 0x04, 0x00000000 },
+       { 0x000eb0,   1, 0x04, 0x00000000 },
+       { 0x000ec0,   1, 0x04, 0x00000000 },
+       { 0x000ed0,   1, 0x04, 0x00000000 },
+       { 0x000ee0,   1, 0x04, 0x00000000 },
+       { 0x000ef0,   1, 0x04, 0x00000000 },
+       { 0x000e04,   1, 0x04, 0xffff0000 },
+       { 0x000e14,   1, 0x04, 0xffff0000 },
+       { 0x000e24,   1, 0x04, 0xffff0000 },
+       { 0x000e34,   1, 0x04, 0xffff0000 },
+       { 0x000e44,   1, 0x04, 0xffff0000 },
+       { 0x000e54,   1, 0x04, 0xffff0000 },
+       { 0x000e64,   1, 0x04, 0xffff0000 },
+       { 0x000e74,   1, 0x04, 0xffff0000 },
+       { 0x000e84,   1, 0x04, 0xffff0000 },
+       { 0x000e94,   1, 0x04, 0xffff0000 },
+       { 0x000ea4,   1, 0x04, 0xffff0000 },
+       { 0x000eb4,   1, 0x04, 0xffff0000 },
+       { 0x000ec4,   1, 0x04, 0xffff0000 },
+       { 0x000ed4,   1, 0x04, 0xffff0000 },
+       { 0x000ee4,   1, 0x04, 0xffff0000 },
+       { 0x000ef4,   1, 0x04, 0xffff0000 },
+       { 0x000e08,   1, 0x04, 0xffff0000 },
+       { 0x000e18,   1, 0x04, 0xffff0000 },
+       { 0x000e28,   1, 0x04, 0xffff0000 },
+       { 0x000e38,   1, 0x04, 0xffff0000 },
+       { 0x000e48,   1, 0x04, 0xffff0000 },
+       { 0x000e58,   1, 0x04, 0xffff0000 },
+       { 0x000e68,   1, 0x04, 0xffff0000 },
+       { 0x000e78,   1, 0x04, 0xffff0000 },
+       { 0x000e88,   1, 0x04, 0xffff0000 },
+       { 0x000e98,   1, 0x04, 0xffff0000 },
+       { 0x000ea8,   1, 0x04, 0xffff0000 },
+       { 0x000eb8,   1, 0x04, 0xffff0000 },
+       { 0x000ec8,   1, 0x04, 0xffff0000 },
+       { 0x000ed8,   1, 0x04, 0xffff0000 },
+       { 0x000ee8,   1, 0x04, 0xffff0000 },
+       { 0x000ef8,   1, 0x04, 0xffff0000 },
+       { 0x000d40,   1, 0x04, 0x00000000 },
+       { 0x000d48,   1, 0x04, 0x00000000 },
+       { 0x000d50,   1, 0x04, 0x00000000 },
+       { 0x000d58,   1, 0x04, 0x00000000 },
+       { 0x000d44,   1, 0x04, 0x00000000 },
+       { 0x000d4c,   1, 0x04, 0x00000000 },
+       { 0x000d54,   1, 0x04, 0x00000000 },
+       { 0x000d5c,   1, 0x04, 0x00000000 },
+       { 0x001e00,   1, 0x04, 0x00000001 },
+       { 0x001e20,   1, 0x04, 0x00000001 },
+       { 0x001e40,   1, 0x04, 0x00000001 },
+       { 0x001e60,   1, 0x04, 0x00000001 },
+       { 0x001e80,   1, 0x04, 0x00000001 },
+       { 0x001ea0,   1, 0x04, 0x00000001 },
+       { 0x001ec0,   1, 0x04, 0x00000001 },
+       { 0x001ee0,   1, 0x04, 0x00000001 },
+       { 0x001e04,   1, 0x04, 0x00000001 },
+       { 0x001e24,   1, 0x04, 0x00000001 },
+       { 0x001e44,   1, 0x04, 0x00000001 },
+       { 0x001e64,   1, 0x04, 0x00000001 },
+       { 0x001e84,   1, 0x04, 0x00000001 },
+       { 0x001ea4,   1, 0x04, 0x00000001 },
+       { 0x001ec4,   1, 0x04, 0x00000001 },
+       { 0x001ee4,   1, 0x04, 0x00000001 },
+       { 0x001e08,   1, 0x04, 0x00000002 },
+       { 0x001e28,   1, 0x04, 0x00000002 },
+       { 0x001e48,   1, 0x04, 0x00000002 },
+       { 0x001e68,   1, 0x04, 0x00000002 },
+       { 0x001e88,   1, 0x04, 0x00000002 },
+       { 0x001ea8,   1, 0x04, 0x00000002 },
+       { 0x001ec8,   1, 0x04, 0x00000002 },
+       { 0x001ee8,   1, 0x04, 0x00000002 },
+       { 0x001e0c,   1, 0x04, 0x00000001 },
+       { 0x001e2c,   1, 0x04, 0x00000001 },
+       { 0x001e4c,   1, 0x04, 0x00000001 },
+       { 0x001e6c,   1, 0x04, 0x00000001 },
+       { 0x001e8c,   1, 0x04, 0x00000001 },
+       { 0x001eac,   1, 0x04, 0x00000001 },
+       { 0x001ecc,   1, 0x04, 0x00000001 },
+       { 0x001eec,   1, 0x04, 0x00000001 },
+       { 0x001e10,   1, 0x04, 0x00000001 },
+       { 0x001e30,   1, 0x04, 0x00000001 },
+       { 0x001e50,   1, 0x04, 0x00000001 },
+       { 0x001e70,   1, 0x04, 0x00000001 },
+       { 0x001e90,   1, 0x04, 0x00000001 },
+       { 0x001eb0,   1, 0x04, 0x00000001 },
+       { 0x001ed0,   1, 0x04, 0x00000001 },
+       { 0x001ef0,   1, 0x04, 0x00000001 },
+       { 0x001e14,   1, 0x04, 0x00000002 },
+       { 0x001e34,   1, 0x04, 0x00000002 },
+       { 0x001e54,   1, 0x04, 0x00000002 },
+       { 0x001e74,   1, 0x04, 0x00000002 },
+       { 0x001e94,   1, 0x04, 0x00000002 },
+       { 0x001eb4,   1, 0x04, 0x00000002 },
+       { 0x001ed4,   1, 0x04, 0x00000002 },
+       { 0x001ef4,   1, 0x04, 0x00000002 },
+       { 0x001e18,   1, 0x04, 0x00000001 },
+       { 0x001e38,   1, 0x04, 0x00000001 },
+       { 0x001e58,   1, 0x04, 0x00000001 },
+       { 0x001e78,   1, 0x04, 0x00000001 },
+       { 0x001e98,   1, 0x04, 0x00000001 },
+       { 0x001eb8,   1, 0x04, 0x00000001 },
+       { 0x001ed8,   1, 0x04, 0x00000001 },
+       { 0x001ef8,   1, 0x04, 0x00000001 },
+       { 0x003400, 128, 0x04, 0x00000000 },
+       { 0x00030c,   1, 0x04, 0x00000001 },
+       { 0x001944,   1, 0x04, 0x00000000 },
+       { 0x001514,   1, 0x04, 0x00000000 },
+       { 0x000d68,   1, 0x04, 0x0000ffff },
+       { 0x00121c,   1, 0x04, 0x0fac6881 },
+       { 0x000fac,   1, 0x04, 0x00000001 },
+       { 0x001538,   1, 0x04, 0x00000001 },
+       { 0x000fe0,   2, 0x04, 0x00000000 },
+       { 0x000fe8,   1, 0x04, 0x00000014 },
+       { 0x000fec,   1, 0x04, 0x00000040 },
+       { 0x000ff0,   1, 0x04, 0x00000000 },
+       { 0x00179c,   1, 0x04, 0x00000000 },
+       { 0x001228,   1, 0x04, 0x00000400 },
+       { 0x00122c,   1, 0x04, 0x00000300 },
+       { 0x001230,   1, 0x04, 0x00010001 },
+       { 0x0007f8,   1, 0x04, 0x00000000 },
+       { 0x0015b4,   1, 0x04, 0x00000001 },
+       { 0x0015cc,   1, 0x04, 0x00000000 },
+       { 0x001534,   1, 0x04, 0x00000000 },
+       { 0x000fb0,   1, 0x04, 0x00000000 },
+       { 0x0015d0,   1, 0x04, 0x00000000 },
+       { 0x00153c,   1, 0x04, 0x00000000 },
+       { 0x0016b4,   1, 0x04, 0x00000003 },
+       { 0x000fbc,   4, 0x04, 0x0000ffff },
+       { 0x000df8,   2, 0x04, 0x00000000 },
+       { 0x001948,   1, 0x04, 0x00000000 },
+       { 0x001970,   1, 0x04, 0x00000001 },
+       { 0x00161c,   1, 0x04, 0x000009f0 },
+       { 0x000dcc,   1, 0x04, 0x00000010 },
+       { 0x00163c,   1, 0x04, 0x00000000 },
+       { 0x0015e4,   1, 0x04, 0x00000000 },
+       { 0x001160,  32, 0x04, 0x25e00040 },
+       { 0x001880,  32, 0x04, 0x00000000 },
+       { 0x000f84,   2, 0x04, 0x00000000 },
+       { 0x0017c8,   2, 0x04, 0x00000000 },
+       { 0x0017d0,   1, 0x04, 0x000000ff },
+       { 0x0017d4,   1, 0x04, 0xffffffff },
+       { 0x0017d8,   1, 0x04, 0x00000002 },
+       { 0x0017dc,   1, 0x04, 0x00000000 },
+       { 0x0015f4,   2, 0x04, 0x00000000 },
+       { 0x001434,   2, 0x04, 0x00000000 },
+       { 0x000d74,   1, 0x04, 0x00000000 },
+       { 0x000dec,   1, 0x04, 0x00000001 },
+       { 0x0013a4,   1, 0x04, 0x00000000 },
+       { 0x001318,   1, 0x04, 0x00000001 },
+       { 0x001644,   1, 0x04, 0x00000000 },
+       { 0x000748,   1, 0x04, 0x00000000 },
+       { 0x000de8,   1, 0x04, 0x00000000 },
+       { 0x001648,   1, 0x04, 0x00000000 },
+       { 0x0012a4,   1, 0x04, 0x00000000 },
+       { 0x001120,   4, 0x04, 0x00000000 },
+       { 0x001118,   1, 0x04, 0x00000000 },
+       { 0x00164c,   1, 0x04, 0x00000000 },
+       { 0x001658,   1, 0x04, 0x00000000 },
+       { 0x001910,   1, 0x04, 0x00000290 },
+       { 0x001518,   1, 0x04, 0x00000000 },
+       { 0x00165c,   1, 0x04, 0x00000001 },
+       { 0x001520,   1, 0x04, 0x00000000 },
+       { 0x001604,   1, 0x04, 0x00000000 },
+       { 0x001570,   1, 0x04, 0x00000000 },
+       { 0x0013b0,   2, 0x04, 0x3f800000 },
+       { 0x00020c,   1, 0x04, 0x00000000 },
+       { 0x001670,   1, 0x04, 0x30201000 },
+       { 0x001674,   1, 0x04, 0x70605040 },
+       { 0x001678,   1, 0x04, 0xb8a89888 },
+       { 0x00167c,   1, 0x04, 0xf8e8d8c8 },
+       { 0x00166c,   1, 0x04, 0x00000000 },
+       { 0x001680,   1, 0x04, 0x00ffff00 },
+       { 0x0012d0,   1, 0x04, 0x00000003 },
+       { 0x0012d4,   1, 0x04, 0x00000002 },
+       { 0x001684,   2, 0x04, 0x00000000 },
+       { 0x000dac,   2, 0x04, 0x00001b02 },
+       { 0x000db4,   1, 0x04, 0x00000000 },
+       { 0x00168c,   1, 0x04, 0x00000000 },
+       { 0x0015bc,   1, 0x04, 0x00000000 },
+       { 0x00156c,   1, 0x04, 0x00000000 },
+       { 0x00187c,   1, 0x04, 0x00000000 },
+       { 0x001110,   1, 0x04, 0x00000001 },
+       { 0x000dc0,   3, 0x04, 0x00000000 },
+       { 0x001234,   1, 0x04, 0x00000000 },
+       { 0x001690,   1, 0x04, 0x00000000 },
+       { 0x0012ac,   1, 0x04, 0x00000001 },
+       { 0x0002c4,   1, 0x04, 0x00000000 },
+       { 0x000790,   5, 0x04, 0x00000000 },
+       { 0x00077c,   1, 0x04, 0x00000000 },
+       { 0x001000,   1, 0x04, 0x00000010 },
+       { 0x0010fc,   1, 0x04, 0x00000000 },
+       { 0x001290,   1, 0x04, 0x00000000 },
+       { 0x000218,   1, 0x04, 0x00000010 },
+       { 0x0012d8,   1, 0x04, 0x00000000 },
+       { 0x0012dc,   1, 0x04, 0x00000010 },
+       { 0x000d94,   1, 0x04, 0x00000001 },
+       { 0x00155c,   2, 0x04, 0x00000000 },
+       { 0x001564,   1, 0x04, 0x00000fff },
+       { 0x001574,   2, 0x04, 0x00000000 },
+       { 0x00157c,   1, 0x04, 0x000fffff },
+       { 0x001354,   1, 0x04, 0x00000000 },
+       { 0x001610,   1, 0x04, 0x00000012 },
+       { 0x001608,   2, 0x04, 0x00000000 },
+       { 0x00260c,   1, 0x04, 0x00000000 },
+       { 0x0007ac,   1, 0x04, 0x00000000 },
+       { 0x00162c,   1, 0x04, 0x00000003 },
+       { 0x000210,   1, 0x04, 0x00000000 },
+       { 0x000320,   1, 0x04, 0x00000000 },
+       { 0x000324,   6, 0x04, 0x3f800000 },
+       { 0x000750,   1, 0x04, 0x00000000 },
+       { 0x000760,   1, 0x04, 0x39291909 },
+       { 0x000764,   1, 0x04, 0x79695949 },
+       { 0x000768,   1, 0x04, 0xb9a99989 },
+       { 0x00076c,   1, 0x04, 0xf9e9d9c9 },
+       { 0x000770,   1, 0x04, 0x30201000 },
+       { 0x000774,   1, 0x04, 0x70605040 },
+       { 0x000778,   1, 0x04, 0x00009080 },
+       { 0x000780,   1, 0x04, 0x39291909 },
+       { 0x000784,   1, 0x04, 0x79695949 },
+       { 0x000788,   1, 0x04, 0xb9a99989 },
+       { 0x00078c,   1, 0x04, 0xf9e9d9c9 },
+       { 0x0007d0,   1, 0x04, 0x30201000 },
+       { 0x0007d4,   1, 0x04, 0x70605040 },
+       { 0x0007d8,   1, 0x04, 0x00009080 },
+       { 0x00037c,   1, 0x04, 0x00000001 },
+       { 0x000740,   2, 0x04, 0x00000000 },
+       { 0x002600,   1, 0x04, 0x00000000 },
+       { 0x001918,   1, 0x04, 0x00000000 },
+       { 0x00191c,   1, 0x04, 0x00000900 },
+       { 0x001920,   1, 0x04, 0x00000405 },
+       { 0x001308,   1, 0x04, 0x00000001 },
+       { 0x001924,   1, 0x04, 0x00000000 },
+       { 0x0013ac,   1, 0x04, 0x00000000 },
+       { 0x00192c,   1, 0x04, 0x00000001 },
+       { 0x00193c,   1, 0x04, 0x00002c1c },
+       { 0x000d7c,   1, 0x04, 0x00000000 },
+       { 0x000f8c,   1, 0x04, 0x00000000 },
+       { 0x0002c0,   1, 0x04, 0x00000001 },
+       { 0x001510,   1, 0x04, 0x00000000 },
+       { 0x001940,   1, 0x04, 0x00000000 },
+       { 0x000ff4,   2, 0x04, 0x00000000 },
+       { 0x00194c,   2, 0x04, 0x00000000 },
+       { 0x001968,   1, 0x04, 0x00000000 },
+       { 0x001590,   1, 0x04, 0x0000003f },
+       { 0x0007e8,   4, 0x04, 0x00000000 },
+       { 0x00196c,   1, 0x04, 0x00000011 },
+       { 0x0002e4,   1, 0x04, 0x0000b001 },
+       { 0x00036c,   2, 0x04, 0x00000000 },
+       { 0x00197c,   1, 0x04, 0x00000000 },
+       { 0x000fcc,   2, 0x04, 0x00000000 },
+       { 0x0002d8,   1, 0x04, 0x00000040 },
+       { 0x001980,   1, 0x04, 0x00000080 },
+       { 0x001504,   1, 0x04, 0x00000080 },
+       { 0x001984,   1, 0x04, 0x00000000 },
+       { 0x000300,   1, 0x04, 0x00000001 },
+       { 0x0013a8,   1, 0x04, 0x00000000 },
+       { 0x0012ec,   1, 0x04, 0x00000000 },
+       { 0x001310,   1, 0x04, 0x00000000 },
+       { 0x001314,   1, 0x04, 0x00000001 },
+       { 0x001380,   1, 0x04, 0x00000000 },
+       { 0x001384,   4, 0x04, 0x00000001 },
+       { 0x001394,   1, 0x04, 0x00000000 },
+       { 0x00139c,   1, 0x04, 0x00000000 },
+       { 0x001398,   1, 0x04, 0x00000000 },
+       { 0x001594,   1, 0x04, 0x00000000 },
+       { 0x001598,   4, 0x04, 0x00000001 },
+       { 0x000f54,   3, 0x04, 0x00000000 },
+       { 0x0019bc,   1, 0x04, 0x00000000 },
+       { 0x000f9c,   2, 0x04, 0x00000000 },
+       { 0x0012cc,   1, 0x04, 0x00000000 },
+       { 0x0012e8,   1, 0x04, 0x00000000 },
+       { 0x00130c,   1, 0x04, 0x00000001 },
+       { 0x001360,   8, 0x04, 0x00000000 },
+       { 0x00133c,   2, 0x04, 0x00000001 },
+       { 0x001344,   1, 0x04, 0x00000002 },
+       { 0x001348,   2, 0x04, 0x00000001 },
+       { 0x001350,   1, 0x04, 0x00000002 },
+       { 0x001358,   1, 0x04, 0x00000001 },
+       { 0x0012e4,   1, 0x04, 0x00000000 },
+       { 0x00131c,   4, 0x04, 0x00000000 },
+       { 0x0019c0,   1, 0x04, 0x00000000 },
+       { 0x001140,   1, 0x04, 0x00000000 },
+       { 0x0019c4,   1, 0x04, 0x00000000 },
+       { 0x0019c8,   1, 0x04, 0x00001500 },
+       { 0x00135c,   1, 0x04, 0x00000000 },
+       { 0x000f90,   1, 0x04, 0x00000000 },
+       { 0x0019e0,   8, 0x04, 0x00000001 },
+       { 0x0019cc,   1, 0x04, 0x00000001 },
+       { 0x0015b8,   1, 0x04, 0x00000000 },
+       { 0x001a00,   1, 0x04, 0x00001111 },
+       { 0x001a04,   7, 0x04, 0x00000000 },
+       { 0x000d6c,   2, 0x04, 0xffff0000 },
+       { 0x0010f8,   1, 0x04, 0x00001010 },
+       { 0x000d80,   5, 0x04, 0x00000000 },
+       { 0x000da0,   1, 0x04, 0x00000000 },
+       { 0x0007a4,   2, 0x04, 0x00000000 },
+       { 0x001508,   1, 0x04, 0x80000000 },
+       { 0x00150c,   1, 0x04, 0x40000000 },
+       { 0x001668,   1, 0x04, 0x00000000 },
+       { 0x000318,   2, 0x04, 0x00000008 },
+       { 0x000d9c,   1, 0x04, 0x00000001 },
+       { 0x000ddc,   1, 0x04, 0x00000002 },
+       { 0x000374,   1, 0x04, 0x00000000 },
+       { 0x000378,   1, 0x04, 0x00000020 },
+       { 0x0007dc,   1, 0x04, 0x00000000 },
+       { 0x00074c,   1, 0x04, 0x00000055 },
+       { 0x001420,   1, 0x04, 0x00000003 },
+       { 0x0017bc,   2, 0x04, 0x00000000 },
+       { 0x0017c4,   1, 0x04, 0x00000001 },
+       { 0x001008,   1, 0x04, 0x00000008 },
+       { 0x00100c,   1, 0x04, 0x00000040 },
+       { 0x001010,   1, 0x04, 0x0000012c },
+       { 0x000d60,   1, 0x04, 0x00000040 },
+       { 0x00075c,   1, 0x04, 0x00000003 },
+       { 0x001018,   1, 0x04, 0x00000020 },
+       { 0x00101c,   1, 0x04, 0x00000001 },
+       { 0x001020,   1, 0x04, 0x00000020 },
+       { 0x001024,   1, 0x04, 0x00000001 },
+       { 0x001444,   3, 0x04, 0x00000000 },
+       { 0x000360,   1, 0x04, 0x20164010 },
+       { 0x000364,   1, 0x04, 0x00000020 },
+       { 0x000368,   1, 0x04, 0x00000000 },
+       { 0x000de4,   1, 0x04, 0x00000000 },
+       { 0x000204,   1, 0x04, 0x00000006 },
+       { 0x000208,   1, 0x04, 0x00000000 },
+       { 0x0002cc,   2, 0x04, 0x003fffff },
+       { 0x001220,   1, 0x04, 0x00000005 },
+       { 0x000fdc,   1, 0x04, 0x00000000 },
+       { 0x000f98,   1, 0x04, 0x00400008 },
+       { 0x001284,   1, 0x04, 0x08000080 },
+       { 0x001450,   1, 0x04, 0x00400008 },
+       { 0x001454,   1, 0x04, 0x08000080 },
+       { 0x000214,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk40xx[] = {
+       { 0x404004,   8, 0x04, 0x00000000 },
+       { 0x404024,   1, 0x04, 0x0000e000 },
+       { 0x404028,   8, 0x04, 0x00000000 },
+       { 0x4040a8,   8, 0x04, 0x00000000 },
+       { 0x4040c8,   1, 0x04, 0xf800008f },
+       { 0x4040d0,   6, 0x04, 0x00000000 },
+       { 0x4040e8,   1, 0x04, 0x00001000 },
+       { 0x4040f8,   1, 0x04, 0x00000000 },
+       { 0x404100,  10, 0x04, 0x00000000 },
+       { 0x404130,   2, 0x04, 0x00000000 },
+       { 0x404138,   1, 0x04, 0x20000040 },
+       { 0x404150,   1, 0x04, 0x0000002e },
+       { 0x404154,   1, 0x04, 0x00000400 },
+       { 0x404158,   1, 0x04, 0x00000200 },
+       { 0x404164,   1, 0x04, 0x00000055 },
+       { 0x40417c,   2, 0x04, 0x00000000 },
+       { 0x404194,   1, 0x04, 0x01000700 },
+       { 0x4041a0,   4, 0x04, 0x00000000 },
+       { 0x404200,   1, 0x04, 0x0000a197 },
+       { 0x404204,   1, 0x04, 0x0000a1c0 },
+       { 0x404208,   1, 0x04, 0x0000a140 },
+       { 0x40420c,   1, 0x04, 0x0000902d },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk58xx[] = {
+       { 0x405800,   1, 0x04, 0x0f8000bf },
+       { 0x405830,   1, 0x04, 0x02180648 },
+       { 0x405834,   1, 0x04, 0x08000000 },
+       { 0x405838,   1, 0x04, 0x00000000 },
+       { 0x405854,   1, 0x04, 0x00000000 },
+       { 0x405870,   4, 0x04, 0x00000001 },
+       { 0x405a00,   2, 0x04, 0x00000000 },
+       { 0x405a18,   1, 0x04, 0x00000000 },
+       { 0x405a1c,   1, 0x04, 0x000000ff },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk64xx[] = {
+       { 0x4064a8,   1, 0x04, 0x00000000 },
+       { 0x4064ac,   1, 0x04, 0x00003fff },
+       { 0x4064b0,   3, 0x04, 0x00000000 },
+       { 0x4064c0,   1, 0x04, 0x802000f0 },
+       { 0x4064c4,   1, 0x04, 0x0192ffff },
+       { 0x4064c8,   1, 0x04, 0x00c20200 },
+       { 0x4064cc,   9, 0x04, 0x00000000 },
+       { 0x4064fc,   1, 0x04, 0x0000022a },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk78xx[] = {
+       { 0x407804,   1, 0x04, 0x00000063 },
+       { 0x40780c,   1, 0x04, 0x0a418820 },
+       { 0x407810,   1, 0x04, 0x062080e6 },
+       { 0x407814,   1, 0x04, 0x020398a4 },
+       { 0x407818,   1, 0x04, 0x0e629062 },
+       { 0x40781c,   1, 0x04, 0x0a418820 },
+       { 0x407820,   1, 0x04, 0x000000e6 },
+       { 0x4078bc,   1, 0x04, 0x00000103 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk88xx[] = {
+       { 0x408800,   1, 0x04, 0x32802a3c },
+       { 0x408804,   1, 0x04, 0x00000040 },
+       { 0x408808,   1, 0x04, 0x1003e005 },
+       { 0x408840,   1, 0x04, 0x0000000b },
+       { 0x408900,   1, 0x04, 0xb080b801 },
+       { 0x408904,   1, 0x04, 0x62000001 },
+       { 0x408908,   1, 0x04, 0x02c8102f },
+       { 0x408980,   1, 0x04, 0x0000011d },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_gpc_0[] = {
+       { 0x418380,   1, 0x04, 0x00000016 },
+       { 0x418400,   1, 0x04, 0x38005e00 },
+       { 0x418404,   1, 0x04, 0x71e0ffff },
+       { 0x41840c,   1, 0x04, 0x00001008 },
+       { 0x418410,   1, 0x04, 0x0fff0fff },
+       { 0x418414,   1, 0x04, 0x02200fff },
+       { 0x418450,   6, 0x04, 0x00000000 },
+       { 0x418468,   1, 0x04, 0x00000001 },
+       { 0x41846c,   2, 0x04, 0x00000000 },
+       { 0x418600,   1, 0x04, 0x0000007f },
+       { 0x418684,   1, 0x04, 0x0000001f },
+       { 0x418700,   1, 0x04, 0x00000002 },
+       { 0x418704,   2, 0x04, 0x00000080 },
+       { 0x41870c,   2, 0x04, 0x00000000 },
+       { 0x418800,   1, 0x04, 0x7006863a },
+       { 0x418808,   1, 0x04, 0x00000000 },
+       { 0x41880c,   1, 0x04, 0x00000030 },
+       { 0x418810,   1, 0x04, 0x00000000 },
+       { 0x418828,   1, 0x04, 0x00000044 },
+       { 0x418830,   1, 0x04, 0x10000001 },
+       { 0x4188d8,   1, 0x04, 0x00000008 },
+       { 0x4188e0,   1, 0x04, 0x01000000 },
+       { 0x4188e8,   5, 0x04, 0x00000000 },
+       { 0x4188fc,   1, 0x04, 0x20100058 },
+       { 0x41891c,   1, 0x04, 0x00ff00ff },
+       { 0x418924,   1, 0x04, 0x00000000 },
+       { 0x418928,   1, 0x04, 0x00ffff00 },
+       { 0x41892c,   1, 0x04, 0x0000ff00 },
+       { 0x418b00,   1, 0x04, 0x0000001e },
+       { 0x418b08,   1, 0x04, 0x0a418820 },
+       { 0x418b0c,   1, 0x04, 0x062080e6 },
+       { 0x418b10,   1, 0x04, 0x020398a4 },
+       { 0x418b14,   1, 0x04, 0x0e629062 },
+       { 0x418b18,   1, 0x04, 0x0a418820 },
+       { 0x418b1c,   1, 0x04, 0x000000e6 },
+       { 0x418bb8,   1, 0x04, 0x00000103 },
+       { 0x418c08,   1, 0x04, 0x00000001 },
+       { 0x418c10,   8, 0x04, 0x00000000 },
+       { 0x418c40,   1, 0x04, 0xffffffff },
+       { 0x418c6c,   1, 0x04, 0x00000001 },
+       { 0x418c80,   1, 0x04, 0x2020000c },
+       { 0x418c8c,   1, 0x04, 0x00000001 },
+       { 0x418d24,   1, 0x04, 0x00000000 },
+       { 0x419000,   1, 0x04, 0x00000780 },
+       { 0x419004,   2, 0x04, 0x00000000 },
+       { 0x419014,   1, 0x04, 0x00000004 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_tpc[] = {
+       { 0x419848,   1, 0x04, 0x00000000 },
+       { 0x419864,   1, 0x04, 0x00000129 },
+       { 0x419888,   1, 0x04, 0x00000000 },
+       { 0x419a00,   1, 0x04, 0x000100f0 },
+       { 0x419a04,   1, 0x04, 0x00000001 },
+       { 0x419a08,   1, 0x04, 0x00000421 },
+       { 0x419a0c,   1, 0x04, 0x00120000 },
+       { 0x419a10,   1, 0x04, 0x00000000 },
+       { 0x419a14,   1, 0x04, 0x00000200 },
+       { 0x419a1c,   1, 0x04, 0x0000c000 },
+       { 0x419a20,   1, 0x04, 0x00000800 },
+       { 0x419a30,   1, 0x04, 0x00000001 },
+       { 0x419ac4,   1, 0x04, 0x0037f440 },
+       { 0x419c00,   1, 0x04, 0x0000001a },
+       { 0x419c04,   1, 0x04, 0x80000006 },
+       { 0x419c08,   1, 0x04, 0x00000002 },
+       { 0x419c20,   1, 0x04, 0x00000000 },
+       { 0x419c24,   1, 0x04, 0x00084210 },
+       { 0x419c28,   1, 0x04, 0x3efbefbe },
+       { 0x419ce8,   1, 0x04, 0x00000000 },
+       { 0x419cf4,   1, 0x04, 0x00000203 },
+       { 0x419e04,   1, 0x04, 0x00000000 },
+       { 0x419e08,   1, 0x04, 0x0000001d },
+       { 0x419e0c,   1, 0x04, 0x00000000 },
+       { 0x419e10,   1, 0x04, 0x00001c02 },
+       { 0x419e44,   1, 0x04, 0x0013eff2 },
+       { 0x419e48,   1, 0x04, 0x00000000 },
+       { 0x419e4c,   1, 0x04, 0x0000007f },
+       { 0x419e50,   2, 0x04, 0x00000000 },
+       { 0x419e58,   1, 0x04, 0x00000001 },
+       { 0x419e5c,   3, 0x04, 0x00000000 },
+       { 0x419e68,   1, 0x04, 0x00000002 },
+       { 0x419e6c,  12, 0x04, 0x00000000 },
+       { 0x419eac,   1, 0x04, 0x00001f8f },
+       { 0x419eb0,   1, 0x04, 0x0db00da0 },
+       { 0x419eb8,   1, 0x04, 0x00000000 },
+       { 0x419ec8,   1, 0x04, 0x0001304f },
+       { 0x419f30,   4, 0x04, 0x00000000 },
+       { 0x419f40,   1, 0x04, 0x00000018 },
+       { 0x419f44,   3, 0x04, 0x00000000 },
+       { 0x419f58,   1, 0x04, 0x00000020 },
+       { 0x419f70,   1, 0x04, 0x00000000 },
+       { 0x419f78,   1, 0x04, 0x000001eb },
+       { 0x419f7c,   1, 0x04, 0x00000404 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_grctx_init_unk[] = {
+       { 0x41be24,   1, 0x04, 0x00000006 },
+       { 0x41bec0,   1, 0x04, 0x10000000 },
+       { 0x41bec4,   1, 0x04, 0x00037f7f },
+       { 0x41bee4,   1, 0x04, 0x00000000 },
+       { 0x41bef0,   1, 0x04, 0x000003ff },
+       { 0x41bf00,   1, 0x04, 0x0a418820 },
+       { 0x41bf04,   1, 0x04, 0x062080e6 },
+       { 0x41bf08,   1, 0x04, 0x020398a4 },
+       { 0x41bf0c,   1, 0x04, 0x0e629062 },
+       { 0x41bf10,   1, 0x04, 0x0a418820 },
+       { 0x41bf14,   1, 0x04, 0x000000e6 },
+       { 0x41bfd0,   1, 0x04, 0x00900103 },
+       { 0x41bfe0,   1, 0x04, 0x00400001 },
+       { 0x41bfe4,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static void
+nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+{
+       u32 magic[GPC_MAX][2];
+       u32 offset;
+       int gpc;
+
+       mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
+       mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
+       mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
+       mmio_list(0x40800c, 0x00000000,  8, 1);
+       mmio_list(0x408010, 0x80000000,  0, 0);
+       mmio_list(0x419004, 0x00000000,  8, 1);
+       mmio_list(0x419008, 0x00000000,  0, 0);
+       mmio_list(0x408004, 0x00000000,  8, 0);
+       mmio_list(0x408008, 0x80000030,  0, 0);
+       mmio_list(0x418808, 0x00000000,  8, 0);
+       mmio_list(0x41880c, 0x80000030,  0, 0);
+       mmio_list(0x418810, 0x80000000, 12, 2);
+       mmio_list(0x419848, 0x10000000, 12, 2);
+
+       mmio_list(0x405830, 0x02180648,  0, 0);
+       mmio_list(0x4064c4, 0x0192ffff,  0, 0);
+
+       for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
+               u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
+               u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
+               magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
+               magic[gpc][1]  = 0x00000000 | (magic1 << 16);
+               offset += 0x0324 * priv->tpc_nr[gpc];
+       }
+
+       for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+               mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
+               mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
+               offset += 0x07ff * priv->tpc_nr[gpc];
+       }
+
+       mmio_list(0x17e91c, 0x0b040a0b, 0, 0);
+       mmio_list(0x17e920, 0x00090d08, 0, 0);
+}
+
+static struct nvc0_graph_init *
+nv108_grctx_init_hub[] = {
+       nvc0_grctx_init_base,
+       nv108_grctx_init_unk40xx,
+       nvf0_grctx_init_unk44xx,
+       nve4_grctx_init_unk46xx,
+       nve4_grctx_init_unk47xx,
+       nv108_grctx_init_unk58xx,
+       nvf0_grctx_init_unk5bxx,
+       nvf0_grctx_init_unk60xx,
+       nv108_grctx_init_unk64xx,
+       nv108_grctx_init_unk78xx,
+       nve4_grctx_init_unk80xx,
+       nv108_grctx_init_unk88xx,
+       NULL
+};
+
+struct nvc0_graph_init *
+nv108_grctx_init_gpc[] = {
+       nv108_grctx_init_gpc_0,
+       nvc0_grctx_init_gpc_1,
+       nv108_grctx_init_tpc,
+       nv108_grctx_init_unk,
+       NULL
+};
+
+struct nvc0_graph_init
+nv108_grctx_init_mthd_magic[] = {
+       { 0x3410, 1, 0x04, 0x8e0e2006 },
+       { 0x3414, 1, 0x04, 0x00000038 },
+       {}
+};
+
+static struct nvc0_graph_mthd
+nv108_grctx_init_mthd[] = {
+       { 0xa197, nv108_grctx_init_a197, },
+       { 0x902d, nvc0_grctx_init_902d, },
+       { 0x902d, nv108_grctx_init_mthd_magic, },
+       {}
+};
+
+struct nouveau_oclass *
+nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
+       .base.handle = NV_ENGCTX(GR, 0x08),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_context_ctor,
+               .dtor = nvc0_graph_context_dtor,
+               .init = _nouveau_graph_context_init,
+               .fini = _nouveau_graph_context_fini,
+               .rd32 = _nouveau_graph_context_rd32,
+               .wr32 = _nouveau_graph_context_wr32,
+       },
+       .main = nve4_grctx_generate_main,
+       .mods = nv108_grctx_generate_mods,
+       .unkn = nve4_grctx_generate_unkn,
+       .hub  = nv108_grctx_init_hub,
+       .gpc  = nv108_grctx_init_gpc,
+       .icmd = nv108_grctx_init_icmd,
+       .mthd = nv108_grctx_init_mthd,
+}.base;
index dcb2ebb8c29d93ac211bebd3d79f6224b48604b8..44012c3da53832c325e2286bafcc191208d9e946 100644 (file)
@@ -50,7 +50,7 @@ nvf0_grctx_init_unk40xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk44xx[] = {
        { 0x404404,  12, 0x04, 0x00000000 },
        { 0x404438,   1, 0x04, 0x00000000 },
@@ -62,7 +62,7 @@ nvf0_grctx_init_unk44xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk5bxx[] = {
        { 0x405b00,   1, 0x04, 0x00000000 },
        { 0x405b10,   1, 0x04, 0x00001000 },
@@ -70,7 +70,7 @@ nvf0_grctx_init_unk5bxx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_grctx_init_unk60xx[] = {
        { 0x406020,   1, 0x04, 0x034103c1 },
        { 0x406028,   4, 0x04, 0x00000001 },
@@ -286,7 +286,6 @@ nvf0_grctx_init_hub[] = {
        nvf0_grctx_init_unk64xx,
        nve4_grctx_init_unk80xx,
        nvf0_grctx_init_unk88xx,
-       nvd9_grctx_init_rop,
        NULL
 };
 
index 5d24b6de16cce636e3db922c7c81d09018d9f2cc..e148961b8075e96be5ab2f1b86ebc7170676db4e 100644 (file)
@@ -38,7 +38,7 @@ queue_put:
        cmpu b32 $r8 $r9
        bra ne #queue_put_next
                mov $r15 E_CMD_OVERFLOW
-               call #error
+               call(error)
                ret
 
        // store cmd/data on queue
@@ -92,18 +92,16 @@ queue_get_done:
 // Out: $r15 value
 //
 nv_rd32:
-       mov $r11 0x728
-       shl b32 $r11 6
        mov b32 $r12 $r14
        bset $r12 31                    // MMIO_CTRL_PENDING
-       iowr I[$r11 + 0x000] $r12       // MMIO_CTRL
+       nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)
        nv_rd32_wait:
-               iord $r12 I[$r11 + 0x000]
+               nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)
                xbit $r12 $r12 31
                bra ne #nv_rd32_wait
        mov $r10 6                      // DONE_MMIO_RD
-       call #wait_doneo
-       iord $r15 I[$r11 + 0x100]       // MMIO_RDVAL
+       call(wait_doneo)
+       nv_iord($r15, NV_PGRAPH_FECS_MMIO_RDVAL, 0)
        ret
 
 // nv_wr32 - write 32-bit value to nv register
@@ -112,37 +110,17 @@ nv_rd32:
 //      $r15 value
 //
 nv_wr32:
-       mov $r11 0x728
-       shl b32 $r11 6
-       iowr I[$r11 + 0x200] $r15       // MMIO_WRVAL
+       nv_iowr(NV_PGRAPH_FECS_MMIO_WRVAL, 0, $r15)
        mov b32 $r12 $r14
        bset $r12 31                    // MMIO_CTRL_PENDING
        bset $r12 30                    // MMIO_CTRL_WRITE
-       iowr I[$r11 + 0x000] $r12       // MMIO_CTRL
+       nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)
        nv_wr32_wait:
-               iord $r12 I[$r11 + 0x000]
+               nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)
                xbit $r12 $r12 31
                bra ne #nv_wr32_wait
        ret
 
-// (re)set watchdog timer
-//
-// In : $r15 timeout
-//
-watchdog_reset:
-       mov $r8 0x430
-       shl b32 $r8 6
-       bset $r15 31
-       iowr I[$r8 + 0x000] $r15
-       ret
-
-// clear watchdog timer
-watchdog_clear:
-       mov $r8 0x430
-       shl b32 $r8 6
-       iowr I[$r8 + 0x000] $r0
-       ret
-
 // wait_donez - wait on FUC_DONE bit to become clear
 //
 // In : $r10 bit to wait on
@@ -163,13 +141,9 @@ wait_donez:
 //
 wait_doneo:
        trace_set(T_WAIT);
-       mov $r8 0x818
-       shl b32 $r8 6
-       iowr I[$r8 + 0x000] $r10
+       nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(6), 0, $r10)
        wait_doneo_e:
-               mov $r8 0x400
-               shl b32 $r8 6
-               iord $r8 I[$r8 + 0x000]
+               nv_iord($r8, NV_PGRAPH_FECS_SIGNAL, 0)
                xbit $r8 $r8 $r10
                bra e #wait_doneo_e
        trace_clr(T_WAIT)
@@ -209,21 +183,18 @@ mmctx_size:
 //
 mmctx_xfer:
        trace_set(T_MMCTX)
-       mov $r8 0x710
-       shl b32 $r8 6
        clear b32 $r9
        or $r11 $r11
        bra e #mmctx_base_disabled
-               iowr I[$r8 + 0x000] $r11        // MMCTX_BASE
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_BASE, 0, $r11)
                bset $r9 0                      // BASE_EN
        mmctx_base_disabled:
        or $r14 $r14
        bra e #mmctx_multi_disabled
-               iowr I[$r8 + 0x200] $r14        // MMCTX_MULTI_STRIDE
-               iowr I[$r8 + 0x300] $r15        // MMCTX_MULTI_MASK
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE, 0, $r14)
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_MASK, 0, $r15)
                bset $r9 1                      // MULTI_EN
        mmctx_multi_disabled:
-       add b32 $r8 0x100
 
        xbit $r11 $r10 0
        shl b32 $r11 16                 // DIR
@@ -231,20 +202,20 @@ mmctx_xfer:
        xbit $r14 $r10 1
        shl b32 $r14 17
        or $r11 $r14                    // START_TRIGGER
-       iowr I[$r8 + 0x000] $r11        // MMCTX_CTRL
+       nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)
 
        // loop over the mmio list, and send requests to the hw
        mmctx_exec_loop:
                // wait for space in mmctx queue
                mmctx_wait_free:
-                       iord $r14 I[$r8 + 0x000] // MMCTX_CTRL
+                       nv_iord($r14, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
                        and $r14 0x1f
                        bra e #mmctx_wait_free
 
                // queue up an entry
                ld b32 $r14 D[$r12]
                or $r14 $r9
-               iowr I[$r8 + 0x300] $r14
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_QUEUE, 0, $r14)
                add b32 $r12 4
                cmpu b32 $r12 $r13
                bra ne #mmctx_exec_loop
@@ -253,22 +224,22 @@ mmctx_xfer:
        bra ne #mmctx_stop
                // wait for queue to empty
                mmctx_fini_wait:
-                       iord $r11 I[$r8 + 0x000]        // MMCTX_CTRL
+                       nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
                        and $r11 0x1f
                        cmpu b32 $r11 0x10
                        bra ne #mmctx_fini_wait
                mov $r10 2                              // DONE_MMCTX
-               call #wait_donez
+               call(wait_donez)
                bra #mmctx_done
        mmctx_stop:
                xbit $r11 $r10 0
                shl b32 $r11 16                 // DIR
                bset $r11 12                    // QLIMIT = 0x10
                bset $r11 18                    // STOP_TRIGGER
-               iowr I[$r8 + 0x000] $r11        // MMCTX_CTRL
+               nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)
                mmctx_stop_wait:
                        // wait for STOP_TRIGGER to clear
-                       iord $r11 I[$r8 + 0x000] // MMCTX_CTRL
+                       nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)
                        xbit $r11 $r11 18
                        bra ne #mmctx_stop_wait
        mmctx_done:
@@ -280,28 +251,24 @@ mmctx_xfer:
 strand_wait:
        push $r10
        mov $r10 2
-       call #wait_donez
+       call(wait_donez)
        pop $r10
        ret
 
 // unknown - call before issuing strand commands
 //
 strand_pre:
-       mov $r8 0x4afc
-       sethi $r8 0x20000
-       mov $r9 0xc
-       iowr I[$r8] $r9
-       call #strand_wait
+       mov $r9 NV_PGRAPH_FECS_STRAND_CMD_ENABLE
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9)
+       call(strand_wait)
        ret
 
 // unknown - call after issuing strand commands
 //
 strand_post:
-       mov $r8 0x4afc
-       sethi $r8 0x20000
-       mov $r9 0xd
-       iowr I[$r8] $r9
-       call #strand_wait
+       mov $r9 NV_PGRAPH_FECS_STRAND_CMD_DISABLE
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9)
+       call(strand_wait)
        ret
 
 // Selects strand set?!
@@ -309,18 +276,14 @@ strand_post:
 // In: $r14 id
 //
 strand_set:
-       mov $r10 0x4ffc
-       sethi $r10 0x20000
-       sub b32 $r11 $r10 0x500
        mov $r12 0xf
-       iowr I[$r10 + 0x000] $r12               // 0x93c = 0xf
-       mov $r12 0xb
-       iowr I[$r11 + 0x000] $r12               // 0x928 = 0xb
-       call #strand_wait
-       iowr I[$r10 + 0x000] $r14               // 0x93c = <id>
-       mov $r12 0xa
-       iowr I[$r11 + 0x000] $r12               // 0x928 = 0xa
-       call #strand_wait
+       nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r12)
+       mov $r12 NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+       nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r14)
+       mov $r12 NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+       call(strand_wait)
        ret
 
 // Initialise strand context data
@@ -332,30 +295,27 @@ strand_set:
 //
 strand_ctx_init:
        trace_set(T_STRINIT)
-       call #strand_pre
+       call(strand_pre)
        mov $r14 3
-       call #strand_set
-       mov $r10 0x46fc
-       sethi $r10 0x20000
-       add b32 $r11 $r10 0x400
-       iowr I[$r10 + 0x100] $r0        // STRAND_FIRST_GENE = 0
-       mov $r12 1
-       iowr I[$r11 + 0x000] $r12       // STRAND_CMD = LATCH_FIRST_GENE
-       call #strand_wait
+       call(strand_set)
+
+       clear b32 $r12
+       nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r12)
+       mov $r12 NV_PGRAPH_FECS_STRAND_CMD_SEEK
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+       call(strand_wait)
        sub b32 $r12 $r0 1
-       iowr I[$r10 + 0x000] $r12       // STRAND_GENE_CNT = 0xffffffff
-       mov $r12 2
-       iowr I[$r11 + 0x000] $r12       // STRAND_CMD = LATCH_GENE_CNT
-       call #strand_wait
-       call #strand_post
+       nv_iowr(NV_PGRAPH_FECS_STRAND_DATA, 0x3f, $r12)
+       mov $r12 NV_PGRAPH_FECS_STRAND_CMD_GET_INFO
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12)
+       call(strand_wait)
+       call(strand_post)
 
        // read the size of each strand, poke the context offset of
        // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry
        // about it later then.
-       mov $r8 0x880
-       shl b32 $r8 6
-       iord $r9 I[$r8 + 0x000]         // STRANDS
-       add b32 $r8 0x2200
+       nv_mkio($r8, NV_PGRAPH_FECS_STRAND_SAVE_SWBASE, 0x00)
+       nv_iord($r9, NV_PGRAPH_FECS_STRANDS_CNT, 0x00)
        shr b32 $r14 $r15 8
        ctx_init_strand_loop:
                iowr I[$r8 + 0x000] $r14        // STRAND_SAVE_SWBASE
index 5547c1b3f4f29414a1334e2a7d5cae9f7452e998..96cbcea3b2c96aa71f2c7ef3d59b3d3184a67e17 100644 (file)
@@ -58,12 +58,9 @@ mmio_list_base:
 //
 error:
        push $r14
-       mov $r14 -0x67ec        // 0x9814
-       sethi $r14 0x400000
-       call #nv_wr32           // HUB_CTXCTL_CC_SCRATCH[5] = error code
-       add b32 $r14 0x41c
+       nv_wr32(NV_PGRAPH_FECS_CC_SCRATCH_VAL(5), $r15)
        mov $r15 1
-       call #nv_wr32           // HUB_CTXCTL_INTR_UP_SET
+       nv_wr32(NV_PGRAPH_FECS_INTR_UP_SET, $r15)
        pop $r14
        ret
 
@@ -84,46 +81,40 @@ init:
        mov $sp $r0
 
        // enable fifo access
-       mov $r1 0x1200
-       mov $r2 2
-       iowr I[$r1 + 0x000] $r2         // FIFO_ENABLE
+       mov $r2 NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_ACCESS, 0, $r2)
 
        // setup i0 handler, and route all interrupts to it
        mov $r1 #ih
        mov $iv0 $r1
-       mov $r1 0x400
-       iowr I[$r1 + 0x300] $r0         // INTR_DISPATCH
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE, 0, $r0)
 
        // enable fifo interrupt
-       mov $r2 4
-       iowr I[$r1 + 0x000] $r2         // INTR_EN_SET
+       mov $r2 NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET, 0, $r2)
 
        // enable interrupts
        bset $flags ie0
 
        // figure out which GPC we are, and how many TPCs we have
-       mov $r1 0x608
-       shl b32 $r1 6
-       iord $r2 I[$r1 + 0x000]         // UNITS
+       nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_UNITS, 0)
        mov $r3 1
        and $r2 0x1f
        shl b32 $r3 $r2
        sub b32 $r3 1
        st b32 D[$r0 + #tpc_count] $r2
        st b32 D[$r0 + #tpc_mask] $r3
-       add b32 $r1 0x400
-       iord $r2 I[$r1 + 0x000]         // MYINDEX
+       nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_MYINDEX, 0)
        st b32 D[$r0 + #gpc_id] $r2
 
 #if NV_PGRAPH_GPCX_UNK__SIZE > 0
        // figure out which, and how many, UNKs are actually present
-       mov $r14 0x0c30
-       sethi $r14 0x500000
+       imm32($r14, 0x500c30)
        clear b32 $r2
        clear b32 $r3
        clear b32 $r4
        init_unk_loop:
-               call #nv_rd32
+               call(nv_rd32)
                cmp b32 $r15 0
                bra z #init_unk_next
                        mov $r15 1
@@ -146,23 +137,21 @@ init:
 
        // set mmctx base addresses now so we don't have to do it later,
        // they don't currently ever change
-       mov $r4 0x700
-       shl b32 $r4 6
        shr b32 $r5 $r2 8
-       iowr I[$r4 + 0x000] $r5         // MMCTX_SAVE_SWBASE
-       iowr I[$r4 + 0x100] $r5         // MMCTX_LOAD_SWBASE
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE, 0, $r5)
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE, 0, $r5)
 
        // calculate GPC mmio context size
        ld b32 $r14 D[$r0 + #gpc_mmio_list_head]
        ld b32 $r15 D[$r0 + #gpc_mmio_list_tail]
-       call #mmctx_size
+       call(mmctx_size)
        add b32 $r2 $r15
        add b32 $r3 $r15
 
        // calculate per-TPC mmio context size
        ld b32 $r14 D[$r0 + #tpc_mmio_list_head]
        ld b32 $r15 D[$r0 + #tpc_mmio_list_tail]
-       call #mmctx_size
+       call(mmctx_size)
        ld b32 $r14 D[$r0 + #tpc_count]
        mulu $r14 $r15
        add b32 $r2 $r14
@@ -172,7 +161,7 @@ init:
        // calculate per-UNK mmio context size
        ld b32 $r14 D[$r0 + #unk_mmio_list_head]
        ld b32 $r15 D[$r0 + #unk_mmio_list_tail]
-       call #mmctx_size
+       call(mmctx_size)
        ld b32 $r14 D[$r0 + #unk_count]
        mulu $r14 $r15
        add b32 $r2 $r14
@@ -180,9 +169,8 @@ init:
 #endif
 
        // round up base/size to 256 byte boundary (for strand SWBASE)
-       add b32 $r4 0x1300
        shr b32 $r3 2
-       iowr I[$r4 + 0x000] $r3         // MMCTX_LOAD_COUNT, wtf for?!?
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT, 0, $r3) // wtf for?!
        shr b32 $r2 8
        shr b32 $r3 6
        add b32 $r2 1
@@ -192,7 +180,7 @@ init:
 
        // calculate size of strand context data
        mov b32 $r15 $r2
-       call #strand_ctx_init
+       call(strand_ctx_init)
        add b32 $r3 $r15
 
        // save context size, and tell HUB we're done
@@ -208,7 +196,7 @@ main:
        bset $flags $p0
        sleep $p0
        mov $r13 #cmd_queue
-       call #queue_get
+       call(queue_get)
        bra $p1 #main
 
        // 0x0000-0x0003 are all context transfers
@@ -224,13 +212,13 @@ main:
                or $r1 $r14
                mov $flags $r1
                // transfer context data
-               call #ctx_xfer
+               call(ctx_xfer)
                bra #main
 
        main_not_ctx_xfer:
        shl b32 $r15 $r14 16
        or $r15 E_BAD_COMMAND
-       call #error
+       call(error)
        bra #main
 
 // interrupt handler
@@ -247,22 +235,20 @@ ih:
        clear b32 $r0
 
        // incoming fifo command?
-       iord $r10 I[$r0 + 0x200]        // INTR
-       and $r11 $r10 0x00000004
+       nv_iord($r10, NV_PGRAPH_GPCX_GPCCS_INTR, 0)
+       and $r11 $r10 NV_PGRAPH_GPCX_GPCCS_INTR_FIFO
        bra e #ih_no_fifo
                // queue incoming fifo command for later processing
-               mov $r11 0x1900
                mov $r13 #cmd_queue
-               iord $r14 I[$r11 + 0x100]       // FIFO_CMD
-               iord $r15 I[$r11 + 0x000]       // FIFO_DATA
-               call #queue_put
-               add b32 $r11 0x400
+               nv_iord($r14, NV_PGRAPH_GPCX_GPCCS_FIFO_CMD, 0)
+               nv_iord($r15, NV_PGRAPH_GPCX_GPCCS_FIFO_DATA, 0)
+               call(queue_put)
                mov $r14 1
-               iowr I[$r11 + 0x000] $r14       // FIFO_ACK
+               nv_iowr(NV_PGRAPH_GPCX_GPCCS_FIFO_ACK, 0, $r14)
 
        // ack, and wake up main()
        ih_no_fifo:
-       iowr I[$r0 + 0x100] $r10        // INTR_ACK
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ACK, 0, $r10)
 
        pop $r15
        pop $r14
@@ -283,9 +269,7 @@ hub_barrier_done:
        mov $r15 1
        ld b32 $r14 D[$r0 + #gpc_id]
        shl b32 $r15 $r14
-       mov $r14 -0x6be8        // 0x409418 - HUB_BAR_SET
-       sethi $r14 0x400000
-       call #nv_wr32
+       nv_wr32(0x409418, $r15) // 0x409418 - HUB_BAR_SET
        ret
 
 // Disables various things, waits a bit, and re-enables them..
@@ -295,16 +279,15 @@ hub_barrier_done:
 // funny things happen.
 //
 ctx_redswitch:
-       mov $r14 0x614
-       shl b32 $r14 6
-       mov $r15 0x020
-       iowr I[$r14] $r15       // GPC_RED_SWITCH = POWER
-       mov $r15 8
+       mov $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)
+       mov $r14 8
        ctx_redswitch_delay:
-               sub b32 $r15 1
+               sub b32 $r14 1
                bra ne #ctx_redswitch_delay
-       mov $r15 0xa20
-       iowr I[$r14] $r15       // GPC_RED_SWITCH = UNK11, ENABLE, POWER
+       or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11
+       or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)
        ret
 
 // Transfer GPC context data between GPU and storage area
@@ -317,46 +300,37 @@ ctx_redswitch:
 //
 ctx_xfer:
        // set context base address
-       mov $r1 0xa04
-       shl b32 $r1 6
-       iowr I[$r1 + 0x000] $r15// MEM_BASE
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_MEM_BASE, 0, $r15)
        bra not $p1 #ctx_xfer_not_load
-               call #ctx_redswitch
+               call(ctx_redswitch)
        ctx_xfer_not_load:
 
        // strands
-       mov $r1 0x4afc
-       sethi $r1 0x20000
-       mov $r2 0xc
-       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0c
-       call #strand_wait
-       mov $r2 0x47fc
-       sethi $r2 0x20000
-       iowr I[$r2] $r0         // STRAND_FIRST_GENE(0x3f) = 0x00
-       xbit $r2 $flags $p1
-       add b32 $r2 3
-       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+       call(strand_pre)
+       clear b32 $r2
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT, 0x3f, $r2)
+       xbit $r2 $flags $p1     // SAVE/LOAD
+       add b32 $r2 NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE
+       nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_CMD, 0x3f, $r2)
 
        // mmio context
        xbit $r10 $flags $p1    // direction
        or $r10 2               // first
-       mov $r11 0x0000
-       sethi $r11 0x500000
+       imm32($r11,0x500000)
        ld b32 $r12 D[$r0 + #gpc_id]
        shl b32 $r12 15
        add b32 $r11 $r12       // base = NV_PGRAPH_GPCn
        ld b32 $r12 D[$r0 + #gpc_mmio_list_head]
        ld b32 $r13 D[$r0 + #gpc_mmio_list_tail]
        mov $r14 0              // not multi
-       call #mmctx_xfer
+       call(mmctx_xfer)
 
        // per-TPC mmio context
        xbit $r10 $flags $p1    // direction
 #if !NV_PGRAPH_GPCX_UNK__SIZE
        or $r10 4               // last
 #endif
-       mov $r11 0x4000
-       sethi $r11 0x500000     // base = NV_PGRAPH_GPC0_TPC0
+       imm32($r11, 0x504000)
        ld b32 $r12 D[$r0 + #gpc_id]
        shl b32 $r12 15
        add b32 $r11 $r12       // base = NV_PGRAPH_GPCn_TPC0
@@ -364,14 +338,13 @@ ctx_xfer:
        ld b32 $r13 D[$r0 + #tpc_mmio_list_tail]
        ld b32 $r15 D[$r0 + #tpc_mask]
        mov $r14 0x800          // stride = 0x800
-       call #mmctx_xfer
+       call(mmctx_xfer)
 
 #if NV_PGRAPH_GPCX_UNK__SIZE > 0
        // per-UNK mmio context
        xbit $r10 $flags $p1    // direction
        or $r10 4               // last
-       mov $r11 0x3000
-       sethi $r11 0x500000     // base = NV_PGRAPH_GPC0_UNK0
+       imm32($r11, 0x503000)
        ld b32 $r12 D[$r0 + #gpc_id]
        shl b32 $r12 15
        add b32 $r11 $r12       // base = NV_PGRAPH_GPCn_UNK0
@@ -379,11 +352,11 @@ ctx_xfer:
        ld b32 $r13 D[$r0 + #unk_mmio_list_tail]
        ld b32 $r15 D[$r0 + #unk_mask]
        mov $r14 0x200          // stride = 0x200
-       call #mmctx_xfer
+       call(mmctx_xfer)
 #endif
 
        // wait for strands to finish
-       call #strand_wait
+       call(strand_wait)
 
        // if load, or a save without a load following, do some
        // unknown stuff that's done after finishing a block of
@@ -391,14 +364,10 @@ ctx_xfer:
        bra $p1 #ctx_xfer_post
        bra not $p2 #ctx_xfer_done
        ctx_xfer_post:
-               mov $r1 0x4afc
-               sethi $r1 0x20000
-               mov $r2 0xd
-               iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0d
-               call #strand_wait
+               call(strand_post)
 
        // mark completion in HUB's barrier
        ctx_xfer_done:
-       call #hub_barrier_done
+       call(hub_barrier_done)
        ret
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5
new file mode 100644 (file)
index 0000000..bd30262
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#define NV_PGRAPH_GPCX_UNK__SIZE                                     0x00000001
+
+#define CHIPSET GK208
+#include "macros.fuc"
+
+.section #nv108_grgpc_data
+#define INCLUDE_DATA
+#include "com.fuc"
+#include "gpc.fuc"
+#undef INCLUDE_DATA
+
+.section #nv108_grgpc_code
+#define INCLUDE_CODE
+bra #init
+#include "com.fuc"
+#include "gpc.fuc"
+.align 256
+#undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h
new file mode 100644 (file)
index 0000000..27dc128
--- /dev/null
@@ -0,0 +1,473 @@
+uint32_t nv108_grgpc_data[] = {
+/* 0x0000: gpc_mmio_list_head */
+       0x0000006c,
+/* 0x0004: gpc_mmio_list_tail */
+/* 0x0004: tpc_mmio_list_head */
+       0x0000006c,
+/* 0x0008: tpc_mmio_list_tail */
+/* 0x0008: unk_mmio_list_head */
+       0x0000006c,
+/* 0x000c: unk_mmio_list_tail */
+       0x0000006c,
+/* 0x0010: gpc_id */
+       0x00000000,
+/* 0x0014: tpc_count */
+       0x00000000,
+/* 0x0018: tpc_mask */
+       0x00000000,
+/* 0x001c: unk_count */
+       0x00000000,
+/* 0x0020: unk_mask */
+       0x00000000,
+/* 0x0024: cmd_queue */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
+
+uint32_t nv108_grgpc_code[] = {
+       0x03140ef5,
+/* 0x0004: queue_put */
+       0x9800d898,
+       0x86f001d9,
+       0xf489a408,
+       0x020f0b1b,
+       0x0002f87e,
+/* 0x001a: queue_put_next */
+       0x98c400f8,
+       0x0384b607,
+       0xb6008dbb,
+       0x8eb50880,
+       0x018fb500,
+       0xf00190b6,
+       0xd9b50f94,
+/* 0x0037: queue_get */
+       0xf400f801,
+       0xd8980131,
+       0x01d99800,
+       0x0bf489a4,
+       0x0789c421,
+       0xbb0394b6,
+       0x90b6009d,
+       0x009e9808,
+       0xb6019f98,
+       0x84f00180,
+       0x00d8b50f,
+/* 0x0063: queue_get_done */
+       0xf80132f4,
+/* 0x0065: nv_rd32 */
+       0xf0ecb200,
+       0x00801fc9,
+       0x0cf601ca,
+/* 0x0073: nv_rd32_wait */
+       0x8c04bd00,
+       0xcf01ca00,
+       0xccc800cc,
+       0xf61bf41f,
+       0xec7e060a,
+       0x008f0000,
+       0xffcf01cb,
+/* 0x008f: nv_wr32 */
+       0x8000f800,
+       0xf601cc00,
+       0x04bd000f,
+       0xc9f0ecb2,
+       0x1ec9f01f,
+       0x01ca0080,
+       0xbd000cf6,
+/* 0x00a9: nv_wr32_wait */
+       0xca008c04,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f61b,
+/* 0x00b8: wait_donez */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x00cf: wait_donez_ne */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf61bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x00ec: wait_doneo */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x0103: wait_doneo_e */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf60bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x0120: mmctx_size */
+/* 0x0122: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0x1bf4efa4,
+       0xf89fb2ec,
+/* 0x013d: mmctx_xfer */
+       0xf094bd00,
+       0x00800199,
+       0x09f60237,
+       0xbd04bd00,
+       0x05bbfd94,
+       0x800f0bf4,
+       0xf601c400,
+       0x04bd000b,
+/* 0x015f: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0xc6008018,
+       0x000ef601,
+       0x008004bd,
+       0x0ff601c7,
+       0xf004bd00,
+/* 0x017a: mmctx_multi_disabled */
+       0xabc80199,
+       0x10b4b600,
+       0xc80cb9f0,
+       0xe4b601ae,
+       0x05befd11,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x0195: mmctx_exec_loop */
+/* 0x0195: mmctx_wait_free */
+       0xc5008e04,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f60b,
+       0x05e9fd00,
+       0x01c80080,
+       0xbd000ef6,
+       0x04c0b604,
+       0x1bf4cda4,
+       0x02abc8df,
+/* 0x01bf: mmctx_fini_wait */
+       0x8b1c1bf4,
+       0xcf01c500,
+       0xb4f000bb,
+       0x10b4b01f,
+       0x0af31bf4,
+       0x00b87e02,
+       0x250ef400,
+/* 0x01d8: mmctx_stop */
+       0xb600abc8,
+       0xb9f010b4,
+       0x12b9f00c,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x01ed: mmctx_stop_wait */
+       0xc5008b04,
+       0x00bbcf01,
+       0xf412bbc8,
+/* 0x01fa: mmctx_done */
+       0x94bdf61b,
+       0x800199f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x020a: strand_wait */
+       0xa0f900f8,
+       0xb87e020a,
+       0xa0fc0000,
+/* 0x0216: strand_pre */
+       0x0c0900f8,
+       0x024afc80,
+       0xbd0009f6,
+       0x020a7e04,
+/* 0x0227: strand_post */
+       0x0900f800,
+       0x4afc800d,
+       0x0009f602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0238: strand_set */
+       0xfc800f0c,
+       0x0cf6024f,
+       0x0c04bd00,
+       0x4afc800b,
+       0x000cf602,
+       0xfc8004bd,
+       0x0ef6024f,
+       0x0c04bd00,
+       0x4afc800a,
+       0x000cf602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0268: strand_ctx_init */
+       0x99f094bd,
+       0x37008003,
+       0x0009f602,
+       0x167e04bd,
+       0x030e0002,
+       0x0002387e,
+       0xfc80c4bd,
+       0x0cf60247,
+       0x0c04bd00,
+       0x4afc8001,
+       0x000cf602,
+       0x0a7e04bd,
+       0x0c920002,
+       0x46fc8001,
+       0x000cf602,
+       0x020c04bd,
+       0x024afc80,
+       0xbd000cf6,
+       0x020a7e04,
+       0x02277e00,
+       0x42008800,
+       0x20008902,
+       0x0099cf02,
+/* 0x02c7: ctx_init_strand_loop */
+       0xf608fe95,
+       0x8ef6008e,
+       0x808acf40,
+       0xb606a5b6,
+       0xeabb01a0,
+       0x0480b600,
+       0xf40192b6,
+       0xe4b6e81b,
+       0xf2efbc08,
+       0x99f094bd,
+       0x17008003,
+       0x0009f602,
+       0x00f804bd,
+/* 0x02f8: error */
+       0xffb2e0f9,
+       0x4098148e,
+       0x00008f7e,
+       0xffb2010f,
+       0x409c1c8e,
+       0x00008f7e,
+       0x00f8e0fc,
+/* 0x0314: init */
+       0x04fe04bd,
+       0x40020200,
+       0x02f61200,
+       0x4104bd00,
+       0x10fe0465,
+       0x07004000,
+       0xbd0000f6,
+       0x40040204,
+       0x02f60400,
+       0xf404bd00,
+       0x00821031,
+       0x22cf0182,
+       0xf0010300,
+       0x32bb1f24,
+       0x0132b604,
+       0xb50502b5,
+       0x00820603,
+       0x22cf0186,
+       0x0402b500,
+       0x500c308e,
+       0x34bd24bd,
+/* 0x036a: init_unk_loop */
+       0x657e44bd,
+       0xf6b00000,
+       0x0e0bf400,
+       0xf2bb010f,
+       0x054ffd04,
+/* 0x037f: init_unk_next */
+       0xb60130b6,
+       0xe0b60120,
+       0x0126b004,
+/* 0x038b: init_unk_done */
+       0xb5e21bf4,
+       0x04b50703,
+       0x01008208,
+       0x0022cf02,
+       0x259534bd,
+       0xc0008008,
+       0x0005f601,
+       0x008004bd,
+       0x05f601c1,
+       0x9804bd00,
+       0x0f98000e,
+       0x01207e01,
+       0x002fbb00,
+       0x98003fbb,
+       0x0f98010e,
+       0x01207e02,
+       0x050e9800,
+       0xbb00effd,
+       0x3ebb002e,
+       0x020e9800,
+       0x7e030f98,
+       0x98000120,
+       0xeffd070e,
+       0x002ebb00,
+       0xb6003ebb,
+       0x00800235,
+       0x03f601d3,
+       0xb604bd00,
+       0x35b60825,
+       0x0120b606,
+       0xb60130b6,
+       0x34b60824,
+       0x7e2fb208,
+       0xbb000268,
+       0x0080003f,
+       0x03f60201,
+       0xbd04bd00,
+       0x1f29f024,
+       0x02300080,
+       0xbd0002f6,
+/* 0x0429: main */
+       0x0031f404,
+       0x0d0028f4,
+       0x00377e24,
+       0xf401f400,
+       0xf404e4b0,
+       0x81fe1d18,
+       0xbd060201,
+       0x0412fd20,
+       0xfd01e4b6,
+       0x18fe051e,
+       0x04fc7e00,
+       0xd40ef400,
+/* 0x0458: main_not_ctx_xfer */
+       0xf010ef94,
+       0xf87e01f5,
+       0x0ef40002,
+/* 0x0465: ih */
+       0xfe80f9c7,
+       0x80f90188,
+       0xa0f990f9,
+       0xd0f9b0f9,
+       0xf0f9e0f9,
+       0x004a04bd,
+       0x00aacf02,
+       0xf404abc4,
+       0x240d1f0b,
+       0xcf1a004e,
+       0x004f00ee,
+       0x00ffcf19,
+       0x0000047e,
+       0x0040010e,
+       0x000ef61d,
+/* 0x04a2: ih_no_fifo */
+       0x004004bd,
+       0x000af601,
+       0xf0fc04bd,
+       0xd0fce0fc,
+       0xa0fcb0fc,
+       0x80fc90fc,
+       0xfc0088fe,
+       0x0032f480,
+/* 0x04c2: hub_barrier_done */
+       0x010f01f8,
+       0xbb040e98,
+       0xffb204fe,
+       0x4094188e,
+       0x00008f7e,
+/* 0x04d6: ctx_redswitch */
+       0x200f00f8,
+       0x01850080,
+       0xbd000ff6,
+/* 0x04e3: ctx_redswitch_delay */
+       0xb6080e04,
+       0x1bf401e2,
+       0x00f5f1fd,
+       0x00f5f108,
+       0x85008002,
+       0x000ff601,
+       0x00f804bd,
+/* 0x04fc: ctx_xfer */
+       0x02810080,
+       0xbd000ff6,
+       0x0711f404,
+       0x0004d67e,
+/* 0x050c: ctx_xfer_not_load */
+       0x0002167e,
+       0xfc8024bd,
+       0x02f60247,
+       0xf004bd00,
+       0x20b6012c,
+       0x4afc8003,
+       0x0002f602,
+       0xacf004bd,
+       0x02a5f001,
+       0x5000008b,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x000c9800,
+       0x0e010d98,
+       0x013d7e00,
+       0x01acf000,
+       0x5040008b,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x010c9800,
+       0x98020d98,
+       0x004e060f,
+       0x013d7e08,
+       0x01acf000,
+       0x8b04a5f0,
+       0x98503000,
+       0xc4b6040c,
+       0x00bcbb0f,
+       0x98020c98,
+       0x0f98030d,
+       0x02004e08,
+       0x00013d7e,
+       0x00020a7e,
+       0xf40601f4,
+/* 0x0596: ctx_xfer_post */
+       0x277e0712,
+/* 0x059a: ctx_xfer_done */
+       0xc27e0002,
+       0x00f80004,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
index f2b0dea80116fd7b42de0a2d1ff8fad4dbd26b96..0e7b01efae8d2979cdffac5bbf4e4a4030580d2d 100644 (file)
@@ -37,14 +37,14 @@ uint32_t nvc0_grgpc_data[] = {
 };
 
 uint32_t nvc0_grgpc_code[] = {
-       0x03180ef5,
+       0x03a10ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -68,184 +68,214 @@ uint32_t nvc0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -259,167 +289,199 @@ uint32_t nvc0_grgpc_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0xe0f900f8,
-       0x9814e7f1,
-       0xf440e3f0,
-       0xe0b78d21,
-       0xf7f0041c,
-       0x8d21f401,
-       0x00f8e0fc,
-/* 0x0318: init */
-       0x04fe04bd,
-       0x0017f100,
-       0x0227f012,
-       0xf10012d0,
-       0xfe042617,
-       0x17f10010,
-       0x10d00400,
-       0x0427f0c0,
-       0xf40012d0,
-       0x17f11031,
-       0x14b60608,
-       0x0012cf06,
+       0xf102ffb9,
+       0xf09814e7,
+       0x21f440e3,
+       0x01f7f09d,
+       0xf102ffb9,
+       0xf09c1ce7,
+       0x21f440e3,
+       0xf8e0fc9d,
+/* 0x03a1: init */
+       0xfe04bd00,
+       0x27f00004,
+       0x0007f102,
+       0x0003f012,
+       0xbd0002d0,
+       0xd517f104,
+       0x0010fe04,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0000,
+       0xf10427f0,
+       0xf0040007,
+       0x02d00003,
+       0xf404bd00,
+       0x27f11031,
+       0x23f08200,
+       0x0022cf01,
        0xf00137f0,
        0x32bb1f24,
        0x0132b604,
        0x80050280,
-       0x10b70603,
-       0x12cf0400,
-       0x04028000,
-       0x010027f1,
-       0xcf0223f0,
-       0x34bd0022,
-       0x070047f1,
-       0x950644b6,
-       0x45d00825,
-       0x4045d000,
-       0x98000e98,
-       0x21f5010f,
-       0x2fbb0147,
-       0x003fbb00,
-       0x98010e98,
-       0x21f5020f,
-       0x0e980147,
-       0x00effd05,
-       0xbb002ebb,
-       0x40b7003e,
-       0x35b61300,
-       0x0043d002,
-       0xb60825b6,
-       0x20b60635,
-       0x0130b601,
-       0xb60824b6,
-       0x2fb90834,
-       0x7121f502,
-       0x003fbb02,
-       0x010007f1,
+       0x27f10603,
+       0x23f08600,
+       0x0022cf01,
+       0xf1040280,
+       0xf0010027,
+       0x22cf0223,
+       0x9534bd00,
+       0x07f10825,
+       0x03f0c000,
+       0x0005d001,
+       0x07f104bd,
+       0x03f0c100,
+       0x0005d001,
+       0x0e9804bd,
+       0x010f9800,
+       0x015021f5,
+       0xbb002fbb,
+       0x0e98003f,
+       0x020f9801,
+       0x015021f5,
+       0xfd050e98,
+       0x2ebb00ef,
+       0x003ebb00,
+       0xf10235b6,
+       0xf0d30007,
+       0x03d00103,
+       0xb604bd00,
+       0x35b60825,
+       0x0120b606,
+       0xb60130b6,
+       0x34b60824,
+       0x022fb908,
+       0x02d321f5,
+       0xf1003fbb,
+       0xf0010007,
+       0x03d00203,
+       0xbd04bd00,
+       0x1f29f024,
+       0x080007f1,
        0xd00203f0,
-       0x04bd0003,
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f008,
-       0xbd0002d0,
-/* 0x03e9: main */
-       0x0031f404,
-       0xf00028f4,
-       0x21f41cd7,
-       0xf401f439,
-       0xf404e4b0,
-       0x81fe1e18,
-       0x0627f001,
-       0x12fd20bd,
-       0x01e4b604,
-       0xfe051efd,
-       0x21f50018,
-       0x0ef404ad,
-/* 0x0419: main_not_ctx_xfer */
-       0x10ef94d3,
-       0xf501f5f0,
-       0xf402fe21,
-/* 0x0426: ih */
-       0x80f9c60e,
-       0xf90188fe,
-       0xf990f980,
-       0xf9b0f9a0,
-       0xf9e0f9d0,
-       0xcf04bdf0,
-       0xabc4800a,
-       0x1d0bf404,
-       0x1900b7f1,
-       0xcf1cd7f0,
-       0xbfcf40be,
+       0x04bd0002,
+/* 0x0498: main */
+       0xf40031f4,
+       0xd7f00028,
+       0x3921f41c,
+       0xb0f401f4,
+       0x18f404e4,
+       0x0181fe1e,
+       0xbd0627f0,
+       0x0412fd20,
+       0xfd01e4b6,
+       0x18fe051e,
+       0x8d21f500,
+       0xd30ef405,
+/* 0x04c8: main_not_ctx_xfer */
+       0xf010ef94,
+       0x21f501f5,
+       0x0ef4037e,
+/* 0x04d5: ih */
+       0xfe80f9c6,
+       0x80f90188,
+       0xa0f990f9,
+       0xd0f9b0f9,
+       0xf0f9e0f9,
+       0xa7f104bd,
+       0xa3f00200,
+       0x00aacf00,
+       0xf404abc4,
+       0xd7f02c0b,
+       0x00e7f11c,
+       0x00e3f01a,
+       0xf100eecf,
+       0xf01900f7,
+       0xffcf00f3,
        0x0421f400,
-       0x0400b0b7,
-       0xd001e7f0,
-/* 0x045e: ih_no_fifo */
-       0x0ad000be,
-       0xfcf0fc40,
-       0xfcd0fce0,
-       0xfca0fcb0,
-       0xfe80fc90,
-       0x80fc0088,
-       0xf80032f4,
-/* 0x0479: hub_barrier_done */
-       0x01f7f001,
-       0xbb040e98,
-       0xe7f104fe,
-       0xe3f09418,
-       0x8d21f440,
-/* 0x048e: ctx_redswitch */
-       0xe7f100f8,
-       0xe4b60614,
-       0x20f7f006,
-       0xf000efd0,
-/* 0x049e: ctx_redswitch_delay */
-       0xf2b608f7,
-       0xfd1bf401,
-       0x0a20f7f1,
-       0xf800efd0,
-/* 0x04ad: ctx_xfer */
-       0x0417f100,
-       0x0614b60a,
-       0xf4001fd0,
-       0x21f50711,
-/* 0x04be: ctx_xfer_not_load */
-       0x17f1048e,
-       0x13f04afc,
-       0x0c27f002,
-       0xf50012d0,
-       0xf1021521,
-       0xf047fc27,
-       0x20d00223,
-       0x012cf000,
-       0xd00320b6,
-       0xacf00012,
-       0x02a5f001,
-       0xf000b7f0,
-       0x0c9850b3,
-       0x0fc4b604,
-       0x9800bcbb,
-       0x0d98000c,
-       0x00e7f001,
-       0x016621f5,
+       0xf101e7f0,
+       0xf01d0007,
+       0x0ed00003,
+/* 0x0523: ih_no_fifo */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
+       0xfce0fcf0,
+       0xfcb0fcd0,
+       0xfc90fca0,
+       0x0088fe80,
+       0x32f480fc,
+/* 0x0547: hub_barrier_done */
+       0xf001f800,
+       0x0e9801f7,
+       0x04febb04,
+       0xf102ffb9,
+       0xf09418e7,
+       0x21f440e3,
+/* 0x055f: ctx_redswitch */
+       0xf000f89d,
+       0x07f120f7,
+       0x03f08500,
+       0x000fd001,
+       0xe7f004bd,
+/* 0x0571: ctx_redswitch_delay */
+       0x01e2b608,
+       0xf1fd1bf4,
+       0xf10800f5,
+       0xf10200f5,
+       0xf0850007,
+       0x0fd00103,
+       0xf804bd00,
+/* 0x058d: ctx_xfer */
+       0x0007f100,
+       0x0203f081,
+       0xbd000fd0,
+       0x0711f404,
+       0x055f21f5,
+/* 0x05a0: ctx_xfer_not_load */
+       0x026a21f5,
+       0x07f124bd,
+       0x03f047fc,
+       0x0002d002,
+       0x2cf004bd,
+       0x0320b601,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd0002,
        0xf001acf0,
-       0xb7f104a5,
-       0xb3f04000,
+       0xb7f102a5,
+       0xb3f00000,
        0x040c9850,
        0xbb0fc4b6,
        0x0c9800bc,
-       0x020d9801,
-       0xf1060f98,
-       0xf50800e7,
-       0xf5016621,
-       0xf4021521,
-       0x12f40601,
-/* 0x0535: ctx_xfer_post */
-       0xfc17f114,
-       0x0213f04a,
-       0xd00d27f0,
-       0x21f50012,
-/* 0x0546: ctx_xfer_done */
-       0x21f50215,
-       0x00f80479,
+       0x010d9800,
+       0xf500e7f0,
+       0xf0016f21,
+       0xa5f001ac,
+       0x00b7f104,
+       0x50b3f040,
+       0xb6040c98,
+       0xbcbb0fc4,
+       0x010c9800,
+       0x98020d98,
+       0xe7f1060f,
+       0x21f50800,
+       0x21f5016f,
+       0x01f4025e,
+       0x0712f406,
+/* 0x0618: ctx_xfer_post */
+       0x027f21f5,
+/* 0x061c: ctx_xfer_done */
+       0x054721f5,
+       0x000000f8,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
index dd346c2a16245849b773e382bad75499a85aa00a..84dd32db28a02cff0118eec2bae837ddf56dcc90 100644 (file)
@@ -41,14 +41,14 @@ uint32_t nvd7_grgpc_data[] = {
 };
 
 uint32_t nvd7_grgpc_code[] = {
-       0x03180ef5,
+       0x03a10ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nvd7_grgpc_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nvd7_grgpc_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0xe0f900f8,
-       0x9814e7f1,
-       0xf440e3f0,
-       0xe0b78d21,
-       0xf7f0041c,
-       0x8d21f401,
-       0x00f8e0fc,
-/* 0x0318: init */
-       0x04fe04bd,
-       0x0017f100,
-       0x0227f012,
-       0xf10012d0,
-       0xfe047017,
-       0x17f10010,
-       0x10d00400,
-       0x0427f0c0,
-       0xf40012d0,
-       0x17f11031,
-       0x14b60608,
-       0x0012cf06,
+       0xf102ffb9,
+       0xf09814e7,
+       0x21f440e3,
+       0x01f7f09d,
+       0xf102ffb9,
+       0xf09c1ce7,
+       0x21f440e3,
+       0xf8e0fc9d,
+/* 0x03a1: init */
+       0xfe04bd00,
+       0x27f00004,
+       0x0007f102,
+       0x0003f012,
+       0xbd0002d0,
+       0x1f17f104,
+       0x0010fe05,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0000,
+       0xf10427f0,
+       0xf0040007,
+       0x02d00003,
+       0xf404bd00,
+       0x27f11031,
+       0x23f08200,
+       0x0022cf01,
        0xf00137f0,
        0x32bb1f24,
        0x0132b604,
        0x80050280,
-       0x10b70603,
-       0x12cf0400,
-       0x04028000,
-       0x0c30e7f1,
-       0xbd50e3f0,
-       0xbd34bd24,
-/* 0x0371: init_unk_loop */
-       0x6821f444,
-       0xf400f6b0,
-       0xf7f00f0b,
-       0x04f2bb01,
-       0xb6054ffd,
-/* 0x0386: init_unk_next */
-       0x20b60130,
-       0x04e0b601,
-       0xf40126b0,
-/* 0x0392: init_unk_done */
-       0x0380e21b,
-       0x08048007,
-       0x010027f1,
-       0xcf0223f0,
-       0x34bd0022,
-       0x070047f1,
-       0x950644b6,
-       0x45d00825,
-       0x4045d000,
-       0x98000e98,
-       0x21f5010f,
-       0x2fbb0147,
-       0x003fbb00,
-       0x98010e98,
-       0x21f5020f,
-       0x0e980147,
-       0x00effd05,
-       0xbb002ebb,
-       0x0e98003e,
-       0x030f9802,
-       0x014721f5,
-       0xfd070e98,
+       0x27f10603,
+       0x23f08600,
+       0x0022cf01,
+       0xf1040280,
+       0xf00c30e7,
+       0x24bd50e3,
+       0x44bd34bd,
+/* 0x0410: init_unk_loop */
+       0xb06821f4,
+       0x0bf400f6,
+       0x01f7f00f,
+       0xfd04f2bb,
+       0x30b6054f,
+/* 0x0425: init_unk_next */
+       0x0120b601,
+       0xb004e0b6,
+       0x1bf40126,
+/* 0x0431: init_unk_done */
+       0x070380e2,
+       0xf1080480,
+       0xf0010027,
+       0x22cf0223,
+       0x9534bd00,
+       0x07f10825,
+       0x03f0c000,
+       0x0005d001,
+       0x07f104bd,
+       0x03f0c100,
+       0x0005d001,
+       0x0e9804bd,
+       0x010f9800,
+       0x015021f5,
+       0xbb002fbb,
+       0x0e98003f,
+       0x020f9801,
+       0x015021f5,
+       0xfd050e98,
        0x2ebb00ef,
        0x003ebb00,
-       0x130040b7,
-       0xd00235b6,
-       0x25b60043,
-       0x0635b608,
-       0xb60120b6,
-       0x24b60130,
-       0x0834b608,
-       0xf5022fb9,
-       0xbb027121,
-       0x07f1003f,
-       0x03f00100,
-       0x0003d002,
-       0x24bd04bd,
-       0xf11f29f0,
-       0xf0080007,
-       0x02d00203,
-/* 0x0433: main */
+       0x98020e98,
+       0x21f5030f,
+       0x0e980150,
+       0x00effd07,
+       0xbb002ebb,
+       0x35b6003e,
+       0x0007f102,
+       0x0103f0d3,
+       0xbd0003d0,
+       0x0825b604,
+       0xb60635b6,
+       0x30b60120,
+       0x0824b601,
+       0xb90834b6,
+       0x21f5022f,
+       0x3fbb02d3,
+       0x0007f100,
+       0x0203f001,
+       0xbd0003d0,
+       0xf024bd04,
+       0x07f11f29,
+       0x03f00800,
+       0x0002d002,
+/* 0x04e2: main */
+       0x31f404bd,
+       0x0028f400,
+       0xf424d7f0,
+       0x01f43921,
+       0x04e4b0f4,
+       0xfe1e18f4,
+       0x27f00181,
+       0xfd20bd06,
+       0xe4b60412,
+       0x051efd01,
+       0xf50018fe,
+       0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+       0xef94d30e,
+       0x01f5f010,
+       0x037e21f5,
+/* 0x051f: ih */
+       0xf9c60ef4,
+       0x0188fe80,
+       0x90f980f9,
+       0xb0f9a0f9,
+       0xe0f9d0f9,
+       0x04bdf0f9,
+       0x0200a7f1,
+       0xcf00a3f0,
+       0xabc400aa,
+       0x2c0bf404,
+       0xf124d7f0,
+       0xf01a00e7,
+       0xeecf00e3,
+       0x00f7f100,
+       0x00f3f019,
+       0xf400ffcf,
+       0xe7f00421,
+       0x0007f101,
+       0x0003f01d,
+       0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+       0x0007f104,
+       0x0003f001,
+       0xbd000ad0,
+       0xfcf0fc04,
+       0xfcd0fce0,
+       0xfca0fcb0,
+       0xfe80fc90,
+       0x80fc0088,
+       0xf80032f4,
+/* 0x0591: hub_barrier_done */
+       0x01f7f001,
+       0xbb040e98,
+       0xffb904fe,
+       0x18e7f102,
+       0x40e3f094,
+       0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+       0x20f7f000,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+       0xb608e7f0,
+       0x1bf401e2,
+       0x00f5f1fd,
+       0x00f5f108,
+       0x0007f102,
+       0x0103f085,
+       0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+       0xf100f804,
+       0xf0810007,
+       0x0fd00203,
        0xf404bd00,
-       0x28f40031,
-       0x24d7f000,
-       0xf43921f4,
-       0xe4b0f401,
-       0x1e18f404,
-       0xf00181fe,
-       0x20bd0627,
-       0xb60412fd,
-       0x1efd01e4,
-       0x0018fe05,
-       0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-       0x94d30ef4,
-       0xf5f010ef,
-       0xfe21f501,
-       0xc60ef402,
-/* 0x0470: ih */
-       0x88fe80f9,
-       0xf980f901,
-       0xf9a0f990,
-       0xf9d0f9b0,
-       0xbdf0f9e0,
-       0x800acf04,
-       0xf404abc4,
-       0xb7f11d0b,
-       0xd7f01900,
-       0x40becf24,
-       0xf400bfcf,
-       0xb0b70421,
-       0xe7f00400,
-       0x00bed001,
-/* 0x04a8: ih_no_fifo */
-       0xfc400ad0,
-       0xfce0fcf0,
-       0xfcb0fcd0,
-       0xfc90fca0,
-       0x0088fe80,
-       0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-       0xf001f800,
-       0x0e9801f7,
-       0x04febb04,
-       0x9418e7f1,
-       0xf440e3f0,
-       0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-       0x0614e7f1,
-       0xf006e4b6,
-       0xefd020f7,
-       0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-       0xf401f2b6,
-       0xf7f1fd1b,
-       0xefd00a20,
-/* 0x04f7: ctx_xfer */
-       0xf100f800,
-       0xb60a0417,
-       0x1fd00614,
-       0x0711f400,
-       0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-       0x4afc17f1,
-       0xf00213f0,
-       0x12d00c27,
-       0x1521f500,
-       0xfc27f102,
-       0x0223f047,
-       0xf00020d0,
-       0x20b6012c,
-       0x0012d003,
-       0xf001acf0,
-       0xb7f002a5,
-       0x50b3f000,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x000c9800,
-       0xf0010d98,
-       0x21f500e7,
-       0xacf00166,
-       0x00b7f101,
-       0x50b3f040,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x010c9800,
-       0x98020d98,
-       0xe7f1060f,
-       0x21f50800,
-       0xacf00166,
-       0x04a5f001,
-       0x3000b7f1,
+       0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+       0x21f505a9,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xb6012cf0,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x02a5f001,
+       0x0000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98020c98,
-       0x0f98030d,
-       0x00e7f108,
-       0x6621f502,
-       0x1521f501,
-       0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-       0xf11412f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00d,
-       0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-       0x04c321f5,
-       0x000000f8,
+       0x98000c98,
+       0xe7f0010d,
+       0x6f21f500,
+       0x01acf001,
+       0x4000b7f1,
+       0x9850b3f0,
+       0xc4b6040c,
+       0x00bcbb0f,
+       0x98010c98,
+       0x0f98020d,
+       0x00e7f106,
+       0x6f21f508,
+       0x01acf001,
+       0xf104a5f0,
+       0xf03000b7,
+       0x0c9850b3,
+       0x0fc4b604,
+       0x9800bcbb,
+       0x0d98020c,
+       0x080f9803,
+       0x0200e7f1,
+       0x016f21f5,
+       0x025e21f5,
+       0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+       0x21f50712,
+/* 0x068a: ctx_xfer_done */
+       0x21f5027f,
+       0x00f80591,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
index 7ff5ef6b08048e0d0b12d8b1cf788f97d4f01143..b6da800ee9c2ddbd2baae4cf5812c681c09fccc6 100644 (file)
@@ -41,14 +41,14 @@ uint32_t nve0_grgpc_data[] = {
 };
 
 uint32_t nve0_grgpc_code[] = {
-       0x03180ef5,
+       0x03a10ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nve0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nve0_grgpc_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0xe0f900f8,
-       0x9814e7f1,
-       0xf440e3f0,
-       0xe0b78d21,
-       0xf7f0041c,
-       0x8d21f401,
-       0x00f8e0fc,
-/* 0x0318: init */
-       0x04fe04bd,
-       0x0017f100,
-       0x0227f012,
-       0xf10012d0,
-       0xfe047017,
-       0x17f10010,
-       0x10d00400,
-       0x0427f0c0,
-       0xf40012d0,
-       0x17f11031,
-       0x14b60608,
-       0x0012cf06,
+       0xf102ffb9,
+       0xf09814e7,
+       0x21f440e3,
+       0x01f7f09d,
+       0xf102ffb9,
+       0xf09c1ce7,
+       0x21f440e3,
+       0xf8e0fc9d,
+/* 0x03a1: init */
+       0xfe04bd00,
+       0x27f00004,
+       0x0007f102,
+       0x0003f012,
+       0xbd0002d0,
+       0x1f17f104,
+       0x0010fe05,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0000,
+       0xf10427f0,
+       0xf0040007,
+       0x02d00003,
+       0xf404bd00,
+       0x27f11031,
+       0x23f08200,
+       0x0022cf01,
        0xf00137f0,
        0x32bb1f24,
        0x0132b604,
        0x80050280,
-       0x10b70603,
-       0x12cf0400,
-       0x04028000,
-       0x0c30e7f1,
-       0xbd50e3f0,
-       0xbd34bd24,
-/* 0x0371: init_unk_loop */
-       0x6821f444,
-       0xf400f6b0,
-       0xf7f00f0b,
-       0x04f2bb01,
-       0xb6054ffd,
-/* 0x0386: init_unk_next */
-       0x20b60130,
-       0x04e0b601,
-       0xf40126b0,
-/* 0x0392: init_unk_done */
-       0x0380e21b,
-       0x08048007,
-       0x010027f1,
-       0xcf0223f0,
-       0x34bd0022,
-       0x070047f1,
-       0x950644b6,
-       0x45d00825,
-       0x4045d000,
-       0x98000e98,
-       0x21f5010f,
-       0x2fbb0147,
-       0x003fbb00,
-       0x98010e98,
-       0x21f5020f,
-       0x0e980147,
-       0x00effd05,
-       0xbb002ebb,
-       0x0e98003e,
-       0x030f9802,
-       0x014721f5,
-       0xfd070e98,
+       0x27f10603,
+       0x23f08600,
+       0x0022cf01,
+       0xf1040280,
+       0xf00c30e7,
+       0x24bd50e3,
+       0x44bd34bd,
+/* 0x0410: init_unk_loop */
+       0xb06821f4,
+       0x0bf400f6,
+       0x01f7f00f,
+       0xfd04f2bb,
+       0x30b6054f,
+/* 0x0425: init_unk_next */
+       0x0120b601,
+       0xb004e0b6,
+       0x1bf40126,
+/* 0x0431: init_unk_done */
+       0x070380e2,
+       0xf1080480,
+       0xf0010027,
+       0x22cf0223,
+       0x9534bd00,
+       0x07f10825,
+       0x03f0c000,
+       0x0005d001,
+       0x07f104bd,
+       0x03f0c100,
+       0x0005d001,
+       0x0e9804bd,
+       0x010f9800,
+       0x015021f5,
+       0xbb002fbb,
+       0x0e98003f,
+       0x020f9801,
+       0x015021f5,
+       0xfd050e98,
        0x2ebb00ef,
        0x003ebb00,
-       0x130040b7,
-       0xd00235b6,
-       0x25b60043,
-       0x0635b608,
-       0xb60120b6,
-       0x24b60130,
-       0x0834b608,
-       0xf5022fb9,
-       0xbb027121,
-       0x07f1003f,
-       0x03f00100,
-       0x0003d002,
-       0x24bd04bd,
-       0xf11f29f0,
-       0xf0080007,
-       0x02d00203,
-/* 0x0433: main */
+       0x98020e98,
+       0x21f5030f,
+       0x0e980150,
+       0x00effd07,
+       0xbb002ebb,
+       0x35b6003e,
+       0x0007f102,
+       0x0103f0d3,
+       0xbd0003d0,
+       0x0825b604,
+       0xb60635b6,
+       0x30b60120,
+       0x0824b601,
+       0xb90834b6,
+       0x21f5022f,
+       0x3fbb02d3,
+       0x0007f100,
+       0x0203f001,
+       0xbd0003d0,
+       0xf024bd04,
+       0x07f11f29,
+       0x03f00800,
+       0x0002d002,
+/* 0x04e2: main */
+       0x31f404bd,
+       0x0028f400,
+       0xf424d7f0,
+       0x01f43921,
+       0x04e4b0f4,
+       0xfe1e18f4,
+       0x27f00181,
+       0xfd20bd06,
+       0xe4b60412,
+       0x051efd01,
+       0xf50018fe,
+       0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+       0xef94d30e,
+       0x01f5f010,
+       0x037e21f5,
+/* 0x051f: ih */
+       0xf9c60ef4,
+       0x0188fe80,
+       0x90f980f9,
+       0xb0f9a0f9,
+       0xe0f9d0f9,
+       0x04bdf0f9,
+       0x0200a7f1,
+       0xcf00a3f0,
+       0xabc400aa,
+       0x2c0bf404,
+       0xf124d7f0,
+       0xf01a00e7,
+       0xeecf00e3,
+       0x00f7f100,
+       0x00f3f019,
+       0xf400ffcf,
+       0xe7f00421,
+       0x0007f101,
+       0x0003f01d,
+       0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+       0x0007f104,
+       0x0003f001,
+       0xbd000ad0,
+       0xfcf0fc04,
+       0xfcd0fce0,
+       0xfca0fcb0,
+       0xfe80fc90,
+       0x80fc0088,
+       0xf80032f4,
+/* 0x0591: hub_barrier_done */
+       0x01f7f001,
+       0xbb040e98,
+       0xffb904fe,
+       0x18e7f102,
+       0x40e3f094,
+       0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+       0x20f7f000,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+       0xb608e7f0,
+       0x1bf401e2,
+       0x00f5f1fd,
+       0x00f5f108,
+       0x0007f102,
+       0x0103f085,
+       0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+       0xf100f804,
+       0xf0810007,
+       0x0fd00203,
        0xf404bd00,
-       0x28f40031,
-       0x24d7f000,
-       0xf43921f4,
-       0xe4b0f401,
-       0x1e18f404,
-       0xf00181fe,
-       0x20bd0627,
-       0xb60412fd,
-       0x1efd01e4,
-       0x0018fe05,
-       0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-       0x94d30ef4,
-       0xf5f010ef,
-       0xfe21f501,
-       0xc60ef402,
-/* 0x0470: ih */
-       0x88fe80f9,
-       0xf980f901,
-       0xf9a0f990,
-       0xf9d0f9b0,
-       0xbdf0f9e0,
-       0x800acf04,
-       0xf404abc4,
-       0xb7f11d0b,
-       0xd7f01900,
-       0x40becf24,
-       0xf400bfcf,
-       0xb0b70421,
-       0xe7f00400,
-       0x00bed001,
-/* 0x04a8: ih_no_fifo */
-       0xfc400ad0,
-       0xfce0fcf0,
-       0xfcb0fcd0,
-       0xfc90fca0,
-       0x0088fe80,
-       0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-       0xf001f800,
-       0x0e9801f7,
-       0x04febb04,
-       0x9418e7f1,
-       0xf440e3f0,
-       0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-       0x0614e7f1,
-       0xf006e4b6,
-       0xefd020f7,
-       0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-       0xf401f2b6,
-       0xf7f1fd1b,
-       0xefd00a20,
-/* 0x04f7: ctx_xfer */
-       0xf100f800,
-       0xb60a0417,
-       0x1fd00614,
-       0x0711f400,
-       0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-       0x4afc17f1,
-       0xf00213f0,
-       0x12d00c27,
-       0x1521f500,
-       0xfc27f102,
-       0x0223f047,
-       0xf00020d0,
-       0x20b6012c,
-       0x0012d003,
-       0xf001acf0,
-       0xb7f002a5,
-       0x50b3f000,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x000c9800,
-       0xf0010d98,
-       0x21f500e7,
-       0xacf00166,
-       0x00b7f101,
-       0x50b3f040,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x010c9800,
-       0x98020d98,
-       0xe7f1060f,
-       0x21f50800,
-       0xacf00166,
-       0x04a5f001,
-       0x3000b7f1,
+       0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+       0x21f505a9,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xb6012cf0,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x02a5f001,
+       0x0000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98020c98,
-       0x0f98030d,
-       0x00e7f108,
-       0x6621f502,
-       0x1521f501,
-       0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-       0xf11412f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00d,
-       0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-       0x04c321f5,
-       0x000000f8,
+       0x98000c98,
+       0xe7f0010d,
+       0x6f21f500,
+       0x01acf001,
+       0x4000b7f1,
+       0x9850b3f0,
+       0xc4b6040c,
+       0x00bcbb0f,
+       0x98010c98,
+       0x0f98020d,
+       0x00e7f106,
+       0x6f21f508,
+       0x01acf001,
+       0xf104a5f0,
+       0xf03000b7,
+       0x0c9850b3,
+       0x0fc4b604,
+       0x9800bcbb,
+       0x0d98020c,
+       0x080f9803,
+       0x0200e7f1,
+       0x016f21f5,
+       0x025e21f5,
+       0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+       0x21f50712,
+/* 0x068a: ctx_xfer_done */
+       0x21f5027f,
+       0x00f80591,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
index f870507be88019cd9167d82a2fd85b3626f820d3..6316ebaf5d9a581dae8ac9e5a6d0464d0f8ec478 100644 (file)
@@ -41,14 +41,14 @@ uint32_t nvf0_grgpc_data[] = {
 };
 
 uint32_t nvf0_grgpc_code[] = {
-       0x03180ef5,
+       0x03a10ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -72,184 +72,214 @@ uint32_t nvf0_grgpc_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f03700,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f037,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f03700,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f037,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf0370007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x370007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f03700,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x370007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -263,198 +293,230 @@ uint32_t nvf0_grgpc_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0xe0f900f8,
-       0x9814e7f1,
-       0xf440e3f0,
-       0xe0b78d21,
-       0xf7f0041c,
-       0x8d21f401,
-       0x00f8e0fc,
-/* 0x0318: init */
-       0x04fe04bd,
-       0x0017f100,
-       0x0227f012,
-       0xf10012d0,
-       0xfe047017,
-       0x17f10010,
-       0x10d00400,
-       0x0427f0c0,
-       0xf40012d0,
-       0x17f11031,
-       0x14b60608,
-       0x0012cf06,
+       0xf102ffb9,
+       0xf09814e7,
+       0x21f440e3,
+       0x01f7f09d,
+       0xf102ffb9,
+       0xf09c1ce7,
+       0x21f440e3,
+       0xf8e0fc9d,
+/* 0x03a1: init */
+       0xfe04bd00,
+       0x27f00004,
+       0x0007f102,
+       0x0003f012,
+       0xbd0002d0,
+       0x1f17f104,
+       0x0010fe05,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0000,
+       0xf10427f0,
+       0xf0040007,
+       0x02d00003,
+       0xf404bd00,
+       0x27f11031,
+       0x23f08200,
+       0x0022cf01,
        0xf00137f0,
        0x32bb1f24,
        0x0132b604,
        0x80050280,
-       0x10b70603,
-       0x12cf0400,
-       0x04028000,
-       0x0c30e7f1,
-       0xbd50e3f0,
-       0xbd34bd24,
-/* 0x0371: init_unk_loop */
-       0x6821f444,
-       0xf400f6b0,
-       0xf7f00f0b,
-       0x04f2bb01,
-       0xb6054ffd,
-/* 0x0386: init_unk_next */
-       0x20b60130,
-       0x04e0b601,
-       0xf40226b0,
-/* 0x0392: init_unk_done */
-       0x0380e21b,
-       0x08048007,
-       0x010027f1,
-       0xcf0223f0,
-       0x34bd0022,
-       0x070047f1,
-       0x950644b6,
-       0x45d00825,
-       0x4045d000,
-       0x98000e98,
-       0x21f5010f,
-       0x2fbb0147,
-       0x003fbb00,
-       0x98010e98,
-       0x21f5020f,
-       0x0e980147,
-       0x00effd05,
-       0xbb002ebb,
-       0x0e98003e,
-       0x030f9802,
-       0x014721f5,
-       0xfd070e98,
+       0x27f10603,
+       0x23f08600,
+       0x0022cf01,
+       0xf1040280,
+       0xf00c30e7,
+       0x24bd50e3,
+       0x44bd34bd,
+/* 0x0410: init_unk_loop */
+       0xb06821f4,
+       0x0bf400f6,
+       0x01f7f00f,
+       0xfd04f2bb,
+       0x30b6054f,
+/* 0x0425: init_unk_next */
+       0x0120b601,
+       0xb004e0b6,
+       0x1bf40226,
+/* 0x0431: init_unk_done */
+       0x070380e2,
+       0xf1080480,
+       0xf0010027,
+       0x22cf0223,
+       0x9534bd00,
+       0x07f10825,
+       0x03f0c000,
+       0x0005d001,
+       0x07f104bd,
+       0x03f0c100,
+       0x0005d001,
+       0x0e9804bd,
+       0x010f9800,
+       0x015021f5,
+       0xbb002fbb,
+       0x0e98003f,
+       0x020f9801,
+       0x015021f5,
+       0xfd050e98,
        0x2ebb00ef,
        0x003ebb00,
-       0x130040b7,
-       0xd00235b6,
-       0x25b60043,
-       0x0635b608,
-       0xb60120b6,
-       0x24b60130,
-       0x0834b608,
-       0xf5022fb9,
-       0xbb027121,
-       0x07f1003f,
-       0x03f00100,
-       0x0003d002,
-       0x24bd04bd,
-       0xf11f29f0,
-       0xf0300007,
-       0x02d00203,
-/* 0x0433: main */
+       0x98020e98,
+       0x21f5030f,
+       0x0e980150,
+       0x00effd07,
+       0xbb002ebb,
+       0x35b6003e,
+       0x0007f102,
+       0x0103f0d3,
+       0xbd0003d0,
+       0x0825b604,
+       0xb60635b6,
+       0x30b60120,
+       0x0824b601,
+       0xb90834b6,
+       0x21f5022f,
+       0x3fbb02d3,
+       0x0007f100,
+       0x0203f001,
+       0xbd0003d0,
+       0xf024bd04,
+       0x07f11f29,
+       0x03f03000,
+       0x0002d002,
+/* 0x04e2: main */
+       0x31f404bd,
+       0x0028f400,
+       0xf424d7f0,
+       0x01f43921,
+       0x04e4b0f4,
+       0xfe1e18f4,
+       0x27f00181,
+       0xfd20bd06,
+       0xe4b60412,
+       0x051efd01,
+       0xf50018fe,
+       0xf405d721,
+/* 0x0512: main_not_ctx_xfer */
+       0xef94d30e,
+       0x01f5f010,
+       0x037e21f5,
+/* 0x051f: ih */
+       0xf9c60ef4,
+       0x0188fe80,
+       0x90f980f9,
+       0xb0f9a0f9,
+       0xe0f9d0f9,
+       0x04bdf0f9,
+       0x0200a7f1,
+       0xcf00a3f0,
+       0xabc400aa,
+       0x2c0bf404,
+       0xf124d7f0,
+       0xf01a00e7,
+       0xeecf00e3,
+       0x00f7f100,
+       0x00f3f019,
+       0xf400ffcf,
+       0xe7f00421,
+       0x0007f101,
+       0x0003f01d,
+       0xbd000ed0,
+/* 0x056d: ih_no_fifo */
+       0x0007f104,
+       0x0003f001,
+       0xbd000ad0,
+       0xfcf0fc04,
+       0xfcd0fce0,
+       0xfca0fcb0,
+       0xfe80fc90,
+       0x80fc0088,
+       0xf80032f4,
+/* 0x0591: hub_barrier_done */
+       0x01f7f001,
+       0xbb040e98,
+       0xffb904fe,
+       0x18e7f102,
+       0x40e3f094,
+       0xf89d21f4,
+/* 0x05a9: ctx_redswitch */
+       0x20f7f000,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000f,
+/* 0x05bb: ctx_redswitch_delay */
+       0xb608e7f0,
+       0x1bf401e2,
+       0x00f5f1fd,
+       0x00f5f108,
+       0x0007f102,
+       0x0103f085,
+       0xbd000fd0,
+/* 0x05d7: ctx_xfer */
+       0xf100f804,
+       0xf0810007,
+       0x0fd00203,
        0xf404bd00,
-       0x28f40031,
-       0x24d7f000,
-       0xf43921f4,
-       0xe4b0f401,
-       0x1e18f404,
-       0xf00181fe,
-       0x20bd0627,
-       0xb60412fd,
-       0x1efd01e4,
-       0x0018fe05,
-       0x04f721f5,
-/* 0x0463: main_not_ctx_xfer */
-       0x94d30ef4,
-       0xf5f010ef,
-       0xfe21f501,
-       0xc60ef402,
-/* 0x0470: ih */
-       0x88fe80f9,
-       0xf980f901,
-       0xf9a0f990,
-       0xf9d0f9b0,
-       0xbdf0f9e0,
-       0x800acf04,
-       0xf404abc4,
-       0xb7f11d0b,
-       0xd7f01900,
-       0x40becf24,
-       0xf400bfcf,
-       0xb0b70421,
-       0xe7f00400,
-       0x00bed001,
-/* 0x04a8: ih_no_fifo */
-       0xfc400ad0,
-       0xfce0fcf0,
-       0xfcb0fcd0,
-       0xfc90fca0,
-       0x0088fe80,
-       0x32f480fc,
-/* 0x04c3: hub_barrier_done */
-       0xf001f800,
-       0x0e9801f7,
-       0x04febb04,
-       0x9418e7f1,
-       0xf440e3f0,
-       0x00f88d21,
-/* 0x04d8: ctx_redswitch */
-       0x0614e7f1,
-       0xf006e4b6,
-       0xefd020f7,
-       0x08f7f000,
-/* 0x04e8: ctx_redswitch_delay */
-       0xf401f2b6,
-       0xf7f1fd1b,
-       0xefd00a20,
-/* 0x04f7: ctx_xfer */
-       0xf100f800,
-       0xb60a0417,
-       0x1fd00614,
-       0x0711f400,
-       0x04d821f5,
-/* 0x0508: ctx_xfer_not_load */
-       0x4afc17f1,
-       0xf00213f0,
-       0x12d00c27,
-       0x1521f500,
-       0xfc27f102,
-       0x0223f047,
-       0xf00020d0,
-       0x20b6012c,
-       0x0012d003,
-       0xf001acf0,
-       0xb7f002a5,
-       0x50b3f000,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x000c9800,
-       0xf0010d98,
-       0x21f500e7,
-       0xacf00166,
-       0x00b7f101,
-       0x50b3f040,
-       0xb6040c98,
-       0xbcbb0fc4,
-       0x010c9800,
-       0x98020d98,
-       0xe7f1060f,
-       0x21f50800,
-       0xacf00166,
-       0x04a5f001,
-       0x3000b7f1,
+       0x21f50711,
+/* 0x05ea: ctx_xfer_not_load */
+       0x21f505a9,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xb6012cf0,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x02a5f001,
+       0x0000b7f1,
        0x9850b3f0,
        0xc4b6040c,
        0x00bcbb0f,
-       0x98020c98,
-       0x0f98030d,
-       0x00e7f108,
-       0x6621f502,
-       0x1521f501,
-       0x0601f402,
-/* 0x05a3: ctx_xfer_post */
-       0xf11412f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00d,
-       0x021521f5,
-/* 0x05b4: ctx_xfer_done */
-       0x04c321f5,
-       0x000000f8,
+       0x98000c98,
+       0xe7f0010d,
+       0x6f21f500,
+       0x01acf001,
+       0x4000b7f1,
+       0x9850b3f0,
+       0xc4b6040c,
+       0x00bcbb0f,
+       0x98010c98,
+       0x0f98020d,
+       0x00e7f106,
+       0x6f21f508,
+       0x01acf001,
+       0xf104a5f0,
+       0xf03000b7,
+       0x0c9850b3,
+       0x0fc4b604,
+       0x9800bcbb,
+       0x0d98020c,
+       0x080f9803,
+       0x0200e7f1,
+       0x016f21f5,
+       0x025e21f5,
+       0xf40601f4,
+/* 0x0686: ctx_xfer_post */
+       0x21f50712,
+/* 0x068a: ctx_xfer_done */
+       0x21f5027f,
+       0x00f80591,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
index b82d2ae8991742e7eb58902f4935663590fbe795..c8ddb8d71b915c668c7b116f1b7f9cf9547289b3 100644 (file)
@@ -68,60 +68,57 @@ error:
 //
 init:
        clear b32 $r0
-       mov $sp $r0
        mov $xdbase $r0
 
+       // setup stack
+       nv_iord($r1, NV_PGRAPH_FECS_CAPS, 0)
+       extr $r1 $r1 9:17
+       shl b32 $r1 8
+       mov $sp $r1
+
        // enable fifo access
-       mov $r1 0x1200
-       mov $r2 2
-       iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
+       mov $r2 NV_PGRAPH_FECS_ACCESS_FIFO
+       nv_iowr(NV_PGRAPH_FECS_ACCESS, 0, $r2)
 
        // setup i0 handler, and route all interrupts to it
        mov $r1 #ih
        mov $iv0 $r1
-       mov $r1 0x400
-       iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
 
-       // route HUB_CHANNEL_SWITCH to fuc interrupt 8
-       mov $r3 0x404
-       shl b32 $r3 6
-       mov $r2 0x2003          // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
-       iowr I[$r3 + 0x000] $r2
+       clear b32 $r2
+       nv_iowr(NV_PGRAPH_FECS_INTR_ROUTE, 0, $r2)
+
+       // route HUB_CHSW_PULSE to fuc interrupt 8
+       mov $r2 0x2003          // { HUB_CHSW_PULSE, ZERO } -> intr 8
+       nv_iowr(NV_PGRAPH_FECS_IROUTE, 0, $r2)
 
        // not sure what these are, route them because NVIDIA does, and
        // the IRQ handler will signal the host if we ever get one.. we
        // may find out if/why we need to handle these if so..
        //
-       mov $r2 0x2004
-       iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
-       mov $r2 0x200b
-       iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
-       mov $r2 0x200c
-       iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
+       mov $r2 0x2004          // { 0x04, ZERO } -> intr 9
+       nv_iowr(NV_PGRAPH_FECS_IROUTE, 1, $r2)
+       mov $r2 0x200b          // { HUB_FIRMWARE_MTHD, ZERO } -> intr 10
+       nv_iowr(NV_PGRAPH_FECS_IROUTE, 2, $r2)
+       mov $r2 0x200c          // { 0x0c, ZERO } -> intr 15
+       nv_iowr(NV_PGRAPH_FECS_IROUTE, 7, $r2)
 
        // enable all INTR_UP interrupts
-       mov $r2 0xc24
-       shl b32 $r2 6
-       not b32 $r3 $r0
-       iowr I[$r2] $r3
+       sub b32 $r3 $r0 1
+       nv_iowr(NV_PGRAPH_FECS_INTR_UP_EN, 0, $r3)
 
-       // enable fifo, ctxsw, 9, 10, 15 interrupts
-       mov $r2 -0x78fc         // 0x8704
-       sethi $r2 0
-       iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
+       // enable fifo, ctxsw, 9, fwmthd, 15 interrupts
+       imm32($r2, 0x8704)
+       nv_iowr(NV_PGRAPH_FECS_INTR_EN_SET, 0, $r2)
 
        // fifo level triggered, rest edge
-       sub b32 $r1 0x100
-       mov $r2 4
-       iowr I[$r1] $r2
+       mov $r2 NV_PGRAPH_FECS_INTR_MODE_FIFO_LEVEL
+       nv_iowr(NV_PGRAPH_FECS_INTR_MODE, 0, $r2)
 
        // enable interrupts
        bset $flags ie0
 
        // fetch enabled GPC/ROP counts
-       mov $r14 -0x69fc        // 0x409604
-       sethi $r14 0x400000
-       call #nv_rd32
+       nv_rd32($r14, 0x409604)
        extr $r1 $r15 16:20
        st b32 D[$r0 + #rop_count] $r1
        and $r15 0x1f
@@ -131,37 +128,40 @@ init:
        mov $r1 1
        shl b32 $r1 $r15
        sub b32 $r1 1
-       mov $r2 0x40c
-       shl b32 $r2 6
-       iowr I[$r2 + 0x000] $r1
-       iowr I[$r2 + 0x100] $r1
+       nv_iowr(NV_PGRAPH_FECS_BAR_MASK0, 0, $r1)
+       nv_iowr(NV_PGRAPH_FECS_BAR_MASK1, 0, $r1)
 
        // context size calculation, reserve first 256 bytes for use by fuc
        mov $r1 256
 
+       //
+       mov $r15 2
+       call(ctx_4170s)
+       call(ctx_4170w)
+       mov $r15 0x10
+       call(ctx_86c)
+
        // calculate size of mmio context data
        ld b32 $r14 D[$r0 + #hub_mmio_list_head]
        ld b32 $r15 D[$r0 + #hub_mmio_list_tail]
-       call #mmctx_size
+       call(mmctx_size)
 
        // set mmctx base addresses now so we don't have to do it later,
        // they don't (currently) ever change
-       mov $r3 0x700
-       shl b32 $r3 6
        shr b32 $r4 $r1 8
-       iowr I[$r3 + 0x000] $r4         // MMCTX_SAVE_SWBASE
-       iowr I[$r3 + 0x100] $r4         // MMCTX_LOAD_SWBASE
+       nv_iowr(NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE, 0, $r4)
+       nv_iowr(NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE, 0, $r4)
        add b32 $r3 0x1300
        add b32 $r1 $r15
        shr b32 $r15 2
-       iowr I[$r3 + 0x000] $r15        // MMCTX_LOAD_COUNT, wtf for?!?
+       nv_iowr(NV_PGRAPH_FECS_MMCTX_LOAD_COUNT, 0, $r15) // wtf??
 
        // strands, base offset needs to be aligned to 256 bytes
        shr b32 $r1 8
        add b32 $r1 1
        shl b32 $r1 8
        mov b32 $r15 $r1
-       call #strand_ctx_init
+       call(strand_ctx_init)
        add b32 $r1 $r15
 
        // initialise each GPC in sequence by passing in the offset of its
@@ -173,30 +173,29 @@ init:
        // in GPCn_CC_SCRATCH[1]
        //
        ld b32 $r3 D[$r0 + #gpc_count]
-       mov $r4 0x2000
-       sethi $r4 0x500000
+       imm32($r4, 0x502000)
        init_gpc:
                // setup, and start GPC ucode running
                add b32 $r14 $r4 0x804
                mov b32 $r15 $r1
-               call #nv_wr32                   // CC_SCRATCH[1] = ctx offset
+               call(nv_wr32)                   // CC_SCRATCH[1] = ctx offset
                add b32 $r14 $r4 0x10c
                clear b32 $r15
-               call #nv_wr32
+               call(nv_wr32)
                add b32 $r14 $r4 0x104
-               call #nv_wr32                   // ENTRY
+               call(nv_wr32)                   // ENTRY
                add b32 $r14 $r4 0x100
                mov $r15 2                      // CTRL_START_TRIGGER
-               call #nv_wr32                   // CTRL
+               call(nv_wr32)                   // CTRL
 
                // wait for it to complete, and adjust context size
                add b32 $r14 $r4 0x800
                init_gpc_wait:
-                       call #nv_rd32
+                       call(nv_rd32)
                        xbit $r15 $r15 31
                        bra e #init_gpc_wait
                add b32 $r14 $r4 0x804
-               call #nv_rd32
+               call(nv_rd32)
                add b32 $r1 $r15
 
                // next!
@@ -204,6 +203,12 @@ init:
                sub b32 $r3 1
                bra ne #init_gpc
 
+       //
+       mov $r15 0
+       call(ctx_86c)
+       mov $r15 0
+       call(ctx_4170s)
+
        // save context size, and tell host we're ready
        nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(1), 0, $r1)
        clear b32 $r1
@@ -218,17 +223,15 @@ main:
        bset $flags $p0
        sleep $p0
        mov $r13 #cmd_queue
-       call #queue_get
+       call(queue_get)
        bra $p1 #main
 
        // context switch, requested by GPU?
        cmpu b32 $r14 0x4001
        bra ne #main_not_ctx_switch
                trace_set(T_AUTO)
-               mov $r1 0xb00
-               shl b32 $r1 6
-               iord $r2 I[$r1 + 0x100]         // CHAN_NEXT
-               iord $r1 I[$r1 + 0x000]         // CHAN_CUR
+               nv_iord($r1, NV_PGRAPH_FECS_CHAN_ADDR, 0)
+               nv_iord($r2, NV_PGRAPH_FECS_CHAN_NEXT, 0)
 
                xbit $r3 $r1 31
                bra e #chsw_no_prev
@@ -239,12 +242,12 @@ main:
                                trace_set(T_SAVE)
                                bclr $flags $p1
                                bset $flags $p2
-                               call #ctx_xfer
+                               call(ctx_xfer)
                                trace_clr(T_SAVE);
                                pop $r2
                                trace_set(T_LOAD);
                                bset $flags $p1
-                               call #ctx_xfer
+                               call(ctx_xfer)
                                trace_clr(T_LOAD);
                                bra #chsw_done
                        chsw_prev_no_next:
@@ -252,25 +255,21 @@ main:
                                mov b32 $r2 $r1
                                bclr $flags $p1
                                bclr $flags $p2
-                               call #ctx_xfer
+                               call(ctx_xfer)
                                pop $r2
-                               mov $r1 0xb00
-                               shl b32 $r1 6
-                               iowr I[$r1] $r2
+                               nv_iowr(NV_PGRAPH_FECS_CHAN_ADDR, 0, $r2)
                                bra #chsw_done
                chsw_no_prev:
                        xbit $r3 $r2 31
                        bra e #chsw_done
                                bset $flags $p1
                                bclr $flags $p2
-                               call #ctx_xfer
+                               call(ctx_xfer)
 
                // ack the context switch request
                chsw_done:
-               mov $r1 0xb0c
-               shl b32 $r1 6
-               mov $r2 1
-               iowr I[$r1 + 0x000] $r2         // 0x409b0c
+               mov $r2 NV_PGRAPH_FECS_CHSW_ACK
+               nv_iowr(NV_PGRAPH_FECS_CHSW, 0, $r2)
                trace_clr(T_AUTO)
                bra #main
 
@@ -279,7 +278,7 @@ main:
        cmpu b32 $r14 0x0001
        bra ne #main_not_ctx_chan
                mov b32 $r2 $r15
-               call #ctx_chan
+               call(ctx_chan)
                bra #main_done
 
        // request to store current channel context?
@@ -289,14 +288,14 @@ main:
                trace_set(T_SAVE)
                bclr $flags $p1
                bclr $flags $p2
-               call #ctx_xfer
+               call(ctx_xfer)
                trace_clr(T_SAVE)
                bra #main_done
 
        main_not_ctx_save:
                shl b32 $r15 $r14 16
                or $r15 E_BAD_COMMAND
-               call #error
+               call(error)
                bra #main
 
        main_done:
@@ -319,41 +318,46 @@ ih:
        clear b32 $r0
 
        // incoming fifo command?
-       iord $r10 I[$r0 + 0x200]        // INTR
-       and $r11 $r10 0x00000004
+       nv_iord($r10, NV_PGRAPH_FECS_INTR, 0)
+       and $r11 $r10 NV_PGRAPH_FECS_INTR_FIFO
        bra e #ih_no_fifo
                // queue incoming fifo command for later processing
-               mov $r11 0x1900
                mov $r13 #cmd_queue
-               iord $r14 I[$r11 + 0x100]       // FIFO_CMD
-               iord $r15 I[$r11 + 0x000]       // FIFO_DATA
-               call #queue_put
+               nv_iord($r14, NV_PGRAPH_FECS_FIFO_CMD, 0)
+               nv_iord($r15, NV_PGRAPH_FECS_FIFO_DATA, 0)
+               call(queue_put)
                add b32 $r11 0x400
                mov $r14 1
-               iowr I[$r11 + 0x000] $r14       // FIFO_ACK
+               nv_iowr(NV_PGRAPH_FECS_FIFO_ACK, 0, $r14)
 
        // context switch request?
        ih_no_fifo:
-       and $r11 $r10 0x00000100
+       and $r11 $r10 NV_PGRAPH_FECS_INTR_CHSW
        bra e #ih_no_ctxsw
                // enqueue a context switch for later processing
                mov $r13 #cmd_queue
                mov $r14 0x4001
-               call #queue_put
+               call(queue_put)
 
-       // anything we didn't handle, bring it to the host's attention
+       // firmware method?
        ih_no_ctxsw:
-       mov $r11 0x104
+       and $r11 $r10 NV_PGRAPH_FECS_INTR_FWMTHD
+       bra e #ih_no_fwmthd
+               // none we handle, ack, and fall-through to unhandled
+               mov $r11 0x100
+               nv_wr32(0x400144, $r11)
+
+       // anything we didn't handle, bring it to the host's attention
+       ih_no_fwmthd:
+       mov $r11 0x104 // FIFO | CHSW
        not b32 $r11
        and $r11 $r10 $r11
        bra e #ih_no_other
-               mov $r10 0xc1c
-               shl b32 $r10 6
-               iowr I[$r10] $r11       // INTR_UP_SET
+               nv_iowr(NV_PGRAPH_FECS_INTR_UP_SET, 0, $r11)
 
        // ack, and wake up main()
        ih_no_other:
-       iowr I[$r0 + 0x100] $r10        // INTR_ACK
+       nv_iowr(NV_PGRAPH_FECS_INTR_ACK, 0, $r10)
 
        pop $r15
        pop $r14
@@ -370,12 +374,10 @@ ih:
 #if CHIPSET < GK100
 // Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
 ctx_4160s:
-       mov $r14 0x4160
-       sethi $r14 0x400000
        mov $r15 1
-       call #nv_wr32
+       nv_wr32(0x404160, $r15)
        ctx_4160s_wait:
-               call #nv_rd32
+               nv_rd32($r15, 0x404160)
                xbit $r15 $r15 4
                bra e #ctx_4160s_wait
        ret
@@ -384,10 +386,8 @@ ctx_4160s:
 // to hang with STATUS=0x00000007 until it's cleared.. fbcon can
 // still function with it set however...
 ctx_4160c:
-       mov $r14 0x4160
-       sethi $r14 0x400000
        clear b32 $r15
-       call #nv_wr32
+       nv_wr32(0x404160, $r15)
        ret
 #endif
 
@@ -396,18 +396,14 @@ ctx_4160c:
 // In: $r15 value to set 0x404170 to
 //
 ctx_4170s:
-       mov $r14 0x4170
-       sethi $r14 0x400000
        or $r15 0x10
-       call #nv_wr32
+       nv_wr32(0x404170, $r15)
        ret
 
 // Waits for a ctx_4170s() call to complete
 //
 ctx_4170w:
-       mov $r14 0x4170
-       sethi $r14 0x400000
-       call #nv_rd32
+       nv_rd32($r15, 0x404170)
        and $r15 0x10
        bra ne #ctx_4170w
        ret
@@ -419,16 +415,18 @@ ctx_4170w:
 // funny things happen.
 //
 ctx_redswitch:
-       mov $r14 0x614
-       shl b32 $r14 6
-       mov $r15 0x270
-       iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
+       mov $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_GPC
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_ROP
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_GPC
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_MAIN
+       nv_iowr(NV_PGRAPH_FECS_RED_SWITCH, 0, $r14)
        mov $r15 8
        ctx_redswitch_delay:
                sub b32 $r15 1
                bra ne #ctx_redswitch_delay
-       mov $r15 0x770
-       iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_ROP
+       or  $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_MAIN
+       nv_iowr(NV_PGRAPH_FECS_RED_SWITCH, 0, $r14)
        ret
 
 // Not a clue what this is for, except that unless the value is 0x10, the
@@ -437,15 +435,18 @@ ctx_redswitch:
 // In: $r15 value to set to (0x00/0x10 are used)
 //
 ctx_86c:
-       mov $r14 0x86c
-       shl b32 $r14 6
-       iowr I[$r14] $r15       // HUB(0x86c) = val
-       mov $r14 -0x75ec
-       sethi $r14 0x400000
-       call #nv_wr32           // ROP(0xa14) = val
-       mov $r14 -0x5794
-       sethi $r14 0x410000
-       call #nv_wr32           // GPC(0x86c) = val
+       nv_iowr(NV_PGRAPH_FECS_UNK86C, 0, $r15)
+       nv_wr32(0x408a14, $r15)
+       nv_wr32(NV_PGRAPH_GPCX_GPCCS_UNK86C, $r15)
+       ret
+
+// In: $r15 NV_PGRAPH_FECS_MEM_CMD_*
+ctx_mem:
+       nv_iowr(NV_PGRAPH_FECS_MEM_CMD, 0, $r15)
+       ctx_mem_wait:
+               nv_iord($r15, NV_PGRAPH_FECS_MEM_CMD, 0)
+               or $r15 $r15
+               bra ne #ctx_mem_wait
        ret
 
 // ctx_load - load's a channel's ctxctl data, and selects its vm
@@ -457,23 +458,14 @@ ctx_load:
 
        // switch to channel, somewhat magic in parts..
        mov $r10 12             // DONE_UNK12
-       call #wait_donez
-       mov $r1 0xa24
-       shl b32 $r1 6
-       iowr I[$r1 + 0x000] $r0 // 0x409a24
-       mov $r3 0xb00
-       shl b32 $r3 6
-       iowr I[$r3 + 0x100] $r2 // CHAN_NEXT
-       mov $r1 0xa0c
-       shl b32 $r1 6
-       mov $r4 7
-       iowr I[$r1 + 0x000] $r2 // MEM_CHAN
-       iowr I[$r1 + 0x100] $r4 // MEM_CMD
-       ctx_chan_wait_0:
-               iord $r4 I[$r1 + 0x100]
-               and $r4 0x1f
-               bra ne #ctx_chan_wait_0
-       iowr I[$r3 + 0x000] $r2 // CHAN_CUR
+       call(wait_donez)
+       clear b32 $r15
+       nv_iowr(0x409a24, 0, $r15)
+       nv_iowr(NV_PGRAPH_FECS_CHAN_NEXT, 0, $r2)
+       nv_iowr(NV_PGRAPH_FECS_MEM_CHAN, 0, $r2)
+       mov $r15 NV_PGRAPH_FECS_MEM_CMD_LOAD_CHAN
+       call(ctx_mem)
+       nv_iowr(NV_PGRAPH_FECS_CHAN_ADDR, 0, $r2)
 
        // load channel header, fetch PGRAPH context pointer
        mov $xtargets $r0
@@ -482,14 +474,10 @@ ctx_load:
        add b32 $r2 2
 
        trace_set(T_LCHAN)
-       mov $r1 0xa04
-       shl b32 $r1 6
-       iowr I[$r1 + 0x000] $r2         // MEM_BASE
-       mov $r1 0xa20
-       shl b32 $r1 6
-       mov $r2 0x0002
-       sethi $r2 0x80000000
-       iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vram
+       nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r2)
+       imm32($r2, NV_PGRAPH_FECS_MEM_TARGET_UNK31)
+       or  $r2 NV_PGRAPH_FECS_MEM_TARGET_AS_VRAM
+       nv_iowr(NV_PGRAPH_FECS_MEM_TARGET, 0, $r2)
        mov $r1 0x10                    // chan + 0x0210
        mov $r2 #xfer_data
        sethi $r2 0x00020000            // 16 bytes
@@ -507,13 +495,9 @@ ctx_load:
 
        // set transfer base to start of context, and fetch context header
        trace_set(T_LCTXH)
-       mov $r2 0xa04
-       shl b32 $r2 6
-       iowr I[$r2 + 0x000] $r1         // MEM_BASE
-       mov $r2 1
-       mov $r1 0xa20
-       shl b32 $r1 6
-       iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vm
+       nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r1)
+       mov $r2 NV_PGRAPH_FECS_MEM_TARGET_AS_VM
+       nv_iowr(NV_PGRAPH_FECS_MEM_TARGET, 0, $r2)
        mov $r1 #chan_data
        sethi $r1 0x00060000            // 256 bytes
        xdld $r0 $r1
@@ -532,21 +516,15 @@ ctx_load:
 //
 ctx_chan:
 #if CHIPSET < GK100
-       call #ctx_4160s
+       call(ctx_4160s)
 #endif
-       call #ctx_load
+       call(ctx_load)
        mov $r10 12                     // DONE_UNK12
-       call #wait_donez
-       mov $r1 0xa10
-       shl b32 $r1 6
-       mov $r2 5
-       iowr I[$r1 + 0x000] $r2         // MEM_CMD = 5 (???)
-       ctx_chan_wait:
-               iord $r2 I[$r1 + 0x000]
-               or $r2 $r2
-               bra ne #ctx_chan_wait
+       call(wait_donez)
+       mov $r15 5 // MEM_CMD 5 ???
+       call(ctx_mem)
 #if CHIPSET < GK100
-       call #ctx_4160c
+       call(ctx_4160c)
 #endif
        ret
 
@@ -562,9 +540,7 @@ ctx_chan:
 ctx_mmio_exec:
        // set transfer base to be the mmio list
        ld b32 $r3 D[$r0 + #chan_mmio_address]
-       mov $r2 0xa04
-       shl b32 $r2 6
-       iowr I[$r2 + 0x000] $r3         // MEM_BASE
+       nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r3)
 
        clear b32 $r3
        ctx_mmio_loop:
@@ -580,7 +556,7 @@ ctx_mmio_exec:
                ctx_mmio_pull:
                ld b32 $r14 D[$r4 + #xfer_data + 0x00]
                ld b32 $r15 D[$r4 + #xfer_data + 0x04]
-               call #nv_wr32
+               call(nv_wr32)
 
                // next!
                add b32 $r3 8
@@ -590,7 +566,7 @@ ctx_mmio_exec:
        // set transfer base back to the current context
        ctx_mmio_done:
        ld b32 $r3 D[$r0 + #ctx_current]
-       iowr I[$r2 + 0x000] $r3         // MEM_BASE
+       nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r3)
 
        // disable the mmio list now, we don't need/want to execute it again
        st b32 D[$r0 + #chan_mmio_count] $r0
@@ -610,12 +586,10 @@ ctx_mmio_exec:
 //
 ctx_xfer:
        // according to mwk, some kind of wait for idle
-       mov $r15 0xc00
-       shl b32 $r15 6
        mov $r14 4
-       iowr I[$r15 + 0x200] $r14
+       nv_iowr(0x409c08, 0, $r14)
        ctx_xfer_idle:
-               iord $r14 I[$r15 + 0x000]
+               nv_iord($r14, 0x409c00, 0)
                and $r14 0x2000
                bra ne #ctx_xfer_idle
 
@@ -623,50 +597,42 @@ ctx_xfer:
        bra $p2 #ctx_xfer_pre_load
        ctx_xfer_pre:
                mov $r15 0x10
-               call #ctx_86c
+               call(ctx_86c)
 #if CHIPSET < GK100
-               call #ctx_4160s
+               call(ctx_4160s)
 #endif
                bra not $p1 #ctx_xfer_exec
 
        ctx_xfer_pre_load:
                mov $r15 2
-               call #ctx_4170s
-               call #ctx_4170w
-               call #ctx_redswitch
+               call(ctx_4170s)
+               call(ctx_4170w)
+               call(ctx_redswitch)
                clear b32 $r15
-               call #ctx_4170s
-               call #ctx_load
+               call(ctx_4170s)
+               call(ctx_load)
 
        // fetch context pointer, and initiate xfer on all GPCs
        ctx_xfer_exec:
        ld b32 $r1 D[$r0 + #ctx_current]
-       mov $r2 0x414
-       shl b32 $r2 6
-       iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset
-       mov $r14 -0x5b00
-       sethi $r14 0x410000
-       mov b32 $r15 $r1
-       call #nv_wr32           // GPC_BCAST_WRCMD_DATA = ctx pointer
-       add b32 $r14 4
+
+       clear b32 $r2
+       nv_iowr(NV_PGRAPH_FECS_BAR, 0, $r2)
+
+       nv_wr32(0x41a500, $r1)  // GPC_BCAST_WRCMD_DATA = ctx pointer
        xbit $r15 $flags $p1
        xbit $r2 $flags $p2
        shl b32 $r2 1
        or $r15 $r2
-       call #nv_wr32           // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
+       nv_wr32(0x41a504, $r15) // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
 
        // strands
-       mov $r1 0x4afc
-       sethi $r1 0x20000
-       mov $r2 0xc
-       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0c
-       call #strand_wait
-       mov $r2 0x47fc
-       sethi $r2 0x20000
-       iowr I[$r2] $r0         // STRAND_FIRST_GENE(0x3f) = 0x00
-       xbit $r2 $flags $p1
-       add b32 $r2 3
-       iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
+       call(strand_pre)
+       clear b32 $r2
+       nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r2)
+       xbit $r2 $flags $p1     // SAVE/LOAD
+       add b32 $r2 NV_PGRAPH_FECS_STRAND_CMD_SAVE
+       nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r2)
 
        // mmio context
        xbit $r10 $flags $p1    // direction
@@ -675,48 +641,42 @@ ctx_xfer:
        ld b32 $r12 D[$r0 + #hub_mmio_list_head]
        ld b32 $r13 D[$r0 + #hub_mmio_list_tail]
        mov $r14 0              // not multi
-       call #mmctx_xfer
+       call(mmctx_xfer)
 
        // wait for GPCs to all complete
        mov $r10 8              // DONE_BAR
-       call #wait_doneo
+       call(wait_doneo)
 
        // wait for strand xfer to complete
-       call #strand_wait
+       call(strand_wait)
 
        // post-op
        bra $p1 #ctx_xfer_post
                mov $r10 12             // DONE_UNK12
-               call #wait_donez
-               mov $r1 0xa10
-               shl b32 $r1 6
-               mov $r2 5
-               iowr I[$r1] $r2         // MEM_CMD
-               ctx_xfer_post_save_wait:
-                       iord $r2 I[$r1]
-                       or $r2 $r2
-                       bra ne #ctx_xfer_post_save_wait
+               call(wait_donez)
+               mov $r15 5 // MEM_CMD 5 ???
+               call(ctx_mem)
 
        bra $p2 #ctx_xfer_done
        ctx_xfer_post:
                mov $r15 2
-               call #ctx_4170s
+               call(ctx_4170s)
                clear b32 $r15
-               call #ctx_86c
-               call #strand_post
-               call #ctx_4170w
+               call(ctx_86c)
+               call(strand_post)
+               call(ctx_4170w)
                clear b32 $r15
-               call #ctx_4170s
+               call(ctx_4170s)
 
                bra not $p1 #ctx_xfer_no_post_mmio
                ld b32 $r1 D[$r0 + #chan_mmio_count]
                or $r1 $r1
                bra e #ctx_xfer_no_post_mmio
-                       call #ctx_mmio_exec
+                       call(ctx_mmio_exec)
 
                ctx_xfer_no_post_mmio:
 #if CHIPSET < GK100
-               call #ctx_4160c
+               call(ctx_4160c)
 #endif
 
        ctx_xfer_done:
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5
new file mode 100644 (file)
index 0000000..7c5d256
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#define CHIPSET GK208
+#include "macros.fuc"
+
+.section #nv108_grhub_data
+#define INCLUDE_DATA
+#include "com.fuc"
+#include "hub.fuc"
+#undef INCLUDE_DATA
+
+.section #nv108_grhub_code
+#define INCLUDE_CODE
+bra #init
+#include "com.fuc"
+#include "hub.fuc"
+.align 256
+#undef INCLUDE_CODE
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h
new file mode 100644 (file)
index 0000000..4750984
--- /dev/null
@@ -0,0 +1,916 @@
+uint32_t nv108_grhub_data[] = {
+/* 0x0000: hub_mmio_list_head */
+       0x00000300,
+/* 0x0004: hub_mmio_list_tail */
+       0x00000304,
+/* 0x0008: gpc_count */
+       0x00000000,
+/* 0x000c: rop_count */
+       0x00000000,
+/* 0x0010: cmd_queue */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0058: ctx_current */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0100: chan_data */
+/* 0x0100: chan_mmio_count */
+       0x00000000,
+/* 0x0104: chan_mmio_address */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0200: xfer_data */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+/* 0x0300: hub_mmio_list_base */
+       0x0417e91c,
+};
+
+uint32_t nv108_grhub_code[] = {
+       0x030e0ef5,
+/* 0x0004: queue_put */
+       0x9800d898,
+       0x86f001d9,
+       0xf489a408,
+       0x020f0b1b,
+       0x0002f87e,
+/* 0x001a: queue_put_next */
+       0x98c400f8,
+       0x0384b607,
+       0xb6008dbb,
+       0x8eb50880,
+       0x018fb500,
+       0xf00190b6,
+       0xd9b50f94,
+/* 0x0037: queue_get */
+       0xf400f801,
+       0xd8980131,
+       0x01d99800,
+       0x0bf489a4,
+       0x0789c421,
+       0xbb0394b6,
+       0x90b6009d,
+       0x009e9808,
+       0xb6019f98,
+       0x84f00180,
+       0x00d8b50f,
+/* 0x0063: queue_get_done */
+       0xf80132f4,
+/* 0x0065: nv_rd32 */
+       0xf0ecb200,
+       0x00801fc9,
+       0x0cf601ca,
+/* 0x0073: nv_rd32_wait */
+       0x8c04bd00,
+       0xcf01ca00,
+       0xccc800cc,
+       0xf61bf41f,
+       0xec7e060a,
+       0x008f0000,
+       0xffcf01cb,
+/* 0x008f: nv_wr32 */
+       0x8000f800,
+       0xf601cc00,
+       0x04bd000f,
+       0xc9f0ecb2,
+       0x1ec9f01f,
+       0x01ca0080,
+       0xbd000cf6,
+/* 0x00a9: nv_wr32_wait */
+       0xca008c04,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f61b,
+/* 0x00b8: wait_donez */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x00cf: wait_donez_ne */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf61bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x00ec: wait_doneo */
+       0x99f094bd,
+       0x37008000,
+       0x0009f602,
+       0x008004bd,
+       0x0af60206,
+/* 0x0103: wait_doneo_e */
+       0x8804bd00,
+       0xcf010000,
+       0x8aff0088,
+       0xf60bf488,
+       0x99f094bd,
+       0x17008000,
+       0x0009f602,
+       0x00f804bd,
+/* 0x0120: mmctx_size */
+/* 0x0122: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0x1bf4efa4,
+       0xf89fb2ec,
+/* 0x013d: mmctx_xfer */
+       0xf094bd00,
+       0x00800199,
+       0x09f60237,
+       0xbd04bd00,
+       0x05bbfd94,
+       0x800f0bf4,
+       0xf601c400,
+       0x04bd000b,
+/* 0x015f: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0xc6008018,
+       0x000ef601,
+       0x008004bd,
+       0x0ff601c7,
+       0xf004bd00,
+/* 0x017a: mmctx_multi_disabled */
+       0xabc80199,
+       0x10b4b600,
+       0xc80cb9f0,
+       0xe4b601ae,
+       0x05befd11,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x0195: mmctx_exec_loop */
+/* 0x0195: mmctx_wait_free */
+       0xc5008e04,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f60b,
+       0x05e9fd00,
+       0x01c80080,
+       0xbd000ef6,
+       0x04c0b604,
+       0x1bf4cda4,
+       0x02abc8df,
+/* 0x01bf: mmctx_fini_wait */
+       0x8b1c1bf4,
+       0xcf01c500,
+       0xb4f000bb,
+       0x10b4b01f,
+       0x0af31bf4,
+       0x00b87e02,
+       0x250ef400,
+/* 0x01d8: mmctx_stop */
+       0xb600abc8,
+       0xb9f010b4,
+       0x12b9f00c,
+       0x01c50080,
+       0xbd000bf6,
+/* 0x01ed: mmctx_stop_wait */
+       0xc5008b04,
+       0x00bbcf01,
+       0xf412bbc8,
+/* 0x01fa: mmctx_done */
+       0x94bdf61b,
+       0x800199f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x020a: strand_wait */
+       0xa0f900f8,
+       0xb87e020a,
+       0xa0fc0000,
+/* 0x0216: strand_pre */
+       0x0c0900f8,
+       0x024afc80,
+       0xbd0009f6,
+       0x020a7e04,
+/* 0x0227: strand_post */
+       0x0900f800,
+       0x4afc800d,
+       0x0009f602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0238: strand_set */
+       0xfc800f0c,
+       0x0cf6024f,
+       0x0c04bd00,
+       0x4afc800b,
+       0x000cf602,
+       0xfc8004bd,
+       0x0ef6024f,
+       0x0c04bd00,
+       0x4afc800a,
+       0x000cf602,
+       0x0a7e04bd,
+       0x00f80002,
+/* 0x0268: strand_ctx_init */
+       0x99f094bd,
+       0x37008003,
+       0x0009f602,
+       0x167e04bd,
+       0x030e0002,
+       0x0002387e,
+       0xfc80c4bd,
+       0x0cf60247,
+       0x0c04bd00,
+       0x4afc8001,
+       0x000cf602,
+       0x0a7e04bd,
+       0x0c920002,
+       0x46fc8001,
+       0x000cf602,
+       0x020c04bd,
+       0x024afc80,
+       0xbd000cf6,
+       0x020a7e04,
+       0x02277e00,
+       0x42008800,
+       0x20008902,
+       0x0099cf02,
+/* 0x02c7: ctx_init_strand_loop */
+       0xf608fe95,
+       0x8ef6008e,
+       0x808acf40,
+       0xb606a5b6,
+       0xeabb01a0,
+       0x0480b600,
+       0xf40192b6,
+       0xe4b6e81b,
+       0xf2efbc08,
+       0x99f094bd,
+       0x17008003,
+       0x0009f602,
+       0x00f804bd,
+/* 0x02f8: error */
+       0x02050080,
+       0xbd000ff6,
+       0x80010f04,
+       0xf6030700,
+       0x04bd000f,
+/* 0x030e: init */
+       0x04bd00f8,
+       0x410007fe,
+       0x11cf4200,
+       0x0911e700,
+       0x0814b601,
+       0x020014fe,
+       0x12004002,
+       0xbd0002f6,
+       0x05c94104,
+       0xbd0010fe,
+       0x07004024,
+       0xbd0002f6,
+       0x20034204,
+       0x01010080,
+       0xbd0002f6,
+       0x20044204,
+       0x01010480,
+       0xbd0002f6,
+       0x200b4204,
+       0x01010880,
+       0xbd0002f6,
+       0x200c4204,
+       0x01011c80,
+       0xbd0002f6,
+       0x01039204,
+       0x03090080,
+       0xbd0003f6,
+       0x87044204,
+       0xf6040040,
+       0x04bd0002,
+       0x00400402,
+       0x0002f603,
+       0x31f404bd,
+       0x96048e10,
+       0x00657e40,
+       0xc7feb200,
+       0x01b590f1,
+       0x1ff4f003,
+       0x01020fb5,
+       0x041fbb01,
+       0x800112b6,
+       0xf6010300,
+       0x04bd0001,
+       0x01040080,
+       0xbd0001f6,
+       0x01004104,
+       0x627e020f,
+       0x717e0006,
+       0x100f0006,
+       0x0006b37e,
+       0x98000e98,
+       0x207e010f,
+       0x14950001,
+       0xc0008008,
+       0x0004f601,
+       0x008004bd,
+       0x04f601c1,
+       0xb704bd00,
+       0xbb130030,
+       0xf5b6001f,
+       0xd3008002,
+       0x000ff601,
+       0x15b604bd,
+       0x0110b608,
+       0xb20814b6,
+       0x02687e1f,
+       0x001fbb00,
+       0x84020398,
+/* 0x041f: init_gpc */
+       0xb8502000,
+       0x0008044e,
+       0x8f7e1fb2,
+       0x4eb80000,
+       0xbd00010c,
+       0x008f7ef4,
+       0x044eb800,
+       0x8f7e0001,
+       0x4eb80000,
+       0x0f000100,
+       0x008f7e02,
+       0x004eb800,
+/* 0x044e: init_gpc_wait */
+       0x657e0008,
+       0xffc80000,
+       0xf90bf41f,
+       0x08044eb8,
+       0x00657e00,
+       0x001fbb00,
+       0x800040b7,
+       0xf40132b6,
+       0x000fb41b,
+       0x0006b37e,
+       0x627e000f,
+       0x00800006,
+       0x01f60201,
+       0xbd04bd00,
+       0x1f19f014,
+       0x02300080,
+       0xbd0001f6,
+/* 0x0491: main */
+       0x0031f404,
+       0x0d0028f4,
+       0x00377e10,
+       0xf401f400,
+       0x4001e4b1,
+       0x00c71bf5,
+       0x99f094bd,
+       0x37008004,
+       0x0009f602,
+       0x008104bd,
+       0x11cf02c0,
+       0xc1008200,
+       0x0022cf02,
+       0xf41f13c8,
+       0x23c8770b,
+       0x550bf41f,
+       0x12b220f9,
+       0x99f094bd,
+       0x37008007,
+       0x0009f602,
+       0x32f404bd,
+       0x0231f401,
+       0x0008367e,
+       0x99f094bd,
+       0x17008007,
+       0x0009f602,
+       0x20fc04bd,
+       0x99f094bd,
+       0x37008006,
+       0x0009f602,
+       0x31f404bd,
+       0x08367e01,
+       0xf094bd00,
+       0x00800699,
+       0x09f60217,
+       0xf404bd00,
+/* 0x0522: chsw_prev_no_next */
+       0x20f92f0e,
+       0x32f412b2,
+       0x0232f401,
+       0x0008367e,
+       0x008020fc,
+       0x02f602c0,
+       0xf404bd00,
+/* 0x053e: chsw_no_prev */
+       0x23c8130e,
+       0x0d0bf41f,
+       0xf40131f4,
+       0x367e0232,
+/* 0x054e: chsw_done */
+       0x01020008,
+       0x02c30080,
+       0xbd0002f6,
+       0xf094bd04,
+       0x00800499,
+       0x09f60217,
+       0xf504bd00,
+/* 0x056b: main_not_ctx_switch */
+       0xb0ff2a0e,
+       0x1bf401e4,
+       0x7ef2b20c,
+       0xf40007d6,
+/* 0x057a: main_not_ctx_chan */
+       0xe4b0400e,
+       0x2c1bf402,
+       0x99f094bd,
+       0x37008007,
+       0x0009f602,
+       0x32f404bd,
+       0x0232f401,
+       0x0008367e,
+       0x99f094bd,
+       0x17008007,
+       0x0009f602,
+       0x0ef404bd,
+/* 0x05a9: main_not_ctx_save */
+       0x10ef9411,
+       0x7e01f5f0,
+       0xf50002f8,
+/* 0x05b7: main_done */
+       0xbdfede0e,
+       0x1f29f024,
+       0x02300080,
+       0xbd0002f6,
+       0xcc0ef504,
+/* 0x05c9: ih */
+       0xfe80f9fe,
+       0x80f90188,
+       0xa0f990f9,
+       0xd0f9b0f9,
+       0xf0f9e0f9,
+       0x004a04bd,
+       0x00aacf02,
+       0xf404abc4,
+       0x100d230b,
+       0xcf1a004e,
+       0x004f00ee,
+       0x00ffcf19,
+       0x0000047e,
+       0x0400b0b7,
+       0x0040010e,
+       0x000ef61d,
+/* 0x060a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x4e100d0c,
+       0x047e4001,
+/* 0x061a: ih_no_ctxsw */
+       0xabe40000,
+       0x0bf40400,
+       0x01004b10,
+       0x448ebfb2,
+       0x8f7e4001,
+/* 0x062e: ih_no_fwmthd */
+       0x044b0000,
+       0xffb0bd01,
+       0x0bf4b4ab,
+       0x0700800c,
+       0x000bf603,
+/* 0x0642: ih_no_other */
+       0x004004bd,
+       0x000af601,
+       0xf0fc04bd,
+       0xd0fce0fc,
+       0xa0fcb0fc,
+       0x80fc90fc,
+       0xfc0088fe,
+       0x0032f480,
+/* 0x0662: ctx_4170s */
+       0xf5f001f8,
+       0x8effb210,
+       0x7e404170,
+       0xf800008f,
+/* 0x0671: ctx_4170w */
+       0x41708e00,
+       0x00657e40,
+       0xf0ffb200,
+       0x1bf410f4,
+/* 0x0683: ctx_redswitch */
+       0x4e00f8f3,
+       0xe5f00200,
+       0x20e5f040,
+       0x8010e5f0,
+       0xf6018500,
+       0x04bd000e,
+/* 0x069a: ctx_redswitch_delay */
+       0xf2b6080f,
+       0xfd1bf401,
+       0x0400e5f1,
+       0x0100e5f1,
+       0x01850080,
+       0xbd000ef6,
+/* 0x06b3: ctx_86c */
+       0x8000f804,
+       0xf6022300,
+       0x04bd000f,
+       0x148effb2,
+       0x8f7e408a,
+       0xffb20000,
+       0x41a88c8e,
+       0x00008f7e,
+/* 0x06d2: ctx_mem */
+       0x008000f8,
+       0x0ff60284,
+/* 0x06db: ctx_mem_wait */
+       0x8f04bd00,
+       0xcf028400,
+       0xfffd00ff,
+       0xf61bf405,
+/* 0x06ea: ctx_load */
+       0x94bd00f8,
+       0x800599f0,
+       0xf6023700,
+       0x04bd0009,
+       0xb87e0c0a,
+       0xf4bd0000,
+       0x02890080,
+       0xbd000ff6,
+       0xc1008004,
+       0x0002f602,
+       0x008004bd,
+       0x02f60283,
+       0x0f04bd00,
+       0x06d27e07,
+       0xc0008000,
+       0x0002f602,
+       0x0bfe04bd,
+       0x1f2af000,
+       0xb60424b6,
+       0x94bd0220,
+       0x800899f0,
+       0xf6023700,
+       0x04bd0009,
+       0x02810080,
+       0xbd0002f6,
+       0x0000d204,
+       0x25f08000,
+       0x88008002,
+       0x0002f602,
+       0x100104bd,
+       0xf0020042,
+       0x12fa0223,
+       0xbd03f805,
+       0x0899f094,
+       0x02170080,
+       0xbd0009f6,
+       0x81019804,
+       0x981814b6,
+       0x25b68002,
+       0x0512fd08,
+       0xbd1601b5,
+       0x0999f094,
+       0x02370080,
+       0xbd0009f6,
+       0x81008004,
+       0x0001f602,
+       0x010204bd,
+       0x02880080,
+       0xbd0002f6,
+       0x01004104,
+       0xfa0613f0,
+       0x03f80501,
+       0x99f094bd,
+       0x17008009,
+       0x0009f602,
+       0x94bd04bd,
+       0x800599f0,
+       0xf6021700,
+       0x04bd0009,
+/* 0x07d6: ctx_chan */
+       0xea7e00f8,
+       0x0c0a0006,
+       0x0000b87e,
+       0xd27e050f,
+       0x00f80006,
+/* 0x07e8: ctx_mmio_exec */
+       0x80410398,
+       0xf6028100,
+       0x04bd0003,
+/* 0x07f6: ctx_mmio_loop */
+       0x34c434bd,
+       0x0e1bf4ff,
+       0xf0020045,
+       0x35fa0653,
+/* 0x0807: ctx_mmio_pull */
+       0x9803f805,
+       0x4f98804e,
+       0x008f7e81,
+       0x0830b600,
+       0xf40112b6,
+/* 0x081a: ctx_mmio_done */
+       0x0398df1b,
+       0x81008016,
+       0x0003f602,
+       0x00b504bd,
+       0x01004140,
+       0xfa0613f0,
+       0x03f80601,
+/* 0x0836: ctx_xfer */
+       0x040e00f8,
+       0x03020080,
+       0xbd000ef6,
+/* 0x0841: ctx_xfer_idle */
+       0x00008e04,
+       0x00eecf03,
+       0x2000e4f1,
+       0xf4f51bf4,
+       0x02f40611,
+/* 0x0855: ctx_xfer_pre */
+       0x7e100f0c,
+       0xf40006b3,
+/* 0x085e: ctx_xfer_pre_load */
+       0x020f1b11,
+       0x0006627e,
+       0x0006717e,
+       0x0006837e,
+       0x627ef4bd,
+       0xea7e0006,
+/* 0x0876: ctx_xfer_exec */
+       0x01980006,
+       0x8024bd16,
+       0xf6010500,
+       0x04bd0002,
+       0x008e1fb2,
+       0x8f7e41a5,
+       0xfcf00000,
+       0x022cf001,
+       0xfd0124b6,
+       0xffb205f2,
+       0x41a5048e,
+       0x00008f7e,
+       0x0002167e,
+       0xfc8024bd,
+       0x02f60247,
+       0xf004bd00,
+       0x20b6012c,
+       0x4afc8003,
+       0x0002f602,
+       0xacf004bd,
+       0x06a5f001,
+       0x0c98000b,
+       0x010d9800,
+       0x3d7e000e,
+       0x080a0001,
+       0x0000ec7e,
+       0x00020a7e,
+       0x0a1201f4,
+       0x00b87e0c,
+       0x7e050f00,
+       0xf40006d2,
+/* 0x08f2: ctx_xfer_post */
+       0x020f2d02,
+       0x0006627e,
+       0xb37ef4bd,
+       0x277e0006,
+       0x717e0002,
+       0xf4bd0006,
+       0x0006627e,
+       0x981011f4,
+       0x11fd4001,
+       0x070bf405,
+       0x0007e87e,
+/* 0x091c: ctx_xfer_no_post_mmio */
+/* 0x091c: ctx_xfer_done */
+       0x000000f8,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+};
index b59f694c0423e35afddc26e2388ae8a7d6514472..132f684b1946a9357697eace024fa866af43b72f 100644 (file)
@@ -206,14 +206,14 @@ uint32_t nvc0_grhub_data[] = {
 };
 
 uint32_t nvc0_grhub_code[] = {
-       0x031b0ef5,
+       0x039b0ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvc0_grhub_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvc0_grhub_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0x07f100f8,
        0x03f00500,
        0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvc0_grhub_code[] = {
        0x0007f101,
        0x0303f007,
        0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
        0xbd00f804,
-       0x0004fe04,
-       0xf10007fe,
-       0xf0120017,
-       0x12d00227,
-       0xb117f100,
-       0x0010fe05,
-       0x040017f1,
-       0xf1c010d0,
-       0xb6040437,
-       0x27f10634,
-       0x32d02003,
-       0x0427f100,
-       0x0132d020,
+       0x0007fe04,
+       0x420017f1,
+       0xcf0013f0,
+       0x11e70011,
+       0x14b60109,
+       0x0014fe08,
+       0xf10227f0,
+       0xf0120007,
+       0x02d00003,
+       0xf104bd00,
+       0xfe06c817,
+       0x24bd0010,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0002,
+       0x200327f1,
+       0x010007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200427f1,
+       0x010407f1,
+       0xd00103f0,
+       0x04bd0002,
        0x200b27f1,
-       0xf10232d0,
-       0xd0200c27,
-       0x27f10732,
-       0x24b60c24,
-       0x0003b906,
-       0xf10023d0,
+       0x010807f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200c27f1,
+       0x011c07f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1010392,
+       0xf0090007,
+       0x03d00303,
+       0xf104bd00,
        0xf0870427,
-       0x12d00023,
-       0x0012b700,
-       0x0427f001,
-       0xf40012d0,
-       0xe7f11031,
-       0xe3f09604,
-       0x6821f440,
-       0x8090f1c7,
-       0xf4f00301,
-       0x020f801f,
-       0xbb0117f0,
-       0x12b6041f,
-       0x0c27f101,
-       0x0624b604,
-       0xd00021d0,
-       0x17f14021,
-       0x0e980100,
-       0x010f9800,
-       0x014721f5,
-       0x070037f1,
-       0x950634b6,
-       0x34d00814,
-       0x4034d000,
-       0x130030b7,
-       0xb6001fbb,
-       0x3fd002f5,
-       0x0815b600,
-       0xb60110b6,
-       0x1fb90814,
-       0x7121f502,
-       0x001fbb02,
-       0xf1020398,
-       0xf0200047,
-/* 0x03f6: init_gpc */
-       0x4ea05043,
-       0x1fb90804,
-       0x8d21f402,
-       0x010c4ea0,
-       0x21f4f4bd,
-       0x044ea08d,
-       0x8d21f401,
-       0x01004ea0,
-       0xf402f7f0,
-       0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-       0x21f40800,
-       0x1fffc868,
-       0xa0fa0bf4,
-       0xf408044e,
-       0x1fbb6821,
-       0x0040b700,
-       0x0132b680,
-       0xf1be1bf4,
+       0x07f10023,
+       0x03f00400,
+       0x0002d000,
+       0x27f004bd,
+       0x0007f104,
+       0x0003f003,
+       0xbd0002d0,
+       0x1031f404,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xfeb96821,
+       0x90f1c702,
+       0xf0030180,
+       0x0f801ff4,
+       0x0117f002,
+       0xb6041fbb,
+       0x07f10112,
+       0x03f00300,
+       0x0001d001,
+       0x07f104bd,
+       0x03f00400,
+       0x0001d001,
+       0x17f104bd,
+       0xf7f00100,
+       0xb521f502,
+       0xc721f507,
+       0x10f7f007,
+       0x081421f5,
+       0x98000e98,
+       0x21f5010f,
+       0x14950150,
+       0x0007f108,
+       0x0103f0c0,
+       0xbd0004d0,
+       0x0007f104,
+       0x0103f0c1,
+       0xbd0004d0,
+       0x0030b704,
+       0x001fbb13,
+       0xf102f5b6,
+       0xf0d30007,
+       0x0fd00103,
+       0xb604bd00,
+       0x10b60815,
+       0x0814b601,
+       0xf5021fb9,
+       0xbb02d321,
+       0x0398001f,
+       0x0047f102,
+       0x5043f020,
+/* 0x04f4: init_gpc */
+       0x08044ea0,
+       0xf4021fb9,
+       0x4ea09d21,
+       0xf4bd010c,
+       0xa09d21f4,
+       0xf401044e,
+       0x4ea09d21,
+       0xf7f00100,
+       0x9d21f402,
+       0x08004ea0,
+/* 0x051c: init_gpc_wait */
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x00f7f0be,
+       0x081421f5,
+       0xf500f7f0,
+       0xf107b521,
        0xf0010007,
        0x01d00203,
        0xbd04bd00,
@@ -519,402 +584,399 @@ uint32_t nvc0_grhub_code[] = {
        0x080007f1,
        0xd00203f0,
        0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
        0xf40031f4,
        0xd7f00028,
        0x3921f410,
        0xb1f401f4,
        0xf54001e4,
-       0xbd00de1b,
+       0xbd00e91b,
        0x0499f094,
        0x0f0007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0b0017f1,
-       0xcf0614b6,
-       0x11cf4012,
-       0x1f13c800,
-       0x00870bf5,
-       0xf41f23c8,
-       0x20f9620b,
-       0xbd0212b9,
-       0x0799f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0xf40132f4,
-       0x21f50231,
-       0x94bd082f,
+       0xc00017f1,
+       0xcf0213f0,
+       0x27f10011,
+       0x23f0c100,
+       0x0022cf02,
+       0xf51f13c8,
+       0xc800890b,
+       0x0bf41f23,
+       0xb920f962,
+       0x94bd0212,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
-       0xfc04bd00,
-       0xf094bd20,
-       0x07f10699,
-       0x03f00f00,
-       0x0009d002,
-       0x31f404bd,
-       0x2f21f501,
-       0xf094bd08,
-       0x07f10699,
+       0xf404bd00,
+       0x31f40132,
+       0xe821f502,
+       0xf094bd09,
+       0x07f10799,
        0x03f01700,
        0x0009d002,
-       0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-       0xb920f931,
-       0x32f40212,
-       0x0232f401,
-       0x082f21f5,
-       0x17f120fc,
-       0x14b60b00,
-       0x0012d006,
-/* 0x0517: chsw_no_prev */
-       0xc8130ef4,
-       0x0bf41f23,
-       0x0131f40d,
-       0xf50232f4,
-/* 0x0527: chsw_done */
-       0xf1082f21,
-       0xb60b0c17,
-       0x27f00614,
-       0x0012d001,
+       0x20fc04bd,
        0x99f094bd,
-       0x0007f104,
+       0x0007f106,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0131f404,
+       0x09e821f5,
+       0x99f094bd,
+       0x0007f106,
        0x0203f017,
        0xbd0009d0,
-       0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-       0x01e4b0ff,
-       0xb90d1bf4,
-       0x21f502f2,
-       0x0ef407bb,
-/* 0x0559: main_not_ctx_chan */
-       0x02e4b046,
-       0xbd321bf4,
-       0x0799f094,
-       0x0f0007f1,
+       0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+       0x12b920f9,
+       0x0132f402,
+       0xf50232f4,
+       0xfc09e821,
+       0x0007f120,
+       0x0203f0c0,
+       0xbd0002d0,
+       0x130ef404,
+/* 0x062c: chsw_no_prev */
+       0xf41f23c8,
+       0x31f40d0b,
+       0x0232f401,
+       0x09e821f5,
+/* 0x063c: chsw_done */
+       0xf10127f0,
+       0xf0c30007,
+       0x02d00203,
+       0xbd04bd00,
+       0x0499f094,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0xf40132f4,
-       0x21f50232,
-       0x94bd082f,
+       0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+       0xf401e4b0,
+       0xf2b90d1b,
+       0x7821f502,
+       0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+       0xf402e4b0,
+       0x94bd321b,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
        0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-       0xef94110e,
-       0x01f5f010,
-       0x02fe21f5,
-       0xfec00ef5,
-/* 0x059c: main_done */
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f008,
-       0xbd0002d0,
-       0xab0ef504,
-/* 0x05b1: ih */
-       0xfe80f9fe,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x0acf04bd,
-       0x04abc480,
-       0xf11d0bf4,
-       0xf01900b7,
-       0xbecf10d7,
-       0x00bfcf40,
+       0x32f40132,
+       0xe821f502,
+       0xf094bd09,
+       0x07f10799,
+       0x03f01700,
+       0x0009d002,
+       0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+       0x10ef9411,
+       0xf501f5f0,
+       0xf5037e21,
+/* 0x06b3: main_done */
+       0xbdfeb50e,
+       0x1f29f024,
+       0x080007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xfea00ef5,
+/* 0x06c8: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x10d7f030,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
        0xb70421f4,
        0xf00400b0,
-       0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-       0x00abe400,
-       0x0d0bf401,
-       0xf110d7f0,
-       0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-       0xb7f10421,
-       0xb0bd0104,
-       0xf4b4abff,
-       0xa7f10d0b,
-       0xa4b60c1c,
-       0x00abd006,
-/* 0x0610: ih_no_other */
-       0xfc400ad0,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x071a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x10d7f00d,
+       0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+       0xe40421f4,
+       0xf40400ab,
+       0xb7f1140b,
+       0xbfb90100,
+       0x44e7f102,
+       0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+       0xf19d21f4,
+       0xbd0104b7,
+       0xb4abffb0,
+       0xf10f0bf4,
+       0xf0070007,
+       0x0bd00303,
+/* 0x075b: ih_no_other */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
        0xfce0fcf0,
        0xfcb0fcd0,
        0xfc90fca0,
        0x0088fe80,
        0x32f480fc,
-/* 0x062b: ctx_4160s */
-       0xf101f800,
-       0xf04160e7,
-       0xf7f040e3,
-       0x8d21f401,
-/* 0x0638: ctx_4160s_wait */
-       0xc86821f4,
-       0x0bf404ff,
-/* 0x0643: ctx_4160c */
-       0xf100f8fa,
+/* 0x077f: ctx_4160s */
+       0xf001f800,
+       0xffb901f7,
+       0x60e7f102,
+       0x40e3f041,
+/* 0x078f: ctx_4160s_wait */
+       0xf19d21f4,
        0xf04160e7,
-       0xf4bd40e3,
-       0xf88d21f4,
-/* 0x0651: ctx_4170s */
-       0x70e7f100,
+       0x21f440e3,
+       0x02ffb968,
+       0xf404ffc8,
+       0x00f8f00b,
+/* 0x07a4: ctx_4160c */
+       0xffb9f4bd,
+       0x60e7f102,
        0x40e3f041,
-       0xf410f5f0,
-       0x00f88d21,
-/* 0x0660: ctx_4170w */
-       0x4170e7f1,
-       0xf440e3f0,
-       0xf4f06821,
-       0xf31bf410,
-/* 0x0672: ctx_redswitch */
-       0xe7f100f8,
-       0xe4b60614,
-       0x70f7f106,
-       0x00efd002,
-/* 0x0683: ctx_redswitch_delay */
-       0xb608f7f0,
-       0x1bf401f2,
-       0x70f7f1fd,
-       0x00efd007,
-/* 0x0692: ctx_86c */
-       0xe7f100f8,
-       0xe4b6086c,
-       0x00efd006,
-       0x8a14e7f1,
-       0xf440e3f0,
-       0xe7f18d21,
-       0xe3f0a86c,
-       0x8d21f441,
-/* 0x06b2: ctx_load */
+       0xf89d21f4,
+/* 0x07b5: ctx_4170s */
+       0x10f5f000,
+       0xf102ffb9,
+       0xf04170e7,
+       0x21f440e3,
+/* 0x07c7: ctx_4170w */
+       0xf100f89d,
+       0xf04170e7,
+       0x21f440e3,
+       0x02ffb968,
+       0xf410f4f0,
+       0x00f8f01b,
+/* 0x07dc: ctx_redswitch */
+       0x0200e7f1,
+       0xf040e5f0,
+       0xe5f020e5,
+       0x0007f110,
+       0x0103f085,
+       0xbd000ed0,
+       0x08f7f004,
+/* 0x07f8: ctx_redswitch_delay */
+       0xf401f2b6,
+       0xe5f1fd1b,
+       0xe5f10400,
+       0x07f10100,
+       0x03f08500,
+       0x000ed001,
+       0x00f804bd,
+/* 0x0814: ctx_86c */
+       0x1b0007f1,
+       0xd00203f0,
+       0x04bd000f,
+       0xf102ffb9,
+       0xf08a14e7,
+       0x21f440e3,
+       0x02ffb99d,
+       0xa86ce7f1,
+       0xf441e3f0,
+       0x00f89d21,
+/* 0x083c: ctx_mem */
+       0x840007f1,
+       0xd00203f0,
+       0x04bd000f,
+/* 0x0848: ctx_mem_wait */
+       0x8400f7f1,
+       0xcf02f3f0,
+       0xfffd00ff,
+       0xf31bf405,
+/* 0x085a: ctx_load */
        0x94bd00f8,
        0xf10599f0,
        0xf00f0007,
        0x09d00203,
        0xf004bd00,
        0x21f40ca7,
-       0x2417f1c9,
-       0x0614b60a,
-       0xf10010d0,
-       0xb60b0037,
-       0x32d00634,
-       0x0c17f140,
-       0x0614b60a,
-       0xd00747f0,
-       0x14d00012,
-/* 0x06ed: ctx_chan_wait_0 */
-       0x4014cf40,
-       0xf41f44f0,
-       0x32d0fa1b,
-       0x000bfe00,
-       0xb61f2af0,
-       0x20b60424,
-       0xf094bd02,
+       0xf1f4bdd0,
+       0xf0890007,
+       0x0fd00203,
+       0xf104bd00,
+       0xf0c10007,
+       0x02d00203,
+       0xf104bd00,
+       0xf0830007,
+       0x02d00203,
+       0xf004bd00,
+       0x21f507f7,
+       0x07f1083c,
+       0x03f0c000,
+       0x0002d002,
+       0x0bfe04bd,
+       0x1f2af000,
+       0xb60424b6,
+       0x94bd0220,
+       0xf10899f0,
+       0xf00f0007,
+       0x09d00203,
+       0xf104bd00,
+       0xf0810007,
+       0x02d00203,
+       0xf104bd00,
+       0xf1000027,
+       0xf0800023,
+       0x07f10225,
+       0x03f08800,
+       0x0002d002,
+       0x17f004bd,
+       0x0027f110,
+       0x0223f002,
+       0xf80512fa,
+       0xf094bd03,
        0x07f10899,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x17f104bd,
-       0x14b60a04,
-       0x0012d006,
-       0x0a2017f1,
-       0xf00614b6,
-       0x23f10227,
-       0x12d08000,
-       0x1017f000,
-       0x020027f1,
-       0xfa0223f0,
-       0x03f80512,
+       0x019804bd,
+       0x1814b681,
+       0xb6800298,
+       0x12fd0825,
+       0x16018005,
        0x99f094bd,
-       0x0007f108,
-       0x0203f017,
+       0x0007f109,
+       0x0203f00f,
        0xbd0009d0,
-       0x81019804,
-       0x981814b6,
-       0x25b68002,
-       0x0512fd08,
-       0xbd160180,
-       0x0999f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0x0a0427f1,
-       0xd00624b6,
-       0x27f00021,
-       0x2017f101,
-       0x0614b60a,
-       0xf10012d0,
-       0xf0010017,
-       0x01fa0613,
-       0xbd03f805,
-       0x0999f094,
-       0x170007f1,
+       0x0007f104,
+       0x0203f081,
+       0xbd0001d0,
+       0x0127f004,
+       0x880007f1,
        0xd00203f0,
-       0x04bd0009,
+       0x04bd0002,
+       0x010017f1,
+       0xfa0613f0,
+       0x03f80501,
        0x99f094bd,
-       0x0007f105,
+       0x0007f109,
        0x0203f017,
        0xbd0009d0,
-/* 0x07bb: ctx_chan */
-       0xf500f804,
-       0xf5062b21,
-       0xf006b221,
-       0x21f40ca7,
-       0x1017f1c9,
-       0x0614b60a,
-       0xd00527f0,
-/* 0x07d6: ctx_chan_wait */
-       0x12cf0012,
-       0x0522fd00,
-       0xf5fa1bf4,
-       0xf8064321,
-/* 0x07e5: ctx_mmio_exec */
-       0x41039800,
-       0x0a0427f1,
-       0xd00624b6,
-       0x34bd0023,
-/* 0x07f4: ctx_mmio_loop */
+       0xf094bd04,
+       0x07f10599,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0978: ctx_chan */
+       0x077f21f5,
+       0x085a21f5,
+       0xf40ca7f0,
+       0xf7f0d021,
+       0x3c21f505,
+       0xa421f508,
+/* 0x0993: ctx_mmio_exec */
+       0x9800f807,
+       0x07f14103,
+       0x03f08100,
+       0x0003d002,
+       0x34bd04bd,
+/* 0x09a4: ctx_mmio_loop */
        0xf4ff34c4,
        0x57f10f1b,
        0x53f00200,
        0x0535fa06,
-/* 0x0806: ctx_mmio_pull */
+/* 0x09b6: ctx_mmio_pull */
        0x4e9803f8,
        0x814f9880,
-       0xb68d21f4,
+       0xb69d21f4,
        0x12b60830,
        0xdf1bf401,
-/* 0x0818: ctx_mmio_done */
-       0xd0160398,
-       0x00800023,
-       0x0017f140,
-       0x0613f001,
-       0xf80601fa,
-/* 0x082f: ctx_xfer */
-       0xf100f803,
-       0xb60c00f7,
-       0xe7f006f4,
-       0x80fed004,
-/* 0x083c: ctx_xfer_idle */
-       0xf100fecf,
-       0xf42000e4,
-       0x11f4f91b,
-       0x1102f406,
-/* 0x084c: ctx_xfer_pre */
-       0xf510f7f0,
-       0xf5069221,
-       0xf4062b21,
-/* 0x085a: ctx_xfer_pre_load */
-       0xf7f01c11,
-       0x5121f502,
-       0x6021f506,
-       0x7221f506,
-       0xf5f4bd06,
-       0xf5065121,
-/* 0x0873: ctx_xfer_exec */
-       0x9806b221,
-       0x27f11601,
-       0x24b60414,
-       0x0020d006,
-       0xa500e7f1,
-       0xb941e3f0,
-       0x21f4021f,
-       0x04e0b68d,
-       0xf001fcf0,
-       0x24b6022c,
-       0x05f2fd01,
-       0xf18d21f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00c,
-       0x021521f5,
-       0x47fc27f1,
-       0xd00223f0,
-       0x2cf00020,
+/* 0x09c8: ctx_mmio_done */
+       0xf1160398,
+       0xf0810007,
+       0x03d00203,
+       0x8004bd00,
+       0x17f14000,
+       0x13f00100,
+       0x0601fa06,
+       0x00f803f8,
+/* 0x09e8: ctx_xfer */
+       0xf104e7f0,
+       0xf0020007,
+       0x0ed00303,
+/* 0x09f7: ctx_xfer_idle */
+       0xf104bd00,
+       0xf00000e7,
+       0xeecf03e3,
+       0x00e4f100,
+       0xf21bf420,
+       0xf40611f4,
+/* 0x0a0e: ctx_xfer_pre */
+       0xf7f01102,
+       0x1421f510,
+       0x7f21f508,
+       0x1c11f407,
+/* 0x0a1c: ctx_xfer_pre_load */
+       0xf502f7f0,
+       0xf507b521,
+       0xf507c721,
+       0xbd07dc21,
+       0xb521f5f4,
+       0x5a21f507,
+/* 0x0a35: ctx_xfer_exec */
+       0x16019808,
+       0x07f124bd,
+       0x03f00500,
+       0x0002d001,
+       0x1fb904bd,
+       0x00e7f102,
+       0x41e3f0a5,
+       0xf09d21f4,
+       0x2cf001fc,
+       0x0124b602,
+       0xb905f2fd,
+       0xe7f102ff,
+       0xe3f0a504,
+       0x9d21f441,
+       0x026a21f5,
+       0x07f124bd,
+       0x03f047fc,
+       0x0002d002,
+       0x2cf004bd,
        0x0320b601,
-       0xf00012d0,
-       0xa5f001ac,
-       0x00b7f006,
-       0x98000c98,
-       0xe7f0010d,
-       0x6621f500,
-       0x08a7f001,
-       0x010921f5,
-       0x021521f5,
-       0xf02201f4,
-       0x21f40ca7,
-       0x1017f1c9,
-       0x0614b60a,
-       0xd00527f0,
-/* 0x08fa: ctx_xfer_post_save_wait */
-       0x12cf0012,
-       0x0522fd00,
-       0xf4fa1bf4,
-/* 0x0906: ctx_xfer_post */
-       0xf7f03202,
-       0x5121f502,
-       0xf5f4bd06,
-       0xf5069221,
-       0xf5023421,
-       0xbd066021,
-       0x5121f5f4,
-       0x1011f406,
-       0xfd400198,
-       0x0bf40511,
-       0xe521f507,
-/* 0x0931: ctx_xfer_no_post_mmio */
-       0x4321f507,
-/* 0x0935: ctx_xfer_done */
-       0x0000f806,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf001acf0,
+       0xb7f006a5,
+       0x000c9800,
+       0xf0010d98,
+       0x21f500e7,
+       0xa7f0016f,
+       0x1021f508,
+       0x5e21f501,
+       0x1301f402,
+       0xf40ca7f0,
+       0xf7f0d021,
+       0x3c21f505,
+       0x3202f408,
+/* 0x0ac4: ctx_xfer_post */
+       0xf502f7f0,
+       0xbd07b521,
+       0x1421f5f4,
+       0x7f21f508,
+       0xc721f502,
+       0xf5f4bd07,
+       0xf407b521,
+       0x01981011,
+       0x0511fd40,
+       0xf5070bf4,
+/* 0x0aef: ctx_xfer_no_post_mmio */
+       0xf5099321,
+/* 0x0af3: ctx_xfer_done */
+       0xf807a421,
        0x00000000,
        0x00000000,
        0x00000000,
index a1b9f763996a349d0def2c0770568accbfea9b8d..84af8241898764bfef6116d881c0425346684ee2 100644 (file)
@@ -206,14 +206,14 @@ uint32_t nvd7_grhub_data[] = {
 };
 
 uint32_t nvd7_grhub_code[] = {
-       0x031b0ef5,
+       0x039b0ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvd7_grhub_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvd7_grhub_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0x07f100f8,
        0x03f00500,
        0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvd7_grhub_code[] = {
        0x0007f101,
        0x0303f007,
        0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
        0xbd00f804,
-       0x0004fe04,
-       0xf10007fe,
-       0xf0120017,
-       0x12d00227,
-       0xb117f100,
-       0x0010fe05,
-       0x040017f1,
-       0xf1c010d0,
-       0xb6040437,
-       0x27f10634,
-       0x32d02003,
-       0x0427f100,
-       0x0132d020,
+       0x0007fe04,
+       0x420017f1,
+       0xcf0013f0,
+       0x11e70011,
+       0x14b60109,
+       0x0014fe08,
+       0xf10227f0,
+       0xf0120007,
+       0x02d00003,
+       0xf104bd00,
+       0xfe06c817,
+       0x24bd0010,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0002,
+       0x200327f1,
+       0x010007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200427f1,
+       0x010407f1,
+       0xd00103f0,
+       0x04bd0002,
        0x200b27f1,
-       0xf10232d0,
-       0xd0200c27,
-       0x27f10732,
-       0x24b60c24,
-       0x0003b906,
-       0xf10023d0,
+       0x010807f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200c27f1,
+       0x011c07f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1010392,
+       0xf0090007,
+       0x03d00303,
+       0xf104bd00,
        0xf0870427,
-       0x12d00023,
-       0x0012b700,
-       0x0427f001,
-       0xf40012d0,
-       0xe7f11031,
-       0xe3f09604,
-       0x6821f440,
-       0x8090f1c7,
-       0xf4f00301,
-       0x020f801f,
-       0xbb0117f0,
-       0x12b6041f,
-       0x0c27f101,
-       0x0624b604,
-       0xd00021d0,
-       0x17f14021,
-       0x0e980100,
-       0x010f9800,
-       0x014721f5,
-       0x070037f1,
-       0x950634b6,
-       0x34d00814,
-       0x4034d000,
-       0x130030b7,
-       0xb6001fbb,
-       0x3fd002f5,
-       0x0815b600,
-       0xb60110b6,
-       0x1fb90814,
-       0x7121f502,
-       0x001fbb02,
-       0xf1020398,
-       0xf0200047,
-/* 0x03f6: init_gpc */
-       0x4ea05043,
-       0x1fb90804,
-       0x8d21f402,
-       0x010c4ea0,
-       0x21f4f4bd,
-       0x044ea08d,
-       0x8d21f401,
-       0x01004ea0,
-       0xf402f7f0,
-       0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-       0x21f40800,
-       0x1fffc868,
-       0xa0fa0bf4,
-       0xf408044e,
-       0x1fbb6821,
-       0x0040b700,
-       0x0132b680,
-       0xf1be1bf4,
+       0x07f10023,
+       0x03f00400,
+       0x0002d000,
+       0x27f004bd,
+       0x0007f104,
+       0x0003f003,
+       0xbd0002d0,
+       0x1031f404,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xfeb96821,
+       0x90f1c702,
+       0xf0030180,
+       0x0f801ff4,
+       0x0117f002,
+       0xb6041fbb,
+       0x07f10112,
+       0x03f00300,
+       0x0001d001,
+       0x07f104bd,
+       0x03f00400,
+       0x0001d001,
+       0x17f104bd,
+       0xf7f00100,
+       0xb521f502,
+       0xc721f507,
+       0x10f7f007,
+       0x081421f5,
+       0x98000e98,
+       0x21f5010f,
+       0x14950150,
+       0x0007f108,
+       0x0103f0c0,
+       0xbd0004d0,
+       0x0007f104,
+       0x0103f0c1,
+       0xbd0004d0,
+       0x0030b704,
+       0x001fbb13,
+       0xf102f5b6,
+       0xf0d30007,
+       0x0fd00103,
+       0xb604bd00,
+       0x10b60815,
+       0x0814b601,
+       0xf5021fb9,
+       0xbb02d321,
+       0x0398001f,
+       0x0047f102,
+       0x5043f020,
+/* 0x04f4: init_gpc */
+       0x08044ea0,
+       0xf4021fb9,
+       0x4ea09d21,
+       0xf4bd010c,
+       0xa09d21f4,
+       0xf401044e,
+       0x4ea09d21,
+       0xf7f00100,
+       0x9d21f402,
+       0x08004ea0,
+/* 0x051c: init_gpc_wait */
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x00f7f0be,
+       0x081421f5,
+       0xf500f7f0,
+       0xf107b521,
        0xf0010007,
        0x01d00203,
        0xbd04bd00,
@@ -519,402 +584,399 @@ uint32_t nvd7_grhub_code[] = {
        0x080007f1,
        0xd00203f0,
        0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
        0xf40031f4,
        0xd7f00028,
        0x3921f410,
        0xb1f401f4,
        0xf54001e4,
-       0xbd00de1b,
+       0xbd00e91b,
        0x0499f094,
        0x0f0007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0b0017f1,
-       0xcf0614b6,
-       0x11cf4012,
-       0x1f13c800,
-       0x00870bf5,
-       0xf41f23c8,
-       0x20f9620b,
-       0xbd0212b9,
-       0x0799f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0xf40132f4,
-       0x21f50231,
-       0x94bd082f,
+       0xc00017f1,
+       0xcf0213f0,
+       0x27f10011,
+       0x23f0c100,
+       0x0022cf02,
+       0xf51f13c8,
+       0xc800890b,
+       0x0bf41f23,
+       0xb920f962,
+       0x94bd0212,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
-       0xfc04bd00,
-       0xf094bd20,
-       0x07f10699,
-       0x03f00f00,
-       0x0009d002,
-       0x31f404bd,
-       0x2f21f501,
-       0xf094bd08,
-       0x07f10699,
+       0xf404bd00,
+       0x31f40132,
+       0xe821f502,
+       0xf094bd09,
+       0x07f10799,
        0x03f01700,
        0x0009d002,
-       0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-       0xb920f931,
-       0x32f40212,
-       0x0232f401,
-       0x082f21f5,
-       0x17f120fc,
-       0x14b60b00,
-       0x0012d006,
-/* 0x0517: chsw_no_prev */
-       0xc8130ef4,
-       0x0bf41f23,
-       0x0131f40d,
-       0xf50232f4,
-/* 0x0527: chsw_done */
-       0xf1082f21,
-       0xb60b0c17,
-       0x27f00614,
-       0x0012d001,
+       0x20fc04bd,
        0x99f094bd,
-       0x0007f104,
+       0x0007f106,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0131f404,
+       0x09e821f5,
+       0x99f094bd,
+       0x0007f106,
        0x0203f017,
        0xbd0009d0,
-       0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-       0x01e4b0ff,
-       0xb90d1bf4,
-       0x21f502f2,
-       0x0ef407bb,
-/* 0x0559: main_not_ctx_chan */
-       0x02e4b046,
-       0xbd321bf4,
-       0x0799f094,
-       0x0f0007f1,
+       0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+       0x12b920f9,
+       0x0132f402,
+       0xf50232f4,
+       0xfc09e821,
+       0x0007f120,
+       0x0203f0c0,
+       0xbd0002d0,
+       0x130ef404,
+/* 0x062c: chsw_no_prev */
+       0xf41f23c8,
+       0x31f40d0b,
+       0x0232f401,
+       0x09e821f5,
+/* 0x063c: chsw_done */
+       0xf10127f0,
+       0xf0c30007,
+       0x02d00203,
+       0xbd04bd00,
+       0x0499f094,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0xf40132f4,
-       0x21f50232,
-       0x94bd082f,
+       0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+       0xf401e4b0,
+       0xf2b90d1b,
+       0x7821f502,
+       0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+       0xf402e4b0,
+       0x94bd321b,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
        0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-       0xef94110e,
-       0x01f5f010,
-       0x02fe21f5,
-       0xfec00ef5,
-/* 0x059c: main_done */
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f008,
-       0xbd0002d0,
-       0xab0ef504,
-/* 0x05b1: ih */
-       0xfe80f9fe,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x0acf04bd,
-       0x04abc480,
-       0xf11d0bf4,
-       0xf01900b7,
-       0xbecf10d7,
-       0x00bfcf40,
+       0x32f40132,
+       0xe821f502,
+       0xf094bd09,
+       0x07f10799,
+       0x03f01700,
+       0x0009d002,
+       0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+       0x10ef9411,
+       0xf501f5f0,
+       0xf5037e21,
+/* 0x06b3: main_done */
+       0xbdfeb50e,
+       0x1f29f024,
+       0x080007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xfea00ef5,
+/* 0x06c8: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x10d7f030,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
        0xb70421f4,
        0xf00400b0,
-       0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-       0x00abe400,
-       0x0d0bf401,
-       0xf110d7f0,
-       0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-       0xb7f10421,
-       0xb0bd0104,
-       0xf4b4abff,
-       0xa7f10d0b,
-       0xa4b60c1c,
-       0x00abd006,
-/* 0x0610: ih_no_other */
-       0xfc400ad0,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x071a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x10d7f00d,
+       0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+       0xe40421f4,
+       0xf40400ab,
+       0xb7f1140b,
+       0xbfb90100,
+       0x44e7f102,
+       0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+       0xf19d21f4,
+       0xbd0104b7,
+       0xb4abffb0,
+       0xf10f0bf4,
+       0xf0070007,
+       0x0bd00303,
+/* 0x075b: ih_no_other */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
        0xfce0fcf0,
        0xfcb0fcd0,
        0xfc90fca0,
        0x0088fe80,
        0x32f480fc,
-/* 0x062b: ctx_4160s */
-       0xf101f800,
-       0xf04160e7,
-       0xf7f040e3,
-       0x8d21f401,
-/* 0x0638: ctx_4160s_wait */
-       0xc86821f4,
-       0x0bf404ff,
-/* 0x0643: ctx_4160c */
-       0xf100f8fa,
+/* 0x077f: ctx_4160s */
+       0xf001f800,
+       0xffb901f7,
+       0x60e7f102,
+       0x40e3f041,
+/* 0x078f: ctx_4160s_wait */
+       0xf19d21f4,
        0xf04160e7,
-       0xf4bd40e3,
-       0xf88d21f4,
-/* 0x0651: ctx_4170s */
-       0x70e7f100,
+       0x21f440e3,
+       0x02ffb968,
+       0xf404ffc8,
+       0x00f8f00b,
+/* 0x07a4: ctx_4160c */
+       0xffb9f4bd,
+       0x60e7f102,
        0x40e3f041,
-       0xf410f5f0,
-       0x00f88d21,
-/* 0x0660: ctx_4170w */
-       0x4170e7f1,
-       0xf440e3f0,
-       0xf4f06821,
-       0xf31bf410,
-/* 0x0672: ctx_redswitch */
-       0xe7f100f8,
-       0xe4b60614,
-       0x70f7f106,
-       0x00efd002,
-/* 0x0683: ctx_redswitch_delay */
-       0xb608f7f0,
-       0x1bf401f2,
-       0x70f7f1fd,
-       0x00efd007,
-/* 0x0692: ctx_86c */
-       0xe7f100f8,
-       0xe4b6086c,
-       0x00efd006,
-       0x8a14e7f1,
-       0xf440e3f0,
-       0xe7f18d21,
-       0xe3f0a86c,
-       0x8d21f441,
-/* 0x06b2: ctx_load */
+       0xf89d21f4,
+/* 0x07b5: ctx_4170s */
+       0x10f5f000,
+       0xf102ffb9,
+       0xf04170e7,
+       0x21f440e3,
+/* 0x07c7: ctx_4170w */
+       0xf100f89d,
+       0xf04170e7,
+       0x21f440e3,
+       0x02ffb968,
+       0xf410f4f0,
+       0x00f8f01b,
+/* 0x07dc: ctx_redswitch */
+       0x0200e7f1,
+       0xf040e5f0,
+       0xe5f020e5,
+       0x0007f110,
+       0x0103f085,
+       0xbd000ed0,
+       0x08f7f004,
+/* 0x07f8: ctx_redswitch_delay */
+       0xf401f2b6,
+       0xe5f1fd1b,
+       0xe5f10400,
+       0x07f10100,
+       0x03f08500,
+       0x000ed001,
+       0x00f804bd,
+/* 0x0814: ctx_86c */
+       0x1b0007f1,
+       0xd00203f0,
+       0x04bd000f,
+       0xf102ffb9,
+       0xf08a14e7,
+       0x21f440e3,
+       0x02ffb99d,
+       0xa86ce7f1,
+       0xf441e3f0,
+       0x00f89d21,
+/* 0x083c: ctx_mem */
+       0x840007f1,
+       0xd00203f0,
+       0x04bd000f,
+/* 0x0848: ctx_mem_wait */
+       0x8400f7f1,
+       0xcf02f3f0,
+       0xfffd00ff,
+       0xf31bf405,
+/* 0x085a: ctx_load */
        0x94bd00f8,
        0xf10599f0,
        0xf00f0007,
        0x09d00203,
        0xf004bd00,
        0x21f40ca7,
-       0x2417f1c9,
-       0x0614b60a,
-       0xf10010d0,
-       0xb60b0037,
-       0x32d00634,
-       0x0c17f140,
-       0x0614b60a,
-       0xd00747f0,
-       0x14d00012,
-/* 0x06ed: ctx_chan_wait_0 */
-       0x4014cf40,
-       0xf41f44f0,
-       0x32d0fa1b,
-       0x000bfe00,
-       0xb61f2af0,
-       0x20b60424,
-       0xf094bd02,
+       0xf1f4bdd0,
+       0xf0890007,
+       0x0fd00203,
+       0xf104bd00,
+       0xf0c10007,
+       0x02d00203,
+       0xf104bd00,
+       0xf0830007,
+       0x02d00203,
+       0xf004bd00,
+       0x21f507f7,
+       0x07f1083c,
+       0x03f0c000,
+       0x0002d002,
+       0x0bfe04bd,
+       0x1f2af000,
+       0xb60424b6,
+       0x94bd0220,
+       0xf10899f0,
+       0xf00f0007,
+       0x09d00203,
+       0xf104bd00,
+       0xf0810007,
+       0x02d00203,
+       0xf104bd00,
+       0xf1000027,
+       0xf0800023,
+       0x07f10225,
+       0x03f08800,
+       0x0002d002,
+       0x17f004bd,
+       0x0027f110,
+       0x0223f002,
+       0xf80512fa,
+       0xf094bd03,
        0x07f10899,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x17f104bd,
-       0x14b60a04,
-       0x0012d006,
-       0x0a2017f1,
-       0xf00614b6,
-       0x23f10227,
-       0x12d08000,
-       0x1017f000,
-       0x020027f1,
-       0xfa0223f0,
-       0x03f80512,
+       0x019804bd,
+       0x1814b681,
+       0xb6800298,
+       0x12fd0825,
+       0x16018005,
        0x99f094bd,
-       0x0007f108,
-       0x0203f017,
+       0x0007f109,
+       0x0203f00f,
        0xbd0009d0,
-       0x81019804,
-       0x981814b6,
-       0x25b68002,
-       0x0512fd08,
-       0xbd160180,
-       0x0999f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0x0a0427f1,
-       0xd00624b6,
-       0x27f00021,
-       0x2017f101,
-       0x0614b60a,
-       0xf10012d0,
-       0xf0010017,
-       0x01fa0613,
-       0xbd03f805,
-       0x0999f094,
-       0x170007f1,
+       0x0007f104,
+       0x0203f081,
+       0xbd0001d0,
+       0x0127f004,
+       0x880007f1,
        0xd00203f0,
-       0x04bd0009,
+       0x04bd0002,
+       0x010017f1,
+       0xfa0613f0,
+       0x03f80501,
        0x99f094bd,
-       0x0007f105,
+       0x0007f109,
        0x0203f017,
        0xbd0009d0,
-/* 0x07bb: ctx_chan */
-       0xf500f804,
-       0xf5062b21,
-       0xf006b221,
-       0x21f40ca7,
-       0x1017f1c9,
-       0x0614b60a,
-       0xd00527f0,
-/* 0x07d6: ctx_chan_wait */
-       0x12cf0012,
-       0x0522fd00,
-       0xf5fa1bf4,
-       0xf8064321,
-/* 0x07e5: ctx_mmio_exec */
-       0x41039800,
-       0x0a0427f1,
-       0xd00624b6,
-       0x34bd0023,
-/* 0x07f4: ctx_mmio_loop */
+       0xf094bd04,
+       0x07f10599,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0978: ctx_chan */
+       0x077f21f5,
+       0x085a21f5,
+       0xf40ca7f0,
+       0xf7f0d021,
+       0x3c21f505,
+       0xa421f508,
+/* 0x0993: ctx_mmio_exec */
+       0x9800f807,
+       0x07f14103,
+       0x03f08100,
+       0x0003d002,
+       0x34bd04bd,
+/* 0x09a4: ctx_mmio_loop */
        0xf4ff34c4,
        0x57f10f1b,
        0x53f00200,
        0x0535fa06,
-/* 0x0806: ctx_mmio_pull */
+/* 0x09b6: ctx_mmio_pull */
        0x4e9803f8,
        0x814f9880,
-       0xb68d21f4,
+       0xb69d21f4,
        0x12b60830,
        0xdf1bf401,
-/* 0x0818: ctx_mmio_done */
-       0xd0160398,
-       0x00800023,
-       0x0017f140,
-       0x0613f001,
-       0xf80601fa,
-/* 0x082f: ctx_xfer */
-       0xf100f803,
-       0xb60c00f7,
-       0xe7f006f4,
-       0x80fed004,
-/* 0x083c: ctx_xfer_idle */
-       0xf100fecf,
-       0xf42000e4,
-       0x11f4f91b,
-       0x1102f406,
-/* 0x084c: ctx_xfer_pre */
-       0xf510f7f0,
-       0xf5069221,
-       0xf4062b21,
-/* 0x085a: ctx_xfer_pre_load */
-       0xf7f01c11,
-       0x5121f502,
-       0x6021f506,
-       0x7221f506,
-       0xf5f4bd06,
-       0xf5065121,
-/* 0x0873: ctx_xfer_exec */
-       0x9806b221,
-       0x27f11601,
-       0x24b60414,
-       0x0020d006,
-       0xa500e7f1,
-       0xb941e3f0,
-       0x21f4021f,
-       0x04e0b68d,
-       0xf001fcf0,
-       0x24b6022c,
-       0x05f2fd01,
-       0xf18d21f4,
-       0xf04afc17,
-       0x27f00213,
-       0x0012d00c,
-       0x021521f5,
-       0x47fc27f1,
-       0xd00223f0,
-       0x2cf00020,
+/* 0x09c8: ctx_mmio_done */
+       0xf1160398,
+       0xf0810007,
+       0x03d00203,
+       0x8004bd00,
+       0x17f14000,
+       0x13f00100,
+       0x0601fa06,
+       0x00f803f8,
+/* 0x09e8: ctx_xfer */
+       0xf104e7f0,
+       0xf0020007,
+       0x0ed00303,
+/* 0x09f7: ctx_xfer_idle */
+       0xf104bd00,
+       0xf00000e7,
+       0xeecf03e3,
+       0x00e4f100,
+       0xf21bf420,
+       0xf40611f4,
+/* 0x0a0e: ctx_xfer_pre */
+       0xf7f01102,
+       0x1421f510,
+       0x7f21f508,
+       0x1c11f407,
+/* 0x0a1c: ctx_xfer_pre_load */
+       0xf502f7f0,
+       0xf507b521,
+       0xf507c721,
+       0xbd07dc21,
+       0xb521f5f4,
+       0x5a21f507,
+/* 0x0a35: ctx_xfer_exec */
+       0x16019808,
+       0x07f124bd,
+       0x03f00500,
+       0x0002d001,
+       0x1fb904bd,
+       0x00e7f102,
+       0x41e3f0a5,
+       0xf09d21f4,
+       0x2cf001fc,
+       0x0124b602,
+       0xb905f2fd,
+       0xe7f102ff,
+       0xe3f0a504,
+       0x9d21f441,
+       0x026a21f5,
+       0x07f124bd,
+       0x03f047fc,
+       0x0002d002,
+       0x2cf004bd,
        0x0320b601,
-       0xf00012d0,
-       0xa5f001ac,
-       0x00b7f006,
-       0x98000c98,
-       0xe7f0010d,
-       0x6621f500,
-       0x08a7f001,
-       0x010921f5,
-       0x021521f5,
-       0xf02201f4,
-       0x21f40ca7,
-       0x1017f1c9,
-       0x0614b60a,
-       0xd00527f0,
-/* 0x08fa: ctx_xfer_post_save_wait */
-       0x12cf0012,
-       0x0522fd00,
-       0xf4fa1bf4,
-/* 0x0906: ctx_xfer_post */
-       0xf7f03202,
-       0x5121f502,
-       0xf5f4bd06,
-       0xf5069221,
-       0xf5023421,
-       0xbd066021,
-       0x5121f5f4,
-       0x1011f406,
-       0xfd400198,
-       0x0bf40511,
-       0xe521f507,
-/* 0x0931: ctx_xfer_no_post_mmio */
-       0x4321f507,
-/* 0x0935: ctx_xfer_done */
-       0x0000f806,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf001acf0,
+       0xb7f006a5,
+       0x000c9800,
+       0xf0010d98,
+       0x21f500e7,
+       0xa7f0016f,
+       0x1021f508,
+       0x5e21f501,
+       0x1301f402,
+       0xf40ca7f0,
+       0xf7f0d021,
+       0x3c21f505,
+       0x3202f408,
+/* 0x0ac4: ctx_xfer_post */
+       0xf502f7f0,
+       0xbd07b521,
+       0x1421f5f4,
+       0x7f21f508,
+       0xc721f502,
+       0xf5f4bd07,
+       0xf407b521,
+       0x01981011,
+       0x0511fd40,
+       0xf5070bf4,
+/* 0x0aef: ctx_xfer_no_post_mmio */
+       0xf5099321,
+/* 0x0af3: ctx_xfer_done */
+       0xf807a421,
        0x00000000,
        0x00000000,
        0x00000000,
index eb7bc0e9576eab1a841bb93fcb3af4e3f924b6d0..1c179bdd48cc2a0ddd3228a3e8bfc0005f1bf06a 100644 (file)
@@ -206,14 +206,14 @@ uint32_t nve0_grhub_data[] = {
 };
 
 uint32_t nve0_grhub_code[] = {
-       0x031b0ef5,
+       0x039b0ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nve0_grhub_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f00f00,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f00f00,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f00f,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf00f0007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f00f00,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x0f0007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nve0_grhub_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0x07f100f8,
        0x03f00500,
        0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nve0_grhub_code[] = {
        0x0007f101,
        0x0303f007,
        0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
        0xbd00f804,
-       0x0004fe04,
-       0xf10007fe,
-       0xf0120017,
-       0x12d00227,
-       0xb117f100,
-       0x0010fe05,
-       0x040017f1,
-       0xf1c010d0,
-       0xb6040437,
-       0x27f10634,
-       0x32d02003,
-       0x0427f100,
-       0x0132d020,
+       0x0007fe04,
+       0x420017f1,
+       0xcf0013f0,
+       0x11e70011,
+       0x14b60109,
+       0x0014fe08,
+       0xf10227f0,
+       0xf0120007,
+       0x02d00003,
+       0xf104bd00,
+       0xfe06c817,
+       0x24bd0010,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0002,
+       0x200327f1,
+       0x010007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200427f1,
+       0x010407f1,
+       0xd00103f0,
+       0x04bd0002,
        0x200b27f1,
-       0xf10232d0,
-       0xd0200c27,
-       0x27f10732,
-       0x24b60c24,
-       0x0003b906,
-       0xf10023d0,
+       0x010807f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200c27f1,
+       0x011c07f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1010392,
+       0xf0090007,
+       0x03d00303,
+       0xf104bd00,
        0xf0870427,
-       0x12d00023,
-       0x0012b700,
-       0x0427f001,
-       0xf40012d0,
-       0xe7f11031,
-       0xe3f09604,
-       0x6821f440,
-       0x8090f1c7,
-       0xf4f00301,
-       0x020f801f,
-       0xbb0117f0,
-       0x12b6041f,
-       0x0c27f101,
-       0x0624b604,
-       0xd00021d0,
-       0x17f14021,
-       0x0e980100,
-       0x010f9800,
-       0x014721f5,
-       0x070037f1,
-       0x950634b6,
-       0x34d00814,
-       0x4034d000,
-       0x130030b7,
-       0xb6001fbb,
-       0x3fd002f5,
-       0x0815b600,
-       0xb60110b6,
-       0x1fb90814,
-       0x7121f502,
-       0x001fbb02,
-       0xf1020398,
-       0xf0200047,
-/* 0x03f6: init_gpc */
-       0x4ea05043,
-       0x1fb90804,
-       0x8d21f402,
-       0x010c4ea0,
-       0x21f4f4bd,
-       0x044ea08d,
-       0x8d21f401,
-       0x01004ea0,
-       0xf402f7f0,
-       0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-       0x21f40800,
-       0x1fffc868,
-       0xa0fa0bf4,
-       0xf408044e,
-       0x1fbb6821,
-       0x0040b700,
-       0x0132b680,
-       0xf1be1bf4,
+       0x07f10023,
+       0x03f00400,
+       0x0002d000,
+       0x27f004bd,
+       0x0007f104,
+       0x0003f003,
+       0xbd0002d0,
+       0x1031f404,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xfeb96821,
+       0x90f1c702,
+       0xf0030180,
+       0x0f801ff4,
+       0x0117f002,
+       0xb6041fbb,
+       0x07f10112,
+       0x03f00300,
+       0x0001d001,
+       0x07f104bd,
+       0x03f00400,
+       0x0001d001,
+       0x17f104bd,
+       0xf7f00100,
+       0x7f21f502,
+       0x9121f507,
+       0x10f7f007,
+       0x07de21f5,
+       0x98000e98,
+       0x21f5010f,
+       0x14950150,
+       0x0007f108,
+       0x0103f0c0,
+       0xbd0004d0,
+       0x0007f104,
+       0x0103f0c1,
+       0xbd0004d0,
+       0x0030b704,
+       0x001fbb13,
+       0xf102f5b6,
+       0xf0d30007,
+       0x0fd00103,
+       0xb604bd00,
+       0x10b60815,
+       0x0814b601,
+       0xf5021fb9,
+       0xbb02d321,
+       0x0398001f,
+       0x0047f102,
+       0x5043f020,
+/* 0x04f4: init_gpc */
+       0x08044ea0,
+       0xf4021fb9,
+       0x4ea09d21,
+       0xf4bd010c,
+       0xa09d21f4,
+       0xf401044e,
+       0x4ea09d21,
+       0xf7f00100,
+       0x9d21f402,
+       0x08004ea0,
+/* 0x051c: init_gpc_wait */
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x00f7f0be,
+       0x07de21f5,
+       0xf500f7f0,
+       0xf1077f21,
        0xf0010007,
        0x01d00203,
        0xbd04bd00,
@@ -519,382 +584,379 @@ uint32_t nve0_grhub_code[] = {
        0x080007f1,
        0xd00203f0,
        0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
        0xf40031f4,
        0xd7f00028,
        0x3921f410,
        0xb1f401f4,
        0xf54001e4,
-       0xbd00de1b,
+       0xbd00e91b,
        0x0499f094,
        0x0f0007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0b0017f1,
-       0xcf0614b6,
-       0x11cf4012,
-       0x1f13c800,
-       0x00870bf5,
-       0xf41f23c8,
-       0x20f9620b,
-       0xbd0212b9,
-       0x0799f094,
-       0x0f0007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0xf40132f4,
-       0x21f50231,
-       0x94bd0801,
+       0xc00017f1,
+       0xcf0213f0,
+       0x27f10011,
+       0x23f0c100,
+       0x0022cf02,
+       0xf51f13c8,
+       0xc800890b,
+       0x0bf41f23,
+       0xb920f962,
+       0x94bd0212,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
-       0xfc04bd00,
-       0xf094bd20,
-       0x07f10699,
-       0x03f00f00,
-       0x0009d002,
-       0x31f404bd,
-       0x0121f501,
-       0xf094bd08,
-       0x07f10699,
+       0xf404bd00,
+       0x31f40132,
+       0xaa21f502,
+       0xf094bd09,
+       0x07f10799,
        0x03f01700,
        0x0009d002,
-       0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-       0xb920f931,
-       0x32f40212,
-       0x0232f401,
-       0x080121f5,
-       0x17f120fc,
-       0x14b60b00,
-       0x0012d006,
-/* 0x0517: chsw_no_prev */
-       0xc8130ef4,
-       0x0bf41f23,
-       0x0131f40d,
-       0xf50232f4,
-/* 0x0527: chsw_done */
-       0xf1080121,
-       0xb60b0c17,
-       0x27f00614,
-       0x0012d001,
+       0x20fc04bd,
        0x99f094bd,
-       0x0007f104,
+       0x0007f106,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0131f404,
+       0x09aa21f5,
+       0x99f094bd,
+       0x0007f106,
        0x0203f017,
        0xbd0009d0,
-       0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-       0x01e4b0ff,
-       0xb90d1bf4,
-       0x21f502f2,
-       0x0ef40795,
-/* 0x0559: main_not_ctx_chan */
-       0x02e4b046,
-       0xbd321bf4,
-       0x0799f094,
-       0x0f0007f1,
+       0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+       0x12b920f9,
+       0x0132f402,
+       0xf50232f4,
+       0xfc09aa21,
+       0x0007f120,
+       0x0203f0c0,
+       0xbd0002d0,
+       0x130ef404,
+/* 0x062c: chsw_no_prev */
+       0xf41f23c8,
+       0x31f40d0b,
+       0x0232f401,
+       0x09aa21f5,
+/* 0x063c: chsw_done */
+       0xf10127f0,
+       0xf0c30007,
+       0x02d00203,
+       0xbd04bd00,
+       0x0499f094,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0xf40132f4,
-       0x21f50232,
-       0x94bd0801,
+       0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+       0xf401e4b0,
+       0xf2b90d1b,
+       0x4221f502,
+       0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+       0xf402e4b0,
+       0x94bd321b,
        0xf10799f0,
-       0xf0170007,
+       0xf00f0007,
        0x09d00203,
        0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-       0xef94110e,
-       0x01f5f010,
-       0x02fe21f5,
-       0xfec00ef5,
-/* 0x059c: main_done */
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f008,
-       0xbd0002d0,
-       0xab0ef504,
-/* 0x05b1: ih */
-       0xfe80f9fe,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x0acf04bd,
-       0x04abc480,
-       0xf11d0bf4,
-       0xf01900b7,
-       0xbecf10d7,
-       0x00bfcf40,
+       0x32f40132,
+       0xaa21f502,
+       0xf094bd09,
+       0x07f10799,
+       0x03f01700,
+       0x0009d002,
+       0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+       0x10ef9411,
+       0xf501f5f0,
+       0xf5037e21,
+/* 0x06b3: main_done */
+       0xbdfeb50e,
+       0x1f29f024,
+       0x080007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xfea00ef5,
+/* 0x06c8: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x10d7f030,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
        0xb70421f4,
        0xf00400b0,
-       0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-       0x00abe400,
-       0x0d0bf401,
-       0xf110d7f0,
-       0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-       0xb7f10421,
-       0xb0bd0104,
-       0xf4b4abff,
-       0xa7f10d0b,
-       0xa4b60c1c,
-       0x00abd006,
-/* 0x0610: ih_no_other */
-       0xfc400ad0,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x071a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x10d7f00d,
+       0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+       0xe40421f4,
+       0xf40400ab,
+       0xb7f1140b,
+       0xbfb90100,
+       0x44e7f102,
+       0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+       0xf19d21f4,
+       0xbd0104b7,
+       0xb4abffb0,
+       0xf10f0bf4,
+       0xf0070007,
+       0x0bd00303,
+/* 0x075b: ih_no_other */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
        0xfce0fcf0,
        0xfcb0fcd0,
        0xfc90fca0,
        0x0088fe80,
        0x32f480fc,
-/* 0x062b: ctx_4170s */
-       0xf101f800,
-       0xf04170e7,
-       0xf5f040e3,
-       0x8d21f410,
-/* 0x063a: ctx_4170w */
+/* 0x077f: ctx_4170s */
+       0xf001f800,
+       0xffb910f5,
+       0x70e7f102,
+       0x40e3f041,
+       0xf89d21f4,
+/* 0x0791: ctx_4170w */
+       0x70e7f100,
+       0x40e3f041,
+       0xb96821f4,
+       0xf4f002ff,
+       0xf01bf410,
+/* 0x07a6: ctx_redswitch */
        0xe7f100f8,
-       0xe3f04170,
-       0x6821f440,
-       0xf410f4f0,
+       0xe5f00200,
+       0x20e5f040,
+       0xf110e5f0,
+       0xf0850007,
+       0x0ed00103,
+       0xf004bd00,
+/* 0x07c2: ctx_redswitch_delay */
+       0xf2b608f7,
+       0xfd1bf401,
+       0x0400e5f1,
+       0x0100e5f1,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000e,
+/* 0x07de: ctx_86c */
+       0x07f100f8,
+       0x03f01b00,
+       0x000fd002,
+       0xffb904bd,
+       0x14e7f102,
+       0x40e3f08a,
+       0xb99d21f4,
+       0xe7f102ff,
+       0xe3f0a86c,
+       0x9d21f441,
+/* 0x0806: ctx_mem */
+       0x07f100f8,
+       0x03f08400,
+       0x000fd002,
+/* 0x0812: ctx_mem_wait */
+       0xf7f104bd,
+       0xf3f08400,
+       0x00ffcf02,
+       0xf405fffd,
        0x00f8f31b,
-/* 0x064c: ctx_redswitch */
-       0x0614e7f1,
-       0xf106e4b6,
-       0xd00270f7,
-       0xf7f000ef,
-/* 0x065d: ctx_redswitch_delay */
-       0x01f2b608,
-       0xf1fd1bf4,
-       0xd00770f7,
-       0x00f800ef,
-/* 0x066c: ctx_86c */
-       0x086ce7f1,
-       0xd006e4b6,
-       0xe7f100ef,
-       0xe3f08a14,
-       0x8d21f440,
-       0xa86ce7f1,
-       0xf441e3f0,
-       0x00f88d21,
-/* 0x068c: ctx_load */
+/* 0x0824: ctx_load */
        0x99f094bd,
        0x0007f105,
        0x0203f00f,
        0xbd0009d0,
        0x0ca7f004,
-       0xf1c921f4,
-       0xb60a2417,
-       0x10d00614,
-       0x0037f100,
-       0x0634b60b,
-       0xf14032d0,
-       0xb60a0c17,
-       0x47f00614,
-       0x0012d007,
-/* 0x06c7: ctx_chan_wait_0 */
-       0xcf4014d0,
-       0x44f04014,
-       0xfa1bf41f,
-       0xfe0032d0,
-       0x2af0000b,
-       0x0424b61f,
-       0xbd0220b6,
+       0xbdd021f4,
+       0x0007f1f4,
+       0x0203f089,
+       0xbd000fd0,
+       0x0007f104,
+       0x0203f0c1,
+       0xbd0002d0,
+       0x0007f104,
+       0x0203f083,
+       0xbd0002d0,
+       0x07f7f004,
+       0x080621f5,
+       0xc00007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf0000bfe,
+       0x24b61f2a,
+       0x0220b604,
+       0x99f094bd,
+       0x0007f108,
+       0x0203f00f,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f081,
+       0xbd0002d0,
+       0x0027f104,
+       0x0023f100,
+       0x0225f080,
+       0x880007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf11017f0,
+       0xf0020027,
+       0x12fa0223,
+       0xbd03f805,
        0x0899f094,
-       0x0f0007f1,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0a0417f1,
-       0xd00614b6,
-       0x17f10012,
-       0x14b60a20,
-       0x0227f006,
-       0x800023f1,
-       0xf00012d0,
-       0x27f11017,
-       0x23f00200,
-       0x0512fa02,
-       0x94bd03f8,
-       0xf10899f0,
-       0xf0170007,
+       0xb6810198,
+       0x02981814,
+       0x0825b680,
+       0x800512fd,
+       0x94bd1601,
+       0xf10999f0,
+       0xf00f0007,
        0x09d00203,
-       0x9804bd00,
-       0x14b68101,
-       0x80029818,
-       0xfd0825b6,
-       0x01800512,
-       0xf094bd16,
-       0x07f10999,
-       0x03f00f00,
-       0x0009d002,
-       0x27f104bd,
-       0x24b60a04,
-       0x0021d006,
-       0xf10127f0,
-       0xb60a2017,
-       0x12d00614,
-       0x0017f100,
-       0x0613f001,
-       0xf80501fa,
-       0xf094bd03,
-       0x07f10999,
-       0x03f01700,
-       0x0009d002,
-       0x94bd04bd,
-       0xf10599f0,
+       0xf104bd00,
+       0xf0810007,
+       0x01d00203,
+       0xf004bd00,
+       0x07f10127,
+       0x03f08800,
+       0x0002d002,
+       0x17f104bd,
+       0x13f00100,
+       0x0501fa06,
+       0x94bd03f8,
+       0xf10999f0,
        0xf0170007,
        0x09d00203,
-       0xf804bd00,
-/* 0x0795: ctx_chan */
-       0x8c21f500,
-       0x0ca7f006,
-       0xf1c921f4,
-       0xb60a1017,
-       0x27f00614,
-       0x0012d005,
-/* 0x07ac: ctx_chan_wait */
-       0xfd0012cf,
-       0x1bf40522,
-/* 0x07b7: ctx_mmio_exec */
-       0x9800f8fa,
-       0x27f14103,
-       0x24b60a04,
-       0x0023d006,
-/* 0x07c6: ctx_mmio_loop */
+       0xbd04bd00,
+       0x0599f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x0942: ctx_chan */
+       0x21f500f8,
+       0xa7f00824,
+       0xd021f40c,
+       0xf505f7f0,
+       0xf8080621,
+/* 0x0955: ctx_mmio_exec */
+       0x41039800,
+       0x810007f1,
+       0xd00203f0,
+       0x04bd0003,
+/* 0x0966: ctx_mmio_loop */
        0x34c434bd,
        0x0f1bf4ff,
        0x020057f1,
        0xfa0653f0,
        0x03f80535,
-/* 0x07d8: ctx_mmio_pull */
+/* 0x0978: ctx_mmio_pull */
        0x98804e98,
        0x21f4814f,
-       0x0830b68d,
+       0x0830b69d,
        0xf40112b6,
-/* 0x07ea: ctx_mmio_done */
+/* 0x098a: ctx_mmio_done */
        0x0398df1b,
-       0x0023d016,
-       0xf1400080,
-       0xf0010017,
-       0x01fa0613,
-       0xf803f806,
-/* 0x0801: ctx_xfer */
-       0x00f7f100,
-       0x06f4b60c,
-       0xd004e7f0,
-/* 0x080e: ctx_xfer_idle */
-       0xfecf80fe,
-       0x00e4f100,
-       0xf91bf420,
-       0xf40611f4,
-/* 0x081e: ctx_xfer_pre */
-       0xf7f00d02,
-       0x6c21f510,
-       0x1c11f406,
-/* 0x0828: ctx_xfer_pre_load */
-       0xf502f7f0,
-       0xf5062b21,
-       0xf5063a21,
-       0xbd064c21,
-       0x2b21f5f4,
-       0x8c21f506,
-/* 0x0841: ctx_xfer_exec */
-       0x16019806,
-       0x041427f1,
-       0xd00624b6,
-       0xe7f10020,
-       0xe3f0a500,
-       0x021fb941,
-       0xb68d21f4,
-       0xfcf004e0,
-       0x022cf001,
-       0xfd0124b6,
-       0x21f405f2,
-       0xfc17f18d,
-       0x0213f04a,
-       0xd00c27f0,
-       0x21f50012,
-       0x27f10215,
-       0x23f047fc,
-       0x0020d002,
+       0x0007f116,
+       0x0203f081,
+       0xbd0003d0,
+       0x40008004,
+       0x010017f1,
+       0xfa0613f0,
+       0x03f80601,
+/* 0x09aa: ctx_xfer */
+       0xe7f000f8,
+       0x0007f104,
+       0x0303f002,
+       0xbd000ed0,
+/* 0x09b9: ctx_xfer_idle */
+       0x00e7f104,
+       0x03e3f000,
+       0xf100eecf,
+       0xf42000e4,
+       0x11f4f21b,
+       0x0d02f406,
+/* 0x09d0: ctx_xfer_pre */
+       0xf510f7f0,
+       0xf407de21,
+/* 0x09da: ctx_xfer_pre_load */
+       0xf7f01c11,
+       0x7f21f502,
+       0x9121f507,
+       0xa621f507,
+       0xf5f4bd07,
+       0xf5077f21,
+/* 0x09f3: ctx_xfer_exec */
+       0x98082421,
+       0x24bd1601,
+       0x050007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1021fb9,
+       0xf0a500e7,
+       0x21f441e3,
+       0x01fcf09d,
+       0xb6022cf0,
+       0xf2fd0124,
+       0x02ffb905,
+       0xa504e7f1,
+       0xf441e3f0,
+       0x21f59d21,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
        0xb6012cf0,
-       0x12d00320,
-       0x01acf000,
-       0xf006a5f0,
-       0x0c9800b7,
-       0x010d9800,
-       0xf500e7f0,
-       0xf0016621,
-       0x21f508a7,
-       0x21f50109,
-       0x01f40215,
-       0x0ca7f022,
-       0xf1c921f4,
-       0xb60a1017,
-       0x27f00614,
-       0x0012d005,
-/* 0x08c8: ctx_xfer_post_save_wait */
-       0xfd0012cf,
-       0x1bf40522,
-       0x2e02f4fa,
-/* 0x08d4: ctx_xfer_post */
-       0xf502f7f0,
-       0xbd062b21,
-       0x6c21f5f4,
-       0x3421f506,
-       0x3a21f502,
-       0xf5f4bd06,
-       0xf4062b21,
-       0x01981011,
-       0x0511fd40,
-       0xf5070bf4,
-/* 0x08ff: ctx_xfer_no_post_mmio */
-/* 0x08ff: ctx_xfer_done */
-       0xf807b721,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x06a5f001,
+       0x9800b7f0,
+       0x0d98000c,
+       0x00e7f001,
+       0x016f21f5,
+       0xf508a7f0,
+       0xf5011021,
+       0xf4025e21,
+       0xa7f01301,
+       0xd021f40c,
+       0xf505f7f0,
+       0xf4080621,
+/* 0x0a82: ctx_xfer_post */
+       0xf7f02e02,
+       0x7f21f502,
+       0xf5f4bd07,
+       0xf507de21,
+       0xf5027f21,
+       0xbd079121,
+       0x7f21f5f4,
+       0x1011f407,
+       0xfd400198,
+       0x0bf40511,
+       0x5521f507,
+/* 0x0aad: ctx_xfer_no_post_mmio */
+/* 0x0aad: ctx_xfer_done */
+       0x0000f809,
        0x00000000,
        0x00000000,
        0x00000000,
index 438506d1474992af9d35ee538282594984a4d81f..229c0ae3722844c16d39e33fb669b677bcefa13c 100644 (file)
@@ -206,14 +206,14 @@ uint32_t nvf0_grhub_data[] = {
 };
 
 uint32_t nvf0_grhub_code[] = {
-       0x031b0ef5,
+       0x039b0ef5,
 /* 0x0004: queue_put */
        0x9800d898,
        0x86f001d9,
        0x0489b808,
        0xf00c1bf4,
        0x21f502f7,
-       0x00f802fe,
+       0x00f8037e,
 /* 0x001c: queue_put_next */
        0xb60798c4,
        0x8dbb0384,
@@ -237,184 +237,214 @@ uint32_t nvf0_grhub_code[] = {
 /* 0x0066: queue_get_done */
        0x00f80132,
 /* 0x0068: nv_rd32 */
-       0x0728b7f1,
-       0xb906b4b6,
-       0xc9f002ec,
-       0x00bcd01f,
-/* 0x0078: nv_rd32_wait */
-       0xc800bccf,
-       0x1bf41fcc,
-       0x06a7f0fa,
-       0x010921f5,
-       0xf840bfcf,
-/* 0x008d: nv_wr32 */
-       0x28b7f100,
-       0x06b4b607,
-       0xb980bfd0,
-       0xc9f002ec,
-       0x1ec9f01f,
-/* 0x00a3: nv_wr32_wait */
-       0xcf00bcd0,
-       0xccc800bc,
-       0xfa1bf41f,
-/* 0x00ae: watchdog_reset */
-       0x87f100f8,
-       0x84b60430,
-       0x1ff9f006,
-       0xf8008fd0,
-/* 0x00bd: watchdog_clear */
-       0x3087f100,
-       0x0684b604,
-       0xf80080d0,
-/* 0x00c9: wait_donez */
-       0xf094bd00,
-       0x07f10099,
-       0x03f03700,
-       0x0009d002,
-       0x07f104bd,
-       0x03f00600,
-       0x000ad002,
-/* 0x00e6: wait_donez_ne */
-       0x87f104bd,
-       0x83f00000,
-       0x0088cf01,
-       0xf4888aff,
-       0x94bdf31b,
-       0xf10099f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0109: wait_doneo */
-       0xf094bd00,
+       0xf002ecb9,
+       0x07f11fc9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x007a: nv_rd32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0xa7f0f31b,
+       0x1021f506,
+       0x00f7f101,
+       0x01f3f0cb,
+       0xf800ffcf,
+/* 0x009d: nv_wr32 */
+       0x0007f100,
+       0x0103f0cc,
+       0xbd000fd0,
+       0x02ecb904,
+       0xf01fc9f0,
+       0x07f11ec9,
+       0x03f0ca00,
+       0x000cd001,
+/* 0x00be: nv_wr32_wait */
+       0xc7f104bd,
+       0xc3f0ca00,
+       0x00cccf01,
+       0xf41fccc8,
+       0x00f8f31b,
+/* 0x00d0: wait_donez */
+       0x99f094bd,
+       0x0007f100,
+       0x0203f037,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x00ed: wait_donez_ne */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x1bf4888a,
+       0xf094bdf3,
        0x07f10099,
-       0x03f03700,
+       0x03f01700,
        0x0009d002,
-       0x87f104bd,
-       0x84b60818,
-       0x008ad006,
-/* 0x0124: wait_doneo_e */
-       0x040087f1,
-       0xcf0684b6,
-       0x8aff0088,
-       0xf30bf488,
+       0x00f804bd,
+/* 0x0110: wait_doneo */
        0x99f094bd,
        0x0007f100,
-       0x0203f017,
+       0x0203f037,
        0xbd0009d0,
-/* 0x0147: mmctx_size */
-       0xbd00f804,
-/* 0x0149: nv_mmctx_size_loop */
-       0x00e89894,
-       0xb61a85b6,
-       0x84b60180,
-       0x0098bb02,
-       0xb804e0b6,
-       0x1bf404ef,
-       0x029fb9eb,
-/* 0x0166: mmctx_xfer */
-       0x94bd00f8,
-       0xf10199f0,
-       0xf0370007,
-       0x09d00203,
-       0xf104bd00,
-       0xb6071087,
-       0x94bd0684,
-       0xf405bbfd,
-       0x8bd0090b,
-       0x0099f000,
-/* 0x018c: mmctx_base_disabled */
-       0xf405eefd,
-       0x8ed00c0b,
-       0xc08fd080,
-/* 0x019b: mmctx_multi_disabled */
-       0xb70199f0,
-       0xc8010080,
+       0x0007f104,
+       0x0203f006,
+       0xbd000ad0,
+/* 0x012d: wait_doneo_e */
+       0x0087f104,
+       0x0183f000,
+       0xff0088cf,
+       0x0bf4888a,
+       0xf094bdf3,
+       0x07f10099,
+       0x03f01700,
+       0x0009d002,
+       0x00f804bd,
+/* 0x0150: mmctx_size */
+/* 0x0152: nv_mmctx_size_loop */
+       0xe89894bd,
+       0x1a85b600,
+       0xb60180b6,
+       0x98bb0284,
+       0x04e0b600,
+       0xf404efb8,
+       0x9fb9eb1b,
+/* 0x016f: mmctx_xfer */
+       0xbd00f802,
+       0x0199f094,
+       0x370007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0xbbfd94bd,
+       0x120bf405,
+       0xc40007f1,
+       0xd00103f0,
+       0x04bd000b,
+/* 0x0197: mmctx_base_disabled */
+       0xfd0099f0,
+       0x0bf405ee,
+       0x0007f11e,
+       0x0103f0c6,
+       0xbd000ed0,
+       0x0007f104,
+       0x0103f0c7,
+       0xbd000fd0,
+       0x0199f004,
+/* 0x01b8: mmctx_multi_disabled */
+       0xb600abc8,
+       0xb9f010b4,
+       0x01aec80c,
+       0xfd11e4b6,
+       0x07f105be,
+       0x03f0c500,
+       0x000bd001,
+/* 0x01d6: mmctx_exec_loop */
+/* 0x01d6: mmctx_wait_free */
+       0xe7f104bd,
+       0xe3f0c500,
+       0x00eecf01,
+       0xf41fe4f0,
+       0xce98f30b,
+       0x05e9fd00,
+       0xc80007f1,
+       0xd00103f0,
+       0x04bd000e,
+       0xb804c0b6,
+       0x1bf404cd,
+       0x02abc8d8,
+/* 0x0207: mmctx_fini_wait */
+       0xf11f1bf4,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x1fb4f000,
+       0xf410b4b0,
+       0xa7f0f01b,
+       0xd021f402,
+/* 0x0223: mmctx_stop */
+       0xc82b0ef4,
        0xb4b600ab,
        0x0cb9f010,
-       0xb601aec8,
-       0xbefd11e4,
-       0x008bd005,
-/* 0x01b4: mmctx_exec_loop */
-/* 0x01b4: mmctx_wait_free */
-       0xf0008ecf,
-       0x0bf41fe4,
-       0x00ce98fa,
-       0xd005e9fd,
-       0xc0b6c08e,
-       0x04cdb804,
-       0xc8e81bf4,
-       0x1bf402ab,
-/* 0x01d5: mmctx_fini_wait */
-       0x008bcf18,
-       0xb01fb4f0,
-       0x1bf410b4,
-       0x02a7f0f7,
-       0xf4c921f4,
-/* 0x01ea: mmctx_stop */
-       0xabc81b0e,
-       0x10b4b600,
-       0xf00cb9f0,
-       0x8bd012b9,
-/* 0x01f9: mmctx_stop_wait */
-       0x008bcf00,
-       0xf412bbc8,
-/* 0x0202: mmctx_done */
-       0x94bdfa1b,
-       0xf10199f0,
-       0xf0170007,
-       0x09d00203,
-       0xf804bd00,
-/* 0x0215: strand_wait */
-       0xf0a0f900,
-       0x21f402a7,
-       0xf8a0fcc9,
-/* 0x0221: strand_pre */
-       0xfc87f100,
-       0x0283f04a,
-       0xd00c97f0,
-       0x21f50089,
-       0x00f80215,
-/* 0x0234: strand_post */
-       0x4afc87f1,
-       0xf00283f0,
-       0x89d00d97,
-       0x1521f500,
-/* 0x0247: strand_set */
-       0xf100f802,
-       0xf04ffca7,
-       0xaba202a3,
-       0xc7f00500,
-       0x00acd00f,
-       0xd00bc7f0,
-       0x21f500bc,
-       0xaed00215,
-       0x0ac7f000,
-       0xf500bcd0,
-       0xf8021521,
-/* 0x0271: strand_ctx_init */
-       0xf094bd00,
-       0x07f10399,
-       0x03f03700,
+       0xf112b9f0,
+       0xf0c50007,
+       0x0bd00103,
+/* 0x023b: mmctx_stop_wait */
+       0xf104bd00,
+       0xf0c500b7,
+       0xbbcf01b3,
+       0x12bbc800,
+/* 0x024b: mmctx_done */
+       0xbdf31bf4,
+       0x0199f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x025e: strand_wait */
+       0xa0f900f8,
+       0xf402a7f0,
+       0xa0fcd021,
+/* 0x026a: strand_pre */
+       0x97f000f8,
+       0xfc07f10c,
+       0x0203f04a,
+       0xbd0009d0,
+       0x5e21f504,
+/* 0x027f: strand_post */
+       0xf000f802,
+       0x07f10d97,
+       0x03f04afc,
        0x0009d002,
        0x21f504bd,
-       0xe7f00221,
-       0x4721f503,
-       0xfca7f102,
-       0x02a3f046,
-       0x0400aba0,
-       0xf040a0d0,
-       0xbcd001c7,
-       0x1521f500,
-       0x010c9202,
-       0xf000acd0,
-       0xbcd002c7,
-       0x1521f500,
-       0x3421f502,
-       0x8087f102,
-       0x0684b608,
-       0xb70089cf,
-       0x95220080,
-/* 0x02ca: ctx_init_strand_loop */
+       0x00f8025e,
+/* 0x0294: strand_set */
+       0xf10fc7f0,
+       0xf04ffc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f10bc7,
+       0x03f04afc,
+       0x000cd002,
+       0x07f104bd,
+       0x03f04ffc,
+       0x000ed002,
+       0xc7f004bd,
+       0xfc07f10a,
+       0x0203f04a,
+       0xbd000cd0,
+       0x5e21f504,
+/* 0x02d3: strand_ctx_init */
+       0xbd00f802,
+       0x0399f094,
+       0x370007f1,
+       0xd00203f0,
+       0x04bd0009,
+       0x026a21f5,
+       0xf503e7f0,
+       0xbd029421,
+       0xfc07f1c4,
+       0x0203f047,
+       0xbd000cd0,
+       0x01c7f004,
+       0x4afc07f1,
+       0xd00203f0,
+       0x04bd000c,
+       0x025e21f5,
+       0xf1010c92,
+       0xf046fc07,
+       0x0cd00203,
+       0xf004bd00,
+       0x07f102c7,
+       0x03f04afc,
+       0x000cd002,
+       0x21f504bd,
+       0x21f5025e,
+       0x87f1027f,
+       0x83f04200,
+       0x0097f102,
+       0x0293f020,
+       0x950099cf,
+/* 0x034a: ctx_init_strand_loop */
        0x8ed008fe,
        0x408ed000,
        0xb6808acf,
@@ -428,7 +458,7 @@ uint32_t nvf0_grhub_code[] = {
        0x170007f1,
        0xd00203f0,
        0x04bd0009,
-/* 0x02fe: error */
+/* 0x037e: error */
        0x07f100f8,
        0x03f00500,
        0x000fd002,
@@ -436,82 +466,117 @@ uint32_t nvf0_grhub_code[] = {
        0x0007f101,
        0x0303f007,
        0xbd000fd0,
-/* 0x031b: init */
+/* 0x039b: init */
        0xbd00f804,
-       0x0004fe04,
-       0xf10007fe,
-       0xf0120017,
-       0x12d00227,
-       0xb117f100,
-       0x0010fe05,
-       0x040017f1,
-       0xf1c010d0,
-       0xb6040437,
-       0x27f10634,
-       0x32d02003,
-       0x0427f100,
-       0x0132d020,
+       0x0007fe04,
+       0x420017f1,
+       0xcf0013f0,
+       0x11e70011,
+       0x14b60109,
+       0x0014fe08,
+       0xf10227f0,
+       0xf0120007,
+       0x02d00003,
+       0xf104bd00,
+       0xfe06c817,
+       0x24bd0010,
+       0x070007f1,
+       0xd00003f0,
+       0x04bd0002,
+       0x200327f1,
+       0x010007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200427f1,
+       0x010407f1,
+       0xd00103f0,
+       0x04bd0002,
        0x200b27f1,
-       0xf10232d0,
-       0xd0200c27,
-       0x27f10732,
-       0x24b60c24,
-       0x0003b906,
-       0xf10023d0,
+       0x010807f1,
+       0xd00103f0,
+       0x04bd0002,
+       0x200c27f1,
+       0x011c07f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1010392,
+       0xf0090007,
+       0x03d00303,
+       0xf104bd00,
        0xf0870427,
-       0x12d00023,
-       0x0012b700,
-       0x0427f001,
-       0xf40012d0,
-       0xe7f11031,
-       0xe3f09604,
-       0x6821f440,
-       0x8090f1c7,
-       0xf4f00301,
-       0x020f801f,
-       0xbb0117f0,
-       0x12b6041f,
-       0x0c27f101,
-       0x0624b604,
-       0xd00021d0,
-       0x17f14021,
-       0x0e980100,
-       0x010f9800,
-       0x014721f5,
-       0x070037f1,
-       0x950634b6,
-       0x34d00814,
-       0x4034d000,
-       0x130030b7,
-       0xb6001fbb,
-       0x3fd002f5,
-       0x0815b600,
-       0xb60110b6,
-       0x1fb90814,
-       0x7121f502,
-       0x001fbb02,
-       0xf1020398,
-       0xf0200047,
-/* 0x03f6: init_gpc */
-       0x4ea05043,
-       0x1fb90804,
-       0x8d21f402,
-       0x010c4ea0,
-       0x21f4f4bd,
-       0x044ea08d,
-       0x8d21f401,
-       0x01004ea0,
-       0xf402f7f0,
-       0x4ea08d21,
-/* 0x041e: init_gpc_wait */
-       0x21f40800,
-       0x1fffc868,
-       0xa0fa0bf4,
-       0xf408044e,
-       0x1fbb6821,
-       0x0040b700,
-       0x0132b680,
-       0xf1be1bf4,
+       0x07f10023,
+       0x03f00400,
+       0x0002d000,
+       0x27f004bd,
+       0x0007f104,
+       0x0003f003,
+       0xbd0002d0,
+       0x1031f404,
+       0x9604e7f1,
+       0xf440e3f0,
+       0xfeb96821,
+       0x90f1c702,
+       0xf0030180,
+       0x0f801ff4,
+       0x0117f002,
+       0xb6041fbb,
+       0x07f10112,
+       0x03f00300,
+       0x0001d001,
+       0x07f104bd,
+       0x03f00400,
+       0x0001d001,
+       0x17f104bd,
+       0xf7f00100,
+       0x7f21f502,
+       0x9121f507,
+       0x10f7f007,
+       0x07de21f5,
+       0x98000e98,
+       0x21f5010f,
+       0x14950150,
+       0x0007f108,
+       0x0103f0c0,
+       0xbd0004d0,
+       0x0007f104,
+       0x0103f0c1,
+       0xbd0004d0,
+       0x0030b704,
+       0x001fbb13,
+       0xf102f5b6,
+       0xf0d30007,
+       0x0fd00103,
+       0xb604bd00,
+       0x10b60815,
+       0x0814b601,
+       0xf5021fb9,
+       0xbb02d321,
+       0x0398001f,
+       0x0047f102,
+       0x5043f020,
+/* 0x04f4: init_gpc */
+       0x08044ea0,
+       0xf4021fb9,
+       0x4ea09d21,
+       0xf4bd010c,
+       0xa09d21f4,
+       0xf401044e,
+       0x4ea09d21,
+       0xf7f00100,
+       0x9d21f402,
+       0x08004ea0,
+/* 0x051c: init_gpc_wait */
+       0xc86821f4,
+       0x0bf41fff,
+       0x044ea0fa,
+       0x6821f408,
+       0xb7001fbb,
+       0xb6800040,
+       0x1bf40132,
+       0x00f7f0be,
+       0x07de21f5,
+       0xf500f7f0,
+       0xf1077f21,
        0xf0010007,
        0x01d00203,
        0xbd04bd00,
@@ -519,382 +584,379 @@ uint32_t nvf0_grhub_code[] = {
        0x300007f1,
        0xd00203f0,
        0x04bd0001,
-/* 0x0458: main */
+/* 0x0564: main */
        0xf40031f4,
        0xd7f00028,
        0x3921f410,
        0xb1f401f4,
        0xf54001e4,
-       0xbd00de1b,
+       0xbd00e91b,
        0x0499f094,
        0x370007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0b0017f1,
-       0xcf0614b6,
-       0x11cf4012,
-       0x1f13c800,
-       0x00870bf5,
-       0xf41f23c8,
-       0x20f9620b,
-       0xbd0212b9,
-       0x0799f094,
-       0x370007f1,
-       0xd00203f0,
-       0x04bd0009,
-       0xf40132f4,
-       0x21f50231,
-       0x94bd0801,
+       0xc00017f1,
+       0xcf0213f0,
+       0x27f10011,
+       0x23f0c100,
+       0x0022cf02,
+       0xf51f13c8,
+       0xc800890b,
+       0x0bf41f23,
+       0xb920f962,
+       0x94bd0212,
        0xf10799f0,
-       0xf0170007,
+       0xf0370007,
        0x09d00203,
-       0xfc04bd00,
-       0xf094bd20,
-       0x07f10699,
-       0x03f03700,
-       0x0009d002,
-       0x31f404bd,
-       0x0121f501,
-       0xf094bd08,
-       0x07f10699,
+       0xf404bd00,
+       0x31f40132,
+       0xaa21f502,
+       0xf094bd09,
+       0x07f10799,
        0x03f01700,
        0x0009d002,
-       0x0ef404bd,
-/* 0x04f9: chsw_prev_no_next */
-       0xb920f931,
-       0x32f40212,
-       0x0232f401,
-       0x080121f5,
-       0x17f120fc,
-       0x14b60b00,
-       0x0012d006,
-/* 0x0517: chsw_no_prev */
-       0xc8130ef4,
-       0x0bf41f23,
-       0x0131f40d,
-       0xf50232f4,
-/* 0x0527: chsw_done */
-       0xf1080121,
-       0xb60b0c17,
-       0x27f00614,
-       0x0012d001,
+       0x20fc04bd,
        0x99f094bd,
-       0x0007f104,
+       0x0007f106,
+       0x0203f037,
+       0xbd0009d0,
+       0x0131f404,
+       0x09aa21f5,
+       0x99f094bd,
+       0x0007f106,
        0x0203f017,
        0xbd0009d0,
-       0x130ef504,
-/* 0x0549: main_not_ctx_switch */
-       0x01e4b0ff,
-       0xb90d1bf4,
-       0x21f502f2,
-       0x0ef40795,
-/* 0x0559: main_not_ctx_chan */
-       0x02e4b046,
-       0xbd321bf4,
-       0x0799f094,
-       0x370007f1,
+       0x330ef404,
+/* 0x060c: chsw_prev_no_next */
+       0x12b920f9,
+       0x0132f402,
+       0xf50232f4,
+       0xfc09aa21,
+       0x0007f120,
+       0x0203f0c0,
+       0xbd0002d0,
+       0x130ef404,
+/* 0x062c: chsw_no_prev */
+       0xf41f23c8,
+       0x31f40d0b,
+       0x0232f401,
+       0x09aa21f5,
+/* 0x063c: chsw_done */
+       0xf10127f0,
+       0xf0c30007,
+       0x02d00203,
+       0xbd04bd00,
+       0x0499f094,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0xf40132f4,
-       0x21f50232,
-       0x94bd0801,
+       0xff080ef5,
+/* 0x0660: main_not_ctx_switch */
+       0xf401e4b0,
+       0xf2b90d1b,
+       0x4221f502,
+       0x460ef409,
+/* 0x0670: main_not_ctx_chan */
+       0xf402e4b0,
+       0x94bd321b,
        0xf10799f0,
-       0xf0170007,
+       0xf0370007,
        0x09d00203,
        0xf404bd00,
-/* 0x058e: main_not_ctx_save */
-       0xef94110e,
-       0x01f5f010,
-       0x02fe21f5,
-       0xfec00ef5,
-/* 0x059c: main_done */
-       0x29f024bd,
-       0x0007f11f,
-       0x0203f030,
-       0xbd0002d0,
-       0xab0ef504,
-/* 0x05b1: ih */
-       0xfe80f9fe,
-       0x80f90188,
-       0xa0f990f9,
-       0xd0f9b0f9,
-       0xf0f9e0f9,
-       0x0acf04bd,
-       0x04abc480,
-       0xf11d0bf4,
-       0xf01900b7,
-       0xbecf10d7,
-       0x00bfcf40,
+       0x32f40132,
+       0xaa21f502,
+       0xf094bd09,
+       0x07f10799,
+       0x03f01700,
+       0x0009d002,
+       0x0ef404bd,
+/* 0x06a5: main_not_ctx_save */
+       0x10ef9411,
+       0xf501f5f0,
+       0xf5037e21,
+/* 0x06b3: main_done */
+       0xbdfeb50e,
+       0x1f29f024,
+       0x300007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xfea00ef5,
+/* 0x06c8: ih */
+       0x88fe80f9,
+       0xf980f901,
+       0xf9a0f990,
+       0xf9d0f9b0,
+       0xbdf0f9e0,
+       0x00a7f104,
+       0x00a3f002,
+       0xc400aacf,
+       0x0bf404ab,
+       0x10d7f030,
+       0x1a00e7f1,
+       0xcf00e3f0,
+       0xf7f100ee,
+       0xf3f01900,
+       0x00ffcf00,
        0xb70421f4,
        0xf00400b0,
-       0xbed001e7,
-/* 0x05e9: ih_no_fifo */
-       0x00abe400,
-       0x0d0bf401,
-       0xf110d7f0,
-       0xf44001e7,
-/* 0x05fa: ih_no_ctxsw */
-       0xb7f10421,
-       0xb0bd0104,
-       0xf4b4abff,
-       0xa7f10d0b,
-       0xa4b60c1c,
-       0x00abd006,
-/* 0x0610: ih_no_other */
-       0xfc400ad0,
+       0x07f101e7,
+       0x03f01d00,
+       0x000ed000,
+/* 0x071a: ih_no_fifo */
+       0xabe404bd,
+       0x0bf40100,
+       0x10d7f00d,
+       0x4001e7f1,
+/* 0x072b: ih_no_ctxsw */
+       0xe40421f4,
+       0xf40400ab,
+       0xb7f1140b,
+       0xbfb90100,
+       0x44e7f102,
+       0x40e3f001,
+/* 0x0743: ih_no_fwmthd */
+       0xf19d21f4,
+       0xbd0104b7,
+       0xb4abffb0,
+       0xf10f0bf4,
+       0xf0070007,
+       0x0bd00303,
+/* 0x075b: ih_no_other */
+       0xf104bd00,
+       0xf0010007,
+       0x0ad00003,
+       0xfc04bd00,
        0xfce0fcf0,
        0xfcb0fcd0,
        0xfc90fca0,
        0x0088fe80,
        0x32f480fc,
-/* 0x062b: ctx_4170s */
-       0xf101f800,
-       0xf04170e7,
-       0xf5f040e3,
-       0x8d21f410,
-/* 0x063a: ctx_4170w */
+/* 0x077f: ctx_4170s */
+       0xf001f800,
+       0xffb910f5,
+       0x70e7f102,
+       0x40e3f041,
+       0xf89d21f4,
+/* 0x0791: ctx_4170w */
+       0x70e7f100,
+       0x40e3f041,
+       0xb96821f4,
+       0xf4f002ff,
+       0xf01bf410,
+/* 0x07a6: ctx_redswitch */
        0xe7f100f8,
-       0xe3f04170,
-       0x6821f440,
-       0xf410f4f0,
+       0xe5f00200,
+       0x20e5f040,
+       0xf110e5f0,
+       0xf0850007,
+       0x0ed00103,
+       0xf004bd00,
+/* 0x07c2: ctx_redswitch_delay */
+       0xf2b608f7,
+       0xfd1bf401,
+       0x0400e5f1,
+       0x0100e5f1,
+       0x850007f1,
+       0xd00103f0,
+       0x04bd000e,
+/* 0x07de: ctx_86c */
+       0x07f100f8,
+       0x03f02300,
+       0x000fd002,
+       0xffb904bd,
+       0x14e7f102,
+       0x40e3f08a,
+       0xb99d21f4,
+       0xe7f102ff,
+       0xe3f0a88c,
+       0x9d21f441,
+/* 0x0806: ctx_mem */
+       0x07f100f8,
+       0x03f08400,
+       0x000fd002,
+/* 0x0812: ctx_mem_wait */
+       0xf7f104bd,
+       0xf3f08400,
+       0x00ffcf02,
+       0xf405fffd,
        0x00f8f31b,
-/* 0x064c: ctx_redswitch */
-       0x0614e7f1,
-       0xf106e4b6,
-       0xd00270f7,
-       0xf7f000ef,
-/* 0x065d: ctx_redswitch_delay */
-       0x01f2b608,
-       0xf1fd1bf4,
-       0xd00770f7,
-       0x00f800ef,
-/* 0x066c: ctx_86c */
-       0x086ce7f1,
-       0xd006e4b6,
-       0xe7f100ef,
-       0xe3f08a14,
-       0x8d21f440,
-       0xa86ce7f1,
-       0xf441e3f0,
-       0x00f88d21,
-/* 0x068c: ctx_load */
+/* 0x0824: ctx_load */
        0x99f094bd,
        0x0007f105,
        0x0203f037,
        0xbd0009d0,
        0x0ca7f004,
-       0xf1c921f4,
-       0xb60a2417,
-       0x10d00614,
-       0x0037f100,
-       0x0634b60b,
-       0xf14032d0,
-       0xb60a0c17,
-       0x47f00614,
-       0x0012d007,
-/* 0x06c7: ctx_chan_wait_0 */
-       0xcf4014d0,
-       0x44f04014,
-       0xfa1bf41f,
-       0xfe0032d0,
-       0x2af0000b,
-       0x0424b61f,
-       0xbd0220b6,
+       0xbdd021f4,
+       0x0007f1f4,
+       0x0203f089,
+       0xbd000fd0,
+       0x0007f104,
+       0x0203f0c1,
+       0xbd0002d0,
+       0x0007f104,
+       0x0203f083,
+       0xbd0002d0,
+       0x07f7f004,
+       0x080621f5,
+       0xc00007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf0000bfe,
+       0x24b61f2a,
+       0x0220b604,
+       0x99f094bd,
+       0x0007f108,
+       0x0203f037,
+       0xbd0009d0,
+       0x0007f104,
+       0x0203f081,
+       0xbd0002d0,
+       0x0027f104,
+       0x0023f100,
+       0x0225f080,
+       0x880007f1,
+       0xd00203f0,
+       0x04bd0002,
+       0xf11017f0,
+       0xf0020027,
+       0x12fa0223,
+       0xbd03f805,
        0x0899f094,
-       0x370007f1,
+       0x170007f1,
        0xd00203f0,
        0x04bd0009,
-       0x0a0417f1,
-       0xd00614b6,
-       0x17f10012,
-       0x14b60a20,
-       0x0227f006,
-       0x800023f1,
-       0xf00012d0,
-       0x27f11017,
-       0x23f00200,
-       0x0512fa02,
-       0x94bd03f8,
-       0xf10899f0,
-       0xf0170007,
+       0xb6810198,
+       0x02981814,
+       0x0825b680,
+       0x800512fd,
+       0x94bd1601,
+       0xf10999f0,
+       0xf0370007,
        0x09d00203,
-       0x9804bd00,
-       0x14b68101,
-       0x80029818,
-       0xfd0825b6,
-       0x01800512,
-       0xf094bd16,
-       0x07f10999,
-       0x03f03700,
-       0x0009d002,
-       0x27f104bd,
-       0x24b60a04,
-       0x0021d006,
-       0xf10127f0,
-       0xb60a2017,
-       0x12d00614,
-       0x0017f100,
-       0x0613f001,
-       0xf80501fa,
-       0xf094bd03,
-       0x07f10999,
-       0x03f01700,
-       0x0009d002,
-       0x94bd04bd,
-       0xf10599f0,
+       0xf104bd00,
+       0xf0810007,
+       0x01d00203,
+       0xf004bd00,
+       0x07f10127,
+       0x03f08800,
+       0x0002d002,
+       0x17f104bd,
+       0x13f00100,
+       0x0501fa06,
+       0x94bd03f8,
+       0xf10999f0,
        0xf0170007,
        0x09d00203,
-       0xf804bd00,
-/* 0x0795: ctx_chan */
-       0x8c21f500,
-       0x0ca7f006,
-       0xf1c921f4,
-       0xb60a1017,
-       0x27f00614,
-       0x0012d005,
-/* 0x07ac: ctx_chan_wait */
-       0xfd0012cf,
-       0x1bf40522,
-/* 0x07b7: ctx_mmio_exec */
-       0x9800f8fa,
-       0x27f14103,
-       0x24b60a04,
-       0x0023d006,
-/* 0x07c6: ctx_mmio_loop */
+       0xbd04bd00,
+       0x0599f094,
+       0x170007f1,
+       0xd00203f0,
+       0x04bd0009,
+/* 0x0942: ctx_chan */
+       0x21f500f8,
+       0xa7f00824,
+       0xd021f40c,
+       0xf505f7f0,
+       0xf8080621,
+/* 0x0955: ctx_mmio_exec */
+       0x41039800,
+       0x810007f1,
+       0xd00203f0,
+       0x04bd0003,
+/* 0x0966: ctx_mmio_loop */
        0x34c434bd,
        0x0f1bf4ff,
        0x020057f1,
        0xfa0653f0,
        0x03f80535,
-/* 0x07d8: ctx_mmio_pull */
+/* 0x0978: ctx_mmio_pull */
        0x98804e98,
        0x21f4814f,
-       0x0830b68d,
+       0x0830b69d,
        0xf40112b6,
-/* 0x07ea: ctx_mmio_done */
+/* 0x098a: ctx_mmio_done */
        0x0398df1b,
-       0x0023d016,
-       0xf1400080,
-       0xf0010017,
-       0x01fa0613,
-       0xf803f806,
-/* 0x0801: ctx_xfer */
-       0x00f7f100,
-       0x06f4b60c,
-       0xd004e7f0,
-/* 0x080e: ctx_xfer_idle */
-       0xfecf80fe,
-       0x00e4f100,
-       0xf91bf420,
-       0xf40611f4,
-/* 0x081e: ctx_xfer_pre */
-       0xf7f00d02,
-       0x6c21f510,
-       0x1c11f406,
-/* 0x0828: ctx_xfer_pre_load */
-       0xf502f7f0,
-       0xf5062b21,
-       0xf5063a21,
-       0xbd064c21,
-       0x2b21f5f4,
-       0x8c21f506,
-/* 0x0841: ctx_xfer_exec */
-       0x16019806,
-       0x041427f1,
-       0xd00624b6,
-       0xe7f10020,
-       0xe3f0a500,
-       0x021fb941,
-       0xb68d21f4,
-       0xfcf004e0,
-       0x022cf001,
-       0xfd0124b6,
-       0x21f405f2,
-       0xfc17f18d,
-       0x0213f04a,
-       0xd00c27f0,
-       0x21f50012,
-       0x27f10215,
-       0x23f047fc,
-       0x0020d002,
+       0x0007f116,
+       0x0203f081,
+       0xbd0003d0,
+       0x40008004,
+       0x010017f1,
+       0xfa0613f0,
+       0x03f80601,
+/* 0x09aa: ctx_xfer */
+       0xe7f000f8,
+       0x0007f104,
+       0x0303f002,
+       0xbd000ed0,
+/* 0x09b9: ctx_xfer_idle */
+       0x00e7f104,
+       0x03e3f000,
+       0xf100eecf,
+       0xf42000e4,
+       0x11f4f21b,
+       0x0d02f406,
+/* 0x09d0: ctx_xfer_pre */
+       0xf510f7f0,
+       0xf407de21,
+/* 0x09da: ctx_xfer_pre_load */
+       0xf7f01c11,
+       0x7f21f502,
+       0x9121f507,
+       0xa621f507,
+       0xf5f4bd07,
+       0xf5077f21,
+/* 0x09f3: ctx_xfer_exec */
+       0x98082421,
+       0x24bd1601,
+       0x050007f1,
+       0xd00103f0,
+       0x04bd0002,
+       0xf1021fb9,
+       0xf0a500e7,
+       0x21f441e3,
+       0x01fcf09d,
+       0xb6022cf0,
+       0xf2fd0124,
+       0x02ffb905,
+       0xa504e7f1,
+       0xf441e3f0,
+       0x21f59d21,
+       0x24bd026a,
+       0x47fc07f1,
+       0xd00203f0,
+       0x04bd0002,
        0xb6012cf0,
-       0x12d00320,
-       0x01acf000,
-       0xf006a5f0,
-       0x0c9800b7,
-       0x010d9800,
-       0xf500e7f0,
-       0xf0016621,
-       0x21f508a7,
-       0x21f50109,
-       0x01f40215,
-       0x0ca7f022,
-       0xf1c921f4,
-       0xb60a1017,
-       0x27f00614,
-       0x0012d005,
-/* 0x08c8: ctx_xfer_post_save_wait */
-       0xfd0012cf,
-       0x1bf40522,
-       0x2e02f4fa,
-/* 0x08d4: ctx_xfer_post */
-       0xf502f7f0,
-       0xbd062b21,
-       0x6c21f5f4,
-       0x3421f506,
-       0x3a21f502,
-       0xf5f4bd06,
-       0xf4062b21,
-       0x01981011,
-       0x0511fd40,
-       0xf5070bf4,
-/* 0x08ff: ctx_xfer_no_post_mmio */
-/* 0x08ff: ctx_xfer_done */
-       0xf807b721,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x07f10320,
+       0x03f04afc,
+       0x0002d002,
+       0xacf004bd,
+       0x06a5f001,
+       0x9800b7f0,
+       0x0d98000c,
+       0x00e7f001,
+       0x016f21f5,
+       0xf508a7f0,
+       0xf5011021,
+       0xf4025e21,
+       0xa7f01301,
+       0xd021f40c,
+       0xf505f7f0,
+       0xf4080621,
+/* 0x0a82: ctx_xfer_post */
+       0xf7f02e02,
+       0x7f21f502,
+       0xf5f4bd07,
+       0xf507de21,
+       0xf5027f21,
+       0xbd079121,
+       0x7f21f5f4,
+       0x1011f407,
+       0xfd400198,
+       0x0bf40511,
+       0x5521f507,
+/* 0x0aad: ctx_xfer_no_post_mmio */
+/* 0x0aad: ctx_xfer_done */
+       0x0000f809,
        0x00000000,
        0x00000000,
        0x00000000,
index 33a5a82eccbd6e8114f55d8d8766d22929474d80..6ffe28307dbd6e420a019d0e7dd4ac891f531fd7 100644 (file)
 #define GF117 0xd7
 #define GK100 0xe0
 #define GK110 0xf0
+#define GK208 0x108
 
+#define NV_PGRAPH_FECS_INTR_ACK                                        0x409004
+#define NV_PGRAPH_FECS_INTR                                            0x409008
+#define NV_PGRAPH_FECS_INTR_FWMTHD                                   0x00000400
+#define NV_PGRAPH_FECS_INTR_CHSW                                     0x00000100
+#define NV_PGRAPH_FECS_INTR_FIFO                                     0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE                                       0x40900c
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO                                0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO_LEVEL                          0x00000004
+#define NV_PGRAPH_FECS_INTR_MODE_FIFO_EDGE                           0x00000000
+#define NV_PGRAPH_FECS_INTR_EN_SET                                     0x409010
+#define NV_PGRAPH_FECS_INTR_EN_SET_FIFO                              0x00000004
+#define NV_PGRAPH_FECS_INTR_ROUTE                                      0x40901c
+#define NV_PGRAPH_FECS_ACCESS                                          0x409048
+#define NV_PGRAPH_FECS_ACCESS_FIFO                                   0x00000002
+#define NV_PGRAPH_FECS_FIFO_DATA                                       0x409064
+#define NV_PGRAPH_FECS_FIFO_CMD                                        0x409068
+#define NV_PGRAPH_FECS_FIFO_ACK                                        0x409074
+#define NV_PGRAPH_FECS_CAPS                                            0x409108
 #define NV_PGRAPH_FECS_SIGNAL                                          0x409400
+#define NV_PGRAPH_FECS_IROUTE                                          0x409404
+#define NV_PGRAPH_FECS_BAR_MASK0                                       0x40940c
+#define NV_PGRAPH_FECS_BAR_MASK1                                       0x409410
+#define NV_PGRAPH_FECS_BAR                                             0x409414
+#define NV_PGRAPH_FECS_BAR_SET                                         0x409418
+#define NV_PGRAPH_FECS_RED_SWITCH                                      0x409614
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_ROP                         0x00000400
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_GPC                         0x00000200
+#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_MAIN                        0x00000100
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_ROP                          0x00000040
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_GPC                          0x00000020
+#define NV_PGRAPH_FECS_RED_SWITCH_POWER_MAIN                         0x00000010
+#define NV_PGRAPH_FECS_RED_SWITCH_PAUSE_GPC                          0x00000002
+#define NV_PGRAPH_FECS_RED_SWITCH_PAUSE_MAIN                         0x00000001
+#define NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE                               0x409700
+#define NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE                               0x409704
+#define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c
+#define NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE                               0x409700
+#define NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE                               0x409704
+#define NV_PGRAPH_FECS_MMCTX_BASE                                      0x409710
+#define NV_PGRAPH_FECS_MMCTX_CTRL                                      0x409714
+#define NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE                              0x409718
+#define NV_PGRAPH_FECS_MMCTX_MULTI_MASK                                0x40971c
+#define NV_PGRAPH_FECS_MMCTX_QUEUE                                     0x409720
+#define NV_PGRAPH_FECS_MMIO_CTRL                                       0x409728
+#define NV_PGRAPH_FECS_MMIO_RDVAL                                      0x40972c
+#define NV_PGRAPH_FECS_MMIO_WRVAL                                      0x409730
+#define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c
 #if CHIPSET < GK110
 #define NV_PGRAPH_FECS_CC_SCRATCH_VAL(n)                    ((n) * 4 + 0x409800)
 #define NV_PGRAPH_FECS_CC_SCRATCH_SET(n)                    ((n) * 4 + 0x409820)
 #define NV_PGRAPH_FECS_CC_SCRATCH_CLR(n)                    ((n) * 4 + 0x409840)
+#define NV_PGRAPH_FECS_UNK86C                                          0x40986c
 #else
 #define NV_PGRAPH_FECS_CC_SCRATCH_VAL(n)                    ((n) * 4 + 0x409800)
 #define NV_PGRAPH_FECS_CC_SCRATCH_CLR(n)                    ((n) * 4 + 0x409840)
+#define NV_PGRAPH_FECS_UNK86C                                          0x40988c
 #define NV_PGRAPH_FECS_CC_SCRATCH_SET(n)                    ((n) * 4 + 0x4098c0)
 #endif
+#define NV_PGRAPH_FECS_STRANDS_CNT                                     0x409880
+#define NV_PGRAPH_FECS_STRAND_SAVE_SWBASE                              0x409908
+#define NV_PGRAPH_FECS_STRAND_LOAD_SWBASE                              0x40990c
+#define NV_PGRAPH_FECS_STRAND_WORDS                                    0x409910
+#define NV_PGRAPH_FECS_STRAND_DATA                                     0x409918
+#define NV_PGRAPH_FECS_STRAND_SELECT                                   0x40991c
+#define NV_PGRAPH_FECS_STRAND_CMD                                      0x409928
+#define NV_PGRAPH_FECS_STRAND_CMD_SEEK                               0x00000001
+#define NV_PGRAPH_FECS_STRAND_CMD_GET_INFO                           0x00000002
+#define NV_PGRAPH_FECS_STRAND_CMD_SAVE                               0x00000003
+#define NV_PGRAPH_FECS_STRAND_CMD_LOAD                               0x00000004
+#define NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER                    0x0000000a
+#define NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER                  0x0000000b
+#define NV_PGRAPH_FECS_STRAND_CMD_ENABLE                             0x0000000c
+#define NV_PGRAPH_FECS_STRAND_CMD_DISABLE                            0x0000000d
+#define NV_PGRAPH_FECS_STRAND_FILTER                                   0x40993c
+#define NV_PGRAPH_FECS_MEM_BASE                                        0x409a04
+#define NV_PGRAPH_FECS_MEM_CHAN                                        0x409a0c
+#define NV_PGRAPH_FECS_MEM_CMD                                         0x409a10
+#define NV_PGRAPH_FECS_MEM_CMD_LOAD_CHAN                             0x00000007
+#define NV_PGRAPH_FECS_MEM_TARGET                                      0x409a20
+#define NV_PGRAPH_FECS_MEM_TARGET_UNK31                              0x80000000
+#define NV_PGRAPH_FECS_MEM_TARGET_AS                                 0x0000001f
+#define NV_PGRAPH_FECS_MEM_TARGET_AS_VM                              0x00000001
+#define NV_PGRAPH_FECS_MEM_TARGET_AS_VRAM                            0x00000002
+#define NV_PGRAPH_FECS_CHAN_ADDR                                       0x409b00
+#define NV_PGRAPH_FECS_CHAN_NEXT                                       0x409b04
+#define NV_PGRAPH_FECS_CHSW                                            0x409b0c
+#define NV_PGRAPH_FECS_CHSW_ACK                                      0x00000001
 #define NV_PGRAPH_FECS_INTR_UP_SET                                     0x409c1c
+#define NV_PGRAPH_FECS_INTR_UP_EN                                      0x409c24
 
+#define NV_PGRAPH_GPCX_GPCCS_INTR_ACK                                  0x41a004
+#define NV_PGRAPH_GPCX_GPCCS_INTR                                      0x41a008
+#define NV_PGRAPH_GPCX_GPCCS_INTR_FIFO                               0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET                               0x41a010
+#define NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO                        0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE                                0x41a01c
+#define NV_PGRAPH_GPCX_GPCCS_ACCESS                                    0x41a048
+#define NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO                             0x00000002
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_DATA                                 0x41a064
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_CMD                                  0x41a068
+#define NV_PGRAPH_GPCX_GPCCS_FIFO_ACK                                  0x41a074
+#define NV_PGRAPH_GPCX_GPCCS_UNITS                                     0x41a608
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH                                0x41a614
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11                        0x00000800
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE                       0x00000200
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER                        0x00000020
+#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_PAUSE                        0x00000002
+#define NV_PGRAPH_GPCX_GPCCS_MYINDEX                                   0x41a618
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE                         0x41a700
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE                         0x41a704
+#define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT                          0x41a74c
 #if CHIPSET < GK110
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(n)              ((n) * 4 + 0x41a820)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_CLR(n)              ((n) * 4 + 0x41a840)
+#define NV_PGRAPH_GPCX_GPCCS_UNK86C                                    0x41a86c
 #else
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_CLR(n)              ((n) * 4 + 0x41a840)
+#define NV_PGRAPH_GPCX_GPCCS_UNK86C                                    0x41a88c
 #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(n)              ((n) * 4 + 0x41a8c0)
 #endif
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT                             0x41a91c
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD                                0x41a928
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE                         0x00000003
+#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_LOAD                         0x00000004
+#define NV_PGRAPH_GPCX_GPCCS_MEM_BASE                                  0x41aa04
 
 #define mmctx_data(r,c) .b32 (((c - 1) << 26) | r)
 #define queue_init      .skip 72 // (2 * 4) + ((8 * 4) * 2)
 #define T_LCHAN   8
 #define T_LCTXH   9
 
-#define nv_mkmm(rv,r) /*
-*/     movw rv  ((r) & 0x0000fffc) /*
-*/     sethi rv ((r) & 0x00ff0000)
+#if CHIPSET < GK208
+#define imm32(reg,val) /*
+*/     movw reg  ((val) & 0x0000ffff) /*
+*/     sethi reg ((val) & 0xffff0000)
+#else
+#define imm32(reg,val) /*
+*/     mov reg (val)
+#endif
+
 #define nv_mkio(rv,r,i) /*
-*/     nv_mkmm(rv, (((r) & 0xffc) << 6) | ((i) << 2))
+*/     imm32(rv, (((r) & 0xffc) << 6) | ((i) << 2))
+
+#define hash #
+#define fn(a) a
+#if CHIPSET < GK208
+#define call(a) call fn(hash)a
+#else
+#define call(a) lcall fn(hash)a
+#endif
 
 #define nv_iord(rv,r,i) /*
 */     nv_mkio(rv,r,i) /*
 */     iord rv I[rv]
+
 #define nv_iowr(r,i,rv) /*
 */     nv_mkio($r0,r,i) /*
 */     iowr I[$r0] rv /*
 */     clear b32 $r0
 
+#define nv_rd32(reg,addr) /*
+*/     imm32($r14, addr) /*
+*/     call(nv_rd32) /*
+*/     mov b32 reg $r15
+
+#define nv_wr32(addr,reg) /*
+*/     mov b32 $r15 reg /*
+*/     imm32($r14, addr) /*
+*/     call(nv_wr32)
+
 #define trace_set(bit) /*
 */     clear b32 $r9 /*
 */     bset $r9 bit /*
 */     nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_SET(7), 0, $r9)
+
 #define trace_clr(bit) /*
 */     clear b32 $r9 /*
 */     bset $r9 bit /*
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c
new file mode 100644 (file)
index 0000000..e1af65e
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "nvc0.h"
+
+/*******************************************************************************
+ * Graphics object classes
+ ******************************************************************************/
+
+static struct nouveau_oclass
+nv108_graph_sclass[] = {
+       { 0x902d, &nouveau_object_ofuncs },
+       { 0xa140, &nouveau_object_ofuncs },
+       { 0xa197, &nouveau_object_ofuncs },
+       { 0xa1c0, &nouveau_object_ofuncs },
+       {}
+};
+
+/*******************************************************************************
+ * PGRAPH engine/subdev functions
+ ******************************************************************************/
+
+static struct nvc0_graph_init
+nv108_graph_init_regs[] = {
+       { 0x400080,   1, 0x04, 0x003083c2 },
+       { 0x400088,   1, 0x04, 0x0001bfe7 },
+       { 0x40008c,   1, 0x04, 0x00000000 },
+       { 0x400090,   1, 0x04, 0x00000030 },
+       { 0x40013c,   1, 0x04, 0x003901f7 },
+       { 0x400140,   1, 0x04, 0x00000100 },
+       { 0x400144,   1, 0x04, 0x00000000 },
+       { 0x400148,   1, 0x04, 0x00000110 },
+       { 0x400138,   1, 0x04, 0x00000000 },
+       { 0x400130,   2, 0x04, 0x00000000 },
+       { 0x400124,   1, 0x04, 0x00000002 },
+       {}
+};
+
+struct nvc0_graph_init
+nv108_graph_init_unk58xx[] = {
+       { 0x405844,   1, 0x04, 0x00ffffff },
+       { 0x405850,   1, 0x04, 0x00000000 },
+       { 0x405900,   1, 0x04, 0x00000000 },
+       { 0x405908,   1, 0x04, 0x00000000 },
+       { 0x405928,   1, 0x04, 0x00000000 },
+       { 0x40592c,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_graph_init_gpc[] = {
+       { 0x418408,   1, 0x04, 0x00000000 },
+       { 0x4184a0,   3, 0x04, 0x00000000 },
+       { 0x418604,   1, 0x04, 0x00000000 },
+       { 0x418680,   1, 0x04, 0x00000000 },
+       { 0x418714,   1, 0x04, 0x00000000 },
+       { 0x418384,   2, 0x04, 0x00000000 },
+       { 0x418814,   3, 0x04, 0x00000000 },
+       { 0x418b04,   1, 0x04, 0x00000000 },
+       { 0x4188c8,   2, 0x04, 0x00000000 },
+       { 0x4188d0,   1, 0x04, 0x00010000 },
+       { 0x4188d4,   1, 0x04, 0x00000201 },
+       { 0x418910,   1, 0x04, 0x00010001 },
+       { 0x418914,   1, 0x04, 0x00000301 },
+       { 0x418918,   1, 0x04, 0x00800000 },
+       { 0x418980,   1, 0x04, 0x77777770 },
+       { 0x418984,   3, 0x04, 0x77777777 },
+       { 0x418c04,   1, 0x04, 0x00000000 },
+       { 0x418c64,   2, 0x04, 0x00000000 },
+       { 0x418c88,   1, 0x04, 0x00000000 },
+       { 0x418cb4,   2, 0x04, 0x00000000 },
+       { 0x418d00,   1, 0x04, 0x00000000 },
+       { 0x418d28,   2, 0x04, 0x00000000 },
+       { 0x418f00,   1, 0x04, 0x00000400 },
+       { 0x418f08,   1, 0x04, 0x00000000 },
+       { 0x418f20,   2, 0x04, 0x00000000 },
+       { 0x418e00,   1, 0x04, 0x00000000 },
+       { 0x418e08,   1, 0x04, 0x00000000 },
+       { 0x418e1c,   2, 0x04, 0x00000000 },
+       { 0x41900c,   1, 0x04, 0x00000000 },
+       { 0x419018,   1, 0x04, 0x00000000 },
+       {}
+};
+
+static struct nvc0_graph_init
+nv108_graph_init_tpc[] = {
+       { 0x419d0c,   1, 0x04, 0x00000000 },
+       { 0x419d10,   1, 0x04, 0x00000014 },
+       { 0x419ab0,   1, 0x04, 0x00000000 },
+       { 0x419ac8,   1, 0x04, 0x00000000 },
+       { 0x419ab8,   1, 0x04, 0x000000e7 },
+       { 0x419abc,   2, 0x04, 0x00000000 },
+       { 0x419ab4,   1, 0x04, 0x00000000 },
+       { 0x419aa8,   2, 0x04, 0x00000000 },
+       { 0x41980c,   1, 0x04, 0x00000010 },
+       { 0x419844,   1, 0x04, 0x00000000 },
+       { 0x419850,   1, 0x04, 0x00000004 },
+       { 0x419854,   2, 0x04, 0x00000000 },
+       { 0x419c98,   1, 0x04, 0x00000000 },
+       { 0x419ca8,   1, 0x04, 0x00000000 },
+       { 0x419cb0,   1, 0x04, 0x01000000 },
+       { 0x419cb4,   1, 0x04, 0x00000000 },
+       { 0x419cb8,   1, 0x04, 0x00b08bea },
+       { 0x419c84,   1, 0x04, 0x00010384 },
+       { 0x419cbc,   1, 0x04, 0x281b3646 },
+       { 0x419cc0,   2, 0x04, 0x00000000 },
+       { 0x419c80,   1, 0x04, 0x00000230 },
+       { 0x419ccc,   2, 0x04, 0x00000000 },
+       { 0x419c0c,   1, 0x04, 0x00000000 },
+       { 0x419e00,   1, 0x04, 0x00000080 },
+       { 0x419ea0,   1, 0x04, 0x00000000 },
+       { 0x419ee4,   1, 0x04, 0x00000000 },
+       { 0x419ea4,   1, 0x04, 0x00000100 },
+       { 0x419ea8,   1, 0x04, 0x00000000 },
+       { 0x419eb4,   1, 0x04, 0x00000000 },
+       { 0x419ebc,   2, 0x04, 0x00000000 },
+       { 0x419edc,   1, 0x04, 0x00000000 },
+       { 0x419f00,   1, 0x04, 0x00000000 },
+       { 0x419ed0,   1, 0x04, 0x00003234 },
+       { 0x419f74,   1, 0x04, 0x00015555 },
+       { 0x419f80,   4, 0x04, 0x00000000 },
+       {}
+};
+
+static int
+nv108_graph_fini(struct nouveau_object *object, bool suspend)
+{
+       struct nvc0_graph_priv *priv = (void *)object;
+       static const struct {
+               u32 addr;
+               u32 data;
+       } magic[] = {
+               { 0x020520, 0xfffffffc },
+               { 0x020524, 0xfffffffe },
+               { 0x020524, 0xfffffffc },
+               { 0x020524, 0xfffffff8 },
+               { 0x020524, 0xffffffe0 },
+               { 0x020530, 0xfffffffe },
+               { 0x02052c, 0xfffffffa },
+               { 0x02052c, 0xfffffff0 },
+               { 0x02052c, 0xffffffc0 },
+               { 0x02052c, 0xffffff00 },
+               { 0x02052c, 0xfffffc00 },
+               { 0x02052c, 0xfffcfc00 },
+               { 0x02052c, 0xfff0fc00 },
+               { 0x02052c, 0xff80fc00 },
+               { 0x020528, 0xfffffffe },
+               { 0x020528, 0xfffffffc },
+       };
+       int i;
+
+       nv_mask(priv, 0x000200, 0x08001000, 0x00000000);
+       nv_mask(priv, 0x0206b4, 0x00000000, 0x00000000);
+       for (i = 0; i < ARRAY_SIZE(magic); i++) {
+               nv_wr32(priv, magic[i].addr, magic[i].data);
+               nv_wait(priv, magic[i].addr, 0x80000000, 0x00000000);
+       }
+
+       return nouveau_graph_fini(&priv->base, suspend);
+}
+
+static struct nvc0_graph_init *
+nv108_graph_init_mmio[] = {
+       nv108_graph_init_regs,
+       nvf0_graph_init_unk40xx,
+       nvc0_graph_init_unk44xx,
+       nvc0_graph_init_unk78xx,
+       nvc0_graph_init_unk60xx,
+       nvd9_graph_init_unk64xx,
+       nv108_graph_init_unk58xx,
+       nvc0_graph_init_unk80xx,
+       nvf0_graph_init_unk70xx,
+       nvf0_graph_init_unk5bxx,
+       nv108_graph_init_gpc,
+       nv108_graph_init_tpc,
+       nve4_graph_init_unk,
+       nve4_graph_init_unk88xx,
+       NULL
+};
+
+#include "fuc/hubnv108.fuc5.h"
+
+static struct nvc0_graph_ucode
+nv108_graph_fecs_ucode = {
+       .code.data = nv108_grhub_code,
+       .code.size = sizeof(nv108_grhub_code),
+       .data.data = nv108_grhub_data,
+       .data.size = sizeof(nv108_grhub_data),
+};
+
+#include "fuc/gpcnv108.fuc5.h"
+
+static struct nvc0_graph_ucode
+nv108_graph_gpccs_ucode = {
+       .code.data = nv108_grgpc_code,
+       .code.size = sizeof(nv108_grgpc_code),
+       .data.data = nv108_grgpc_data,
+       .data.size = sizeof(nv108_grgpc_data),
+};
+
+struct nouveau_oclass *
+nv108_graph_oclass = &(struct nvc0_graph_oclass) {
+       .base.handle = NV_ENGINE(GR, 0x08),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_ctor,
+               .dtor = nvc0_graph_dtor,
+               .init = nve4_graph_init,
+               .fini = nv108_graph_fini,
+       },
+       .cclass = &nv108_grctx_oclass,
+       .sclass =  nv108_graph_sclass,
+       .mmio = nv108_graph_init_mmio,
+       .fecs.ucode = &nv108_graph_fecs_ucode,
+       .gpccs.ucode = &nv108_graph_gpccs_ucode,
+}.base;
index 03de5175dd9f8bcdb1a2ad48c18de965cf31a3c1..30ed19c52e05ca0cd6a1e759a8fc426f61f246a7 100644 (file)
@@ -304,12 +304,28 @@ nv84_graph_tlb_flush(struct nouveau_engine *engine)
        return timeout ? -EBUSY : 0;
 }
 
-static const struct nouveau_enum nv50_mp_exec_error_names[] = {
-       { 3, "STACK_UNDERFLOW", NULL },
-       { 4, "QUADON_ACTIVE", NULL },
-       { 8, "TIMEOUT", NULL },
-       { 0x10, "INVALID_OPCODE", NULL },
-       { 0x40, "BREAKPOINT", NULL },
+static const struct nouveau_bitfield nv50_mp_exec_errors[] = {
+       { 0x01, "STACK_UNDERFLOW" },
+       { 0x02, "STACK_MISMATCH" },
+       { 0x04, "QUADON_ACTIVE" },
+       { 0x08, "TIMEOUT" },
+       { 0x10, "INVALID_OPCODE" },
+       { 0x20, "PM_OVERFLOW" },
+       { 0x40, "BREAKPOINT" },
+       {}
+};
+
+static const struct nouveau_bitfield nv50_mpc_traps[] = {
+       { 0x0000001, "LOCAL_LIMIT_READ" },
+       { 0x0000010, "LOCAL_LIMIT_WRITE" },
+       { 0x0000040, "STACK_LIMIT" },
+       { 0x0000100, "GLOBAL_LIMIT_READ" },
+       { 0x0001000, "GLOBAL_LIMIT_WRITE" },
+       { 0x0010000, "MP0" },
+       { 0x0020000, "MP1" },
+       { 0x0040000, "GLOBAL_LIMIT_RED" },
+       { 0x0400000, "GLOBAL_LIMIT_ATOM" },
+       { 0x4000000, "MP2" },
        {}
 };
 
@@ -396,6 +412,60 @@ static const struct nouveau_bitfield nv50_graph_intr_name[] = {
        {}
 };
 
+static const struct nouveau_bitfield nv50_graph_trap_prop[] = {
+       { 0x00000004, "SURF_WIDTH_OVERRUN" },
+       { 0x00000008, "SURF_HEIGHT_OVERRUN" },
+       { 0x00000010, "DST2D_FAULT" },
+       { 0x00000020, "ZETA_FAULT" },
+       { 0x00000040, "RT_FAULT" },
+       { 0x00000080, "CUDA_FAULT" },
+       { 0x00000100, "DST2D_STORAGE_TYPE_MISMATCH" },
+       { 0x00000200, "ZETA_STORAGE_TYPE_MISMATCH" },
+       { 0x00000400, "RT_STORAGE_TYPE_MISMATCH" },
+       { 0x00000800, "DST2D_LINEAR_MISMATCH" },
+       { 0x00001000, "RT_LINEAR_MISMATCH" },
+       {}
+};
+
+static void
+nv50_priv_prop_trap(struct nv50_graph_priv *priv,
+                   u32 ustatus_addr, u32 ustatus, u32 tp)
+{
+       u32 e0c = nv_rd32(priv, ustatus_addr + 0x04);
+       u32 e10 = nv_rd32(priv, ustatus_addr + 0x08);
+       u32 e14 = nv_rd32(priv, ustatus_addr + 0x0c);
+       u32 e18 = nv_rd32(priv, ustatus_addr + 0x10);
+       u32 e1c = nv_rd32(priv, ustatus_addr + 0x14);
+       u32 e20 = nv_rd32(priv, ustatus_addr + 0x18);
+       u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c);
+
+       /* CUDA memory: l[], g[] or stack. */
+       if (ustatus & 0x00000080) {
+               if (e18 & 0x80000000) {
+                       /* g[] read fault? */
+                       nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n",
+                                        tp, e14, e10 | ((e18 >> 24) & 0x1f));
+                       e18 &= ~0x1f000000;
+               } else if (e18 & 0xc) {
+                       /* g[] write fault? */
+                       nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n",
+                                tp, e14, e10 | ((e18 >> 7) & 0x1f));
+                       e18 &= ~0x00000f80;
+               } else {
+                       nv_error(priv, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n",
+                                tp, e14, e10);
+               }
+               ustatus &= ~0x00000080;
+       }
+       if (ustatus) {
+               nv_error(priv, "TRAP_PROP - TP %d -", tp);
+               nouveau_bitfield_print(nv50_graph_trap_prop, ustatus);
+               pr_cont(" - Address %02x%08x\n", e14, e10);
+       }
+       nv_error(priv, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
+                tp, e0c, e18, e1c, e20, e24);
+}
+
 static void
 nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
 {
@@ -420,8 +490,8 @@ nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)
                        oplow = nv_rd32(priv, addr + 0x70);
                        ophigh = nv_rd32(priv, addr + 0x74);
                        nv_error(priv, "TRAP_MP_EXEC - "
-                                       "TP %d MP %d: ", tpid, i);
-                       nouveau_enum_print(nv50_mp_exec_error_names, status);
+                                       "TP %d MP %d:", tpid, i);
+                       nouveau_bitfield_print(nv50_mp_exec_errors, status);
                        pr_cont(" at %06x warp %d, opcode %08x %08x\n",
                                        pc&0xffffff, pc >> 24,
                                        oplow, ophigh);
@@ -468,60 +538,19 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
                                nv50_priv_mp_trap(priv, i, display);
                                ustatus &= ~0x04030000;
                        }
-                       break;
-               case 8: /* TPDMA error */
-                       {
-                       u32 e0c = nv_rd32(priv, ustatus_addr + 4);
-                       u32 e10 = nv_rd32(priv, ustatus_addr + 8);
-                       u32 e14 = nv_rd32(priv, ustatus_addr + 0xc);
-                       u32 e18 = nv_rd32(priv, ustatus_addr + 0x10);
-                       u32 e1c = nv_rd32(priv, ustatus_addr + 0x14);
-                       u32 e20 = nv_rd32(priv, ustatus_addr + 0x18);
-                       u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c);
-                       /* 2d engine destination */
-                       if (ustatus & 0x00000010) {
-                               if (display) {
-                                       nv_error(priv, "TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
-                                                       i, e14, e10);
-                                       nv_error(priv, "TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-                                                       i, e0c, e18, e1c, e20, e24);
-                               }
-                               ustatus &= ~0x00000010;
-                       }
-                       /* Render target */
-                       if (ustatus & 0x00000040) {
-                               if (display) {
-                                       nv_error(priv, "TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
-                                                       i, e14, e10);
-                                       nv_error(priv, "TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-                                                       i, e0c, e18, e1c, e20, e24);
-                               }
-                               ustatus &= ~0x00000040;
-                       }
-                       /* CUDA memory: l[], g[] or stack. */
-                       if (ustatus & 0x00000080) {
-                               if (display) {
-                                       if (e18 & 0x80000000) {
-                                               /* g[] read fault? */
-                                               nv_error(priv, "TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
-                                                               i, e14, e10 | ((e18 >> 24) & 0x1f));
-                                               e18 &= ~0x1f000000;
-                                       } else if (e18 & 0xc) {
-                                               /* g[] write fault? */
-                                               nv_error(priv, "TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
-                                                               i, e14, e10 | ((e18 >> 7) & 0x1f));
-                                               e18 &= ~0x00000f80;
-                                       } else {
-                                               nv_error(priv, "TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
-                                                               i, e14, e10);
-                                       }
-                                       nv_error(priv, "TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
-                                                       i, e0c, e18, e1c, e20, e24);
-                               }
-                               ustatus &= ~0x00000080;
-                       }
+                       if (ustatus && display) {
+                               nv_error("%s - TP%d:", name, i);
+                               nouveau_bitfield_print(nv50_mpc_traps, ustatus);
+                               pr_cont("\n");
+                               ustatus = 0;
                        }
                        break;
+               case 8: /* PROP error */
+                       if (display)
+                               nv50_priv_prop_trap(
+                                               priv, ustatus_addr, ustatus, i);
+                       ustatus = 0;
+                       break;
                }
                if (ustatus) {
                        if (display)
@@ -727,11 +756,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,
                status &= ~0x080;
        }
 
-       /* TPDMA:  Handles TP-initiated uncached memory accesses:
+       /* PROP:  Handles TP-initiated uncached memory accesses:
         * l[], g[], stack, 2d surfaces, render targets. */
        if (status & 0x100) {
                nv50_priv_tp_trap(priv, 8, 0x408e08, 0x408708, display,
-                                   "TRAP_TPDMA");
+                                   "TRAP_PROP");
                nv_wr32(priv, 0x400108, 0x100);
                status &= ~0x100;
        }
@@ -760,7 +789,7 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
        u32 mthd = (addr & 0x00001ffc);
        u32 data = nv_rd32(priv, 0x400708);
        u32 class = nv_rd32(priv, 0x400814);
-       u32 show = stat;
+       u32 show = stat, show_bitfield = stat;
        int chid;
 
        engctx = nouveau_engctx_get(engine, inst);
@@ -778,21 +807,26 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
                nv_error(priv, "DATA_ERROR ");
                nouveau_enum_print(nv50_data_error_names, ecode);
                pr_cont("\n");
+               show_bitfield &= ~0x00100000;
        }
 
        if (stat & 0x00200000) {
                if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12,
                                engctx))
                        show &= ~0x00200000;
+               show_bitfield &= ~0x00200000;
        }
 
        nv_wr32(priv, 0x400100, stat);
        nv_wr32(priv, 0x400500, 0x00010001);
 
        if (show) {
-               nv_error(priv, "%s", "");
-               nouveau_bitfield_print(nv50_graph_intr_name, show);
-               pr_cont("\n");
+               show &= show_bitfield;
+               if (show) {
+                       nv_error(priv, "%s", "");
+                       nouveau_bitfield_print(nv50_graph_intr_name, show);
+                       pr_cont("\n");
+               }
                nv_error(priv,
                         "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
                         chid, (u64)inst << 12, nouveau_client_name(engctx),
index 434bb4b0fa2e650a130a98cc940f5ca7727cfeac..a73ab209ea88c85121fe3580e9daa189b29de46e 100644 (file)
@@ -334,7 +334,7 @@ nvc0_graph_mthd(struct nvc0_graph_priv *priv, struct nvc0_graph_mthd *mthds)
        while ((mthd = &mthds[i++]) && (init = mthd->init)) {
                u32  addr = 0x80000000 | mthd->oclass;
                for (data = 0; init->count; init++) {
-                       if (data != init->data) {
+                       if (init == mthd->init || data != init->data) {
                                nv_wr32(priv, 0x40448c, init->data);
                                data = init->data;
                        }
@@ -901,6 +901,9 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
                }
 
                return 0;
+       } else
+       if (!oclass->fecs.ucode) {
+               return -ENOSYS;
        }
 
        /* load HUB microcode */
index ea17a80ad7fce3d7bcee48013ac6ba8c65acc4c7..b0ab6de270b2ea9d148b483b8249bc11efa27496 100644 (file)
@@ -205,6 +205,11 @@ extern struct nvc0_graph_init nve4_graph_init_regs[];
 extern struct nvc0_graph_init nve4_graph_init_unk[];
 extern struct nvc0_graph_init nve4_graph_init_unk88xx[];
 
+extern struct nvc0_graph_init nvf0_graph_init_unk40xx[];
+extern struct nvc0_graph_init nvf0_graph_init_unk70xx[];
+extern struct nvc0_graph_init nvf0_graph_init_unk5bxx[];
+extern struct nvc0_graph_init nvf0_graph_init_tpc[];
+
 int  nvc0_grctx_generate(struct nvc0_graph_priv *);
 void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
 void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
@@ -266,6 +271,11 @@ extern struct nvc0_graph_init nve4_grctx_init_unk80xx[];
 extern struct nvc0_graph_init nve4_grctx_init_unk90xx[];
 
 extern struct nouveau_oclass *nvf0_grctx_oclass;
+extern struct nvc0_graph_init nvf0_grctx_init_unk44xx[];
+extern struct nvc0_graph_init nvf0_grctx_init_unk5bxx[];
+extern struct nvc0_graph_init nvf0_grctx_init_unk60xx[];
+
+extern struct nouveau_oclass *nv108_grctx_oclass;
 
 #define mmio_data(s,a,p) do {                                                  \
        info->buffer[info->buffer_nr] = round_up(info->addr, (a));             \
index 2f0ac78322345a0d5dd997f5dc3d83327ba4b809..b1acb9939d95cfe460cea8e9aa2475d85256c20f 100644 (file)
@@ -41,7 +41,7 @@ nvf0_graph_sclass[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk40xx[] = {
        { 0x40415c,   1, 0x04, 0x00000000 },
        { 0x404170,   1, 0x04, 0x00000000 },
@@ -60,7 +60,7 @@ nvf0_graph_init_unk58xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk70xx[] = {
        { 0x407010,   1, 0x04, 0x00000000 },
        { 0x407040,   1, 0x04, 0x80440424 },
@@ -68,7 +68,7 @@ nvf0_graph_init_unk70xx[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_unk5bxx[] = {
        { 0x405b44,   1, 0x04, 0x00000000 },
        { 0x405b50,   1, 0x04, 0x00000000 },
@@ -114,7 +114,7 @@ nvf0_graph_init_gpc[] = {
        {}
 };
 
-static struct nvc0_graph_init
+struct nvc0_graph_init
 nvf0_graph_init_tpc[] = {
        { 0x419d0c,   1, 0x04, 0x00000000 },
        { 0x419d10,   1, 0x04, 0x00000014 },
@@ -243,6 +243,6 @@ nvf0_graph_oclass = &(struct nvc0_graph_oclass) {
        .cclass = &nvf0_grctx_oclass,
        .sclass =  nvf0_graph_sclass,
        .mmio = nvf0_graph_init_mmio,
-       .fecs.ucode = 0 ? &nvf0_graph_fecs_ucode : NULL,
+       .fecs.ucode = &nvf0_graph_fecs_ucode,
        .gpccs.ucode = &nvf0_graph_gpccs_ucode,
 }.base;
index ac2881d1776ac1a071371a84f379ea57ea8ee856..7b8ea221b00dc7bf0d88021fc5443ae059401cbb 100644 (file)
@@ -38,7 +38,8 @@ enum nv_subdev_type {
        NVDEV_SUBDEV_THERM,
        NVDEV_SUBDEV_CLOCK,
 
-       NVDEV_ENGINE_DMAOBJ,
+       NVDEV_ENGINE_FIRST,
+       NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST,
        NVDEV_ENGINE_FIFO,
        NVDEV_ENGINE_SW,
        NVDEV_ENGINE_GR,
@@ -70,6 +71,7 @@ struct nouveau_device {
        const char *dbgopt;
        const char *name;
        const char *cname;
+       u64 disable_mask;
 
        enum {
                NV_04    = 0x04,
index 8c32cf4d83c78bb39773cd11233e59941da52699..26b6b2bb11121e28d4de88f08d4f308ab02fed7a 100644 (file)
@@ -109,6 +109,7 @@ extern struct nouveau_oclass *nv50_fifo_oclass;
 extern struct nouveau_oclass *nv84_fifo_oclass;
 extern struct nouveau_oclass *nvc0_fifo_oclass;
 extern struct nouveau_oclass *nve0_fifo_oclass;
+extern struct nouveau_oclass *nv108_fifo_oclass;
 
 void nv04_fifo_intr(struct nouveau_subdev *);
 int  nv04_fifo_context_attach(struct nouveau_object *, struct nouveau_object *);
index 8e1b52312ddc5cb2675696223ea8344548452ef1..97705618de979e9fe1f810ca3ee5f557d5dd19e2 100644 (file)
@@ -69,6 +69,7 @@ extern struct nouveau_oclass *nvd7_graph_oclass;
 extern struct nouveau_oclass *nvd9_graph_oclass;
 extern struct nouveau_oclass *nve4_graph_oclass;
 extern struct nouveau_oclass *nvf0_graph_oclass;
+extern struct nouveau_oclass *nv108_graph_oclass;
 
 extern const struct nouveau_bitfield nv04_graph_nsource[];
 extern struct nouveau_ofuncs nv04_graph_ofuncs;
index 4f4ff4502c3d2f284e2e6424abe05a923fbc6ff7..9faa98e67ad8c9057273eff0a7fc0f145799abf8 100644 (file)
@@ -4,8 +4,7 @@
 #include <core/subdev.h>
 #include <core/device.h>
 
-#include <subdev/fb.h>
-
+struct nouveau_mem;
 struct nouveau_vma;
 
 struct nouveau_bar {
@@ -29,27 +28,7 @@ nouveau_bar(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BAR];
 }
 
-#define nouveau_bar_create(p,e,o,d)                                            \
-       nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_bar_init(p)                                                    \
-       nouveau_subdev_init(&(p)->base)
-#define nouveau_bar_fini(p,s)                                                  \
-       nouveau_subdev_fini(&(p)->base, (s))
-
-int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *,
-                       struct nouveau_oclass *, int, void **);
-void nouveau_bar_destroy(struct nouveau_bar *);
-
-void _nouveau_bar_dtor(struct nouveau_object *);
-#define _nouveau_bar_init _nouveau_subdev_init
-#define _nouveau_bar_fini _nouveau_subdev_fini
-
 extern struct nouveau_oclass nv50_bar_oclass;
 extern struct nouveau_oclass nvc0_bar_oclass;
 
-int nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *,
-                     struct nouveau_mem *, struct nouveau_object **);
-
-void nv84_bar_flush(struct nouveau_bar *);
-
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h
new file mode 100644 (file)
index 0000000..c5e6d1e
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __NVBIOS_RAMCFG_H__
+#define __NVBIOS_RAMCFG_H__
+
+struct nouveau_bios;
+
+struct nvbios_ramcfg {
+       unsigned rammap_11_08_01:1;
+       unsigned rammap_11_08_0c:2;
+       unsigned rammap_11_08_10:1;
+       unsigned rammap_11_11_0c:2;
+
+       unsigned ramcfg_11_01_01:1;
+       unsigned ramcfg_11_01_02:1;
+       unsigned ramcfg_11_01_04:1;
+       unsigned ramcfg_11_01_08:1;
+       unsigned ramcfg_11_01_10:1;
+       unsigned ramcfg_11_01_20:1;
+       unsigned ramcfg_11_01_40:1;
+       unsigned ramcfg_11_01_80:1;
+       unsigned ramcfg_11_02_03:2;
+       unsigned ramcfg_11_02_04:1;
+       unsigned ramcfg_11_02_08:1;
+       unsigned ramcfg_11_02_10:1;
+       unsigned ramcfg_11_02_40:1;
+       unsigned ramcfg_11_02_80:1;
+       unsigned ramcfg_11_03_0f:4;
+       unsigned ramcfg_11_03_30:2;
+       unsigned ramcfg_11_03_c0:2;
+       unsigned ramcfg_11_03_f0:4;
+       unsigned ramcfg_11_04:8;
+       unsigned ramcfg_11_06:8;
+       unsigned ramcfg_11_07_02:1;
+       unsigned ramcfg_11_07_04:1;
+       unsigned ramcfg_11_07_08:1;
+       unsigned ramcfg_11_07_10:1;
+       unsigned ramcfg_11_07_40:1;
+       unsigned ramcfg_11_07_80:1;
+       unsigned ramcfg_11_08_01:1;
+       unsigned ramcfg_11_08_02:1;
+       unsigned ramcfg_11_08_04:1;
+       unsigned ramcfg_11_08_08:1;
+       unsigned ramcfg_11_08_10:1;
+       unsigned ramcfg_11_08_20:1;
+       unsigned ramcfg_11_09:8;
+
+       unsigned timing[11];
+       unsigned timing_20_2e_03:2;
+       unsigned timing_20_2e_30:2;
+       unsigned timing_20_2e_c0:2;
+       unsigned timing_20_2f_03:2;
+       unsigned timing_20_2c_003f:6;
+       unsigned timing_20_2c_1fc0:7;
+       unsigned timing_20_30_f8:5;
+       unsigned timing_20_30_07:3;
+       unsigned timing_20_31_0007:3;
+       unsigned timing_20_31_0078:4;
+       unsigned timing_20_31_0780:4;
+       unsigned timing_20_31_0800:1;
+       unsigned timing_20_31_7000:3;
+       unsigned timing_20_31_8000:1;
+};
+
+u8 nvbios_ramcfg_count(struct nouveau_bios *);
+u8 nvbios_ramcfg_index(struct nouveau_bios *);
+
+#endif
index bc15e03208773cea8a16ce3a62a84e4cea702ec3..5bdf8e4db40a137df8b00f4a0183424929ad828c 100644 (file)
@@ -1,11 +1,25 @@
 #ifndef __NVBIOS_RAMMAP_H__
 #define __NVBIOS_RAMMAP_H__
 
-u16 nvbios_rammap_table(struct nouveau_bios *, u8 *ver, u8 *hdr,
-                       u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
-u16 nvbios_rammap_entry(struct nouveau_bios *, int idx,
-                       u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_rammap_match(struct nouveau_bios *, u16 khz,
-                       u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+struct nvbios_ramcfg;
+
+u32 nvbios_rammapTe(struct nouveau_bios *, u8 *ver, u8 *hdr,
+                   u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
+
+u32 nvbios_rammapEe(struct nouveau_bios *, int idx,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_rammapEm(struct nouveau_bios *, u16 mhz,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_rammapEp(struct nouveau_bios *, u16 mhz,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+                   struct nvbios_ramcfg *);
+
+u32 nvbios_rammapSe(struct nouveau_bios *, u32 data,
+                   u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+                   u8 *ver, u8 *hdr);
+u32 nvbios_rammapSp(struct nouveau_bios *, u32 data,
+                   u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+                   u8 *ver, u8 *hdr,
+                   struct nvbios_ramcfg *);
 
 #endif
index 963694b5422492ea17526f88ef14ce5e30b70554..76d914b67ab5cc9c0a435d5fc77654cbbfb884e3 100644 (file)
@@ -1,8 +1,14 @@
 #ifndef __NVBIOS_TIMING_H__
 #define __NVBIOS_TIMING_H__
 
-u16 nvbios_timing_table(struct nouveau_bios *,
-                       u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_timing_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr);
+struct nvbios_ramcfg;
+
+u16 nvbios_timingTe(struct nouveau_bios *,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
+u16 nvbios_timingEe(struct nouveau_bios *, int idx,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u16 nvbios_timingEp(struct nouveau_bios *, int idx,
+                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+                   struct nvbios_ramcfg *);
 
 #endif
index 685c9b12ee4cff48a682f373b7dbd94d5ea0bb24..ed1ac68c38b354a58211c386e1c9bc450b8501ab 100644 (file)
@@ -9,7 +9,6 @@ struct nouveau_devinit {
        bool post;
        void (*meminit)(struct nouveau_devinit *);
        int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
-
 };
 
 static inline struct nouveau_devinit *
@@ -18,32 +17,16 @@ nouveau_devinit(void *obj)
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_DEVINIT];
 }
 
-#define nouveau_devinit_create(p,e,o,d)                                        \
-       nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_devinit_destroy(p)                                             \
-       nouveau_subdev_destroy(&(p)->base)
-#define nouveau_devinit_init(p) ({                                             \
-       struct nouveau_devinit *d = (p);                                       \
-       _nouveau_devinit_init(nv_object(d));                                   \
-})
-#define nouveau_devinit_fini(p,s) ({                                           \
-       struct nouveau_devinit *d = (p);                                       \
-       _nouveau_devinit_fini(nv_object(d), (s));                              \
-})
-
-int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *,
-                           struct nouveau_oclass *, int, void **);
-#define _nouveau_devinit_dtor _nouveau_subdev_dtor
-int _nouveau_devinit_init(struct nouveau_object *);
-int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);
-
-extern struct nouveau_oclass nv04_devinit_oclass;
-extern struct nouveau_oclass nv05_devinit_oclass;
-extern struct nouveau_oclass nv10_devinit_oclass;
-extern struct nouveau_oclass nv1a_devinit_oclass;
-extern struct nouveau_oclass nv20_devinit_oclass;
-extern struct nouveau_oclass nv50_devinit_oclass;
-extern struct nouveau_oclass nva3_devinit_oclass;
-extern struct nouveau_oclass nvc0_devinit_oclass;
+extern struct nouveau_oclass *nv04_devinit_oclass;
+extern struct nouveau_oclass *nv05_devinit_oclass;
+extern struct nouveau_oclass *nv10_devinit_oclass;
+extern struct nouveau_oclass *nv1a_devinit_oclass;
+extern struct nouveau_oclass *nv20_devinit_oclass;
+extern struct nouveau_oclass *nv50_devinit_oclass;
+extern struct nouveau_oclass *nv84_devinit_oclass;
+extern struct nouveau_oclass *nv98_devinit_oclass;
+extern struct nouveau_oclass *nva3_devinit_oclass;
+extern struct nouveau_oclass *nvaf_devinit_oclass;
+extern struct nouveau_oclass *nvc0_devinit_oclass;
 
 #endif
index 8541aa382ff224136d8c1cedff00db0595a753c2..d7ecafbae1ca1c1b0a43192673fbf5ae582ffa60 100644 (file)
@@ -75,6 +75,11 @@ struct nouveau_fb {
 static inline struct nouveau_fb *
 nouveau_fb(void *obj)
 {
+       /* fbram uses this before device subdev pointer is valid */
+       if (nv_iclass(obj, NV_SUBDEV_CLASS) &&
+           nv_subidx(obj) == NVDEV_SUBDEV_FB)
+               return obj;
+
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB];
 }
 
@@ -101,6 +106,13 @@ extern struct nouveau_oclass *nvaf_fb_oclass;
 extern struct nouveau_oclass *nvc0_fb_oclass;
 extern struct nouveau_oclass *nve0_fb_oclass;
 
+#include <subdev/bios/ramcfg.h>
+
+struct nouveau_ram_data {
+       struct nvbios_ramcfg bios;
+       u32 freq;
+};
+
 struct nouveau_ram {
        struct nouveau_object base;
        enum {
@@ -137,6 +149,12 @@ struct nouveau_ram {
        } rammap, ramcfg, timing;
        u32 freq;
        u32 mr[16];
+       u32 mr1_nuts;
+
+       struct nouveau_ram_data *next;
+       struct nouveau_ram_data former;
+       struct nouveau_ram_data xition;
+       struct nouveau_ram_data target;
 };
 
 #endif
index 9fa5da72387192467ba80c9f9f9a7f2a0adbe339..7f50a858b16f68395a3fe0b84c5bd9f275e8849f 100644 (file)
@@ -73,7 +73,7 @@ struct nouveau_i2c {
        int (*identify)(struct nouveau_i2c *, int index,
                        const char *what, struct nouveau_i2c_board_info *,
                        bool (*match)(struct nouveau_i2c_port *,
-                                     struct i2c_board_info *));
+                                     struct i2c_board_info *, void *), void *);
        struct list_head ports;
 };
 
index ec7a54e91a087cdea900dd1f94947adc0f6f395c..c1df26f3230c17f8fe6ff2a270b95cbafb441c6f 100644 (file)
@@ -23,21 +23,6 @@ nv_memobj(void *obj)
        return obj;
 }
 
-#define nouveau_instobj_create(p,e,o,d)                                        \
-       nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_instobj_init(p)                                                \
-       nouveau_object_init(&(p)->base)
-#define nouveau_instobj_fini(p,s)                                              \
-       nouveau_object_fini(&(p)->base, (s))
-
-int  nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *,
-                            struct nouveau_oclass *, int, void **);
-void nouveau_instobj_destroy(struct nouveau_instobj *);
-
-void _nouveau_instobj_dtor(struct nouveau_object *);
-#define _nouveau_instobj_init nouveau_object_init
-#define _nouveau_instobj_fini nouveau_object_fini
-
 struct nouveau_instmem {
        struct nouveau_subdev base;
        struct list_head list;
@@ -50,24 +35,18 @@ struct nouveau_instmem {
 static inline struct nouveau_instmem *
 nouveau_instmem(void *obj)
 {
+       /* nv04/nv40 impls need to create objects in their constructor,
+        * which is before the subdev pointer is valid
+        */
+       if (nv_iclass(obj, NV_SUBDEV_CLASS) &&
+           nv_subidx(obj) == NVDEV_SUBDEV_INSTMEM)
+               return obj;
+
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM];
 }
 
-#define nouveau_instmem_create(p,e,o,d)                                        \
-       nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d)
-#define nouveau_instmem_destroy(p)                                             \
-       nouveau_subdev_destroy(&(p)->base)
-int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *,
-                           struct nouveau_oclass *, int, void **);
-int nouveau_instmem_init(struct nouveau_instmem *);
-int nouveau_instmem_fini(struct nouveau_instmem *, bool);
-
-#define _nouveau_instmem_dtor _nouveau_subdev_dtor
-int _nouveau_instmem_init(struct nouveau_object *);
-int _nouveau_instmem_fini(struct nouveau_object *, bool);
-
-extern struct nouveau_oclass nv04_instmem_oclass;
-extern struct nouveau_oclass nv40_instmem_oclass;
-extern struct nouveau_oclass nv50_instmem_oclass;
+extern struct nouveau_oclass *nv04_instmem_oclass;
+extern struct nouveau_oclass *nv40_instmem_oclass;
+extern struct nouveau_oclass *nv50_instmem_oclass;
 
 #endif
index fcf57fa309bfd54bbcbba86bdfc53ef5fcc481f6..c9509039f94b4b57bff45b718651bbdfd663012c 100644 (file)
@@ -131,9 +131,5 @@ void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *);
 void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *);
 void nouveau_vm_unmap(struct nouveau_vma *);
 void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length);
-void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
-                      struct nouveau_mem *);
-void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
-                    struct nouveau_mem *mem);
 
 #endif
index d70ba342aa2e8f46c5de87c406b223d39ed98194..7098ddd546788c3adca970af4afc1a5a8d122d1a 100644 (file)
  */
 
 #include <core/object.h>
-#include <subdev/bar.h>
+
+#include <subdev/fb.h>
+#include <subdev/vm.h>
+
+#include "priv.h"
 
 struct nouveau_barobj {
        struct nouveau_object base;
index 160d27f3c7b4732fc67a069a415681295a0d8dd4..090d594a21b36ee9633462db5f0ee838547b1557 100644 (file)
 #include <core/gpuobj.h>
 
 #include <subdev/timer.h>
-#include <subdev/bar.h>
 #include <subdev/fb.h>
 #include <subdev/vm.h>
 
+#include "priv.h"
+
 struct nv50_bar_priv {
        struct nouveau_bar base;
        spinlock_t lock;
index b2ec7411eb2eb7cb43e5434016cad756159c69d6..bac5e754de35acdf838b571bf1d6e25eb8b5faec 100644 (file)
 #include <core/gpuobj.h>
 
 #include <subdev/timer.h>
-#include <subdev/bar.h>
 #include <subdev/fb.h>
 #include <subdev/vm.h>
 
+#include "priv.h"
+
 struct nvc0_bar_priv {
        struct nouveau_bar base;
        spinlock_t lock;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h
new file mode 100644 (file)
index 0000000..ffad8f3
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __NVKM_BAR_PRIV_H__
+#define __NVKM_BAR_PRIV_H__
+
+#include <subdev/bar.h>
+
+#define nouveau_bar_create(p,e,o,d)                                            \
+       nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_bar_init(p)                                                    \
+       nouveau_subdev_init(&(p)->base)
+#define nouveau_bar_fini(p,s)                                                  \
+       nouveau_subdev_fini(&(p)->base, (s))
+
+int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *,
+                       struct nouveau_oclass *, int, void **);
+void nouveau_bar_destroy(struct nouveau_bar *);
+
+void _nouveau_bar_dtor(struct nouveau_object *);
+#define _nouveau_bar_init _nouveau_subdev_init
+#define _nouveau_bar_fini _nouveau_subdev_fini
+
+int  nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *,
+                      struct nouveau_mem *, struct nouveau_object **);
+
+void nv84_bar_flush(struct nouveau_bar *);
+
+#endif
index 420908cb82b613bbc97fbccb9b123f3449926100..de201baeb053aea79a6632289a865de94fc5dc07 100644 (file)
@@ -9,6 +9,7 @@
 #include <subdev/bios/dp.h>
 #include <subdev/bios/gpio.h>
 #include <subdev/bios/init.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/devinit.h>
 #include <subdev/i2c.h>
 #include <subdev/vga.h>
@@ -365,13 +366,13 @@ static u16
 init_script(struct nouveau_bios *bios, int index)
 {
        struct nvbios_init init = { .bios = bios };
-       u16 data;
+       u16 bmp_ver = bmp_version(bios), data;
 
-       if (bmp_version(bios) && bmp_version(bios) < 0x0510) {
-               if (index > 1)
+       if (bmp_ver && bmp_ver < 0x0510) {
+               if (index > 1 || bmp_ver < 0x0100)
                        return 0x0000;
 
-               data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18);
+               data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18);
                return nv_ro16(bios, data + (index * 2));
        }
 
@@ -391,43 +392,14 @@ init_unknown_script(struct nouveau_bios *bios)
        return 0x0000;
 }
 
-static u16
-init_ram_restrict_table(struct nvbios_init *init)
-{
-       struct nouveau_bios *bios = init->bios;
-       struct bit_entry bit_M;
-       u16 data = 0x0000;
-
-       if (!bit_entry(bios, 'M', &bit_M)) {
-               if (bit_M.version == 1 && bit_M.length >= 5)
-                       data = nv_ro16(bios, bit_M.offset + 3);
-               if (bit_M.version == 2 && bit_M.length >= 3)
-                       data = nv_ro16(bios, bit_M.offset + 1);
-       }
-
-       if (data == 0x0000)
-               warn("ram restrict table not found\n");
-       return data;
-}
-
 static u8
 init_ram_restrict_group_count(struct nvbios_init *init)
 {
-       struct nouveau_bios *bios = init->bios;
-       struct bit_entry bit_M;
-
-       if (!bit_entry(bios, 'M', &bit_M)) {
-               if (bit_M.version == 1 && bit_M.length >= 5)
-                       return nv_ro08(bios, bit_M.offset + 2);
-               if (bit_M.version == 2 && bit_M.length >= 3)
-                       return nv_ro08(bios, bit_M.offset + 0);
-       }
-
-       return 0x00;
+       return nvbios_ramcfg_count(init->bios);
 }
 
 static u8
-init_ram_restrict_strap(struct nvbios_init *init)
+init_ram_restrict(struct nvbios_init *init)
 {
        /* This appears to be the behaviour of the VBIOS parser, and *is*
         * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to
@@ -438,18 +410,8 @@ init_ram_restrict_strap(struct nvbios_init *init)
         * in case *not* re-reading the strap causes similar breakage.
         */
        if (!init->ramcfg || init->bios->version.major < 0x70)
-               init->ramcfg = init_rd32(init, 0x101000);
-       return (init->ramcfg & 0x00000003c) >> 2;
-}
-
-static u8
-init_ram_restrict(struct nvbios_init *init)
-{
-       u8  strap = init_ram_restrict_strap(init);
-       u16 table = init_ram_restrict_table(init);
-       if (table)
-               return nv_ro08(init->bios, table + strap);
-       return 0x00;
+               init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->bios);
+       return (init->ramcfg & 0x7fffffff);
 }
 
 static u8
@@ -1294,7 +1256,11 @@ init_jump(struct nvbios_init *init)
        u16 offset = nv_ro16(bios, init->offset + 1);
 
        trace("JUMP\t0x%04x\n", offset);
-       init->offset = offset;
+
+       if (init_exec(init))
+               init->offset = offset;
+       else
+               init->offset += 3;
 }
 
 /**
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c
new file mode 100644 (file)
index 0000000..991aedd
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
+
+static u8
+nvbios_ramcfg_strap(struct nouveau_bios *bios)
+{
+       return (nv_rd32(bios, 0x101000) & 0x0000003c) >> 2;
+}
+
+u8
+nvbios_ramcfg_count(struct nouveau_bios *bios)
+{
+       struct bit_entry bit_M;
+
+       if (!bit_entry(bios, 'M', &bit_M)) {
+               if (bit_M.version == 1 && bit_M.length >= 5)
+                       return nv_ro08(bios, bit_M.offset + 2);
+               if (bit_M.version == 2 && bit_M.length >= 3)
+                       return nv_ro08(bios, bit_M.offset + 0);
+       }
+
+       return 0x00;
+}
+
+u8
+nvbios_ramcfg_index(struct nouveau_bios *bios)
+{
+       u8 strap = nvbios_ramcfg_strap(bios);
+       u32 xlat = 0x00000000;
+       struct bit_entry bit_M;
+
+       if (!bit_entry(bios, 'M', &bit_M)) {
+               if (bit_M.version == 1 && bit_M.length >= 5)
+                       xlat = nv_ro16(bios, bit_M.offset + 3);
+               if (bit_M.version == 2 && bit_M.length >= 3)
+                       xlat = nv_ro16(bios, bit_M.offset + 1);
+       }
+
+       if (xlat)
+               strap = nv_ro08(bios, xlat + strap);
+       return strap;
+}
index 916fa9d302b7f2fd108617844db25ddb565e4b5d..1811b2cb047276ead557d6d1025568667a1fbc24 100644 (file)
 
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/bios/rammap.h>
 
-u16
-nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
-                   u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
+u32
+nvbios_rammapTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
+               u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
        struct bit_entry bit_P;
        u16 rammap = 0x0000;
@@ -57,12 +58,12 @@ nvbios_rammap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr,
        return 0x0000;
 }
 
-u16
-nvbios_rammap_entry(struct nouveau_bios *bios, int idx,
-                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+u32
+nvbios_rammapEe(struct nouveau_bios *bios, int idx,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
        u8  snr, ssz;
-       u16 rammap = nvbios_rammap_table(bios, ver, hdr, cnt, len, &snr, &ssz);
+       u16 rammap = nvbios_rammapTe(bios, ver, hdr, cnt, len, &snr, &ssz);
        if (rammap && idx < *cnt) {
                rammap = rammap + *hdr + (idx * (*len + (snr * ssz)));
                *hdr = *len;
@@ -73,16 +74,100 @@ nvbios_rammap_entry(struct nouveau_bios *bios, int idx,
        return 0x0000;
 }
 
-u16
-nvbios_rammap_match(struct nouveau_bios *bios, u16 khz,
-                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+u32
+nvbios_rammapEm(struct nouveau_bios *bios, u16 khz,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
        int idx = 0;
        u32 data;
-       while ((data = nvbios_rammap_entry(bios, idx++, ver, hdr, cnt, len))) {
+       while ((data = nvbios_rammapEe(bios, idx++, ver, hdr, cnt, len))) {
                if (khz >= nv_ro16(bios, data + 0x00) &&
                    khz <= nv_ro16(bios, data + 0x02))
                        break;
        }
        return data;
 }
+
+u32
+nvbios_rammapEp(struct nouveau_bios *bios, u16 khz,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+               struct nvbios_ramcfg *p)
+{
+       u32 data = nvbios_rammapEm(bios, khz, ver, hdr, cnt, len);
+       memset(p, 0x00, sizeof(*p));
+       switch (!!data * *ver) {
+       case 0x11:
+               p->rammap_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0;
+               p->rammap_11_08_0c = (nv_ro08(bios, data + 0x08) & 0x0c) >> 2;
+               p->rammap_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4;
+               p->rammap_11_11_0c = (nv_ro08(bios, data + 0x11) & 0x0c) >> 2;
+               break;
+       default:
+               data = 0;
+               break;
+       }
+       return data;
+}
+
+u32
+nvbios_rammapSe(struct nouveau_bios *bios, u32 data,
+               u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+               u8 *ver, u8 *hdr)
+{
+       if (idx < ecnt) {
+               data = data + ehdr + (idx * elen);
+               *ver = ever;
+               *hdr = elen;
+               return data;
+       }
+       return 0;
+}
+
+u32
+nvbios_rammapSp(struct nouveau_bios *bios, u32 data,
+               u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx,
+               u8 *ver, u8 *hdr, struct nvbios_ramcfg *p)
+{
+       data = nvbios_rammapSe(bios, data, ever, ehdr, ecnt, elen, idx, ver, hdr);
+       switch (!!data * *ver) {
+       case 0x11:
+               p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0;
+               p->ramcfg_11_01_02 = (nv_ro08(bios, data + 0x01) & 0x02) >> 1;
+               p->ramcfg_11_01_04 = (nv_ro08(bios, data + 0x01) & 0x04) >> 2;
+               p->ramcfg_11_01_08 = (nv_ro08(bios, data + 0x01) & 0x08) >> 3;
+               p->ramcfg_11_01_10 = (nv_ro08(bios, data + 0x01) & 0x10) >> 4;
+               p->ramcfg_11_01_20 = (nv_ro08(bios, data + 0x01) & 0x20) >> 5;
+               p->ramcfg_11_01_40 = (nv_ro08(bios, data + 0x01) & 0x40) >> 6;
+               p->ramcfg_11_01_80 = (nv_ro08(bios, data + 0x01) & 0x80) >> 7;
+               p->ramcfg_11_02_03 = (nv_ro08(bios, data + 0x02) & 0x03) >> 0;
+               p->ramcfg_11_02_04 = (nv_ro08(bios, data + 0x02) & 0x04) >> 2;
+               p->ramcfg_11_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3;
+               p->ramcfg_11_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4;
+               p->ramcfg_11_02_40 = (nv_ro08(bios, data + 0x02) & 0x40) >> 6;
+               p->ramcfg_11_02_80 = (nv_ro08(bios, data + 0x02) & 0x80) >> 7;
+               p->ramcfg_11_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0;
+               p->ramcfg_11_03_30 = (nv_ro08(bios, data + 0x03) & 0x30) >> 4;
+               p->ramcfg_11_03_c0 = (nv_ro08(bios, data + 0x03) & 0xc0) >> 6;
+               p->ramcfg_11_03_f0 = (nv_ro08(bios, data + 0x03) & 0xf0) >> 4;
+               p->ramcfg_11_04    = (nv_ro08(bios, data + 0x04) & 0xff) >> 0;
+               p->ramcfg_11_06    = (nv_ro08(bios, data + 0x06) & 0xff) >> 0;
+               p->ramcfg_11_07_02 = (nv_ro08(bios, data + 0x07) & 0x02) >> 1;
+               p->ramcfg_11_07_04 = (nv_ro08(bios, data + 0x07) & 0x04) >> 2;
+               p->ramcfg_11_07_08 = (nv_ro08(bios, data + 0x07) & 0x08) >> 3;
+               p->ramcfg_11_07_10 = (nv_ro08(bios, data + 0x07) & 0x10) >> 4;
+               p->ramcfg_11_07_40 = (nv_ro08(bios, data + 0x07) & 0x40) >> 6;
+               p->ramcfg_11_07_80 = (nv_ro08(bios, data + 0x07) & 0x80) >> 7;
+               p->ramcfg_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0;
+               p->ramcfg_11_08_02 = (nv_ro08(bios, data + 0x08) & 0x02) >> 1;
+               p->ramcfg_11_08_04 = (nv_ro08(bios, data + 0x08) & 0x04) >> 2;
+               p->ramcfg_11_08_08 = (nv_ro08(bios, data + 0x08) & 0x08) >> 3;
+               p->ramcfg_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4;
+               p->ramcfg_11_08_20 = (nv_ro08(bios, data + 0x08) & 0x20) >> 5;
+               p->ramcfg_11_09    = (nv_ro08(bios, data + 0x09) & 0xff) >> 0;
+               break;
+       default:
+               data = 0;
+               break;
+       }
+       return data;
+}
index 151c2d6aaee872f1398fcca6aab7ae7b48a928d7..350d44ab2ba24b9e56a9dbf178a86497159cc326 100644 (file)
 
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
+#include <subdev/bios/ramcfg.h>
 #include <subdev/bios/timing.h>
 
 u16
-nvbios_timing_table(struct nouveau_bios *bios,
-                   u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
+nvbios_timingTe(struct nouveau_bios *bios,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
        struct bit_entry bit_P;
        u16 timing = 0x0000;
@@ -47,11 +48,15 @@ nvbios_timing_table(struct nouveau_bios *bios,
                                *hdr = nv_ro08(bios, timing + 1);
                                *cnt = nv_ro08(bios, timing + 2);
                                *len = nv_ro08(bios, timing + 3);
+                               *snr = 0;
+                               *ssz = 0;
                                return timing;
                        case 0x20:
                                *hdr = nv_ro08(bios, timing + 1);
-                               *cnt = nv_ro08(bios, timing + 3);
+                               *cnt = nv_ro08(bios, timing + 5);
                                *len = nv_ro08(bios, timing + 2);
+                               *snr = nv_ro08(bios, timing + 4);
+                               *ssz = nv_ro08(bios, timing + 3);
                                return timing;
                        default:
                                break;
@@ -63,11 +68,60 @@ nvbios_timing_table(struct nouveau_bios *bios,
 }
 
 u16
-nvbios_timing_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len)
+nvbios_timingEe(struct nouveau_bios *bios, int idx,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
-       u8  hdr, cnt;
-       u16 timing = nvbios_timing_table(bios, ver, &hdr, &cnt, len);
-       if (timing && idx < cnt)
-               return timing + hdr + (idx * *len);
+       u8  snr, ssz;
+       u16 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz);
+       if (timing && idx < *cnt) {
+               timing += *hdr + idx * (*len + (snr * ssz));
+               *hdr = *len;
+               *cnt = snr;
+               *len = ssz;
+               return timing;
+       }
        return 0x0000;
 }
+
+u16
+nvbios_timingEp(struct nouveau_bios *bios, int idx,
+               u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+               struct nvbios_ramcfg *p)
+{
+       u16 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp;
+       switch (!!data * *ver) {
+       case 0x20:
+               p->timing[0] = nv_ro32(bios, data + 0x00);
+               p->timing[1] = nv_ro32(bios, data + 0x04);
+               p->timing[2] = nv_ro32(bios, data + 0x08);
+               p->timing[3] = nv_ro32(bios, data + 0x0c);
+               p->timing[4] = nv_ro32(bios, data + 0x10);
+               p->timing[5] = nv_ro32(bios, data + 0x14);
+               p->timing[6] = nv_ro32(bios, data + 0x18);
+               p->timing[7] = nv_ro32(bios, data + 0x1c);
+               p->timing[8] = nv_ro32(bios, data + 0x20);
+               p->timing[9] = nv_ro32(bios, data + 0x24);
+               p->timing[10] = nv_ro32(bios, data + 0x28);
+               p->timing_20_2e_03 = (nv_ro08(bios, data + 0x2e) & 0x03) >> 0;
+               p->timing_20_2e_30 = (nv_ro08(bios, data + 0x2e) & 0x30) >> 4;
+               p->timing_20_2e_c0 = (nv_ro08(bios, data + 0x2e) & 0xc0) >> 6;
+               p->timing_20_2f_03 = (nv_ro08(bios, data + 0x2f) & 0x03) >> 0;
+               temp = nv_ro16(bios, data + 0x2c);
+               p->timing_20_2c_003f = (temp & 0x003f) >> 0;
+               p->timing_20_2c_1fc0 = (temp & 0x1fc0) >> 6;
+               p->timing_20_30_07 = (nv_ro08(bios, data + 0x30) & 0x07) >> 0;
+               p->timing_20_30_f8 = (nv_ro08(bios, data + 0x30) & 0xf8) >> 3;
+               temp = nv_ro16(bios, data + 0x31);
+               p->timing_20_31_0007 = (temp & 0x0007) >> 0;
+               p->timing_20_31_0078 = (temp & 0x0078) >> 3;
+               p->timing_20_31_0780 = (temp & 0x0780) >> 7;
+               p->timing_20_31_0800 = (temp & 0x0800) >> 11;
+               p->timing_20_31_7000 = (temp & 0x7000) >> 12;
+               p->timing_20_31_8000 = (temp & 0x8000) >> 15;
+               break;
+       default:
+               data = 0;
+               break;
+       }
+       return data;
+}
index e2938a21b06fe8a7ac255e9abe106ce1533dc448..dd62baead39c54c9a906939576553b59bf9355a2 100644 (file)
@@ -182,9 +182,12 @@ nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei)
        clk->pstate = pstatei;
 
        if (pfb->ram->calc) {
-               ret = pfb->ram->calc(pfb, pstate->base.domain[nv_clk_src_mem]);
-               if (ret == 0)
-                       ret = pfb->ram->prog(pfb);
+               int khz = pstate->base.domain[nv_clk_src_mem];
+               do {
+                       ret = pfb->ram->calc(pfb, khz);
+                       if (ret == 0)
+                               ret = pfb->ram->prog(pfb);
+               } while (ret > 0);
                pfb->ram->tidy(pfb);
        }
 
index 30c1f3a4158e3de87fd2bfb24592b9ea685b2d88..b74db6cfc4e21ee8f811a08e54da3dfdc7f824a1 100644 (file)
@@ -25,7 +25,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/pll.h>
 #include <subdev/clock.h>
-#include <subdev/devinit/priv.h>
+#include <subdev/devinit/nv04.h>
 
 #include "pll.h"
 
index 4c62e84b96f5f7a4aa65d5e8d37bd25d12b120eb..d3c37c96f0e7eaeed97c08749bc23611642705db 100644 (file)
@@ -457,7 +457,7 @@ nve0_domain[] = {
        { nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
        { nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
        { nv_clk_src_rop    , 0x02, NVKM_CLK_DOM_FLAG_CORE },
-       { nv_clk_src_mem    , 0x03, 0, "memory", 1000 },
+       { nv_clk_src_mem    , 0x03, 0, "memory", 500 },
        { nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE },
        { nv_clk_src_hubk01 , 0x05 },
        { nv_clk_src_vdec   , 0x06 },
index 79c81d3d9bacee32ec45f36dee8b73cee3ac2953..8fa34e8152c20b6ae90f2ca020f6c49a077f2cdd 100644 (file)
 
 #include <core/option.h>
 
-#include <subdev/devinit.h>
 #include <subdev/bios.h>
 #include <subdev/bios/init.h>
+#include <subdev/vga.h>
+
+#include "priv.h"
 
 int
 _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
@@ -37,18 +39,41 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)
        if (suspend)
                devinit->post = true;
 
+       /* unlock the extended vga crtc regs */
+       nv_lockvgac(devinit, false);
+
        return nouveau_subdev_fini(&devinit->base, suspend);
 }
 
 int
 _nouveau_devinit_init(struct nouveau_object *object)
 {
+       struct nouveau_devinit_impl *impl = (void *)object->oclass;
        struct nouveau_devinit *devinit = (void *)object;
-       int ret = nouveau_subdev_init(&devinit->base);
+       int ret;
+
+       ret = nouveau_subdev_init(&devinit->base);
+       if (ret)
+               return ret;
+
+       ret = nvbios_init(&devinit->base, devinit->post);
        if (ret)
                return ret;
 
-       return nvbios_init(&devinit->base, devinit->post);
+       if (impl->disable)
+               nv_device(devinit)->disable_mask |= impl->disable(devinit);
+       return 0;
+}
+
+void
+_nouveau_devinit_dtor(struct nouveau_object *object)
+{
+       struct nouveau_devinit *devinit = (void *)object;
+
+       /* lock crtc regs */
+       nv_lockvgac(devinit, true);
+
+       nouveau_subdev_destroy(&devinit->base);
 }
 
 int
@@ -57,6 +82,7 @@ nouveau_devinit_create_(struct nouveau_object *parent,
                        struct nouveau_oclass *oclass,
                        int size, void **pobject)
 {
+       struct nouveau_devinit_impl *impl = (void *)oclass;
        struct nouveau_device *device = nv_device(parent);
        struct nouveau_devinit *devinit;
        int ret;
@@ -68,5 +94,7 @@ nouveau_devinit_create_(struct nouveau_object *parent,
                return ret;
 
        devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false);
+       devinit->meminit = impl->meminit;
+       devinit->pll_set = impl->pll_set;
        return 0;
 }
index 27c8235f1a85d08a3128dd3266416461ba08a9a7..7037eae46e445bd5d3278dfc70119dac180cadbb 100644 (file)
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv04_devinit_priv {
-       struct nouveau_devinit base;
-       int owner;
-};
+#include "nv04.h"
 
 static void
 nv04_devinit_meminit(struct nouveau_devinit *devinit)
@@ -393,17 +388,21 @@ int
 nv04_devinit_fini(struct nouveau_object *object, bool suspend)
 {
        struct nv04_devinit_priv *priv = (void *)object;
+       int ret;
 
        /* make i2c busses accessible */
        nv_mask(priv, 0x000200, 0x00000001, 0x00000001);
 
-       /* unlock extended vga crtc regs, and unslave crtcs */
-       nv_lockvgac(priv, false);
+       ret = nouveau_devinit_fini(&priv->base, suspend);
+       if (ret)
+               return ret;
+
+       /* unslave crtcs */
        if (priv->owner < 0)
                priv->owner = nv_rdvgaowner(priv);
        nv_wrvgaowner(priv, 0);
 
-       return nouveau_devinit_fini(&priv->base, suspend);
+       return 0;
 }
 
 int
@@ -431,14 +430,13 @@ nv04_devinit_dtor(struct nouveau_object *object)
 {
        struct nv04_devinit_priv *priv = (void *)object;
 
-       /* restore vga owner saved at first init, and lock crtc regs  */
+       /* restore vga owner saved at first init */
        nv_wrvgaowner(priv, priv->owner);
-       nv_lockvgac(priv, true);
 
        nouveau_devinit_destroy(&priv->base);
 }
 
-static int
+int
 nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
                  struct nouveau_object **pobject)
@@ -451,19 +449,19 @@ nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       priv->base.meminit = nv04_devinit_meminit;
-       priv->base.pll_set = nv04_devinit_pll_set;
        priv->owner = -1;
        return 0;
 }
 
-struct nouveau_oclass
-nv04_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x04),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv04_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x04),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .meminit = nv04_devinit_meminit,
+       .pll_set = nv04_devinit_pll_set,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h
new file mode 100644 (file)
index 0000000..23470a5
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __NVKM_DEVINIT_NV04_H__
+#define __NVKM_DEVINIT_NV04_H__
+
+#include "priv.h"
+
+struct nv04_devinit_priv {
+       struct nouveau_devinit base;
+       u8 owner;
+};
+
+int  nv04_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
+                      struct nouveau_oclass *, void *, u32,
+                      struct nouveau_object **);
+void nv04_devinit_dtor(struct nouveau_object *);
+int  nv04_devinit_init(struct nouveau_object *);
+int  nv04_devinit_fini(struct nouveau_object *, bool);
+int  nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
+
+#endif
index b1912a8a8942129b6292323faed5aa11475bfe3e..98b7e6780dc7f4826c4eb946419d0ceb6cfb5d84 100644 (file)
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv05_devinit_priv {
-       struct nouveau_devinit base;
-       u8 owner;
-};
+#include "nv04.h"
 
 static void
 nv05_devinit_meminit(struct nouveau_devinit *devinit)
@@ -49,7 +44,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)
                { 0x06, 0x00 },
                { 0x00, 0x00 }
        };
-       struct nv05_devinit_priv *priv = (void *)devinit;
+       struct nv04_devinit_priv *priv = (void *)devinit;
        struct nouveau_bios *bios = nouveau_bios(priv);
        struct io_mapping *fb;
        u32 patt = 0xdeadbeef;
@@ -130,31 +125,15 @@ out:
        fbmem_fini(fb);
 }
 
-static int
-nv05_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nv05_devinit_priv *priv;
-       int ret;
-
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.meminit = nv05_devinit_meminit;
-       priv->base.pll_set = nv04_devinit_pll_set;
-       return 0;
-}
-
-struct nouveau_oclass
-nv05_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x05),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv05_devinit_ctor,
+struct nouveau_oclass *
+nv05_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x05),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .meminit = nv05_devinit_meminit,
+       .pll_set = nv04_devinit_pll_set,
+}.base;
index 8d274dba1ef17a363af4d4c33c3cea4451025159..32b3d2131a7f0d14b0e37e8b9888e2b38cf937c5 100644 (file)
 #include <subdev/vga.h>
 
 #include "fbmem.h"
-#include "priv.h"
-
-struct nv10_devinit_priv {
-       struct nouveau_devinit base;
-       u8 owner;
-};
+#include "nv04.h"
 
 static void
 nv10_devinit_meminit(struct nouveau_devinit *devinit)
 {
-       struct nv10_devinit_priv *priv = (void *)devinit;
+       struct nv04_devinit_priv *priv = (void *)devinit;
        static const int mem_width[] = { 0x10, 0x00, 0x20 };
        int mem_width_count;
        uint32_t patt = 0xdeadbeef;
@@ -101,31 +96,15 @@ amount_found:
        fbmem_fini(fb);
 }
 
-static int
-nv10_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nv10_devinit_priv *priv;
-       int ret;
-
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.meminit = nv10_devinit_meminit;
-       priv->base.pll_set = nv04_devinit_pll_set;
-       return 0;
-}
-
-struct nouveau_oclass
-nv10_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x10),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv10_devinit_ctor,
+struct nouveau_oclass *
+nv10_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x10),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .meminit = nv10_devinit_meminit,
+       .pll_set = nv04_devinit_pll_set,
+}.base;
index e9743cdabe757df66b92509f295d9c800a6ae919..526d0c6faacd3d2623f1dae3aa2cd1b92087a00e 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv04.h"
 
-struct nv1a_devinit_priv {
-       struct nouveau_devinit base;
-       u8 owner;
-};
-
-static int
-nv1a_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nv1a_devinit_priv *priv;
-       int ret;
-
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.pll_set = nv04_devinit_pll_set;
-       return 0;
-}
-
-struct nouveau_oclass
-nv1a_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x1a),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv1a_devinit_ctor,
+struct nouveau_oclass *
+nv1a_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x1a),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .pll_set = nv04_devinit_pll_set,
+}.base;
index 6cc6080d3bc01e4e9e461bb5c323f82e48a60908..4689ba303b0bd6620ec080fcfe9fa3defad2f3ff 100644 (file)
  *
  */
 
-#include "priv.h"
+#include "nv04.h"
 #include "fbmem.h"
 
-struct nv20_devinit_priv {
-       struct nouveau_devinit base;
-       u8 owner;
-};
-
 static void
 nv20_devinit_meminit(struct nouveau_devinit *devinit)
 {
-       struct nv20_devinit_priv *priv = (void *)devinit;
+       struct nv04_devinit_priv *priv = (void *)devinit;
        struct nouveau_device *device = nv_device(priv);
        uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900);
        uint32_t amount, off;
@@ -65,31 +60,15 @@ nv20_devinit_meminit(struct nouveau_devinit *devinit)
        fbmem_fini(fb);
 }
 
-static int
-nv20_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nv20_devinit_priv *priv;
-       int ret;
-
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.meminit = nv20_devinit_meminit;
-       priv->base.pll_set = nv04_devinit_pll_set;
-       return 0;
-}
-
-struct nouveau_oclass
-nv20_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x20),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv20_devinit_ctor,
+struct nouveau_oclass *
+nv20_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x20),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_devinit_ctor,
                .dtor = nv04_devinit_dtor,
                .init = nv04_devinit_init,
                .fini = nv04_devinit_fini,
        },
-};
+       .meminit = nv20_devinit_meminit,
+       .pll_set = nv04_devinit_pll_set,
+}.base;
index 6df72247c477b5a7c96214fe28a0d7a40be82696..b46c62a1d5d86a9a44a0db88932dacbca6a10598 100644 (file)
@@ -28,9 +28,9 @@
 #include <subdev/bios/init.h>
 #include <subdev/vga.h>
 
-#include "priv.h"
+#include "nv50.h"
 
-static int
+int
 nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
        struct nv50_devinit_priv *priv = (void *)devinit;
@@ -74,6 +74,19 @@ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return 0;
 }
 
+static u64
+nv50_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000))
+               disable |= (1ULL << NVDEV_ENGINE_MPEG);
+
+       return disable;
+}
+
 int
 nv50_devinit_init(struct nouveau_object *object)
 {
@@ -120,7 +133,7 @@ nv50_devinit_init(struct nouveau_object *object)
        return 0;
 }
 
-static int
+int
 nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
                  struct nouveau_object **pobject)
@@ -133,17 +146,18 @@ nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       priv->base.pll_set = nv50_devinit_pll_set;
        return 0;
 }
 
-struct nouveau_oclass
-nv50_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0x50),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv50_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x50),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv50_devinit_ctor,
                .dtor = _nouveau_devinit_dtor,
                .init = nv50_devinit_init,
                .fini = _nouveau_devinit_fini,
        },
-};
+       .pll_set = nv50_devinit_pll_set,
+       .disable = nv50_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h
new file mode 100644 (file)
index 0000000..141c27e
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __NVKM_DEVINIT_NV50_H__
+#define __NVKM_DEVINIT_NV50_H__
+
+#include "priv.h"
+
+struct nv50_devinit_priv {
+       struct nouveau_devinit base;
+};
+
+int  nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *,
+                      struct nouveau_oclass *, void *, u32,
+                      struct nouveau_object **);
+int  nv50_devinit_init(struct nouveau_object *);
+int  nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+int  nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c
new file mode 100644 (file)
index 0000000..7874225
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nv84_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_MPEG);
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nv84_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x84),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nv50_devinit_pll_set,
+       .disable = nv84_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c
new file mode 100644 (file)
index 0000000..2b0e963
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nv98_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_CRYPT);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nv98_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0x98),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nv50_devinit_pll_set,
+       .disable = nv98_devinit_disable,
+}.base;
index 76a68b29014119f57c909c4770777016e8838250..6dedf1dad7f7bce5b71d33dd01111cac7324621b 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv50.h"
 
-static int
+int
 nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
-       struct nva3_devinit_priv *priv = (void *)devinit;
+       struct nv50_devinit_priv *priv = (void *)devinit;
        struct nouveau_bios *bios = nouveau_bios(priv);
        struct nvbios_pll info;
        int N, fN, M, P;
@@ -58,30 +58,38 @@ nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return ret;
 }
 
-static int
-nva3_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
+static u64
+nva3_devinit_disable(struct nouveau_devinit *devinit)
 {
-       struct nv50_devinit_priv *priv;
-       int ret;
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0ULL;
 
-       ret = nouveau_devinit_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000200))
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
 
-       priv->base.pll_set = nva3_devinit_pll_set;
-       return 0;
+       return disable;
 }
 
-struct nouveau_oclass
-nva3_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0xa3),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nva3_devinit_ctor,
+struct nouveau_oclass *
+nva3_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0xa3),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
                .dtor = _nouveau_devinit_dtor,
                .init = nv50_devinit_init,
                .fini = _nouveau_devinit_fini,
        },
-};
+       .pll_set = nva3_devinit_pll_set,
+       .disable = nva3_devinit_disable,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c
new file mode 100644 (file)
index 0000000..4fc68d2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "nv50.h"
+
+static u64
+nvaf_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r001540 = nv_rd32(priv, 0x001540);
+       u32 r00154c = nv_rd32(priv, 0x00154c);
+       u64 disable = 0;
+
+       if (!(r001540 & 0x40000000)) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (!(r00154c & 0x00000004))
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+       if (!(r00154c & 0x00000020))
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (!(r00154c & 0x00000040))
+               disable |= (1ULL << NVDEV_ENGINE_VIC);
+       if (!(r00154c & 0x00000200))
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
+
+       return disable;
+}
+
+struct nouveau_oclass *
+nvaf_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0xaf),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_devinit_ctor,
+               .dtor = _nouveau_devinit_dtor,
+               .init = nv50_devinit_init,
+               .fini = _nouveau_devinit_fini,
+       },
+       .pll_set = nva3_devinit_pll_set,
+       .disable = nvaf_devinit_disable,
+}.base;
index 19e265bf4574a0ad04086bd99d6fa0c2dd9912f9..fa7e63766b1b19ae47b8557c4581b77cb0ff0a22 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include "priv.h"
+#include "nv50.h"
 
 static int
 nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
 {
-       struct nvc0_devinit_priv *priv = (void *)devinit;
+       struct nv50_devinit_priv *priv = (void *)devinit;
        struct nouveau_bios *bios = nouveau_bios(priv);
        struct nvbios_pll info;
        int N, fN, M, P;
@@ -59,6 +59,33 @@ nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
        return ret;
 }
 
+static u64
+nvc0_devinit_disable(struct nouveau_devinit *devinit)
+{
+       struct nv50_devinit_priv *priv = (void *)devinit;
+       u32 r022500 = nv_rd32(priv, 0x022500);
+       u64 disable = 0ULL;
+
+       if (r022500 & 0x00000001)
+               disable |= (1ULL << NVDEV_ENGINE_DISP);
+
+       if (r022500 & 0x00000002) {
+               disable |= (1ULL << NVDEV_ENGINE_VP);
+               disable |= (1ULL << NVDEV_ENGINE_PPP);
+       }
+
+       if (r022500 & 0x00000004)
+               disable |= (1ULL << NVDEV_ENGINE_BSP);
+       if (r022500 & 0x00000008)
+               disable |= (1ULL << NVDEV_ENGINE_VENC);
+       if (r022500 & 0x00000100)
+               disable |= (1ULL << NVDEV_ENGINE_COPY0);
+       if (r022500 & 0x00000200)
+               disable |= (1ULL << NVDEV_ENGINE_COPY1);
+
+       return disable;
+}
+
 static int
 nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -72,19 +99,20 @@ nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (ret)
                return ret;
 
-       priv->base.pll_set = nvc0_devinit_pll_set;
        if (nv_rd32(priv, 0x022500) & 0x00000001)
                priv->base.post = true;
        return 0;
 }
 
-struct nouveau_oclass
-nvc0_devinit_oclass = {
-       .handle = NV_SUBDEV(DEVINIT, 0xc0),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nvc0_devinit_oclass = &(struct nouveau_devinit_impl) {
+       .base.handle = NV_SUBDEV(DEVINIT, 0xc0),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nvc0_devinit_ctor,
                .dtor = _nouveau_devinit_dtor,
                .init = nv50_devinit_init,
                .fini = _nouveau_devinit_fini,
        },
-};
+       .pll_set = nvc0_devinit_pll_set,
+       .disable = nvc0_devinit_disable,
+}.base;
index 7d622e2b01712508259e1f4436e0284543da7435..822a2fbf44a5b3d601d5c79eedb7b2af68654d86 100644 (file)
@@ -6,20 +6,32 @@
 #include <subdev/clock/pll.h>
 #include <subdev/devinit.h>
 
-void nv04_devinit_dtor(struct nouveau_object *);
-int  nv04_devinit_init(struct nouveau_object *);
-int  nv04_devinit_fini(struct nouveau_object *, bool);
-int  nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32);
-
-void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *);
-
-
-struct nv50_devinit_priv {
-       struct nouveau_devinit base;
+struct nouveau_devinit_impl {
+       struct nouveau_oclass base;
+       void (*meminit)(struct nouveau_devinit *);
+       int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq);
+       u64  (*disable)(struct nouveau_devinit *);
 };
 
-int  nv50_devinit_init(struct nouveau_object *);
+#define nouveau_devinit_create(p,e,o,d)                                        \
+       nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_devinit_destroy(p) ({                                          \
+       struct nouveau_devinit *d = (p);                                       \
+       _nouveau_devinit_dtor(nv_object(d));                                   \
+})
+#define nouveau_devinit_init(p) ({                                             \
+       struct nouveau_devinit *d = (p);                                       \
+       _nouveau_devinit_init(nv_object(d));                                   \
+})
+#define nouveau_devinit_fini(p,s) ({                                           \
+       struct nouveau_devinit *d = (p);                                       \
+       _nouveau_devinit_fini(nv_object(d), (s));                              \
+})
+
+int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *,
+                           struct nouveau_oclass *, int, void **);
+void _nouveau_devinit_dtor(struct nouveau_object *);
+int _nouveau_devinit_init(struct nouveau_object *);
+int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);
 
 #endif
index 34f9605ffee61321d381d6c3ed7e552f8918c51b..66fe959b4f7431dd2cc1b9ce6520263560fb769f 100644 (file)
 #include <subdev/bios.h>
 #include "priv.h"
 
+/* binary driver only executes this path if the condition (a) is true
+ * for any configuration (combination of rammap+ramcfg+timing) that
+ * can be reached on a given card.  for now, we will execute the branch
+ * unconditionally in the hope that a "false everywhere" in the bios
+ * tables doesn't actually mean "don't touch this".
+ */
+#define NOTE00(a) 1
+
 int
-nouveau_gddr5_calc(struct nouveau_ram *ram)
+nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts)
 {
-       struct nouveau_bios *bios = nouveau_bios(ram);
-       int pd, lf, xd, vh, vr, vo;
-       int WL, CL, WR, at, dt, ds;
+       int pd, lf, xd, vh, vr, vo, l3;
+       int WL, CL, WR, at[2], dt, ds;
        int rq = ram->freq < 1000000; /* XXX */
 
-       switch (!!ram->ramcfg.data * ram->ramcfg.version) {
+       switch (ram->ramcfg.version) {
        case 0x11:
-               pd =  (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x80) >> 7;
-               lf =  (nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x40) >> 6;
-               xd = !(nv_ro08(bios, ram->ramcfg.data + 0x01) & 0x20);
-               vh =  (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x10) >> 4;
-               vr =  (nv_ro08(bios, ram->ramcfg.data + 0x02) & 0x04) >> 2;
-               vo =   nv_ro08(bios, ram->ramcfg.data + 0x06) & 0xff;
+               pd =  ram->next->bios.ramcfg_11_01_80;
+               lf =  ram->next->bios.ramcfg_11_01_40;
+               xd = !ram->next->bios.ramcfg_11_01_20;
+               vh =  ram->next->bios.ramcfg_11_02_10;
+               vr =  ram->next->bios.ramcfg_11_02_04;
+               vo =  ram->next->bios.ramcfg_11_06;
+               l3 = !ram->next->bios.ramcfg_11_07_02;
                break;
        default:
                return -ENOSYS;
        }
 
-       switch (!!ram->timing.data * ram->timing.version) {
+       switch (ram->timing.version) {
        case 0x20:
-               WL = (nv_ro16(bios, ram->timing.data + 0x04) & 0x0f80) >> 7;
-               CL =  nv_ro08(bios, ram->timing.data + 0x04) & 0x1f;
-               WR =  nv_ro08(bios, ram->timing.data + 0x0a) & 0x7f;
-               at = (nv_ro08(bios, ram->timing.data + 0x2e) & 0xc0) >> 6;
-               dt =  nv_ro08(bios, ram->timing.data + 0x2e) & 0x03;
-               ds =  nv_ro08(bios, ram->timing.data + 0x2f) & 0x03;
+               WL = (ram->next->bios.timing[1] & 0x00000f80) >> 7;
+               CL = (ram->next->bios.timing[1] & 0x0000001f);
+               WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16;
+               at[0] = ram->next->bios.timing_20_2e_c0;
+               at[1] = ram->next->bios.timing_20_2e_30;
+               dt =  ram->next->bios.timing_20_2e_03;
+               ds =  ram->next->bios.timing_20_2f_03;
                break;
        default:
                return -ENOSYS;
@@ -71,13 +80,25 @@ nouveau_gddr5_calc(struct nouveau_ram *ram)
 
        ram->mr[1] &= ~0x0bf;
        ram->mr[1] |= (xd & 0x01) << 7;
-       ram->mr[1] |= (at & 0x03) << 4;
+       ram->mr[1] |= (at[0] & 0x03) << 4;
        ram->mr[1] |= (dt & 0x03) << 2;
        ram->mr[1] |= (ds & 0x03) << 0;
 
+       /* this seems wrong, alternate field used for the broadcast
+        * on nuts vs non-nuts configs..  meh, it matches for now.
+        */
+       ram->mr1_nuts = ram->mr[1];
+       if (nuts) {
+               ram->mr[1] &= ~0x030;
+               ram->mr[1] |= (at[1] & 0x03) << 4;
+       }
+
        ram->mr[3] &= ~0x020;
        ram->mr[3] |= (rq & 0x01) << 5;
 
+       ram->mr[5] &= ~0x004;
+       ram->mr[5] |= (l3 << 2);
+
        if (!vo)
                vo = (ram->mr[6] & 0xff0) >> 4;
        if (ram->mr[6] & 0x001)
@@ -86,11 +107,16 @@ nouveau_gddr5_calc(struct nouveau_ram *ram)
        ram->mr[6] |= (vo & 0xff) << 4;
        ram->mr[6] |= (pd & 0x01) << 0;
 
-       if (!(ram->mr[7] & 0x100))
-               vr = 0; /* binary driver does this.. bug? */
-       ram->mr[7] &= ~0x188;
-       ram->mr[7] |= (vr & 0x01) << 8;
+       if (NOTE00(vr)) {
+               ram->mr[7] &= ~0x300;
+               ram->mr[7] |= (vr & 0x03) << 8;
+       }
+       ram->mr[7] &= ~0x088;
        ram->mr[7] |= (vh & 0x01) << 7;
        ram->mr[7] |= (lf & 0x01) << 3;
+
+       ram->mr[8] &= ~0x003;
+       ram->mr[8] |= (WR & 0x10) >> 3;
+       ram->mr[8] |= (CL & 0x10) >> 4;
        return 0;
 }
index e5fc37c4caac841977a99e4530059ebd6235b36f..45470e1f0385f4682a654e0c37cb27212d3ba8eb 100644 (file)
@@ -33,6 +33,21 @@ nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)
        return likely((nvc0_pte_storage_type_map[memtype] != 0xff));
 }
 
+static void
+nvc0_fb_intr(struct nouveau_subdev *subdev)
+{
+       struct nvc0_fb_priv *priv = (void *)subdev;
+       u32 intr = nv_rd32(priv, 0x000100);
+       if (intr & 0x08000000) {
+               nv_debug(priv, "PFFB intr\n");
+               intr &= ~0x08000000;
+       }
+       if (intr & 0x00002000) {
+               nv_debug(priv, "PBFB intr\n");
+               intr &= ~0x00002000;
+       }
+}
+
 int
 nvc0_fb_init(struct nouveau_object *object)
 {
@@ -86,6 +101,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                        return -EFAULT;
        }
 
+       nv_subdev(priv)->intr = nvc0_fb_intr;
        return 0;
 }
 
index 493125214e88696db12ff1786f88be701e108225..edaf95dee61285d81d468060cd2b284b4da89cc0 100644 (file)
@@ -34,7 +34,7 @@ extern struct nouveau_oclass nvc0_ram_oclass;
 extern struct nouveau_oclass nve0_ram_oclass;
 
 int nouveau_sddr3_calc(struct nouveau_ram *ram);
-int nouveau_gddr5_calc(struct nouveau_ram *ram);
+int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts);
 
 #define nouveau_fb_create(p,e,c,d)                                             \
        nouveau_fb_create_((p), (e), (c), sizeof(**d), (void **)d)
index 76762a17d89cfe46a7b794e510fb83225c4aced7..c7fdb3a9e88b06cdcfa3151abf5ae7331c04e409 100644 (file)
@@ -70,13 +70,11 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
        struct nv50_ramseq *hwsq = &ram->hwsq;
        struct nvbios_perfE perfE;
        struct nvbios_pll mpll;
-       struct bit_entry M;
        struct {
                u32 data;
                u8  size;
        } ramcfg, timing;
-       u8  ver, hdr, cnt, strap;
-       u32 data;
+       u8  ver, hdr, cnt, len, strap;
        int N1, M1, N2, M2, P;
        int ret, i;
 
@@ -93,16 +91,7 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
        } while (perfE.memory < freq);
 
        /* locate specific data set for the attached memory */
-       if (bit_entry(bios, 'M', &M) || M.version != 1 || M.length < 5) {
-               nv_error(pfb, "invalid/missing memory table\n");
-               return -EINVAL;
-       }
-
-       strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-       data = nv_ro16(bios, M.offset + 3);
-       if (data)
-               strap = nv_ro08(bios, data + strap);
-
+       strap = nvbios_ramcfg_index(bios);
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
@@ -113,7 +102,8 @@ nv50_ram_calc(struct nouveau_fb *pfb, u32 freq)
        /* lookup memory timings, if bios says they're present */
        strap = nv_ro08(bios, ramcfg.data + 0x01);
        if (strap != 0xff) {
-               timing.data = nvbios_timing_entry(bios, strap, &ver, &hdr);
+               timing.data = nvbios_timingEe(bios, strap, &ver, &hdr,
+                                            &cnt, &len);
                if (!timing.data || ver != 0x10 || hdr < 0x12) {
                        nv_error(pfb, "invalid/missing timing entry "
                                 "%02x %04x %02x %02x\n",
index f6292cd9207cf354384738c50a135bea9e0ec562..f4ae8aa46a255948df24c3e4d2f4e259ed583d53 100644 (file)
@@ -79,8 +79,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
        struct nva3_ram *ram = (void *)pfb->ram;
        struct nva3_ramfuc *fuc = &ram->fuc;
        struct nva3_clock_info mclk;
-       struct bit_entry M;
-       u8  ver, cnt, strap;
+       u8  ver, cnt, len, strap;
        u32 data;
        struct {
                u32 data;
@@ -91,24 +90,15 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
        int ret;
 
        /* lookup memory config data relevant to the target frequency */
-       rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size,
-                                        &cnt, &ramcfg.size);
+       rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
+                                    &cnt, &ramcfg.size);
        if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
                nv_error(pfb, "invalid/missing rammap entry\n");
                return -EINVAL;
        }
 
        /* locate specific data set for the attached memory */
-       if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-               nv_error(pfb, "invalid/missing memory table\n");
-               return -EINVAL;
-       }
-
-       strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-       data = nv_ro16(bios, M.offset + 1);
-       if (data)
-               strap = nv_ro08(bios, data + strap);
-
+       strap = nvbios_ramcfg_index(bios);
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
@@ -123,8 +113,8 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
        /* lookup memory timings, if bios says they're present */
        strap = nv_ro08(bios, ramcfg.data + 0x01);
        if (strap != 0xff) {
-               timing.data = nvbios_timing_entry(bios, strap, &ver,
-                                                &timing.size);
+               timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size,
+                                            &cnt, &len);
                if (!timing.data || ver != 0x10 || timing.size < 0x19) {
                        nv_error(pfb, "invalid/missing timing entry\n");
                        return -EINVAL;
index f464547c6bab70c714626672bfbb015d7512d1a3..0391b824ee767d7629e333c56965366bc15347fd 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 #include <subdev/bios.h>
-#include <subdev/bios/bit.h>
 #include <subdev/bios/pll.h>
 #include <subdev/bios/rammap.h>
 #include <subdev/bios/timing.h>
@@ -134,9 +133,7 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nvc0_ram *ram = (void *)pfb->ram;
        struct nvc0_ramfuc *fuc = &ram->fuc;
-       struct bit_entry M;
-       u8  ver, cnt, strap;
-       u32 data;
+       u8  ver, cnt, len, strap;
        struct {
                u32 data;
                u8  size;
@@ -147,24 +144,15 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        int ret;
 
        /* lookup memory config data relevant to the target frequency */
-       rammap.data = nvbios_rammap_match(bios, freq / 1000, &ver, &rammap.size,
-                                        &cnt, &ramcfg.size);
+       rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size,
+                                    &cnt, &ramcfg.size);
        if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) {
                nv_error(pfb, "invalid/missing rammap entry\n");
                return -EINVAL;
        }
 
        /* locate specific data set for the attached memory */
-       if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-               nv_error(pfb, "invalid/missing memory table\n");
-               return -EINVAL;
-       }
-
-       strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-       data = nv_ro16(bios, M.offset + 1);
-       if (data)
-               strap = nv_ro08(bios, data + strap);
-
+       strap = nvbios_ramcfg_index(bios);
        if (strap >= cnt) {
                nv_error(pfb, "invalid ramcfg strap\n");
                return -EINVAL;
@@ -179,8 +167,8 @@ nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        /* lookup memory timings, if bios says they're present */
        strap = nv_ro08(bios, ramcfg.data + 0x01);
        if (strap != 0xff) {
-               timing.data = nvbios_timing_entry(bios, strap, &ver,
-                                                &timing.size);
+               timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size,
+                                            &cnt, &len);
                if (!timing.data || ver != 0x10 || timing.size < 0x19) {
                        nv_error(pfb, "invalid/missing timing entry\n");
                        return -EINVAL;
index bc86cfd084f66c106c4a46980212a59cdde47dad..3257c522a0219026e5147d37725b1f6a30fcac21 100644 (file)
@@ -25,7 +25,6 @@
 #include <subdev/gpio.h>
 
 #include <subdev/bios.h>
-#include <subdev/bios/bit.h>
 #include <subdev/bios/pll.h>
 #include <subdev/bios/init.h>
 #include <subdev/bios/rammap.h>
 
 #include "ramfuc.h"
 
+/* binary driver only executes this path if the condition (a) is true
+ * for any configuration (combination of rammap+ramcfg+timing) that
+ * can be reached on a given card.  for now, we will execute the branch
+ * unconditionally in the hope that a "false everywhere" in the bios
+ * tables doesn't actually mean "don't touch this".
+ */
+#define NOTE00(a) 1
+
 struct nve0_ramfuc {
        struct ramfuc base;
 
@@ -104,7 +111,9 @@ struct nve0_ramfuc {
        struct ramfuc_reg r_mr[16]; /* MR0 - MR8, MR15 */
 
        struct ramfuc_reg r_0x62c000;
+
        struct ramfuc_reg r_0x10f200;
+
        struct ramfuc_reg r_0x10f210;
        struct ramfuc_reg r_0x10f310;
        struct ramfuc_reg r_0x10f314;
@@ -118,12 +127,17 @@ struct nve0_ramfuc {
        struct ramfuc_reg r_0x10f65c;
        struct ramfuc_reg r_0x10f6bc;
        struct ramfuc_reg r_0x100710;
-       struct ramfuc_reg r_0x10f750;
+       struct ramfuc_reg r_0x100750;
 };
 
 struct nve0_ram {
        struct nouveau_ram base;
        struct nve0_ramfuc fuc;
+
+       u32 parts;
+       u32 pmask;
+       u32 pnuts;
+
        int from;
        int mode;
        int N1, fN1, M1, P1;
@@ -134,17 +148,17 @@ struct nve0_ram {
  * GDDR5
  ******************************************************************************/
 static void
-train(struct nve0_ramfuc *fuc, u32 magic)
+nve0_ram_train(struct nve0_ramfuc *fuc, u32 mask, u32 data)
 {
        struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
-       struct nouveau_fb *pfb = nouveau_fb(ram);
-       const int mc = nv_rd32(pfb, 0x02243c);
-       int i;
-
-       ram_mask(fuc, 0x10f910, 0xbc0e0000, magic);
-       ram_mask(fuc, 0x10f914, 0xbc0e0000, magic);
-       for (i = 0; i < mc; i++) {
-               const u32 addr = 0x110974 + (i * 0x1000);
+       u32 addr = 0x110974, i;
+
+       ram_mask(fuc, 0x10f910, mask, data);
+       ram_mask(fuc, 0x10f914, mask, data);
+
+       for (i = 0; (data & 0x80000000) && i < ram->parts; addr += 0x1000, i++) {
+               if (ram->pmask & (1 << i))
+                       continue;
                ram_wait(fuc, addr, 0x0000000f, 0x00000000, 500000);
        }
 }
@@ -199,12 +213,12 @@ r1373f4_init(struct nve0_ramfuc *fuc)
 }
 
 static void
-r1373f4_fini(struct nve0_ramfuc *fuc, u32 ramcfg)
+r1373f4_fini(struct nve0_ramfuc *fuc)
 {
        struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc);
-       struct nouveau_bios *bios = nouveau_bios(ram);
-       u8 v0 = (nv_ro08(bios, ramcfg + 0x03) & 0xc0) >> 6;
-       u8 v1 = (nv_ro08(bios, ramcfg + 0x03) & 0x30) >> 4;
+       struct nouveau_ram_data *next = ram->base.next;
+       u8 v0 = next->bios.ramcfg_11_03_c0;
+       u8 v1 = next->bios.ramcfg_11_03_30;
        u32 tmp;
 
        tmp = ram_rd32(fuc, 0x1373ec) & ~0x00030000;
@@ -220,25 +234,46 @@ r1373f4_fini(struct nve0_ramfuc *fuc, u32 ramcfg)
        ram_mask(fuc, 0x10f800, 0x00000030, (v0 ^ v1) << 4);
 }
 
+static void
+nve0_ram_nuts(struct nve0_ram *ram, struct ramfuc_reg *reg,
+             u32 _mask, u32 _data, u32 _copy)
+{
+       struct nve0_fb_priv *priv = (void *)nouveau_fb(ram);
+       struct ramfuc *fuc = &ram->fuc.base;
+       u32 addr = 0x110000 + (reg->addr[0] & 0xfff);
+       u32 mask = _mask | _copy;
+       u32 data = (_data & _mask) | (reg->data & _copy);
+       u32 i;
+
+       for (i = 0; i < 16; i++, addr += 0x1000) {
+               if (ram->pnuts & (1 << i)) {
+                       u32 prev = nv_rd32(priv, addr);
+                       u32 next = (prev & ~mask) | data;
+                       nouveau_memx_wr32(fuc->memx, addr, next);
+               }
+       }
+}
+#define ram_nuts(s,r,m,d,c)                                                    \
+       nve0_ram_nuts((s), &(s)->fuc.r_##r, (m), (d), (c))
+
 static int
 nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 {
-       struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
-       const u32 rammap = ram->base.rammap.data;
-       const u32 ramcfg = ram->base.ramcfg.data;
-       const u32 timing = ram->base.timing.data;
-       int vc = !(nv_ro08(bios, ramcfg + 0x02) & 0x08);
-       int mv = 1; /*XXX*/
+       struct nouveau_ram_data *next = ram->base.next;
+       int vc = !(next->bios.ramcfg_11_02_08);
+       int mv = !(next->bios.ramcfg_11_02_04);
        u32 mask, data;
 
        ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
        ram_wr32(fuc, 0x62c000, 0x0f0f0000);
 
        /* MR1: turn termination on early, for some reason.. */
-       if ((ram->base.mr[1] & 0x03c) != 0x030)
+       if ((ram->base.mr[1] & 0x03c) != 0x030) {
                ram_mask(fuc, mr[1], 0x03c, ram->base.mr[1] & 0x03c);
+               ram_nuts(ram, mr[1], 0x03c, ram->base.mr1_nuts & 0x03c, 0x000);
+       }
 
        if (vc == 1 && ram_have(fuc, gpio2E)) {
                u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]);
@@ -250,8 +285,7 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000);
 
-       ram_mask(fuc, 0x10f914, 0x01020000, 0x000c0000);
-       ram_mask(fuc, 0x10f910, 0x01020000, 0x000c0000);
+       nve0_ram_train(fuc, 0x01020000, 0x000c0000);
 
        ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */
        ram_nsec(fuc, 1000);
@@ -280,28 +314,28 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        if (1) {
                data |= 0x800807e0;
-               switch (nv_ro08(bios, ramcfg + 0x03) & 0xc0) {
-               case 0xc0: data &= ~0x00000040; break;
-               case 0x80: data &= ~0x00000100; break;
-               case 0x40: data &= ~0x80000000; break;
-               case 0x00: data &= ~0x00000400; break;
+               switch (next->bios.ramcfg_11_03_c0) {
+               case 3: data &= ~0x00000040; break;
+               case 2: data &= ~0x00000100; break;
+               case 1: data &= ~0x80000000; break;
+               case 0: data &= ~0x00000400; break;
                }
 
-               switch (nv_ro08(bios, ramcfg + 0x03) & 0x30) {
-               case 0x30: data &= ~0x00000020; break;
-               case 0x20: data &= ~0x00000080; break;
-               case 0x10: data &= ~0x00080000; break;
-               case 0x00: data &= ~0x00000200; break;
+               switch (next->bios.ramcfg_11_03_30) {
+               case 3: data &= ~0x00000020; break;
+               case 2: data &= ~0x00000080; break;
+               case 1: data &= ~0x00080000; break;
+               case 0: data &= ~0x00000200; break;
                }
        }
 
-       if (nv_ro08(bios, ramcfg + 0x02) & 0x80)
+       if (next->bios.ramcfg_11_02_80)
                mask |= 0x03000000;
-       if (nv_ro08(bios, ramcfg + 0x02) & 0x40)
+       if (next->bios.ramcfg_11_02_40)
                mask |= 0x00002000;
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x10)
+       if (next->bios.ramcfg_11_07_10)
                mask |= 0x00004000;
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x08)
+       if (next->bios.ramcfg_11_07_08)
                mask |= 0x00000003;
        else {
                mask |= 0x34000000;
@@ -314,18 +348,18 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        if (ram->from == 2 && ram->mode != 2) {
                ram_mask(fuc, 0x10f808, 0x00080000, 0x00000000);
-               ram_mask(fuc, 0x10f200, 0x00008000, 0x00008000);
+               ram_mask(fuc, 0x10f200, 0x18008000, 0x00008000);
                ram_mask(fuc, 0x10f800, 0x00000000, 0x00000004);
                ram_mask(fuc, 0x10f830, 0x00008000, 0x01040010);
                ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
                r1373f4_init(fuc);
                ram_mask(fuc, 0x1373f0, 0x00000002, 0x00000001);
-               r1373f4_fini(fuc, ramcfg);
+               r1373f4_fini(fuc);
                ram_mask(fuc, 0x10f830, 0x00c00000, 0x00240001);
        } else
        if (ram->from != 2 && ram->mode != 2) {
                r1373f4_init(fuc);
-               r1373f4_fini(fuc, ramcfg);
+               r1373f4_fini(fuc);
        }
 
        if (ram_have(fuc, gpioMV)) {
@@ -336,49 +370,54 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
                }
        }
 
-       if ( (nv_ro08(bios, ramcfg + 0x02) & 0x40) ||
-            (nv_ro08(bios, ramcfg + 0x07) & 0x10)) {
+       if ( (next->bios.ramcfg_11_02_40) ||
+            (next->bios.ramcfg_11_07_10)) {
                ram_mask(fuc, 0x132040, 0x00010000, 0x00010000);
                ram_nsec(fuc, 20000);
        }
 
        if (ram->from != 2 && ram->mode == 2) {
+               if (0 /*XXX: Titan */)
+                       ram_mask(fuc, 0x10f200, 0x18000000, 0x18000000);
                ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000);
                ram_mask(fuc, 0x1373f0, 0x00000000, 0x00000002);
                ram_mask(fuc, 0x10f830, 0x00800001, 0x00408010);
                r1373f4_init(fuc);
-               r1373f4_fini(fuc, ramcfg);
+               r1373f4_fini(fuc);
                ram_mask(fuc, 0x10f808, 0x00000000, 0x00080000);
                ram_mask(fuc, 0x10f200, 0x00808000, 0x00800000);
        } else
        if (ram->from == 2 && ram->mode == 2) {
                ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000);
                r1373f4_init(fuc);
-               r1373f4_fini(fuc, ramcfg);
+               r1373f4_fini(fuc);
        }
 
        if (ram->mode != 2) /*XXX*/ {
-               if (nv_ro08(bios, ramcfg + 0x07) & 0x40)
+               if (next->bios.ramcfg_11_07_40)
                        ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000);
        }
 
-       data = (nv_ro08(bios, rammap + 0x11) & 0x0c) >> 2;
-       ram_wr32(fuc, 0x10f65c, 0x00000011 * data);
-       ram_wr32(fuc, 0x10f6b8, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
-       ram_wr32(fuc, 0x10f6bc, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
+       ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c);
+       ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09);
+       ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09);
 
-       data = nv_ro08(bios, ramcfg + 0x04);
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
-               ram_wr32(fuc, 0x10f698, 0x01010101 * data);
-               ram_wr32(fuc, 0x10f69c, 0x01010101 * data);
+       if (!next->bios.ramcfg_11_07_08 && !next->bios.ramcfg_11_07_04) {
+               ram_wr32(fuc, 0x10f698, 0x01010101 * next->bios.ramcfg_11_04);
+               ram_wr32(fuc, 0x10f69c, 0x01010101 * next->bios.ramcfg_11_04);
+       } else
+       if (!next->bios.ramcfg_11_07_08) {
+               ram_wr32(fuc, 0x10f698, 0x00000000);
+               ram_wr32(fuc, 0x10f69c, 0x00000000);
        }
 
        if (ram->mode != 2) {
-               u32 temp = ram_rd32(fuc, 0x10f694) & ~0xff00ff00;
-               ram_wr32(fuc, 0x10f694, temp | (0x01000100 * data));
+               u32 data = 0x01000100 * next->bios.ramcfg_11_04;
+               ram_nuke(fuc, 0x10f694);
+               ram_mask(fuc, 0x10f694, 0xff00ff00, data);
        }
 
-       if (ram->mode == 2 && (nv_ro08(bios, ramcfg + 0x08) & 0x10))
+       if (ram->mode == 2 && (next->bios.ramcfg_11_08_10))
                data = 0x00000080;
        else
                data = 0x00000000;
@@ -386,19 +425,19 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        mask = 0x00070000;
        data = 0x00000000;
-       if (!(nv_ro08(bios, ramcfg + 0x02) & 0x80))
+       if (!(next->bios.ramcfg_11_02_80))
                data |= 0x03000000;
-       if (!(nv_ro08(bios, ramcfg + 0x02) & 0x40))
+       if (!(next->bios.ramcfg_11_02_40))
                data |= 0x00002000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x10))
+       if (!(next->bios.ramcfg_11_07_10))
                data |= 0x00004000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08))
+       if (!(next->bios.ramcfg_11_07_08))
                data |= 0x00000003;
        else
                data |= 0x74000000;
        ram_mask(fuc, 0x10f824, mask, data);
 
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x08)
+       if (next->bios.ramcfg_11_01_08)
                data = 0x00000000;
        else
                data = 0x00001000;
@@ -409,61 +448,90 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
                ram_mask(fuc, 0x10f670, 0x80000000, 0x00000000);
        }
 
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x01)
+       if (next->bios.ramcfg_11_08_01)
                data = 0x00100000;
        else
                data = 0x00000000;
        ram_mask(fuc, 0x10f82c, 0x00100000, data);
 
        data = 0x00000000;
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x08)
+       if (next->bios.ramcfg_11_08_08)
                data |= 0x00002000;
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x04)
+       if (next->bios.ramcfg_11_08_04)
                data |= 0x00001000;
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x02)
+       if (next->bios.ramcfg_11_08_02)
                data |= 0x00004000;
        ram_mask(fuc, 0x10f830, 0x00007000, data);
 
        /* PFB timing */
-       ram_mask(fuc, 0x10f248, 0xffffffff, nv_ro32(bios, timing + 0x28));
-       ram_mask(fuc, 0x10f290, 0xffffffff, nv_ro32(bios, timing + 0x00));
-       ram_mask(fuc, 0x10f294, 0xffffffff, nv_ro32(bios, timing + 0x04));
-       ram_mask(fuc, 0x10f298, 0xffffffff, nv_ro32(bios, timing + 0x08));
-       ram_mask(fuc, 0x10f29c, 0xffffffff, nv_ro32(bios, timing + 0x0c));
-       ram_mask(fuc, 0x10f2a0, 0xffffffff, nv_ro32(bios, timing + 0x10));
-       ram_mask(fuc, 0x10f2a4, 0xffffffff, nv_ro32(bios, timing + 0x14));
-       ram_mask(fuc, 0x10f2a8, 0xffffffff, nv_ro32(bios, timing + 0x18));
-       ram_mask(fuc, 0x10f2ac, 0xffffffff, nv_ro32(bios, timing + 0x1c));
-       ram_mask(fuc, 0x10f2cc, 0xffffffff, nv_ro32(bios, timing + 0x20));
-       ram_mask(fuc, 0x10f2e8, 0xffffffff, nv_ro32(bios, timing + 0x24));
-
-       data = (nv_ro08(bios, ramcfg + 0x02) & 0x03) << 8;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x10)
-               data |= 0x70000000;
-       ram_mask(fuc, 0x10f604, 0x70000300, data);
-
-       data = (nv_ro08(bios, timing + 0x30) & 0x07) << 28;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x01)
-               data |= 0x00000100;
-       ram_mask(fuc, 0x10f614, 0x70000000, data);
-
-       data = (nv_ro08(bios, timing + 0x30) & 0x07) << 28;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x02)
-               data |= 0x00000100;
-       ram_mask(fuc, 0x10f610, 0x70000000, data);
+       ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]);
+       ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]);
+       ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]);
+       ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]);
+       ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]);
+       ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]);
+       ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]);
+       ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]);
+       ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]);
+       ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]);
+       ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]);
+
+       data = mask = 0x00000000;
+       if (NOTE00(ramcfg_08_20)) {
+               if (next->bios.ramcfg_11_08_20)
+                       data |= 0x01000000;
+               mask |= 0x01000000;
+       }
+       ram_mask(fuc, 0x10f200, mask, data);
+
+       data = mask = 0x00000000;
+       if (NOTE00(ramcfg_02_03 != 0)) {
+               data |= (next->bios.ramcfg_11_02_03) << 8;
+               mask |= 0x00000300;
+       }
+       if (NOTE00(ramcfg_01_10)) {
+               if (next->bios.ramcfg_11_01_10)
+                       data |= 0x70000000;
+               mask |= 0x70000000;
+       }
+       ram_mask(fuc, 0x10f604, mask, data);
+
+       data = mask = 0x00000000;
+       if (NOTE00(timing_30_07 != 0)) {
+               data |= (next->bios.timing_20_30_07) << 28;
+               mask |= 0x70000000;
+       }
+       if (NOTE00(ramcfg_01_01)) {
+               if (next->bios.ramcfg_11_01_01)
+                       data |= 0x00000100;
+               mask |= 0x00000100;
+       }
+       ram_mask(fuc, 0x10f614, mask, data);
+
+       data = mask = 0x00000000;
+       if (NOTE00(timing_30_07 != 0)) {
+               data |= (next->bios.timing_20_30_07) << 28;
+               mask |= 0x70000000;
+       }
+       if (NOTE00(ramcfg_01_02)) {
+               if (next->bios.ramcfg_11_01_02)
+                       data |= 0x00000100;
+               mask |= 0x00000100;
+       }
+       ram_mask(fuc, 0x10f610, mask, data);
 
        mask = 0x33f00000;
        data = 0x00000000;
-       if (!(nv_ro08(bios, ramcfg + 0x01) & 0x04))
+       if (!(next->bios.ramcfg_11_01_04))
                data |= 0x20200000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+       if (!(next->bios.ramcfg_11_07_80))
                data |= 0x12800000;
        /*XXX: see note above about there probably being some condition
         *     for the 10f824 stuff that uses ramcfg 3...
         */
-       if ( (nv_ro08(bios, ramcfg + 0x03) & 0xf0)) {
-               if (nv_ro08(bios, rammap + 0x08) & 0x0c) {
-                       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+       if ( (next->bios.ramcfg_11_03_f0)) {
+               if (next->bios.rammap_11_08_0c) {
+                       if (!(next->bios.ramcfg_11_07_80))
                                mask |= 0x00000020;
                        else
                                data |= 0x00000020;
@@ -476,49 +544,53 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 
        ram_mask(fuc, 0x10f808, mask, data);
 
-       data = nv_ro08(bios, ramcfg + 0x03) & 0x0f;
-       ram_wr32(fuc, 0x10f870, 0x11111111 * data);
+       ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f);
 
-       data = nv_ro08(bios, ramcfg + 0x02) & 0x03;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x10)
-               data |= 0x00000004;
-       if ((nv_rd32(bios, 0x100770) & 0x00000004) != (data & 0x00000004)) {
-               ram_wr32(fuc, 0x10f750, 0x04000009);
+       data = mask = 0x00000000;
+       if (NOTE00(ramcfg_02_03 != 0)) {
+               data |= next->bios.ramcfg_11_02_03;
+               mask |= 0x00000003;
+       }
+       if (NOTE00(ramcfg_01_10)) {
+               if (next->bios.ramcfg_11_01_10)
+                       data |= 0x00000004;
+               mask |= 0x00000004;
+       }
+
+       if ((ram_mask(fuc, 0x100770, mask, data) & mask & 4) != (data & 4)) {
+               ram_mask(fuc, 0x100750, 0x00000008, 0x00000008);
                ram_wr32(fuc, 0x100710, 0x00000000);
                ram_wait(fuc, 0x100710, 0x80000000, 0x80000000, 200000);
        }
-       ram_mask(fuc, 0x100770, 0x00000007, data);
 
-       data = (nv_ro08(bios, timing + 0x30) & 0x07) << 8;
-       if (nv_ro08(bios, ramcfg + 0x01) & 0x01)
+       data = (next->bios.timing_20_30_07) << 8;
+       if (next->bios.ramcfg_11_01_01)
                data |= 0x80000000;
        ram_mask(fuc, 0x100778, 0x00000700, data);
 
-       data = nv_ro16(bios, timing + 0x2c);
-       ram_mask(fuc, 0x10f250, 0x000003f0, (data & 0x003f) <<  4);
-       ram_mask(fuc, 0x10f24c, 0x7f000000, (data & 0x1fc0) << 18);
-
-       data = nv_ro08(bios, timing + 0x30);
-       ram_mask(fuc, 0x10f224, 0x001f0000, (data & 0xf8) << 13);
+       ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4);
+       data = (next->bios.timing[10] & 0x7f000000) >> 24;
+       if (data < next->bios.timing_20_2c_1fc0)
+               data = next->bios.timing_20_2c_1fc0;
+       ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
+       ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8 << 16);
 
-       data = nv_ro16(bios, timing + 0x31);
-       ram_mask(fuc, 0x10fec4, 0x041e0f07, (data & 0x0800) << 15 |
-                                           (data & 0x0780) << 10 |
-                                           (data & 0x0078) <<  5 |
-                                           (data & 0x0007));
-       ram_mask(fuc, 0x10fec8, 0x00000027, (data & 0x8000) >> 10 |
-                                           (data & 0x7000) >> 12);
+       ram_mask(fuc, 0x10fec4, 0x041e0f07, next->bios.timing_20_31_0800 << 26 |
+                                           next->bios.timing_20_31_0780 << 17 |
+                                           next->bios.timing_20_31_0078 << 8 |
+                                           next->bios.timing_20_31_0007);
+       ram_mask(fuc, 0x10fec8, 0x00000027, next->bios.timing_20_31_8000 << 5 |
+                                           next->bios.timing_20_31_7000);
 
        ram_wr32(fuc, 0x10f090, 0x4000007e);
-       ram_nsec(fuc, 1000);
+       ram_nsec(fuc, 2000);
        ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
        ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */
-       ram_nsec(fuc, 2000);
        ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */
 
-       if ((nv_ro08(bios, ramcfg + 0x08) & 0x10) && (ram->mode == 2) /*XXX*/) {
+       if ((next->bios.ramcfg_11_08_10) && (ram->mode == 2) /*XXX*/) {
                u32 temp = ram_mask(fuc, 0x10f294, 0xff000000, 0x24000000);
-               train(fuc, 0xa4010000); /*XXX*/
+               nve0_ram_train(fuc, 0xbc0e0000, 0xa4010000); /*XXX*/
                ram_nsec(fuc, 1000);
                ram_wr32(fuc, 0x10f294, temp);
        }
@@ -528,7 +600,7 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
        ram_mask(fuc, mr[8], 0xfff, ram->base.mr[8]);
        ram_nsec(fuc, 1000);
        ram_mask(fuc, mr[1], 0xfff, ram->base.mr[1]);
-       ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5]);
+       ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5] & ~0x004); /* LP3 later */
        ram_mask(fuc, mr[6], 0xfff, ram->base.mr[6]);
        ram_mask(fuc, mr[7], 0xfff, ram->base.mr[7]);
 
@@ -544,12 +616,13 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
        ram_wr32(fuc, 0x10f318, 0x00000001); /* NOP? */
        ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000);
        ram_nsec(fuc, 1000);
+       ram_nuts(ram, 0x10f200, 0x18808800, 0x00000000, 0x18808800);
 
        data  = ram_rd32(fuc, 0x10f978);
        data &= ~0x00046144;
        data |=  0x0000000b;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
-               if (!(nv_ro08(bios, ramcfg + 0x07) & 0x04))
+       if (!(next->bios.ramcfg_11_07_08)) {
+               if (!(next->bios.ramcfg_11_07_04))
                        data |= 0x0000200c;
                else
                        data |= 0x00000000;
@@ -563,44 +636,43 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
                ram_wr32(fuc, 0x10f830, data);
        }
 
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08)) {
+       if (!(next->bios.ramcfg_11_07_08)) {
                data = 0x88020000;
-               if ( (nv_ro08(bios, ramcfg + 0x07) & 0x04))
+               if ( (next->bios.ramcfg_11_07_04))
                        data |= 0x10000000;
-               if (!(nv_ro08(bios, rammap + 0x08) & 0x10))
+               if (!(next->bios.rammap_11_08_10))
                        data |= 0x00080000;
        } else {
                data = 0xa40e0000;
        }
-       train(fuc, data);
-       ram_nsec(fuc, 1000);
+       nve0_ram_train(fuc, 0xbc0f0000, data);
+       if (1) /* XXX: not always? */
+               ram_nsec(fuc, 1000);
 
        if (ram->mode == 2) { /*XXX*/
                ram_mask(fuc, 0x10f800, 0x00000004, 0x00000004);
        }
 
-       /* MR5: (re)enable LP3 if necessary
-        * XXX: need to find the switch, keeping off for now
-        */
-       ram_mask(fuc, mr[5], 0x00000004, 0x00000000);
+       /* LP3 */
+       if (ram_mask(fuc, mr[5], 0x004, ram->base.mr[5]) != ram->base.mr[5])
+               ram_nsec(fuc, 1000);
 
        if (ram->mode != 2) {
                ram_mask(fuc, 0x10f830, 0x01000000, 0x01000000);
                ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000);
        }
 
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x02) {
-               ram_mask(fuc, 0x10f910, 0x80020000, 0x01000000);
-               ram_mask(fuc, 0x10f914, 0x80020000, 0x01000000);
-       }
+       if (next->bios.ramcfg_11_07_02)
+               nve0_ram_train(fuc, 0x80020000, 0x01000000);
 
        ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
 
-       if (nv_ro08(bios, rammap + 0x08) & 0x01)
+       if (next->bios.rammap_11_08_01)
                data = 0x00000800;
        else
                data = 0x00000000;
        ram_mask(fuc, 0x10f200, 0x00000800, data);
+       ram_nuts(ram, 0x10f200, 0x18808800, data, 0x18808800);
        return 0;
 }
 
@@ -611,17 +683,14 @@ nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq)
 static int
 nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 {
-       struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
        const u32 rcoef = ((  ram->P1 << 16) | (ram->N1 << 8) | ram->M1);
        const u32 runk0 = ram->fN1 << 16;
        const u32 runk1 = ram->fN1;
-       const u32 rammap = ram->base.rammap.data;
-       const u32 ramcfg = ram->base.ramcfg.data;
-       const u32 timing = ram->base.timing.data;
-       int vc = !(nv_ro08(bios, ramcfg + 0x02) & 0x08);
-       int mv = 1; /*XXX*/
+       struct nouveau_ram_data *next = ram->base.next;
+       int vc = !(next->bios.ramcfg_11_02_08);
+       int mv = !(next->bios.ramcfg_11_02_04);
        u32 mask, data;
 
        ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
@@ -636,7 +705,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
        }
 
        ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000);
-       if ((nv_ro08(bios, ramcfg + 0x03) & 0xf0))
+       if ((next->bios.ramcfg_11_03_f0))
                ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000);
 
        ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */
@@ -661,28 +730,28 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
        if (1) {
                mask |= 0x800807e0;
                data |= 0x800807e0;
-               switch (nv_ro08(bios, ramcfg + 0x03) & 0xc0) {
-               case 0xc0: data &= ~0x00000040; break;
-               case 0x80: data &= ~0x00000100; break;
-               case 0x40: data &= ~0x80000000; break;
-               case 0x00: data &= ~0x00000400; break;
+               switch (next->bios.ramcfg_11_03_c0) {
+               case 3: data &= ~0x00000040; break;
+               case 2: data &= ~0x00000100; break;
+               case 1: data &= ~0x80000000; break;
+               case 0: data &= ~0x00000400; break;
                }
 
-               switch (nv_ro08(bios, ramcfg + 0x03) & 0x30) {
-               case 0x30: data &= ~0x00000020; break;
-               case 0x20: data &= ~0x00000080; break;
-               case 0x10: data &= ~0x00080000; break;
-               case 0x00: data &= ~0x00000200; break;
+               switch (next->bios.ramcfg_11_03_30) {
+               case 3: data &= ~0x00000020; break;
+               case 2: data &= ~0x00000080; break;
+               case 1: data &= ~0x00080000; break;
+               case 0: data &= ~0x00000200; break;
                }
        }
 
-       if (nv_ro08(bios, ramcfg + 0x02) & 0x80)
+       if (next->bios.ramcfg_11_02_80)
                mask |= 0x03000000;
-       if (nv_ro08(bios, ramcfg + 0x02) & 0x40)
+       if (next->bios.ramcfg_11_02_40)
                mask |= 0x00002000;
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x10)
+       if (next->bios.ramcfg_11_07_10)
                mask |= 0x00004000;
-       if (nv_ro08(bios, ramcfg + 0x07) & 0x08)
+       if (next->bios.ramcfg_11_07_08)
                mask |= 0x00000003;
        else
                mask |= 0x14000000;
@@ -692,7 +761,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
        ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010010);
        data  = ram_rd32(fuc, 0x1373ec) & ~0x00030000;
-       data |= (nv_ro08(bios, ramcfg + 0x03) & 0x30) << 12;
+       data |= (next->bios.ramcfg_11_03_30) << 12;
        ram_wr32(fuc, 0x1373ec, data);
        ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000000);
        ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000000);
@@ -724,68 +793,67 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
                }
        }
 
-       if ( (nv_ro08(bios, ramcfg + 0x02) & 0x40) ||
-            (nv_ro08(bios, ramcfg + 0x07) & 0x10)) {
+       if ( (next->bios.ramcfg_11_02_40) ||
+            (next->bios.ramcfg_11_07_10)) {
                ram_mask(fuc, 0x132040, 0x00010000, 0x00010000);
                ram_nsec(fuc, 20000);
        }
 
        if (ram->mode != 2) /*XXX*/ {
-               if (nv_ro08(bios, ramcfg + 0x07) & 0x40)
+               if (next->bios.ramcfg_11_07_40)
                        ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000);
        }
 
-       data = (nv_ro08(bios, rammap + 0x11) & 0x0c) >> 2;
-       ram_wr32(fuc, 0x10f65c, 0x00000011 * data);
-       ram_wr32(fuc, 0x10f6b8, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
-       ram_wr32(fuc, 0x10f6bc, 0x01010101 * nv_ro08(bios, ramcfg + 0x09));
+       ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c);
+       ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09);
+       ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09);
 
        mask = 0x00010000;
        data = 0x00000000;
-       if (!(nv_ro08(bios, ramcfg + 0x02) & 0x80))
+       if (!(next->bios.ramcfg_11_02_80))
                data |= 0x03000000;
-       if (!(nv_ro08(bios, ramcfg + 0x02) & 0x40))
+       if (!(next->bios.ramcfg_11_02_40))
                data |= 0x00002000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x10))
+       if (!(next->bios.ramcfg_11_07_10))
                data |= 0x00004000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x08))
+       if (!(next->bios.ramcfg_11_07_08))
                data |= 0x00000003;
        else
                data |= 0x14000000;
        ram_mask(fuc, 0x10f824, mask, data);
        ram_nsec(fuc, 1000);
 
-       if (nv_ro08(bios, ramcfg + 0x08) & 0x01)
+       if (next->bios.ramcfg_11_08_01)
                data = 0x00100000;
        else
                data = 0x00000000;
        ram_mask(fuc, 0x10f82c, 0x00100000, data);
 
        /* PFB timing */
-       ram_mask(fuc, 0x10f248, 0xffffffff, nv_ro32(bios, timing + 0x28));
-       ram_mask(fuc, 0x10f290, 0xffffffff, nv_ro32(bios, timing + 0x00));
-       ram_mask(fuc, 0x10f294, 0xffffffff, nv_ro32(bios, timing + 0x04));
-       ram_mask(fuc, 0x10f298, 0xffffffff, nv_ro32(bios, timing + 0x08));
-       ram_mask(fuc, 0x10f29c, 0xffffffff, nv_ro32(bios, timing + 0x0c));
-       ram_mask(fuc, 0x10f2a0, 0xffffffff, nv_ro32(bios, timing + 0x10));
-       ram_mask(fuc, 0x10f2a4, 0xffffffff, nv_ro32(bios, timing + 0x14));
-       ram_mask(fuc, 0x10f2a8, 0xffffffff, nv_ro32(bios, timing + 0x18));
-       ram_mask(fuc, 0x10f2ac, 0xffffffff, nv_ro32(bios, timing + 0x1c));
-       ram_mask(fuc, 0x10f2cc, 0xffffffff, nv_ro32(bios, timing + 0x20));
-       ram_mask(fuc, 0x10f2e8, 0xffffffff, nv_ro32(bios, timing + 0x24));
+       ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]);
+       ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]);
+       ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]);
+       ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]);
+       ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]);
+       ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]);
+       ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]);
+       ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]);
+       ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]);
+       ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]);
+       ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]);
 
        mask = 0x33f00000;
        data = 0x00000000;
-       if (!(nv_ro08(bios, ramcfg + 0x01) & 0x04))
+       if (!(next->bios.ramcfg_11_01_04))
                data |= 0x20200000;
-       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+       if (!(next->bios.ramcfg_11_07_80))
                data |= 0x12800000;
        /*XXX: see note above about there probably being some condition
         *     for the 10f824 stuff that uses ramcfg 3...
         */
-       if ( (nv_ro08(bios, ramcfg + 0x03) & 0xf0)) {
-               if (nv_ro08(bios, rammap + 0x08) & 0x0c) {
-                       if (!(nv_ro08(bios, ramcfg + 0x07) & 0x80))
+       if ( (next->bios.ramcfg_11_03_f0)) {
+               if (next->bios.rammap_11_08_0c) {
+                       if (!(next->bios.ramcfg_11_07_80))
                                mask |= 0x00000020;
                        else
                                data |= 0x00000020;
@@ -799,21 +867,16 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
        ram_mask(fuc, 0x10f808, mask, data);
 
-       data = nv_ro08(bios, ramcfg + 0x03) & 0x0f;
-       ram_wr32(fuc, 0x10f870, 0x11111111 * data);
+       ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f);
 
-       data = nv_ro16(bios, timing + 0x2c);
-       ram_mask(fuc, 0x10f250, 0x000003f0, (data & 0x003f) <<  4);
+       ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4);
 
-       if (((nv_ro32(bios, timing + 0x2c) & 0x00001fc0) >>  6) >
-           ((nv_ro32(bios, timing + 0x28) & 0x7f000000) >> 24))
-               data = (nv_ro32(bios, timing + 0x2c) & 0x00001fc0) >>  6;
-       else
-               data = (nv_ro32(bios, timing + 0x28) & 0x1f000000) >> 24;
+       data = (next->bios.timing[10] & 0x7f000000) >> 24;
+       if (data < next->bios.timing_20_2c_1fc0)
+               data = next->bios.timing_20_2c_1fc0;
        ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
 
-       data = nv_ro08(bios, timing + 0x30);
-       ram_mask(fuc, 0x10f224, 0x001f0000, (data & 0xf8) << 13);
+       ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8);
 
        ram_wr32(fuc, 0x10f090, 0x4000007f);
        ram_nsec(fuc, 1000);
@@ -855,7 +918,7 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
 
        ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
 
-       if (nv_ro08(bios, rammap + 0x08) & 0x01)
+       if (next->bios.rammap_11_08_01)
                data = 0x00000800;
        else
                data = 0x00000000;
@@ -868,21 +931,18 @@ nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq)
  ******************************************************************************/
 
 static int
-nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
+nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq,
+                  struct nouveau_ram_data *data)
 {
        struct nouveau_bios *bios = nouveau_bios(pfb);
        struct nve0_ram *ram = (void *)pfb->ram;
-       struct nve0_ramfuc *fuc = &ram->fuc;
-       struct bit_entry M;
-       int ret, refclk, strap, i;
-       u32 data;
-       u8  cnt;
+       u8 strap, cnt, len;
 
        /* lookup memory config data relevant to the target frequency */
-       ram->base.rammap.data = nvbios_rammap_match(bios, freq / 1000,
-                                                  &ram->base.rammap.version,
-                                                  &ram->base.rammap.size, &cnt,
-                                                  &ram->base.ramcfg.size);
+       ram->base.rammap.data = nvbios_rammapEp(bios, freq / 1000,
+                                              &ram->base.rammap.version,
+                                              &ram->base.rammap.size,
+                                              &cnt, &len, &data->bios);
        if (!ram->base.rammap.data || ram->base.rammap.version != 0x11 ||
             ram->base.rammap.size < 0x09) {
                nv_error(pfb, "invalid/missing rammap entry\n");
@@ -890,24 +950,13 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        }
 
        /* locate specific data set for the attached memory */
-       if (bit_entry(bios, 'M', &M) || M.version != 2 || M.length < 3) {
-               nv_error(pfb, "invalid/missing memory table\n");
-               return -EINVAL;
-       }
-
-       strap = (nv_rd32(pfb, 0x101000) & 0x0000003c) >> 2;
-       data = nv_ro16(bios, M.offset + 1);
-       if (data)
-               strap = nv_ro08(bios, data + strap);
-
-       if (strap >= cnt) {
-               nv_error(pfb, "invalid ramcfg strap\n");
-               return -EINVAL;
-       }
-
-       ram->base.ramcfg.version = ram->base.rammap.version;
-       ram->base.ramcfg.data = ram->base.rammap.data + ram->base.rammap.size +
-                              (ram->base.ramcfg.size * strap);
+       ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data,
+                                               ram->base.rammap.version,
+                                               ram->base.rammap.size, cnt, len,
+                                               nvbios_ramcfg_index(bios),
+                                               &ram->base.ramcfg.version,
+                                               &ram->base.ramcfg.size,
+                                               &data->bios);
        if (!ram->base.ramcfg.data || ram->base.ramcfg.version != 0x11 ||
             ram->base.ramcfg.size < 0x08) {
                nv_error(pfb, "invalid/missing ramcfg entry\n");
@@ -918,9 +967,9 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        strap = nv_ro08(bios, ram->base.ramcfg.data + 0x00);
        if (strap != 0xff) {
                ram->base.timing.data =
-                       nvbios_timing_entry(bios, strap,
-                                          &ram->base.timing.version,
-                                          &ram->base.timing.size);
+                       nvbios_timingEp(bios, strap, &ram->base.timing.version,
+                                      &ram->base.timing.size, &cnt, &len,
+                                      &data->bios);
                if (!ram->base.timing.data ||
                     ram->base.timing.version != 0x20 ||
                     ram->base.timing.size < 0x33) {
@@ -931,11 +980,23 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
                ram->base.timing.data = 0;
        }
 
+       data->freq = freq;
+       return 0;
+}
+
+static int
+nve0_ram_calc_xits(struct nouveau_fb *pfb, struct nouveau_ram_data *next)
+{
+       struct nve0_ram *ram = (void *)pfb->ram;
+       struct nve0_ramfuc *fuc = &ram->fuc;
+       int refclk, i;
+       int ret;
+
        ret = ram_init(fuc, pfb);
        if (ret)
                return ret;
 
-       ram->mode = (freq > fuc->refpll.vco1.max_freq) ? 2 : 1;
+       ram->mode = (next->freq > fuc->refpll.vco1.max_freq) ? 2 : 1;
        ram->from = ram_rd32(fuc, 0x1373f4) & 0x0000000f;
 
        /* XXX: this is *not* what nvidia do.  on fermi nvidia generally
@@ -946,7 +1007,7 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
         * so far, i've seen very weird values being chosen by nvidia on
         * kepler boards, no idea how/why they're chosen.
         */
-       refclk = freq;
+       refclk = next->freq;
        if (ram->mode == 2)
                refclk = fuc->mempll.refclk;
 
@@ -968,7 +1029,7 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
                fuc->mempll.min_p = 1;
                fuc->mempll.max_p = 2;
 
-               ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, freq,
+               ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, next->freq,
                                   &ram->N2, NULL, &ram->M2, &ram->P2);
                if (ret <= 0) {
                        nv_error(pfb, "unable to calc mempll\n");
@@ -980,17 +1041,18 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
                if (ram_have(fuc, mr[i]))
                        ram->base.mr[i] = ram_rd32(fuc, mr[i]);
        }
+       ram->base.freq = next->freq;
 
        switch (ram->base.type) {
        case NV_MEM_TYPE_DDR3:
                ret = nouveau_sddr3_calc(&ram->base);
                if (ret == 0)
-                       ret = nve0_ram_calc_sddr3(pfb, freq);
+                       ret = nve0_ram_calc_sddr3(pfb, next->freq);
                break;
        case NV_MEM_TYPE_GDDR5:
-               ret = nouveau_gddr5_calc(&ram->base);
+               ret = nouveau_gddr5_calc(&ram->base, ram->pnuts != 0);
                if (ret == 0)
-                       ret = nve0_ram_calc_gddr5(pfb, freq);
+                       ret = nve0_ram_calc_gddr5(pfb, next->freq);
                break;
        default:
                ret = -ENOSYS;
@@ -1000,6 +1062,48 @@ nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
        return ret;
 }
 
+static int
+nve0_ram_calc(struct nouveau_fb *pfb, u32 freq)
+{
+       struct nouveau_clock *clk = nouveau_clock(pfb);
+       struct nve0_ram *ram = (void *)pfb->ram;
+       struct nouveau_ram_data *xits = &ram->base.xition;
+       struct nouveau_ram_data *copy;
+       int ret;
+
+       if (ram->base.next == NULL) {
+               ret = nve0_ram_calc_data(pfb, clk->read(clk, nv_clk_src_mem),
+                                       &ram->base.former);
+               if (ret)
+                       return ret;
+
+               ret = nve0_ram_calc_data(pfb, freq, &ram->base.target);
+               if (ret)
+                       return ret;
+
+               if (ram->base.target.freq < ram->base.former.freq) {
+                       *xits = ram->base.target;
+                       copy = &ram->base.former;
+               } else {
+                       *xits = ram->base.former;
+                       copy = &ram->base.target;
+               }
+
+               xits->bios.ramcfg_11_02_04 = copy->bios.ramcfg_11_02_04;
+               xits->bios.ramcfg_11_02_03 = copy->bios.ramcfg_11_02_03;
+               xits->bios.timing_20_30_07 = copy->bios.timing_20_30_07;
+
+               ram->base.next = &ram->base.target;
+               if (memcmp(xits, &ram->base.former, sizeof(xits->bios)))
+                       ram->base.next = &ram->base.xition;
+       } else {
+               BUG_ON(ram->base.next != &ram->base.xition);
+               ram->base.next = &ram->base.target;
+       }
+
+       return nve0_ram_calc_xits(pfb, ram->base.next);
+}
+
 static int
 nve0_ram_prog(struct nouveau_fb *pfb)
 {
@@ -1007,7 +1111,7 @@ nve0_ram_prog(struct nouveau_fb *pfb)
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
        ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
-       return 0;
+       return (ram->base.next == &ram->base.xition);
 }
 
 static void
@@ -1015,6 +1119,7 @@ nve0_ram_tidy(struct nouveau_fb *pfb)
 {
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
+       ram->base.next = NULL;
        ram_exec(fuc, false);
 }
 
@@ -1055,7 +1160,7 @@ nve0_ram_init(struct nouveau_object *object)
         * binary driver skips the one that's already been setup by
         * the init tables.
         */
-       data = nvbios_rammap_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
+       data = nvbios_rammapTe(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
        if (!data || hdr < 0x15)
                return -EINVAL;
 
@@ -1073,6 +1178,7 @@ nve0_ram_init(struct nouveau_object *object)
                data += 4;
        }
        nv_wr32(pfb, 0x10f65c, save);
+       nv_mask(pfb, 0x10f584, 0x11000000, 0x00000000);
 
        switch (ram->base.type) {
        case NV_MEM_TYPE_GDDR5:
@@ -1117,7 +1223,8 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nouveau_gpio *gpio = nouveau_gpio(pfb);
        struct dcb_gpio_func func;
        struct nve0_ram *ram;
-       int ret;
+       int ret, i;
+       u32 tmp;
 
        ret = nvc0_ram_create(parent, engine, oclass, &ram);
        *pobject = nv_object(ram);
@@ -1136,6 +1243,25 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                break;
        }
 
+       /* calculate a mask of differently configured memory partitions,
+        * because, of course reclocking wasn't complicated enough
+        * already without having to treat some of them differently to
+        * the others....
+        */
+       ram->parts = nv_rd32(pfb, 0x022438);
+       ram->pmask = nv_rd32(pfb, 0x022554);
+       ram->pnuts = 0;
+       for (i = 0, tmp = 0; i < ram->parts; i++) {
+               if (!(ram->pmask & (1 << i))) {
+                       u32 cfg1 = nv_rd32(pfb, 0x110204 + (i * 0x1000));
+                       if (tmp && tmp != cfg1) {
+                               ram->pnuts |= (1 << i);
+                               continue;
+                       }
+                       tmp = cfg1;
+               }
+       }
+
        // parse bios data for both pll's
        ret = nvbios_pll_parse(bios, 0x0c, &ram->fuc.refpll);
        if (ret) {
@@ -1248,7 +1374,7 @@ nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        ram->fuc.r_0x10f65c = ramfuc_reg(0x10f65c);
        ram->fuc.r_0x10f6bc = ramfuc_reg(0x10f6bc);
        ram->fuc.r_0x100710 = ramfuc_reg(0x100710);
-       ram->fuc.r_0x10f750 = ramfuc_reg(0x10f750);
+       ram->fuc.r_0x100750 = ramfuc_reg(0x100750);
        return 0;
 }
 
index 041fd5edaebf7de988206ec6440bdf1950edc938..c33c03d2f4af2f695e50e92078ea18c800d07eec 100644 (file)
@@ -197,7 +197,7 @@ static int
 nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
                     struct nouveau_i2c_board_info *info,
                     bool (*match)(struct nouveau_i2c_port *,
-                                  struct i2c_board_info *))
+                                  struct i2c_board_info *, void *), void *data)
 {
        struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index);
        int i;
@@ -221,7 +221,7 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
                }
 
                if (nv_probe_i2c(port, info[i].dev.addr) &&
-                   (!match || match(port, &info[i].dev))) {
+                   (!match || match(port, &info[i].dev, data))) {
                        nv_info(i2c, "detected %s: %s\n", what,
                                info[i].dev.type);
                        return i;
index 6565f3dbbe04e7e04c0721ad49f3523688f8b729..14706d9842ca6d1428298982e247f1887f11cff6 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include <subdev/instmem.h>
+#include "priv.h"
+
+/******************************************************************************
+ * instmem object base implementation
+ *****************************************************************************/
+
+void
+_nouveau_instobj_dtor(struct nouveau_object *object)
+{
+       struct nouveau_instmem *imem = (void *)object->engine;
+       struct nouveau_instobj *iobj = (void *)object;
+
+       mutex_lock(&nv_subdev(imem)->mutex);
+       list_del(&iobj->head);
+       mutex_unlock(&nv_subdev(imem)->mutex);
+
+       return nouveau_object_destroy(&iobj->base);
+}
 
 int
 nouveau_instobj_create_(struct nouveau_object *parent,
@@ -46,73 +63,26 @@ nouveau_instobj_create_(struct nouveau_object *parent,
        return 0;
 }
 
-void
-nouveau_instobj_destroy(struct nouveau_instobj *iobj)
-{
-       struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine);
+/******************************************************************************
+ * instmem subdev base implementation
+ *****************************************************************************/
 
-       mutex_lock(&subdev->mutex);
-       list_del(&iobj->head);
-       mutex_unlock(&subdev->mutex);
-
-       return nouveau_object_destroy(&iobj->base);
-}
-
-void
-_nouveau_instobj_dtor(struct nouveau_object *object)
+static int
+nouveau_instmem_alloc(struct nouveau_instmem *imem,
+                     struct nouveau_object *parent, u32 size, u32 align,
+                     struct nouveau_object **pobject)
 {
-       struct nouveau_instobj *iobj = (void *)object;
-       return nouveau_instobj_destroy(iobj);
+       struct nouveau_object *engine = nv_object(imem);
+       struct nouveau_instmem_impl *impl = (void *)engine->oclass;
+       struct nouveau_instobj_args args = { .size = size, .align = align };
+       return nouveau_object_ctor(parent, engine, impl->instobj, &args,
+                                  sizeof(args), pobject);
 }
 
 int
-nouveau_instmem_create_(struct nouveau_object *parent,
-                       struct nouveau_object *engine,
-                       struct nouveau_oclass *oclass,
-                       int length, void **pobject)
-{
-       struct nouveau_instmem *imem;
-       int ret;
-
-       ret = nouveau_subdev_create_(parent, engine, oclass, 0,
-                                    "INSTMEM", "instmem", length, pobject);
-       imem = *pobject;
-       if (ret)
-               return ret;
-
-       INIT_LIST_HEAD(&imem->list);
-       return 0;
-}
-
-int
-nouveau_instmem_init(struct nouveau_instmem *imem)
-{
-       struct nouveau_instobj *iobj;
-       int ret, i;
-
-       ret = nouveau_subdev_init(&imem->base);
-       if (ret)
-               return ret;
-
-       mutex_lock(&imem->base.mutex);
-
-       list_for_each_entry(iobj, &imem->list, head) {
-               if (iobj->suspend) {
-                       for (i = 0; i < iobj->size; i += 4)
-                               nv_wo32(iobj, i, iobj->suspend[i / 4]);
-                       vfree(iobj->suspend);
-                       iobj->suspend = NULL;
-               }
-       }
-
-       mutex_unlock(&imem->base.mutex);
-
-       return 0;
-}
-
-int
-nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend)
+_nouveau_instmem_fini(struct nouveau_object *object, bool suspend)
 {
+       struct nouveau_instmem *imem = (void *)object;
        struct nouveau_instobj *iobj;
        int i, ret = 0;
 
@@ -143,12 +113,45 @@ int
 _nouveau_instmem_init(struct nouveau_object *object)
 {
        struct nouveau_instmem *imem = (void *)object;
-       return nouveau_instmem_init(imem);
+       struct nouveau_instobj *iobj;
+       int ret, i;
+
+       ret = nouveau_subdev_init(&imem->base);
+       if (ret)
+               return ret;
+
+       mutex_lock(&imem->base.mutex);
+
+       list_for_each_entry(iobj, &imem->list, head) {
+               if (iobj->suspend) {
+                       for (i = 0; i < iobj->size; i += 4)
+                               nv_wo32(iobj, i, iobj->suspend[i / 4]);
+                       vfree(iobj->suspend);
+                       iobj->suspend = NULL;
+               }
+       }
+
+       mutex_unlock(&imem->base.mutex);
+
+       return 0;
 }
 
 int
-_nouveau_instmem_fini(struct nouveau_object *object, bool suspend)
+nouveau_instmem_create_(struct nouveau_object *parent,
+                       struct nouveau_object *engine,
+                       struct nouveau_oclass *oclass,
+                       int length, void **pobject)
 {
-       struct nouveau_instmem *imem = (void *)object;
-       return nouveau_instmem_fini(imem, suspend);
+       struct nouveau_instmem *imem;
+       int ret;
+
+       ret = nouveau_subdev_create_(parent, engine, oclass, 0,
+                                    "INSTMEM", "instmem", length, pobject);
+       imem = *pobject;
+       if (ret)
+               return ret;
+
+       INIT_LIST_HEAD(&imem->list);
+       imem->alloc = nouveau_instmem_alloc;
+       return 0;
 }
index 795393d7b2f56826c0be783c320867bd14d4336b..7b64befee48fbb5b30b306c980ae53bd077c3368 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include <subdev/fb.h>
-
 #include "nv04.h"
 
+/******************************************************************************
+ * instmem object implementation
+ *****************************************************************************/
+
+static u32
+nv04_instobj_rd32(struct nouveau_object *object, u64 addr)
+{
+       struct nv04_instobj_priv *node = (void *)object;
+       return nv_ro32(object->engine, node->mem->offset + addr);
+}
+
+static void
+nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+       struct nv04_instobj_priv *node = (void *)object;
+       nv_wo32(object->engine, node->mem->offset + addr, data);
+}
+
+static void
+nv04_instobj_dtor(struct nouveau_object *object)
+{
+       struct nv04_instmem_priv *priv = (void *)object->engine;
+       struct nv04_instobj_priv *node = (void *)object;
+       nouveau_mm_free(&priv->heap, &node->mem);
+       nouveau_instobj_destroy(&node->base);
+}
+
 static int
 nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -33,18 +58,19 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 {
        struct nv04_instmem_priv *priv = (void *)engine;
        struct nv04_instobj_priv *node;
-       int ret, align;
+       struct nouveau_instobj_args *args = data;
+       int ret;
 
-       align = (unsigned long)data;
-       if (!align)
-               align = 1;
+       if (!args->align)
+               args->align = 1;
 
        ret = nouveau_instobj_create(parent, engine, oclass, &node);
        *pobject = nv_object(node);
        if (ret)
                return ret;
 
-       ret = nouveau_mm_head(&priv->heap, 1, size, size, align, &node->mem);
+       ret = nouveau_mm_head(&priv->heap, 1, args->size, args->size,
+                             args->align, &node->mem);
        if (ret)
                return ret;
 
@@ -53,32 +79,9 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-static void
-nv04_instobj_dtor(struct nouveau_object *object)
-{
-       struct nv04_instmem_priv *priv = (void *)object->engine;
-       struct nv04_instobj_priv *node = (void *)object;
-       nouveau_mm_free(&priv->heap, &node->mem);
-       nouveau_instobj_destroy(&node->base);
-}
-
-static u32
-nv04_instobj_rd32(struct nouveau_object *object, u64 addr)
-{
-       struct nv04_instobj_priv *node = (void *)object;
-       return nv_ro32(object->engine, node->mem->offset + addr);
-}
-
-static void
-nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-       struct nv04_instobj_priv *node = (void *)object;
-       nv_wo32(object->engine, node->mem->offset + addr, data);
-}
-
-static struct nouveau_oclass
+struct nouveau_instobj_impl
 nv04_instobj_oclass = {
-       .ofuncs = &(struct nouveau_ofuncs) {
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv04_instobj_ctor,
                .dtor = nv04_instobj_dtor,
                .init = _nouveau_instobj_init,
@@ -88,19 +91,34 @@ nv04_instobj_oclass = {
        },
 };
 
-int
-nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent,
-                  u32 size, u32 align, struct nouveau_object **pobject)
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
+static u32
+nv04_instmem_rd32(struct nouveau_object *object, u64 addr)
 {
-       struct nouveau_object *engine = nv_object(imem);
-       int ret;
+       return nv_rd32(object, 0x700000 + addr);
+}
 
-       ret = nouveau_object_ctor(parent, engine, &nv04_instobj_oclass,
-                                 (void *)(unsigned long)align, size, pobject);
-       if (ret)
-               return ret;
+static void
+nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+       return nv_wr32(object, 0x700000 + addr, data);
+}
 
-       return 0;
+void
+nv04_instmem_dtor(struct nouveau_object *object)
+{
+       struct nv04_instmem_priv *priv = (void *)object;
+       nouveau_gpuobj_ref(NULL, &priv->ramfc);
+       nouveau_gpuobj_ref(NULL, &priv->ramro);
+       nouveau_ramht_ref(NULL, &priv->ramht);
+       nouveau_gpuobj_ref(NULL, &priv->vbios);
+       nouveau_mm_fini(&priv->heap);
+       if (priv->iomem)
+               iounmap(priv->iomem);
+       nouveau_instmem_destroy(&priv->base);
 }
 
 static int
@@ -118,7 +136,6 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        /* PRAMIN aperture maps over the end of VRAM, reserve it */
        priv->base.reserved = 512 * 1024;
-       priv->base.alloc    = nv04_instmem_alloc;
 
        ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);
        if (ret)
@@ -150,36 +167,10 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-void
-nv04_instmem_dtor(struct nouveau_object *object)
-{
-       struct nv04_instmem_priv *priv = (void *)object;
-       nouveau_gpuobj_ref(NULL, &priv->ramfc);
-       nouveau_gpuobj_ref(NULL, &priv->ramro);
-       nouveau_ramht_ref(NULL, &priv->ramht);
-       nouveau_gpuobj_ref(NULL, &priv->vbios);
-       nouveau_mm_fini(&priv->heap);
-       if (priv->iomem)
-               iounmap(priv->iomem);
-       nouveau_instmem_destroy(&priv->base);
-}
-
-static u32
-nv04_instmem_rd32(struct nouveau_object *object, u64 addr)
-{
-       return nv_rd32(object, 0x700000 + addr);
-}
-
-static void
-nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-       return nv_wr32(object, 0x700000 + addr, data);
-}
-
-struct nouveau_oclass
-nv04_instmem_oclass = {
-       .handle = NV_SUBDEV(INSTMEM, 0x04),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv04_instmem_oclass = &(struct nouveau_instmem_impl) {
+       .base.handle = NV_SUBDEV(INSTMEM, 0x04),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv04_instmem_ctor,
                .dtor = nv04_instmem_dtor,
                .init = _nouveau_instmem_init,
@@ -187,4 +178,5 @@ nv04_instmem_oclass = {
                .rd32 = nv04_instmem_rd32,
                .wr32 = nv04_instmem_wr32,
        },
-};
+       .instobj = &nv04_instobj_oclass.base,
+}.base;
index b15b61310236608e88a1bc2b89f58b70f3705f48..095fbc6fc099a852bfee334dea9aba389448adcb 100644 (file)
@@ -5,7 +5,9 @@
 #include <core/ramht.h>
 #include <core/mm.h>
 
-#include <subdev/instmem.h>
+#include "priv.h"
+
+extern struct nouveau_instobj_impl nv04_instobj_oclass;
 
 struct nv04_instmem_priv {
        struct nouveau_instmem base;
index b10a143787a7af95af24475f78fa52de7c7a641f..ec0b9661d614ced3dec026e3460d3eeb07905f2e 100644 (file)
 
 #include "nv04.h"
 
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
+static u32
+nv40_instmem_rd32(struct nouveau_object *object, u64 addr)
+{
+       struct nv04_instmem_priv *priv = (void *)object;
+       return ioread32_native(priv->iomem + addr);
+}
+
+static void
+nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+       struct nv04_instmem_priv *priv = (void *)object;
+       iowrite32_native(data, priv->iomem + addr);
+}
+
 static int
 nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                  struct nouveau_oclass *oclass, void *data, u32 size,
@@ -69,7 +87,6 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->base.reserved += 512 * 1024;      /* object storage */
 
        priv->base.reserved = round_up(priv->base.reserved, 4096);
-       priv->base.alloc    = nv04_instmem_alloc;
 
        ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);
        if (ret)
@@ -106,24 +123,10 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        return 0;
 }
 
-static u32
-nv40_instmem_rd32(struct nouveau_object *object, u64 addr)
-{
-       struct nv04_instmem_priv *priv = (void *)object;
-       return ioread32_native(priv->iomem + addr);
-}
-
-static void
-nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data)
-{
-       struct nv04_instmem_priv *priv = (void *)object;
-       iowrite32_native(data, priv->iomem + addr);
-}
-
-struct nouveau_oclass
-nv40_instmem_oclass = {
-       .handle = NV_SUBDEV(INSTMEM, 0x40),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv40_instmem_oclass = &(struct nouveau_instmem_impl) {
+       .base.handle = NV_SUBDEV(INSTMEM, 0x40),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv40_instmem_ctor,
                .dtor = nv04_instmem_dtor,
                .init = _nouveau_instmem_init,
@@ -131,4 +134,5 @@ nv40_instmem_oclass = {
                .rd32 = nv40_instmem_rd32,
                .wr32 = nv40_instmem_wr32,
        },
-};
+       .instobj = &nv04_instobj_oclass.base,
+}.base;
index 97bc5dff93e7aa224643c0cb5422faa15adb9e36..7cb3b098a08d030d7d315a1642ebf6a167033ffe 100644 (file)
  * Authors: Ben Skeggs
  */
 
-#include <subdev/instmem.h>
 #include <subdev/fb.h>
-
 #include <core/mm.h>
 
+#include "priv.h"
+
 struct nv50_instmem_priv {
        struct nouveau_instmem base;
        spinlock_t lock;
@@ -38,42 +38,9 @@ struct nv50_instobj_priv {
        struct nouveau_mem *mem;
 };
 
-static int
-nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-                 struct nouveau_oclass *oclass, void *data, u32 size,
-                 struct nouveau_object **pobject)
-{
-       struct nouveau_fb *pfb = nouveau_fb(parent);
-       struct nv50_instobj_priv *node;
-       u32 align = (unsigned long)data;
-       int ret;
-
-       size  = max((size  + 4095) & ~4095, (u32)4096);
-       align = max((align + 4095) & ~4095, (u32)4096);
-
-       ret = nouveau_instobj_create(parent, engine, oclass, &node);
-       *pobject = nv_object(node);
-       if (ret)
-               return ret;
-
-       ret = pfb->ram->get(pfb, size, align, 0, 0x800, &node->mem);
-       if (ret)
-               return ret;
-
-       node->base.addr = node->mem->offset;
-       node->base.size = node->mem->size << 12;
-       node->mem->page_shift = 12;
-       return 0;
-}
-
-static void
-nv50_instobj_dtor(struct nouveau_object *object)
-{
-       struct nv50_instobj_priv *node = (void *)object;
-       struct nouveau_fb *pfb = nouveau_fb(object);
-       pfb->ram->put(pfb, &node->mem);
-       nouveau_instobj_destroy(&node->base);
-}
+/******************************************************************************
+ * instmem object implementation
+ *****************************************************************************/
 
 static u32
 nv50_instobj_rd32(struct nouveau_object *object, u64 offset)
@@ -113,9 +80,46 @@ nv50_instobj_wr32(struct nouveau_object *object, u64 offset, u32 data)
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static struct nouveau_oclass
+static void
+nv50_instobj_dtor(struct nouveau_object *object)
+{
+       struct nv50_instobj_priv *node = (void *)object;
+       struct nouveau_fb *pfb = nouveau_fb(object);
+       pfb->ram->put(pfb, &node->mem);
+       nouveau_instobj_destroy(&node->base);
+}
+
+static int
+nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+                 struct nouveau_oclass *oclass, void *data, u32 size,
+                 struct nouveau_object **pobject)
+{
+       struct nouveau_fb *pfb = nouveau_fb(parent);
+       struct nouveau_instobj_args *args = data;
+       struct nv50_instobj_priv *node;
+       int ret;
+
+       args->size  = max((args->size  + 4095) & ~4095, (u32)4096);
+       args->align = max((args->align + 4095) & ~4095, (u32)4096);
+
+       ret = nouveau_instobj_create(parent, engine, oclass, &node);
+       *pobject = nv_object(node);
+       if (ret)
+               return ret;
+
+       ret = pfb->ram->get(pfb, args->size, args->align, 0, 0x800, &node->mem);
+       if (ret)
+               return ret;
+
+       node->base.addr = node->mem->offset;
+       node->base.size = node->mem->size << 12;
+       node->mem->page_shift = 12;
+       return 0;
+}
+
+static struct nouveau_instobj_impl
 nv50_instobj_oclass = {
-       .ofuncs = &(struct nouveau_ofuncs) {
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv50_instobj_ctor,
                .dtor = nv50_instobj_dtor,
                .init = _nouveau_instobj_init,
@@ -125,13 +129,16 @@ nv50_instobj_oclass = {
        },
 };
 
+/******************************************************************************
+ * instmem subdev implementation
+ *****************************************************************************/
+
 static int
-nv50_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent,
-                  u32 size, u32 align, struct nouveau_object **pobject)
+nv50_instmem_fini(struct nouveau_object *object, bool suspend)
 {
-       struct nouveau_object *engine = nv_object(imem);
-       return nouveau_object_ctor(parent, engine, &nv50_instobj_oclass,
-                                  (void *)(unsigned long)align, size, pobject);
+       struct nv50_instmem_priv *priv = (void *)object;
+       priv->addr = ~0ULL;
+       return nouveau_instmem_fini(&priv->base, suspend);
 }
 
 static int
@@ -148,25 +155,17 @@ nv50_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        spin_lock_init(&priv->lock);
-       priv->base.alloc = nv50_instmem_alloc;
        return 0;
 }
 
-static int
-nv50_instmem_fini(struct nouveau_object *object, bool suspend)
-{
-       struct nv50_instmem_priv *priv = (void *)object;
-       priv->addr = ~0ULL;
-       return nouveau_instmem_fini(&priv->base, suspend);
-}
-
-struct nouveau_oclass
-nv50_instmem_oclass = {
-       .handle = NV_SUBDEV(INSTMEM, 0x50),
-       .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv50_instmem_oclass = &(struct nouveau_instmem_impl) {
+       .base.handle = NV_SUBDEV(INSTMEM, 0x50),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = nv50_instmem_ctor,
                .dtor = _nouveau_instmem_dtor,
                .init = _nouveau_instmem_init,
                .fini = nv50_instmem_fini,
        },
-};
+       .instobj = &nv50_instobj_oclass.base,
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h
new file mode 100644 (file)
index 0000000..8d67ded
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __NVKM_INSTMEM_PRIV_H__
+#define __NVKM_INSTMEM_PRIV_H__
+
+#include <subdev/instmem.h>
+
+struct nouveau_instobj_impl {
+       struct nouveau_oclass base;
+};
+
+struct nouveau_instobj_args {
+       u32 size;
+       u32 align;
+};
+
+#define nouveau_instobj_create(p,e,o,d)                                        \
+       nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_instobj_destroy(p) ({                                          \
+       struct nouveau_instobj *iobj = (p);                                    \
+       _nouveau_instobj_dtor(nv_object(iobj));                                \
+})
+#define nouveau_instobj_init(p)                                                \
+       nouveau_object_init(&(p)->base)
+#define nouveau_instobj_fini(p,s)                                              \
+       nouveau_object_fini(&(p)->base, (s))
+
+int  nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *,
+                            struct nouveau_oclass *, int, void **);
+void _nouveau_instobj_dtor(struct nouveau_object *);
+#define _nouveau_instobj_init nouveau_object_init
+#define _nouveau_instobj_fini nouveau_object_fini
+
+struct nouveau_instmem_impl {
+       struct nouveau_oclass base;
+       struct nouveau_oclass *instobj;
+};
+
+#define nouveau_instmem_create(p,e,o,d)                                        \
+       nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d)
+#define nouveau_instmem_destroy(p)                                             \
+       nouveau_subdev_destroy(&(p)->base)
+#define nouveau_instmem_init(p) ({                                             \
+       struct nouveau_instmem *imem = (p);                                    \
+       _nouveau_instmem_init(nv_object(imem));                                \
+})
+#define nouveau_instmem_fini(p,s) ({                                           \
+       struct nouveau_instmem *imem = (p);                                    \
+       _nouveau_instmem_fini(nv_object(imem), (s));                           \
+})
+
+int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *,
+                           struct nouveau_oclass *, int, void **);
+#define _nouveau_instmem_dtor _nouveau_subdev_dtor
+int _nouveau_instmem_init(struct nouveau_object *);
+int _nouveau_instmem_fini(struct nouveau_object *, bool);
+
+#endif
index c02b4763a2d50e40db65cf2a8a247f2e8374cd3f..34472d3170974ca8e6207afe0a347f332130d6bd 100644 (file)
@@ -32,6 +32,7 @@ nvc0_mc_intr[] = {
        { 0x00000080, NVDEV_ENGINE_COPY2 },
        { 0x00000100, NVDEV_ENGINE_FIFO },
        { 0x00001000, NVDEV_ENGINE_GR },
+       { 0x00002000, NVDEV_SUBDEV_FB },
        { 0x00008000, NVDEV_ENGINE_BSP },
        { 0x00040000, NVDEV_SUBDEV_THERM },
        { 0x00020000, NVDEV_ENGINE_VP },
@@ -40,6 +41,7 @@ nvc0_mc_intr[] = {
        { 0x01000000, NVDEV_SUBDEV_PWR },
        { 0x02000000, NVDEV_SUBDEV_LTCG },
        { 0x04000000, NVDEV_ENGINE_DISP },
+       { 0x08000000, NVDEV_SUBDEV_FB },
        { 0x10000000, NVDEV_SUBDEV_BUS },
        { 0x40000000, NVDEV_SUBDEV_IBUS },
        { 0x80000000, NVDEV_ENGINE_SW },
index af129c2e811388adbb3129a0f76f9648eb669658..64f8b4702bf7272c3edf7950e16bf46b07d5457a 100644 (file)
@@ -100,7 +100,7 @@ mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info)
 static int
 mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb)
 {
-       struct nouveau_mxm *mxm = nouveau_mxm(bios);
+       struct nouveau_mxm *mxm = data;
        struct context ctx = { .outp = (u32 *)(bios->data + pdcb) };
        u8 type, i2cidx, link, ver, len;
        u8 *conn;
@@ -199,7 +199,7 @@ mxm_dcb_sanitise(struct nouveau_mxm *mxm)
                return;
        }
 
-       dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry);
+       dcb_outp_foreach(bios, mxm, mxm_dcb_sanitise_entry);
        mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL);
 }
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc
new file mode 100644 (file)
index 0000000..757dda7
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#define T_TIMEOUT  2200000
+#define T_RISEFALL 1000
+#define T_HOLD     5000
+
+#ifdef INCLUDE_PROC
+process(PROC_I2C_, #i2c_init, #i2c_recv)
+#endif
+
+/******************************************************************************
+ * I2C_ data segment
+ *****************************************************************************/
+#ifdef INCLUDE_DATA
+i2c_scl_map:
+.b32 NV_PPWR_OUTPUT_I2C_0_SCL
+.b32 NV_PPWR_OUTPUT_I2C_1_SCL
+.b32 NV_PPWR_OUTPUT_I2C_2_SCL
+.b32 NV_PPWR_OUTPUT_I2C_3_SCL
+.b32 NV_PPWR_OUTPUT_I2C_4_SCL
+.b32 NV_PPWR_OUTPUT_I2C_5_SCL
+.b32 NV_PPWR_OUTPUT_I2C_6_SCL
+.b32 NV_PPWR_OUTPUT_I2C_7_SCL
+.b32 NV_PPWR_OUTPUT_I2C_8_SCL
+.b32 NV_PPWR_OUTPUT_I2C_9_SCL
+i2c_sda_map:
+.b32 NV_PPWR_OUTPUT_I2C_0_SDA
+.b32 NV_PPWR_OUTPUT_I2C_1_SDA
+.b32 NV_PPWR_OUTPUT_I2C_2_SDA
+.b32 NV_PPWR_OUTPUT_I2C_3_SDA
+.b32 NV_PPWR_OUTPUT_I2C_4_SDA
+.b32 NV_PPWR_OUTPUT_I2C_5_SDA
+.b32 NV_PPWR_OUTPUT_I2C_6_SDA
+.b32 NV_PPWR_OUTPUT_I2C_7_SDA
+.b32 NV_PPWR_OUTPUT_I2C_8_SDA
+.b32 NV_PPWR_OUTPUT_I2C_9_SDA
+#if NVKM_PPWR_CHIPSET < GF119
+i2c_ctrl:
+.b32 0x00e138
+.b32 0x00e150
+.b32 0x00e168
+.b32 0x00e180
+.b32 0x00e254
+.b32 0x00e274
+.b32 0x00e764
+.b32 0x00e780
+.b32 0x00e79c
+.b32 0x00e7b8
+#endif
+#endif
+
+/******************************************************************************
+ * I2C_ code segment
+ *****************************************************************************/
+#ifdef INCLUDE_CODE
+
+// $r3  - value
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_drive_scl:
+       cmp b32 $r3 0
+       bra e #i2c_drive_scl_lo
+       nv_iowr(NV_PPWR_OUTPUT_SET, $r1)
+       ret
+       i2c_drive_scl_lo:
+       nv_iowr(NV_PPWR_OUTPUT_CLR, $r1)
+       ret
+
+i2c_drive_sda:
+       cmp b32 $r3 0
+       bra e #i2c_drive_sda_lo
+       nv_iowr(NV_PPWR_OUTPUT_SET, $r2)
+       ret
+       i2c_drive_sda_lo:
+       nv_iowr(NV_PPWR_OUTPUT_CLR, $r2)
+       ret
+
+i2c_sense_scl:
+       bclr $flags $p1
+       nv_iord($r3, NV_PPWR_INPUT)
+       and $r3 $r1
+       bra z #i2c_sense_scl_done
+               bset $flags $p1
+       i2c_sense_scl_done:
+       ret
+
+i2c_sense_sda:
+       bclr $flags $p1
+       nv_iord($r3, NV_PPWR_INPUT)
+       and $r3 $r2
+       bra z #i2c_sense_sda_done
+               bset $flags $p1
+       i2c_sense_sda_done:
+       ret
+
+#define i2c_drive_scl(v) /*
+*/     mov $r3 (v) /*
+*/     call(i2c_drive_scl)
+#define i2c_drive_sda(v) /*
+*/     mov $r3 (v) /*
+*/     call(i2c_drive_sda)
+#define i2c_sense_scl() /*
+*/     call(i2c_sense_scl)
+#define i2c_sense_sda() /*
+*/     call(i2c_sense_sda)
+#define i2c_delay(v) /*
+*/     mov $r14 (v) /*
+*/     call(nsec)
+
+#define i2c_trace_init() /*
+*/     imm32($r6, 0x10000000) /*
+*/     sub b32 $r7 $r6 1 /*
+*/
+#define i2c_trace_down() /*
+*/     shr b32 $r6 4 /*
+*/     push $r5 /*
+*/     shl b32 $r5 $r6 4 /*
+*/     sub b32 $r5 $r6 /*
+*/     not b32 $r5 /*
+*/     and $r7 $r5 /*
+*/     pop $r5 /*
+*/
+#define i2c_trace_exit() /*
+*/     shl b32 $r6 4 /*
+*/
+#define i2c_trace_next() /*
+*/     add b32 $r7 $r6 /*
+*/
+#define i2c_trace_call(func) /*
+*/     i2c_trace_next() /*
+*/     i2c_trace_down() /*
+*/     call(func) /*
+*/     i2c_trace_exit() /*
+*/
+
+i2c_raise_scl:
+       push $r4
+       mov $r4 (T_TIMEOUT / T_RISEFALL)
+       i2c_drive_scl(1)
+       i2c_raise_scl_wait:
+               i2c_delay(T_RISEFALL)
+               i2c_sense_scl()
+               bra $p1 #i2c_raise_scl_done
+               sub b32 $r4 1
+               bra nz #i2c_raise_scl_wait
+       i2c_raise_scl_done:
+       pop $r4
+       ret
+
+i2c_start:
+       i2c_sense_scl()
+       bra not $p1 #i2c_start_rep
+       i2c_sense_sda()
+       bra not $p1 #i2c_start_rep
+       bra #i2c_start_send
+       i2c_start_rep:
+               i2c_drive_scl(0)
+               i2c_drive_sda(1)
+               i2c_trace_call(i2c_raise_scl)
+               bra not $p1 #i2c_start_out
+       i2c_start_send:
+       i2c_drive_sda(0)
+       i2c_delay(T_HOLD)
+       i2c_drive_scl(0)
+       i2c_delay(T_HOLD)
+       i2c_start_out:
+       ret
+
+i2c_stop:
+       i2c_drive_scl(0)
+       i2c_drive_sda(0)
+       i2c_delay(T_RISEFALL)
+       i2c_drive_scl(1)
+       i2c_delay(T_HOLD)
+       i2c_drive_sda(1)
+       i2c_delay(T_HOLD)
+       ret
+
+// $r3  - value
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_bitw:
+       call(i2c_drive_sda)
+       i2c_delay(T_RISEFALL)
+       i2c_trace_call(i2c_raise_scl)
+       bra not $p1 #i2c_bitw_out
+       i2c_delay(T_HOLD)
+       i2c_drive_scl(0)
+       i2c_delay(T_HOLD)
+       i2c_bitw_out:
+       ret
+
+// $r3  - value (out)
+// $r2  - sda line
+// $r1  - scl line
+// $r0  - zero
+i2c_bitr:
+       i2c_drive_sda(1)
+       i2c_delay(T_RISEFALL)
+       i2c_trace_call(i2c_raise_scl)
+       bra not $p1 #i2c_bitr_done
+       i2c_sense_sda()
+       i2c_drive_scl(0)
+       i2c_delay(T_HOLD)
+       xbit $r3 $flags $p1
+       bset $flags $p1
+       i2c_bitr_done:
+       ret
+
+i2c_get_byte:
+       mov $r5 0
+       mov $r4 8
+       i2c_get_byte_next:
+               shl b32 $r5 1
+               i2c_trace_call(i2c_bitr)
+               bra not $p1 #i2c_get_byte_done
+               or $r5 $r3
+               sub b32 $r4 1
+               bra nz #i2c_get_byte_next
+       mov $r3 1
+       i2c_trace_call(i2c_bitw)
+       i2c_get_byte_done:
+       ret
+
+i2c_put_byte:
+       mov $r4 8
+       i2c_put_byte_next:
+               sub b32 $r4 1
+               xbit $r3 $r5 $r4
+               i2c_trace_call(i2c_bitw)
+               bra not $p1 #i2c_put_byte_done
+               cmp b32 $r4 0
+               bra ne #i2c_put_byte_next
+       i2c_trace_call(i2c_bitr)
+       bra not $p1 #i2c_put_byte_done
+       i2c_trace_next()
+       cmp b32 $r3 1
+       bra ne #i2c_put_byte_done
+       bclr $flags $p1 // nack
+       i2c_put_byte_done:
+       ret
+
+i2c_addr:
+       i2c_trace_call(i2c_start)
+       bra not $p1 #i2c_addr_done
+       extr $r3 $r12 I2C__MSG_DATA0_ADDR
+       shl b32 $r3 1
+       or $r5 $r3
+       i2c_trace_call(i2c_put_byte)
+       i2c_addr_done:
+       ret
+
+i2c_acquire_addr:
+       extr $r14 $r12 I2C__MSG_DATA0_PORT
+#if NVKM_PPWR_CHIPSET < GF119
+       shl b32 $r14 2
+       add b32 $r14 #i2c_ctrl
+       ld b32 $r14 D[$r14]
+#else
+       shl b32 $r14 5
+       add b32 $r14 0x00d014
+#endif
+       ret
+
+i2c_acquire:
+       call(i2c_acquire_addr)
+       call(rd32)
+       bset $r13 3
+       call(wr32)
+       ret
+
+i2c_release:
+       call(i2c_acquire_addr)
+       call(rd32)
+       bclr $r13 3
+       call(wr32)
+       ret
+
+// description
+//
+// $r15 - current (i2c)
+// $r14 - sender process name
+// $r13 - message
+// $r12 - data0
+// $r11 - data1
+// $r0  - zero
+i2c_recv:
+       bclr $flags $p1
+       extr $r1 $r12 I2C__MSG_DATA0_PORT
+       shl b32 $r1 2
+       cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map)
+       bra ge #i2c_recv_done
+       add b32 $r3 $r1 #i2c_sda_map
+       ld b32 $r2 D[$r3]
+       add b32 $r3 $r1 #i2c_scl_map
+       ld b32 $r1 D[$r3]
+
+       bset $flags $p2
+       push $r13
+       push $r14
+
+       push $r13
+       i2c_trace_init()
+       i2c_trace_call(i2c_acquire)
+       pop $r13
+
+       cmp b32 $r13 I2C__MSG_RD08
+       bra ne #i2c_recv_not_rd08
+               mov $r5 0
+               i2c_trace_call(i2c_addr)
+               bra not $p1 #i2c_recv_done
+               extr $r5 $r12 I2C__MSG_DATA0_RD08_REG
+               i2c_trace_call(i2c_put_byte)
+               bra not $p1 #i2c_recv_done
+               mov $r5 1
+               i2c_trace_call(i2c_addr)
+               bra not $p1 #i2c_recv_done
+               i2c_trace_call(i2c_get_byte)
+               bra not $p1 #i2c_recv_done
+               ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL
+               i2c_trace_call(i2c_stop)
+               mov b32 $r11 $r5
+               clear b32 $r7
+               bra #i2c_recv_done
+
+       i2c_recv_not_rd08:
+       cmp b32 $r13 I2C__MSG_WR08
+       bra ne #i2c_recv_not_wr08
+               mov $r5 0
+               call(i2c_addr)
+               bra not $p1 #i2c_recv_done
+               extr $r5 $r12 I2C__MSG_DATA0_WR08_REG
+               call(i2c_put_byte)
+               bra not $p1 #i2c_recv_done
+               mov $r5 0
+               call(i2c_addr)
+               bra not $p1 #i2c_recv_done
+               extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL
+               call(i2c_put_byte)
+               bra not $p1 #i2c_recv_done
+               call(i2c_stop)
+               clear b32 $r7
+               extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC
+               bra nz #i2c_recv_done
+               bclr $flags $p2
+               bra #i2c_recv_done
+
+       i2c_recv_not_wr08:
+
+       i2c_recv_done:
+       extr $r14 $r12 I2C__MSG_DATA0_PORT
+       call(i2c_release)
+
+       pop $r14
+       pop $r13
+       bra not $p2 #i2c_recv_exit
+       mov b32 $r12 $r7
+       call(send)
+
+       i2c_recv_exit:
+       ret
+
+// description
+//
+// $r15 - current (i2c)
+// $r0  - zero
+i2c_init:
+       ret
+#endif
index 0a7b05fa5c1112ab4f172ca39a5d66fd1de7ead2..8f29badd785f16f9cd37cff7adf19d03f1aafc44 100644 (file)
@@ -51,12 +51,12 @@ time_next: .b32 0
 // $r0  - zero
 rd32:
        nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
-       mov $r14 NV_PPWR_MMIO_CTRL_OP_RD
-       sethi $r14 NV_PPWR_MMIO_CTRL_TRIGGER
-       nv_iowr(NV_PPWR_MMIO_CTRL, $r14)
+       mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
+       sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
+       nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
        rd32_wait:
-               nv_iord($r14, NV_PPWR_MMIO_CTRL)
-               and $r14 NV_PPWR_MMIO_CTRL_STATUS
+               nv_iord($r13, NV_PPWR_MMIO_CTRL)
+               and $r13 NV_PPWR_MMIO_CTRL_STATUS
                bra nz #rd32_wait
        nv_iord($r13, NV_PPWR_MMIO_DATA)
        ret
@@ -70,23 +70,25 @@ rd32:
 wr32:
        nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
        nv_iowr(NV_PPWR_MMIO_DATA, $r13)
-       mov $r14 NV_PPWR_MMIO_CTRL_OP_WR
-       or $r14 NV_PPWR_MMIO_CTRL_MASK_B32_0
-       sethi $r14 NV_PPWR_MMIO_CTRL_TRIGGER
+       mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
+       or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
+       sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
 
 #ifdef NVKM_FALCON_MMIO_TRAP
-       mov $r8 NV_PPWR_INTR_TRIGGER_USER1
-       nv_iowr(NV_PPWR_INTR_TRIGGER, $r8)
+       push $r13
+       mov $r13 NV_PPWR_INTR_TRIGGER_USER1
+       nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
        wr32_host:
-               nv_iord($r8, NV_PPWR_INTR)
-               and $r8 NV_PPWR_INTR_USER1
+               nv_iord($r13, NV_PPWR_INTR)
+               and $r13 NV_PPWR_INTR_USER1
                bra nz #wr32_host
+       pop $r13
 #endif
 
-       nv_iowr(NV_PPWR_MMIO_CTRL, $r14)
+       nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
        wr32_wait:
-               nv_iord($r14, NV_PPWR_MMIO_CTRL)
-               and $r14 NV_PPWR_MMIO_CTRL_STATUS
+               nv_iord($r13, NV_PPWR_MMIO_CTRL)
+               and $r13 NV_PPWR_MMIO_CTRL_STATUS
                bra nz #wr32_wait
        ret
 
index 2a74ea90760430624d6bb369b02e5a575ad75c5d..e2a63ac5422b8180e4e21cd77e622f688900e4ad 100644 (file)
 #define NV_PPWR_MMIO_CTRL_OP_WR                                      0x00000002
 #define NV_PPWR_OUTPUT                                                   0x07c0
 #define NV_PPWR_OUTPUT_FB_PAUSE                                      0x00000004
+#if NVKM_PPWR_CHIPSET < GF119
+#define NV_PPWR_OUTPUT_I2C_3_SCL                                     0x00000100
+#define NV_PPWR_OUTPUT_I2C_3_SDA                                     0x00000200
+#define NV_PPWR_OUTPUT_I2C_0_SCL                                     0x00001000
+#define NV_PPWR_OUTPUT_I2C_0_SDA                                     0x00002000
+#define NV_PPWR_OUTPUT_I2C_1_SCL                                     0x00004000
+#define NV_PPWR_OUTPUT_I2C_1_SDA                                     0x00008000
+#define NV_PPWR_OUTPUT_I2C_2_SCL                                     0x00010000
+#define NV_PPWR_OUTPUT_I2C_2_SDA                                     0x00020000
+#define NV_PPWR_OUTPUT_I2C_4_SCL                                     0x00040000
+#define NV_PPWR_OUTPUT_I2C_4_SDA                                     0x00080000
+#define NV_PPWR_OUTPUT_I2C_5_SCL                                     0x00100000
+#define NV_PPWR_OUTPUT_I2C_5_SDA                                     0x00200000
+#define NV_PPWR_OUTPUT_I2C_6_SCL                                     0x00400000
+#define NV_PPWR_OUTPUT_I2C_6_SDA                                     0x00800000
+#define NV_PPWR_OUTPUT_I2C_7_SCL                                     0x01000000
+#define NV_PPWR_OUTPUT_I2C_7_SDA                                     0x02000000
+#define NV_PPWR_OUTPUT_I2C_8_SCL                                     0x04000000
+#define NV_PPWR_OUTPUT_I2C_8_SDA                                     0x08000000
+#define NV_PPWR_OUTPUT_I2C_9_SCL                                     0x10000000
+#define NV_PPWR_OUTPUT_I2C_9_SDA                                     0x20000000
+#else
+#define NV_PPWR_OUTPUT_I2C_0_SCL                                     0x00000400
+#define NV_PPWR_OUTPUT_I2C_1_SCL                                     0x00000800
+#define NV_PPWR_OUTPUT_I2C_2_SCL                                     0x00001000
+#define NV_PPWR_OUTPUT_I2C_3_SCL                                     0x00002000
+#define NV_PPWR_OUTPUT_I2C_4_SCL                                     0x00004000
+#define NV_PPWR_OUTPUT_I2C_5_SCL                                     0x00008000
+#define NV_PPWR_OUTPUT_I2C_6_SCL                                     0x00010000
+#define NV_PPWR_OUTPUT_I2C_7_SCL                                     0x00020000
+#define NV_PPWR_OUTPUT_I2C_8_SCL                                     0x00040000
+#define NV_PPWR_OUTPUT_I2C_9_SCL                                     0x00080000
+#define NV_PPWR_OUTPUT_I2C_0_SDA                                     0x00100000
+#define NV_PPWR_OUTPUT_I2C_1_SDA                                     0x00200000
+#define NV_PPWR_OUTPUT_I2C_2_SDA                                     0x00400000
+#define NV_PPWR_OUTPUT_I2C_3_SDA                                     0x00800000
+#define NV_PPWR_OUTPUT_I2C_4_SDA                                     0x01000000
+#define NV_PPWR_OUTPUT_I2C_5_SDA                                     0x02000000
+#define NV_PPWR_OUTPUT_I2C_6_SDA                                     0x04000000
+#define NV_PPWR_OUTPUT_I2C_7_SDA                                     0x08000000
+#define NV_PPWR_OUTPUT_I2C_8_SDA                                     0x10000000
+#define NV_PPWR_OUTPUT_I2C_9_SDA                                     0x20000000
+#endif
+#define NV_PPWR_INPUT                                                    0x07c4
 #define NV_PPWR_OUTPUT_SET                                               0x07e0
 #define NV_PPWR_OUTPUT_SET_FB_PAUSE                                  0x00000004
 #define NV_PPWR_OUTPUT_CLR                                               0x07e4
 */     .b32 0 /*
 */     .skip 64
 
+#if NV_PPWR_CHIPSET < GK208
+#define imm32(reg,val) /*
+*/     movw reg  ((val) & 0x0000ffff) /*
+*/     sethi reg ((val) & 0xffff0000)
+#else
+#define imm32(reg,val) /*
+*/     mov reg (val)
+#endif
+
 #ifndef NVKM_FALCON_UNSHIFTED_IO
 #define nv_iord(reg,ior) /*
 */     mov reg ior /*
index 947be536daefcb6031723f3d5e8eb2638c29eb47..17a8a383d91a91929c2eebad9ef1f531861c6800 100644 (file)
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
index 9342e2d7d3b7909b94f5cc02ead4c80d1e9e3e9b..4bd43a99fdccbe3d2cde12233644f18bda7561c0 100644 (file)
@@ -89,16 +89,9 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-       0x54534554,
-       0x00000494,
-       0x00000475,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x5f433249,
+       0x00000877,
+       0x0000071e,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -111,16 +104,6 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-       0x454c4449,
-       0x0000049f,
-       0x0000049d,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -128,17 +111,16 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x54534554,
+       0x00000898,
+       0x00000879,
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
        0x00000000,
-/* 0x0214: time_next */
        0x00000000,
-/* 0x0218: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -151,6 +133,9 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x454c4449,
+       0x000008a3,
+       0x000008a1,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -170,9 +155,12 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
        0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x026c: time_next */
        0x00000000,
+/* 0x0270: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -204,31 +192,8 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0318: memx_func_head */
-       0x00010000,
-       0x00000000,
-       0x000003a9,
-/* 0x0324: memx_func_next */
-       0x00000001,
-       0x00000000,
-       0x000003c7,
-       0x00000002,
-       0x00000002,
-       0x000003df,
-       0x00040003,
-       0x00000000,
-       0x00000407,
-       0x00010004,
-       0x00000000,
-       0x00000421,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
        0x00000000,
+/* 0x02f0: rfifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -261,10 +226,25 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0370: memx_func_head */
+       0x00010000,
        0x00000000,
+       0x000003a9,
+/* 0x037c: memx_func_next */
+       0x00000001,
        0x00000000,
+       0x000003c7,
+       0x00000002,
+       0x00000002,
+       0x000003df,
+       0x00040003,
        0x00000000,
+       0x00000407,
+       0x00010004,
        0x00000000,
+       0x00000421,
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -735,7 +715,6 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0b54: memx_data_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -778,6 +757,29 @@ uint32_t nv108_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+       0x00000400,
+       0x00000800,
+       0x00001000,
+       0x00002000,
+       0x00004000,
+       0x00008000,
+       0x00010000,
+       0x00020000,
+       0x00040000,
+       0x00080000,
+/* 0x0bd4: i2c_sda_map */
+       0x00100000,
+       0x00200000,
+       0x00400000,
+       0x00800000,
+       0x01000000,
+       0x02000000,
+       0x04000000,
+       0x08000000,
+       0x10000000,
+       0x20000000,
        0x00000000,
 };
 
@@ -786,13 +788,13 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0004: rd32 */
        0xf607a040,
        0x04bd000e,
-       0xe3f0010e,
+       0xd3f0010d,
        0x07ac4001,
-       0xbd000ef6,
+       0xbd000df6,
 /* 0x0019: rd32_wait */
-       0x07ac4e04,
-       0xf100eecf,
-       0xf47000e4,
+       0x07ac4d04,
+       0xf100ddcf,
+       0xf47000d4,
        0xa44df61b,
        0x00ddcf07,
 /* 0x002e: wr32 */
@@ -800,14 +802,14 @@ uint32_t nv108_pwr_code[] = {
        0x000ef607,
        0xa44004bd,
        0x000df607,
-       0x020e04bd,
-       0xf0f0e5f0,
-       0xac4001e3,
-       0x000ef607,
+       0x020d04bd,
+       0xf0f0d5f0,
+       0xac4001d3,
+       0x000df607,
 /* 0x004e: wr32_wait */
-       0xac4e04bd,
-       0x00eecf07,
-       0x7000e4f1,
+       0xac4d04bd,
+       0x00ddcf07,
+       0x7000d4f1,
        0xf8f61bf4,
 /* 0x005d: nsec */
        0xcf2c0800,
@@ -832,20 +834,20 @@ uint32_t nv108_pwr_code[] = {
        0x03e99800,
        0xf40096b0,
        0x0a98280b,
-       0x029abb84,
+       0x029abb9a,
        0x0d0e1cf4,
        0x01de7e01,
        0xf494bd00,
 /* 0x00b2: intr_watchdog_next_time */
        0x0a98140e,
-       0x00a6b085,
+       0x00a6b09b,
        0xa6080bf4,
        0x061cf49a,
 /* 0x00c0: intr_watchdog_next_time_set */
 /* 0x00c3: intr_watchdog_next_proc */
-       0xb58509b5,
+       0xb59b09b5,
        0xe0b603e9,
-       0x10e6b158,
+       0x68e6b158,
        0xc81bf402,
 /* 0x00d2: intr */
        0x00f900f8,
@@ -862,15 +864,15 @@ uint32_t nv108_pwr_code[] = {
        0x080804bd,
        0xc40088cf,
        0x0bf40289,
-       0x8500b51f,
+       0x9b00b51f,
        0x957e580e,
        0x09980000,
-       0x0096b085,
+       0x0096b09b,
        0x000d0bf4,
        0x0009f634,
        0x09b504bd,
 /* 0x0125: intr_skip_watchdog */
-       0x0089e484,
+       0x0089e49a,
        0x360bf408,
        0xcf068849,
        0x9ac40099,
@@ -918,7 +920,7 @@ uint32_t nv108_pwr_code[] = {
 /* 0x01c6: timer_reset */
        0x3400161e,
        0xbd000ef6,
-       0x840eb504,
+       0x9a0eb504,
 /* 0x01d0: timer_enable */
        0x38000108,
        0xbd0008f6,
@@ -949,7 +951,7 @@ uint32_t nv108_pwr_code[] = {
        0xa6008a98,
        0x100bf4ae,
        0xb15880b6,
-       0xf4021086,
+       0xf4026886,
        0x32f4f11b,
 /* 0x0239: find_done */
        0xfc8eb201,
@@ -1009,7 +1011,7 @@ uint32_t nv108_pwr_code[] = {
        0x0bf412a6,
        0x071ec42e,
        0xb704ee94,
-       0x980218e0,
+       0x980270e0,
        0xec9803eb,
        0x01ed9802,
        0x7e00ee98,
@@ -1031,7 +1033,7 @@ uint32_t nv108_pwr_code[] = {
        0xf412a608,
        0x23c4ef0b,
        0x0434b607,
-       0x029830b7,
+       0x02f030b7,
        0xb5033bb5,
        0x3db5023c,
        0x003eb501,
@@ -1044,11 +1046,11 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0379: host_init */
        0x00804100,
        0xf11014b6,
-       0x40021815,
+       0x40027015,
        0x01f604d0,
        0x4104bd00,
        0x14b60080,
-       0x9815f110,
+       0xf015f110,
        0x04dc4002,
        0xbd0001f6,
        0x40010104,
@@ -1101,13 +1103,13 @@ uint32_t nv108_pwr_code[] = {
        0x001398b2,
        0x950410b6,
        0x30f01034,
-       0xc835980c,
+       0xde35980c,
        0x12a655f9,
        0xfced1ef4,
        0x7ee0fcd0,
        0xf800023f,
 /* 0x0455: memx_info */
-       0x03544c00,
+       0x03ac4c00,
        0x7e08004b,
        0xf800023f,
 /* 0x0461: memx_recv */
@@ -1119,7 +1121,301 @@ uint32_t nv108_pwr_code[] = {
 /* 0x0471: perf_recv */
 /* 0x0473: perf_init */
        0xf800f800,
-/* 0x0475: test_recv */
+/* 0x0475: i2c_drive_scl */
+       0x0036b000,
+       0x400d0bf4,
+       0x01f607e0,
+       0xf804bd00,
+/* 0x0485: i2c_drive_scl_lo */
+       0x07e44000,
+       0xbd0001f6,
+/* 0x048f: i2c_drive_sda */
+       0xb000f804,
+       0x0bf40036,
+       0x07e0400d,
+       0xbd0002f6,
+/* 0x049f: i2c_drive_sda_lo */
+       0x4000f804,
+       0x02f607e4,
+       0xf804bd00,
+/* 0x04a9: i2c_sense_scl */
+       0x0132f400,
+       0xcf07c443,
+       0x31fd0033,
+       0x060bf404,
+/* 0x04bb: i2c_sense_scl_done */
+       0xf80131f4,
+/* 0x04bd: i2c_sense_sda */
+       0x0132f400,
+       0xcf07c443,
+       0x32fd0033,
+       0x060bf404,
+/* 0x04cf: i2c_sense_sda_done */
+       0xf80131f4,
+/* 0x04d1: i2c_raise_scl */
+       0x4440f900,
+       0x01030898,
+       0x0004757e,
+/* 0x04dc: i2c_raise_scl_wait */
+       0x7e03e84e,
+       0x7e00005d,
+       0xf40004a9,
+       0x42b60901,
+       0xef1bf401,
+/* 0x04f0: i2c_raise_scl_done */
+       0x00f840fc,
+/* 0x04f4: i2c_start */
+       0x0004a97e,
+       0x7e0d11f4,
+       0xf40004bd,
+       0x0ef40611,
+/* 0x0505: i2c_start_rep */
+       0x7e00032e,
+       0x03000475,
+       0x048f7e01,
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0xd17e50fc,
+       0x64b60004,
+       0x1d11f404,
+/* 0x0530: i2c_start_send */
+       0x8f7e0003,
+       0x884e0004,
+       0x005d7e13,
+       0x7e000300,
+       0x4e000475,
+       0x5d7e1388,
+/* 0x054a: i2c_start_out */
+       0x00f80000,
+/* 0x054c: i2c_stop */
+       0x757e0003,
+       0x00030004,
+       0x00048f7e,
+       0x7e03e84e,
+       0x0300005d,
+       0x04757e01,
+       0x13884e00,
+       0x00005d7e,
+       0x8f7e0103,
+       0x884e0004,
+       0x005d7e13,
+/* 0x057b: i2c_bitw */
+       0x7e00f800,
+       0x4e00048f,
+       0x5d7e03e8,
+       0x76bb0000,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb60004d1,
+       0x11f40464,
+       0x13884e17,
+       0x00005d7e,
+       0x757e0003,
+       0x884e0004,
+       0x005d7e13,
+/* 0x05b9: i2c_bitw_out */
+/* 0x05bb: i2c_bitr */
+       0x0300f800,
+       0x048f7e01,
+       0x03e84e00,
+       0x00005d7e,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x04d17e50,
+       0x0464b600,
+       0x7e1a11f4,
+       0x030004bd,
+       0x04757e00,
+       0x13884e00,
+       0x00005d7e,
+       0xf4013cf0,
+/* 0x05fe: i2c_bitr_done */
+       0x00f80131,
+/* 0x0600: i2c_get_byte */
+       0x08040005,
+/* 0x0604: i2c_get_byte_next */
+       0xbb0154b6,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x0005bb7e,
+       0xf40464b6,
+       0x53fd2a11,
+       0x0142b605,
+       0x03d81bf4,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x7b7e50fc,
+       0x64b60005,
+/* 0x064d: i2c_get_byte_done */
+/* 0x064f: i2c_put_byte */
+       0x0400f804,
+/* 0x0651: i2c_put_byte_next */
+       0x0142b608,
+       0xbb3854ff,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x00057b7e,
+       0xf40464b6,
+       0x46b03411,
+       0xd81bf400,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x05bb7e50,
+       0x0464b600,
+       0xbb0f11f4,
+       0x36b00076,
+       0x061bf401,
+/* 0x06a7: i2c_put_byte_done */
+       0xf80132f4,
+/* 0x06a9: i2c_addr */
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0xf47e50fc,
+       0x64b60004,
+       0x2911f404,
+       0x012ec3e7,
+       0xfd0134b6,
+       0x76bb0553,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb600064f,
+/* 0x06ee: i2c_addr_done */
+       0x00f80464,
+/* 0x06f0: i2c_acquire_addr */
+       0xb6f8cec7,
+       0xe0b705e4,
+       0x00f8d014,
+/* 0x06fc: i2c_acquire */
+       0x0006f07e,
+       0x0000047e,
+       0x7e03d9f0,
+       0xf800002e,
+/* 0x070d: i2c_release */
+       0x06f07e00,
+       0x00047e00,
+       0x03daf000,
+       0x00002e7e,
+/* 0x071e: i2c_recv */
+       0x32f400f8,
+       0xf8c1c701,
+       0xb00214b6,
+       0x1ff52816,
+       0x13b80137,
+       0x98000bd4,
+       0x13b80032,
+       0x98000bac,
+       0x31f40031,
+       0xf9d0f902,
+       0xf1d0f9e0,
+       0xf1000067,
+       0x92100063,
+       0x76bb0167,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb60006fc,
+       0xd0fc0464,
+       0xf500d6b0,
+       0x0500b01b,
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0xa97e50fc,
+       0x64b60006,
+       0xcc11f504,
+       0xe0c5c700,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x064f7e50,
+       0x0464b600,
+       0x00a911f5,
+       0x76bb0105,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb60006a9,
+       0x11f50464,
+       0x76bb0087,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0x7e50fc04,
+       0xb6000600,
+       0x11f40464,
+       0xe05bcb67,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x054c7e50,
+       0x0464b600,
+       0x74bd5bb2,
+/* 0x0823: i2c_recv_not_rd08 */
+       0xb0410ef4,
+       0x1bf401d6,
+       0x7e00053b,
+       0xf40006a9,
+       0xc5c73211,
+       0x064f7ee0,
+       0x2811f400,
+       0xa97e0005,
+       0x11f40006,
+       0xe0b5c71f,
+       0x00064f7e,
+       0x7e1511f4,
+       0xbd00054c,
+       0x08c5c774,
+       0xf4091bf4,
+       0x0ef40232,
+/* 0x0861: i2c_recv_not_wr08 */
+/* 0x0861: i2c_recv_done */
+       0xf8cec703,
+       0x00070d7e,
+       0xd0fce0fc,
+       0xb20912f4,
+       0x023f7e7c,
+/* 0x0875: i2c_recv_exit */
+/* 0x0877: i2c_init */
+       0xf800f800,
+/* 0x0879: test_recv */
        0x04584100,
        0xb60011cf,
        0x58400110,
@@ -1128,26 +1424,26 @@ uint32_t nv108_pwr_code[] = {
        0xe3f1d900,
        0x967e134f,
        0x00f80001,
-/* 0x0494: test_init */
+/* 0x0898: test_init */
        0x7e08004e,
        0xf8000196,
-/* 0x049d: idle_recv */
-/* 0x049f: idle */
+/* 0x08a1: idle_recv */
+/* 0x08a3: idle */
        0xf400f800,
        0x54410031,
        0x0011cf04,
        0x400110b6,
        0x01f60454,
-/* 0x04b3: idle_loop */
+/* 0x08b7: idle_loop */
        0x0104bd00,
        0x0232f458,
-/* 0x04b8: idle_proc */
-/* 0x04b8: idle_proc_exec */
+/* 0x08bc: idle_proc */
+/* 0x08bc: idle_proc_exec */
        0x1eb210f9,
        0x0002487e,
        0x11f410fc,
        0x0231f409,
-/* 0x04cb: idle_proc_next */
+/* 0x08cf: idle_proc_next */
        0xb6f00ef4,
        0x1fa65810,
        0xf4e81bf4,
@@ -1161,5 +1457,4 @@ uint32_t nv108_pwr_code[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-       0x00000000,
 };
index 6fde0b89e5aa641de3add5489a98dea4e25c61bc..6744fcc0615160e657227285a70fc2c201bb7cb9 100644 (file)
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
index 0fa4d7dcd407bb5bdb7802dcd4a6382c6bb84803..5a73fa620978aa0b300f87f80e6a1c049a2aa094 100644 (file)
@@ -89,9 +89,31 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x5f433249,
+       0x00000982,
+       0x00000825,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x54534554,
-       0x0000057b,
-       0x00000554,
+       0x000009ab,
+       0x00000984,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -112,8 +134,8 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x454c4449,
-       0x00000587,
-       0x00000585,
+       0x000009b7,
+       0x000009b5,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -133,12 +155,12 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
        0x00000000,
-/* 0x0214: time_next */
+/* 0x026c: time_next */
        0x00000000,
-/* 0x0218: fifo_queue */
+/* 0x0270: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -171,7 +193,7 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x02f0: rfifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -204,11 +226,11 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0318: memx_func_head */
+/* 0x0370: memx_func_head */
        0x00010000,
        0x00000000,
        0x0000046f,
-/* 0x0324: memx_func_next */
+/* 0x037c: memx_func_next */
        0x00000001,
        0x00000000,
        0x00000496,
@@ -221,8 +243,18 @@ uint32_t nva3_pwr_data[] = {
        0x00010004,
        0x00000000,
        0x000004fc,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -725,6 +757,42 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+       0x00001000,
+       0x00004000,
+       0x00010000,
+       0x00000100,
+       0x00040000,
+       0x00100000,
+       0x00400000,
+       0x01000000,
+       0x04000000,
+       0x10000000,
+/* 0x0bd4: i2c_sda_map */
+       0x00002000,
+       0x00008000,
+       0x00020000,
+       0x00000200,
+       0x00080000,
+       0x00200000,
+       0x00800000,
+       0x02000000,
+       0x08000000,
+       0x20000000,
+/* 0x0bfc: i2c_ctrl */
+       0x0000e138,
+       0x0000e150,
+       0x0000e168,
+       0x0000e180,
+       0x0000e254,
+       0x0000e274,
+       0x0000e764,
+       0x0000e780,
+       0x0000e79c,
+       0x0000e7b8,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -735,7 +803,6 @@ uint32_t nva3_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0b54: memx_data_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -787,15 +854,15 @@ uint32_t nva3_pwr_code[] = {
        0x07a007f1,
        0xd00604b6,
        0x04bd000e,
-       0xf001e7f0,
-       0x07f101e3,
+       0xf001d7f0,
+       0x07f101d3,
        0x04b607ac,
-       0x000ed006,
+       0x000dd006,
 /* 0x0022: rd32_wait */
-       0xe7f104bd,
-       0xe4b607ac,
-       0x00eecf06,
-       0x7000e4f1,
+       0xd7f104bd,
+       0xd4b607ac,
+       0x00ddcf06,
+       0x7000d4f1,
        0xf1f21bf4,
        0xb607a4d7,
        0xddcf06d4,
@@ -807,15 +874,15 @@ uint32_t nva3_pwr_code[] = {
        0xb607a407,
        0x0dd00604,
        0xf004bd00,
-       0xe5f002e7,
-       0x01e3f0f0,
+       0xd5f002d7,
+       0x01d3f0f0,
        0x07ac07f1,
        0xd00604b6,
-       0x04bd000e,
+       0x04bd000d,
 /* 0x006c: wr32_wait */
-       0x07ace7f1,
-       0xcf06e4b6,
-       0xe4f100ee,
+       0x07acd7f1,
+       0xcf06d4b6,
+       0xd4f100dd,
        0x1bf47000,
 /* 0x007f: nsec */
        0xf000f8f2,
@@ -845,21 +912,21 @@ uint32_t nva3_pwr_code[] = {
        0x9800f8df,
        0x96b003e9,
        0x2a0bf400,
-       0xbb840a98,
+       0xbb9a0a98,
        0x1cf4029a,
        0x01d7f00f,
        0x025421f5,
        0x0ef494bd,
 /* 0x00e9: intr_watchdog_next_time */
-       0x850a9815,
+       0x9b0a9815,
        0xf400a6b0,
        0x9ab8090b,
        0x061cf406,
 /* 0x00f8: intr_watchdog_next_time_set */
 /* 0x00fb: intr_watchdog_next_proc */
-       0x80850980,
+       0x809b0980,
        0xe0b603e9,
-       0x10e6b158,
+       0x68e6b158,
        0xc61bf402,
 /* 0x010a: intr */
        0x00f900f8,
@@ -880,15 +947,15 @@ uint32_t nva3_pwr_code[] = {
        0x0088cf06,
        0xf40289c4,
        0x0080230b,
-       0x58e7f085,
+       0x58e7f09b,
        0x98cb21f4,
-       0x96b08509,
+       0x96b09b09,
        0x110bf400,
        0xb63407f0,
        0x09d00604,
        0x8004bd00,
 /* 0x016e: intr_skip_watchdog */
-       0x89e48409,
+       0x89e49a09,
        0x0bf40800,
        0x8897f148,
        0x0694b606,
@@ -948,7 +1015,7 @@ uint32_t nva3_pwr_code[] = {
        0x000ed006,
        0x0e8004bd,
 /* 0x0241: timer_enable */
-       0x0187f084,
+       0x0187f09a,
        0xb63807f0,
        0x08d00604,
 /* 0x024f: timer_done */
@@ -979,7 +1046,7 @@ uint32_t nva3_pwr_code[] = {
        0xb8008a98,
        0x0bf406ae,
        0x5880b610,
-       0x021086b1,
+       0x026886b1,
        0xf4f01bf4,
 /* 0x02b2: find_done */
        0x8eb90132,
@@ -1049,7 +1116,7 @@ uint32_t nva3_pwr_code[] = {
        0x320bf406,
        0x94071ec4,
        0xe0b704ee,
-       0xeb980218,
+       0xeb980270,
        0x02ec9803,
        0x9801ed98,
        0x21f500ee,
@@ -1075,7 +1142,7 @@ uint32_t nva3_pwr_code[] = {
        0xe60bf406,
        0xb60723c4,
        0x30b70434,
-       0x3b800298,
+       0x3b8002f0,
        0x023c8003,
        0x80013d80,
        0x20b6003e,
@@ -1090,13 +1157,13 @@ uint32_t nva3_pwr_code[] = {
 /* 0x0430: host_init */
        0x008017f1,
        0xf11014b6,
-       0xf1021815,
+       0xf1027015,
        0xb604d007,
        0x01d00604,
        0xf104bd00,
        0xb6008017,
        0x15f11014,
-       0x07f10298,
+       0x07f102f0,
        0x04b604dc,
        0x0001d006,
        0x17f004bd,
@@ -1156,14 +1223,14 @@ uint32_t nva3_pwr_code[] = {
        0x00139802,
        0x950410b6,
        0x30f01034,
-       0xc835980c,
+       0xde35980c,
        0x12b855f9,
        0xec1ef406,
        0xe0fcd0fc,
        0x02b921f5,
 /* 0x0532: memx_info */
        0xc7f100f8,
-       0xb7f10354,
+       0xb7f103ac,
        0x21f50800,
        0x00f802b9,
 /* 0x0540: memx_recv */
@@ -1175,7 +1242,312 @@ uint32_t nva3_pwr_code[] = {
 /* 0x0550: perf_recv */
 /* 0x0552: perf_init */
        0x00f800f8,
-/* 0x0554: test_recv */
+/* 0x0554: i2c_drive_scl */
+       0xf40036b0,
+       0x07f1110b,
+       0x04b607e0,
+       0x0001d006,
+       0x00f804bd,
+/* 0x0568: i2c_drive_scl_lo */
+       0x07e407f1,
+       0xd00604b6,
+       0x04bd0001,
+/* 0x0576: i2c_drive_sda */
+       0x36b000f8,
+       0x110bf400,
+       0x07e007f1,
+       0xd00604b6,
+       0x04bd0002,
+/* 0x058a: i2c_drive_sda_lo */
+       0x07f100f8,
+       0x04b607e4,
+       0x0002d006,
+       0x00f804bd,
+/* 0x0598: i2c_sense_scl */
+       0xf10132f4,
+       0xb607c437,
+       0x33cf0634,
+       0x0431fd00,
+       0xf4060bf4,
+/* 0x05ae: i2c_sense_scl_done */
+       0x00f80131,
+/* 0x05b0: i2c_sense_sda */
+       0xf10132f4,
+       0xb607c437,
+       0x33cf0634,
+       0x0432fd00,
+       0xf4060bf4,
+/* 0x05c6: i2c_sense_sda_done */
+       0x00f80131,
+/* 0x05c8: i2c_raise_scl */
+       0x47f140f9,
+       0x37f00898,
+       0x5421f501,
+/* 0x05d5: i2c_raise_scl_wait */
+       0xe8e7f105,
+       0x7f21f403,
+       0x059821f5,
+       0xb60901f4,
+       0x1bf40142,
+/* 0x05e9: i2c_raise_scl_done */
+       0xf840fcef,
+/* 0x05ed: i2c_start */
+       0x9821f500,
+       0x0d11f405,
+       0x05b021f5,
+       0xf40611f4,
+/* 0x05fe: i2c_start_rep */
+       0x37f0300e,
+       0x5421f500,
+       0x0137f005,
+       0x057621f5,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xc821f550,
+       0x0464b605,
+/* 0x062b: i2c_start_send */
+       0xf01f11f4,
+       0x21f50037,
+       0xe7f10576,
+       0x21f41388,
+       0x0037f07f,
+       0x055421f5,
+       0x1388e7f1,
+/* 0x0647: i2c_start_out */
+       0xf87f21f4,
+/* 0x0649: i2c_stop */
+       0x0037f000,
+       0x055421f5,
+       0xf50037f0,
+       0xf1057621,
+       0xf403e8e7,
+       0x37f07f21,
+       0x5421f501,
+       0x88e7f105,
+       0x7f21f413,
+       0xf50137f0,
+       0xf1057621,
+       0xf41388e7,
+       0x00f87f21,
+/* 0x067c: i2c_bitw */
+       0x057621f5,
+       0x03e8e7f1,
+       0xbb7f21f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05c821f5,
+       0xf40464b6,
+       0xe7f11811,
+       0x21f41388,
+       0x0037f07f,
+       0x055421f5,
+       0x1388e7f1,
+/* 0x06bb: i2c_bitw_out */
+       0xf87f21f4,
+/* 0x06bd: i2c_bitr */
+       0x0137f000,
+       0x057621f5,
+       0x03e8e7f1,
+       0xbb7f21f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05c821f5,
+       0xf40464b6,
+       0x21f51b11,
+       0x37f005b0,
+       0x5421f500,
+       0x88e7f105,
+       0x7f21f413,
+       0xf4013cf0,
+/* 0x0702: i2c_bitr_done */
+       0x00f80131,
+/* 0x0704: i2c_get_byte */
+       0xf00057f0,
+/* 0x070a: i2c_get_byte_next */
+       0x54b60847,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b606bd,
+       0x2b11f404,
+       0xb60553fd,
+       0x1bf40142,
+       0x0137f0d8,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x7c21f550,
+       0x0464b606,
+/* 0x0754: i2c_get_byte_done */
+/* 0x0756: i2c_put_byte */
+       0x47f000f8,
+/* 0x0759: i2c_put_byte_next */
+       0x0142b608,
+       0xbb3854ff,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x067c21f5,
+       0xf40464b6,
+       0x46b03411,
+       0xd81bf400,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xbd21f550,
+       0x0464b606,
+       0xbb0f11f4,
+       0x36b00076,
+       0x061bf401,
+/* 0x07af: i2c_put_byte_done */
+       0xf80132f4,
+/* 0x07b1: i2c_addr */
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b605ed,
+       0x2911f404,
+       0x012ec3e7,
+       0xfd0134b6,
+       0x76bb0553,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6075621,
+/* 0x07f6: i2c_addr_done */
+       0x00f80464,
+/* 0x07f8: i2c_acquire_addr */
+       0xb6f8cec7,
+       0xe0b702e4,
+       0xee980bfc,
+/* 0x0807: i2c_acquire */
+       0xf500f800,
+       0xf407f821,
+       0xd9f00421,
+       0x3f21f403,
+/* 0x0816: i2c_release */
+       0x21f500f8,
+       0x21f407f8,
+       0x03daf004,
+       0xf83f21f4,
+/* 0x0825: i2c_recv */
+       0x0132f400,
+       0xb6f8c1c7,
+       0x16b00214,
+       0x3a1ff528,
+       0xd413a001,
+       0x0032980b,
+       0x0bac13a0,
+       0xf4003198,
+       0xd0f90231,
+       0xd0f9e0f9,
+       0x000067f1,
+       0x100063f1,
+       0xbb016792,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x080721f5,
+       0xfc0464b6,
+       0x00d6b0d0,
+       0x00b31bf5,
+       0xbb0057f0,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x07b121f5,
+       0xf50464b6,
+       0xc700d011,
+       0x76bbe0c5,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6075621,
+       0x11f50464,
+       0x57f000ad,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b607b1,
+       0x8a11f504,
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b60704,
+       0x6a11f404,
+       0xbbe05bcb,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x064921f5,
+       0xb90464b6,
+       0x74bd025b,
+/* 0x092b: i2c_recv_not_rd08 */
+       0xb0430ef4,
+       0x1bf401d6,
+       0x0057f03d,
+       0x07b121f5,
+       0xc73311f4,
+       0x21f5e0c5,
+       0x11f40756,
+       0x0057f029,
+       0x07b121f5,
+       0xc71f11f4,
+       0x21f5e0b5,
+       0x11f40756,
+       0x4921f515,
+       0xc774bd06,
+       0x1bf408c5,
+       0x0232f409,
+/* 0x096b: i2c_recv_not_wr08 */
+/* 0x096b: i2c_recv_done */
+       0xc7030ef4,
+       0x21f5f8ce,
+       0xe0fc0816,
+       0x12f4d0fc,
+       0x027cb90a,
+       0x02b921f5,
+/* 0x0980: i2c_recv_exit */
+/* 0x0982: i2c_init */
+       0x00f800f8,
+/* 0x0984: test_recv */
        0x05d817f1,
        0xcf0614b6,
        0x10b60011,
@@ -1185,12 +1557,12 @@ uint32_t nva3_pwr_code[] = {
        0x00e7f104,
        0x4fe3f1d9,
        0xf521f513,
-/* 0x057b: test_init */
+/* 0x09ab: test_init */
        0xf100f801,
        0xf50800e7,
        0xf801f521,
-/* 0x0585: idle_recv */
-/* 0x0587: idle */
+/* 0x09b5: idle_recv */
+/* 0x09b7: idle */
        0xf400f800,
        0x17f10031,
        0x14b605d4,
@@ -1198,32 +1570,20 @@ uint32_t nva3_pwr_code[] = {
        0xf10110b6,
        0xb605d407,
        0x01d00604,
-/* 0x05a3: idle_loop */
+/* 0x09d3: idle_loop */
        0xf004bd00,
        0x32f45817,
-/* 0x05a9: idle_proc */
-/* 0x05a9: idle_proc_exec */
+/* 0x09d9: idle_proc */
+/* 0x09d9: idle_proc_exec */
        0xb910f902,
        0x21f5021e,
        0x10fc02c2,
        0xf40911f4,
        0x0ef40231,
-/* 0x05bd: idle_proc_next */
+/* 0x09ed: idle_proc_next */
        0x5810b6ef,
        0xf4061fb8,
        0x02f4e61b,
        0x0028f4dd,
        0x00bb0ef4,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
 };
index eaa64da68e3604b1537753cc314388311dd48514..48f79434a4491f30c61f95755d43c37097f73249 100644 (file)
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
index 82c8e8b889178dd34e0eef6cf6a39fdd0d7a800d..4dba00d2dd1a6f579d19c4571964440ccbf077b5 100644 (file)
@@ -89,9 +89,31 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x5f433249,
+       0x00000982,
+       0x00000825,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x54534554,
-       0x0000057b,
-       0x00000554,
+       0x000009ab,
+       0x00000984,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -112,8 +134,8 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x454c4449,
-       0x00000587,
-       0x00000585,
+       0x000009b7,
+       0x000009b5,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -133,12 +155,12 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
        0x00000000,
-/* 0x0214: time_next */
+/* 0x026c: time_next */
        0x00000000,
-/* 0x0218: fifo_queue */
+/* 0x0270: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -171,7 +193,7 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0298: rfifo_queue */
+/* 0x02f0: rfifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -204,11 +226,11 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0318: memx_func_head */
+/* 0x0370: memx_func_head */
        0x00010000,
        0x00000000,
        0x0000046f,
-/* 0x0324: memx_func_next */
+/* 0x037c: memx_func_next */
        0x00000001,
        0x00000000,
        0x00000496,
@@ -221,8 +243,18 @@ uint32_t nvc0_pwr_data[] = {
        0x00010004,
        0x00000000,
        0x000004fc,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -725,6 +757,42 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+       0x00001000,
+       0x00004000,
+       0x00010000,
+       0x00000100,
+       0x00040000,
+       0x00100000,
+       0x00400000,
+       0x01000000,
+       0x04000000,
+       0x10000000,
+/* 0x0bd4: i2c_sda_map */
+       0x00002000,
+       0x00008000,
+       0x00020000,
+       0x00000200,
+       0x00080000,
+       0x00200000,
+       0x00800000,
+       0x02000000,
+       0x08000000,
+       0x20000000,
+/* 0x0bfc: i2c_ctrl */
+       0x0000e138,
+       0x0000e150,
+       0x0000e168,
+       0x0000e180,
+       0x0000e254,
+       0x0000e274,
+       0x0000e764,
+       0x0000e780,
+       0x0000e79c,
+       0x0000e7b8,
+       0x00000000,
+       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -735,7 +803,6 @@ uint32_t nvc0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0b54: memx_data_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -787,15 +854,15 @@ uint32_t nvc0_pwr_code[] = {
        0x07a007f1,
        0xd00604b6,
        0x04bd000e,
-       0xf001e7f0,
-       0x07f101e3,
+       0xf001d7f0,
+       0x07f101d3,
        0x04b607ac,
-       0x000ed006,
+       0x000dd006,
 /* 0x0022: rd32_wait */
-       0xe7f104bd,
-       0xe4b607ac,
-       0x00eecf06,
-       0x7000e4f1,
+       0xd7f104bd,
+       0xd4b607ac,
+       0x00ddcf06,
+       0x7000d4f1,
        0xf1f21bf4,
        0xb607a4d7,
        0xddcf06d4,
@@ -807,15 +874,15 @@ uint32_t nvc0_pwr_code[] = {
        0xb607a407,
        0x0dd00604,
        0xf004bd00,
-       0xe5f002e7,
-       0x01e3f0f0,
+       0xd5f002d7,
+       0x01d3f0f0,
        0x07ac07f1,
        0xd00604b6,
-       0x04bd000e,
+       0x04bd000d,
 /* 0x006c: wr32_wait */
-       0x07ace7f1,
-       0xcf06e4b6,
-       0xe4f100ee,
+       0x07acd7f1,
+       0xcf06d4b6,
+       0xd4f100dd,
        0x1bf47000,
 /* 0x007f: nsec */
        0xf000f8f2,
@@ -845,21 +912,21 @@ uint32_t nvc0_pwr_code[] = {
        0x9800f8df,
        0x96b003e9,
        0x2a0bf400,
-       0xbb840a98,
+       0xbb9a0a98,
        0x1cf4029a,
        0x01d7f00f,
        0x025421f5,
        0x0ef494bd,
 /* 0x00e9: intr_watchdog_next_time */
-       0x850a9815,
+       0x9b0a9815,
        0xf400a6b0,
        0x9ab8090b,
        0x061cf406,
 /* 0x00f8: intr_watchdog_next_time_set */
 /* 0x00fb: intr_watchdog_next_proc */
-       0x80850980,
+       0x809b0980,
        0xe0b603e9,
-       0x10e6b158,
+       0x68e6b158,
        0xc61bf402,
 /* 0x010a: intr */
        0x00f900f8,
@@ -880,15 +947,15 @@ uint32_t nvc0_pwr_code[] = {
        0x0088cf06,
        0xf40289c4,
        0x0080230b,
-       0x58e7f085,
+       0x58e7f09b,
        0x98cb21f4,
-       0x96b08509,
+       0x96b09b09,
        0x110bf400,
        0xb63407f0,
        0x09d00604,
        0x8004bd00,
 /* 0x016e: intr_skip_watchdog */
-       0x89e48409,
+       0x89e49a09,
        0x0bf40800,
        0x8897f148,
        0x0694b606,
@@ -948,7 +1015,7 @@ uint32_t nvc0_pwr_code[] = {
        0x000ed006,
        0x0e8004bd,
 /* 0x0241: timer_enable */
-       0x0187f084,
+       0x0187f09a,
        0xb63807f0,
        0x08d00604,
 /* 0x024f: timer_done */
@@ -979,7 +1046,7 @@ uint32_t nvc0_pwr_code[] = {
        0xb8008a98,
        0x0bf406ae,
        0x5880b610,
-       0x021086b1,
+       0x026886b1,
        0xf4f01bf4,
 /* 0x02b2: find_done */
        0x8eb90132,
@@ -1049,7 +1116,7 @@ uint32_t nvc0_pwr_code[] = {
        0x320bf406,
        0x94071ec4,
        0xe0b704ee,
-       0xeb980218,
+       0xeb980270,
        0x02ec9803,
        0x9801ed98,
        0x21f500ee,
@@ -1075,7 +1142,7 @@ uint32_t nvc0_pwr_code[] = {
        0xe60bf406,
        0xb60723c4,
        0x30b70434,
-       0x3b800298,
+       0x3b8002f0,
        0x023c8003,
        0x80013d80,
        0x20b6003e,
@@ -1090,13 +1157,13 @@ uint32_t nvc0_pwr_code[] = {
 /* 0x0430: host_init */
        0x008017f1,
        0xf11014b6,
-       0xf1021815,
+       0xf1027015,
        0xb604d007,
        0x01d00604,
        0xf104bd00,
        0xb6008017,
        0x15f11014,
-       0x07f10298,
+       0x07f102f0,
        0x04b604dc,
        0x0001d006,
        0x17f004bd,
@@ -1156,14 +1223,14 @@ uint32_t nvc0_pwr_code[] = {
        0x00139802,
        0x950410b6,
        0x30f01034,
-       0xc835980c,
+       0xde35980c,
        0x12b855f9,
        0xec1ef406,
        0xe0fcd0fc,
        0x02b921f5,
 /* 0x0532: memx_info */
        0xc7f100f8,
-       0xb7f10354,
+       0xb7f103ac,
        0x21f50800,
        0x00f802b9,
 /* 0x0540: memx_recv */
@@ -1175,7 +1242,312 @@ uint32_t nvc0_pwr_code[] = {
 /* 0x0550: perf_recv */
 /* 0x0552: perf_init */
        0x00f800f8,
-/* 0x0554: test_recv */
+/* 0x0554: i2c_drive_scl */
+       0xf40036b0,
+       0x07f1110b,
+       0x04b607e0,
+       0x0001d006,
+       0x00f804bd,
+/* 0x0568: i2c_drive_scl_lo */
+       0x07e407f1,
+       0xd00604b6,
+       0x04bd0001,
+/* 0x0576: i2c_drive_sda */
+       0x36b000f8,
+       0x110bf400,
+       0x07e007f1,
+       0xd00604b6,
+       0x04bd0002,
+/* 0x058a: i2c_drive_sda_lo */
+       0x07f100f8,
+       0x04b607e4,
+       0x0002d006,
+       0x00f804bd,
+/* 0x0598: i2c_sense_scl */
+       0xf10132f4,
+       0xb607c437,
+       0x33cf0634,
+       0x0431fd00,
+       0xf4060bf4,
+/* 0x05ae: i2c_sense_scl_done */
+       0x00f80131,
+/* 0x05b0: i2c_sense_sda */
+       0xf10132f4,
+       0xb607c437,
+       0x33cf0634,
+       0x0432fd00,
+       0xf4060bf4,
+/* 0x05c6: i2c_sense_sda_done */
+       0x00f80131,
+/* 0x05c8: i2c_raise_scl */
+       0x47f140f9,
+       0x37f00898,
+       0x5421f501,
+/* 0x05d5: i2c_raise_scl_wait */
+       0xe8e7f105,
+       0x7f21f403,
+       0x059821f5,
+       0xb60901f4,
+       0x1bf40142,
+/* 0x05e9: i2c_raise_scl_done */
+       0xf840fcef,
+/* 0x05ed: i2c_start */
+       0x9821f500,
+       0x0d11f405,
+       0x05b021f5,
+       0xf40611f4,
+/* 0x05fe: i2c_start_rep */
+       0x37f0300e,
+       0x5421f500,
+       0x0137f005,
+       0x057621f5,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xc821f550,
+       0x0464b605,
+/* 0x062b: i2c_start_send */
+       0xf01f11f4,
+       0x21f50037,
+       0xe7f10576,
+       0x21f41388,
+       0x0037f07f,
+       0x055421f5,
+       0x1388e7f1,
+/* 0x0647: i2c_start_out */
+       0xf87f21f4,
+/* 0x0649: i2c_stop */
+       0x0037f000,
+       0x055421f5,
+       0xf50037f0,
+       0xf1057621,
+       0xf403e8e7,
+       0x37f07f21,
+       0x5421f501,
+       0x88e7f105,
+       0x7f21f413,
+       0xf50137f0,
+       0xf1057621,
+       0xf41388e7,
+       0x00f87f21,
+/* 0x067c: i2c_bitw */
+       0x057621f5,
+       0x03e8e7f1,
+       0xbb7f21f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05c821f5,
+       0xf40464b6,
+       0xe7f11811,
+       0x21f41388,
+       0x0037f07f,
+       0x055421f5,
+       0x1388e7f1,
+/* 0x06bb: i2c_bitw_out */
+       0xf87f21f4,
+/* 0x06bd: i2c_bitr */
+       0x0137f000,
+       0x057621f5,
+       0x03e8e7f1,
+       0xbb7f21f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05c821f5,
+       0xf40464b6,
+       0x21f51b11,
+       0x37f005b0,
+       0x5421f500,
+       0x88e7f105,
+       0x7f21f413,
+       0xf4013cf0,
+/* 0x0702: i2c_bitr_done */
+       0x00f80131,
+/* 0x0704: i2c_get_byte */
+       0xf00057f0,
+/* 0x070a: i2c_get_byte_next */
+       0x54b60847,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b606bd,
+       0x2b11f404,
+       0xb60553fd,
+       0x1bf40142,
+       0x0137f0d8,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x7c21f550,
+       0x0464b606,
+/* 0x0754: i2c_get_byte_done */
+/* 0x0756: i2c_put_byte */
+       0x47f000f8,
+/* 0x0759: i2c_put_byte_next */
+       0x0142b608,
+       0xbb3854ff,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x067c21f5,
+       0xf40464b6,
+       0x46b03411,
+       0xd81bf400,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xbd21f550,
+       0x0464b606,
+       0xbb0f11f4,
+       0x36b00076,
+       0x061bf401,
+/* 0x07af: i2c_put_byte_done */
+       0xf80132f4,
+/* 0x07b1: i2c_addr */
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b605ed,
+       0x2911f404,
+       0x012ec3e7,
+       0xfd0134b6,
+       0x76bb0553,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6075621,
+/* 0x07f6: i2c_addr_done */
+       0x00f80464,
+/* 0x07f8: i2c_acquire_addr */
+       0xb6f8cec7,
+       0xe0b702e4,
+       0xee980bfc,
+/* 0x0807: i2c_acquire */
+       0xf500f800,
+       0xf407f821,
+       0xd9f00421,
+       0x3f21f403,
+/* 0x0816: i2c_release */
+       0x21f500f8,
+       0x21f407f8,
+       0x03daf004,
+       0xf83f21f4,
+/* 0x0825: i2c_recv */
+       0x0132f400,
+       0xb6f8c1c7,
+       0x16b00214,
+       0x3a1ff528,
+       0xd413a001,
+       0x0032980b,
+       0x0bac13a0,
+       0xf4003198,
+       0xd0f90231,
+       0xd0f9e0f9,
+       0x000067f1,
+       0x100063f1,
+       0xbb016792,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x080721f5,
+       0xfc0464b6,
+       0x00d6b0d0,
+       0x00b31bf5,
+       0xbb0057f0,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x07b121f5,
+       0xf50464b6,
+       0xc700d011,
+       0x76bbe0c5,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6075621,
+       0x11f50464,
+       0x57f000ad,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b607b1,
+       0x8a11f504,
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b60704,
+       0x6a11f404,
+       0xbbe05bcb,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x064921f5,
+       0xb90464b6,
+       0x74bd025b,
+/* 0x092b: i2c_recv_not_rd08 */
+       0xb0430ef4,
+       0x1bf401d6,
+       0x0057f03d,
+       0x07b121f5,
+       0xc73311f4,
+       0x21f5e0c5,
+       0x11f40756,
+       0x0057f029,
+       0x07b121f5,
+       0xc71f11f4,
+       0x21f5e0b5,
+       0x11f40756,
+       0x4921f515,
+       0xc774bd06,
+       0x1bf408c5,
+       0x0232f409,
+/* 0x096b: i2c_recv_not_wr08 */
+/* 0x096b: i2c_recv_done */
+       0xc7030ef4,
+       0x21f5f8ce,
+       0xe0fc0816,
+       0x12f4d0fc,
+       0x027cb90a,
+       0x02b921f5,
+/* 0x0980: i2c_recv_exit */
+/* 0x0982: i2c_init */
+       0x00f800f8,
+/* 0x0984: test_recv */
        0x05d817f1,
        0xcf0614b6,
        0x10b60011,
@@ -1185,12 +1557,12 @@ uint32_t nvc0_pwr_code[] = {
        0x00e7f104,
        0x4fe3f1d9,
        0xf521f513,
-/* 0x057b: test_init */
+/* 0x09ab: test_init */
        0xf100f801,
        0xf50800e7,
        0xf801f521,
-/* 0x0585: idle_recv */
-/* 0x0587: idle */
+/* 0x09b5: idle_recv */
+/* 0x09b7: idle */
        0xf400f800,
        0x17f10031,
        0x14b605d4,
@@ -1198,32 +1570,20 @@ uint32_t nvc0_pwr_code[] = {
        0xf10110b6,
        0xb605d407,
        0x01d00604,
-/* 0x05a3: idle_loop */
+/* 0x09d3: idle_loop */
        0xf004bd00,
        0x32f45817,
-/* 0x05a9: idle_proc */
-/* 0x05a9: idle_proc_exec */
+/* 0x09d9: idle_proc */
+/* 0x09d9: idle_proc_exec */
        0xb910f902,
        0x21f5021e,
        0x10fc02c2,
        0xf40911f4,
        0x0ef40231,
-/* 0x05bd: idle_proc_next */
+/* 0x09ed: idle_proc_next */
        0x5810b6ef,
        0xf4061fb8,
        0x02f4e61b,
        0x0028f4dd,
        0x00bb0ef4,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
 };
index 32d65ea254dd85c9b89677855d527c63d2b85654..8a89dfe41ce1ba8ddf7b808ef5534e5eefd418a9 100644 (file)
@@ -37,6 +37,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_PROC
@@ -46,6 +47,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_DATA
@@ -57,6 +59,7 @@
 #include "host.fuc"
 #include "memx.fuc"
 #include "perf.fuc"
+#include "i2c_.fuc"
 #include "test.fuc"
 #include "idle.fuc"
 #undef INCLUDE_CODE
index ce65e2a4b789b4cfef72c9ee196bc0a69c20b906..5e24c6bc041d6aefbe8de51933ed4c30e0af3fcc 100644 (file)
@@ -89,33 +89,13 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-       0x54534554,
-       0x000004eb,
-       0x000004ca,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+       0x5f433249,
+       0x000008e3,
+       0x00000786,
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
-       0x454c4449,
-       0x000004f7,
-       0x000004f5,
-       0x00000000,
-       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -131,14 +111,13 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x54534554,
+       0x00000906,
+       0x000008e5,
        0x00000000,
        0x00000000,
-/* 0x0210: proc_list_tail */
-/* 0x0210: time_prev */
        0x00000000,
-/* 0x0214: time_next */
        0x00000000,
-/* 0x0218: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -154,6 +133,9 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+       0x454c4449,
+       0x00000912,
+       0x00000910,
        0x00000000,
        0x00000000,
        0x00000000,
@@ -171,11 +153,14 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0298: rfifo_queue */
        0x00000000,
        0x00000000,
+/* 0x0268: proc_list_tail */
+/* 0x0268: time_prev */
        0x00000000,
+/* 0x026c: time_next */
        0x00000000,
+/* 0x0270: fifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -204,31 +189,11 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0318: memx_func_head */
-       0x00010000,
-       0x00000000,
-       0x000003f4,
-/* 0x0324: memx_func_next */
-       0x00000001,
-       0x00000000,
-       0x00000415,
-       0x00000002,
-       0x00000002,
-       0x00000430,
-       0x00040003,
-       0x00000000,
-       0x00000458,
-       0x00010004,
-       0x00000000,
-       0x00000472,
-/* 0x0354: memx_func_tail */
-/* 0x0354: memx_data_head */
-       0x00000000,
-       0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x02f0: rfifo_queue */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -261,10 +226,25 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0370: memx_func_head */
+       0x00010000,
        0x00000000,
+       0x000003f4,
+/* 0x037c: memx_func_next */
+       0x00000001,
        0x00000000,
+       0x00000415,
+       0x00000002,
+       0x00000002,
+       0x00000430,
+       0x00040003,
        0x00000000,
+       0x00000458,
+       0x00010004,
        0x00000000,
+       0x00000472,
+/* 0x03ac: memx_func_tail */
+/* 0x03ac: memx_data_head */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -735,7 +715,6 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
-/* 0x0b54: memx_data_tail */
        0x00000000,
        0x00000000,
        0x00000000,
@@ -778,6 +757,29 @@ uint32_t nvd0_pwr_data[] = {
        0x00000000,
        0x00000000,
        0x00000000,
+/* 0x0bac: memx_data_tail */
+/* 0x0bac: i2c_scl_map */
+       0x00000400,
+       0x00000800,
+       0x00001000,
+       0x00002000,
+       0x00004000,
+       0x00008000,
+       0x00010000,
+       0x00020000,
+       0x00040000,
+       0x00080000,
+/* 0x0bd4: i2c_sda_map */
+       0x00100000,
+       0x00200000,
+       0x00400000,
+       0x00800000,
+       0x01000000,
+       0x02000000,
+       0x04000000,
+       0x08000000,
+       0x10000000,
+       0x20000000,
        0x00000000,
 };
 
@@ -786,14 +788,14 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x0004: rd32 */
        0x07a007f1,
        0xbd000ed0,
-       0x01e7f004,
-       0xf101e3f0,
+       0x01d7f004,
+       0xf101d3f0,
        0xd007ac07,
-       0x04bd000e,
+       0x04bd000d,
 /* 0x001c: rd32_wait */
-       0x07ace7f1,
-       0xf100eecf,
-       0xf47000e4,
+       0x07acd7f1,
+       0xf100ddcf,
+       0xf47000d4,
        0xd7f1f51b,
        0xddcf07a4,
 /* 0x0033: wr32 */
@@ -802,14 +804,14 @@ uint32_t nvd0_pwr_code[] = {
        0x04bd000e,
        0x07a407f1,
        0xbd000dd0,
-       0x02e7f004,
-       0xf0f0e5f0,
-       0x07f101e3,
-       0x0ed007ac,
+       0x02d7f004,
+       0xf0f0d5f0,
+       0x07f101d3,
+       0x0dd007ac,
 /* 0x0057: wr32_wait */
        0xf104bd00,
-       0xcf07ace7,
-       0xe4f100ee,
+       0xcf07acd7,
+       0xd4f100dd,
        0x1bf47000,
 /* 0x0067: nsec */
        0xf000f8f5,
@@ -836,21 +838,21 @@ uint32_t nvd0_pwr_code[] = {
        0x9800f8e2,
        0x96b003e9,
        0x2a0bf400,
-       0xbb840a98,
+       0xbb9a0a98,
        0x1cf4029a,
        0x01d7f00f,
        0x020621f5,
        0x0ef494bd,
 /* 0x00c5: intr_watchdog_next_time */
-       0x850a9815,
+       0x9b0a9815,
        0xf400a6b0,
        0x9ab8090b,
        0x061cf406,
 /* 0x00d4: intr_watchdog_next_time_set */
 /* 0x00d7: intr_watchdog_next_proc */
-       0x80850980,
+       0x809b0980,
        0xe0b603e9,
-       0x10e6b158,
+       0x68e6b158,
        0xc61bf402,
 /* 0x00e6: intr */
        0x00f900f8,
@@ -868,15 +870,15 @@ uint32_t nvd0_pwr_code[] = {
        0x0887f004,
        0xc40088cf,
        0x0bf40289,
-       0x85008020,
+       0x9b008020,
        0xf458e7f0,
        0x0998a721,
-       0x0096b085,
+       0x0096b09b,
        0xf00e0bf4,
        0x09d03407,
        0x8004bd00,
 /* 0x013e: intr_skip_watchdog */
-       0x89e48409,
+       0x89e49a09,
        0x0bf40800,
        0x8897f13c,
        0x0099cf06,
@@ -929,7 +931,7 @@ uint32_t nvd0_pwr_code[] = {
        0x0ed03407,
        0x8004bd00,
 /* 0x01f6: timer_enable */
-       0x87f0840e,
+       0x87f09a0e,
        0x3807f001,
        0xbd0008d0,
 /* 0x0201: timer_done */
@@ -960,7 +962,7 @@ uint32_t nvd0_pwr_code[] = {
        0x06aeb800,
        0xb6100bf4,
        0x86b15880,
-       0x1bf40210,
+       0x1bf40268,
        0x0132f4f0,
 /* 0x0264: find_done */
        0xfc028eb9,
@@ -1024,7 +1026,7 @@ uint32_t nvd0_pwr_code[] = {
        0x0bf40612,
        0x071ec42f,
        0xb704ee94,
-       0x980218e0,
+       0x980270e0,
        0xec9803eb,
        0x01ed9802,
        0xf500ee98,
@@ -1048,7 +1050,7 @@ uint32_t nvd0_pwr_code[] = {
        0xec0bf406,
        0xb60723c4,
        0x30b70434,
-       0x3b800298,
+       0x3b8002f0,
        0x023c8003,
        0x80013d80,
        0x20b6003e,
@@ -1061,12 +1063,12 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x03be: host_init */
        0x17f100f8,
        0x14b60080,
-       0x1815f110,
+       0x7015f110,
        0xd007f102,
        0x0001d004,
        0x17f104bd,
        0x14b60080,
-       0x9815f110,
+       0xf015f110,
        0xdc07f102,
        0x0001d004,
        0x17f004bd,
@@ -1122,13 +1124,13 @@ uint32_t nvd0_pwr_code[] = {
        0x10b60013,
        0x10349504,
        0x980c30f0,
-       0x55f9c835,
+       0x55f9de35,
        0xf40612b8,
        0xd0fcec1e,
        0x21f5e0fc,
        0x00f8026b,
 /* 0x04a8: memx_info */
-       0x0354c7f1,
+       0x03acc7f1,
        0x0800b7f1,
        0x026b21f5,
 /* 0x04b6: memx_recv */
@@ -1140,49 +1142,342 @@ uint32_t nvd0_pwr_code[] = {
 /* 0x04c6: perf_recv */
        0x00f800f8,
 /* 0x04c8: perf_init */
-/* 0x04ca: test_recv */
-       0x17f100f8,
-       0x11cf05d8,
-       0x0110b600,
-       0x05d807f1,
+/* 0x04ca: i2c_drive_scl */
+       0x36b000f8,
+       0x0e0bf400,
+       0x07e007f1,
        0xbd0001d0,
-       0x00e7f104,
-       0x4fe3f1d9,
-       0xb621f513,
-/* 0x04eb: test_init */
-       0xf100f801,
-       0xf50800e7,
-       0xf801b621,
-/* 0x04f5: idle_recv */
-/* 0x04f7: idle */
-       0xf400f800,
-       0x17f10031,
-       0x11cf05d4,
-       0x0110b600,
-       0x05d407f1,
-       0xbd0001d0,
-/* 0x050d: idle_loop */
-       0x5817f004,
-/* 0x0513: idle_proc */
-/* 0x0513: idle_proc_exec */
-       0xf90232f4,
-       0x021eb910,
-       0x027421f5,
-       0x11f410fc,
-       0x0231f409,
-/* 0x0527: idle_proc_next */
-       0xb6ef0ef4,
-       0x1fb85810,
-       0xe61bf406,
-       0xf4dd02f4,
-       0x0ef40028,
-       0x000000c1,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
-       0x00000000,
+/* 0x04db: i2c_drive_scl_lo */
+       0xf100f804,
+       0xd007e407,
+       0x04bd0001,
+/* 0x04e6: i2c_drive_sda */
+       0x36b000f8,
+       0x0e0bf400,
+       0x07e007f1,
+       0xbd0002d0,
+/* 0x04f7: i2c_drive_sda_lo */
+       0xf100f804,
+       0xd007e407,
+       0x04bd0002,
+/* 0x0502: i2c_sense_scl */
+       0x32f400f8,
+       0xc437f101,
+       0x0033cf07,
+       0xf40431fd,
+       0x31f4060b,
+/* 0x0515: i2c_sense_scl_done */
+/* 0x0517: i2c_sense_sda */
+       0xf400f801,
+       0x37f10132,
+       0x33cf07c4,
+       0x0432fd00,
+       0xf4060bf4,
+/* 0x052a: i2c_sense_sda_done */
+       0x00f80131,
+/* 0x052c: i2c_raise_scl */
+       0x47f140f9,
+       0x37f00898,
+       0xca21f501,
+/* 0x0539: i2c_raise_scl_wait */
+       0xe8e7f104,
+       0x6721f403,
+       0x050221f5,
+       0xb60901f4,
+       0x1bf40142,
+/* 0x054d: i2c_raise_scl_done */
+       0xf840fcef,
+/* 0x0551: i2c_start */
+       0x0221f500,
+       0x0d11f405,
+       0x051721f5,
+       0xf40611f4,
+/* 0x0562: i2c_start_rep */
+       0x37f0300e,
+       0xca21f500,
+       0x0137f004,
+       0x04e621f5,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x2c21f550,
+       0x0464b605,
+/* 0x058f: i2c_start_send */
+       0xf01f11f4,
+       0x21f50037,
+       0xe7f104e6,
+       0x21f41388,
+       0x0037f067,
+       0x04ca21f5,
+       0x1388e7f1,
+/* 0x05ab: i2c_start_out */
+       0xf86721f4,
+/* 0x05ad: i2c_stop */
+       0x0037f000,
+       0x04ca21f5,
+       0xf50037f0,
+       0xf104e621,
+       0xf403e8e7,
+       0x37f06721,
+       0xca21f501,
+       0x88e7f104,
+       0x6721f413,
+       0xf50137f0,
+       0xf104e621,
+       0xf41388e7,
+       0x00f86721,
+/* 0x05e0: i2c_bitw */
+       0x04e621f5,
+       0x03e8e7f1,
+       0xbb6721f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x052c21f5,
+       0xf40464b6,
+       0xe7f11811,
+       0x21f41388,
+       0x0037f067,
+       0x04ca21f5,
+       0x1388e7f1,
+/* 0x061f: i2c_bitw_out */
+       0xf86721f4,
+/* 0x0621: i2c_bitr */
+       0x0137f000,
+       0x04e621f5,
+       0x03e8e7f1,
+       0xbb6721f4,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x052c21f5,
+       0xf40464b6,
+       0x21f51b11,
+       0x37f00517,
+       0xca21f500,
+       0x88e7f104,
+       0x6721f413,
+       0xf4013cf0,
+/* 0x0666: i2c_bitr_done */
+       0x00f80131,
+/* 0x0668: i2c_get_byte */
+       0xf00057f0,
+/* 0x066e: i2c_get_byte_next */
+       0x54b60847,
+       0x0076bb01,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b60621,
+       0x2b11f404,
+       0xb60553fd,
+       0x1bf40142,
+       0x0137f0d8,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xe021f550,
+       0x0464b605,
+/* 0x06b8: i2c_get_byte_done */
+/* 0x06ba: i2c_put_byte */
+       0x47f000f8,
+/* 0x06bd: i2c_put_byte_next */
+       0x0142b608,
+       0xbb3854ff,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x05e021f5,
+       0xf40464b6,
+       0x46b03411,
+       0xd81bf400,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x2121f550,
+       0x0464b606,
+       0xbb0f11f4,
+       0x36b00076,
+       0x061bf401,
+/* 0x0713: i2c_put_byte_done */
+       0xf80132f4,
+/* 0x0715: i2c_addr */
+       0x0076bb00,
+       0xf90465b6,
+       0x04659450,
+       0xbd0256bb,
+       0x0475fd50,
+       0x21f550fc,
+       0x64b60551,
+       0x2911f404,
+       0x012ec3e7,
+       0xfd0134b6,
+       0x76bb0553,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb606ba21,
+/* 0x075a: i2c_addr_done */
+       0x00f80464,
+/* 0x075c: i2c_acquire_addr */
+       0xb6f8cec7,
+       0xe0b705e4,
+       0x00f8d014,
+/* 0x0768: i2c_acquire */
+       0x075c21f5,
+       0xf00421f4,
+       0x21f403d9,
+/* 0x0777: i2c_release */
+       0xf500f833,
+       0xf4075c21,
+       0xdaf00421,
+       0x3321f403,
+/* 0x0786: i2c_recv */
+       0x32f400f8,
+       0xf8c1c701,
+       0xb00214b6,
+       0x1ff52816,
+       0x13a0013a,
+       0x32980bd4,
+       0xac13a000,
+       0x0031980b,
+       0xf90231f4,
+       0xf9e0f9d0,
+       0x0067f1d0,
+       0x0063f100,
+       0x01679210,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x6821f550,
+       0x0464b607,
+       0xd6b0d0fc,
+       0xb31bf500,
+       0x0057f000,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0x1521f550,
+       0x0464b607,
+       0x00d011f5,
+       0xbbe0c5c7,
+       0x65b60076,
+       0x9450f904,
+       0x56bb0465,
+       0xfd50bd02,
+       0x50fc0475,
+       0x06ba21f5,
+       0xf50464b6,
+       0xf000ad11,
+       0x76bb0157,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6071521,
+       0x11f50464,
+       0x76bb008a,
+       0x0465b600,
+       0x659450f9,
+       0x0256bb04,
+       0x75fd50bd,
+       0xf550fc04,
+       0xb6066821,
+       0x11f40464,
+       0xe05bcb6a,
+       0xb60076bb,
+       0x50f90465,
+       0xbb046594,
+       0x50bd0256,
+       0xfc0475fd,
+       0xad21f550,
+       0x0464b605,
+       0xbd025bb9,
+       0x430ef474,
+/* 0x088c: i2c_recv_not_rd08 */
+       0xf401d6b0,
+       0x57f03d1b,
+       0x1521f500,
+       0x3311f407,
+       0xf5e0c5c7,
+       0xf406ba21,
+       0x57f02911,
+       0x1521f500,
+       0x1f11f407,
+       0xf5e0b5c7,
+       0xf406ba21,
+       0x21f51511,
+       0x74bd05ad,
+       0xf408c5c7,
+       0x32f4091b,
+       0x030ef402,
+/* 0x08cc: i2c_recv_not_wr08 */
+/* 0x08cc: i2c_recv_done */
+       0xf5f8cec7,
+       0xfc077721,
+       0xf4d0fce0,
+       0x7cb90a12,
+       0x6b21f502,
+/* 0x08e1: i2c_recv_exit */
+/* 0x08e3: i2c_init */
+       0xf800f802,
+/* 0x08e5: test_recv */
+       0xd817f100,
+       0x0011cf05,
+       0xf10110b6,
+       0xd005d807,
+       0x04bd0001,
+       0xd900e7f1,
+       0x134fe3f1,
+       0x01b621f5,
+/* 0x0906: test_init */
+       0xe7f100f8,
+       0x21f50800,
+       0x00f801b6,
+/* 0x0910: idle_recv */
+/* 0x0912: idle */
+       0x31f400f8,
+       0xd417f100,
+       0x0011cf05,
+       0xf10110b6,
+       0xd005d407,
+       0x04bd0001,
+/* 0x0928: idle_loop */
+       0xf45817f0,
+/* 0x092e: idle_proc */
+/* 0x092e: idle_proc_exec */
+       0x10f90232,
+       0xf5021eb9,
+       0xfc027421,
+       0x0911f410,
+       0xf40231f4,
+/* 0x0942: idle_proc_next */
+       0x10b6ef0e,
+       0x061fb858,
+       0xf4e61bf4,
+       0x28f4dd02,
+       0xc10ef400,
        0x00000000,
        0x00000000,
        0x00000000,
index 5fb0cccc6c64b593dbe1d2728a4011e793744f21..574acfa44c8c78f327dcd9d59cc7e1b6e9b2bc1f 100644 (file)
@@ -7,6 +7,7 @@
 #define PROC_HOST 0x54534f48
 #define PROC_MEMX 0x584d454d
 #define PROC_PERF 0x46524550
+#define PROC_I2C_ 0x5f433249
 #define PROC_TEST 0x54534554
 
 /* KERN: message identifiers */
 #define MEMX_WAIT   3
 #define MEMX_DELAY  4
 
+/* I2C_: message identifiers */
+#define I2C__MSG_RD08 0
+#define I2C__MSG_WR08 1
+
+#define I2C__MSG_DATA0_PORT 24:31
+#define I2C__MSG_DATA0_ADDR 14:23
+
+#define I2C__MSG_DATA0_RD08_PORT I2C__MSG_DATA0_PORT
+#define I2C__MSG_DATA0_RD08_ADDR I2C__MSG_DATA0_ADDR
+#define I2C__MSG_DATA0_RD08_REG 0:7
+#define I2C__MSG_DATA1_RD08_VAL 0:7
+
+#define I2C__MSG_DATA0_WR08_PORT I2C__MSG_DATA0_PORT
+#define I2C__MSG_DATA0_WR08_ADDR I2C__MSG_DATA0_ADDR
+#define I2C__MSG_DATA0_WR08_SYNC 8:8
+#define I2C__MSG_DATA0_WR08_REG 0:7
+#define I2C__MSG_DATA1_WR08_VAL 0:7
+
 #endif
index e44ed7b93c6d88db3826a6c6dcb13efd5429385a..7610fc5f8fa256de8038e3770ca227a3d0150c64 100644 (file)
@@ -29,9 +29,9 @@
 
 static bool
 probe_monitoring_device(struct nouveau_i2c_port *i2c,
-                       struct i2c_board_info *info)
+                       struct i2c_board_info *info, void *data)
 {
-       struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c);
+       struct nouveau_therm_priv *priv = data;
        struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
        struct i2c_client *client;
 
@@ -96,7 +96,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
                };
 
                i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                                 board, probe_monitoring_device);
+                             board, probe_monitoring_device, therm);
                if (priv->ic)
                        return;
        }
@@ -108,7 +108,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
                };
 
                i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                                 board, probe_monitoring_device);
+                             board, probe_monitoring_device, therm);
                if (priv->ic)
                        return;
        }
@@ -117,5 +117,5 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
           device. Let's try our static list.
         */
        i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                     nv_board_infos, probe_monitoring_device);
+                     nv_board_infos, probe_monitoring_device, therm);
 }
index ef3133e7575c8eaf937520cf750bd51effcd7505..7dd680ff2f6f63683f34e39a1d7821f3c73c140c 100644 (file)
@@ -72,13 +72,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
        vmm->flush(vm);
 }
 
-void
-nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
-{
-       nouveau_vm_map_at(vma, 0, node);
-}
-
-void
+static void
 nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
                        struct nouveau_mem *mem)
 {
@@ -136,7 +130,7 @@ finish:
        vmm->flush(vm);
 }
 
-void
+static void
 nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
                  struct nouveau_mem *mem)
 {
@@ -174,6 +168,18 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
        vmm->flush(vm);
 }
 
+void
+nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
+{
+       if (node->sg)
+               nouveau_vm_map_sg_table(vma, 0, node->size << 12, node);
+       else
+       if (node->pages)
+               nouveau_vm_map_sg(vma, 0, node->size << 12, node);
+       else
+               nouveau_vm_map_at(vma, 0, node);
+}
+
 void
 nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length)
 {
index 936a71c5908076814a4aa8ffc5c2a3757e745ea5..7fdc51e2a571bee85b6fcf707890c8e4138ca8d9 100644 (file)
@@ -643,7 +643,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
            get_tmds_slave(encoder))
                return;
 
-       type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL);
+       type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL, NULL);
        if (type < 0)
                return;
 
index b13ff0fc42de4b2dcaf175e4a1ec3a126f04732c..2f1ed61f7c8c9e39d44c1528410eb4aaeb83fe17 100644 (file)
@@ -77,11 +77,6 @@ nv04_display_create(struct drm_device *dev)
 
        nouveau_hw_save_vga_fonts(dev, 1);
 
-       ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, 0xd1500000,
-                                NV04_DISP_CLASS, NULL, 0, &disp->core);
-       if (ret)
-               return ret;
-
        nv04_crtc_create(dev, 0);
        if (nv_two_heads(dev))
                nv04_crtc_create(dev, 1);
index 56a28db040004fe6ecfebb6b3b69c8feda6a85f5..4245fc3dab70e5ce06964cc70296ef4e6929a9b8 100644 (file)
@@ -80,7 +80,6 @@ struct nv04_display {
        struct nv04_mode_state saved_reg;
        uint32_t saved_vga_font[4][16384];
        uint32_t dac_users[4];
-       struct nouveau_object *core;
        struct nouveau_bo *image[2];
 };
 
index 32e7064b819b6df4f9e5847beba7a826eaaed726..ab03f7719d2d3af06687ea0b1e840290094ad8dd 100644 (file)
@@ -55,9 +55,12 @@ struct nouveau_plane {
        int hue;
        int saturation;
        int iturbt_709;
+
+       void (*set_params)(struct nouveau_plane *);
 };
 
 static uint32_t formats[] = {
+       DRM_FORMAT_YUYV,
        DRM_FORMAT_UYVY,
        DRM_FORMAT_NV12,
 };
@@ -140,10 +143,10 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        nv_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x);
        nv_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w);
 
-       if (fb->pixel_format == DRM_FORMAT_NV12) {
+       if (fb->pixel_format != DRM_FORMAT_UYVY)
                format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
+       if (fb->pixel_format == DRM_FORMAT_NV12)
                format |= NV_PVIDEO_FORMAT_PLANAR;
-       }
        if (nv_plane->iturbt_709)
                format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
        if (nv_plane->colorkey & (1 << 24))
@@ -182,9 +185,9 @@ nv10_disable_plane(struct drm_plane *plane)
 }
 
 static void
-nv10_destroy_plane(struct drm_plane *plane)
+nv_destroy_plane(struct drm_plane *plane)
 {
-       nv10_disable_plane(plane);
+       plane->funcs->disable_plane(plane);
        drm_plane_cleanup(plane);
        kfree(plane);
 }
@@ -217,9 +220,9 @@ nv10_set_params(struct nouveau_plane *plane)
 }
 
 static int
-nv10_set_property(struct drm_plane *plane,
-                 struct drm_property *property,
-                 uint64_t value)
+nv_set_property(struct drm_plane *plane,
+               struct drm_property *property,
+               uint64_t value)
 {
        struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
 
@@ -238,15 +241,16 @@ nv10_set_property(struct drm_plane *plane,
        else
                return -EINVAL;
 
-       nv10_set_params(nv_plane);
+       if (nv_plane->set_params)
+               nv_plane->set_params(nv_plane);
        return 0;
 }
 
 static const struct drm_plane_funcs nv10_plane_funcs = {
        .update_plane = nv10_update_plane,
        .disable_plane = nv10_disable_plane,
-       .set_property = nv10_set_property,
-       .destroy = nv10_destroy_plane,
+       .set_property = nv_set_property,
+       .destroy = nv_destroy_plane,
 };
 
 static void
@@ -266,7 +270,7 @@ nv10_overlay_init(struct drm_device *device)
        case 0x15:
        case 0x1a:
        case 0x20:
-               num_formats = 1;
+               num_formats = 2;
                break;
        }
 
@@ -321,8 +325,159 @@ nv10_overlay_init(struct drm_device *device)
        drm_object_attach_property(&plane->base.base,
                                   plane->props.iturbt_709, plane->iturbt_709);
 
+       plane->set_params = nv10_set_params;
        nv10_set_params(plane);
-       nv_wr32(dev, NV_PVIDEO_STOP, 1);
+       nv10_disable_plane(&plane->base);
+       return;
+cleanup:
+       drm_plane_cleanup(&plane->base);
+err:
+       kfree(plane);
+       nv_error(dev, "Failed to create plane\n");
+}
+
+static int
+nv04_update_plane(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 nouveau_device *dev = nouveau_dev(plane->dev);
+       struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
+       struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
+       struct nouveau_bo *cur = nv_plane->cur;
+       uint32_t overlay = 1;
+       int brightness = (nv_plane->brightness - 512) * 62 / 512;
+       int pitch, ret, i;
+
+       /* Source parameters given in 16.16 fixed point, ignore fractional. */
+       src_x >>= 16;
+       src_y >>= 16;
+       src_w >>= 16;
+       src_h >>= 16;
+
+       pitch = ALIGN(src_w * 4, 0x100);
+
+       if (pitch > 0xffff)
+               return -ERANGE;
+
+       /* TODO: Compute an offset? Not sure how to do this for YUYV. */
+       if (src_x != 0 || src_y != 0)
+               return -ERANGE;
+
+       if (crtc_w < src_w || crtc_h < src_h)
+               return -ERANGE;
+
+       ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
+       if (ret)
+               return ret;
+
+       nv_plane->cur = nv_fb->nvbo;
+
+       nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+       nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+       nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+
+       for (i = 0; i < 2; i++) {
+               nv_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
+                       nv_fb->nvbo->bo.offset);
+               nv_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch);
+               nv_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
+       }
+       nv_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x);
+       nv_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w);
+       nv_wr32(dev, NV_PVIDEO_STEP_SIZE,
+               (uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1)));
+
+       /* It should be possible to convert hue/contrast to this */
+       nv_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness);
+       nv_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness);
+       nv_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness);
+       nv_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0);
+
+       nv_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */
+       nv_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */
+
+       nv_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03);
+       nv_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38);
+
+       nv_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey);
+
+       if (nv_plane->colorkey & (1 << 24))
+               overlay |= 0x10;
+       if (fb->pixel_format == DRM_FORMAT_YUYV)
+               overlay |= 0x100;
+
+       nv_wr32(dev, NV_PVIDEO_OVERLAY, overlay);
+
+       nv_wr32(dev, NV_PVIDEO_SU_STATE, nv_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16));
+
+       if (cur)
+               nouveau_bo_unpin(cur);
+
+       return 0;
+}
+
+static int
+nv04_disable_plane(struct drm_plane *plane)
+{
+       struct nouveau_device *dev = nouveau_dev(plane->dev);
+       struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
+
+       nv_mask(dev, NV_PVIDEO_OVERLAY, 1, 0);
+       nv_wr32(dev, NV_PVIDEO_OE_STATE, 0);
+       nv_wr32(dev, NV_PVIDEO_SU_STATE, 0);
+       nv_wr32(dev, NV_PVIDEO_RM_STATE, 0);
+       if (nv_plane->cur) {
+               nouveau_bo_unpin(nv_plane->cur);
+               nv_plane->cur = NULL;
+       }
+
+       return 0;
+}
+
+static const struct drm_plane_funcs nv04_plane_funcs = {
+       .update_plane = nv04_update_plane,
+       .disable_plane = nv04_disable_plane,
+       .set_property = nv_set_property,
+       .destroy = nv_destroy_plane,
+};
+
+static void
+nv04_overlay_init(struct drm_device *device)
+{
+       struct nouveau_device *dev = nouveau_dev(device);
+       struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
+       int ret;
+
+       if (!plane)
+               return;
+
+       ret = drm_plane_init(device, &plane->base, 1 /* single crtc */,
+                            &nv04_plane_funcs,
+                            formats, 2, false);
+       if (ret)
+               goto err;
+
+       /* Set up the plane properties */
+       plane->props.colorkey = drm_property_create_range(
+                       device, 0, "colorkey", 0, 0x01ffffff);
+       plane->props.brightness = drm_property_create_range(
+                       device, 0, "brightness", 0, 1024);
+       if (!plane->props.colorkey ||
+           !plane->props.brightness)
+               goto cleanup;
+
+       plane->colorkey = 0;
+       drm_object_attach_property(&plane->base.base,
+                                  plane->props.colorkey, plane->colorkey);
+
+       plane->brightness = 512;
+       drm_object_attach_property(&plane->base.base,
+                                  plane->props.brightness, plane->brightness);
+
+       nv04_disable_plane(&plane->base);
        return;
 cleanup:
        drm_plane_cleanup(&plane->base);
@@ -335,6 +490,8 @@ void
 nouveau_overlay_init(struct drm_device *device)
 {
        struct nouveau_device *dev = nouveau_dev(device);
-       if (dev->chipset >= 0x10 && dev->chipset <= 0x40)
+       if (dev->chipset < 0x10)
+               nv04_overlay_init(device);
+       else if (dev->chipset <= 0x40)
                nv10_overlay_init(device);
 }
index cc4b208ce546d50aad1813810981099fe6d81935..244822df8ffc73d1e9f15075c7ee6faa54368a84 100644 (file)
@@ -59,7 +59,7 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index)
        struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
 
        return i2c->identify(i2c, i2c_index, "TV encoder",
-                            nv04_tv_encoder_info, NULL);
+                            nv04_tv_encoder_info, NULL, NULL);
 }
 
 
index 6828d81ed7b99daea875ffd06c4dd399d4aa05dd..900fae01793e7884ee8033a11d6c247cbeb36678 100644 (file)
@@ -447,6 +447,8 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        if (ret)
                goto done;
 
+       info->offset = ntfy->node->offset;
+
 done:
        if (ret)
                nouveau_abi16_ntfy_fini(chan, ntfy);
index 95c740454049ad1b4a4cf23c2bc63d7038c7a362..d9f6120e972e649ccc77be83abb9a53f9660ec9a 100644 (file)
@@ -51,6 +51,7 @@ static struct nouveau_dsm_priv {
        bool dsm_detected;
        bool optimus_detected;
        acpi_handle dhandle;
+       acpi_handle other_handle;
        acpi_handle rom_handle;
 } nouveau_dsm_priv;
 
@@ -65,6 +66,7 @@ bool nouveau_is_v1_dsm(void) {
 #define NOUVEAU_DSM_HAS_MUX 0x1
 #define NOUVEAU_DSM_HAS_OPT 0x2
 
+#ifdef CONFIG_VGA_SWITCHEROO
 static const char nouveau_dsm_muid[] = {
        0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
        0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
@@ -260,9 +262,10 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
        if (!dhandle)
                return false;
 
-       if (!acpi_has_method(dhandle, "_DSM"))
+       if (!acpi_has_method(dhandle, "_DSM")) {
+               nouveau_dsm_priv.other_handle = dhandle;
                return false;
-
+       }
        if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
 
@@ -338,6 +341,16 @@ static bool nouveau_dsm_detect(void)
                printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
                        acpi_method_name);
                nouveau_dsm_priv.dsm_detected = true;
+               /*
+                * On some systems hotplug events are generated for the device
+                * being switched off when _DSM is executed.  They cause ACPI
+                * hotplug to trigger and attempt to remove the device from
+                * the system, which causes it to break down.  Prevent that from
+                * happening by setting the no_hotplug flag for the involved
+                * ACPI device objects.
+                */
+               acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
+               acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
                ret = true;
        }
 
@@ -376,6 +389,11 @@ void nouveau_unregister_dsm_handler(void)
        if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected)
                vga_switcheroo_unregister_handler();
 }
+#else
+void nouveau_register_dsm_handler(void) {}
+void nouveau_unregister_dsm_handler(void) {}
+void nouveau_switcheroo_optimus_dsm(void) {}
+#endif
 
 /* retrieve the ROM in 4k blocks */
 static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
index c0fde6b9393cb24fa602e838fdf145657d059d05..488686d490c0c7a96ba016e0f55a4beffcda6e4f 100644 (file)
@@ -560,28 +560,6 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
 }
 
 
-/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
- * TTM_PL_{VRAM,TT} directly.
- */
-
-static int
-nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
-                             struct nouveau_bo *nvbo, bool evict,
-                             bool no_wait_gpu, struct ttm_mem_reg *new_mem)
-{
-       struct nouveau_fence *fence = NULL;
-       int ret;
-
-       ret = nouveau_fence_new(chan, false, &fence);
-       if (ret)
-               return ret;
-
-       ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, evict,
-                                       no_wait_gpu, new_mem);
-       nouveau_fence_unref(&fence);
-       return ret;
-}
-
 static int
 nve0_bo_move_init(struct nouveau_channel *chan, u32 handle)
 {
@@ -798,25 +776,25 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
        struct nouveau_mem *node = old_mem->mm_node;
-       struct nouveau_bo *nvbo = nouveau_bo(bo);
        u64 length = (new_mem->num_pages << PAGE_SHIFT);
        u64 src_offset = node->vma[0].offset;
        u64 dst_offset = node->vma[1].offset;
+       int src_tiled = !!node->memtype;
+       int dst_tiled = !!((struct nouveau_mem *)new_mem->mm_node)->memtype;
        int ret;
 
        while (length) {
                u32 amount, stride, height;
 
+               ret = RING_SPACE(chan, 18 + 6 * (src_tiled + dst_tiled));
+               if (ret)
+                       return ret;
+
                amount  = min(length, (u64)(4 * 1024 * 1024));
                stride  = 16 * 4;
                height  = amount / stride;
 
-               if (old_mem->mem_type == TTM_PL_VRAM &&
-                   nouveau_bo_tile_layout(nvbo)) {
-                       ret = RING_SPACE(chan, 8);
-                       if (ret)
-                               return ret;
-
+               if (src_tiled) {
                        BEGIN_NV04(chan, NvSubCopy, 0x0200, 7);
                        OUT_RING  (chan, 0);
                        OUT_RING  (chan, 0);
@@ -826,19 +804,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                        OUT_RING  (chan, 0);
                        OUT_RING  (chan, 0);
                } else {
-                       ret = RING_SPACE(chan, 2);
-                       if (ret)
-                               return ret;
-
                        BEGIN_NV04(chan, NvSubCopy, 0x0200, 1);
                        OUT_RING  (chan, 1);
                }
-               if (new_mem->mem_type == TTM_PL_VRAM &&
-                   nouveau_bo_tile_layout(nvbo)) {
-                       ret = RING_SPACE(chan, 8);
-                       if (ret)
-                               return ret;
-
+               if (dst_tiled) {
                        BEGIN_NV04(chan, NvSubCopy, 0x021c, 7);
                        OUT_RING  (chan, 0);
                        OUT_RING  (chan, 0);
@@ -848,18 +817,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                        OUT_RING  (chan, 0);
                        OUT_RING  (chan, 0);
                } else {
-                       ret = RING_SPACE(chan, 2);
-                       if (ret)
-                               return ret;
-
                        BEGIN_NV04(chan, NvSubCopy, 0x021c, 1);
                        OUT_RING  (chan, 1);
                }
 
-               ret = RING_SPACE(chan, 14);
-               if (ret)
-                       return ret;
-
                BEGIN_NV04(chan, NvSubCopy, 0x0238, 2);
                OUT_RING  (chan, upper_32_bits(src_offset));
                OUT_RING  (chan, upper_32_bits(dst_offset));
@@ -953,23 +914,28 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 }
 
 static int
-nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
-                  struct ttm_mem_reg *mem, struct nouveau_vma *vma)
+nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo,
+                    struct ttm_mem_reg *mem)
 {
-       struct nouveau_mem *node = mem->mm_node;
+       struct nouveau_mem *old_node = bo->mem.mm_node;
+       struct nouveau_mem *new_node = mem->mm_node;
+       u64 size = (u64)mem->num_pages << PAGE_SHIFT;
        int ret;
 
-       ret = nouveau_vm_get(nv_client(chan->cli)->vm, mem->num_pages <<
-                            PAGE_SHIFT, node->page_shift,
-                            NV_MEM_ACCESS_RW, vma);
+       ret = nouveau_vm_get(nv_client(drm)->vm, size, old_node->page_shift,
+                            NV_MEM_ACCESS_RW, &old_node->vma[0]);
        if (ret)
                return ret;
 
-       if (mem->mem_type == TTM_PL_VRAM)
-               nouveau_vm_map(vma, node);
-       else
-               nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, node);
+       ret = nouveau_vm_get(nv_client(drm)->vm, size, new_node->page_shift,
+                            NV_MEM_ACCESS_RW, &old_node->vma[1]);
+       if (ret) {
+               nouveau_vm_put(&old_node->vma[0]);
+               return ret;
+       }
 
+       nouveau_vm_map(&old_node->vma[0], old_node);
+       nouveau_vm_map(&old_node->vma[1], new_node);
        return 0;
 }
 
@@ -979,35 +945,34 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
 {
        struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
        struct nouveau_channel *chan = drm->ttm.chan;
-       struct nouveau_bo *nvbo = nouveau_bo(bo);
-       struct ttm_mem_reg *old_mem = &bo->mem;
+       struct nouveau_fence *fence;
        int ret;
 
-       mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING);
-
        /* create temporary vmas for the transfer and attach them to the
         * old nouveau_mem node, these will get cleaned up after ttm has
         * destroyed the ttm_mem_reg
         */
        if (nv_device(drm->device)->card_type >= NV_50) {
-               struct nouveau_mem *node = old_mem->mm_node;
-
-               ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]);
-               if (ret)
-                       goto out;
-
-               ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]);
+               ret = nouveau_bo_move_prep(drm, bo, new_mem);
                if (ret)
-                       goto out;
+                       return ret;
        }
 
-       ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
+       mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING);
+       ret = nouveau_fence_sync(bo->sync_obj, chan);
        if (ret == 0) {
-               ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict,
-                                                   no_wait_gpu, new_mem);
+               ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
+               if (ret == 0) {
+                       ret = nouveau_fence_new(chan, false, &fence);
+                       if (ret == 0) {
+                               ret = ttm_bo_move_accel_cleanup(bo, fence,
+                                                               evict,
+                                                               no_wait_gpu,
+                                                               new_mem);
+                               nouveau_fence_unref(&fence);
+                       }
+               }
        }
-
-out:
        mutex_unlock(&chan->cli->mutex);
        return ret;
 }
@@ -1147,19 +1112,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
                return;
 
        list_for_each_entry(vma, &nvbo->vma_list, head) {
-               if (new_mem && new_mem->mem_type == TTM_PL_VRAM) {
+               if (new_mem && new_mem->mem_type != TTM_PL_SYSTEM &&
+                             (new_mem->mem_type == TTM_PL_VRAM ||
+                              nvbo->page_shift != vma->vm->vmm->lpg_shift)) {
                        nouveau_vm_map(vma, new_mem->mm_node);
-               } else
-               if (new_mem && new_mem->mem_type == TTM_PL_TT &&
-                   nvbo->page_shift == vma->vm->vmm->spg_shift) {
-                       if (((struct nouveau_mem *)new_mem->mm_node)->sg)
-                               nouveau_vm_map_sg_table(vma, 0, new_mem->
-                                                 num_pages << PAGE_SHIFT,
-                                                 new_mem->mm_node);
-                       else
-                               nouveau_vm_map_sg(vma, 0, new_mem->
-                                                 num_pages << PAGE_SHIFT,
-                                                 new_mem->mm_node);
                } else {
                        nouveau_vm_unmap(vma);
                }
@@ -1224,28 +1180,27 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
                goto out;
        }
 
-       /* CPU copy if we have no accelerated method available */
-       if (!drm->ttm.move) {
-               ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
-               goto out;
-       }
-
        /* Hardware assisted copy. */
-       if (new_mem->mem_type == TTM_PL_SYSTEM)
-               ret = nouveau_bo_move_flipd(bo, evict, intr,
-                                           no_wait_gpu, new_mem);
-       else if (old_mem->mem_type == TTM_PL_SYSTEM)
-               ret = nouveau_bo_move_flips(bo, evict, intr,
-                                           no_wait_gpu, new_mem);
-       else
-               ret = nouveau_bo_move_m2mf(bo, evict, intr,
-                                          no_wait_gpu, new_mem);
-
-       if (!ret)
-               goto out;
+       if (drm->ttm.move) {
+               if (new_mem->mem_type == TTM_PL_SYSTEM)
+                       ret = nouveau_bo_move_flipd(bo, evict, intr,
+                                                   no_wait_gpu, new_mem);
+               else if (old_mem->mem_type == TTM_PL_SYSTEM)
+                       ret = nouveau_bo_move_flips(bo, evict, intr,
+                                                   no_wait_gpu, new_mem);
+               else
+                       ret = nouveau_bo_move_m2mf(bo, evict, intr,
+                                                  no_wait_gpu, new_mem);
+               if (!ret)
+                       goto out;
+       }
 
        /* Fallback to software copy. */
-       ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
+       spin_lock(&bo->bdev->fence_lock);
+       ret = ttm_bo_wait(bo, true, intr, no_wait_gpu);
+       spin_unlock(&bo->bdev->fence_lock);
+       if (ret == 0)
+               ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
 
 out:
        if (nv_device(drm->device)->card_type < NV_50) {
@@ -1271,6 +1226,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 {
        struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
        struct nouveau_drm *drm = nouveau_bdev(bdev);
+       struct nouveau_mem *node = mem->mm_node;
        struct drm_device *dev = drm->dev;
        int ret;
 
@@ -1293,14 +1249,16 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
                        mem->bus.is_iomem = !dev->agp->cant_use_aperture;
                }
 #endif
-               break;
+               if (!node->memtype)
+                       /* untiled */
+                       break;
+               /* fallthrough, tiled memory */
        case TTM_PL_VRAM:
                mem->bus.offset = mem->start << PAGE_SHIFT;
                mem->bus.base = pci_resource_start(dev->pdev, 1);
                mem->bus.is_iomem = true;
                if (nv_device(drm->device)->card_type >= NV_50) {
                        struct nouveau_bar *bar = nouveau_bar(drm->device);
-                       struct nouveau_mem *node = mem->mm_node;
 
                        ret = bar->umap(bar, node, NV_MEM_ACCESS_RW,
                                        &node->bar_vma);
@@ -1336,6 +1294,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
        struct nouveau_bo *nvbo = nouveau_bo(bo);
        struct nouveau_device *device = nv_device(drm->device);
        u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT;
+       int ret;
 
        /* as long as the bo isn't in vram, and isn't tiled, we've got
         * nothing to do here.
@@ -1344,10 +1303,20 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
                if (nv_device(drm->device)->card_type < NV_50 ||
                    !nouveau_bo_tile_layout(nvbo))
                        return 0;
+
+               if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+                       nouveau_bo_placement_set(nvbo, TTM_PL_TT, 0);
+
+                       ret = nouveau_bo_validate(nvbo, false, false);
+                       if (ret)
+                               return ret;
+               }
+               return 0;
        }
 
        /* make sure bo is in mappable vram */
-       if (bo->mem.start + bo->mem.num_pages < mappable)
+       if (nv_device(drm->device)->card_type >= NV_50 ||
+           bo->mem.start + bo->mem.num_pages < mappable)
                return 0;
 
 
@@ -1535,7 +1504,6 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
                   struct nouveau_vma *vma)
 {
        const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
-       struct nouveau_mem *node = nvbo->bo.mem.mm_node;
        int ret;
 
        ret = nouveau_vm_get(vm, size, nvbo->page_shift,
@@ -1543,15 +1511,10 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
        if (ret)
                return ret;
 
-       if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+       if ( nvbo->bo.mem.mem_type != TTM_PL_SYSTEM &&
+           (nvbo->bo.mem.mem_type == TTM_PL_VRAM ||
+            nvbo->page_shift != vma->vm->vmm->lpg_shift))
                nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
-       else if (nvbo->bo.mem.mem_type == TTM_PL_TT &&
-                nvbo->page_shift == vma->vm->vmm->spg_shift) {
-               if (node->sg)
-                       nouveau_vm_map_sg_table(vma, 0, size, node);
-               else
-                       nouveau_vm_map_sg(vma, 0, size, node);
-       }
 
        list_add_tail(&vma->head, &nvbo->vma_list);
        vma->refcount = 1;
index 29c3efdfc7dd714e00ae03525d0b9528fce841cd..b4262ad66b182de48af73965fb3c0ce4af250e4a 100644 (file)
@@ -74,14 +74,14 @@ nouveau_display_vblank_fini(struct drm_device *dev)
        struct nouveau_display *disp = nouveau_display(dev);
        int i;
 
+       drm_vblank_cleanup(dev);
+
        if (disp->vblank) {
                for (i = 0; i < dev->mode_config.num_crtc; i++)
                        nouveau_event_ref(NULL, &disp->vblank[i]);
                kfree(disp->vblank);
                disp->vblank = NULL;
        }
-
-       drm_vblank_cleanup(dev);
 }
 
 static int
@@ -407,10 +407,31 @@ nouveau_display_create(struct drm_device *dev)
        drm_kms_helper_poll_disable(dev);
 
        if (drm->vbios.dcb.entries) {
-               if (nv_device(drm->device)->card_type < NV_50)
-                       ret = nv04_display_create(dev);
-               else
-                       ret = nv50_display_create(dev);
+               static const u16 oclass[] = {
+                       NVF0_DISP_CLASS,
+                       NVE0_DISP_CLASS,
+                       NVD0_DISP_CLASS,
+                       NVA3_DISP_CLASS,
+                       NV94_DISP_CLASS,
+                       NVA0_DISP_CLASS,
+                       NV84_DISP_CLASS,
+                       NV50_DISP_CLASS,
+                       NV04_DISP_CLASS,
+               };
+               int i;
+
+               for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) {
+                       ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
+                                                NVDRM_DISPLAY, oclass[i],
+                                                NULL, 0, &disp->core);
+               }
+
+               if (ret == 0) {
+                       if (nv_mclass(disp->core) < NV50_DISP_CLASS)
+                               ret = nv04_display_create(dev);
+                       else
+                               ret = nv50_display_create(dev);
+               }
        } else {
                ret = 0;
        }
@@ -439,6 +460,7 @@ void
 nouveau_display_destroy(struct drm_device *dev)
 {
        struct nouveau_display *disp = nouveau_display(dev);
+       struct nouveau_drm *drm = nouveau_drm(dev);
 
        nouveau_backlight_exit(dev);
        nouveau_display_vblank_fini(dev);
@@ -449,6 +471,8 @@ nouveau_display_destroy(struct drm_device *dev)
        if (disp->dtor)
                disp->dtor(dev);
 
+       nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_DISPLAY);
+
        nouveau_drm(dev)->display = NULL;
        kfree(disp);
 }
@@ -603,6 +627,14 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        if (!s)
                return -ENOMEM;
 
+       if (new_bo != old_bo) {
+               ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
+               if (ret)
+                       goto fail_free;
+       }
+
+       mutex_lock(&chan->cli->mutex);
+
        /* synchronise rendering channel with the kernel's channel */
        spin_lock(&new_bo->bo.bdev->fence_lock);
        fence = nouveau_fence_ref(new_bo->bo.sync_obj);
@@ -610,15 +642,8 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        ret = nouveau_fence_sync(fence, chan);
        nouveau_fence_unref(&fence);
        if (ret)
-               return ret;
+               goto fail_free;
 
-       if (new_bo != old_bo) {
-               ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
-               if (ret)
-                       goto fail_free;
-       }
-
-       mutex_lock(&chan->cli->mutex);
        ret = ttm_bo_reserve(&old_bo->bo, true, false, false, NULL);
        if (ret)
                goto fail_unpin;
index 8bc8bab90e8d34462f0b484a90710a9094247216..73aa231130b8ddbb8e610881367f6daa81de070f 100644 (file)
@@ -36,6 +36,7 @@ struct nouveau_display {
        int  (*init)(struct drm_device *);
        void (*fini)(struct drm_device *);
 
+       struct nouveau_object *core;
        struct nouveau_eventh **vblank;
 
        struct drm_property *dithering_mode;
index 40f91e1e58422f0cdd7db3f607cde397966a7e8d..c177272152e24b7fb525891b8308668abfbeb460 100644 (file)
@@ -100,7 +100,7 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
 
        chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;
 
-       DRM_MEMORYBARRIER();
+       mb();
        /* Flush writes. */
        nouveau_bo_rd32(pb, 0);
 
index 984004d66a6d313d1934230bc654c091a77b5f8f..dc0e0c5cadb48753d0c814f4b24586620053fb10 100644 (file)
@@ -155,7 +155,7 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data)
 }
 
 #define WRITE_PUT(val) do {                                                    \
-       DRM_MEMORYBARRIER();                                                   \
+       mb();                                                   \
        nouveau_bo_rd32(chan->push.buffer, 0);                                 \
        nv_wo32(chan->object, chan->user_put, ((val) << 2) + chan->push.vma.offset);  \
 } while (0)
index 7a3759f1c41a67bac6b48cdcfd5b10b5ac30ae39..98a22e6e27a11f73045fdbab161452309f2416ab 100644 (file)
@@ -858,6 +858,12 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
        if (nouveau_runtime_pm == 0)
                return -EINVAL;
 
+       /* are we optimus enabled? */
+       if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
+               DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+               return -EINVAL;
+       }
+
        nv_debug_level(SILENT);
        drm_kms_helper_poll_disable(drm_dev);
        vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
index 4b0fb6c66be918857bc6529b3a7c5a7c7a49a498..23ca7a517246feda3e7dfae782683c88c2bc64a5 100644 (file)
@@ -54,6 +54,7 @@ enum nouveau_drm_handle {
        NVDRM_CLIENT  = 0xffffffff,
        NVDRM_DEVICE  = 0xdddddddd,
        NVDRM_CONTROL = 0xdddddddc,
+       NVDRM_DISPLAY = 0xd1500000,
        NVDRM_PUSH    = 0xbbbb0000, /* |= client chid */
        NVDRM_CHAN    = 0xcccc0000, /* |= client chid */
        NVDRM_NVSW    = 0x55550000,
index 40cf52e6d6d21ffb818f70b2b01be3b5f5e02b95..90074d620e31265bdcc70d4b7285fc9be077fee8 100644 (file)
@@ -143,7 +143,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
        int ret;
 
        fence->channel  = chan;
-       fence->timeout  = jiffies + (15 * DRM_HZ);
+       fence->timeout  = jiffies + (15 * HZ);
        fence->sequence = ++fctx->sequence;
 
        ret = fctx->emit(fence);
index 78a27f8ad7d97be653a63506bb60bd9c7b518252..27c3fd89e8ceb657595d188a8a3ff16cadde0edc 100644 (file)
@@ -463,12 +463,6 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
        list_for_each_entry(nvbo, list, entry) {
                struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
 
-               ret = validate_sync(chan, nvbo);
-               if (unlikely(ret)) {
-                       NV_ERROR(cli, "fail pre-validate sync\n");
-                       return ret;
-               }
-
                ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains,
                                             b->write_domains,
                                             b->valid_domains);
@@ -506,7 +500,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
                        b->presumed.valid = 0;
                        relocs++;
 
-                       if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
+                       if (copy_to_user(&upbbo[nvbo->pbbo_index].presumed,
                                             &b->presumed, sizeof(b->presumed)))
                                return -EFAULT;
                }
@@ -593,7 +587,7 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
        if (!mem)
                return ERR_PTR(-ENOMEM);
 
-       if (DRM_COPY_FROM_USER(mem, userptr, size)) {
+       if (copy_from_user(mem, userptr, size)) {
                u_free(mem);
                return ERR_PTR(-EFAULT);
        }
index 0843ebc910d4d6062ce94023f70dde1f1cc00ea0..a4d22e5eb176ef342023fdf0e581c564139139ed 100644 (file)
@@ -31,16 +31,17 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
 {
        struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
        struct nouveau_mem *node = mem->mm_node;
-       u64 size = mem->num_pages << 12;
 
        if (ttm->sg) {
-               node->sg = ttm->sg;
-               nouveau_vm_map_sg_table(&node->vma[0], 0, size, node);
+               node->sg    = ttm->sg;
+               node->pages = NULL;
        } else {
+               node->sg    = NULL;
                node->pages = nvbe->ttm.dma_address;
-               nouveau_vm_map_sg(&node->vma[0], 0, size, node);
        }
+       node->size = (mem->num_pages << PAGE_SHIFT) >> 12;
 
+       nouveau_vm_map(&node->vma[0], node);
        nvbe->node = node;
        return 0;
 }
@@ -67,9 +68,13 @@ nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
 
        /* noop: bound in move_notify() */
        if (ttm->sg) {
-               node->sg = ttm->sg;
-       } else
+               node->sg    = ttm->sg;
+               node->pages = NULL;
+       } else {
+               node->sg    = NULL;
                node->pages = nvbe->ttm.dma_address;
+       }
+       node->size = (mem->num_pages << PAGE_SHIFT) >> 12;
        return 0;
 }
 
index 19e3757291fba09434de033622fd4f5f6b35ea8c..d45d50da978f07870fb2bfc703ef509b4a2482f9 100644 (file)
@@ -171,6 +171,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
        node = kzalloc(sizeof(*node), GFP_KERNEL);
        if (!node)
                return -ENOMEM;
+
        node->page_shift = 12;
 
        switch (nv_device(drm->device)->card_type) {
index 4e384a2f99c3627ea0fc6e31f5f0e34ac95e71e8..6ae7a697866e1ccca6e3fc4aa481def0e1e82992 100644 (file)
@@ -2199,16 +2199,6 @@ nv50_display_destroy(struct drm_device *dev)
 int
 nv50_display_create(struct drm_device *dev)
 {
-       static const u16 oclass[] = {
-               NVF0_DISP_CLASS,
-               NVE0_DISP_CLASS,
-               NVD0_DISP_CLASS,
-               NVA3_DISP_CLASS,
-               NV94_DISP_CLASS,
-               NVA0_DISP_CLASS,
-               NV84_DISP_CLASS,
-               NV50_DISP_CLASS,
-       };
        struct nouveau_device *device = nouveau_dev(dev);
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct dcb_table *dcb = &drm->vbios.dcb;
@@ -2225,6 +2215,7 @@ nv50_display_create(struct drm_device *dev)
        nouveau_display(dev)->dtor = nv50_display_destroy;
        nouveau_display(dev)->init = nv50_display_init;
        nouveau_display(dev)->fini = nv50_display_fini;
+       disp->core = nouveau_display(dev)->core;
 
        /* small shared memory area we use for notifiers and semaphores */
        ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
@@ -2240,17 +2231,6 @@ nv50_display_create(struct drm_device *dev)
                        nouveau_bo_ref(NULL, &disp->sync);
        }
 
-       if (ret)
-               goto out;
-
-       /* attempt to allocate a supported evo display class */
-       ret = -ENODEV;
-       for (i = 0; ret && i < ARRAY_SIZE(oclass); i++) {
-               ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE,
-                                        0xd1500000, oclass[i], NULL, 0,
-                                        &disp->core);
-       }
-
        if (ret)
                goto out;
 
index 0fd2eb139f6e402cd6856d5996ee4faf6affa950..4313bb0a49a62a70039e1bd952a402e2ac54221e 100644 (file)
@@ -411,7 +411,7 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
        struct drm_crtc *crtc = &omap_crtc->base;
        DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
        /* avoid getting in a flood, unregister the irq until next vblank */
-       omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+       __omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
 }
 
 static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -421,13 +421,13 @@ static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
        struct drm_crtc *crtc = &omap_crtc->base;
 
        if (!omap_crtc->error_irq.registered)
-               omap_irq_register(crtc->dev, &omap_crtc->error_irq);
+               __omap_irq_register(crtc->dev, &omap_crtc->error_irq);
 
        if (!dispc_mgr_go_busy(omap_crtc->channel)) {
                struct omap_drm_private *priv =
                                crtc->dev->dev_private;
                DBG("%s: apply done", omap_crtc->name);
-               omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
+               __omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
                queue_work(priv->wq, &omap_crtc->apply_work);
        }
 }
@@ -623,6 +623,11 @@ void omap_crtc_pre_init(void)
        dss_install_mgr_ops(&mgr_ops);
 }
 
+void omap_crtc_pre_uninit(void)
+{
+       dss_uninstall_mgr_ops();
+}
+
 /* initialize crtc */
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
                struct drm_plane *plane, enum omap_channel channel, int id)
index c27f59da7f2935f0fe3a1908b9a73c9a4c6b7529..d4c04d69fc4df62a62352db72cd035ae6e5e53d1 100644 (file)
@@ -48,7 +48,7 @@ static int mm_show(struct seq_file *m, void *arg)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
-       return drm_mm_dump_table(m, dev->mm_private);
+       return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
 }
 
 static int fb_show(struct seq_file *m, void *arg)
index 701c4c10e08b5858a5e083d05329af23c076669e..f926b4caf44989be904451c277049152cfc9b9ad 100644 (file)
@@ -969,12 +969,21 @@ static const struct dev_pm_ops omap_dmm_pm_ops = {
 };
 #endif
 
+#if defined(CONFIG_OF)
+static const struct of_device_id dmm_of_match[] = {
+       { .compatible = "ti,omap4-dmm", },
+       { .compatible = "ti,omap5-dmm", },
+       {},
+};
+#endif
+
 struct platform_driver omap_dmm_driver = {
        .probe = omap_dmm_probe,
        .remove = omap_dmm_remove,
        .driver = {
                .owner = THIS_MODULE,
                .name = DMM_DRIVER_NAME,
+               .of_match_table = of_match_ptr(dmm_of_match),
 #ifdef CONFIG_PM
                .pm = &omap_dmm_pm_ops,
 #endif
index e7fa3cd9674389e1cac2de91816ce6b0013b2a1b..bf39fcc49e0f181ddcbf340632fa4f77c8b1bb10 100644 (file)
@@ -86,6 +86,47 @@ static bool channel_used(struct drm_device *dev, enum omap_channel channel)
 
        return false;
 }
+static void omap_disconnect_dssdevs(void)
+{
+       struct omap_dss_device *dssdev = NULL;
+
+       for_each_dss_dev(dssdev)
+               dssdev->driver->disconnect(dssdev);
+}
+
+static int omap_connect_dssdevs(void)
+{
+       int r;
+       struct omap_dss_device *dssdev = NULL;
+       bool no_displays = true;
+
+       for_each_dss_dev(dssdev) {
+               r = dssdev->driver->connect(dssdev);
+               if (r == -EPROBE_DEFER) {
+                       omap_dss_put_device(dssdev);
+                       goto cleanup;
+               } else if (r) {
+                       dev_warn(dssdev->dev, "could not connect display: %s\n",
+                               dssdev->name);
+               } else {
+                       no_displays = false;
+               }
+       }
+
+       if (no_displays)
+               return -EPROBE_DEFER;
+
+       return 0;
+
+cleanup:
+       /*
+        * if we are deferring probe, we disconnect the devices we previously
+        * connected
+        */
+       omap_disconnect_dssdevs();
+
+       return r;
+}
 
 static int omap_modeset_init(struct drm_device *dev)
 {
@@ -95,9 +136,6 @@ static int omap_modeset_init(struct drm_device *dev)
        int num_mgrs = dss_feat_get_num_mgrs();
        int num_crtcs;
        int i, id = 0;
-       int r;
-
-       omap_crtc_pre_init();
 
        drm_mode_config_init(dev);
 
@@ -119,26 +157,8 @@ static int omap_modeset_init(struct drm_device *dev)
                enum omap_channel channel;
                struct omap_overlay_manager *mgr;
 
-               if (!dssdev->driver) {
-                       dev_warn(dev->dev, "%s has no driver.. skipping it\n",
-                                       dssdev->name);
-                       continue;
-               }
-
-               if (!(dssdev->driver->get_timings ||
-                                       dssdev->driver->read_edid)) {
-                       dev_warn(dev->dev, "%s driver does not support "
-                               "get_timings or read_edid.. skipping it!\n",
-                               dssdev->name);
-                       continue;
-               }
-
-               r = dssdev->driver->connect(dssdev);
-               if (r) {
-                       dev_err(dev->dev, "could not connect display: %s\n",
-                                       dssdev->name);
+               if (!omapdss_device_is_connected(dssdev))
                        continue;
-               }
 
                encoder = omap_encoder_init(dev, dssdev);
 
@@ -497,16 +517,16 @@ static int dev_unload(struct drm_device *dev)
        DBG("unload: dev=%p", dev);
 
        drm_kms_helper_poll_fini(dev);
-       drm_vblank_cleanup(dev);
-       omap_drm_irq_uninstall(dev);
 
        omap_fbdev_free(dev);
        omap_modeset_free(dev);
        omap_gem_deinit(dev);
 
-       flush_workqueue(priv->wq);
        destroy_workqueue(priv->wq);
 
+       drm_vblank_cleanup(dev);
+       omap_drm_irq_uninstall(dev);
+
        kfree(dev->dev_private);
        dev->dev_private = NULL;
 
@@ -655,9 +675,19 @@ static void pdev_shutdown(struct platform_device *device)
 
 static int pdev_probe(struct platform_device *device)
 {
+       int r;
+
        if (omapdss_is_initialized() == false)
                return -EPROBE_DEFER;
 
+       omap_crtc_pre_init();
+
+       r = omap_connect_dssdevs();
+       if (r) {
+               omap_crtc_pre_uninit();
+               return r;
+       }
+
        DBG("%s", device->name);
        return drm_platform_init(&omap_drm_driver, device);
 }
@@ -665,9 +695,11 @@ static int pdev_probe(struct platform_device *device)
 static int pdev_remove(struct platform_device *device)
 {
        DBG("");
-       drm_platform_exit(&omap_drm_driver, device);
 
-       platform_driver_unregister(&omap_dmm_driver);
+       omap_disconnect_dssdevs();
+       omap_crtc_pre_uninit();
+
+       drm_put_dev(platform_get_drvdata(device));
        return 0;
 }
 
index 07847693cf494caababe5780bae717ef393c8af1..428b2981fd685f3e42b3ec4d0a63021a94fdaf15 100644 (file)
@@ -141,10 +141,12 @@ int omap_gem_resume(struct device *dev);
 
 int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id);
 void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id);
-irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
+irqreturn_t omap_irq_handler(int irq, void *arg);
 void omap_irq_preinstall(struct drm_device *dev);
 int omap_irq_postinstall(struct drm_device *dev);
 void omap_irq_uninstall(struct drm_device *dev);
+void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
+void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
 void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
 void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
 int omap_drm_irq_uninstall(struct drm_device *dev);
@@ -158,6 +160,7 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
 int omap_crtc_apply(struct drm_crtc *crtc,
                struct omap_drm_apply *apply);
 void omap_crtc_pre_init(void);
+void omap_crtc_pre_uninit(void);
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
                struct drm_plane *plane, enum omap_channel channel, int id);
 
index 6a12e899235bfe480dda3fd1bf80876bc6c805aa..5290a88c681db3e6cd2d4a9e4fa32c0e50230153 100644 (file)
@@ -51,6 +51,9 @@ struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder)
 static void omap_encoder_destroy(struct drm_encoder *encoder)
 {
        struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+
+       omap_encoder_set_enabled(encoder, false);
+
        drm_encoder_cleanup(encoder);
        kfree(omap_encoder);
 }
index f2b8f0668c0c1701887e8b6c4a8ccb3b3bf1952b..f466c4aaee9464c7ca4c16d684a4e7d4bfec5584 100644 (file)
@@ -123,12 +123,16 @@ static int omap_framebuffer_dirty(struct drm_framebuffer *fb,
 {
        int i;
 
+       drm_modeset_lock_all(fb->dev);
+
        for (i = 0; i < num_clips; i++) {
                omap_framebuffer_flush(fb, clips[i].x1, clips[i].y1,
                                        clips[i].x2 - clips[i].x1,
                                        clips[i].y2 - clips[i].y1);
        }
 
+       drm_modeset_unlock_all(fb->dev);
+
        return 0;
 }
 
index cb858600185f8051c7f92997e5e7e8ad7d8a6173..f035d2bceae7db358427c689b3a1fdd6cde28334 100644 (file)
@@ -45,12 +45,11 @@ static void omap_irq_update(struct drm_device *dev)
        dispc_read_irqenable();        /* flush posted write */
 }
 
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
 {
        struct omap_drm_private *priv = dev->dev_private;
        unsigned long flags;
 
-       dispc_runtime_get();
        spin_lock_irqsave(&list_lock, flags);
 
        if (!WARN_ON(irq->registered)) {
@@ -60,14 +59,21 @@ void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
        }
 
        spin_unlock_irqrestore(&list_lock, flags);
+}
+
+void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+       dispc_runtime_get();
+
+       __omap_irq_register(dev, irq);
+
        dispc_runtime_put();
 }
 
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
 {
        unsigned long flags;
 
-       dispc_runtime_get();
        spin_lock_irqsave(&list_lock, flags);
 
        if (!WARN_ON(!irq->registered)) {
@@ -77,6 +83,14 @@ void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
        }
 
        spin_unlock_irqrestore(&list_lock, flags);
+}
+
+void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+       dispc_runtime_get();
+
+       __omap_irq_unregister(dev, irq);
+
        dispc_runtime_put();
 }
 
@@ -173,7 +187,7 @@ void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id)
        dispc_runtime_put();
 }
 
-irqreturn_t omap_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t omap_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        struct omap_drm_private *priv = dev->dev_private;
@@ -308,7 +322,7 @@ int omap_drm_irq_uninstall(struct drm_device *dev)
        if (dev->num_crtcs) {
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
                for (i = 0; i < dev->num_crtcs; i++) {
-                       DRM_WAKEUP(&dev->vblank[i].queue);
+                       wake_up(&dev->vblank[i].queue);
                        dev->vblank[i].enabled = false;
                        dev->vblank[i].last =
                                dev->driver->get_vblank_counter(dev, i);
index 037d324bf58f6ccfda14ff471f3c98b4405981a0..66ac0ff95f5a30408bf722b43e49e76138e74546 100644 (file)
@@ -8,5 +8,6 @@ config DRM_QXL
         select DRM_KMS_HELPER
        select DRM_KMS_FB_HELPER
         select DRM_TTM
+       select CRC32
        help
                QXL virtual GPU for Spice virtualization desktop integration. Do not enable this driver unless your distro ships a corresponding X.org QXL driver that can handle kernel modesetting.
index 5e827c29d1948a658cf61205b7607ff5a53263d7..798bde2e5881db484fd3797013aa11a04f11c902 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 
-#include "linux/crc32.h"
+#include <linux/crc32.h>
 
 #include "qxl_drv.h"
 #include "qxl_object.h"
@@ -399,10 +399,14 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
        struct qxl_bo *qobj;
        int inc = 1;
 
+       drm_modeset_lock_all(fb->dev);
+
        qobj = gem_to_qxl_bo(qxl_fb->obj);
        /* if we aren't primary surface ignore this */
-       if (!qobj->is_primary)
+       if (!qobj->is_primary) {
+               drm_modeset_unlock_all(fb->dev);
                return 0;
+       }
 
        if (!num_clips) {
                num_clips = 1;
@@ -417,6 +421,9 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
 
        qxl_draw_dirty_fb(qdev, qxl_fb, qobj, flags, color,
                          clips, num_clips, inc);
+
+       drm_modeset_unlock_all(fb->dev);
+
        return 0;
 }
 
index 7bda32f68d3b50e528c21c3bba29a3b2018d1df1..36ed40ba773f8149d88eacef4c0633614e09eb83 100644 (file)
@@ -534,7 +534,7 @@ void qxl_debugfs_takedown(struct drm_minor *minor);
 
 /* qxl_irq.c */
 int qxl_irq_init(struct qxl_device *qdev);
-irqreturn_t qxl_irq_handler(DRM_IRQ_ARGS);
+irqreturn_t qxl_irq_handler(int irq, void *arg);
 
 /* qxl_fb.c */
 int qxl_fb_init(struct qxl_device *qdev);
index 7b95c75e9626ae1324dea48b310d3052f0c00d2d..0bb86e6d41b44cc4c1641e72da6e67e754994798 100644 (file)
@@ -200,7 +200,7 @@ static int qxl_process_single_command(struct qxl_device *qdev,
        for (i = 0; i < cmd->relocs_num; ++i) {
                struct drm_qxl_reloc reloc;
 
-               if (DRM_COPY_FROM_USER(&reloc,
+               if (copy_from_user(&reloc,
                                       &((struct drm_qxl_reloc *)(uintptr_t)cmd->relocs)[i],
                                       sizeof(reloc))) {
                        ret = -EFAULT;
@@ -297,7 +297,7 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data,
                struct drm_qxl_command *commands =
                        (struct drm_qxl_command *)(uintptr_t)execbuffer->commands;
 
-               if (DRM_COPY_FROM_USER(&user_cmd, &commands[cmd_num],
+               if (copy_from_user(&user_cmd, &commands[cmd_num],
                                       sizeof(user_cmd)))
                        return -EFAULT;
 
index 21393dc4700a09697b7551d274b18a96ff5938ab..28f84b4fce32fab576d4bd71d324bceaf93c0682 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "qxl_drv.h"
 
-irqreturn_t qxl_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t qxl_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        struct qxl_device *qdev = (struct qxl_device *)dev->dev_private;
index e5ca498be920a86be9507c94858637aeb0b3c4c6..fd88eb4a3f79d1be5b5478ef04a3c77dde2dbb71 100644 (file)
@@ -115,7 +115,7 @@ static void qxl_gc_work(struct work_struct *work)
        qxl_garbage_collect(qdev);
 }
 
-int qxl_device_init(struct qxl_device *qdev,
+static int qxl_device_init(struct qxl_device *qdev,
                    struct drm_device *ddev,
                    struct pci_dev *pdev,
                    unsigned long flags)
index c451257f08fb51ea4b2c5346339237032705f955..59459fe4e8c57b9c367887daa945324ac7f4eb34 100644 (file)
@@ -892,10 +892,10 @@ static int r128_cce_get_buffers(struct drm_device *dev,
 
                buf->file_priv = file_priv;
 
-               if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+               if (copy_to_user(&d->request_indices[i], &buf->idx,
                                     sizeof(buf->idx)))
                        return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+               if (copy_to_user(&d->request_sizes[i], &buf->total,
                                     sizeof(buf->total)))
                        return -EFAULT;
 
index 56eb5e3f54399ae9197e62cd5cfadcf094b7fb1b..5bf3f5ff805d941b74e05ab26f5119b8f154c057 100644 (file)
@@ -154,7 +154,7 @@ extern int r128_do_cleanup_cce(struct drm_device *dev);
 extern int r128_enable_vblank(struct drm_device *dev, int crtc);
 extern void r128_disable_vblank(struct drm_device *dev, int crtc);
 extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
-extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t r128_driver_irq_handler(int irq, void *arg);
 extern void r128_driver_irq_preinstall(struct drm_device *dev);
 extern int r128_driver_irq_postinstall(struct drm_device *dev);
 extern void r128_driver_irq_uninstall(struct drm_device *dev);
@@ -514,7 +514,7 @@ do {                                                                        \
        if (R128_VERBOSE)                                               \
                DRM_INFO("COMMIT_RING() tail=0x%06x\n",                 \
                         dev_priv->ring.tail);                          \
-       DRM_MEMORYBARRIER();                                            \
+       mb();                                           \
        R128_WRITE(R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail);       \
        R128_READ(R128_PM4_BUFFER_DL_WPTR);                             \
 } while (0)
index a954c548201ece8f733a933885c3830e32de1788..b0d0fd3e437676cb306a55df7fa82cba49bcdda1 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <drm/drmP.h>
 #include <drm/r128_drm.h>
+#include "r128_drv.h"
 
 typedef struct drm_r128_init32 {
        int func;
index 2ea4f09d2691d7f69f0a084677c9821f1e0afd69..c2ae496babb7374da8381c688f15883ebc533bc0 100644 (file)
@@ -44,7 +44,7 @@ u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
        return atomic_read(&dev_priv->vbl_received);
 }
 
-irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t r128_driver_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
index 01dd9aef9f0e9046116d570d52de96b3bf4a121b..e806dacd452f7b9cc8c93d20308db93ea0ef0da6 100644 (file)
@@ -895,31 +895,22 @@ static int r128_cce_dispatch_write_span(struct drm_device *dev,
        if (count > 4096 || count <= 0)
                return -EMSGSIZE;
 
-       if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x)))
+       if (copy_from_user(&x, depth->x, sizeof(x)))
                return -EFAULT;
-       if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y)))
+       if (copy_from_user(&y, depth->y, sizeof(y)))
                return -EFAULT;
 
        buffer_size = depth->n * sizeof(u32);
-       buffer = kmalloc(buffer_size, GFP_KERNEL);
-       if (buffer == NULL)
-               return -ENOMEM;
-       if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
-               kfree(buffer);
-               return -EFAULT;
-       }
+       buffer = memdup_user(depth->buffer, buffer_size);
+       if (IS_ERR(buffer))
+               return PTR_ERR(buffer);
 
        mask_size = depth->n * sizeof(u8);
        if (depth->mask) {
-               mask = kmalloc(mask_size, GFP_KERNEL);
-               if (mask == NULL) {
+               mask = memdup_user(depth->mask, mask_size);
+               if (IS_ERR(mask)) {
                        kfree(buffer);
-                       return -ENOMEM;
-               }
-               if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
-                       kfree(buffer);
-                       kfree(mask);
-                       return -EFAULT;
+                       return PTR_ERR(mask);
                }
 
                for (i = 0; i < count; i++, x++) {
@@ -999,46 +990,33 @@ static int r128_cce_dispatch_write_pixels(struct drm_device *dev,
                kfree(x);
                return -ENOMEM;
        }
-       if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+       if (copy_from_user(x, depth->x, xbuf_size)) {
                kfree(x);
                kfree(y);
                return -EFAULT;
        }
-       if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
+       if (copy_from_user(y, depth->y, xbuf_size)) {
                kfree(x);
                kfree(y);
                return -EFAULT;
        }
 
        buffer_size = depth->n * sizeof(u32);
-       buffer = kmalloc(buffer_size, GFP_KERNEL);
-       if (buffer == NULL) {
-               kfree(x);
-               kfree(y);
-               return -ENOMEM;
-       }
-       if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
+       buffer = memdup_user(depth->buffer, buffer_size);
+       if (IS_ERR(buffer)) {
                kfree(x);
                kfree(y);
-               kfree(buffer);
-               return -EFAULT;
+               return PTR_ERR(buffer);
        }
 
        if (depth->mask) {
                mask_size = depth->n * sizeof(u8);
-               mask = kmalloc(mask_size, GFP_KERNEL);
-               if (mask == NULL) {
-                       kfree(x);
-                       kfree(y);
-                       kfree(buffer);
-                       return -ENOMEM;
-               }
-               if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
+               mask = memdup_user(depth->mask, mask_size);
+               if (IS_ERR(mask)) {
                        kfree(x);
                        kfree(y);
                        kfree(buffer);
-                       kfree(mask);
-                       return -EFAULT;
+                       return PTR_ERR(mask);
                }
 
                for (i = 0; i < count; i++) {
@@ -1107,9 +1085,9 @@ static int r128_cce_dispatch_read_span(struct drm_device *dev,
        if (count > 4096 || count <= 0)
                return -EMSGSIZE;
 
-       if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x)))
+       if (copy_from_user(&x, depth->x, sizeof(x)))
                return -EFAULT;
-       if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y)))
+       if (copy_from_user(&y, depth->y, sizeof(y)))
                return -EFAULT;
 
        BEGIN_RING(7);
@@ -1162,12 +1140,12 @@ static int r128_cce_dispatch_read_pixels(struct drm_device *dev,
                kfree(x);
                return -ENOMEM;
        }
-       if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+       if (copy_from_user(x, depth->x, xbuf_size)) {
                kfree(x);
                kfree(y);
                return -EFAULT;
        }
-       if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
+       if (copy_from_user(y, depth->y, ybuf_size)) {
                kfree(x);
                kfree(y);
                return -EFAULT;
@@ -1524,7 +1502,7 @@ static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file
 
        DEV_INIT_TEST_WITH_RETURN(dev_priv);
 
-       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
+       if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32)))
                return -EFAULT;
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
@@ -1622,7 +1600,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+       if (copy_to_user(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
index 80a20120e6253590d07e9ec4b0085b6ea9d31437..4cf678306c9c19b05aa51324160fdf943e15a826 100644 (file)
@@ -423,7 +423,17 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
        int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
        union atom_enable_ss args;
 
-       if (!enable) {
+       if (enable) {
+               /* Don't mess with SS if percentage is 0 or external ss.
+                * SS is already disabled previously, and disabling it
+                * again can cause display problems if the pll is already
+                * programmed.
+                */
+               if (ss->percentage == 0)
+                       return;
+               if (ss->type & ATOM_EXTERNAL_SS_MASK)
+                       return;
+       } else {
                for (i = 0; i < rdev->num_crtc; i++) {
                        if (rdev->mode_info.crtcs[i] &&
                            rdev->mode_info.crtcs[i]->enabled &&
@@ -459,8 +469,6 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
                args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
                args.v3.ucEnable = enable;
-               if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev))
-                       args.v3.ucEnable = ATOM_DISABLE;
        } else if (ASIC_IS_DCE4(rdev)) {
                args.v2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
                args.v2.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
@@ -480,8 +488,6 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
                args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);
                args.v2.ucEnable = enable;
-               if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev))
-                       args.v2.ucEnable = ATOM_DISABLE;
        } else if (ASIC_IS_DCE3(rdev)) {
                args.v1.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
                args.v1.ucSpreadSpectrumType = ss->type & ATOM_SS_CENTRE_SPREAD_MODE_MASK;
@@ -503,8 +509,7 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
                args.lvds_ss_2.ucSpreadSpectrumRange = ss->range;
                args.lvds_ss_2.ucEnable = enable;
        } else {
-               if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
-                   (ss->type & ATOM_EXTERNAL_SS_MASK)) {
+               if (enable == ATOM_DISABLE) {
                        atombios_disable_ss(rdev, pll_id);
                        return;
                }
@@ -938,11 +943,14 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_
                                                        radeon_atombios_get_ppll_ss_info(rdev,
                                                                                         &radeon_crtc->ss,
                                                                                         ATOM_DP_SS_ID1);
-                               } else
+                               } else {
                                        radeon_crtc->ss_enabled =
                                                radeon_atombios_get_ppll_ss_info(rdev,
                                                                                 &radeon_crtc->ss,
                                                                                 ATOM_DP_SS_ID1);
+                               }
+                               /* disable spread spectrum on DCE3 DP */
+                               radeon_crtc->ss_enabled = false;
                        }
                        break;
                case ATOM_ENCODER_MODE_LVDS:
@@ -1039,15 +1047,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                /* calculate ss amount and step size */
                if (ASIC_IS_DCE4(rdev)) {
                        u32 step_size;
-                       u32 amount = (((fb_div * 10) + frac_fb_div) * radeon_crtc->ss.percentage) / 10000;
+                       u32 amount = (((fb_div * 10) + frac_fb_div) *
+                                     (u32)radeon_crtc->ss.percentage) /
+                               (100 * (u32)radeon_crtc->ss.percentage_divider);
                        radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;
                        radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
                                ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK;
                        if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)
-                               step_size = (4 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
+                               step_size = (4 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /
                                        (125 * 25 * pll->reference_freq / 100);
                        else
-                               step_size = (2 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
+                               step_size = (2 * amount * ref_div * ((u32)radeon_crtc->ss.rate * 2048)) /
                                        (125 * 25 * pll->reference_freq / 100);
                        radeon_crtc->ss.step = step_size;
                }
@@ -1143,31 +1153,53 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        }
 
        if (tiling_flags & RADEON_TILING_MACRO) {
-               if (rdev->family >= CHIP_BONAIRE)
-                       tmp = rdev->config.cik.tile_config;
-               else if (rdev->family >= CHIP_TAHITI)
-                       tmp = rdev->config.si.tile_config;
-               else if (rdev->family >= CHIP_CAYMAN)
-                       tmp = rdev->config.cayman.tile_config;
-               else
-                       tmp = rdev->config.evergreen.tile_config;
+               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
 
-               switch ((tmp & 0xf0) >> 4) {
-               case 0: /* 4 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
-                       break;
-               case 1: /* 8 banks */
-               default:
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
-                       break;
-               case 2: /* 16 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
-                       break;
+               /* Set NUM_BANKS. */
+               if (rdev->family >= CHIP_BONAIRE) {
+                       unsigned tileb, index, num_banks, tile_split_bytes;
+
+                       /* Calculate the macrotile mode index. */
+                       tile_split_bytes = 64 << tile_split;
+                       tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
+                       tileb = min(tile_split_bytes, tileb);
+
+                       for (index = 0; tileb > 64; index++) {
+                               tileb >>= 1;
+                       }
+
+                       if (index >= 16) {
+                               DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
+                                         target_fb->bits_per_pixel, tile_split);
+                               return -EINVAL;
+                       }
+
+                       num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
+               } else {
+                       /* SI and older. */
+                       if (rdev->family >= CHIP_TAHITI)
+                               tmp = rdev->config.si.tile_config;
+                       else if (rdev->family >= CHIP_CAYMAN)
+                               tmp = rdev->config.cayman.tile_config;
+                       else
+                               tmp = rdev->config.evergreen.tile_config;
+
+                       switch ((tmp & 0xf0) >> 4) {
+                       case 0: /* 4 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+                               break;
+                       case 1: /* 8 banks */
+                       default:
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+                               break;
+                       case 2: /* 16 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+                               break;
+                       }
                }
 
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-
-               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
                fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);
                fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
                fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
@@ -1180,23 +1212,18 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
 
        if (rdev->family >= CHIP_BONAIRE) {
-               u32 num_pipe_configs = rdev->config.cik.max_tile_pipes;
-               u32 num_rb = rdev->config.cik.max_backends_per_se;
-               if (num_pipe_configs > 8)
-                       num_pipe_configs = 8;
-               if (num_pipe_configs == 8)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16);
-               else if (num_pipe_configs == 4) {
-                       if (num_rb == 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16);
-                       else if (num_rb < 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16);
-               } else if (num_pipe_configs == 2)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2);
+               /* Read the pipe config from the 2D TILED SCANOUT mode.
+                * It should be the same for the other modes too, but not all
+                * modes set the pipe config field. */
+               u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f;
+
+               fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config);
        } else if ((rdev->family == CHIP_TAHITI) ||
                   (rdev->family == CHIP_PITCAIRN))
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);
-       else if (rdev->family == CHIP_VERDE)
+       else if ((rdev->family == CHIP_VERDE) ||
+                (rdev->family == CHIP_OLAND) ||
+                (rdev->family == CHIP_HAINAN)) /* for completeness.  HAINAN has no display hw */
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16);
 
        switch (radeon_crtc->crtc_id) {
index fb3ae07a14692601a912b1cbea37ae7ff13bcc62..4ad7643fce5fe9bdb8a479727400ae173475bb37 100644 (file)
@@ -157,21 +157,22 @@ static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector,
 
        msg[0] = address;
        msg[1] = address >> 8;
-       msg[2] = AUX_NATIVE_WRITE << 4;
+       msg[2] = DP_AUX_NATIVE_WRITE << 4;
        msg[3] = (msg_bytes << 4) | (send_bytes - 1);
        memcpy(&msg[4], send, send_bytes);
 
-       for (retry = 0; retry < 4; retry++) {
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
                                            msg, msg_bytes, NULL, 0, delay, &ack);
                if (ret == -EBUSY)
                        continue;
                else if (ret < 0)
                        return ret;
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+               ack >>= 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        return send_bytes;
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
-                       udelay(400);
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
@@ -191,20 +192,21 @@ static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
 
        msg[0] = address;
        msg[1] = address >> 8;
-       msg[2] = AUX_NATIVE_READ << 4;
+       msg[2] = DP_AUX_NATIVE_READ << 4;
        msg[3] = (msg_bytes << 4) | (recv_bytes - 1);
 
-       for (retry = 0; retry < 4; retry++) {
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
                                            msg, msg_bytes, recv, recv_bytes, delay, &ack);
                if (ret == -EBUSY)
                        continue;
                else if (ret < 0)
                        return ret;
-               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+               ack >>= 4;
+               if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
                        return ret;
-               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
-                       udelay(400);
+               else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
+                       usleep_range(400, 500);
                else if (ret == 0)
                        return -EPROTO;
                else
@@ -246,12 +248,12 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 
        /* Set up the command byte */
        if (mode & MODE_I2C_READ)
-               msg[2] = AUX_I2C_READ << 4;
+               msg[2] = DP_AUX_I2C_READ << 4;
        else
-               msg[2] = AUX_I2C_WRITE << 4;
+               msg[2] = DP_AUX_I2C_WRITE << 4;
 
        if (!(mode & MODE_I2C_STOP))
-               msg[2] |= AUX_I2C_MOT << 4;
+               msg[2] |= DP_AUX_I2C_MOT << 4;
 
        msg[0] = address;
        msg[1] = address >> 8;
@@ -272,7 +274,7 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                break;
        }
 
-       for (retry = 0; retry < 4; retry++) {
+       for (retry = 0; retry < 7; retry++) {
                ret = radeon_process_aux_ch(auxch,
                                            msg, msg_bytes, reply, reply_bytes, 0, &ack);
                if (ret == -EBUSY)
@@ -282,35 +284,35 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        return ret;
                }
 
-               switch (ack & AUX_NATIVE_REPLY_MASK) {
-               case AUX_NATIVE_REPLY_ACK:
+               switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
+               case DP_AUX_NATIVE_REPLY_ACK:
                        /* I2C-over-AUX Reply field is only valid
                         * when paired with AUX ACK.
                         */
                        break;
-               case AUX_NATIVE_REPLY_NACK:
+               case DP_AUX_NATIVE_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_ch native nack\n");
                        return -EREMOTEIO;
-               case AUX_NATIVE_REPLY_DEFER:
+               case DP_AUX_NATIVE_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_ch native defer\n");
-                       udelay(400);
+                       usleep_range(500, 600);
                        continue;
                default:
                        DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack);
                        return -EREMOTEIO;
                }
 
-               switch (ack & AUX_I2C_REPLY_MASK) {
-               case AUX_I2C_REPLY_ACK:
+               switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) {
+               case DP_AUX_I2C_REPLY_ACK:
                        if (mode == MODE_I2C_READ)
                                *read_byte = reply[0];
                        return ret;
-               case AUX_I2C_REPLY_NACK:
+               case DP_AUX_I2C_REPLY_NACK:
                        DRM_DEBUG_KMS("aux_i2c nack\n");
                        return -EREMOTEIO;
-               case AUX_I2C_REPLY_DEFER:
+               case DP_AUX_I2C_REPLY_DEFER:
                        DRM_DEBUG_KMS("aux_i2c defer\n");
-                       udelay(400);
+                       usleep_range(400, 500);
                        break;
                default:
                        DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack);
@@ -671,9 +673,11 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
        u8 tmp;
 
        /* power up the sink */
-       if (dp_info->dpcd[0] >= 0x11)
+       if (dp_info->dpcd[0] >= 0x11) {
                radeon_write_dpcd_reg(dp_info->radeon_connector,
                                      DP_SET_POWER, DP_SET_POWER_D0);
+               usleep_range(1000, 2000);
+       }
 
        /* possibly enable downspread on the sink */
        if (dp_info->dpcd[3] & 0x1)
index f685035dbe39a7d7ad48e63a9b4ca2ea717701fe..b5162c3b6111a1845834fe1b63d3e1f17642d501 100644 (file)
@@ -27,8 +27,6 @@
 #include "radeon.h"
 #include "atom.h"
 
-extern void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
-
 #define TARGET_HW_I2C_CLOCK 50
 
 /* these are a limitation of ProcessI2cChannelTransaction not the hw */
index 9b6950d9b3c09cc193010a50bdd521939464d539..0fbd36f3d4e9da34b65bc5f8ed302dc143b2d3c7 100644 (file)
@@ -49,6 +49,7 @@ struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps);
 struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
 struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
 
+extern int ni_mc_load_microcode(struct radeon_device *rdev);
 
 //********* BARTS **************//
 static const u32 barts_cgcg_cgls_default[] =
@@ -2510,21 +2511,6 @@ int btc_dpm_enable(struct radeon_device *rdev)
        if (eg_pi->ls_clock_gating)
                btc_ls_clock_gating_enable(rdev, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               PPSMC_Result result;
-
-               ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-               result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
-
-               if (result != PPSMC_Result_OK)
-                       DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
-       }
-
        rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        btc_init_stutter_mode(rdev);
@@ -2576,7 +2562,11 @@ void btc_dpm_disable(struct radeon_device *rdev)
 void btc_dpm_setup_asic(struct radeon_device *rdev)
 {
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       int r;
 
+       r = ni_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        rv770_get_memory_type(rdev);
        rv740_read_clock_registers(rdev);
        btc_read_arb_registers(rdev);
index 1ed47997635803d9e69bba8b3bd0202ecbc04b0e..8d49104ca6c254efa86f4287059323be28ba3f29 100644 (file)
@@ -171,8 +171,7 @@ extern void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
                                                     struct atom_voltage_table *voltage_table);
 extern void cik_enter_rlc_safe_mode(struct radeon_device *rdev);
 extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev);
-extern void cik_update_cg(struct radeon_device *rdev,
-                         u32 block, bool enable);
+extern int ci_mc_load_microcode(struct radeon_device *rdev);
 
 static int ci_get_std_voltage_value_sidd(struct radeon_device *rdev,
                                         struct atom_voltage_table_entry *voltage_table,
@@ -4503,8 +4502,8 @@ static void ci_get_memory_type(struct radeon_device *rdev)
 
 }
 
-void ci_update_current_ps(struct radeon_device *rdev,
-                         struct radeon_ps *rps)
+static void ci_update_current_ps(struct radeon_device *rdev,
+                                struct radeon_ps *rps)
 {
        struct ci_ps *new_ps = ci_get_ps(rps);
        struct ci_power_info *pi = ci_get_pi(rdev);
@@ -4514,8 +4513,8 @@ void ci_update_current_ps(struct radeon_device *rdev,
        pi->current_rps.ps_priv = &pi->current_ps;
 }
 
-void ci_update_requested_ps(struct radeon_device *rdev,
-                           struct radeon_ps *rps)
+static void ci_update_requested_ps(struct radeon_device *rdev,
+                                  struct radeon_ps *rps)
 {
        struct ci_ps *new_ps = ci_get_ps(rps);
        struct ci_power_info *pi = ci_get_pi(rdev);
@@ -4549,6 +4548,11 @@ void ci_dpm_post_set_power_state(struct radeon_device *rdev)
 
 void ci_dpm_setup_asic(struct radeon_device *rdev)
 {
+       int r;
+
+       r = ci_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        ci_read_clock_registers(rdev);
        ci_get_memory_type(rdev);
        ci_enable_acpi_power_management(rdev);
@@ -4561,13 +4565,6 @@ int ci_dpm_enable(struct radeon_device *rdev)
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        if (ci_is_smc_running(rdev))
                return -EINVAL;
        if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE) {
@@ -4665,6 +4662,18 @@ int ci_dpm_enable(struct radeon_device *rdev)
                DRM_ERROR("ci_enable_power_containment failed\n");
                return ret;
        }
+
+       ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
+
+       ci_update_current_ps(rdev, boot_ps);
+
+       return 0;
+}
+
+int ci_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
 #if 0
@@ -4685,19 +4694,8 @@ int ci_dpm_enable(struct radeon_device *rdev)
 #endif
        }
 
-       ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
-
        ci_dpm_powergate_uvd(rdev, true);
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), true);
-
-       ci_update_current_ps(rdev, boot_ps);
-
        return 0;
 }
 
@@ -4706,12 +4704,6 @@ void ci_dpm_disable(struct radeon_device *rdev)
        struct ci_power_info *pi = ci_get_pi(rdev);
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        ci_dpm_powergate_uvd(rdev, false);
 
        if (!ci_is_smc_running(rdev))
@@ -4742,13 +4734,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
        struct radeon_ps *old_ps = &pi->current_rps;
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), false);
-
        ci_find_dpm_states_clocks_in_dpm_table(rdev, new_ps);
        if (pi->pcie_performance_request)
                ci_request_link_speed_change_before_state_change(rdev, new_ps, old_ps);
@@ -4804,13 +4789,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
        if (pi->pcie_performance_request)
                ci_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_MC |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_UVD |
-                            RADEON_CG_BLOCK_HDP), true);
-
        return 0;
 }
 
@@ -5023,8 +5001,8 @@ static int ci_parse_power_table(struct radeon_device *rdev)
        return 0;
 }
 
-int ci_get_vbios_boot_values(struct radeon_device *rdev,
-                            struct ci_vbios_boot_state *boot_state)
+static int ci_get_vbios_boot_values(struct radeon_device *rdev,
+                                   struct ci_vbios_boot_state *boot_state)
 {
        struct radeon_mode_info *mode_info = &rdev->mode_info;
        int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
index 9c745dd22438953106715feceb974cb620c7db02..8debc9d473625d642243b5a1923b6725eb534387 100644 (file)
@@ -28,6 +28,7 @@
 #include "cikd.h"
 #include "ppsmc.h"
 #include "radeon_ucode.h"
+#include "ci_dpm.h"
 
 static int ci_set_smc_sram_address(struct radeon_device *rdev,
                                   u32 smc_address, u32 limit)
index b43a3a3c90671911a4eaa0a7c5a260c42118df41..6ffe824624fb5a014f2bb74434b09257f00e0959 100644 (file)
@@ -1697,7 +1697,7 @@ static void cik_srbm_select(struct radeon_device *rdev,
  * Load the GDDR MC ucode into the hw (CIK).
  * Returns 0 on success, error on failure.
  */
-static int ci_mc_load_microcode(struct radeon_device *rdev)
+int ci_mc_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
        u32 running, blackout = 0;
@@ -3057,7 +3057,7 @@ static u32 cik_create_bitmask(u32 bit_width)
  * Returns the disabled RB bitmask.
  */
 static u32 cik_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -3071,7 +3071,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
@@ -3088,7 +3088,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
  */
 static void cik_setup_rb(struct radeon_device *rdev,
                         u32 se_num, u32 sh_per_se,
-                        u32 max_rb_num)
+                        u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -3098,7 +3098,7 @@ static void cik_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        cik_select_se_sh(rdev, i, j);
-                       data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+                       data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
                        if (rdev->family == CHIP_HAWAII)
                                disabled_rbs |= data << ((i * sh_per_se + j) * HAWAII_RB_BITMAP_WIDTH_PER_SH);
                        else
@@ -3108,12 +3108,14 @@ static void cik_setup_rb(struct radeon_device *rdev,
        cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.cik.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                cik_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
@@ -3484,6 +3486,51 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
        return r;
 }
 
+/**
+ * cik_hdp_flush_cp_ring_emit - emit an hdp flush on the cp
+ *
+ * @rdev: radeon_device pointer
+ * @ridx: radeon ring index
+ *
+ * Emits an hdp flush on the cp.
+ */
+static void cik_hdp_flush_cp_ring_emit(struct radeon_device *rdev,
+                                      int ridx)
+{
+       struct radeon_ring *ring = &rdev->ring[ridx];
+       u32 ref_and_mask;
+
+       switch (ring->idx) {
+       case CAYMAN_RING_TYPE_CP1_INDEX:
+       case CAYMAN_RING_TYPE_CP2_INDEX:
+       default:
+               switch (ring->me) {
+               case 0:
+                       ref_and_mask = CP2 << ring->pipe;
+                       break;
+               case 1:
+                       ref_and_mask = CP6 << ring->pipe;
+                       break;
+               default:
+                       return;
+               }
+               break;
+       case RADEON_RING_TYPE_GFX_INDEX:
+               ref_and_mask = CP0;
+               break;
+       }
+
+       radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
+       radeon_ring_write(ring, (WAIT_REG_MEM_OPERATION(1) | /* write, wait, write */
+                                WAIT_REG_MEM_FUNCTION(3) |  /* == */
+                                WAIT_REG_MEM_ENGINE(1)));   /* pfp */
+       radeon_ring_write(ring, GPU_HDP_FLUSH_REQ >> 2);
+       radeon_ring_write(ring, GPU_HDP_FLUSH_DONE >> 2);
+       radeon_ring_write(ring, ref_and_mask);
+       radeon_ring_write(ring, ref_and_mask);
+       radeon_ring_write(ring, 0x20); /* poll interval */
+}
+
 /**
  * cik_fence_gfx_ring_emit - emit a fence on the gfx ring
  *
@@ -3510,15 +3557,7 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, fence->seq);
        radeon_ring_write(ring, 0);
        /* HDP flush */
-       /* We should be using the new WAIT_REG_MEM special op packet here
-        * but it causes the CP to hang
-        */
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(0)));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 0);
+       cik_hdp_flush_cp_ring_emit(rdev, fence->ring);
 }
 
 /**
@@ -3548,15 +3587,7 @@ void cik_fence_compute_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, fence->seq);
        radeon_ring_write(ring, 0);
        /* HDP flush */
-       /* We should be using the new WAIT_REG_MEM special op packet here
-        * but it causes the CP to hang
-        */
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(0)));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 0);
+       cik_hdp_flush_cp_ring_emit(rdev, fence->ring);
 }
 
 bool cik_semaphore_ring_emit(struct radeon_device *rdev,
@@ -3564,8 +3595,6 @@ bool cik_semaphore_ring_emit(struct radeon_device *rdev,
                             struct radeon_semaphore *semaphore,
                             bool emit_wait)
 {
-/* TODO: figure out why semaphore cause lockups */
-#if 0
        uint64_t addr = semaphore->gpu_addr;
        unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL;
 
@@ -3574,9 +3603,6 @@ bool cik_semaphore_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | sel);
 
        return true;
-#else
-       return false;
-#endif
 }
 
 /**
@@ -4015,15 +4041,43 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
        return 0;
 }
 
-u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring)
+u32 cik_gfx_get_rptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring)
 {
        u32 rptr;
 
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else
+               rptr = RREG32(CP_RB0_RPTR);
+
+       return rptr;
+}
+
+u32 cik_gfx_get_wptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       wptr = RREG32(CP_RB0_WPTR);
 
+       return wptr;
+}
+
+void cik_gfx_set_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       WREG32(CP_RB0_WPTR, ring->wptr);
+       (void)RREG32(CP_RB0_WPTR);
+}
+
+u32 cik_compute_get_rptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring)
+{
+       u32 rptr;
 
        if (rdev->wb.enabled) {
-               rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
        } else {
                mutex_lock(&rdev->srbm_mutex);
                cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
@@ -4035,13 +4089,14 @@ u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
        return rptr;
 }
 
-u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring)
+u32 cik_compute_get_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring)
 {
        u32 wptr;
 
        if (rdev->wb.enabled) {
-               wptr = le32_to_cpu(rdev->wb.wb[ring->wptr_offs/4]);
+               /* XXX check if swapping is necessary on BE */
+               wptr = rdev->wb.wb[ring->wptr_offs/4];
        } else {
                mutex_lock(&rdev->srbm_mutex);
                cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
@@ -4053,10 +4108,11 @@ u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
        return wptr;
 }
 
-void cik_compute_ring_set_wptr(struct radeon_device *rdev,
-                              struct radeon_ring *ring)
+void cik_compute_set_wptr(struct radeon_device *rdev,
+                         struct radeon_ring *ring)
 {
-       rdev->wb.wb[ring->wptr_offs/4] = cpu_to_le32(ring->wptr);
+       /* XXX check if swapping is necessary on BE */
+       rdev->wb.wb[ring->wptr_offs/4] = ring->wptr;
        WDOORBELL32(ring->doorbell_index, ring->wptr);
 }
 
@@ -4850,6 +4906,160 @@ static void cik_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        cik_print_gpu_status_regs(rdev);
 }
 
+struct kv_reset_save_regs {
+       u32 gmcon_reng_execute;
+       u32 gmcon_misc;
+       u32 gmcon_misc3;
+};
+
+static void kv_save_regs_for_reset(struct radeon_device *rdev,
+                                  struct kv_reset_save_regs *save)
+{
+       save->gmcon_reng_execute = RREG32(GMCON_RENG_EXECUTE);
+       save->gmcon_misc = RREG32(GMCON_MISC);
+       save->gmcon_misc3 = RREG32(GMCON_MISC3);
+
+       WREG32(GMCON_RENG_EXECUTE, save->gmcon_reng_execute & ~RENG_EXECUTE_ON_PWR_UP);
+       WREG32(GMCON_MISC, save->gmcon_misc & ~(RENG_EXECUTE_ON_REG_UPDATE |
+                                               STCTRL_STUTTER_EN));
+}
+
+static void kv_restore_regs_for_reset(struct radeon_device *rdev,
+                                     struct kv_reset_save_regs *save)
+{
+       int i;
+
+       WREG32(GMCON_PGFSM_WRITE, 0);
+       WREG32(GMCON_PGFSM_CONFIG, 0x200010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0);
+       WREG32(GMCON_PGFSM_CONFIG, 0x300010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x210000);
+       WREG32(GMCON_PGFSM_CONFIG, 0xa00010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x21003);
+       WREG32(GMCON_PGFSM_CONFIG, 0xb00010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x2b00);
+       WREG32(GMCON_PGFSM_CONFIG, 0xc00010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0);
+       WREG32(GMCON_PGFSM_CONFIG, 0xd00010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x420000);
+       WREG32(GMCON_PGFSM_CONFIG, 0x100010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x120202);
+       WREG32(GMCON_PGFSM_CONFIG, 0x500010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x3e3e36);
+       WREG32(GMCON_PGFSM_CONFIG, 0x600010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x373f3e);
+       WREG32(GMCON_PGFSM_CONFIG, 0x700010ff);
+
+       for (i = 0; i < 5; i++)
+               WREG32(GMCON_PGFSM_WRITE, 0);
+
+       WREG32(GMCON_PGFSM_WRITE, 0x3e1332);
+       WREG32(GMCON_PGFSM_CONFIG, 0xe00010ff);
+
+       WREG32(GMCON_MISC3, save->gmcon_misc3);
+       WREG32(GMCON_MISC, save->gmcon_misc);
+       WREG32(GMCON_RENG_EXECUTE, save->gmcon_reng_execute);
+}
+
+static void cik_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct evergreen_mc_save save;
+       struct kv_reset_save_regs kv_save = { 0 };
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* disable cg/pg */
+       cik_fini_pg(rdev);
+       cik_fini_cg(rdev);
+
+       /* Disable GFX parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
+
+       /* Disable MEC parsing/prefetching */
+       WREG32(CP_MEC_CNTL, MEC_ME1_HALT | MEC_ME2_HALT);
+
+       /* sdma0 */
+       tmp = RREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET);
+       tmp |= SDMA_HALT;
+       WREG32(SDMA0_ME_CNTL + SDMA0_REGISTER_OFFSET, tmp);
+       /* sdma1 */
+       tmp = RREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET);
+       tmp |= SDMA_HALT;
+       WREG32(SDMA0_ME_CNTL + SDMA1_REGISTER_OFFSET, tmp);
+       /* XXX other engines? */
+
+       /* halt the rlc, disable cp internal ints */
+       cik_rlc_stop(rdev);
+
+       udelay(50);
+
+       /* disable mem access */
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
+       }
+
+       if (rdev->flags & RADEON_IS_IGP)
+               kv_save_regs_for_reset(rdev, &kv_save);
+
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* reset */
+       radeon_pci_config_reset(rdev);
+
+       udelay(100);
+
+       /* wait for asic to come out of reset */
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+
+       /* does asic init need to be run first??? */
+       if (rdev->flags & RADEON_IS_IGP)
+               kv_restore_regs_for_reset(rdev, &kv_save);
+}
+
 /**
  * cik_asic_reset - soft reset GPU
  *
@@ -4868,10 +5078,17 @@ int cik_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        cik_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = cik_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               cik_gpu_pci_config_reset(rdev);
+
+       reset_mask = cik_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
@@ -5136,20 +5353,6 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
                                WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT |
                                WRITE_PROTECTION_FAULT_ENABLE_DEFAULT);
 
-       /* TC cache setup ??? */
-       WREG32(TC_CFG_L1_LOAD_POLICY0, 0);
-       WREG32(TC_CFG_L1_LOAD_POLICY1, 0);
-       WREG32(TC_CFG_L1_STORE_POLICY, 0);
-
-       WREG32(TC_CFG_L2_LOAD_POLICY0, 0);
-       WREG32(TC_CFG_L2_LOAD_POLICY1, 0);
-       WREG32(TC_CFG_L2_STORE_POLICY0, 0);
-       WREG32(TC_CFG_L2_STORE_POLICY1, 0);
-       WREG32(TC_CFG_L2_ATOMIC_POLICY, 0);
-
-       WREG32(TC_CFG_L1_VOLATILE, 0);
-       WREG32(TC_CFG_L2_VOLATILE, 0);
-
        if (rdev->family == CHIP_KAVERI) {
                u32 tmp = RREG32(CHUB_CONTROL);
                tmp &= ~BYPASS_VM;
@@ -5365,16 +5568,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        radeon_ring_write(ring, VMID(0));
 
        /* HDP flush */
-       /* We should be using the WAIT_REG_MEM packet here like in
-        * cik_fence_ring_emit(), but it causes the CP to hang in this
-        * context...
-        */
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(0)));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 0);
+       cik_hdp_flush_cp_ring_emit(rdev, ridx);
 
        /* bits 0-15 are the VM contexts0-15 */
        radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
@@ -7501,26 +7695,7 @@ static int cik_startup(struct radeon_device *rdev)
 
        cik_mc_program(rdev);
 
-       if (rdev->flags & RADEON_IS_IGP) {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
-                   !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) {
-                       r = cik_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
-       } else {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
-                   !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw ||
-                   !rdev->mc_fw) {
-                       r = cik_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
-
+       if (!(rdev->flags & RADEON_IS_IGP) && !rdev->pm.dpm_enabled) {
                r = ci_mc_load_microcode(rdev);
                if (r) {
                        DRM_ERROR("Failed to load MC firmware!\n");
@@ -7625,7 +7800,6 @@ static int cik_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            CP_RB0_RPTR, CP_RB0_WPTR,
                             PACKET3(PACKET3_NOP, 0x3FFF));
        if (r)
                return r;
@@ -7634,7 +7808,6 @@ static int cik_startup(struct radeon_device *rdev)
        /* type-2 packets are deprecated on MEC, use type-3 instead */
        ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
-                            CP_HQD_PQ_RPTR, CP_HQD_PQ_WPTR,
                             PACKET3(PACKET3_NOP, 0x3FFF));
        if (r)
                return r;
@@ -7646,7 +7819,6 @@ static int cik_startup(struct radeon_device *rdev)
        /* type-2 packets are deprecated on MEC, use type-3 instead */
        ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
-                            CP_HQD_PQ_RPTR, CP_HQD_PQ_WPTR,
                             PACKET3(PACKET3_NOP, 0x3FFF));
        if (r)
                return r;
@@ -7658,16 +7830,12 @@ static int cik_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET,
-                            SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET,
                             SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0));
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
-                            SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET,
-                            SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET,
                             SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0));
        if (r)
                return r;
@@ -7683,7 +7851,6 @@ static int cik_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        if (ring->ring_size) {
                r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
                        r = uvd_v1_0_init(rdev);
@@ -7729,6 +7896,8 @@ int cik_resume(struct radeon_device *rdev)
        /* init golden registers */
        cik_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = cik_startup(rdev);
        if (r) {
@@ -7752,6 +7921,7 @@ int cik_resume(struct radeon_device *rdev)
  */
 int cik_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        dce6_audio_fini(rdev);
        radeon_vm_manager_fini(rdev);
        cik_cp_enable(rdev, false);
@@ -7833,6 +8003,30 @@ int cik_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (rdev->flags & RADEON_IS_IGP) {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+                   !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) {
+                       r = cik_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       } else {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+                   !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw ||
+                   !rdev->mc_fw) {
+                       r = cik_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 1024 * 1024);
@@ -7913,6 +8107,7 @@ int cik_init(struct radeon_device *rdev)
  */
 void cik_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        cik_cp_fini(rdev);
        cik_sdma_fini(rdev);
        cik_fini_pg(rdev);
index 0300727a4f70d52c71e24931bbec8335ce6ba6d3..9abea87a92133b7073ba64500d4083f711b82a63 100644 (file)
@@ -51,6 +51,75 @@ u32 cik_gpu_check_soft_reset(struct radeon_device *rdev);
  * buffers.
  */
 
+/**
+ * cik_sdma_get_rptr - get the current read pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current rptr from the hardware (CIK+).
+ */
+uint32_t cik_sdma_get_rptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       u32 rptr, reg;
+
+       if (rdev->wb.enabled) {
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       } else {
+               if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+                       reg = SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET;
+               else
+                       reg = SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET;
+
+               rptr = RREG32(reg);
+       }
+
+       return (rptr & 0x3fffc) >> 2;
+}
+
+/**
+ * cik_sdma_get_wptr - get the current write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current wptr from the hardware (CIK+).
+ */
+uint32_t cik_sdma_get_wptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET;
+       else
+               reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
+
+       return (RREG32(reg) & 0x3fffc) >> 2;
+}
+
+/**
+ * cik_sdma_set_wptr - commit the write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Write the wptr back to the hardware (CIK+).
+ */
+void cik_sdma_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET;
+       else
+               reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
+
+       WREG32(reg, (ring->wptr << 2) & 0x3fffc);
+}
+
 /**
  * cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine
  *
@@ -87,6 +156,35 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev,
 
 }
 
+/**
+ * cik_sdma_hdp_flush_ring_emit - emit an hdp flush on the DMA ring
+ *
+ * @rdev: radeon_device pointer
+ * @ridx: radeon ring index
+ *
+ * Emit an hdp flush packet on the requested DMA ring.
+ */
+static void cik_sdma_hdp_flush_ring_emit(struct radeon_device *rdev,
+                                        int ridx)
+{
+       struct radeon_ring *ring = &rdev->ring[ridx];
+       u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) |
+                         SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */
+       u32 ref_and_mask;
+
+       if (ridx == R600_RING_TYPE_DMA_INDEX)
+               ref_and_mask = SDMA0;
+       else
+               ref_and_mask = SDMA1;
+
+       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits));
+       radeon_ring_write(ring, GPU_HDP_FLUSH_DONE);
+       radeon_ring_write(ring, GPU_HDP_FLUSH_REQ);
+       radeon_ring_write(ring, ref_and_mask); /* reference */
+       radeon_ring_write(ring, ref_and_mask); /* mask */
+       radeon_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */
+}
+
 /**
  * cik_sdma_fence_ring_emit - emit a fence on the DMA ring
  *
@@ -111,12 +209,7 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
        /* generate an interrupt */
        radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_TRAP, 0, 0));
        /* flush HDP */
-       /* We should be using the new POLL_REG_MEM special op packet here
-        * but it causes sDMA to hang sometimes
-        */
-       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
+       cik_sdma_hdp_flush_ring_emit(rdev, fence->ring);
 }
 
 /**
@@ -458,7 +551,7 @@ int cik_copy_dma(struct radeon_device *rdev,
                radeon_ring_write(ring, 0); /* src/dst endian swap */
                radeon_ring_write(ring, src_offset & 0xffffffff);
                radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff);
-               radeon_ring_write(ring, dst_offset & 0xfffffffc);
+               radeon_ring_write(ring, dst_offset & 0xffffffff);
                radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff);
                src_offset += cur_size_in_bytes;
                dst_offset += cur_size_in_bytes;
@@ -747,12 +840,7 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm
        radeon_ring_write(ring, VMID(0));
 
        /* flush HDP */
-       /* We should be using the new POLL_REG_MEM special op packet here
-        * but it causes sDMA to hang sometimes
-        */
-       radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
-       radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
-       radeon_ring_write(ring, 0);
+       cik_sdma_hdp_flush_ring_emit(rdev, ridx);
 
        /* flush TLB */
        radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
index 5964af5e5b2d8823c4626cad40bfd2abf385fb40..98bae9d7b74d1b3fe82ab41bc5f631d7e4acfc86 100644 (file)
 
 #define ATC_MISC_CG                                    0x3350
 
+#define GMCON_RENG_EXECUTE                             0x3508
+#define        RENG_EXECUTE_ON_PWR_UP                  (1 << 0)
+#define GMCON_MISC                                     0x350c
+#define        RENG_EXECUTE_ON_REG_UPDATE              (1 << 11)
+#define        STCTRL_STUTTER_EN                       (1 << 16)
+
+#define GMCON_PGFSM_CONFIG                             0x3538
+#define GMCON_PGFSM_WRITE                              0x353c
+#define GMCON_PGFSM_READ                               0x3540
+#define GMCON_MISC3                                    0x3544
+
 #define MC_SEQ_CNTL_3                                     0x3600
 #       define CAC_EN                                     (1 << 31)
 #define MC_SEQ_G5PDX_CTRL                                 0x3604
index 920e1e4a52c52c1edefd84e727a0fc13c2dde39b..cf783fc0ef21920f7d0e50156bddbd9c24299150 100644 (file)
@@ -1905,21 +1905,6 @@ int cypress_dpm_enable(struct radeon_device *rdev)
        if (pi->mg_clock_gating)
                cypress_mg_clock_gating_enable(rdev, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               PPSMC_Result result;
-
-               ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-               result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
-
-               if (result != PPSMC_Result_OK)
-                       DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
-       }
-
        rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        return 0;
index de86493cbc44af60a8079028e8e509f8cee81c7e..713a5d35990102ea315fa078a93c11d6c1aae1f5 100644 (file)
@@ -174,7 +174,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
        }
@@ -235,7 +235,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
        }
@@ -308,7 +308,9 @@ int dce6_audio_init(struct radeon_device *rdev)
        rdev->audio.enabled = true;
 
        if (ASIC_IS_DCE8(rdev))
-               rdev->audio.num_pins = 7;
+               rdev->audio.num_pins = 6;
+       else if (ASIC_IS_DCE61(rdev))
+               rdev->audio.num_pins = 4;
        else
                rdev->audio.num_pins = 6;
 
index 9702e55e924e8327740869eb34ed455dcd908db3..4116d0279596605d0447d9687c6d9f5698ea27de 100644 (file)
@@ -146,6 +146,7 @@ extern u32 si_get_csb_size(struct radeon_device *rdev);
 extern void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
 extern u32 cik_get_csb_size(struct radeon_device *rdev);
 extern void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer);
+extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
 
 static const u32 evergreen_golden_registers[] =
 {
@@ -3867,6 +3868,48 @@ static void evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        evergreen_print_gpu_status_regs(rdev);
 }
 
+void evergreen_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct evergreen_mc_save save;
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* Disable CP parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
+       udelay(50);
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+       /* XXX other engines? */
+
+       /* halt the rlc */
+       r600_rlc_stop(rdev);
+
+       udelay(50);
+
+       /* set mclk/sclk to bypass */
+       rv770_set_clk_bypass_mode(rdev);
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* disable mem access */
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
+       }
+       /* reset */
+       radeon_pci_config_reset(rdev);
+       /* wait for asic to come out of reset */
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+}
+
 int evergreen_asic_reset(struct radeon_device *rdev)
 {
        u32 reset_mask;
@@ -3876,10 +3919,17 @@ int evergreen_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        evergreen_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = evergreen_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               evergreen_gpu_pci_config_reset(rdev);
+
+       reset_mask = evergreen_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
@@ -5109,27 +5159,12 @@ static int evergreen_startup(struct radeon_device *rdev)
 
        evergreen_mc_program(rdev);
 
-       if (ASIC_IS_DCE5(rdev)) {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
-                       r = ni_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
+       if (ASIC_IS_DCE5(rdev) && !rdev->pm.dpm_enabled) {
                r = ni_mc_load_microcode(rdev);
                if (r) {
                        DRM_ERROR("Failed to load MC firmware!\n");
                        return r;
                }
-       } else {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-                       r = r600_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
        }
 
        if (rdev->flags & RADEON_IS_AGP) {
@@ -5199,14 +5234,12 @@ static int evergreen_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR, DMA_RB_WPTR,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0));
        if (r)
                return r;
@@ -5224,7 +5257,6 @@ static int evergreen_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        if (ring->ring_size) {
                r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
                        r = uvd_v1_0_init(rdev);
@@ -5267,6 +5299,8 @@ int evergreen_resume(struct radeon_device *rdev)
        /* init golden registers */
        evergreen_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = evergreen_startup(rdev);
        if (r) {
@@ -5281,6 +5315,7 @@ int evergreen_resume(struct radeon_device *rdev)
 
 int evergreen_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_suspend(rdev);
@@ -5357,6 +5392,27 @@ int evergreen_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (ASIC_IS_DCE5(rdev)) {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+                       r = ni_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       } else {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+                       r = r600_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -5409,6 +5465,7 @@ int evergreen_init(struct radeon_device *rdev)
 
 void evergreen_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r700_cp_fini(rdev);
        r600_dma_fini(rdev);
index eb8ac315f92faa3cbd58468b6bf9ba360a8c0986..c7cac07f139b2106041208179d124d8ff5ba20b0 100644 (file)
@@ -967,7 +967,10 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p)
        if (track->cb_dirty) {
                tmp = track->cb_target_mask;
                for (i = 0; i < 8; i++) {
-                       if ((tmp >> (i * 4)) & 0xF) {
+                       u32 format = G_028C70_FORMAT(track->cb_color_info[i]);
+
+                       if (format != V_028C70_COLOR_INVALID &&
+                           (tmp >> (i * 4)) & 0xF) {
                                /* at least one component is enabled */
                                if (track->cb_color_bo[i] == NULL) {
                                        dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
index aa695c4feb3d00d393c2e9b74e2395a3a7395164..0c6d5cef4cf121770c63fcb559bf6cc187640292 100644 (file)
@@ -118,7 +118,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
        }
@@ -173,7 +173,7 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
        }
index 8a4e641f0e3c3712cfbcb543372fde5707e6cce5..a0f63ff5a5e97cb47100abce14bc249083c61479 100644 (file)
@@ -33,6 +33,7 @@
 #define EVERGREEN_PIF_PHY0_DATA                         0xc
 #define EVERGREEN_PIF_PHY1_INDEX                        0x10
 #define EVERGREEN_PIF_PHY1_DATA                         0x14
+#define EVERGREEN_MM_INDEX_HI                           0x18
 
 #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS               0x310
 #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH          0x324
index 17f990798992dae5d6335726a8f3b4c259659f89..f9c7963b3ee6b38730cdf6d422c2b612f0d1c904 100644 (file)
 #define        CG_SPLL_FUNC_CNTL_2                             0x604
 #define                SCLK_MUX_SEL(x)                         ((x) << 0)
 #define                SCLK_MUX_SEL_MASK                       (0x1ff << 0)
+#define                SCLK_MUX_UPDATE                         (1 << 26)
 #define        CG_SPLL_FUNC_CNTL_3                             0x608
 #define                SPLL_FB_DIV(x)                          ((x) << 0)
 #define                SPLL_FB_DIV_MASK                        (0x3ffffff << 0)
 #define                SPLL_DITHEN                             (1 << 28)
+#define        CG_SPLL_STATUS                                  0x60c
+#define                SPLL_CHG_STATUS                         (1 << 1)
 
 #define MPLL_CNTL_MODE                                  0x61c
+#       define MPLL_MCLK_SEL                            (1 << 11)
 #       define SS_SSEN                                  (1 << 24)
 #       define SS_DSMODE_EN                             (1 << 25)
 
index b41905573cd2a431862b3684f4d43ad445ecd15d..b6e01d5d2cced24edc67e773c84cba33a6d5fef8 100644 (file)
@@ -1126,11 +1126,6 @@ int kv_dpm_enable(struct radeon_device *rdev)
        struct kv_power_info *pi = kv_get_pi(rdev);
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), false);
-
        ret = kv_process_firmware_header(rdev);
        if (ret) {
                DRM_ERROR("kv_process_firmware_header failed\n");
@@ -1215,6 +1210,21 @@ int kv_dpm_enable(struct radeon_device *rdev)
 
        kv_reset_acp_boot_level(rdev);
 
+       ret = kv_smc_bapm_enable(rdev, false);
+       if (ret) {
+               DRM_ERROR("kv_smc_bapm_enable failed\n");
+               return ret;
+       }
+
+       kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+
+       return ret;
+}
+
+int kv_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1226,35 +1236,17 @@ int kv_dpm_enable(struct radeon_device *rdev)
                radeon_irq_set(rdev);
        }
 
-       ret = kv_smc_bapm_enable(rdev, false);
-       if (ret) {
-               DRM_ERROR("kv_smc_bapm_enable failed\n");
-               return ret;
-       }
-
        /* powerdown unused blocks for now */
        kv_dpm_powergate_acp(rdev, true);
        kv_dpm_powergate_samu(rdev, true);
        kv_dpm_powergate_vce(rdev, true);
        kv_dpm_powergate_uvd(rdev, true);
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), true);
-
-       kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
-
        return ret;
 }
 
 void kv_dpm_disable(struct radeon_device *rdev)
 {
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), false);
-
        kv_smc_bapm_enable(rdev, false);
 
        /* powerup blocks */
@@ -1779,11 +1771,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
        /*struct radeon_ps *old_ps = &pi->current_rps;*/
        int ret;
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), false);
-
        if (pi->bapm_enable) {
                ret = kv_smc_bapm_enable(rdev, rdev->pm.dpm.ac_power);
                if (ret) {
@@ -1849,11 +1836,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
                }
        }
 
-       cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                            RADEON_CG_BLOCK_SDMA |
-                            RADEON_CG_BLOCK_BIF |
-                            RADEON_CG_BLOCK_HDP), true);
-
        return 0;
 }
 
index 11aab2ab54ce27fb5c0279cbaaad797e95bea42f..647b1d0fa62c3fc5bf0e7c424ffc6cb606aff9f2 100644 (file)
@@ -174,6 +174,7 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
 extern void evergreen_program_aspm(struct radeon_device *rdev);
 extern void sumo_rlc_fini(struct radeon_device *rdev);
 extern int sumo_rlc_init(struct radeon_device *rdev);
+extern void evergreen_gpu_pci_config_reset(struct radeon_device *rdev);
 
 /* Firmware Names */
 MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
@@ -895,6 +896,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                    (rdev->pdev->device == 0x999C)) {
                        rdev->config.cayman.max_simds_per_se = 6;
                        rdev->config.cayman.max_backends_per_se = 2;
+                       rdev->config.cayman.max_hw_contexts = 8;
+                       rdev->config.cayman.sx_max_export_size = 256;
+                       rdev->config.cayman.sx_max_export_pos_size = 64;
+                       rdev->config.cayman.sx_max_export_smx_size = 192;
                } else if ((rdev->pdev->device == 0x9903) ||
                           (rdev->pdev->device == 0x9904) ||
                           (rdev->pdev->device == 0x990A) ||
@@ -905,6 +910,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x999D)) {
                        rdev->config.cayman.max_simds_per_se = 4;
                        rdev->config.cayman.max_backends_per_se = 2;
+                       rdev->config.cayman.max_hw_contexts = 8;
+                       rdev->config.cayman.sx_max_export_size = 256;
+                       rdev->config.cayman.sx_max_export_pos_size = 64;
+                       rdev->config.cayman.sx_max_export_smx_size = 192;
                } else if ((rdev->pdev->device == 0x9919) ||
                           (rdev->pdev->device == 0x9990) ||
                           (rdev->pdev->device == 0x9991) ||
@@ -915,9 +924,17 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x99A0)) {
                        rdev->config.cayman.max_simds_per_se = 3;
                        rdev->config.cayman.max_backends_per_se = 1;
+                       rdev->config.cayman.max_hw_contexts = 4;
+                       rdev->config.cayman.sx_max_export_size = 128;
+                       rdev->config.cayman.sx_max_export_pos_size = 32;
+                       rdev->config.cayman.sx_max_export_smx_size = 96;
                } else {
                        rdev->config.cayman.max_simds_per_se = 2;
                        rdev->config.cayman.max_backends_per_se = 1;
+                       rdev->config.cayman.max_hw_contexts = 4;
+                       rdev->config.cayman.sx_max_export_size = 128;
+                       rdev->config.cayman.sx_max_export_pos_size = 32;
+                       rdev->config.cayman.sx_max_export_smx_size = 96;
                }
                rdev->config.cayman.max_texture_channel_caches = 2;
                rdev->config.cayman.max_gprs = 256;
@@ -925,10 +942,6 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                rdev->config.cayman.max_gs_threads = 32;
                rdev->config.cayman.max_stack_entries = 512;
                rdev->config.cayman.sx_num_of_sets = 8;
-               rdev->config.cayman.sx_max_export_size = 256;
-               rdev->config.cayman.sx_max_export_pos_size = 64;
-               rdev->config.cayman.sx_max_export_smx_size = 192;
-               rdev->config.cayman.max_hw_contexts = 8;
                rdev->config.cayman.sq_num_cf_insts = 2;
 
                rdev->config.cayman.sc_prim_fifo_size = 0x40;
@@ -1318,13 +1331,12 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
 {
        struct radeon_ring *ring = &rdev->ring[fence->ring];
        u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
+       u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
+               PACKET3_SH_ACTION_ENA;
 
        /* flush read cache over gart for this vmid */
-       radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-       radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
-       radeon_ring_write(ring, 0);
        radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
-       radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA);
+       radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
        radeon_ring_write(ring, 0xFFFFFFFF);
        radeon_ring_write(ring, 0);
        radeon_ring_write(ring, 10); /* poll interval */
@@ -1340,6 +1352,8 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
 void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 {
        struct radeon_ring *ring = &rdev->ring[ib->ring];
+       u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
+               PACKET3_SH_ACTION_ENA;
 
        /* set to DX10/11 mode */
        radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
@@ -1364,14 +1378,11 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
                          (ib->vm ? (ib->vm->id << 24) : 0));
 
        /* flush read cache over gart for this vmid */
-       radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-       radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
-       radeon_ring_write(ring, ib->vm ? ib->vm->id : 0);
        radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
-       radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA);
+       radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
        radeon_ring_write(ring, 0xFFFFFFFF);
        radeon_ring_write(ring, 0);
-       radeon_ring_write(ring, 10); /* poll interval */
+       radeon_ring_write(ring, ((ib->vm ? ib->vm->id : 0) << 24) | 10); /* poll interval */
 }
 
 static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
@@ -1386,6 +1397,55 @@ static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
        }
 }
 
+u32 cayman_gfx_get_rptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring)
+{
+       u32 rptr;
+
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else {
+               if (ring->idx == RADEON_RING_TYPE_GFX_INDEX)
+                       rptr = RREG32(CP_RB0_RPTR);
+               else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX)
+                       rptr = RREG32(CP_RB1_RPTR);
+               else
+                       rptr = RREG32(CP_RB2_RPTR);
+       }
+
+       return rptr;
+}
+
+u32 cayman_gfx_get_wptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       if (ring->idx == RADEON_RING_TYPE_GFX_INDEX)
+               wptr = RREG32(CP_RB0_WPTR);
+       else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX)
+               wptr = RREG32(CP_RB1_WPTR);
+       else
+               wptr = RREG32(CP_RB2_WPTR);
+
+       return wptr;
+}
+
+void cayman_gfx_set_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring)
+{
+       if (ring->idx == RADEON_RING_TYPE_GFX_INDEX) {
+               WREG32(CP_RB0_WPTR, ring->wptr);
+               (void)RREG32(CP_RB0_WPTR);
+       } else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX) {
+               WREG32(CP_RB1_WPTR, ring->wptr);
+               (void)RREG32(CP_RB1_WPTR);
+       } else {
+               WREG32(CP_RB2_WPTR, ring->wptr);
+               (void)RREG32(CP_RB2_WPTR);
+       }
+}
+
 static int cayman_cp_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
@@ -1514,6 +1574,16 @@ static int cayman_cp_resume(struct radeon_device *rdev)
                CP_RB1_BASE,
                CP_RB2_BASE
        };
+       static const unsigned cp_rb_rptr[] = {
+               CP_RB0_RPTR,
+               CP_RB1_RPTR,
+               CP_RB2_RPTR
+       };
+       static const unsigned cp_rb_wptr[] = {
+               CP_RB0_WPTR,
+               CP_RB1_WPTR,
+               CP_RB2_WPTR
+       };
        struct radeon_ring *ring;
        int i, r;
 
@@ -1572,8 +1642,8 @@ static int cayman_cp_resume(struct radeon_device *rdev)
                WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA);
 
                ring->rptr = ring->wptr = 0;
-               WREG32(ring->rptr_reg, ring->rptr);
-               WREG32(ring->wptr_reg, ring->wptr);
+               WREG32(cp_rb_rptr[i], ring->rptr);
+               WREG32(cp_rb_wptr[i], ring->wptr);
 
                mdelay(1);
                WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA);
@@ -1819,8 +1889,10 @@ int cayman_asic_reset(struct radeon_device *rdev)
 
        reset_mask = cayman_gpu_check_soft_reset(rdev);
 
-       if (!reset_mask)
-               r600_set_bios_scratch_engine_hung(rdev, false);
+       if (reset_mask)
+               evergreen_gpu_pci_config_reset(rdev);
+
+       r600_set_bios_scratch_engine_hung(rdev, false);
 
        return 0;
 }
@@ -1866,23 +1938,7 @@ static int cayman_startup(struct radeon_device *rdev)
 
        evergreen_mc_program(rdev);
 
-       if (rdev->flags & RADEON_IS_IGP) {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-                       r = ni_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
-       } else {
-               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
-                       r = ni_init_microcode(rdev);
-                       if (r) {
-                               DRM_ERROR("Failed to load firmware!\n");
-                               return r;
-                       }
-               }
-
+       if (!(rdev->flags & RADEON_IS_IGP) && !rdev->pm.dpm_enabled) {
                r = ni_mc_load_microcode(rdev);
                if (r) {
                        DRM_ERROR("Failed to load MC firmware!\n");
@@ -1969,23 +2025,18 @@ static int cayman_startup(struct radeon_device *rdev)
        evergreen_irq_set(rdev);
 
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            CP_RB0_RPTR, CP_RB0_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR + DMA0_REGISTER_OFFSET,
-                            DMA_RB_WPTR + DMA0_REGISTER_OFFSET,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
-                            DMA_RB_RPTR + DMA1_REGISTER_OFFSET,
-                            DMA_RB_WPTR + DMA1_REGISTER_OFFSET,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
        if (r)
                return r;
@@ -2004,7 +2055,6 @@ static int cayman_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        if (ring->ring_size) {
                r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
                        r = uvd_v1_0_init(rdev);
@@ -2051,6 +2101,8 @@ int cayman_resume(struct radeon_device *rdev)
        /* init golden registers */
        ni_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = cayman_startup(rdev);
        if (r) {
@@ -2063,6 +2115,7 @@ int cayman_resume(struct radeon_device *rdev)
 
 int cayman_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        if (ASIC_IS_DCE6(rdev))
                dce6_audio_fini(rdev);
        else
@@ -2133,6 +2186,27 @@ int cayman_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (rdev->flags & RADEON_IS_IGP) {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+                       r = ni_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       } else {
+               if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+                       r = ni_init_microcode(rdev);
+                       if (r) {
+                               DRM_ERROR("Failed to load firmware!\n");
+                               return r;
+                       }
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 1024 * 1024);
 
@@ -2192,6 +2266,7 @@ int cayman_init(struct radeon_device *rdev)
 
 void cayman_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        cayman_cp_fini(rdev);
        cayman_dma_fini(rdev);
        r600_irq_fini(rdev);
index bdeb65ed365831db35a94a0ffae523f3c8e419dd..51424ab79432788d3006ba6268c6a4229c4dd43f 100644 (file)
@@ -42,6 +42,75 @@ u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev);
  * Cayman and newer support two asynchronous DMA engines.
  */
 
+/**
+ * cayman_dma_get_rptr - get the current read pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current rptr from the hardware (cayman+).
+ */
+uint32_t cayman_dma_get_rptr(struct radeon_device *rdev,
+                            struct radeon_ring *ring)
+{
+       u32 rptr, reg;
+
+       if (rdev->wb.enabled) {
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       } else {
+               if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+                       reg = DMA_RB_RPTR + DMA0_REGISTER_OFFSET;
+               else
+                       reg = DMA_RB_RPTR + DMA1_REGISTER_OFFSET;
+
+               rptr = RREG32(reg);
+       }
+
+       return (rptr & 0x3fffc) >> 2;
+}
+
+/**
+ * cayman_dma_get_wptr - get the current write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Get the current wptr from the hardware (cayman+).
+ */
+uint32_t cayman_dma_get_wptr(struct radeon_device *rdev,
+                          struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = DMA_RB_WPTR + DMA0_REGISTER_OFFSET;
+       else
+               reg = DMA_RB_WPTR + DMA1_REGISTER_OFFSET;
+
+       return (RREG32(reg) & 0x3fffc) >> 2;
+}
+
+/**
+ * cayman_dma_set_wptr - commit the write pointer
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon ring pointer
+ *
+ * Write the wptr back to the hardware (cayman+).
+ */
+void cayman_dma_set_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring)
+{
+       u32 reg;
+
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               reg = DMA_RB_WPTR + DMA0_REGISTER_OFFSET;
+       else
+               reg = DMA_RB_WPTR + DMA1_REGISTER_OFFSET;
+
+       WREG32(reg, (ring->wptr << 2) & 0x3fffc);
+}
+
 /**
  * cayman_dma_ring_ib_execute - Schedule an IB on the DMA engine
  *
index 49c4d48f54d616b49b7af261d8fa2d71586ab8fd..c351226ecb31b0d9fa2d94a32ac23d504d61952b 100644 (file)
@@ -720,6 +720,8 @@ static const u32 cayman_sysls_enable[] =
 struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
 struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
 
+extern int ni_mc_load_microcode(struct radeon_device *rdev);
+
 struct ni_power_info *ni_get_pi(struct radeon_device *rdev)
 {
         struct ni_power_info *pi = rdev->pm.dpm.priv;
@@ -3565,7 +3567,11 @@ void ni_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
 void ni_dpm_setup_asic(struct radeon_device *rdev)
 {
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       int r;
 
+       r = ni_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        ni_read_clock_registers(rdev);
        btc_read_arb_registers(rdev);
        rv770_get_memory_type(rdev);
@@ -3710,21 +3716,6 @@ int ni_dpm_enable(struct radeon_device *rdev)
        if (eg_pi->ls_clock_gating)
                ni_ls_clockgating_enable(rdev, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               PPSMC_Result result;
-
-               ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, 0xff * 1000);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-               result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
-
-               if (result != PPSMC_Result_OK)
-                       DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
-       }
-
        rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        ni_update_current_ps(rdev, boot_ps);
index 22421bc80c0d0d0d33c8b87ef9922c3cf982fc15..d996033c243ee14f4509220a707edf50f9dbe489 100644 (file)
 #              define PACKET3_DB_ACTION_ENA        (1 << 26)
 #              define PACKET3_SH_ACTION_ENA        (1 << 27)
 #              define PACKET3_SX_ACTION_ENA        (1 << 28)
+#              define PACKET3_ENGINE_ME            (1 << 31)
 #define        PACKET3_ME_INITIALIZE                           0x44
 #define                PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
 #define        PACKET3_COND_WRITE                              0x45
index da43ab3288332faf705a3e673663c5fe7fbc30b3..2d532996c69795cc129cb4ac6c60a4dfc4b70808 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef _PPTABLE_H
 #define _PPTABLE_H
 
-#pragma pack(push, 1)
+#pragma pack(1)
 
 typedef struct _ATOM_PPLIB_THERMALCONTROLLER
 
@@ -677,6 +677,6 @@ typedef struct _ATOM_PPLIB_PPM_Table
       ULONG  ulTjmax;
 } ATOM_PPLIB_PPM_Table;
 
-#pragma pack(pop)
+#pragma pack()
 
 #endif
index 10abc4d5a6cc396a85bb32d4b7d094b748757f99..ef024ce3f7ccfd39b1be47be9840a401b588b1dc 100644 (file)
@@ -1050,6 +1050,36 @@ static int r100_cp_init_microcode(struct radeon_device *rdev)
        return err;
 }
 
+u32 r100_gfx_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       u32 rptr;
+
+       if (rdev->wb.enabled)
+               rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
+       else
+               rptr = RREG32(RADEON_CP_RB_RPTR);
+
+       return rptr;
+}
+
+u32 r100_gfx_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       wptr = RREG32(RADEON_CP_RB_WPTR);
+
+       return wptr;
+}
+
+void r100_gfx_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring)
+{
+       WREG32(RADEON_CP_RB_WPTR, ring->wptr);
+       (void)RREG32(RADEON_CP_RB_WPTR);
+}
+
 static void r100_cp_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
@@ -1102,7 +1132,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
        ring_size = (1 << (rb_bufsz + 1)) * 4;
        r100_cp_load_microcode(rdev);
        r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR,
                             RADEON_CP_PACKET2);
        if (r) {
                return r;
@@ -3913,6 +3942,8 @@ int r100_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r100_startup(rdev);
        if (r) {
@@ -3923,6 +3954,7 @@ int r100_resume(struct radeon_device *rdev)
 
 int r100_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
        r100_irq_disable(rdev);
@@ -3933,6 +3965,7 @@ int r100_suspend(struct radeon_device *rdev)
 
 void r100_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -4039,6 +4072,9 @@ int r100_init(struct radeon_device *rdev)
        }
        r100_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = r100_startup(rdev);
        if (r) {
index d8dd269b9159fcc0dfbed98cf8c3c2037742e671..7c63ef840e86abaf04f216201b32ee2f40323b9b 100644 (file)
@@ -1430,6 +1430,8 @@ int r300_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r300_startup(rdev);
        if (r) {
@@ -1440,6 +1442,7 @@ int r300_resume(struct radeon_device *rdev)
 
 int r300_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
        r100_irq_disable(rdev);
@@ -1452,6 +1455,7 @@ int r300_suspend(struct radeon_device *rdev)
 
 void r300_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -1538,6 +1542,9 @@ int r300_init(struct radeon_device *rdev)
        }
        r300_set_reg_safe(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = r300_startup(rdev);
        if (r) {
index 60170ea5e3a228c0483c18f0fd1652b30ec7760b..84b1d5367a11f6950026337f76117bbb8edda0bb 100644 (file)
@@ -75,7 +75,7 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
                OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
 
                for (i = 0; i < nr; ++i) {
-                       if (DRM_COPY_FROM_USER
+                       if (copy_from_user
                            (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
                                DRM_ERROR("copy cliprect faulted\n");
                                return -EFAULT;
@@ -928,12 +928,12 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
                buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
                *buf_idx *= 2; /* 8 bytes per buf */
 
-               if (DRM_COPY_TO_USER(ref_age_base + *buf_idx,
+               if (copy_to_user(ref_age_base + *buf_idx,
                                &dev_priv->scratch_ages[header.scratch.reg],
                                sizeof(u32)))
                        return -EINVAL;
 
-               if (DRM_COPY_FROM_USER(&h_pending,
+               if (copy_from_user(&h_pending,
                                ref_age_base + *buf_idx + 1,
                                sizeof(u32)))
                        return -EINVAL;
@@ -943,7 +943,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
 
                h_pending--;
 
-               if (DRM_COPY_TO_USER(ref_age_base + *buf_idx + 1,
+               if (copy_to_user(ref_age_base + *buf_idx + 1,
                                        &h_pending,
                                        sizeof(u32)))
                        return -EINVAL;
index 6edf2b3a52b4d7e4ba82cc063048ffb73733a984..3768aab2710b3943261312c4fcc5184b4f18a6fb 100644 (file)
@@ -325,6 +325,8 @@ int r420_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r420_startup(rdev);
        if (r) {
@@ -335,6 +337,7 @@ int r420_resume(struct radeon_device *rdev)
 
 int r420_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r420_cp_errata_fini(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
@@ -348,6 +351,7 @@ int r420_suspend(struct radeon_device *rdev)
 
 void r420_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -444,6 +448,9 @@ int r420_init(struct radeon_device *rdev)
        }
        r420_set_reg_safe(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = r420_startup(rdev);
        if (r) {
index e1aece73b370c1ec9d6d9f86273caad0cbb14d36..e209eb75024f9dc1c441518cbe8f8d70a41844f5 100644 (file)
@@ -240,6 +240,8 @@ int r520_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r520_startup(rdev);
        if (r) {
@@ -312,6 +314,9 @@ int r520_init(struct radeon_device *rdev)
                return r;
        rv515_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = r520_startup(rdev);
        if (r) {
index 9ad06732a78bc6d079914a6ce15e92b7e273b265..3dce370adc1b78aedc2b316f81ef8375c8ed7309 100644 (file)
@@ -105,6 +105,7 @@ void r600_fini(struct radeon_device *rdev);
 void r600_irq_disable(struct radeon_device *rdev);
 static void r600_pcie_gen2_enable(struct radeon_device *rdev);
 extern int evergreen_rlc_resume(struct radeon_device *rdev);
+extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
 
 /**
  * r600_get_xclk - get the xclk
@@ -1644,6 +1645,67 @@ static void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        r600_print_gpu_status_regs(rdev);
 }
 
+static void r600_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct rv515_mc_save save;
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* Disable CP parsing/prefetching */
+       if (rdev->family >= CHIP_RV770)
+               WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1));
+       else
+               WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
+
+       /* disable the RLC */
+       WREG32(RLC_CNTL, 0);
+
+       /* Disable DMA */
+       tmp = RREG32(DMA_RB_CNTL);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL, tmp);
+
+       mdelay(50);
+
+       /* set mclk/sclk to bypass */
+       if (rdev->family >= CHIP_RV770)
+               rv770_set_clk_bypass_mode(rdev);
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* disable mem access */
+       rv515_mc_stop(rdev, &save);
+       if (r600_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+       }
+
+       /* BIF reset workaround.  Not sure if this is needed on 6xx */
+       tmp = RREG32(BUS_CNTL);
+       tmp |= VGA_COHE_SPEC_TIMER_DIS;
+       WREG32(BUS_CNTL, tmp);
+
+       tmp = RREG32(BIF_SCRATCH0);
+
+       /* reset */
+       radeon_pci_config_reset(rdev);
+       mdelay(1);
+
+       /* BIF reset workaround.  Not sure if this is needed on 6xx */
+       tmp = SOFT_RESET_BIF;
+       WREG32(SRBM_SOFT_RESET, tmp);
+       mdelay(1);
+       WREG32(SRBM_SOFT_RESET, 0);
+
+       /* wait for asic to come out of reset */
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+}
+
 int r600_asic_reset(struct radeon_device *rdev)
 {
        u32 reset_mask;
@@ -1653,10 +1715,17 @@ int r600_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        r600_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = r600_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               r600_gpu_pci_config_reset(rdev);
+
+       reset_mask = r600_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
@@ -2382,6 +2451,36 @@ out:
        return err;
 }
 
+u32 r600_gfx_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       u32 rptr;
+
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else
+               rptr = RREG32(R600_CP_RB_RPTR);
+
+       return rptr;
+}
+
+u32 r600_gfx_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring)
+{
+       u32 wptr;
+
+       wptr = RREG32(R600_CP_RB_WPTR);
+
+       return wptr;
+}
+
+void r600_gfx_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring)
+{
+       WREG32(R600_CP_RB_WPTR, ring->wptr);
+       (void)RREG32(R600_CP_RB_WPTR);
+}
+
 static int r600_cp_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
@@ -2607,14 +2706,17 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
                          struct radeon_fence *fence)
 {
        struct radeon_ring *ring = &rdev->ring[fence->ring];
+       u32 cp_coher_cntl = PACKET3_TC_ACTION_ENA | PACKET3_VC_ACTION_ENA |
+               PACKET3_SH_ACTION_ENA;
+
+       if (rdev->family >= CHIP_RV770)
+               cp_coher_cntl |= PACKET3_FULL_CACHE_ENA;
 
        if (rdev->wb.use_event) {
                u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
                /* flush read cache over gart */
                radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
-               radeon_ring_write(ring, PACKET3_TC_ACTION_ENA |
-                                       PACKET3_VC_ACTION_ENA |
-                                       PACKET3_SH_ACTION_ENA);
+               radeon_ring_write(ring, cp_coher_cntl);
                radeon_ring_write(ring, 0xFFFFFFFF);
                radeon_ring_write(ring, 0);
                radeon_ring_write(ring, 10); /* poll interval */
@@ -2628,9 +2730,7 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
        } else {
                /* flush read cache over gart */
                radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
-               radeon_ring_write(ring, PACKET3_TC_ACTION_ENA |
-                                       PACKET3_VC_ACTION_ENA |
-                                       PACKET3_SH_ACTION_ENA);
+               radeon_ring_write(ring, cp_coher_cntl);
                radeon_ring_write(ring, 0xFFFFFFFF);
                radeon_ring_write(ring, 0);
                radeon_ring_write(ring, 10); /* poll interval */
@@ -2775,14 +2875,6 @@ static int r600_startup(struct radeon_device *rdev)
 
        r600_mc_program(rdev);
 
-       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-               r = r600_init_microcode(rdev);
-               if (r) {
-                       DRM_ERROR("Failed to load firmware!\n");
-                       return r;
-               }
-       }
-
        if (rdev->flags & RADEON_IS_AGP) {
                r600_agp_enable(rdev);
        } else {
@@ -2826,14 +2918,12 @@ static int r600_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR, DMA_RB_WPTR,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
        if (r)
                return r;
@@ -2889,6 +2979,8 @@ int r600_resume(struct radeon_device *rdev)
        /* post card */
        atom_asic_init(rdev->mode_info.atom_context);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = r600_startup(rdev);
        if (r) {
@@ -2902,6 +2994,7 @@ int r600_resume(struct radeon_device *rdev)
 
 int r600_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        r600_cp_stop(rdev);
        r600_dma_stop(rdev);
@@ -2970,6 +3063,17 @@ int r600_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+               r = r600_init_microcode(rdev);
+               if (r) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       return r;
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -3002,6 +3106,7 @@ int r600_init(struct radeon_device *rdev)
 
 void r600_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r600_cp_fini(rdev);
        r600_dma_fini(rdev);
index d8eb48bff0ed204e9c52538342a11dcd1bd5b8ff..8c9b7e26533c6c81635a9dafa20e7cecb164b167 100644 (file)
@@ -2515,7 +2515,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev,
                buf = radeon_freelist_get(dev);
                if (!buf) {
                        DRM_DEBUG("EAGAIN\n");
-                       if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
+                       if (copy_to_user(tex->image, image, sizeof(*image)))
                                return -EFAULT;
                        return -EAGAIN;
                }
@@ -2528,7 +2528,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev,
                buffer =
                    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
 
-               if (DRM_COPY_FROM_USER(buffer, data, pass_size)) {
+               if (copy_from_user(buffer, data, pass_size)) {
                        DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size);
                        return -EFAULT;
                }
index 5dceea6f71ae450cf925b0d7e119783c801d6ebd..7b399dc5fd5492d1e53dcaa5b5be728164dc85b2 100644 (file)
@@ -749,7 +749,10 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
                }
 
                for (i = 0; i < 8; i++) {
-                       if ((tmp >> (i * 4)) & 0xF) {
+                       u32 format = G_0280A0_FORMAT(track->cb_color_info[i]);
+
+                       if (format != V_0280A0_COLOR_INVALID &&
+                           (tmp >> (i * 4)) & 0xF) {
                                /* at least one component is enabled */
                                if (track->cb_color_bo[i] == NULL) {
                                        dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
@@ -2386,7 +2389,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
        ib_chunk = &parser.chunks[parser.chunk_ib_idx];
        parser.ib.length_dw = ib_chunk->length_dw;
        *l = parser.ib.length_dw;
-       if (DRM_COPY_FROM_USER(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) {
+       if (copy_from_user(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) {
                r = -EFAULT;
                r600_cs_parser_fini(&parser, r);
                return r;
index 7844d15c139fcb97247880d596ab4354d4bea8d5..3452c8410bd76fa49a12cd5536f64793135ad9e7 100644 (file)
@@ -51,7 +51,14 @@ u32 r600_gpu_check_soft_reset(struct radeon_device *rdev);
 uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
                           struct radeon_ring *ring)
 {
-       return (radeon_ring_generic_get_rptr(rdev, ring) & 0x3fffc) >> 2;
+       u32 rptr;
+
+       if (rdev->wb.enabled)
+               rptr = rdev->wb.wb[ring->rptr_offs/4];
+       else
+               rptr = RREG32(DMA_RB_RPTR);
+
+       return (rptr & 0x3fffc) >> 2;
 }
 
 /**
@@ -65,7 +72,7 @@ uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
 uint32_t r600_dma_get_wptr(struct radeon_device *rdev,
                           struct radeon_ring *ring)
 {
-       return (RREG32(ring->wptr_reg) & 0x3fffc) >> 2;
+       return (RREG32(DMA_RB_WPTR) & 0x3fffc) >> 2;
 }
 
 /**
@@ -79,7 +86,7 @@ uint32_t r600_dma_get_wptr(struct radeon_device *rdev,
 void r600_dma_set_wptr(struct radeon_device *rdev,
                       struct radeon_ring *ring)
 {
-       WREG32(ring->wptr_reg, (ring->wptr << 2) & 0x3fffc);
+       WREG32(DMA_RB_WPTR, (ring->wptr << 2) & 0x3fffc);
 }
 
 /**
index 5513d8f06252e13e11e27e9d21d5aecae775b5a8..e4cc9b314ce974fe5caacf91a000cb9a76a584d6 100644 (file)
@@ -729,8 +729,8 @@ bool r600_is_uvd_state(u32 class, u32 class2)
        return false;
 }
 
-int r600_set_thermal_temperature_range(struct radeon_device *rdev,
-                                      int min_temp, int max_temp)
+static int r600_set_thermal_temperature_range(struct radeon_device *rdev,
+                                             int min_temp, int max_temp)
 {
        int low_temp = 0 * 1000;
        int high_temp = 255 * 1000;
@@ -777,6 +777,22 @@ bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor)
        }
 }
 
+int r600_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
+       if (rdev->irq.installed &&
+           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
+               ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
+               if (ret)
+                       return ret;
+               rdev->irq.dpm_thermal = true;
+               radeon_irq_set(rdev);
+       }
+
+       return 0;
+}
+
 union power_info {
        struct _ATOM_POWERPLAY_INFO info;
        struct _ATOM_POWERPLAY_INFO_V2 info_2;
index 1000bf9719f2449af5d15a153b147f19c6af25e4..07eab2b04e81b5db420a6ee96152c8b8e94e4092 100644 (file)
@@ -213,8 +213,6 @@ void r600_wait_for_power_level(struct radeon_device *rdev,
 void r600_start_dpm(struct radeon_device *rdev);
 void r600_stop_dpm(struct radeon_device *rdev);
 
-int r600_set_thermal_temperature_range(struct radeon_device *rdev,
-                                      int min_temp, int max_temp);
 bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor);
 
 int r600_parse_extended_power_table(struct radeon_device *rdev);
index b7d3ecba43e34d3b559ee072800101532150c631..3016fc14f502c49a61c2343c3b2ca877d2590109 100644 (file)
@@ -250,7 +250,7 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
                 value, ~HDMI0_AUDIO_TEST_EN);
 }
 
-void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+static void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
index ebe38724a9765765041eaa245fc7994c4fec01fb..37455f65107f7fc8c0d2ff8a6a14d5abe43c13af 100644 (file)
 #define RLC_UCODE_DATA                                    0x3f30
 
 #define SRBM_SOFT_RESET                                   0xe60
+#       define SOFT_RESET_BIF                             (1 << 1)
 #       define SOFT_RESET_DMA                             (1 << 12)
 #       define SOFT_RESET_RLC                             (1 << 13)
 #       define SOFT_RESET_UVD                             (1 << 18)
 #       define RV770_SOFT_RESET_DMA                       (1 << 20)
 
+#define BIF_SCRATCH0                                      0x5438
+
+#define BUS_CNTL                                          0x5420
+#       define BIOS_ROM_DIS                               (1 << 1)
+#       define VGA_COHE_SPEC_TIMER_DIS                    (1 << 9)
+
 #define CP_INT_CNTL                                       0xc124
 #       define CNTX_BUSY_INT_ENABLE                       (1 << 19)
 #       define CNTX_EMPTY_INT_ENABLE                      (1 << 20)
 #              define PACKET3_CP_DMA_CMD_DAIC      (1 << 29)
 #define        PACKET3_SURFACE_SYNC                            0x43
 #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
+#              define PACKET3_FULL_CACHE_ENA       (1 << 20) /* r7xx+ only */
 #              define PACKET3_TC_ACTION_ENA        (1 << 23)
 #              define PACKET3_VC_ACTION_ENA        (1 << 24)
 #              define PACKET3_CB_ACTION_ENA        (1 << 25)
index b1f990d0eaa101d1bce56fabfc4b286ff01de7e9..c5519ca4bbc4ac2b4eb84b93822ab3fe2f6b4643 100644 (file)
@@ -99,6 +99,7 @@ extern int radeon_fastfb;
 extern int radeon_dpm;
 extern int radeon_aspm;
 extern int radeon_runtime_pm;
+extern int radeon_hard_reset;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -139,6 +140,9 @@ extern int radeon_runtime_pm;
 #define RADEON_VA_RESERVED_SIZE                        (8 << 20)
 #define RADEON_IB_VM_MAX_SIZE                  (64 << 10)
 
+/* hard reset data */
+#define RADEON_ASIC_RESET_DATA                  0x39d5e86b
+
 /* reset flags */
 #define RADEON_RESET_GFX                       (1 << 0)
 #define RADEON_RESET_COMPUTE                   (1 << 1)
@@ -252,6 +256,7 @@ struct radeon_clock {
  * Power management
  */
 int radeon_pm_init(struct radeon_device *rdev);
+int radeon_pm_late_init(struct radeon_device *rdev);
 void radeon_pm_fini(struct radeon_device *rdev);
 void radeon_pm_compute_clocks(struct radeon_device *rdev);
 void radeon_pm_suspend(struct radeon_device *rdev);
@@ -413,6 +418,11 @@ struct radeon_mman {
        struct ttm_bo_device            bdev;
        bool                            mem_global_referenced;
        bool                            initialized;
+
+#if defined(CONFIG_DEBUG_FS)
+       struct dentry                   *vram;
+       struct dentry                   *gtt;
+#endif
 };
 
 /* bo virtual address in a specific vm */
@@ -779,13 +789,11 @@ struct radeon_ring {
        volatile uint32_t       *ring;
        unsigned                rptr;
        unsigned                rptr_offs;
-       unsigned                rptr_reg;
        unsigned                rptr_save_reg;
        u64                     next_rptr_gpu_addr;
        volatile u32            *next_rptr_cpu_addr;
        unsigned                wptr;
        unsigned                wptr_old;
-       unsigned                wptr_reg;
        unsigned                ring_size;
        unsigned                ring_free_dw;
        int                     count_dw;
@@ -949,7 +957,7 @@ unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring
 int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,
                        unsigned size, uint32_t *data);
 int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size,
-                    unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 nop);
+                    unsigned rptr_offs, u32 nop);
 void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *cp);
 
 
@@ -1775,6 +1783,7 @@ struct radeon_asic {
                int (*init)(struct radeon_device *rdev);
                void (*setup_asic)(struct radeon_device *rdev);
                int (*enable)(struct radeon_device *rdev);
+               int (*late_enable)(struct radeon_device *rdev);
                void (*disable)(struct radeon_device *rdev);
                int (*pre_set_power_state)(struct radeon_device *rdev);
                int (*set_power_state)(struct radeon_device *rdev);
@@ -1940,7 +1949,7 @@ struct si_asic {
        unsigned sc_earlyz_tile_fifo_size;
 
        unsigned num_tile_pipes;
-       unsigned num_backends_per_se;
+       unsigned backend_enable_mask;
        unsigned backend_disable_mask_per_asic;
        unsigned backend_map;
        unsigned num_texture_channel_caches;
@@ -1970,7 +1979,7 @@ struct cik_asic {
        unsigned sc_earlyz_tile_fifo_size;
 
        unsigned num_tile_pipes;
-       unsigned num_backends_per_se;
+       unsigned backend_enable_mask;
        unsigned backend_disable_mask_per_asic;
        unsigned backend_map;
        unsigned num_texture_channel_caches;
@@ -2650,6 +2659,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_dpm_init(rdev) rdev->asic->dpm.init((rdev))
 #define radeon_dpm_setup_asic(rdev) rdev->asic->dpm.setup_asic((rdev))
 #define radeon_dpm_enable(rdev) rdev->asic->dpm.enable((rdev))
+#define radeon_dpm_late_enable(rdev) rdev->asic->dpm.late_enable((rdev))
 #define radeon_dpm_disable(rdev) rdev->asic->dpm.disable((rdev))
 #define radeon_dpm_pre_set_power_state(rdev) rdev->asic->dpm.pre_set_power_state((rdev))
 #define radeon_dpm_set_power_state(rdev) rdev->asic->dpm.set_power_state((rdev))
@@ -2668,6 +2678,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 /* Common functions */
 /* AGP */
 extern int radeon_gpu_reset(struct radeon_device *rdev);
+extern void radeon_pci_config_reset(struct radeon_device *rdev);
 extern void r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung);
 extern void radeon_agp_disable(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
index e354ce94cdd17492030e2bd85ef1406810e9e5df..f74db43346fd86f4658e11cc62e6e08134127936 100644 (file)
@@ -182,9 +182,9 @@ static struct radeon_asic_ring r100_gfx_ring = {
        .ring_test = &r100_ring_test,
        .ib_test = &r100_ib_test,
        .is_lockup = &r100_gpu_is_lockup,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &r100_gfx_get_rptr,
+       .get_wptr = &r100_gfx_get_wptr,
+       .set_wptr = &r100_gfx_set_wptr,
 };
 
 static struct radeon_asic r100_asic = {
@@ -330,9 +330,9 @@ static struct radeon_asic_ring r300_gfx_ring = {
        .ring_test = &r100_ring_test,
        .ib_test = &r100_ib_test,
        .is_lockup = &r100_gpu_is_lockup,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &r100_gfx_get_rptr,
+       .get_wptr = &r100_gfx_get_wptr,
+       .set_wptr = &r100_gfx_set_wptr,
 };
 
 static struct radeon_asic r300_asic = {
@@ -883,9 +883,9 @@ static struct radeon_asic_ring r600_gfx_ring = {
        .ring_test = &r600_ring_test,
        .ib_test = &r600_ib_test,
        .is_lockup = &r600_gfx_is_lockup,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &r600_gfx_get_rptr,
+       .get_wptr = &r600_gfx_get_wptr,
+       .set_wptr = &r600_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring r600_dma_ring = {
@@ -1045,6 +1045,7 @@ static struct radeon_asic rv6xx_asic = {
                .init = &rv6xx_dpm_init,
                .setup_asic = &rv6xx_setup_asic,
                .enable = &rv6xx_dpm_enable,
+               .late_enable = &r600_dpm_late_enable,
                .disable = &rv6xx_dpm_disable,
                .pre_set_power_state = &r600_dpm_pre_set_power_state,
                .set_power_state = &rv6xx_dpm_set_power_state,
@@ -1135,6 +1136,7 @@ static struct radeon_asic rs780_asic = {
                .init = &rs780_dpm_init,
                .setup_asic = &rs780_dpm_setup_asic,
                .enable = &rs780_dpm_enable,
+               .late_enable = &r600_dpm_late_enable,
                .disable = &rs780_dpm_disable,
                .pre_set_power_state = &r600_dpm_pre_set_power_state,
                .set_power_state = &rs780_dpm_set_power_state,
@@ -1239,6 +1241,7 @@ static struct radeon_asic rv770_asic = {
                .init = &rv770_dpm_init,
                .setup_asic = &rv770_dpm_setup_asic,
                .enable = &rv770_dpm_enable,
+               .late_enable = &rv770_dpm_late_enable,
                .disable = &rv770_dpm_disable,
                .pre_set_power_state = &r600_dpm_pre_set_power_state,
                .set_power_state = &rv770_dpm_set_power_state,
@@ -1267,9 +1270,9 @@ static struct radeon_asic_ring evergreen_gfx_ring = {
        .ring_test = &r600_ring_test,
        .ib_test = &r600_ib_test,
        .is_lockup = &evergreen_gfx_is_lockup,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &r600_gfx_get_rptr,
+       .get_wptr = &r600_gfx_get_wptr,
+       .set_wptr = &r600_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring evergreen_dma_ring = {
@@ -1357,6 +1360,7 @@ static struct radeon_asic evergreen_asic = {
                .init = &cypress_dpm_init,
                .setup_asic = &cypress_dpm_setup_asic,
                .enable = &cypress_dpm_enable,
+               .late_enable = &rv770_dpm_late_enable,
                .disable = &cypress_dpm_disable,
                .pre_set_power_state = &r600_dpm_pre_set_power_state,
                .set_power_state = &cypress_dpm_set_power_state,
@@ -1449,6 +1453,7 @@ static struct radeon_asic sumo_asic = {
                .init = &sumo_dpm_init,
                .setup_asic = &sumo_dpm_setup_asic,
                .enable = &sumo_dpm_enable,
+               .late_enable = &sumo_dpm_late_enable,
                .disable = &sumo_dpm_disable,
                .pre_set_power_state = &sumo_dpm_pre_set_power_state,
                .set_power_state = &sumo_dpm_set_power_state,
@@ -1540,6 +1545,7 @@ static struct radeon_asic btc_asic = {
                .init = &btc_dpm_init,
                .setup_asic = &btc_dpm_setup_asic,
                .enable = &btc_dpm_enable,
+               .late_enable = &rv770_dpm_late_enable,
                .disable = &btc_dpm_disable,
                .pre_set_power_state = &btc_dpm_pre_set_power_state,
                .set_power_state = &btc_dpm_set_power_state,
@@ -1570,9 +1576,9 @@ static struct radeon_asic_ring cayman_gfx_ring = {
        .ib_test = &r600_ib_test,
        .is_lockup = &cayman_gfx_is_lockup,
        .vm_flush = &cayman_vm_flush,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &cayman_gfx_get_rptr,
+       .get_wptr = &cayman_gfx_get_wptr,
+       .set_wptr = &cayman_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring cayman_dma_ring = {
@@ -1585,9 +1591,9 @@ static struct radeon_asic_ring cayman_dma_ring = {
        .ib_test = &r600_dma_ib_test,
        .is_lockup = &cayman_dma_is_lockup,
        .vm_flush = &cayman_dma_vm_flush,
-       .get_rptr = &r600_dma_get_rptr,
-       .get_wptr = &r600_dma_get_wptr,
-       .set_wptr = &r600_dma_set_wptr
+       .get_rptr = &cayman_dma_get_rptr,
+       .get_wptr = &cayman_dma_get_wptr,
+       .set_wptr = &cayman_dma_set_wptr
 };
 
 static struct radeon_asic_ring cayman_uvd_ring = {
@@ -1683,6 +1689,7 @@ static struct radeon_asic cayman_asic = {
                .init = &ni_dpm_init,
                .setup_asic = &ni_dpm_setup_asic,
                .enable = &ni_dpm_enable,
+               .late_enable = &rv770_dpm_late_enable,
                .disable = &ni_dpm_disable,
                .pre_set_power_state = &ni_dpm_pre_set_power_state,
                .set_power_state = &ni_dpm_set_power_state,
@@ -1783,6 +1790,7 @@ static struct radeon_asic trinity_asic = {
                .init = &trinity_dpm_init,
                .setup_asic = &trinity_dpm_setup_asic,
                .enable = &trinity_dpm_enable,
+               .late_enable = &trinity_dpm_late_enable,
                .disable = &trinity_dpm_disable,
                .pre_set_power_state = &trinity_dpm_pre_set_power_state,
                .set_power_state = &trinity_dpm_set_power_state,
@@ -1813,9 +1821,9 @@ static struct radeon_asic_ring si_gfx_ring = {
        .ib_test = &r600_ib_test,
        .is_lockup = &si_gfx_is_lockup,
        .vm_flush = &si_vm_flush,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &cayman_gfx_get_rptr,
+       .get_wptr = &cayman_gfx_get_wptr,
+       .set_wptr = &cayman_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring si_dma_ring = {
@@ -1828,9 +1836,9 @@ static struct radeon_asic_ring si_dma_ring = {
        .ib_test = &r600_dma_ib_test,
        .is_lockup = &si_dma_is_lockup,
        .vm_flush = &si_dma_vm_flush,
-       .get_rptr = &r600_dma_get_rptr,
-       .get_wptr = &r600_dma_get_wptr,
-       .set_wptr = &r600_dma_set_wptr,
+       .get_rptr = &cayman_dma_get_rptr,
+       .get_wptr = &cayman_dma_get_wptr,
+       .set_wptr = &cayman_dma_set_wptr,
 };
 
 static struct radeon_asic si_asic = {
@@ -1913,6 +1921,7 @@ static struct radeon_asic si_asic = {
                .init = &si_dpm_init,
                .setup_asic = &si_dpm_setup_asic,
                .enable = &si_dpm_enable,
+               .late_enable = &si_dpm_late_enable,
                .disable = &si_dpm_disable,
                .pre_set_power_state = &si_dpm_pre_set_power_state,
                .set_power_state = &si_dpm_set_power_state,
@@ -1943,9 +1952,9 @@ static struct radeon_asic_ring ci_gfx_ring = {
        .ib_test = &cik_ib_test,
        .is_lockup = &cik_gfx_is_lockup,
        .vm_flush = &cik_vm_flush,
-       .get_rptr = &radeon_ring_generic_get_rptr,
-       .get_wptr = &radeon_ring_generic_get_wptr,
-       .set_wptr = &radeon_ring_generic_set_wptr,
+       .get_rptr = &cik_gfx_get_rptr,
+       .get_wptr = &cik_gfx_get_wptr,
+       .set_wptr = &cik_gfx_set_wptr,
 };
 
 static struct radeon_asic_ring ci_cp_ring = {
@@ -1958,9 +1967,9 @@ static struct radeon_asic_ring ci_cp_ring = {
        .ib_test = &cik_ib_test,
        .is_lockup = &cik_gfx_is_lockup,
        .vm_flush = &cik_vm_flush,
-       .get_rptr = &cik_compute_ring_get_rptr,
-       .get_wptr = &cik_compute_ring_get_wptr,
-       .set_wptr = &cik_compute_ring_set_wptr,
+       .get_rptr = &cik_compute_get_rptr,
+       .get_wptr = &cik_compute_get_wptr,
+       .set_wptr = &cik_compute_set_wptr,
 };
 
 static struct radeon_asic_ring ci_dma_ring = {
@@ -1973,9 +1982,9 @@ static struct radeon_asic_ring ci_dma_ring = {
        .ib_test = &cik_sdma_ib_test,
        .is_lockup = &cik_sdma_is_lockup,
        .vm_flush = &cik_dma_vm_flush,
-       .get_rptr = &r600_dma_get_rptr,
-       .get_wptr = &r600_dma_get_wptr,
-       .set_wptr = &r600_dma_set_wptr,
+       .get_rptr = &cik_sdma_get_rptr,
+       .get_wptr = &cik_sdma_get_wptr,
+       .set_wptr = &cik_sdma_set_wptr,
 };
 
 static struct radeon_asic ci_asic = {
@@ -2021,7 +2030,7 @@ static struct radeon_asic ci_asic = {
                .hdmi_setmode = &evergreen_hdmi_setmode,
        },
        .copy = {
-               .blit = NULL,
+               .blit = &cik_copy_cpdma,
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &cik_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
@@ -2058,6 +2067,7 @@ static struct radeon_asic ci_asic = {
                .init = &ci_dpm_init,
                .setup_asic = &ci_dpm_setup_asic,
                .enable = &ci_dpm_enable,
+               .late_enable = &ci_dpm_late_enable,
                .disable = &ci_dpm_disable,
                .pre_set_power_state = &ci_dpm_pre_set_power_state,
                .set_power_state = &ci_dpm_set_power_state,
@@ -2122,7 +2132,7 @@ static struct radeon_asic kv_asic = {
                .hdmi_setmode = &evergreen_hdmi_setmode,
        },
        .copy = {
-               .blit = NULL,
+               .blit = &cik_copy_cpdma,
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &cik_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
@@ -2159,6 +2169,7 @@ static struct radeon_asic kv_asic = {
                .init = &kv_dpm_init,
                .setup_asic = &kv_dpm_setup_asic,
                .enable = &kv_dpm_enable,
+               .late_enable = &kv_dpm_late_enable,
                .disable = &kv_dpm_disable,
                .pre_set_power_state = &kv_dpm_pre_set_power_state,
                .set_power_state = &kv_dpm_set_power_state,
@@ -2449,7 +2460,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                        rdev->cg_flags =
                                RADEON_CG_SUPPORT_GFX_MGCG |
                                RADEON_CG_SUPPORT_GFX_MGLS |
-                               /*RADEON_CG_SUPPORT_GFX_CGCG |*/
+                               RADEON_CG_SUPPORT_GFX_CGCG |
                                RADEON_CG_SUPPORT_GFX_CGLS |
                                RADEON_CG_SUPPORT_GFX_CGTS |
                                RADEON_CG_SUPPORT_GFX_CGTS_LS |
@@ -2468,7 +2479,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                        rdev->cg_flags =
                                RADEON_CG_SUPPORT_GFX_MGCG |
                                RADEON_CG_SUPPORT_GFX_MGLS |
-                               /*RADEON_CG_SUPPORT_GFX_CGCG |*/
+                               RADEON_CG_SUPPORT_GFX_CGCG |
                                RADEON_CG_SUPPORT_GFX_CGLS |
                                RADEON_CG_SUPPORT_GFX_CGTS |
                                RADEON_CG_SUPPORT_GFX_CP_LS |
@@ -2493,7 +2504,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                        rdev->cg_flags =
                                RADEON_CG_SUPPORT_GFX_MGCG |
                                RADEON_CG_SUPPORT_GFX_MGLS |
-                               /*RADEON_CG_SUPPORT_GFX_CGCG |*/
+                               RADEON_CG_SUPPORT_GFX_CGCG |
                                RADEON_CG_SUPPORT_GFX_CGLS |
                                RADEON_CG_SUPPORT_GFX_CGTS |
                                RADEON_CG_SUPPORT_GFX_CGTS_LS |
@@ -2521,7 +2532,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                        rdev->cg_flags =
                                RADEON_CG_SUPPORT_GFX_MGCG |
                                RADEON_CG_SUPPORT_GFX_MGLS |
-                               /*RADEON_CG_SUPPORT_GFX_CGCG |*/
+                               RADEON_CG_SUPPORT_GFX_CGCG |
                                RADEON_CG_SUPPORT_GFX_CGLS |
                                RADEON_CG_SUPPORT_GFX_CGTS |
                                RADEON_CG_SUPPORT_GFX_CGTS_LS |
index c9fd97b58076bd366e57e7916f93de5435c58c52..b3bc433eed4c3bd832424051306a845461c90aa8 100644 (file)
@@ -47,13 +47,6 @@ u8 atombios_get_backlight_level(struct radeon_encoder *radeon_encoder);
 void radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level);
 u8 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder);
 
-u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
-                                struct radeon_ring *ring);
-u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev,
-                                struct radeon_ring *ring);
-void radeon_ring_generic_set_wptr(struct radeon_device *rdev,
-                                 struct radeon_ring *ring);
-
 /*
  * r100,rv100,rs100,rv200,rs200
  */
@@ -148,6 +141,13 @@ extern void r100_post_page_flip(struct radeon_device *rdev, int crtc);
 extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
 extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
 
+u32 r100_gfx_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+u32 r100_gfx_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+void r100_gfx_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring);
+
 /*
  * r200,rv250,rs300,rv280
  */
@@ -368,6 +368,12 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev);
 int r600_pcie_gart_init(struct radeon_device *rdev);
 void r600_scratch_init(struct radeon_device *rdev);
 int r600_init_microcode(struct radeon_device *rdev);
+u32 r600_gfx_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+u32 r600_gfx_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+void r600_gfx_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring);
 /* r600 irq */
 int r600_irq_process(struct radeon_device *rdev);
 int r600_irq_init(struct radeon_device *rdev);
@@ -392,6 +398,7 @@ int rv6xx_get_temp(struct radeon_device *rdev);
 int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int r600_dpm_pre_set_power_state(struct radeon_device *rdev);
 void r600_dpm_post_set_power_state(struct radeon_device *rdev);
+int r600_dpm_late_enable(struct radeon_device *rdev);
 /* r600 dma */
 uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
                           struct radeon_ring *ring);
@@ -454,6 +461,7 @@ int rv770_get_temp(struct radeon_device *rdev);
 /* rv7xx pm */
 int rv770_dpm_init(struct radeon_device *rdev);
 int rv770_dpm_enable(struct radeon_device *rdev);
+int rv770_dpm_late_enable(struct radeon_device *rdev);
 void rv770_dpm_disable(struct radeon_device *rdev);
 int rv770_dpm_set_power_state(struct radeon_device *rdev);
 void rv770_dpm_setup_asic(struct radeon_device *rdev);
@@ -545,6 +553,7 @@ u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low);
 bool btc_dpm_vblank_too_short(struct radeon_device *rdev);
 int sumo_dpm_init(struct radeon_device *rdev);
 int sumo_dpm_enable(struct radeon_device *rdev);
+int sumo_dpm_late_enable(struct radeon_device *rdev);
 void sumo_dpm_disable(struct radeon_device *rdev);
 int sumo_dpm_pre_set_power_state(struct radeon_device *rdev);
 int sumo_dpm_set_power_state(struct radeon_device *rdev);
@@ -591,6 +600,19 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev,
 
 void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
 
+u32 cayman_gfx_get_rptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring);
+u32 cayman_gfx_get_wptr(struct radeon_device *rdev,
+                       struct radeon_ring *ring);
+void cayman_gfx_set_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring);
+uint32_t cayman_dma_get_rptr(struct radeon_device *rdev,
+                            struct radeon_ring *ring);
+uint32_t cayman_dma_get_wptr(struct radeon_device *rdev,
+                            struct radeon_ring *ring);
+void cayman_dma_set_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring);
+
 int ni_dpm_init(struct radeon_device *rdev);
 void ni_dpm_setup_asic(struct radeon_device *rdev);
 int ni_dpm_enable(struct radeon_device *rdev);
@@ -610,6 +632,7 @@ int ni_dpm_force_performance_level(struct radeon_device *rdev,
 bool ni_dpm_vblank_too_short(struct radeon_device *rdev);
 int trinity_dpm_init(struct radeon_device *rdev);
 int trinity_dpm_enable(struct radeon_device *rdev);
+int trinity_dpm_late_enable(struct radeon_device *rdev);
 void trinity_dpm_disable(struct radeon_device *rdev);
 int trinity_dpm_pre_set_power_state(struct radeon_device *rdev);
 int trinity_dpm_set_power_state(struct radeon_device *rdev);
@@ -669,6 +692,7 @@ int si_get_temp(struct radeon_device *rdev);
 int si_dpm_init(struct radeon_device *rdev);
 void si_dpm_setup_asic(struct radeon_device *rdev);
 int si_dpm_enable(struct radeon_device *rdev);
+int si_dpm_late_enable(struct radeon_device *rdev);
 void si_dpm_disable(struct radeon_device *rdev);
 int si_dpm_pre_set_power_state(struct radeon_device *rdev);
 int si_dpm_set_power_state(struct radeon_device *rdev);
@@ -739,17 +763,30 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
                          uint32_t incr, uint32_t flags);
 void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
 int cik_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
-u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring);
-u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
-                             struct radeon_ring *ring);
-void cik_compute_ring_set_wptr(struct radeon_device *rdev,
-                              struct radeon_ring *ring);
+u32 cik_gfx_get_rptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring);
+u32 cik_gfx_get_wptr(struct radeon_device *rdev,
+                    struct radeon_ring *ring);
+void cik_gfx_set_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+u32 cik_compute_get_rptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring);
+u32 cik_compute_get_wptr(struct radeon_device *rdev,
+                        struct radeon_ring *ring);
+void cik_compute_set_wptr(struct radeon_device *rdev,
+                         struct radeon_ring *ring);
+u32 cik_sdma_get_rptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+u32 cik_sdma_get_wptr(struct radeon_device *rdev,
+                     struct radeon_ring *ring);
+void cik_sdma_set_wptr(struct radeon_device *rdev,
+                      struct radeon_ring *ring);
 int ci_get_temp(struct radeon_device *rdev);
 int kv_get_temp(struct radeon_device *rdev);
 
 int ci_dpm_init(struct radeon_device *rdev);
 int ci_dpm_enable(struct radeon_device *rdev);
+int ci_dpm_late_enable(struct radeon_device *rdev);
 void ci_dpm_disable(struct radeon_device *rdev);
 int ci_dpm_pre_set_power_state(struct radeon_device *rdev);
 int ci_dpm_set_power_state(struct radeon_device *rdev);
@@ -770,6 +807,7 @@ void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
 
 int kv_dpm_init(struct radeon_device *rdev);
 int kv_dpm_enable(struct radeon_device *rdev);
+int kv_dpm_late_enable(struct radeon_device *rdev);
 void kv_dpm_disable(struct radeon_device *rdev);
 int kv_dpm_pre_set_power_state(struct radeon_device *rdev);
 int kv_dpm_set_power_state(struct radeon_device *rdev);
index 5c39bf7c3d88668bad65ef9667de82a0a145f196..f48bd6dc10cda2a9c993879c65f5fac574702728 100644 (file)
 #include "atom.h"
 #include "atom-bits.h"
 
-/* from radeon_encoder.c */
-extern uint32_t
-radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
-                       uint8_t dac);
-extern void radeon_link_encoder_connector(struct drm_device *dev);
 extern void
 radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum,
                        uint32_t supported_device, u16 caps);
 
-/* from radeon_connector.c */
-extern void
-radeon_add_atom_connector(struct drm_device *dev,
-                         uint32_t connector_id,
-                         uint32_t supported_device,
-                         int connector_type,
-                         struct radeon_i2c_bus_rec *i2c_bus,
-                         uint32_t igp_lane_info,
-                         uint16_t connector_object_id,
-                         struct radeon_hpd *hpd,
-                         struct radeon_router *router);
-
 /* from radeon_legacy_encoder.c */
 extern void
 radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
@@ -1528,6 +1511,7 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                                                le16_to_cpu(ss_assign->v1.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v1.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v1.usSpreadRateInKhz);
+                                       ss->percentage_divider = 100;
                                        return true;
                                }
                                ss_assign = (union asic_ss_assignment *)
@@ -1545,6 +1529,7 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                                                le16_to_cpu(ss_assign->v2.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v2.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v2.usSpreadRateIn10Hz);
+                                       ss->percentage_divider = 100;
                                        if ((crev == 2) &&
                                            ((id == ASIC_INTERNAL_ENGINE_SS) ||
                                             (id == ASIC_INTERNAL_MEMORY_SS)))
@@ -1566,6 +1551,11 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                                                le16_to_cpu(ss_assign->v3.usSpreadSpectrumPercentage);
                                        ss->type = ss_assign->v3.ucSpreadSpectrumMode;
                                        ss->rate = le16_to_cpu(ss_assign->v3.usSpreadRateIn10Hz);
+                                       if (ss_assign->v3.ucSpreadSpectrumMode &
+                                           SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK)
+                                               ss->percentage_divider = 1000;
+                                       else
+                                               ss->percentage_divider = 100;
                                        if ((id == ASIC_INTERNAL_ENGINE_SS) ||
                                            (id == ASIC_INTERNAL_MEMORY_SS))
                                                ss->rate /= 100;
@@ -1809,7 +1799,8 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
                if (misc & ATOM_DOUBLE_CLOCK_MODE)
                        mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 
-               mode->clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
+               mode->crtc_clock = mode->clock =
+                       le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
 
                if (index == 1) {
                        /* PAL timings appear to have wrong values for totals */
@@ -1852,7 +1843,8 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
                if (misc & ATOM_DOUBLE_CLOCK_MODE)
                        mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 
-               mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
+               mode->crtc_clock = mode->clock =
+                       le16_to_cpu(dtd_timings->usPixClk) * 10;
                break;
        }
        return true;
@@ -3884,16 +3876,18 @@ int radeon_atom_init_mc_reg_table(struct radeon_device *rdev,
                                                        ((u8 *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT));
                                        }
                                        reg_table->last = i;
-                                       while ((*(u32 *)reg_data != END_OF_REG_DATA_BLOCK) &&
+                                       while ((le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK) &&
                                               (num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES)) {
-                                               t_mem_id = (u8)((*(u32 *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT);
+                                               t_mem_id = (u8)((le32_to_cpu(*(u32 *)reg_data) & MEM_ID_MASK)
+                                                               >> MEM_ID_SHIFT);
                                                if (module_index == t_mem_id) {
                                                        reg_table->mc_reg_table_entry[num_ranges].mclk_max =
-                                                               (u32)((*(u32 *)reg_data & CLOCK_RANGE_MASK) >> CLOCK_RANGE_SHIFT);
+                                                               (u32)((le32_to_cpu(*(u32 *)reg_data) & CLOCK_RANGE_MASK)
+                                                                     >> CLOCK_RANGE_SHIFT);
                                                        for (i = 0, j = 1; i < reg_table->last; i++) {
                                                                if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_FROM_TABLE) {
                                                                        reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
-                                                                               (u32)*((u32 *)reg_data + j);
+                                                                               (u32)le32_to_cpu(*((u32 *)reg_data + j));
                                                                        j++;
                                                                } else if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_EQU_PREV) {
                                                                        reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
@@ -3905,7 +3899,7 @@ int radeon_atom_init_mc_reg_table(struct radeon_device *rdev,
                                                reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *)
                                                        ((u8 *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize));
                                        }
-                                       if (*(u32 *)reg_data != END_OF_REG_DATA_BLOCK)
+                                       if (le32_to_cpu(*(u32 *)reg_data) != END_OF_REG_DATA_BLOCK)
                                                return -EINVAL;
                                        reg_table->num_entries = num_ranges;
                                } else
index 9d302eaeea1587b6fdb5439119b6f45c0de961db..485848f889f55c9f4b86bf61bd8c019e2ad96a27 100644 (file)
@@ -33,6 +33,7 @@ static struct radeon_atpx_priv {
        bool atpx_detected;
        /* handle for device - and atpx */
        acpi_handle dhandle;
+       acpi_handle other_handle;
        struct radeon_atpx atpx;
 } radeon_atpx_priv;
 
@@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
                return false;
 
        status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
-       if (ACPI_FAILURE(status))
+       if (ACPI_FAILURE(status)) {
+               radeon_atpx_priv.other_handle = dhandle;
                return false;
-
+       }
        radeon_atpx_priv.dhandle = dhandle;
        radeon_atpx_priv.atpx.handle = atpx_handle;
        return true;
@@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void)
                printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
                       acpi_method_name);
                radeon_atpx_priv.atpx_detected = true;
+               /*
+                * On some systems hotplug events are generated for the device
+                * being switched off when ATPX is executed.  They cause ACPI
+                * hotplug to trigger and attempt to remove the device from
+                * the system, which causes it to break down.  Prevent that from
+                * happening by setting the no_hotplug flag for the involved
+                * ACPI device objects.
+                */
+               acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
+               acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
                return true;
        }
        return false;
index 68ce360560190af6505856452658e450d3f6878a..6651177110f08cd5afb9088f4849ad3f987f5a1b 100644 (file)
 #include <asm/pci-bridge.h>
 #endif /* CONFIG_PPC_PMAC */
 
-/* from radeon_encoder.c */
-extern uint32_t
-radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
-                       uint8_t dac);
-extern void radeon_link_encoder_connector(struct drm_device *dev);
-
-/* from radeon_connector.c */
-extern void
-radeon_add_legacy_connector(struct drm_device *dev,
-                           uint32_t connector_id,
-                           uint32_t supported_device,
-                           int connector_type,
-                           struct radeon_i2c_bus_rec *i2c_bus,
-                           uint16_t connector_object_id,
-                           struct radeon_hpd *hpd);
-
 /* from radeon_legacy_encoder.c */
 extern void
 radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum,
index 20a768ac89a8e6532b33cbb3114928afc98749b7..82d4f865546ed9024b4078d67bfdd947f08a1060 100644 (file)
 
 #include <linux/pm_runtime.h>
 
-extern void
-radeon_combios_connected_scratch_regs(struct drm_connector *connector,
-                                     struct drm_encoder *encoder,
-                                     bool connected);
-extern void
-radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
-                                      struct drm_encoder *encoder,
-                                      bool connected);
-
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
index 3cae2bbc1854d73dda35f13f0b8cfc3201dc2c25..bb0d5c3a8311bf0dc274c2b47930078d7e657852 100644 (file)
@@ -2020,10 +2020,10 @@ static int radeon_cp_get_buffers(struct drm_device *dev,
 
                buf->file_priv = file_priv;
 
-               if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+               if (copy_to_user(&d->request_indices[i], &buf->idx,
                                     sizeof(buf->idx)))
                        return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+               if (copy_to_user(&d->request_sizes[i], &buf->total,
                                     sizeof(buf->total)))
                        return -EFAULT;
 
@@ -2228,7 +2228,7 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv)
 
        dev_priv->ring.tail &= dev_priv->ring.tail_mask;
 
-       DRM_MEMORYBARRIER();
+       mb();
        GET_RING_HEAD( dev_priv );
 
        if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
index 0b366169d64de55c52e4c2d9c26d1c3b9db19b2d..a8e3342fd4a9d0d4a1f67c0a6cee0f3134ffa8d2 100644 (file)
@@ -192,7 +192,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                return -ENOMEM;
        }
        chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks);
-       if (DRM_COPY_FROM_USER(p->chunks_array, chunk_array_ptr,
+       if (copy_from_user(p->chunks_array, chunk_array_ptr,
                               sizeof(uint64_t)*cs->num_chunks)) {
                return -EFAULT;
        }
@@ -208,7 +208,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                uint32_t __user *cdata;
 
                chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i];
-               if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr,
+               if (copy_from_user(&user_chunk, chunk_ptr,
                                       sizeof(struct drm_radeon_cs_chunk))) {
                        return -EFAULT;
                }
@@ -252,7 +252,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                if (p->chunks[i].kdata == NULL) {
                        return -ENOMEM;
                }
-               if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) {
+               if (copy_from_user(p->chunks[i].kdata, cdata, size)) {
                        return -EFAULT;
                }
                if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) {
@@ -472,7 +472,7 @@ static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser
                        }
                        parser->const_ib.is_const_ib = true;
                        parser->const_ib.length_dw = ib_chunk->length_dw;
-                       if (DRM_COPY_FROM_USER(parser->const_ib.ptr,
+                       if (copy_from_user(parser->const_ib.ptr,
                                               ib_chunk->user_ptr,
                                               ib_chunk->length_dw * 4))
                                return -EFAULT;
@@ -495,7 +495,7 @@ static int radeon_cs_ib_fill(struct radeon_device *rdev, struct radeon_cs_parser
        parser->ib.length_dw = ib_chunk->length_dw;
        if (ib_chunk->kdata)
                memcpy(parser->ib.ptr, ib_chunk->kdata, ib_chunk->length_dw * 4);
-       else if (DRM_COPY_FROM_USER(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4))
+       else if (copy_from_user(parser->ib.ptr, ib_chunk->user_ptr, ib_chunk->length_dw * 4))
                return -EFAULT;
        return 0;
 }
index 39b033b441d2a6f76e8d021df7085568538887b3..b012cbbc3ed5a9b892b433eff0ee5f3134a130de 100644 (file)
@@ -144,6 +144,11 @@ void radeon_program_register_sequence(struct radeon_device *rdev,
        }
 }
 
+void radeon_pci_config_reset(struct radeon_device *rdev)
+{
+       pci_write_config_dword(rdev->pdev, 0x7c, RADEON_ASIC_RESET_DATA);
+}
+
 /**
  * radeon_surface_init - Clear GPU surface registers.
  *
@@ -249,7 +254,7 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg)
  * Init doorbell driver information (CIK)
  * Returns 0 on success, error on failure.
  */
-int radeon_doorbell_init(struct radeon_device *rdev)
+static int radeon_doorbell_init(struct radeon_device *rdev)
 {
        /* doorbell bar mapping */
        rdev->doorbell.base = pci_resource_start(rdev->pdev, 2);
@@ -278,7 +283,7 @@ int radeon_doorbell_init(struct radeon_device *rdev)
  *
  * Tear down doorbell driver information (CIK)
  */
-void radeon_doorbell_fini(struct radeon_device *rdev)
+static void radeon_doorbell_fini(struct radeon_device *rdev)
 {
        iounmap(rdev->doorbell.ptr);
        rdev->doorbell.ptr = NULL;
@@ -1330,6 +1335,7 @@ int radeon_device_init(struct radeon_device *rdev,
                if (r)
                        return r;
        }
+
        if ((radeon_testing & 1)) {
                if (rdev->accel_working)
                        radeon_test_moves(rdev);
@@ -1455,7 +1461,6 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 
        radeon_save_bios_scratch_regs(rdev);
 
-       radeon_pm_suspend(rdev);
        radeon_suspend(rdev);
        radeon_hpd_fini(rdev);
        /* evict remaining vram memory */
@@ -1516,14 +1521,22 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        if (r)
                DRM_ERROR("ib ring test failed (%d).\n", r);
 
-       radeon_pm_resume(rdev);
+       if (rdev->pm.dpm_enabled) {
+               /* do dpm late init */
+               r = radeon_pm_late_init(rdev);
+               if (r) {
+                       rdev->pm.dpm_enabled = false;
+                       DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+               }
+       }
+
        radeon_restore_bios_scratch_regs(rdev);
 
        if (fbcon) {
                radeon_fbdev_set_suspend(rdev, 0);
                console_unlock();
        }
-       
+
        /* init dig PHYs, disp eng pll */
        if (rdev->is_atom_bios) {
                radeon_atom_encoder_init(rdev);
index 7b253815a3237153b668d660e9ef7d56642597ec..d680608f6f5bc9a80e879b4f24769f8a9ffb1e8c 100644 (file)
@@ -306,7 +306,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
         * to complete in this vblank?
         */
        if (update_pending &&
-           (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id,
+           (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, 0,
                                                               &vpos, &hpos, NULL, NULL)) &&
            ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
             (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
@@ -1464,12 +1464,22 @@ int radeon_modeset_init(struct radeon_device *rdev)
        /* setup afmt */
        radeon_afmt_init(rdev);
 
-       /* Initialize power management */
-       radeon_pm_init(rdev);
-
        radeon_fbdev_init(rdev);
        drm_kms_helper_poll_init(rdev->ddev);
 
+       if (rdev->pm.dpm_enabled) {
+               /* do dpm late init */
+               ret = radeon_pm_late_init(rdev);
+               if (ret) {
+                       rdev->pm.dpm_enabled = false;
+                       DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+               }
+               /* set the dpm state for PX since there won't be
+                * a modeset to call this.
+                */
+               radeon_pm_compute_clocks(rdev);
+       }
+
        return 0;
 }
 
@@ -1477,7 +1487,6 @@ void radeon_modeset_fini(struct radeon_device *rdev)
 {
        radeon_fbdev_fini(rdev);
        kfree(rdev->mode_info.bios_hardcoded_edid);
-       radeon_pm_fini(rdev);
 
        if (rdev->mode_info.mode_config_initialized) {
                radeon_afmt_fini(rdev);
@@ -1601,6 +1610,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
  *
  * \param dev Device to query.
  * \param crtc Crtc to query.
+ * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0).
  * \param *vpos Location where vertical scanout position should be stored.
  * \param *hpos Location where horizontal scanout position should go.
  * \param *stime Target location for timestamp taken immediately before
@@ -1622,8 +1632,8 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
  * unknown small number of scanlines wrt. real scanout position.
  *
  */
-int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos,
-                              ktime_t *stime, ktime_t *etime)
+int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags,
+                              int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
 {
        u32 stat_crtc = 0, vbl = 0, position = 0;
        int vbl_start, vbl_end, vtotal, ret = 0;
@@ -1765,5 +1775,27 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int
        if (in_vbl)
                ret |= DRM_SCANOUTPOS_INVBL;
 
+       /* Is vpos outside nominal vblank area, but less than
+        * 1/100 of a frame height away from start of vblank?
+        * If so, assume this isn't a massively delayed vblank
+        * interrupt, but a vblank interrupt that fired a few
+        * microseconds before true start of vblank. Compensate
+        * by adding a full frame duration to the final timestamp.
+        * Happens, e.g., on ATI R500, R600.
+        *
+        * We only do this if DRM_CALLED_FROM_VBLIRQ.
+        */
+       if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
+               vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
+               vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+
+               if (vbl_start - *vpos < vtotal / 100) {
+                       *vpos -= vtotal;
+
+                       /* Signal this correction as "applied". */
+                       ret |= 0x8;
+               }
+       }
+
        return ret;
 }
index 9f5ff28864f6e3ccf4f4736cc55307735d87a70a..1235a78fbba15716d9987b3cb645120fca6bc30d 100644 (file)
  *   2.33.0 - Add SI tiling mode array query
  *   2.34.0 - Add CIK tiling mode array query
  *   2.35.0 - Add CIK macrotile mode array query
+ *   2.36.0 - Fix CIK DCE tiling setup
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       35
+#define KMS_DRIVER_MINOR       36
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -101,13 +102,14 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
 void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
 int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
 void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
-irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS);
+irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg);
 void radeon_gem_object_free(struct drm_gem_object *obj);
 int radeon_gem_object_open(struct drm_gem_object *obj,
                                struct drm_file *file_priv);
 void radeon_gem_object_close(struct drm_gem_object *obj,
                                struct drm_file *file_priv);
 extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+                                     unsigned int flags,
                                      int *vpos, int *hpos, ktime_t *stime,
                                      ktime_t *etime);
 extern const struct drm_ioctl_desc radeon_ioctls_kms[];
@@ -167,6 +169,7 @@ int radeon_fastfb = 0;
 int radeon_dpm = -1;
 int radeon_aspm = -1;
 int radeon_runtime_pm = -1;
+int radeon_hard_reset = 0;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -231,6 +234,9 @@ module_param_named(aspm, radeon_aspm, int, 0444);
 MODULE_PARM_DESC(runpm, "PX runtime pm (1 = force enable, 0 = disable, -1 = PX only default)");
 module_param_named(runpm, radeon_runtime_pm, int, 0444);
 
+MODULE_PARM_DESC(hard_reset, "PCI config reset (1 = force enable, 0 = disable (default))");
+module_param_named(hard_reset, radeon_hard_reset, int, 0444);
+
 static struct pci_device_id pciidlist[] = {
        radeon_PCI_IDS
 };
@@ -508,15 +514,6 @@ static const struct file_operations radeon_driver_kms_fops = {
 #endif
 };
 
-
-static void
-radeon_pci_shutdown(struct pci_dev *pdev)
-{
-       struct drm_device *dev = pci_get_drvdata(pdev);
-
-       radeon_driver_unload_kms(dev);
-}
-
 static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP |
@@ -586,7 +583,6 @@ static struct pci_driver radeon_kms_pci_driver = {
        .probe = radeon_pci_probe,
        .remove = radeon_pci_remove,
        .driver.pm = &radeon_pm_ops,
-       .shutdown = radeon_pci_shutdown,
 };
 
 static int __init radeon_init(void)
index 00e0d449021c343015540ea3baf1028b85a10090..dafd812e45710b0ffed36c33f3e37de20ec64733 100644 (file)
@@ -405,7 +405,7 @@ extern void radeon_do_release(struct drm_device * dev);
 extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
 extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
-extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t radeon_driver_irq_handler(int irq, void *arg);
 extern void radeon_driver_irq_preinstall(struct drm_device * dev);
 extern int radeon_driver_irq_postinstall(struct drm_device *dev);
 extern void radeon_driver_irq_uninstall(struct drm_device * dev);
index d3a86e43c0123715e0cf765a738e6664f42ab6e0..866744e47cfacc20c98a19151c9b7529eb9c447b 100644 (file)
@@ -841,6 +841,8 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
                if (!rdev->fence_drv[i].initialized)
                        continue;
 
+               radeon_fence_process(rdev, i);
+
                seq_printf(m, "--- ring %d ---\n", i);
                seq_printf(m, "Last signaled fence 0x%016llx\n",
                           (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq));
index 805c5e566b9a1f29539a4cf1148183056dc90579..b96c819024b3cdb7b2ea8f387c1e267a563ed8df 100644 (file)
@@ -86,7 +86,7 @@ retry:
        return 0;
 }
 
-int radeon_gem_set_domain(struct drm_gem_object *gobj,
+static int radeon_gem_set_domain(struct drm_gem_object *gobj,
                          uint32_t rdomain, uint32_t wdomain)
 {
        struct radeon_bo *robj;
index fc60b74ee304dd779d98db03b3ec60c58767ed9a..e24ca6ab96decdf94c3e86a097d949f2705a1f7c 100644 (file)
@@ -1020,6 +1020,9 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
 /* Add the default buses */
 void radeon_i2c_init(struct radeon_device *rdev)
 {
+       if (radeon_hw_i2c)
+               DRM_INFO("hw_i2c forced on, you may experience display detection problems!\n");
+
        if (rdev->is_atom_bios)
                radeon_atombios_i2c_init(rdev);
        else
index 8d68e972789a343f08186c3a4560d7c18db24999..244b19bab2e72406648ef1b2eae8ef7965bfcf01 100644 (file)
@@ -181,7 +181,7 @@ static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_dis
  * tied to dma at all, this is just a hangover from dri prehistory.
  */
 
-irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t radeon_driver_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_radeon_private_t *dev_priv =
@@ -203,7 +203,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
 
        /* SW interrupt */
        if (stat & RADEON_SW_INT_TEST)
-               DRM_WAKEUP(&dev_priv->swi_queue);
+               wake_up(&dev_priv->swi_queue);
 
        /* VBLANK interrupt */
        if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
@@ -249,7 +249,7 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
 
        dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
-       DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
+       DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * HZ,
                    RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
 
        return ret;
@@ -302,7 +302,7 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr
 
        result = radeon_emit_irq(dev);
 
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
+       if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
@@ -354,7 +354,7 @@ int radeon_driver_irq_postinstall(struct drm_device *dev)
            (drm_radeon_private_t *) dev->dev_private;
 
        atomic_set(&dev_priv->swi_emitted, 0);
-       DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+       init_waitqueue_head(&dev_priv->swi_queue);
 
        dev->max_vblank_count = 0x001fffff;
 
index ec6240b00469a18c471e181d59c4670b2e05069d..089c9ffb0aa95e8e47c964f190b07e0e8fe93c32 100644 (file)
 /**
  * radeon_driver_irq_handler_kms - irq handler for KMS
  *
- * @DRM_IRQ_ARGS: args
+ * @int irq, void *arg: args
  *
  * This is the irq handler for the radeon KMS driver (all asics).
  * radeon_irq_process is a macro that points to the per-asic
  * irq handler callback.
  */
-irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
+irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        struct radeon_device *rdev = dev->dev_private;
index 55d0b474bd371ae83f1cea0ec08d30504b371816..114d1672d616d0b5d7b85ab5d739da66f2db823e 100644 (file)
@@ -191,7 +191,7 @@ static void radeon_set_filp_rights(struct drm_device *dev,
  * etc. (all asics).
  * Returns 0 on success, -EINVAL on failure.
  */
-int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
        struct radeon_device *rdev = dev->dev_private;
        struct drm_radeon_info *info = data;
@@ -223,7 +223,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                        *value = rdev->accel_working;
                break;
        case RADEON_INFO_CRTC_FROM_ID:
-               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+               if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
                        DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
                        return -EFAULT;
                }
@@ -269,7 +269,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                 *
                 * When returning, the value is 1 if filp owns hyper-z access,
                 * 0 otherwise. */
-               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+               if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
                        DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
                        return -EFAULT;
                }
@@ -281,7 +281,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                break;
        case RADEON_INFO_WANT_CMASK:
                /* The same logic as Hyper-Z. */
-               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+               if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
                        DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
                        return -EFAULT;
                }
@@ -417,7 +417,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                *value = rdev->fastfb_working;
                break;
        case RADEON_INFO_RING_WORKING:
-               if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
+               if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
                        DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
                        return -EFAULT;
                }
@@ -461,11 +461,27 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        case RADEON_INFO_SI_CP_DMA_COMPUTE:
                *value = 1;
                break;
+       case RADEON_INFO_SI_BACKEND_ENABLED_MASK:
+               if (rdev->family >= CHIP_BONAIRE) {
+                       *value = rdev->config.cik.backend_enable_mask;
+               } else if (rdev->family >= CHIP_TAHITI) {
+                       *value = rdev->config.si.backend_enable_mask;
+               } else {
+                       DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
+               }
+               break;
+       case RADEON_INFO_MAX_SCLK:
+               if ((rdev->pm.pm_method == PM_METHOD_DPM) &&
+                   rdev->pm.dpm_enabled)
+                       *value = rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk * 10;
+               else
+                       *value = rdev->pm.default_sclk * 10;
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
        }
-       if (DRM_COPY_TO_USER(value_ptr, (char*)value, value_size)) {
+       if (copy_to_user(value_ptr, (char*)value, value_size)) {
                DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
                return -EFAULT;
        }
@@ -703,11 +719,12 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
        /* Helper routine in DRM core does all the work: */
        return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
                                                     vblank_time, flags,
-                                                    drmcrtc);
+                                                    drmcrtc, &drmcrtc->hwmode);
 }
 
 #define KMS_INVALID_IOCTL(name)                                                \
-int name(struct drm_device *dev, void *data, struct drm_file *file_priv)\
+static int name(struct drm_device *dev, void *data, struct drm_file    \
+               *file_priv)                                             \
 {                                                                      \
        DRM_ERROR("invalid ioctl with kms %s\n", __func__);             \
        return -EINVAL;                                                 \
index d54d2d7c9031a7ff957fec87b1d58c0ed927e6a5..146d253f1131a4780e889893b3e566336548b3f7 100644 (file)
@@ -243,7 +243,7 @@ int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_p
        if (!block)
                return -ENOMEM;
 
-       if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
+       if (copy_to_user(alloc->region_offset, &block->start,
                             sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
index 3f0dd664af90d6815b2edea895662936cc1982e4..402dbe32c23483afb3524d3397e3ce1b7c3cc281 100644 (file)
@@ -291,6 +291,7 @@ struct radeon_tv_regs {
 
 struct radeon_atom_ss {
        uint16_t percentage;
+       uint16_t percentage_divider;
        uint8_t type;
        uint16_t step;
        uint8_t delay;
@@ -624,6 +625,30 @@ struct atom_voltage_table
        struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES];
 };
 
+
+extern void
+radeon_add_atom_connector(struct drm_device *dev,
+                         uint32_t connector_id,
+                         uint32_t supported_device,
+                         int connector_type,
+                         struct radeon_i2c_bus_rec *i2c_bus,
+                         uint32_t igp_lane_info,
+                         uint16_t connector_object_id,
+                         struct radeon_hpd *hpd,
+                         struct radeon_router *router);
+extern void
+radeon_add_legacy_connector(struct drm_device *dev,
+                           uint32_t connector_id,
+                           uint32_t supported_device,
+                           int connector_type,
+                           struct radeon_i2c_bus_rec *i2c_bus,
+                           uint16_t connector_object_id,
+                           struct radeon_hpd *hpd);
+extern uint32_t
+radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device,
+                       uint8_t dac);
+extern void radeon_link_encoder_connector(struct drm_device *dev);
+
 extern enum radeon_tv_std
 radeon_combios_get_tv_info(struct radeon_device *rdev);
 extern enum radeon_tv_std
@@ -631,6 +656,15 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev);
 extern void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
                                                 u16 *vddc, u16 *vddci, u16 *mvdd);
 
+extern void
+radeon_combios_connected_scratch_regs(struct drm_connector *connector,
+                                     struct drm_encoder *encoder,
+                                     bool connected);
+extern void
+radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
+                                      struct drm_encoder *encoder,
+                                      bool connected);
+
 extern struct drm_connector *
 radeon_get_connector_for_encoder(struct drm_encoder *encoder);
 extern struct drm_connector *
@@ -666,6 +700,7 @@ extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
 extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
 extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                                u8 write_byte, u8 *read_byte);
+void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
 
 extern void radeon_i2c_init(struct radeon_device *rdev);
 extern void radeon_i2c_fini(struct radeon_device *rdev);
@@ -766,6 +801,7 @@ extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                                   int x, int y);
 
 extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+                                     unsigned int flags,
                                      int *vpos, int *hpos, ktime_t *stime,
                                      ktime_t *etime);
 
index c0fa4aa9ceea8ad8d22c7485b28f4bf045a3a7dd..08595cf90b0139ee0da24f4ac3725e30dcbf9d68 100644 (file)
@@ -46,7 +46,7 @@ static void radeon_bo_clear_surface_reg(struct radeon_bo *bo);
  * function are calling it.
  */
 
-void radeon_bo_clear_va(struct radeon_bo *bo)
+static void radeon_bo_clear_va(struct radeon_bo *bo)
 {
        struct radeon_bo_va *bo_va, *tmp;
 
index 984097b907ef5ee67c8e59faf4198ccf8add5f1b..8e8153e471c20a6b0dba28b38ce36bcd78f41a7b 100644 (file)
@@ -924,6 +924,10 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
 
        if (rdev->asic->dpm.powergate_uvd) {
                mutex_lock(&rdev->pm.mutex);
+               /* don't powergate anything if we
+                  have active but pause streams */
+               enable |= rdev->pm.dpm.sd > 0;
+               enable |= rdev->pm.dpm.hd > 0;
                /* enable/disable UVD */
                radeon_dpm_powergate_uvd(rdev, !enable);
                mutex_unlock(&rdev->pm.mutex);
@@ -1010,8 +1014,10 @@ static void radeon_pm_resume_old(struct radeon_device *rdev)
        rdev->pm.current_clock_mode_index = 0;
        rdev->pm.current_sclk = rdev->pm.default_sclk;
        rdev->pm.current_mclk = rdev->pm.default_mclk;
-       rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
-       rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
+       if (rdev->pm.power_state) {
+               rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+               rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
+       }
        if (rdev->pm.pm_method == PM_METHOD_DYNPM
            && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
                rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
@@ -1032,25 +1038,27 @@ static void radeon_pm_resume_dpm(struct radeon_device *rdev)
        radeon_dpm_setup_asic(rdev);
        ret = radeon_dpm_enable(rdev);
        mutex_unlock(&rdev->pm.mutex);
-       if (ret) {
-               DRM_ERROR("radeon: dpm resume failed\n");
-               if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_CAYMAN) &&
-                   rdev->mc_fw) {
-                       if (rdev->pm.default_vddc)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDC);
-                       if (rdev->pm.default_vddci)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDCI);
-                       if (rdev->pm.default_sclk)
-                               radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
-                       if (rdev->pm.default_mclk)
-                               radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
-               }
-       } else {
-               rdev->pm.dpm_enabled = true;
-               radeon_pm_compute_clocks(rdev);
+       if (ret)
+               goto dpm_resume_fail;
+       rdev->pm.dpm_enabled = true;
+       radeon_pm_compute_clocks(rdev);
+       return;
+
+dpm_resume_fail:
+       DRM_ERROR("radeon: dpm resume failed\n");
+       if ((rdev->family >= CHIP_BARTS) &&
+           (rdev->family <= CHIP_CAYMAN) &&
+           rdev->mc_fw) {
+               if (rdev->pm.default_vddc)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDC);
+               if (rdev->pm.default_vddci)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDCI);
+               if (rdev->pm.default_sclk)
+                       radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
+               if (rdev->pm.default_mclk)
+                       radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
        }
 }
 
@@ -1170,51 +1178,50 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
        radeon_dpm_setup_asic(rdev);
        ret = radeon_dpm_enable(rdev);
        mutex_unlock(&rdev->pm.mutex);
-       if (ret) {
-               rdev->pm.dpm_enabled = false;
-               if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_CAYMAN) &&
-                   rdev->mc_fw) {
-                       if (rdev->pm.default_vddc)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDC);
-                       if (rdev->pm.default_vddci)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDCI);
-                       if (rdev->pm.default_sclk)
-                               radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
-                       if (rdev->pm.default_mclk)
-                               radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
-               }
-               DRM_ERROR("radeon: dpm initialization failed\n");
-               return ret;
-       }
+       if (ret)
+               goto dpm_failed;
        rdev->pm.dpm_enabled = true;
-       radeon_pm_compute_clocks(rdev);
 
-       if (rdev->pm.num_power_states > 1) {
-               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
-               if (ret)
-                       DRM_ERROR("failed to create device file for dpm state\n");
-               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
-               if (ret)
-                       DRM_ERROR("failed to create device file for dpm state\n");
-               /* XXX: these are noops for dpm but are here for backwards compat */
-               ret = device_create_file(rdev->dev, &dev_attr_power_profile);
-               if (ret)
-                       DRM_ERROR("failed to create device file for power profile\n");
-               ret = device_create_file(rdev->dev, &dev_attr_power_method);
-               if (ret)
-                       DRM_ERROR("failed to create device file for power method\n");
-
-               if (radeon_debugfs_pm_init(rdev)) {
-                       DRM_ERROR("Failed to register debugfs file for dpm!\n");
-               }
+       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
+       if (ret)
+               DRM_ERROR("failed to create device file for dpm state\n");
+       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
+       if (ret)
+               DRM_ERROR("failed to create device file for dpm state\n");
+       /* XXX: these are noops for dpm but are here for backwards compat */
+       ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+       if (ret)
+               DRM_ERROR("failed to create device file for power profile\n");
+       ret = device_create_file(rdev->dev, &dev_attr_power_method);
+       if (ret)
+               DRM_ERROR("failed to create device file for power method\n");
 
-               DRM_INFO("radeon: dpm initialized\n");
+       if (radeon_debugfs_pm_init(rdev)) {
+               DRM_ERROR("Failed to register debugfs file for dpm!\n");
        }
 
+       DRM_INFO("radeon: dpm initialized\n");
+
        return 0;
+
+dpm_failed:
+       rdev->pm.dpm_enabled = false;
+       if ((rdev->family >= CHIP_BARTS) &&
+           (rdev->family <= CHIP_CAYMAN) &&
+           rdev->mc_fw) {
+               if (rdev->pm.default_vddc)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDC);
+               if (rdev->pm.default_vddci)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDCI);
+               if (rdev->pm.default_sclk)
+                       radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
+               if (rdev->pm.default_mclk)
+                       radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
+       }
+       DRM_ERROR("radeon: dpm initialization failed\n");
+       return ret;
 }
 
 int radeon_pm_init(struct radeon_device *rdev)
@@ -1228,11 +1235,10 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_RV670:
        case CHIP_RS780:
        case CHIP_RS880:
+       case CHIP_BARTS:
+       case CHIP_TURKS:
+       case CHIP_CAICOS:
        case CHIP_CAYMAN:
-       case CHIP_BONAIRE:
-       case CHIP_KABINI:
-       case CHIP_KAVERI:
-       case CHIP_HAWAII:
                /* DPM requires the RLC, RV770+ dGPU requires SMC */
                if (!rdev->rlc_fw)
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1257,15 +1263,16 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_PALM:
        case CHIP_SUMO:
        case CHIP_SUMO2:
-       case CHIP_BARTS:
-       case CHIP_TURKS:
-       case CHIP_CAICOS:
        case CHIP_ARUBA:
        case CHIP_TAHITI:
        case CHIP_PITCAIRN:
        case CHIP_VERDE:
        case CHIP_OLAND:
        case CHIP_HAINAN:
+       case CHIP_BONAIRE:
+       case CHIP_KABINI:
+       case CHIP_KAVERI:
+       case CHIP_HAWAII:
                /* DPM requires the RLC, RV770+ dGPU requires SMC */
                if (!rdev->rlc_fw)
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1290,6 +1297,18 @@ int radeon_pm_init(struct radeon_device *rdev)
                return radeon_pm_init_old(rdev);
 }
 
+int radeon_pm_late_init(struct radeon_device *rdev)
+{
+       int ret = 0;
+
+       if (rdev->pm.pm_method == PM_METHOD_DPM) {
+               mutex_lock(&rdev->pm.mutex);
+               ret = radeon_dpm_late_enable(rdev);
+               mutex_unlock(&rdev->pm.mutex);
+       }
+       return ret;
+}
+
 static void radeon_pm_fini_old(struct radeon_device *rdev)
 {
        if (rdev->pm.num_power_states > 1) {
@@ -1420,6 +1439,9 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
        struct drm_crtc *crtc;
        struct radeon_crtc *radeon_crtc;
 
+       if (!rdev->pm.dpm_enabled)
+               return;
+
        mutex_lock(&rdev->pm.mutex);
 
        /* update active crtc counts */
@@ -1464,7 +1486,7 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev)
         */
        for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
                if (rdev->pm.active_crtcs & (1 << crtc)) {
-                       vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos, NULL, NULL);
+                       vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, &vpos, &hpos, NULL, NULL);
                        if ((vbl_status & DRM_SCANOUTPOS_VALID) &&
                            !(vbl_status & DRM_SCANOUTPOS_INVBL))
                                in_vbl = false;
index 9214403ae173c146573cf8c4441a6a71cf052665..1b783f0e6d3ad084b0a62629a4b5d67c9e92453f 100644 (file)
@@ -332,36 +332,6 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
        }
 }
 
-u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
-                                struct radeon_ring *ring)
-{
-       u32 rptr;
-
-       if (rdev->wb.enabled)
-               rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
-       else
-               rptr = RREG32(ring->rptr_reg);
-
-       return rptr;
-}
-
-u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev,
-                                struct radeon_ring *ring)
-{
-       u32 wptr;
-
-       wptr = RREG32(ring->wptr_reg);
-
-       return wptr;
-}
-
-void radeon_ring_generic_set_wptr(struct radeon_device *rdev,
-                                 struct radeon_ring *ring)
-{
-       WREG32(ring->wptr_reg, ring->wptr);
-       (void)RREG32(ring->wptr_reg);
-}
-
 /**
  * radeon_ring_free_size - update the free size
  *
@@ -463,7 +433,7 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
        while (ring->wptr & ring->align_mask) {
                radeon_ring_write(ring, ring->nop);
        }
-       DRM_MEMORYBARRIER();
+       mb();
        radeon_ring_set_wptr(rdev, ring);
 }
 
@@ -689,22 +659,18 @@ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,
  * @ring: radeon_ring structure holding ring information
  * @ring_size: size of the ring
  * @rptr_offs: offset of the rptr writeback location in the WB buffer
- * @rptr_reg: MMIO offset of the rptr register
- * @wptr_reg: MMIO offset of the wptr register
  * @nop: nop packet for this ring
  *
  * Initialize the driver information for the selected ring (all asics).
  * Returns 0 on success, error on failure.
  */
 int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size,
-                    unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 nop)
+                    unsigned rptr_offs, u32 nop)
 {
        int r;
 
        ring->ring_size = ring_size;
        ring->rptr_offs = rptr_offs;
-       ring->rptr_reg = rptr_reg;
-       ring->wptr_reg = wptr_reg;
        ring->nop = nop;
        /* Allocate ring buffer */
        if (ring->ring_obj == NULL) {
@@ -790,34 +756,54 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
        struct radeon_device *rdev = dev->dev_private;
        int ridx = *(int*)node->info_ent->data;
        struct radeon_ring *ring = &rdev->ring[ridx];
+
+       uint32_t rptr, wptr, rptr_next;
        unsigned count, i, j;
-       u32 tmp;
 
        radeon_ring_free_size(rdev, ring);
        count = (ring->ring_size / 4) - ring->ring_free_dw;
-       tmp = radeon_ring_get_wptr(rdev, ring);
-       seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n", ring->wptr_reg, tmp, tmp);
-       tmp = radeon_ring_get_rptr(rdev, ring);
-       seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n", ring->rptr_reg, tmp, tmp);
+
+       wptr = radeon_ring_get_wptr(rdev, ring);
+       seq_printf(m, "wptr: 0x%08x [%5d]\n",
+                  wptr, wptr);
+
+       rptr = radeon_ring_get_rptr(rdev, ring);
+       seq_printf(m, "rptr: 0x%08x [%5d]\n",
+                  rptr, rptr);
+
        if (ring->rptr_save_reg) {
-               seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg,
-                          RREG32(ring->rptr_save_reg));
-       }
-       seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr);
-       seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr);
-       seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr);
-       seq_printf(m, "last semaphore wait addr   : 0x%016llx\n", ring->last_semaphore_wait_addr);
+               rptr_next = RREG32(ring->rptr_save_reg);
+               seq_printf(m, "rptr next(0x%04x): 0x%08x [%5d]\n",
+                          ring->rptr_save_reg, rptr_next, rptr_next);
+       } else
+               rptr_next = ~0;
+
+       seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n",
+                  ring->wptr, ring->wptr);
+       seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n",
+                  ring->rptr, ring->rptr);
+       seq_printf(m, "last semaphore signal addr : 0x%016llx\n",
+                  ring->last_semaphore_signal_addr);
+       seq_printf(m, "last semaphore wait addr   : 0x%016llx\n",
+                  ring->last_semaphore_wait_addr);
        seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
        seq_printf(m, "%u dwords in ring\n", count);
+
+       if (!ring->ready)
+               return 0;
+
        /* print 8 dw before current rptr as often it's the last executed
         * packet that is the root issue
         */
-       i = (ring->rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask;
-       if (ring->ready) {
-               for (j = 0; j <= (count + 32); j++) {
-                       seq_printf(m, "r[%5d]=0x%08x\n", i, ring->ring[i]);
-                       i = (i + 1) & ring->ptr_mask;
-               }
+       i = (rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask;
+       for (j = 0; j <= (count + 32); j++) {
+               seq_printf(m, "r[%5d]=0x%08x", i, ring->ring[i]);
+               if (rptr == i)
+                       seq_puts(m, " *");
+               if (rptr_next == i)
+                       seq_puts(m, " #");
+               seq_puts(m, "\n");
+               i = (i + 1) & ring->ptr_mask;
        }
        return 0;
 }
index f0bac68254b79a5dd31cfdc14ce80a98bca91065..c0625805cdd769b826d0605141f6cc80ce80ad72 100644 (file)
@@ -402,13 +402,15 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
 
        spin_lock(&sa_manager->wq.lock);
        list_for_each_entry(i, &sa_manager->olist, olist) {
+               uint64_t soffset = i->soffset + sa_manager->gpu_addr;
+               uint64_t eoffset = i->eoffset + sa_manager->gpu_addr;
                if (&i->olist == sa_manager->hole) {
                        seq_printf(m, ">");
                } else {
                        seq_printf(m, " ");
                }
-               seq_printf(m, "[0x%08x 0x%08x] size %8d",
-                          i->soffset, i->eoffset, i->eoffset - i->soffset);
+               seq_printf(m, "[0x%010llx 0x%010llx] size %8lld",
+                          soffset, eoffset, eoffset - soffset);
                if (i->fence) {
                        seq_printf(m, " protected by 0x%016llx on ring %d",
                                   i->fence->seq, i->fence->ring);
index 4d20910899d4c7ed8ad85f29788bfd35cc359fb5..956ab7f14e1650607c8dd09f1b9c96daaee3169a 100644 (file)
@@ -1810,7 +1810,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
                }
                if (!buf) {
                        DRM_DEBUG("EAGAIN\n");
-                       if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
+                       if (copy_to_user(tex->image, image, sizeof(*image)))
                                return -EFAULT;
                        return -EAGAIN;
                }
@@ -1823,7 +1823,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
 
 #define RADEON_COPY_MT(_buf, _data, _width) \
        do { \
-               if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
+               if (copy_from_user(_buf, _data, (_width))) {\
                        DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
                        return -EFAULT; \
                } \
@@ -2168,7 +2168,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *
        if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-       if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes,
+       if (copy_from_user(&depth_boxes, clear->depth_boxes,
                               sarea_priv->nbox * sizeof(depth_boxes[0])))
                return -EFAULT;
 
@@ -2436,7 +2436,7 @@ static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file
                return -EINVAL;
        }
 
-       if (DRM_COPY_FROM_USER(&image,
+       if (copy_from_user(&image,
                               (drm_radeon_tex_image_t __user *) tex->image,
                               sizeof(image)))
                return -EFAULT;
@@ -2460,7 +2460,7 @@ static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file
 
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
-       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
+       if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32)))
                return -EFAULT;
 
        RING_SPACE_TEST_WITH_RETURN(dev_priv);
@@ -2585,13 +2585,13 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
                drm_radeon_prim_t prim;
                drm_radeon_tcl_prim_t tclprim;
 
-               if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim)))
+               if (copy_from_user(&prim, &vertex->prim[i], sizeof(prim)))
                        return -EFAULT;
 
                if (prim.stateidx != laststate) {
                        drm_radeon_state_t state;
 
-                       if (DRM_COPY_FROM_USER(&state,
+                       if (copy_from_user(&state,
                                               &vertex->state[prim.stateidx],
                                               sizeof(state)))
                                return -EFAULT;
@@ -2799,7 +2799,7 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev,
 
        do {
                if (i < cmdbuf->nbox) {
-                       if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
+                       if (copy_from_user(&box, &boxes[i], sizeof(box)))
                                return -EFAULT;
                        /* FIXME The second and subsequent times round
                         * this loop, send a WAIT_UNTIL_3D_IDLE before
@@ -3116,7 +3116,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
                return -EINVAL;
        }
 
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+       if (copy_to_user(param->value, &value, sizeof(int))) {
                DRM_ERROR("copy_to_user\n");
                return -EFAULT;
        }
index 71245d6f34a20c0f64a6eff3057eb6d7ae37f388..77f5b0c3edb8d8b1f4835620d626c3981171c7a6 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/swiotlb.h>
+#include <linux/debugfs.h>
 #include "radeon_reg.h"
 #include "radeon.h"
 
 #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
 
 static int radeon_ttm_debugfs_init(struct radeon_device *rdev);
+static void radeon_ttm_debugfs_fini(struct radeon_device *rdev);
 
 static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev)
 {
@@ -142,7 +144,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
                man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
 #if __OS_HAS_AGP
                if (rdev->flags & RADEON_IS_AGP) {
-                       if (!(drm_core_has_AGP(rdev->ddev) && rdev->ddev->agp)) {
+                       if (!rdev->ddev->agp) {
                                DRM_ERROR("AGP is not enabled for memory type %u\n",
                                          (unsigned)type);
                                return -EINVAL;
@@ -753,6 +755,7 @@ void radeon_ttm_fini(struct radeon_device *rdev)
 
        if (!rdev->mman.initialized)
                return;
+       radeon_ttm_debugfs_fini(rdev);
        if (rdev->stollen_vga_memory) {
                r = radeon_bo_reserve(rdev->stollen_vga_memory, false);
                if (r == 0) {
@@ -832,16 +835,15 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
        return 0;
 }
 
-
-#define RADEON_DEBUGFS_MEM_TYPES 2
-
 #if defined(CONFIG_DEBUG_FS)
+
 static int radeon_mm_dump_table(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = (struct drm_info_node *)m->private;
-       struct drm_mm *mm = (struct drm_mm *)node->info_ent->data;
+       unsigned ttm_pl = *(int *)node->info_ent->data;
        struct drm_device *dev = node->minor->dev;
        struct radeon_device *rdev = dev->dev_private;
+       struct drm_mm *mm = (struct drm_mm *)rdev->mman.bdev.man[ttm_pl].priv;
        int ret;
        struct ttm_bo_global *glob = rdev->mman.bdev.glob;
 
@@ -850,46 +852,169 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data)
        spin_unlock(&glob->lru_lock);
        return ret;
 }
+
+static int ttm_pl_vram = TTM_PL_VRAM;
+static int ttm_pl_tt = TTM_PL_TT;
+
+static struct drm_info_list radeon_ttm_debugfs_list[] = {
+       {"radeon_vram_mm", radeon_mm_dump_table, 0, &ttm_pl_vram},
+       {"radeon_gtt_mm", radeon_mm_dump_table, 0, &ttm_pl_tt},
+       {"ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL},
+#ifdef CONFIG_SWIOTLB
+       {"ttm_dma_page_pool", ttm_dma_page_alloc_debugfs, 0, NULL}
 #endif
+};
 
-static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+static int radeon_ttm_vram_open(struct inode *inode, struct file *filep)
 {
-#if defined(CONFIG_DEBUG_FS)
-       static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+2];
-       static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES+2][32];
-       unsigned i;
+       struct radeon_device *rdev = inode->i_private;
+       i_size_write(inode, rdev->mc.mc_vram_size);
+       filep->private_data = inode->i_private;
+       return 0;
+}
 
-       for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) {
-               if (i == 0)
-                       sprintf(radeon_mem_types_names[i], "radeon_vram_mm");
-               else
-                       sprintf(radeon_mem_types_names[i], "radeon_gtt_mm");
-               radeon_mem_types_list[i].name = radeon_mem_types_names[i];
-               radeon_mem_types_list[i].show = &radeon_mm_dump_table;
-               radeon_mem_types_list[i].driver_features = 0;
-               if (i == 0)
-                       radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_VRAM].priv;
-               else
-                       radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_TT].priv;
+static ssize_t radeon_ttm_vram_read(struct file *f, char __user *buf,
+                                   size_t size, loff_t *pos)
+{
+       struct radeon_device *rdev = f->private_data;
+       ssize_t result = 0;
+       int r;
 
+       if (size & 0x3 || *pos & 0x3)
+               return -EINVAL;
+
+       while (size) {
+               unsigned long flags;
+               uint32_t value;
+
+               if (*pos >= rdev->mc.mc_vram_size)
+                       return result;
+
+               spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
+               WREG32(RADEON_MM_INDEX, ((uint32_t)*pos) | 0x80000000);
+               if (rdev->family >= CHIP_CEDAR)
+                       WREG32(EVERGREEN_MM_INDEX_HI, *pos >> 31);
+               value = RREG32(RADEON_MM_DATA);
+               spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+
+               r = put_user(value, (uint32_t *)buf);
+               if (r)
+                       return r;
+
+               result += 4;
+               buf += 4;
+               *pos += 4;
+               size -= 4;
        }
-       /* Add ttm page pool to debugfs */
-       sprintf(radeon_mem_types_names[i], "ttm_page_pool");
-       radeon_mem_types_list[i].name = radeon_mem_types_names[i];
-       radeon_mem_types_list[i].show = &ttm_page_alloc_debugfs;
-       radeon_mem_types_list[i].driver_features = 0;
-       radeon_mem_types_list[i++].data = NULL;
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb_nr_tbl()) {
-               sprintf(radeon_mem_types_names[i], "ttm_dma_page_pool");
-               radeon_mem_types_list[i].name = radeon_mem_types_names[i];
-               radeon_mem_types_list[i].show = &ttm_dma_page_alloc_debugfs;
-               radeon_mem_types_list[i].driver_features = 0;
-               radeon_mem_types_list[i++].data = NULL;
+
+       return result;
+}
+
+static const struct file_operations radeon_ttm_vram_fops = {
+       .owner = THIS_MODULE,
+       .open = radeon_ttm_vram_open,
+       .read = radeon_ttm_vram_read,
+       .llseek = default_llseek
+};
+
+static int radeon_ttm_gtt_open(struct inode *inode, struct file *filep)
+{
+       struct radeon_device *rdev = inode->i_private;
+       i_size_write(inode, rdev->mc.gtt_size);
+       filep->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t radeon_ttm_gtt_read(struct file *f, char __user *buf,
+                                  size_t size, loff_t *pos)
+{
+       struct radeon_device *rdev = f->private_data;
+       ssize_t result = 0;
+       int r;
+
+       while (size) {
+               loff_t p = *pos / PAGE_SIZE;
+               unsigned off = *pos & ~PAGE_MASK;
+               ssize_t cur_size = min(size, PAGE_SIZE - off);
+               struct page *page;
+               void *ptr;
+
+               if (p >= rdev->gart.num_cpu_pages)
+                       return result;
+
+               page = rdev->gart.pages[p];
+               if (page) {
+                       ptr = kmap(page);
+                       ptr += off;
+
+                       r = copy_to_user(buf, ptr, cur_size);
+                       kunmap(rdev->gart.pages[p]);
+               } else
+                       r = clear_user(buf, cur_size);
+
+               if (r)
+                       return -EFAULT;
+
+               result += cur_size;
+               buf += cur_size;
+               *pos += cur_size;
+               size -= cur_size;
        }
+
+       return result;
+}
+
+static const struct file_operations radeon_ttm_gtt_fops = {
+       .owner = THIS_MODULE,
+       .open = radeon_ttm_gtt_open,
+       .read = radeon_ttm_gtt_read,
+       .llseek = default_llseek
+};
+
 #endif
-       return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i);
 
+static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+       unsigned count;
+
+       struct drm_minor *minor = rdev->ddev->primary;
+       struct dentry *ent, *root = minor->debugfs_root;
+
+       ent = debugfs_create_file("radeon_vram", S_IFREG | S_IRUGO, root,
+                                 rdev, &radeon_ttm_vram_fops);
+       if (IS_ERR(ent))
+               return PTR_ERR(ent);
+       rdev->mman.vram = ent;
+
+       ent = debugfs_create_file("radeon_gtt", S_IFREG | S_IRUGO, root,
+                                 rdev, &radeon_ttm_gtt_fops);
+       if (IS_ERR(ent))
+               return PTR_ERR(ent);
+       rdev->mman.gtt = ent;
+
+       count = ARRAY_SIZE(radeon_ttm_debugfs_list);
+
+#ifdef CONFIG_SWIOTLB
+       if (!swiotlb_nr_tbl())
+               --count;
 #endif
+
+       return radeon_debugfs_add_files(rdev, radeon_ttm_debugfs_list, count);
+#else
+
        return 0;
+#endif
+}
+
+static void radeon_ttm_debugfs_fini(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+
+       debugfs_remove(rdev->mman.vram);
+       rdev->mman.vram = NULL;
+
+       debugfs_remove(rdev->mman.gtt);
+       rdev->mman.gtt = NULL;
+#endif
 }
index 373d088bac66db910291045424e075921d39d202..6781fee1eaadc21a68e50de696dd353be0a3e9e5 100644 (file)
@@ -91,6 +91,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
        case CHIP_VERDE:
        case CHIP_PITCAIRN:
        case CHIP_ARUBA:
+       case CHIP_OLAND:
                fw_name = FIRMWARE_TAHITI;
                break;
 
@@ -473,7 +474,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
                return -EINVAL;
        }
 
-       if ((start >> 28) != (end >> 28)) {
+       if ((start >> 28) != ((end - 1) >> 28)) {
                DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
                          start, end);
                return -EINVAL;
@@ -778,6 +779,8 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work)
 
        if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) {
                if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+                       radeon_uvd_count_handles(rdev, &rdev->pm.dpm.sd,
+                                                &rdev->pm.dpm.hd);
                        radeon_dpm_enable_uvd(rdev, false);
                } else {
                        radeon_set_uvd_clocks(rdev, 0, 0);
index 9566b5940a5ae723f90dfa11427e3f09bac233b3..b5c2369cda2fe28ca043fe91f4fcfe12fc227fc6 100644 (file)
@@ -474,6 +474,8 @@ int rs400_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = rs400_startup(rdev);
        if (r) {
@@ -484,6 +486,7 @@ int rs400_resume(struct radeon_device *rdev)
 
 int rs400_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
        r100_irq_disable(rdev);
@@ -493,6 +496,7 @@ int rs400_suspend(struct radeon_device *rdev)
 
 void rs400_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -560,6 +564,9 @@ int rs400_init(struct radeon_device *rdev)
                return r;
        r300_set_reg_safe(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = rs400_startup(rdev);
        if (r) {
index 76cc8d3aafec461d0b41668f25500f2a4753dbc3..fdcde7693032c28cc30008b494fd573fd82e58f3 100644 (file)
@@ -1048,6 +1048,8 @@ int rs600_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = rs600_startup(rdev);
        if (r) {
@@ -1058,6 +1060,7 @@ int rs600_resume(struct radeon_device *rdev)
 
 int rs600_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
@@ -1068,6 +1071,7 @@ int rs600_suspend(struct radeon_device *rdev)
 
 void rs600_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
@@ -1136,6 +1140,9 @@ int rs600_init(struct radeon_device *rdev)
                return r;
        rs600_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = rs600_startup(rdev);
        if (r) {
index 1c560629575a8906fb74e006285096f07eac7f19..35950738bd5e449465e0e5062d096e3e8ae9ff0e 100644 (file)
@@ -162,6 +162,16 @@ static void rs690_mc_init(struct radeon_device *rdev)
        base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
        base = G_000100_MC_FB_START(base) << 16;
        rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+       /* Some boards seem to be configured for 128MB of sideport memory,
+        * but really only have 64MB.  Just skip the sideport and use
+        * UMA memory.
+        */
+       if (rdev->mc.igp_sideport_enabled &&
+           (rdev->mc.real_vram_size == (384 * 1024 * 1024))) {
+               base += 128 * 1024 * 1024;
+               rdev->mc.real_vram_size -= 128 * 1024 * 1024;
+               rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+       }
 
        /* Use K8 direct mapping for fast fb access. */ 
        rdev->fastfb_working = false;
@@ -746,6 +756,8 @@ int rs690_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = rs690_startup(rdev);
        if (r) {
@@ -756,6 +768,7 @@ int rs690_resume(struct radeon_device *rdev)
 
 int rs690_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
@@ -766,6 +779,7 @@ int rs690_suspend(struct radeon_device *rdev)
 
 void rs690_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r600_audio_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
@@ -835,6 +849,9 @@ int rs690_init(struct radeon_device *rdev)
                return r;
        rs600_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = rs690_startup(rdev);
        if (r) {
index 6af8505cf4d2db624ee64811ba4575158d90e974..8512085b0aefe0139c6ffabdc69114510ae3e2f3 100644 (file)
@@ -623,14 +623,6 @@ int rs780_dpm_enable(struct radeon_device *rdev)
        if (pi->gfx_clock_gating)
                r600_gfx_clockgating_enable(rdev, true);
 
-       if (rdev->irq.installed && (rdev->pm.int_thermal_type == THERMAL_TYPE_RV6XX)) {
-               ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-       }
-
        return 0;
 }
 
index 5d1c316115efa31ab7b029de44db66e399322e71..98e8138ff77945ecdba447bdcb94310c30dcb1c7 100644 (file)
@@ -586,6 +586,8 @@ int rv515_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r =  rv515_startup(rdev);
        if (r) {
@@ -596,6 +598,7 @@ int rv515_resume(struct radeon_device *rdev)
 
 int rv515_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r100_cp_disable(rdev);
        radeon_wb_disable(rdev);
        rs600_irq_disable(rdev);
@@ -612,6 +615,7 @@ void rv515_set_safe_registers(struct radeon_device *rdev)
 
 void rv515_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r100_cp_fini(rdev);
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
@@ -685,6 +689,9 @@ int rv515_init(struct radeon_device *rdev)
                return r;
        rv515_set_safe_registers(rdev);
 
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->accel_working = true;
        r = rv515_startup(rdev);
        if (r) {
index 26633a0252522051bc5a504357d93bd9b6257c67..bebf31c4d841ccaa07b86d9bae96c7abb5c223be 100644 (file)
@@ -1546,7 +1546,6 @@ int rv6xx_dpm_enable(struct radeon_device *rdev)
 {
        struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
-       int ret;
 
        if (r600_dynamicpm_enabled(rdev))
                return -EINVAL;
@@ -1594,15 +1593,6 @@ int rv6xx_dpm_enable(struct radeon_device *rdev)
        r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, true);
        r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, true);
 
-       if (rdev->irq.installed &&
-           r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
-               ret = r600_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
-               if (ret)
-                       return ret;
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
-       }
-
        rv6xx_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
 
        r600_start_dpm(rdev);
index 9f5846743c9e0a26dbcf76662250bfb957f6ced1..18e02889ec7d748791d06ab18e521bfa55cd33ee 100644 (file)
@@ -1123,6 +1123,35 @@ void r700_cp_fini(struct radeon_device *rdev)
        radeon_scratch_free(rdev, ring->rptr_save_reg);
 }
 
+void rv770_set_clk_bypass_mode(struct radeon_device *rdev)
+{
+       u32 tmp, i;
+
+       if (rdev->flags & RADEON_IS_IGP)
+               return;
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
+       tmp &= SCLK_MUX_SEL_MASK;
+       tmp |= SCLK_MUX_SEL(1) | SCLK_MUX_UPDATE;
+       WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
+
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CG_SPLL_STATUS) & SPLL_CHG_STATUS)
+                       break;
+               udelay(1);
+       }
+
+       tmp &= ~SCLK_MUX_UPDATE;
+       WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
+
+       tmp = RREG32(MPLL_CNTL_MODE);
+       if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
+               tmp &= ~RV730_MPLL_MCLK_SEL;
+       else
+               tmp &= ~MPLL_MCLK_SEL;
+       WREG32(MPLL_CNTL_MODE, tmp);
+}
+
 /*
  * Core functions
  */
@@ -1665,14 +1694,6 @@ static int rv770_startup(struct radeon_device *rdev)
 
        rv770_mc_program(rdev);
 
-       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
-               r = r600_init_microcode(rdev);
-               if (r) {
-                       DRM_ERROR("Failed to load firmware!\n");
-                       return r;
-               }
-       }
-
        if (rdev->flags & RADEON_IS_AGP) {
                rv770_agp_enable(rdev);
        } else {
@@ -1728,14 +1749,12 @@ static int rv770_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            R600_CP_RB_RPTR, R600_CP_RB_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR, DMA_RB_WPTR,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
        if (r)
                return r;
@@ -1754,7 +1773,6 @@ static int rv770_startup(struct radeon_device *rdev)
        ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
        if (ring->ring_size) {
                r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                    UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                     RADEON_CP_PACKET2);
                if (!r)
                        r = uvd_v1_0_init(rdev);
@@ -1792,6 +1810,8 @@ int rv770_resume(struct radeon_device *rdev)
        /* init golden registers */
        rv770_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = rv770_startup(rdev);
        if (r) {
@@ -1806,6 +1826,7 @@ int rv770_resume(struct radeon_device *rdev)
 
 int rv770_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        r600_audio_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_suspend(rdev);
@@ -1876,6 +1897,17 @@ int rv770_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+               r = r600_init_microcode(rdev);
+               if (r) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       return r;
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
        r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
@@ -1915,6 +1947,7 @@ int rv770_init(struct radeon_device *rdev)
 
 void rv770_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        r700_cp_fini(rdev);
        r600_dma_fini(rdev);
        r600_irq_fini(rdev);
index 913b025ae9b399695bed47af97cccf08fe68caf7..80c595aba359b53c4f748feae3aeab9d207f5db8 100644 (file)
@@ -1863,8 +1863,8 @@ void rv770_enable_auto_throttle_source(struct radeon_device *rdev,
        }
 }
 
-int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
-                                       int min_temp, int max_temp)
+static int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
+                                              int min_temp, int max_temp)
 {
        int low_temp = 0 * 1000;
        int high_temp = 255 * 1000;
@@ -1966,6 +1966,15 @@ int rv770_dpm_enable(struct radeon_device *rdev)
        if (pi->mg_clock_gating)
                rv770_mg_clock_gating_enable(rdev, true);
 
+       rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
+
+       return 0;
+}
+
+int rv770_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                PPSMC_Result result;
@@ -1981,8 +1990,6 @@ int rv770_dpm_enable(struct radeon_device *rdev)
                        DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
        }
 
-       rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
-
        return 0;
 }
 
@@ -2244,14 +2251,12 @@ static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev,
                pl->vddci = vddci;
        }
 
-       if (rdev->family >= CHIP_BARTS) {
-               if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
-                   ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
-                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
-                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
-                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
-                       rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
-               }
+       if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
+           ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
+               rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
+               rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
+               rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
+               rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
        }
 }
 
@@ -2328,6 +2333,12 @@ void rv770_get_engine_memory_ss(struct radeon_device *rdev)
        pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
                                                       ASIC_INTERNAL_MEMORY_SS, 0);
 
+       /* disable ss, causes hangs on some cayman boards */
+       if (rdev->family == CHIP_CAYMAN) {
+               pi->sclk_ss = false;
+               pi->mclk_ss = false;
+       }
+
        if (pi->sclk_ss || pi->mclk_ss)
                pi->dynamic_ss = true;
        else
@@ -2525,6 +2536,12 @@ bool rv770_dpm_vblank_too_short(struct radeon_device *rdev)
            (rdev->pdev->subsystem_device == 0x1c42))
                switch_limit = 200;
 
+       /* RV770 */
+       /* mclk switching doesn't seem to work reliably on desktop RV770s */
+       if ((rdev->family == CHIP_RV770) &&
+           !(rdev->flags & RADEON_IS_MOBILITY))
+               switch_limit = 0xffffffff; /* disable mclk switching */
+
        if (vblank_time < switch_limit)
                return true;
        else
index 9244effc6b59e2e69c6882b0d4dc35dd2517379c..f776634840c9782bde2e9228007720448aa469d1 100644 (file)
@@ -283,8 +283,4 @@ int rv770_read_smc_soft_register(struct radeon_device *rdev,
 int rv770_write_smc_soft_register(struct radeon_device *rdev,
                                  u16 reg_offset, u32 value);
 
-/* thermal */
-int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
-                                       int min_temp, int max_temp);
-
 #endif
index 1ae277152cc7f0c66f7babbcb0cdfcec5ab04f71..3cf1e2921545f9a980569925088d720e347505d1 100644 (file)
 #define        CG_SPLL_FUNC_CNTL_2                             0x604
 #define                SCLK_MUX_SEL(x)                         ((x) << 0)
 #define                SCLK_MUX_SEL_MASK                       (0x1ff << 0)
+#define                SCLK_MUX_UPDATE                         (1 << 26)
 #define        CG_SPLL_FUNC_CNTL_3                             0x608
 #define                SPLL_FB_DIV(x)                          ((x) << 0)
 #define                SPLL_FB_DIV_MASK                        (0x3ffffff << 0)
 #define                SPLL_DITHEN                             (1 << 28)
+#define        CG_SPLL_STATUS                                  0x60c
+#define                SPLL_CHG_STATUS                         (1 << 1)
 
 #define        SPLL_CNTL_MODE                                  0x610
 #define                SPLL_DIV_SYNC                           (1 << 5)
 
+#define MPLL_CNTL_MODE                                  0x61c
+#       define MPLL_MCLK_SEL                            (1 << 11)
+#       define RV730_MPLL_MCLK_SEL                      (1 << 25)
+
 #define        MPLL_AD_FUNC_CNTL                               0x624
 #define                CLKF(x)                                 ((x) << 0)
 #define                CLKF_MASK                               (0x7f << 0)
index a36736dab5e0694cd5a7b78d6dbb013b484cb8f6..07ce58716e44c4b507358ee54009063c4474a32f 100644 (file)
@@ -80,6 +80,8 @@ extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
 extern bool evergreen_is_display_hung(struct radeon_device *rdev);
 static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
                                         bool enable);
+static void si_init_pg(struct radeon_device *rdev);
+static void si_init_cg(struct radeon_device *rdev);
 static void si_fini_pg(struct radeon_device *rdev);
 static void si_fini_cg(struct radeon_device *rdev);
 static void si_rlc_stop(struct radeon_device *rdev);
@@ -1460,7 +1462,7 @@ static const u32 hainan_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
 };
 
 /* ucode loading */
-static int si_mc_load_microcode(struct radeon_device *rdev)
+int si_mc_load_microcode(struct radeon_device *rdev)
 {
        const __be32 *fw_data;
        u32 running, blackout = 0;
@@ -2811,7 +2813,7 @@ static void si_setup_spi(struct radeon_device *rdev,
 }
 
 static u32 si_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -2825,14 +2827,14 @@ static u32 si_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = si_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = si_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
 
 static void si_setup_rb(struct radeon_device *rdev,
                        u32 se_num, u32 sh_per_se,
-                       u32 max_rb_num)
+                       u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -2842,19 +2844,21 @@ static void si_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        si_select_se_sh(rdev, i, j);
-                       data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+                       data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
                        disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
                }
        }
        si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.si.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                si_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
@@ -3722,6 +3726,106 @@ static void si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        evergreen_print_gpu_status_regs(rdev);
 }
 
+static void si_set_clk_bypass_mode(struct radeon_device *rdev)
+{
+       u32 tmp, i;
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL);
+       tmp |= SPLL_BYPASS_EN;
+       WREG32(CG_SPLL_FUNC_CNTL, tmp);
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
+       tmp |= SPLL_CTLREQ_CHG;
+       WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
+
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(SPLL_STATUS) & SPLL_CHG_STATUS)
+                       break;
+               udelay(1);
+       }
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
+       tmp &= ~(SPLL_CTLREQ_CHG | SCLK_MUX_UPDATE);
+       WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
+
+       tmp = RREG32(MPLL_CNTL_MODE);
+       tmp &= ~MPLL_MCLK_SEL;
+       WREG32(MPLL_CNTL_MODE, tmp);
+}
+
+static void si_spll_powerdown(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       tmp = RREG32(SPLL_CNTL_MODE);
+       tmp |= SPLL_SW_DIR_CONTROL;
+       WREG32(SPLL_CNTL_MODE, tmp);
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL);
+       tmp |= SPLL_RESET;
+       WREG32(CG_SPLL_FUNC_CNTL, tmp);
+
+       tmp = RREG32(CG_SPLL_FUNC_CNTL);
+       tmp |= SPLL_SLEEP;
+       WREG32(CG_SPLL_FUNC_CNTL, tmp);
+
+       tmp = RREG32(SPLL_CNTL_MODE);
+       tmp &= ~SPLL_SW_DIR_CONTROL;
+       WREG32(SPLL_CNTL_MODE, tmp);
+}
+
+static void si_gpu_pci_config_reset(struct radeon_device *rdev)
+{
+       struct evergreen_mc_save save;
+       u32 tmp, i;
+
+       dev_info(rdev->dev, "GPU pci config reset\n");
+
+       /* disable dpm? */
+
+       /* disable cg/pg */
+       si_fini_pg(rdev);
+       si_fini_cg(rdev);
+
+       /* Disable CP parsing/prefetching */
+       WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
+       /* dma0 */
+       tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
+       /* dma1 */
+       tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
+       tmp &= ~DMA_RB_ENABLE;
+       WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
+       /* XXX other engines? */
+
+       /* halt the rlc, disable cp internal ints */
+       si_rlc_stop(rdev);
+
+       udelay(50);
+
+       /* disable mem access */
+       evergreen_mc_stop(rdev, &save);
+       if (evergreen_mc_wait_for_idle(rdev)) {
+               dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
+       }
+
+       /* set mclk/sclk to bypass */
+       si_set_clk_bypass_mode(rdev);
+       /* powerdown spll */
+       si_spll_powerdown(rdev);
+       /* disable BM */
+       pci_clear_master(rdev->pdev);
+       /* reset */
+       radeon_pci_config_reset(rdev);
+       /* wait for asic to come out of reset */
+       for (i = 0; i < rdev->usec_timeout; i++) {
+               if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+}
+
 int si_asic_reset(struct radeon_device *rdev)
 {
        u32 reset_mask;
@@ -3731,10 +3835,17 @@ int si_asic_reset(struct radeon_device *rdev)
        if (reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, true);
 
+       /* try soft reset */
        si_gpu_soft_reset(rdev, reset_mask);
 
        reset_mask = si_gpu_check_soft_reset(rdev);
 
+       /* try pci config reset */
+       if (reset_mask && radeon_hard_reset)
+               si_gpu_pci_config_reset(rdev);
+
+       reset_mask = si_gpu_check_soft_reset(rdev);
+
        if (!reset_mask)
                r600_set_bios_scratch_engine_hung(rdev, false);
 
@@ -5210,8 +5321,8 @@ static void si_enable_hdp_ls(struct radeon_device *rdev,
                WREG32(HDP_MEM_POWER_LS, data);
 }
 
-void si_update_cg(struct radeon_device *rdev,
-                 u32 block, bool enable)
+static void si_update_cg(struct radeon_device *rdev,
+                        u32 block, bool enable)
 {
        if (block & RADEON_CG_BLOCK_GFX) {
                si_enable_gui_idle_interrupt(rdev, false);
@@ -5377,6 +5488,9 @@ static void si_init_pg(struct radeon_device *rdev)
                si_init_ao_cu_mask(rdev);
                if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) {
                        si_init_gfx_cgpg(rdev);
+               } else {
+                       WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
+                       WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
                }
                si_enable_dma_pg(rdev, true);
                si_enable_gfx_cgpg(rdev, true);
@@ -6322,21 +6436,14 @@ static int si_startup(struct radeon_device *rdev)
 
        si_mc_program(rdev);
 
-       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
-           !rdev->rlc_fw || !rdev->mc_fw) {
-               r = si_init_microcode(rdev);
+       if (!rdev->pm.dpm_enabled) {
+               r = si_mc_load_microcode(rdev);
                if (r) {
-                       DRM_ERROR("Failed to load firmware!\n");
+                       DRM_ERROR("Failed to load MC firmware!\n");
                        return r;
                }
        }
 
-       r = si_mc_load_microcode(rdev);
-       if (r) {
-               DRM_ERROR("Failed to load MC firmware!\n");
-               return r;
-       }
-
        r = si_pcie_gart_enable(rdev);
        if (r)
                return r;
@@ -6419,37 +6526,30 @@ static int si_startup(struct radeon_device *rdev)
 
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
-                            CP_RB0_RPTR, CP_RB0_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
-                            CP_RB1_RPTR, CP_RB1_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
-                            CP_RB2_RPTR, CP_RB2_WPTR,
                             RADEON_CP_PACKET2);
        if (r)
                return r;
 
        ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
-                            DMA_RB_RPTR + DMA0_REGISTER_OFFSET,
-                            DMA_RB_WPTR + DMA0_REGISTER_OFFSET,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0));
        if (r)
                return r;
 
        ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
        r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
-                            DMA_RB_RPTR + DMA1_REGISTER_OFFSET,
-                            DMA_RB_WPTR + DMA1_REGISTER_OFFSET,
                             DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0));
        if (r)
                return r;
@@ -6469,7 +6569,6 @@ static int si_startup(struct radeon_device *rdev)
                ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
                if (ring->ring_size) {
                        r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-                                            UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
                                             RADEON_CP_PACKET2);
                        if (!r)
                                r = uvd_v1_0_init(rdev);
@@ -6511,6 +6610,8 @@ int si_resume(struct radeon_device *rdev)
        /* init golden registers */
        si_init_golden_registers(rdev);
 
+       radeon_pm_resume(rdev);
+
        rdev->accel_working = true;
        r = si_startup(rdev);
        if (r) {
@@ -6525,6 +6626,7 @@ int si_resume(struct radeon_device *rdev)
 
 int si_suspend(struct radeon_device *rdev)
 {
+       radeon_pm_suspend(rdev);
        dce6_audio_fini(rdev);
        radeon_vm_manager_fini(rdev);
        si_cp_enable(rdev, false);
@@ -6598,6 +6700,18 @@ int si_init(struct radeon_device *rdev)
        if (r)
                return r;
 
+       if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+           !rdev->rlc_fw || !rdev->mc_fw) {
+               r = si_init_microcode(rdev);
+               if (r) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       return r;
+               }
+       }
+
+       /* Initialize power management */
+       radeon_pm_init(rdev);
+
        ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        ring->ring_obj = NULL;
        r600_ring_init(rdev, ring, 1024 * 1024);
@@ -6664,6 +6778,7 @@ int si_init(struct radeon_device *rdev)
 
 void si_fini(struct radeon_device *rdev)
 {
+       radeon_pm_fini(rdev);
        si_cp_fini(rdev);
        cayman_dma_fini(rdev);
        si_fini_pg(rdev);
index 0b00c790fb7713d8b4cbddb91c9b319ecc41c3b9..36a5da4791ce7354aec03a33e670f8bfc8f4484f 100644 (file)
@@ -1738,6 +1738,8 @@ struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
 struct ni_power_info *ni_get_pi(struct radeon_device *rdev);
 struct ni_ps *ni_get_ps(struct radeon_ps *rps);
 
+extern int si_mc_load_microcode(struct radeon_device *rdev);
+
 static int si_populate_voltage_value(struct radeon_device *rdev,
                                     const struct atom_voltage_table *table,
                                     u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage);
@@ -1753,9 +1755,6 @@ static int si_calculate_sclk_params(struct radeon_device *rdev,
                                    u32 engine_clock,
                                    SISLANDS_SMC_SCLK_VALUE *sclk);
 
-extern void si_update_cg(struct radeon_device *rdev,
-                        u32 block, bool enable);
-
 static struct si_power_info *si_get_pi(struct radeon_device *rdev)
 {
         struct si_power_info *pi = rdev->pm.dpm.priv;
@@ -2396,7 +2395,7 @@ static int si_populate_sq_ramping_values(struct radeon_device *rdev,
        if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
                enable_sq_ramping = false;
 
-       if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+       if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
                enable_sq_ramping = false;
 
        for (i = 0; i < state->performance_level_count; i++) {
@@ -5414,7 +5413,7 @@ static void si_populate_mc_reg_addresses(struct radeon_device *rdev,
 
        for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) {
                if (si_pi->mc_reg_table.valid_flag & (1 << j)) {
-                       if (i >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
+                       if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
                                break;
                        mc_reg_table->address[i].s0 =
                                cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0);
@@ -5754,6 +5753,11 @@ static void si_set_pcie_lane_width_in_smc(struct radeon_device *rdev,
 
 void si_dpm_setup_asic(struct radeon_device *rdev)
 {
+       int r;
+
+       r = si_mc_load_microcode(rdev);
+       if (r)
+               DRM_ERROR("Failed to load MC firmware!\n");
        rv770_get_memory_type(rdev);
        si_read_clock_registers(rdev);
        si_enable_acpi_power_management(rdev);
@@ -5791,13 +5795,6 @@ int si_dpm_enable(struct radeon_device *rdev)
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
        int ret;
 
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), false);
-
        if (si_is_smc_running(rdev))
                return -EINVAL;
        if (pi->voltage_control)
@@ -5900,6 +5897,17 @@ int si_dpm_enable(struct radeon_device *rdev)
        si_enable_sclk_control(rdev, true);
        si_start_dpm(rdev);
 
+       si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
+
+       ni_update_current_ps(rdev, boot_ps);
+
+       return 0;
+}
+
+int si_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                PPSMC_Result result;
@@ -5915,17 +5923,6 @@ int si_dpm_enable(struct radeon_device *rdev)
                        DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
        }
 
-       si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
-
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), true);
-
-       ni_update_current_ps(rdev, boot_ps);
-
        return 0;
 }
 
@@ -5934,13 +5931,6 @@ void si_dpm_disable(struct radeon_device *rdev)
        struct rv7xx_power_info *pi = rv770_get_pi(rdev);
        struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
 
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), false);
-
        if (!si_is_smc_running(rdev))
                return;
        si_disable_ulv(rdev);
@@ -6005,13 +5995,6 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
        struct radeon_ps *old_ps = &eg_pi->current_rps;
        int ret;
 
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), false);
-
        ret = si_disable_ulv(rdev);
        if (ret) {
                DRM_ERROR("si_disable_ulv failed\n");
@@ -6104,13 +6087,6 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
                return ret;
        }
 
-       si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
-                           RADEON_CG_BLOCK_MC |
-                           RADEON_CG_BLOCK_SDMA |
-                           RADEON_CG_BLOCK_BIF |
-                           RADEON_CG_BLOCK_UVD |
-                           RADEON_CG_BLOCK_HDP), true);
-
        return 0;
 }
 
index d422a1cbf727b375c467bcf78dc417431c7db2fd..e80efcf0c2306e812b4462ab930464bc03c8c5b5 100644 (file)
@@ -28,6 +28,7 @@
 #include "sid.h"
 #include "ppsmc.h"
 #include "radeon_ucode.h"
+#include "sislands_smc.h"
 
 static int si_set_smc_sram_address(struct radeon_device *rdev,
                                   u32 smc_address, u32 limit)
index b322acc48097f632a0fa1ac3204facc3287912f5..caa3e61a38c25b587537933850317ac5d89e10bf 100644 (file)
@@ -94,6 +94,8 @@
 #define        CG_SPLL_FUNC_CNTL_2                             0x604
 #define                SCLK_MUX_SEL(x)                         ((x) << 0)
 #define                SCLK_MUX_SEL_MASK                       (0x1ff << 0)
+#define                SPLL_CTLREQ_CHG                         (1 << 23)
+#define                SCLK_MUX_UPDATE                         (1 << 26)
 #define        CG_SPLL_FUNC_CNTL_3                             0x608
 #define                SPLL_FB_DIV(x)                          ((x) << 0)
 #define                SPLL_FB_DIV_MASK                        (0x3ffffff << 0)
 #define                SPLL_DITHEN                             (1 << 28)
 #define        CG_SPLL_FUNC_CNTL_4                             0x60c
 
+#define        SPLL_STATUS                                     0x614
+#define                SPLL_CHG_STATUS                         (1 << 1)
 #define        SPLL_CNTL_MODE                                  0x618
+#define                SPLL_SW_DIR_CONTROL                     (1 << 0)
 #      define SPLL_REFCLK_SEL(x)                       ((x) << 8)
 #      define SPLL_REFCLK_SEL_MASK                     0xFF00
 
 #       define MRDCK0_BYPASS                            (1 << 24)
 #       define MRDCK1_BYPASS                            (1 << 25)
 
+#define        MPLL_CNTL_MODE                                  0x2bb0
+#       define MPLL_MCLK_SEL                            (1 << 11)
 #define        MPLL_FUNC_CNTL                                  0x2bb4
 #define                BWCTRL(x)                               ((x) << 20)
 #define                BWCTRL_MASK                             (0xff << 20)
index 5578e9837026fec65ac023a71c5ed3400d8d0734..10e945a49479e3e9bb611ec98cb62b409046acf6 100644 (file)
@@ -374,8 +374,6 @@ typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration;
 
 #pragma pack(pop)
 
-int si_set_smc_sram_address(struct radeon_device *rdev,
-                           u32 smc_address, u32 limit);
 int si_copy_bytes_to_smc(struct radeon_device *rdev,
                         u32 smc_start_address,
                         const u8 *src, u32 byte_count, u32 limit);
index 96ea6db8bf575e7a45f6af501e26120f7e996a9a..f121efe12dc5c10a4fd6f1c5283ee7f87e8b0797 100644 (file)
@@ -71,7 +71,7 @@ static const u32 sumo_dtc[SUMO_PM_NUMBER_OF_TC] =
        SUMO_DTC_DFLT_14,
 };
 
-struct sumo_ps *sumo_get_ps(struct radeon_ps *rps)
+static struct sumo_ps *sumo_get_ps(struct radeon_ps *rps)
 {
        struct sumo_ps *ps = rps->ps_priv;
 
@@ -1202,14 +1202,10 @@ static void sumo_update_requested_ps(struct radeon_device *rdev,
 int sumo_dpm_enable(struct radeon_device *rdev)
 {
        struct sumo_power_info *pi = sumo_get_pi(rdev);
-       int ret;
 
        if (sumo_dpm_enabled(rdev))
                return -EINVAL;
 
-       ret = sumo_enable_clock_power_gating(rdev);
-       if (ret)
-               return ret;
        sumo_program_bootup_state(rdev);
        sumo_init_bsp(rdev);
        sumo_reset_am(rdev);
@@ -1233,6 +1229,19 @@ int sumo_dpm_enable(struct radeon_device *rdev)
        if (pi->enable_boost)
                sumo_enable_boost_timer(rdev);
 
+       sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+
+       return 0;
+}
+
+int sumo_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
+       ret = sumo_enable_clock_power_gating(rdev);
+       if (ret)
+               return ret;
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                ret = sumo_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1242,8 +1251,6 @@ int sumo_dpm_enable(struct radeon_device *rdev)
                radeon_irq_set(rdev);
        }
 
-       sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
-
        return 0;
 }
 
index 18abba5b5810b467f23efb012b9eee24e5e3a155..fb081d2ae37477e37b0ec28068c7d45112e19bc0 100644 (file)
@@ -31,7 +31,6 @@
 #define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY  27
 #define SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20  20
 
-struct sumo_ps *sumo_get_ps(struct radeon_ps *rps);
 struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev);
 
 static void sumo_send_msg_to_smu(struct radeon_device *rdev, u32 id)
index d700698a1f224bea67bd585061289e56735072e4..2d447192d6f7356b1f37af690e1242932b23d7bf 100644 (file)
@@ -342,14 +342,14 @@ static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
                                             struct radeon_ps *new_rps,
                                             struct radeon_ps *old_rps);
 
-struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
+static struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
 {
        struct trinity_ps *ps = rps->ps_priv;
 
        return ps;
 }
 
-struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
+static struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
 {
        struct trinity_power_info *pi = rdev->pm.dpm.priv;
 
@@ -1082,7 +1082,6 @@ void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
 int trinity_dpm_enable(struct radeon_device *rdev)
 {
        struct trinity_power_info *pi = trinity_get_pi(rdev);
-       int ret;
 
        trinity_acquire_mutex(rdev);
 
@@ -1091,7 +1090,6 @@ int trinity_dpm_enable(struct radeon_device *rdev)
                return -EINVAL;
        }
 
-       trinity_enable_clock_power_gating(rdev);
        trinity_program_bootup_state(rdev);
        sumo_program_vc(rdev, 0x00C00033);
        trinity_start_am(rdev);
@@ -1105,6 +1103,18 @@ int trinity_dpm_enable(struct radeon_device *rdev)
        trinity_dpm_bapm_enable(rdev, false);
        trinity_release_mutex(rdev);
 
+       trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+
+       return 0;
+}
+
+int trinity_dpm_late_enable(struct radeon_device *rdev)
+{
+       int ret;
+
+       trinity_acquire_mutex(rdev);
+       trinity_enable_clock_power_gating(rdev);
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1115,8 +1125,7 @@ int trinity_dpm_enable(struct radeon_device *rdev)
                rdev->irq.dpm_thermal = true;
                radeon_irq_set(rdev);
        }
-
-       trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
+       trinity_release_mutex(rdev);
 
        return 0;
 }
index 9672bcbc7312218a357f07ae54393ed511284279..99dd0455334d1a433c880565ee84dd60e14989c9 100644 (file)
@@ -27,9 +27,6 @@
 #include "trinity_dpm.h"
 #include "ppsmc.h"
 
-struct trinity_ps *trinity_get_ps(struct radeon_ps *rps);
-struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev);
-
 static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
 {
        int i;
index b19ef4951085b06422aa7b2f8b1f634fba086d87..824550db3fed59e2220953e9e9976b8b28443260 100644 (file)
@@ -153,6 +153,7 @@ int uvd_v2_2_resume(struct radeon_device *rdev)
                chip_id = 0x01000015;
                break;
        case CHIP_PITCAIRN:
+       case CHIP_OLAND:
                chip_id = 0x01000016;
                break;
        case CHIP_ARUBA:
index a9d24e4bf79280c90991c155634c0ca8bd87c1d9..fbf4be316d0b675f89be45db4d820952af079287 100644 (file)
@@ -371,7 +371,6 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
                goto error;
 
        rcrtc->plane->format = format;
-       rcrtc->plane->pitch = crtc->fb->pitches[0];
 
        rcrtc->plane->src_x = x;
        rcrtc->plane->src_y = y;
@@ -413,7 +412,7 @@ static int rcar_du_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        rcrtc->plane->src_x = x;
        rcrtc->plane->src_y = y;
 
-       rcar_du_crtc_update_base(to_rcar_crtc(crtc));
+       rcar_du_crtc_update_base(rcrtc);
 
        return 0;
 }
index 0023f9719cf18fda9e2f3232bae5bf178e15de7d..792fd1d20e865df1125294dcfbf626e6a7a16524 100644 (file)
@@ -224,7 +224,9 @@ static int rcar_du_probe(struct platform_device *pdev)
 
 static int rcar_du_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&rcar_du_driver, pdev);
+       struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
+
+       drm_put_dev(rcdu->ddev);
 
        return 0;
 }
@@ -249,8 +251,8 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 };
 
 static const struct rcar_du_device_info rcar_du_r8a7790_info = {
-       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B
-                 | RCAR_DU_FEATURE_DEFR8,
+       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
+       .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
        .num_crtcs = 3,
        .routes = {
                /* R8A7790 has one RGB output, two LVDS outputs and one
@@ -272,9 +274,29 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
        .num_lvds = 2,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7791_info = {
+       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
+       .num_crtcs = 2,
+       .routes = {
+               /* R8A7791 has one RGB output, one LVDS output and one
+                * (currently unsupported) TCON output.
+                */
+               [RCAR_DU_OUTPUT_DPAD0] = {
+                       .possible_crtcs = BIT(1),
+                       .encoder_type = DRM_MODE_ENCODER_NONE,
+               },
+               [RCAR_DU_OUTPUT_LVDS0] = {
+                       .possible_crtcs = BIT(0),
+                       .encoder_type = DRM_MODE_ENCODER_LVDS,
+               },
+       },
+       .num_lvds = 1,
+};
+
 static const struct platform_device_id rcar_du_id_table[] = {
        { "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
        { "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
+       { "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info },
        { }
 };
 
index 65d2d636b002d9fbf32fb2c6391b8df4bc63ff03..e31b735d3f258b69b65ab97320ddfe7440d7d6b9 100644 (file)
@@ -28,8 +28,10 @@ struct rcar_du_device;
 struct rcar_du_lvdsenc;
 
 #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0)        /* Per-CRTC IRQ and clock */
-#define RCAR_DU_FEATURE_ALIGN_128B     (1 << 1)        /* Align pitches to 128 bytes */
-#define RCAR_DU_FEATURE_DEFR8          (1 << 2)        /* Has DEFR8 register */
+#define RCAR_DU_FEATURE_DEFR8          (1 << 1)        /* Has DEFR8 register */
+
+#define RCAR_DU_QUIRK_ALIGN_128B       (1 << 0)        /* Align pitches to 128 bytes */
+#define RCAR_DU_QUIRK_LVDS_LANES       (1 << 1)        /* LVDS lanes 1 and 3 inverted */
 
 /*
  * struct rcar_du_output_routing - Output routing specification
@@ -48,12 +50,14 @@ struct rcar_du_output_routing {
 /*
  * struct rcar_du_device_info - DU model-specific information
  * @features: device features (RCAR_DU_FEATURE_*)
+ * @quirks: device quirks (RCAR_DU_QUIRK_*)
  * @num_crtcs: total number of CRTCs
  * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
  * @num_lvds: number of internal LVDS encoders
  */
 struct rcar_du_device_info {
        unsigned int features;
+       unsigned int quirks;
        unsigned int num_crtcs;
        struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
        unsigned int num_lvds;
@@ -84,6 +88,12 @@ static inline bool rcar_du_has(struct rcar_du_device *rcdu,
        return rcdu->info->features & feature;
 }
 
+static inline bool rcar_du_needs(struct rcar_du_device *rcdu,
+                                unsigned int quirk)
+{
+       return rcdu->info->quirks & quirk;
+}
+
 static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg)
 {
        return ioread32(rcdu->mmio + reg);
index b31ac080c4a77ba6554ae281d0fd90754e8d633b..fbeabd9a281f9a71c2e283df478fb7e3428a7655 100644 (file)
@@ -119,7 +119,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,
        /* The R8A7779 DU requires a 16 pixels pitch alignment as documented,
         * but the R8A7790 DU seems to require a 128 bytes pitch alignment.
         */
-       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B))
+       if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
                align = 128;
        else
                align = 16 * args->bpp / 8;
@@ -144,7 +144,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                return ERR_PTR(-EINVAL);
        }
 
-       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B))
+       if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
                align = 128;
        else
                align = 16 * format->bpp / 8;
index a0f6a17819252b51c0f201861777b8c73fc30ef1..df30a075d793ce5d97c550c80a2f01ce172fbdc1 100644 (file)
@@ -44,6 +44,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
        const struct drm_display_mode *mode = &rcrtc->crtc.mode;
        unsigned int freq = mode->clock;
        u32 lvdcr0;
+       u32 lvdhcr;
        u32 pllcr;
        int ret;
 
@@ -72,15 +73,19 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
         * VSYNC -> CTRL1
         * DISP  -> CTRL2
         * 0     -> CTRL3
-        *
-        * Channels 1 and 3 are switched on ES1.
         */
        rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
                        LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
                        LVDCTRCR_CTR0SEL_HSYNC);
-       rcar_lvds_write(lvds, LVDCHCR,
-                       LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3) |
-                       LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1));
+
+       if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES))
+               lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
+                      | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
+       else
+               lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
+                      | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
+
+       rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
 
        /* Select the input, hardcode mode 0, enable LVDS operation and turn
         * bias circuitry on.
@@ -144,18 +149,9 @@ static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
        sprintf(name, "lvds.%u", lvds->index);
 
        mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
-       if (mem == NULL) {
-               dev_err(&pdev->dev, "failed to get memory resource for %s\n",
-                       name);
-               return -EINVAL;
-       }
-
        lvds->mmio = devm_ioremap_resource(&pdev->dev, mem);
-       if (lvds->mmio == NULL) {
-               dev_err(&pdev->dev, "failed to remap memory resource for %s\n",
-                       name);
-               return -ENOMEM;
-       }
+       if (IS_ERR(lvds->mmio))
+               return PTR_ERR(lvds->mmio);
 
        lvds->clock = devm_clk_get(&pdev->dev, name);
        if (IS_ERR(lvds->clock)) {
index 53000644733f29c25a5db1edb5d24e5090bbc666..3fb69d9ae61bd15fdea9e1801a5e0c69a19d13df 100644 (file)
@@ -104,6 +104,15 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
 {
        struct rcar_du_group *rgrp = plane->group;
        unsigned int index = plane->hwindex;
+       u32 mwr;
+
+       /* Memory pitch (expressed in pixels) */
+       if (plane->format->planes == 2)
+               mwr = plane->pitch;
+       else
+               mwr = plane->pitch * 8 / plane->format->bpp;
+
+       rcar_du_plane_write(rgrp, index, PnMWR, mwr);
 
        /* The Y position is expressed in raster line units and must be doubled
         * for 32bpp formats, according to the R8A7790 datasheet. No mention of
@@ -133,6 +142,8 @@ void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
 {
        struct drm_gem_cma_object *gem;
 
+       plane->pitch = fb->pitches[0];
+
        gem = drm_fb_cma_get_gem_obj(fb, 0);
        plane->dma[0] = gem->paddr + fb->offsets[0];
 
@@ -209,7 +220,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
        struct rcar_du_group *rgrp = plane->group;
        u32 ddcr2 = PnDDCR2_CODE;
        u32 ddcr4;
-       u32 mwr;
 
        /* Data format
         *
@@ -240,14 +250,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
        rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
        rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
 
-       /* Memory pitch (expressed in pixels) */
-       if (plane->format->planes == 2)
-               mwr = plane->pitch;
-       else
-               mwr = plane->pitch * 8 / plane->format->bpp;
-
-       rcar_du_plane_write(rgrp, index, PnMWR, mwr);
-
        /* Destination position and size */
        rcar_du_plane_write(rgrp, index, PnDSXR, plane->width);
        rcar_du_plane_write(rgrp, index, PnDSYR, plane->height);
@@ -309,7 +311,6 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
 
        rplane->crtc = crtc;
        rplane->format = format;
-       rplane->pitch = fb->pitches[0];
 
        rplane->src_x = src_x >> 16;
        rplane->src_y = src_y >> 16;
index b17d0710871abc77487973d837dfe212d17eb5df..d2b2df9e26f3692b51d7495b5197b66ad9d6387b 100644 (file)
@@ -49,7 +49,7 @@ savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
 #endif
 
        for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
-               DRM_MEMORYBARRIER();
+               mb();
                status = dev_priv->status_ptr[0];
                if ((status & mask) < threshold)
                        return 0;
@@ -123,7 +123,7 @@ savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e)
        int i;
 
        for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
-               DRM_MEMORYBARRIER();
+               mb();
                status = dev_priv->status_ptr[1];
                if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
                    (status & 0xffff) == 0)
@@ -449,7 +449,7 @@ static void savage_dma_flush(drm_savage_private_t * dev_priv)
                }
        }
 
-       DRM_MEMORYBARRIER();
+       mb();
 
        /* do flush ... */
        phys_addr = dev_priv->cmd_dma->offset +
@@ -990,10 +990,10 @@ static int savage_bci_get_buffers(struct drm_device *dev,
 
                buf->file_priv = file_priv;
 
-               if (DRM_COPY_TO_USER(&d->request_indices[i],
+               if (copy_to_user(&d->request_indices[i],
                                     &buf->idx, sizeof(buf->idx)))
                        return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i],
+               if (copy_to_user(&d->request_sizes[i],
                                     &buf->total, sizeof(buf->total)))
                        return -EFAULT;
 
index b35e75ed890c0384c48130108858d5e2f95297c3..c01ad0aeaa5806dd034910eff873d48a149fdbc5 100644 (file)
@@ -992,7 +992,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
                if (kcmd_addr == NULL)
                        return -ENOMEM;
 
-               if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr,
+               if (copy_from_user(kcmd_addr, cmdbuf->cmd_addr,
                                       cmdbuf->size * 8))
                {
                        kfree(kcmd_addr);
@@ -1007,7 +1007,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
                        goto done;
                }
 
-               if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf->vb_addr,
+               if (copy_from_user(kvb_addr, cmdbuf->vb_addr,
                                       cmdbuf->vb_size)) {
                        ret = -EFAULT;
                        goto done;
@@ -1022,7 +1022,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
                        goto done;
                }
 
-               if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf->box_addr,
+               if (copy_from_user(kbox_addr, cmdbuf->box_addr,
                                       cmdbuf->nbox * sizeof(struct drm_clip_rect))) {
                        ret = -EFAULT;
                        goto done;
@@ -1032,7 +1032,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
 
        /* Make sure writes to DMA buffers are finished before sending
         * DMA commands to the graphics hardware. */
-       DRM_MEMORYBARRIER();
+       mb();
 
        /* Coming from user space. Don't know if the Xserver has
         * emitted wait commands. Assuming the worst. */
index 562f9a401cf65996bb5b0fa99982451271537736..0428076f1ce8723d025e64cdea77df33777288b6 100644 (file)
  * Clock management
  */
 
-static void shmob_drm_clk_on(struct shmob_drm_device *sdev)
+static int shmob_drm_clk_on(struct shmob_drm_device *sdev)
 {
-       if (sdev->clock)
-               clk_prepare_enable(sdev->clock);
+       int ret;
+
+       if (sdev->clock) {
+               ret = clk_prepare_enable(sdev->clock);
+               if (ret < 0)
+                       return ret;
+       }
 #if 0
        if (sdev->meram_dev && sdev->meram_dev->pdev)
                pm_runtime_get_sync(&sdev->meram_dev->pdev->dev);
 #endif
+
+       return 0;
 }
 
 static void shmob_drm_clk_off(struct shmob_drm_device *sdev)
@@ -161,6 +168,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
        struct drm_device *dev = sdev->ddev;
        struct drm_plane *plane;
        u32 value;
+       int ret;
 
        if (scrtc->started)
                return;
@@ -170,7 +178,9 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
                return;
 
        /* Enable clocks before accessing the hardware. */
-       shmob_drm_clk_on(sdev);
+       ret = shmob_drm_clk_on(sdev);
+       if (ret < 0)
+               return;
 
        /* Reset and enable the LCDC. */
        lcdc_write(sdev, LDCNT2R, lcdc_read(sdev, LDCNT2R) | LDCNT2R_BR);
index 015551866b4a0d3c6f9912c361993f99c3b548b1..c839c9c89efbf6f4eb4a37cac2fba654435bd1f9 100644 (file)
@@ -336,7 +336,9 @@ static int shmob_drm_probe(struct platform_device *pdev)
 
 static int shmob_drm_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&shmob_drm_driver, pdev);
+       struct shmob_drm_device *sdev = platform_get_drvdata(pdev);
+
+       drm_put_dev(sdev->ddev);
 
        return 0;
 }
index 4383b74a3aa46f480ac3c118e3a113812fdff9de..756f787b71439ac42af2b6a723916207165b2382 100644 (file)
@@ -94,7 +94,7 @@ static int sis_driver_open(struct drm_device *dev, struct drm_file *file)
        return 0;
 }
 
-void sis_driver_postclose(struct drm_device *dev, struct drm_file *file)
+static void sis_driver_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct sis_file_private *file_priv = file->driver_priv;
 
index 01857d836350db00261d96870af2571e2b3e356f..0573be0d293304269f6cd11eb8677002ddf217a6 100644 (file)
@@ -266,7 +266,7 @@ int sis_idle(struct drm_device *dev)
         * because its polling frequency is too low.
         */
 
-       end = jiffies + (DRM_HZ * 3);
+       end = jiffies + (HZ * 3);
 
        for (i = 0; i < 4; ++i) {
                do {
index 565f8f7b9a4781d0f9d0b33e1b53b2ecbe2b7eda..e38e5967d77bdc4a4c709cd44744887318cb87bf 100644 (file)
@@ -46,7 +46,6 @@ int drm_host1x_init(struct drm_driver *driver, struct host1x_device *device)
        struct drm_device *drm;
        int ret;
 
-       INIT_LIST_HEAD(&driver->device_list);
        driver->bus = &drm_host1x_bus;
 
        drm = drm_dev_alloc(driver, &device->dev);
index 116da199b9429a56ba8a7b58efc953369b721344..171a8203892ce16b7767b2fb3fa11fc1995f0fad 100644 (file)
@@ -311,7 +311,7 @@ static void tilcdc_lastclose(struct drm_device *dev)
        drm_fbdev_cma_restore_mode(priv->fbdev);
 }
 
-static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS)
+static irqreturn_t tilcdc_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
        struct tilcdc_drm_private *priv = dev->dev_private;
@@ -444,7 +444,7 @@ static int tilcdc_mm_show(struct seq_file *m, void *arg)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
-       return drm_mm_dump_table(m, dev->mm_private);
+       return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
 }
 
 static struct drm_info_list tilcdc_debugfs_list[] = {
@@ -594,7 +594,7 @@ static int tilcdc_pdev_probe(struct platform_device *pdev)
 
 static int tilcdc_pdev_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&tilcdc_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
 
        return 0;
 }
index 07e02c4bf5a8e0def00e120a14b5ada2d1cfaa97..a066513093880a218d185624589ec07efce66b0b 100644 (file)
@@ -957,7 +957,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
 }
 EXPORT_SYMBOL(ttm_bo_mem_space);
 
-int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
+static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
                        struct ttm_placement *placement,
                        bool interruptible,
                        bool no_wait_gpu)
index 15b86a94949dcb875d3cd716322875ad8c763e88..1df856f7856821b31fe96e55dac5bc74bd74ed4b 100644 (file)
@@ -187,7 +187,7 @@ void ttm_mem_io_free_vm(struct ttm_buffer_object *bo)
        }
 }
 
-int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
+static int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
                        void **virtual)
 {
        struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
@@ -219,7 +219,7 @@ int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
        return 0;
 }
 
-void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
+static void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
                         void *virtual)
 {
        struct ttm_mem_type_manager *man;
@@ -353,7 +353,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
         * Don't move nonexistent data. Clear destination instead.
         */
        if (old_iomap == NULL &&
-           (ttm == NULL || ttm->state == tt_unpopulated)) {
+           (ttm == NULL || (ttm->state == tt_unpopulated &&
+                            !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)))) {
                memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE);
                goto out2;
        }
@@ -593,7 +594,7 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo,
        if (start_page > bo->num_pages)
                return -EINVAL;
 #if 0
-       if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC))
+       if (num_pages > 1 && !capable(CAP_SYS_ADMIN))
                return -EPERM;
 #endif
        (void) ttm_mem_io_lock(man, false);
index b249ab9b1eb29c402d407049a42c2fda83b3ffb1..801231c9ae483980afe0e93a0af73a7f07123864 100644 (file)
@@ -132,6 +132,15 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                return VM_FAULT_NOPAGE;
        }
 
+       /*
+        * Refuse to fault imported pages. This should be handled
+        * (if at all) by redirecting mmap to the exporter.
+        */
+       if (bo->ttm && (bo->ttm->page_flags & TTM_PAGE_FLAG_SG)) {
+               retval = VM_FAULT_SIGBUS;
+               goto out_unlock;
+       }
+
        if (bdev->driver->fault_reserve_notify) {
                ret = bdev->driver->fault_reserve_notify(bo);
                switch (ret) {
@@ -169,9 +178,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        }
 
        page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) +
-           drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
-       page_last = vma_pages(vma) +
-           drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
+               vma->vm_pgoff - drm_vma_node_start(&bo->vma_node);
+       page_last = vma_pages(vma) + vma->vm_pgoff -
+               drm_vma_node_start(&bo->vma_node);
 
        if (unlikely(page_offset >= bo->num_pages)) {
                retval = VM_FAULT_SIGBUS;
@@ -217,10 +226,17 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                        } else if (unlikely(!page)) {
                                break;
                        }
+                       page->mapping = vma->vm_file->f_mapping;
+                       page->index = drm_vma_node_start(&bo->vma_node) +
+                               page_offset;
                        pfn = page_to_pfn(page);
                }
 
-               ret = vm_insert_mixed(&cvma, address, pfn);
+               if (vma->vm_flags & VM_MIXEDMAP)
+                       ret = vm_insert_mixed(&cvma, address, pfn);
+               else
+                       ret = vm_insert_pfn(&cvma, address, pfn);
+
                /*
                 * Somebody beat us to this PTE or prefaulting to
                 * an already populated PTE, or prefaulting error.
@@ -250,6 +266,8 @@ static void ttm_bo_vm_open(struct vm_area_struct *vma)
        struct ttm_buffer_object *bo =
            (struct ttm_buffer_object *)vma->vm_private_data;
 
+       WARN_ON(bo->bdev->dev_mapping != vma->vm_file->f_mapping);
+
        (void)ttm_bo_reference(bo);
 }
 
@@ -319,7 +337,14 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
         */
 
        vma->vm_private_data = bo;
-       vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
+
+       /*
+        * PFNMAP is faster than MIXEDMAP due to reduced page
+        * administration. So use MIXEDMAP only if private VMA, where
+        * we need to support COW.
+        */
+       vma->vm_flags |= (vma->vm_flags & VM_SHARED) ? VM_PFNMAP : VM_MIXEDMAP;
+       vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
        return 0;
 out_unref:
        ttm_bo_unref(&bo);
@@ -334,7 +359,8 @@ int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo)
 
        vma->vm_ops = &ttm_bo_vm_ops;
        vma->vm_private_data = ttm_bo_reference(bo);
-       vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
+       vma->vm_flags |= (vma->vm_flags & VM_SHARED) ? VM_PFNMAP : VM_MIXEDMAP;
+       vma->vm_flags |= VM_IO | VM_DONTEXPAND;
        return 0;
 }
 EXPORT_SYMBOL(ttm_fbdev_mmap);
index 3daa9a3930b810c5adaf310a3dbea89e0e73343d..6a954544727f3f13cfa8d9be0b8ff4cbf39d9367 100644 (file)
@@ -186,14 +186,6 @@ int ttm_write_lock(struct ttm_lock *lock, bool interruptible)
 }
 EXPORT_SYMBOL(ttm_write_lock);
 
-void ttm_write_lock_downgrade(struct ttm_lock *lock)
-{
-       spin_lock(&lock->lock);
-       lock->rw = 1;
-       wake_up_all(&lock->queue);
-       spin_unlock(&lock->lock);
-}
-
 static int __ttm_vt_unlock(struct ttm_lock *lock)
 {
        int ret = 0;
index 6fe7b92a82d1f72f465a79d48dd0088337d713fe..37079859afc86e6cef120cd4d8a924388c3f6e3b 100644 (file)
@@ -68,7 +68,7 @@
 
 struct ttm_object_file {
        struct ttm_object_device *tdev;
-       rwlock_t lock;
+       spinlock_t lock;
        struct list_head ref_list;
        struct drm_open_hash ref_hash[TTM_REF_NUM];
        struct kref refcount;
@@ -118,6 +118,7 @@ struct ttm_object_device {
  */
 
 struct ttm_ref_object {
+       struct rcu_head rcu_head;
        struct drm_hash_item hash;
        struct list_head head;
        struct kref kref;
@@ -210,10 +211,9 @@ static void ttm_release_base(struct kref *kref)
         * call_rcu() or ttm_base_object_kfree().
         */
 
-       if (base->refcount_release) {
-               ttm_object_file_unref(&base->tfile);
+       ttm_object_file_unref(&base->tfile);
+       if (base->refcount_release)
                base->refcount_release(&base);
-       }
 }
 
 void ttm_base_object_unref(struct ttm_base_object **p_base)
@@ -229,32 +229,46 @@ EXPORT_SYMBOL(ttm_base_object_unref);
 struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
                                               uint32_t key)
 {
-       struct ttm_object_device *tdev = tfile->tdev;
-       struct ttm_base_object *uninitialized_var(base);
+       struct ttm_base_object *base = NULL;
        struct drm_hash_item *hash;
+       struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
        int ret;
 
        rcu_read_lock();
-       ret = drm_ht_find_item_rcu(&tdev->object_hash, key, &hash);
+       ret = drm_ht_find_item_rcu(ht, key, &hash);
 
        if (likely(ret == 0)) {
-               base = drm_hash_entry(hash, struct ttm_base_object, hash);
-               ret = kref_get_unless_zero(&base->refcount) ? 0 : -EINVAL;
+               base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
+               if (!kref_get_unless_zero(&base->refcount))
+                       base = NULL;
        }
        rcu_read_unlock();
 
-       if (unlikely(ret != 0))
-               return NULL;
+       return base;
+}
+EXPORT_SYMBOL(ttm_base_object_lookup);
 
-       if (tfile != base->tfile && !base->shareable) {
-               pr_err("Attempted access of non-shareable object\n");
-               ttm_base_object_unref(&base);
-               return NULL;
+struct ttm_base_object *
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
+{
+       struct ttm_base_object *base = NULL;
+       struct drm_hash_item *hash;
+       struct drm_open_hash *ht = &tdev->object_hash;
+       int ret;
+
+       rcu_read_lock();
+       ret = drm_ht_find_item_rcu(ht, key, &hash);
+
+       if (likely(ret == 0)) {
+               base = drm_hash_entry(hash, struct ttm_base_object, hash);
+               if (!kref_get_unless_zero(&base->refcount))
+                       base = NULL;
        }
+       rcu_read_unlock();
 
        return base;
 }
-EXPORT_SYMBOL(ttm_base_object_lookup);
+EXPORT_SYMBOL(ttm_base_object_lookup_for_ref);
 
 int ttm_ref_object_add(struct ttm_object_file *tfile,
                       struct ttm_base_object *base,
@@ -266,21 +280,25 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
        struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
        int ret = -EINVAL;
 
+       if (base->tfile != tfile && !base->shareable)
+               return -EPERM;
+
        if (existed != NULL)
                *existed = true;
 
        while (ret == -EINVAL) {
-               read_lock(&tfile->lock);
-               ret = drm_ht_find_item(ht, base->hash.key, &hash);
+               rcu_read_lock();
+               ret = drm_ht_find_item_rcu(ht, base->hash.key, &hash);
 
                if (ret == 0) {
                        ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
-                       kref_get(&ref->kref);
-                       read_unlock(&tfile->lock);
-                       break;
+                       if (!kref_get_unless_zero(&ref->kref)) {
+                               rcu_read_unlock();
+                               break;
+                       }
                }
 
-               read_unlock(&tfile->lock);
+               rcu_read_unlock();
                ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
                                           false, false);
                if (unlikely(ret != 0))
@@ -297,19 +315,19 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
                ref->ref_type = ref_type;
                kref_init(&ref->kref);
 
-               write_lock(&tfile->lock);
-               ret = drm_ht_insert_item(ht, &ref->hash);
+               spin_lock(&tfile->lock);
+               ret = drm_ht_insert_item_rcu(ht, &ref->hash);
 
                if (likely(ret == 0)) {
                        list_add_tail(&ref->head, &tfile->ref_list);
                        kref_get(&base->refcount);
-                       write_unlock(&tfile->lock);
+                       spin_unlock(&tfile->lock);
                        if (existed != NULL)
                                *existed = false;
                        break;
                }
 
-               write_unlock(&tfile->lock);
+               spin_unlock(&tfile->lock);
                BUG_ON(ret != -EINVAL);
 
                ttm_mem_global_free(mem_glob, sizeof(*ref));
@@ -330,17 +348,17 @@ static void ttm_ref_object_release(struct kref *kref)
        struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
 
        ht = &tfile->ref_hash[ref->ref_type];
-       (void)drm_ht_remove_item(ht, &ref->hash);
+       (void)drm_ht_remove_item_rcu(ht, &ref->hash);
        list_del(&ref->head);
-       write_unlock(&tfile->lock);
+       spin_unlock(&tfile->lock);
 
        if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release)
                base->ref_obj_release(base, ref->ref_type);
 
        ttm_base_object_unref(&ref->obj);
        ttm_mem_global_free(mem_glob, sizeof(*ref));
-       kfree(ref);
-       write_lock(&tfile->lock);
+       kfree_rcu(ref, rcu_head);
+       spin_lock(&tfile->lock);
 }
 
 int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
@@ -351,15 +369,15 @@ int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
        struct drm_hash_item *hash;
        int ret;
 
-       write_lock(&tfile->lock);
+       spin_lock(&tfile->lock);
        ret = drm_ht_find_item(ht, key, &hash);
        if (unlikely(ret != 0)) {
-               write_unlock(&tfile->lock);
+               spin_unlock(&tfile->lock);
                return -EINVAL;
        }
        ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
        kref_put(&ref->kref, ttm_ref_object_release);
-       write_unlock(&tfile->lock);
+       spin_unlock(&tfile->lock);
        return 0;
 }
 EXPORT_SYMBOL(ttm_ref_object_base_unref);
@@ -372,7 +390,7 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
        struct ttm_object_file *tfile = *p_tfile;
 
        *p_tfile = NULL;
-       write_lock(&tfile->lock);
+       spin_lock(&tfile->lock);
 
        /*
         * Since we release the lock within the loop, we have to
@@ -388,7 +406,7 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
        for (i = 0; i < TTM_REF_NUM; ++i)
                drm_ht_remove(&tfile->ref_hash[i]);
 
-       write_unlock(&tfile->lock);
+       spin_unlock(&tfile->lock);
        ttm_object_file_unref(&tfile);
 }
 EXPORT_SYMBOL(ttm_object_file_release);
@@ -404,7 +422,7 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
        if (unlikely(tfile == NULL))
                return NULL;
 
-       rwlock_init(&tfile->lock);
+       spin_lock_init(&tfile->lock);
        tfile->tdev = tdev;
        kref_init(&tfile->refcount);
        INIT_LIST_HEAD(&tfile->ref_list);
index 210d50365162d39d8b2048ba3d8c0e567ed95bf9..9af99084b344413dcb07c2a368916bff647fc119 100644 (file)
@@ -170,9 +170,8 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
                ttm_tt_unbind(ttm);
        }
 
-       if (ttm->state == tt_unbound) {
-               ttm->bdev->driver->ttm_tt_unpopulate(ttm);
-       }
+       if (ttm->state == tt_unbound)
+               ttm_tt_unpopulate(ttm);
 
        if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) &&
            ttm->swap_storage)
@@ -362,7 +361,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                page_cache_release(to_page);
        }
 
-       ttm->bdev->driver->ttm_tt_unpopulate(ttm);
+       ttm_tt_unpopulate(ttm);
        ttm->swap_storage = swap_storage;
        ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
        if (persistent_swap_storage)
@@ -375,3 +374,23 @@ out_err:
 
        return ret;
 }
+
+static void ttm_tt_clear_mapping(struct ttm_tt *ttm)
+{
+       pgoff_t i;
+       struct page **page = ttm->pages;
+
+       for (i = 0; i < ttm->num_pages; ++i) {
+               (*page)->mapping = NULL;
+               (*page++)->index = 0;
+       }
+}
+
+void ttm_tt_unpopulate(struct ttm_tt *ttm)
+{
+       if (ttm->state == tt_unpopulated)
+               return;
+
+       ttm_tt_clear_mapping(ttm);
+       ttm->bdev->driver->ttm_tt_unpopulate(ttm);
+}
index 97e9d614700f7f6d475b55c7ecae8a513e54afb4..dbadd49e4c4a62bdd32c83473ad3751452e4033d 100644 (file)
@@ -403,15 +403,17 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb,
        int i;
        int ret = 0;
 
+       drm_modeset_lock_all(fb->dev);
+
        if (!ufb->active_16)
-               return 0;
+               goto unlock;
 
        if (ufb->obj->base.import_attach) {
                ret = dma_buf_begin_cpu_access(ufb->obj->base.import_attach->dmabuf,
                                               0, ufb->obj->base.size,
                                               DMA_FROM_DEVICE);
                if (ret)
-                       return ret;
+                       goto unlock;
        }
 
        for (i = 0; i < num_clips; i++) {
@@ -419,7 +421,7 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb,
                                  clips[i].x2 - clips[i].x1,
                                  clips[i].y2 - clips[i].y1);
                if (ret)
-                       break;
+                       goto unlock;
        }
 
        if (ufb->obj->base.import_attach) {
@@ -427,6 +429,10 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb,
                                       0, ufb->obj->base.size,
                                       DMA_FROM_DEVICE);
        }
+
+ unlock:
+       drm_modeset_unlock_all(fb->dev);
+
        return ret;
 }
 
index 652f9b43ec9dcfc1c8a6e383dcc443fa9ef2db94..a18479c6b6dae3dfdbb3d3e6e238f129dc79a3ad 100644 (file)
@@ -60,7 +60,7 @@
        dev_priv->dma_low += 8;                                 \
 }
 
-#define via_flush_write_combine() DRM_MEMORYBARRIER()
+#define via_flush_write_combine() mb()
 
 #define VIA_OUT_RING_QW(w1, w2)        do {            \
        *vb++ = (w1);                           \
@@ -234,13 +234,13 @@ static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *fil
 
        switch (init->func) {
        case VIA_INIT_DMA:
-               if (!DRM_SUSER(DRM_CURPROC))
+               if (!capable(CAP_SYS_ADMIN))
                        retcode = -EPERM;
                else
                        retcode = via_initialize(dev, dev_priv, init);
                break;
        case VIA_CLEANUP_DMA:
-               if (!DRM_SUSER(DRM_CURPROC))
+               if (!capable(CAP_SYS_ADMIN))
                        retcode = -EPERM;
                else
                        retcode = via_dma_cleanup(dev);
@@ -273,7 +273,7 @@ static int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *c
        if (cmd->size > VIA_PCI_BUF_SIZE)
                return -ENOMEM;
 
-       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+       if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size))
                return -EFAULT;
 
        /*
@@ -346,7 +346,7 @@ static int via_dispatch_pci_cmdbuffer(struct drm_device *dev,
 
        if (cmd->size > VIA_PCI_BUF_SIZE)
                return -ENOMEM;
-       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+       if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size))
                return -EFAULT;
 
        if ((ret =
@@ -543,7 +543,7 @@ static void via_cmdbuf_start(drm_via_private_t *dev_priv)
 
        VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
        VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
-       DRM_WRITEMEMORYBARRIER();
+       wmb();
        VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
        VIA_READ(VIA_REG_TRANSPACE);
 
index 8b0f25904e6db4edf754c9c18ab58077bfb0930e..ba33cf679180498a4ecd29260c16ee0570d2f480 100644 (file)
@@ -217,7 +217,7 @@ via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
        VIA_WRITE(VIA_PCI_DMA_MR0  + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
        VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);
        VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
-       DRM_WRITEMEMORYBARRIER();
+       wmb();
        VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
        VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04);
 }
@@ -338,7 +338,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
 
                blitq->blits[cur]->aborted = blitq->aborting;
                blitq->done_blit_handle++;
-               DRM_WAKEUP(blitq->blit_queue + cur);
+               wake_up(blitq->blit_queue + cur);
 
                cur++;
                if (cur >= VIA_NUM_BLIT_SLOTS)
@@ -363,7 +363,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
 
                via_abort_dmablit(dev, engine);
                blitq->aborting = 1;
-               blitq->end = jiffies + DRM_HZ;
+               blitq->end = jiffies + HZ;
        }
 
        if (!blitq->is_active) {
@@ -372,7 +372,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
                        blitq->is_active = 1;
                        blitq->cur = cur;
                        blitq->num_outstanding--;
-                       blitq->end = jiffies + DRM_HZ;
+                       blitq->end = jiffies + HZ;
                        if (!timer_pending(&blitq->poll_timer))
                                mod_timer(&blitq->poll_timer, jiffies + 1);
                } else {
@@ -436,7 +436,7 @@ via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine)
        int ret = 0;
 
        if (via_dmablit_active(blitq, engine, handle, &queue)) {
-               DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, *queue, 3 * HZ,
                            !via_dmablit_active(blitq, engine, handle, NULL));
        }
        DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
@@ -521,7 +521,7 @@ via_dmablit_workqueue(struct work_struct *work)
 
                spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
 
-               DRM_WAKEUP(&blitq->busy_queue);
+               wake_up(&blitq->busy_queue);
 
                via_free_sg_info(dev->pdev, cur_sg);
                kfree(cur_sg);
@@ -561,8 +561,8 @@ via_init_dmablit(struct drm_device *dev)
                blitq->aborting = 0;
                spin_lock_init(&blitq->blit_lock);
                for (j = 0; j < VIA_NUM_BLIT_SLOTS; ++j)
-                       DRM_INIT_WAITQUEUE(blitq->blit_queue + j);
-               DRM_INIT_WAITQUEUE(&blitq->busy_queue);
+                       init_waitqueue_head(blitq->blit_queue + j);
+               init_waitqueue_head(&blitq->busy_queue);
                INIT_WORK(&blitq->wq, via_dmablit_workqueue);
                setup_timer(&blitq->poll_timer, via_dmablit_timer,
                                (unsigned long)blitq);
@@ -688,7 +688,7 @@ via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
        while (blitq->num_free == 0) {
                spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
 
-               DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);
+               DRM_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0);
                if (ret)
                        return (-EINTR == ret) ? -EAGAIN : ret;
 
@@ -713,7 +713,7 @@ via_dmablit_release_slot(drm_via_blitq_t *blitq)
        spin_lock_irqsave(&blitq->blit_lock, irqsave);
        blitq->num_free++;
        spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-       DRM_WAKEUP(&blitq->busy_queue);
+       wake_up(&blitq->busy_queue);
 }
 
 /*
index 92684a9b7e3414f69cdc76f2d2ef82d286cda734..50abc2adfaee495730337a94b4fc931bcdd40f37 100644 (file)
@@ -46,7 +46,7 @@ static int via_driver_open(struct drm_device *dev, struct drm_file *file)
        return 0;
 }
 
-void via_driver_postclose(struct drm_device *dev, struct drm_file *file)
+static void via_driver_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct via_file_private *file_priv = file->driver_priv;
 
index a811ef2b505f1b25de22921a55ad8309d6a33d6a..ad0273256beb58b3bd4ff65c3c6b230427543a17 100644 (file)
@@ -138,7 +138,7 @@ extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int via_enable_vblank(struct drm_device *dev, int crtc);
 extern void via_disable_vblank(struct drm_device *dev, int crtc);
 
-extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t via_driver_irq_handler(int irq, void *arg);
 extern void via_driver_irq_preinstall(struct drm_device *dev);
 extern int via_driver_irq_postinstall(struct drm_device *dev);
 extern void via_driver_irq_uninstall(struct drm_device *dev);
index ac98964297cfffcf4939817629fbd51d17f32dd7..1319433816d3cd4743c7eadbcf073d8703c6476b 100644 (file)
@@ -104,7 +104,7 @@ u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
        return atomic_read(&dev_priv->vbl_received);
 }
 
-irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t via_driver_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *) arg;
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
@@ -138,7 +138,7 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
        for (i = 0; i < dev_priv->num_irqs; ++i) {
                if (status & cur_irq->pending_mask) {
                        atomic_inc(&cur_irq->irq_received);
-                       DRM_WAKEUP(&cur_irq->irq_queue);
+                       wake_up(&cur_irq->irq_queue);
                        handled = 1;
                        if (dev_priv->irq_map[drm_via_irq_dma0_td] == i)
                                via_dmablit_handler(dev, 0, 1);
@@ -239,12 +239,12 @@ via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence
        cur_irq = dev_priv->via_irqs + real_irq;
 
        if (masks[real_irq][2] && !force_sequence) {
-               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
                            ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
                             masks[irq][4]));
                cur_irq_sequence = atomic_read(&cur_irq->irq_received);
        } else {
-               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
                            (((cur_irq_sequence =
                               atomic_read(&cur_irq->irq_received)) -
                              *sequence) <= (1 << 23)));
@@ -287,7 +287,7 @@ void via_driver_irq_preinstall(struct drm_device *dev)
                        atomic_set(&cur_irq->irq_received, 0);
                        cur_irq->enable_mask = dev_priv->irq_masks[i][0];
                        cur_irq->pending_mask = dev_priv->irq_masks[i][1];
-                       DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
+                       init_waitqueue_head(&cur_irq->irq_queue);
                        dev_priv->irq_enable_mask |= cur_irq->enable_mask;
                        dev_priv->irq_pending_mask |= cur_irq->pending_mask;
                        cur_irq++;
index 6569efa2ff6ea4e82f2e91649dc9fdec0964b107..a9ffbad1cfdd87fe9d4c4bf14ce8902ca07f4f50 100644 (file)
@@ -36,7 +36,7 @@ void via_init_futex(drm_via_private_t *dev_priv)
        DRM_DEBUG("\n");
 
        for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
-               DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i]));
+               init_waitqueue_head(&(dev_priv->decoder_queue[i]));
                XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
        }
 }
@@ -58,7 +58,7 @@ void via_release_futex(drm_via_private_t *dev_priv, int context)
                if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
                        if (_DRM_LOCK_IS_HELD(*lock)
                            && (*lock & _DRM_LOCK_CONT)) {
-                               DRM_WAKEUP(&(dev_priv->decoder_queue[i]));
+                               wake_up(&(dev_priv->decoder_queue[i]));
                        }
                        *lock = 0;
                }
@@ -83,10 +83,10 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_
        switch (fx->func) {
        case VIA_FUTEX_WAIT:
                DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
-                           (fx->ms / 10) * (DRM_HZ / 100), *lock != fx->val);
+                           (fx->ms / 10) * (HZ / 100), *lock != fx->val);
                return ret;
        case VIA_FUTEX_WAKE:
-               DRM_WAKEUP(&(dev_priv->decoder_queue[fx->lock]));
+               wake_up(&(dev_priv->decoder_queue[fx->lock]));
                return 0;
        }
        return 0;
index 9f8b690bcf52c97e24db7c6a515f9be185b30321..458cdf6d81e8b91781af5d1c18d663c133c5f455 100644 (file)
@@ -6,6 +6,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
            vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
            vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
            vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \
-           vmwgfx_surface.o vmwgfx_prime.o
+           vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
index d0e085ee82498679cdde540f2ce87c539fa4856b..d95335cb90bd4f30f7b7cdcf601028611986d802 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "svga_reg.h"
 
+typedef uint32 PPN;
+typedef __le64 PPN64;
 
 /*
  * 3D Hardware Version
@@ -71,6 +73,9 @@ typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
 #define SVGA3D_MAX_CONTEXT_IDS                  256
 #define SVGA3D_MAX_SURFACE_IDS                  (32 * 1024)
 
+#define SVGA3D_NUM_TEXTURE_UNITS                32
+#define SVGA3D_NUM_LIGHTS                       8
+
 /*
  * Surface formats.
  *
@@ -81,6 +86,7 @@ typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
  */
 
 typedef enum SVGA3dSurfaceFormat {
+   SVGA3D_FORMAT_MIN                   = 0,
    SVGA3D_FORMAT_INVALID               = 0,
 
    SVGA3D_X8R8G8B8                     = 1,
@@ -134,12 +140,6 @@ typedef enum SVGA3dSurfaceFormat {
    SVGA3D_RG_S10E5                     = 35,
    SVGA3D_RG_S23E8                     = 36,
 
-   /*
-    * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
-    * the most efficient format to use when creating new surfaces
-    * expressly for index or vertex data.
-    */
-
    SVGA3D_BUFFER                       = 37,
 
    SVGA3D_Z_D24X8                      = 38,
@@ -159,15 +159,114 @@ typedef enum SVGA3dSurfaceFormat {
    /* Video format with alpha */
    SVGA3D_AYUV                         = 45,
 
+   SVGA3D_R32G32B32A32_TYPELESS        = 46,
+   SVGA3D_R32G32B32A32_FLOAT           = 25,
+   SVGA3D_R32G32B32A32_UINT            = 47,
+   SVGA3D_R32G32B32A32_SINT            = 48,
+   SVGA3D_R32G32B32_TYPELESS           = 49,
+   SVGA3D_R32G32B32_FLOAT              = 50,
+   SVGA3D_R32G32B32_UINT               = 51,
+   SVGA3D_R32G32B32_SINT               = 52,
+   SVGA3D_R16G16B16A16_TYPELESS        = 53,
+   SVGA3D_R16G16B16A16_FLOAT           = 24,
+   SVGA3D_R16G16B16A16_UNORM           = 41,
+   SVGA3D_R16G16B16A16_UINT            = 54,
+   SVGA3D_R16G16B16A16_SNORM           = 55,
+   SVGA3D_R16G16B16A16_SINT            = 56,
+   SVGA3D_R32G32_TYPELESS              = 57,
+   SVGA3D_R32G32_FLOAT                 = 36,
+   SVGA3D_R32G32_UINT                  = 58,
+   SVGA3D_R32G32_SINT                  = 59,
+   SVGA3D_R32G8X24_TYPELESS            = 60,
+   SVGA3D_D32_FLOAT_S8X24_UINT         = 61,
+   SVGA3D_R32_FLOAT_X8X24_TYPELESS     = 62,
+   SVGA3D_X32_TYPELESS_G8X24_UINT      = 63,
+   SVGA3D_R10G10B10A2_TYPELESS         = 64,
+   SVGA3D_R10G10B10A2_UNORM            = 26,
+   SVGA3D_R10G10B10A2_UINT             = 65,
+   SVGA3D_R11G11B10_FLOAT              = 66,
+   SVGA3D_R8G8B8A8_TYPELESS            = 67,
+   SVGA3D_R8G8B8A8_UNORM               = 68,
+   SVGA3D_R8G8B8A8_UNORM_SRGB          = 69,
+   SVGA3D_R8G8B8A8_UINT                = 70,
+   SVGA3D_R8G8B8A8_SNORM               = 28,
+   SVGA3D_R8G8B8A8_SINT                = 71,
+   SVGA3D_R16G16_TYPELESS              = 72,
+   SVGA3D_R16G16_FLOAT                 = 35,
+   SVGA3D_R16G16_UNORM                 = 40,
+   SVGA3D_R16G16_UINT                  = 73,
+   SVGA3D_R16G16_SNORM                 = 39,
+   SVGA3D_R16G16_SINT                  = 74,
+   SVGA3D_R32_TYPELESS                 = 75,
+   SVGA3D_D32_FLOAT                    = 76,
+   SVGA3D_R32_FLOAT                    = 34,
+   SVGA3D_R32_UINT                     = 77,
+   SVGA3D_R32_SINT                     = 78,
+   SVGA3D_R24G8_TYPELESS               = 79,
+   SVGA3D_D24_UNORM_S8_UINT            = 80,
+   SVGA3D_R24_UNORM_X8_TYPELESS        = 81,
+   SVGA3D_X24_TYPELESS_G8_UINT         = 82,
+   SVGA3D_R8G8_TYPELESS                = 83,
+   SVGA3D_R8G8_UNORM                   = 84,
+   SVGA3D_R8G8_UINT                    = 85,
+   SVGA3D_R8G8_SNORM                   = 27,
+   SVGA3D_R8G8_SINT                    = 86,
+   SVGA3D_R16_TYPELESS                 = 87,
+   SVGA3D_R16_FLOAT                    = 33,
+   SVGA3D_D16_UNORM                    = 8,
+   SVGA3D_R16_UNORM                    = 88,
+   SVGA3D_R16_UINT                     = 89,
+   SVGA3D_R16_SNORM                    = 90,
+   SVGA3D_R16_SINT                     = 91,
+   SVGA3D_R8_TYPELESS                  = 92,
+   SVGA3D_R8_UNORM                     = 93,
+   SVGA3D_R8_UINT                      = 94,
+   SVGA3D_R8_SNORM                     = 95,
+   SVGA3D_R8_SINT                      = 96,
+   SVGA3D_A8_UNORM                     = 32,
+   SVGA3D_R1_UNORM                     = 97,
+   SVGA3D_R9G9B9E5_SHAREDEXP           = 98,
+   SVGA3D_R8G8_B8G8_UNORM              = 99,
+   SVGA3D_G8R8_G8B8_UNORM              = 100,
+   SVGA3D_BC1_TYPELESS                 = 101,
+   SVGA3D_BC1_UNORM                    = 15,
+   SVGA3D_BC1_UNORM_SRGB               = 102,
+   SVGA3D_BC2_TYPELESS                 = 103,
+   SVGA3D_BC2_UNORM                    = 17,
+   SVGA3D_BC2_UNORM_SRGB               = 104,
+   SVGA3D_BC3_TYPELESS                 = 105,
+   SVGA3D_BC3_UNORM                    = 19,
+   SVGA3D_BC3_UNORM_SRGB               = 106,
+   SVGA3D_BC4_TYPELESS                 = 107,
    SVGA3D_BC4_UNORM                    = 108,
+   SVGA3D_BC4_SNORM                    = 109,
+   SVGA3D_BC5_TYPELESS                 = 110,
    SVGA3D_BC5_UNORM                    = 111,
+   SVGA3D_BC5_SNORM                    = 112,
+   SVGA3D_B5G6R5_UNORM                 = 3,
+   SVGA3D_B5G5R5A1_UNORM               = 5,
+   SVGA3D_B8G8R8A8_UNORM               = 2,
+   SVGA3D_B8G8R8X8_UNORM               = 1,
+   SVGA3D_R10G10B10_XR_BIAS_A2_UNORM   = 113,
+   SVGA3D_B8G8R8A8_TYPELESS            = 114,
+   SVGA3D_B8G8R8A8_UNORM_SRGB          = 115,
+   SVGA3D_B8G8R8X8_TYPELESS            = 116,
+   SVGA3D_B8G8R8X8_UNORM_SRGB          = 117,
 
    /* Advanced D3D9 depth formats. */
    SVGA3D_Z_DF16                       = 118,
    SVGA3D_Z_DF24                       = 119,
    SVGA3D_Z_D24S8_INT                  = 120,
 
-   SVGA3D_FORMAT_MAX
+   /* Planar video formats. */
+   SVGA3D_YV12                         = 121,
+
+   /* Shader constant formats. */
+   SVGA3D_SURFACE_SHADERCONST_FLOAT    = 122,
+   SVGA3D_SURFACE_SHADERCONST_INT      = 123,
+   SVGA3D_SURFACE_SHADERCONST_BOOL     = 124,
+
+   SVGA3D_FORMAT_MAX                   = 125,
 } SVGA3dSurfaceFormat;
 
 typedef uint32 SVGA3dColor; /* a, r, g, b */
@@ -957,15 +1056,21 @@ typedef enum {
 } SVGA3dCubeFace;
 
 typedef enum {
+   SVGA3D_SHADERTYPE_INVALID                    = 0,
+   SVGA3D_SHADERTYPE_MIN                        = 1,
    SVGA3D_SHADERTYPE_VS                         = 1,
    SVGA3D_SHADERTYPE_PS                         = 2,
-   SVGA3D_SHADERTYPE_MAX
+   SVGA3D_SHADERTYPE_MAX                        = 3,
+   SVGA3D_SHADERTYPE_GS                         = 3,
 } SVGA3dShaderType;
 
+#define SVGA3D_NUM_SHADERTYPE (SVGA3D_SHADERTYPE_MAX - SVGA3D_SHADERTYPE_MIN)
+
 typedef enum {
    SVGA3D_CONST_TYPE_FLOAT                      = 0,
    SVGA3D_CONST_TYPE_INT                        = 1,
    SVGA3D_CONST_TYPE_BOOL                       = 2,
+   SVGA3D_CONST_TYPE_MAX
 } SVGA3dShaderConstType;
 
 #define SVGA3D_MAX_SURFACE_FACES                6
@@ -1056,9 +1161,74 @@ typedef enum {
 #define SVGA_3D_CMD_GENERATE_MIPMAPS       SVGA_3D_CMD_BASE + 31
 #define SVGA_3D_CMD_ACTIVATE_SURFACE       SVGA_3D_CMD_BASE + 40
 #define SVGA_3D_CMD_DEACTIVATE_SURFACE     SVGA_3D_CMD_BASE + 41
-#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 42
-
-#define SVGA_3D_CMD_FUTURE_MAX             2000
+#define SVGA_3D_CMD_SCREEN_DMA               1082
+#define SVGA_3D_CMD_SET_UNITY_SURFACE_COOKIE 1083
+#define SVGA_3D_CMD_OPEN_CONTEXT_SURFACE     1084
+
+#define SVGA_3D_CMD_LOGICOPS_BITBLT          1085
+#define SVGA_3D_CMD_LOGICOPS_TRANSBLT        1086
+#define SVGA_3D_CMD_LOGICOPS_STRETCHBLT      1087
+#define SVGA_3D_CMD_LOGICOPS_COLORFILL       1088
+#define SVGA_3D_CMD_LOGICOPS_ALPHABLEND      1089
+#define SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND  1090
+
+#define SVGA_3D_CMD_SET_OTABLE_BASE          1091
+#define SVGA_3D_CMD_READBACK_OTABLE          1092
+
+#define SVGA_3D_CMD_DEFINE_GB_MOB            1093
+#define SVGA_3D_CMD_DESTROY_GB_MOB           1094
+#define SVGA_3D_CMD_REDEFINE_GB_MOB          1095
+#define SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING    1096
+
+#define SVGA_3D_CMD_DEFINE_GB_SURFACE        1097
+#define SVGA_3D_CMD_DESTROY_GB_SURFACE       1098
+#define SVGA_3D_CMD_BIND_GB_SURFACE          1099
+#define SVGA_3D_CMD_COND_BIND_GB_SURFACE     1100
+#define SVGA_3D_CMD_UPDATE_GB_IMAGE          1101
+#define SVGA_3D_CMD_UPDATE_GB_SURFACE        1102
+#define SVGA_3D_CMD_READBACK_GB_IMAGE        1103
+#define SVGA_3D_CMD_READBACK_GB_SURFACE      1104
+#define SVGA_3D_CMD_INVALIDATE_GB_IMAGE      1105
+#define SVGA_3D_CMD_INVALIDATE_GB_SURFACE    1106
+
+#define SVGA_3D_CMD_DEFINE_GB_CONTEXT        1107
+#define SVGA_3D_CMD_DESTROY_GB_CONTEXT       1108
+#define SVGA_3D_CMD_BIND_GB_CONTEXT          1109
+#define SVGA_3D_CMD_READBACK_GB_CONTEXT      1110
+#define SVGA_3D_CMD_INVALIDATE_GB_CONTEXT    1111
+
+#define SVGA_3D_CMD_DEFINE_GB_SHADER         1112
+#define SVGA_3D_CMD_DESTROY_GB_SHADER        1113
+#define SVGA_3D_CMD_BIND_GB_SHADER           1114
+
+#define SVGA_3D_CMD_SET_OTABLE_BASE64        1115
+
+#define SVGA_3D_CMD_BEGIN_GB_QUERY           1116
+#define SVGA_3D_CMD_END_GB_QUERY             1117
+#define SVGA_3D_CMD_WAIT_FOR_GB_QUERY        1118
+
+#define SVGA_3D_CMD_NOP                      1119
+
+#define SVGA_3D_CMD_ENABLE_GART              1120
+#define SVGA_3D_CMD_DISABLE_GART             1121
+#define SVGA_3D_CMD_MAP_MOB_INTO_GART        1122
+#define SVGA_3D_CMD_UNMAP_GART_RANGE         1123
+
+#define SVGA_3D_CMD_DEFINE_GB_SCREENTARGET   1124
+#define SVGA_3D_CMD_DESTROY_GB_SCREENTARGET  1125
+#define SVGA_3D_CMD_BIND_GB_SCREENTARGET     1126
+#define SVGA_3D_CMD_UPDATE_GB_SCREENTARGET   1127
+
+#define SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL   1128
+#define SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL 1129
+
+#define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE  1130
+
+#define SVGA_3D_CMD_DEFINE_GB_MOB64          1135
+#define SVGA_3D_CMD_REDEFINE_GB_MOB64        1136
+
+#define SVGA_3D_CMD_MAX                      1142
+#define SVGA_3D_CMD_FUTURE_MAX               3000
 
 /*
  * Common substructures used in multiple FIFO commands:
@@ -1749,6 +1919,495 @@ struct {
 } SVGA3dCmdGenerateMipmaps;             /* SVGA_3D_CMD_GENERATE_MIPMAPS */
 
 
+/*
+ * Guest-backed surface definitions.
+ */
+
+typedef uint32 SVGAMobId;
+
+typedef enum SVGAMobFormat {
+   SVGA3D_MOBFMT_INVALID = SVGA3D_INVALID_ID,
+   SVGA3D_MOBFMT_PTDEPTH_0 = 0,
+   SVGA3D_MOBFMT_PTDEPTH_1 = 1,
+   SVGA3D_MOBFMT_PTDEPTH_2 = 2,
+   SVGA3D_MOBFMT_RANGE     = 3,
+   SVGA3D_MOBFMT_PTDEPTH64_0 = 4,
+   SVGA3D_MOBFMT_PTDEPTH64_1 = 5,
+   SVGA3D_MOBFMT_PTDEPTH64_2 = 6,
+   SVGA3D_MOBFMT_MAX,
+} SVGAMobFormat;
+
+/*
+ * Sizes of opaque types.
+ */
+
+#define SVGA3D_OTABLE_MOB_ENTRY_SIZE 16
+#define SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE 8
+#define SVGA3D_OTABLE_SURFACE_ENTRY_SIZE 64
+#define SVGA3D_OTABLE_SHADER_ENTRY_SIZE 16
+#define SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE 64
+#define SVGA3D_CONTEXT_DATA_SIZE 16384
+
+/*
+ * SVGA3dCmdSetOTableBase --
+ *
+ * This command allows the guest to specify the base PPN of the
+ * specified object table.
+ */
+
+typedef enum {
+   SVGA_OTABLE_MOB           = 0,
+   SVGA_OTABLE_MIN           = 0,
+   SVGA_OTABLE_SURFACE       = 1,
+   SVGA_OTABLE_CONTEXT       = 2,
+   SVGA_OTABLE_SHADER        = 3,
+   SVGA_OTABLE_SCREEN_TARGET = 4,
+   SVGA_OTABLE_DX9_MAX       = 5,
+   SVGA_OTABLE_MAX           = 8
+} SVGAOTableType;
+
+typedef
+struct {
+   SVGAOTableType type;
+   PPN baseAddress;
+   uint32 sizeInBytes;
+   uint32 validSizeInBytes;
+   SVGAMobFormat ptDepth;
+}
+__attribute__((__packed__))
+SVGA3dCmdSetOTableBase;  /* SVGA_3D_CMD_SET_OTABLE_BASE */
+
+typedef
+struct {
+   SVGAOTableType type;
+   PPN64 baseAddress;
+   uint32 sizeInBytes;
+   uint32 validSizeInBytes;
+   SVGAMobFormat ptDepth;
+}
+__attribute__((__packed__))
+SVGA3dCmdSetOTableBase64;  /* SVGA_3D_CMD_SET_OTABLE_BASE64 */
+
+typedef
+struct {
+   SVGAOTableType type;
+}
+__attribute__((__packed__))
+SVGA3dCmdReadbackOTable;  /* SVGA_3D_CMD_READBACK_OTABLE */
+
+/*
+ * Define a memory object (Mob) in the OTable.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBMob {
+   SVGAMobId mobid;
+   SVGAMobFormat ptDepth;
+   PPN base;
+   uint32 sizeInBytes;
+}
+__attribute__((__packed__))
+SVGA3dCmdDefineGBMob;   /* SVGA_3D_CMD_DEFINE_GB_MOB */
+
+
+/*
+ * Destroys an object in the OTable.
+ */
+
+typedef
+struct SVGA3dCmdDestroyGBMob {
+   SVGAMobId mobid;
+}
+__attribute__((__packed__))
+SVGA3dCmdDestroyGBMob;   /* SVGA_3D_CMD_DESTROY_GB_MOB */
+
+/*
+ * Redefine an object in the OTable.
+ */
+
+typedef
+struct SVGA3dCmdRedefineGBMob {
+   SVGAMobId mobid;
+   SVGAMobFormat ptDepth;
+   PPN base;
+   uint32 sizeInBytes;
+}
+__attribute__((__packed__))
+SVGA3dCmdRedefineGBMob;   /* SVGA_3D_CMD_REDEFINE_GB_MOB */
+
+/*
+ * Define a memory object (Mob) in the OTable with a PPN64 base.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBMob64 {
+   SVGAMobId mobid;
+   SVGAMobFormat ptDepth;
+   PPN64 base;
+   uint32 sizeInBytes;
+}
+__attribute__((__packed__))
+SVGA3dCmdDefineGBMob64;   /* SVGA_3D_CMD_DEFINE_GB_MOB64 */
+
+/*
+ * Redefine an object in the OTable with PPN64 base.
+ */
+
+typedef
+struct SVGA3dCmdRedefineGBMob64 {
+   SVGAMobId mobid;
+   SVGAMobFormat ptDepth;
+   PPN64 base;
+   uint32 sizeInBytes;
+}
+__attribute__((__packed__))
+SVGA3dCmdRedefineGBMob64;   /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */
+
+/*
+ * Notification that the page tables have been modified.
+ */
+
+typedef
+struct SVGA3dCmdUpdateGBMobMapping {
+   SVGAMobId mobid;
+}
+__attribute__((__packed__))
+SVGA3dCmdUpdateGBMobMapping;   /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */
+
+/*
+ * Define a guest-backed surface.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBSurface {
+   uint32 sid;
+   SVGA3dSurfaceFlags surfaceFlags;
+   SVGA3dSurfaceFormat format;
+   uint32 numMipLevels;
+   uint32 multisampleCount;
+   SVGA3dTextureFilter autogenFilter;
+   SVGA3dSize size;
+} SVGA3dCmdDefineGBSurface;   /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
+
+/*
+ * Destroy a guest-backed surface.
+ */
+
+typedef
+struct SVGA3dCmdDestroyGBSurface {
+   uint32 sid;
+} SVGA3dCmdDestroyGBSurface;   /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
+
+/*
+ * Bind a guest-backed surface to an object.
+ */
+
+typedef
+struct SVGA3dCmdBindGBSurface {
+   uint32 sid;
+   SVGAMobId mobid;
+} SVGA3dCmdBindGBSurface;   /* SVGA_3D_CMD_BIND_GB_SURFACE */
+
+/*
+ * Conditionally bind a mob to a guest backed surface if testMobid
+ * matches the currently bound mob.  Optionally issue a readback on
+ * the surface while it is still bound to the old mobid if the mobid
+ * is changed by this command.
+ */
+
+#define SVGA3D_COND_BIND_GB_SURFACE_FLAG_READBACK (1 << 0)
+
+typedef
+struct{
+   uint32 sid;
+   SVGAMobId testMobid;
+   SVGAMobId mobid;
+   uint32 flags;
+}
+SVGA3dCmdCondBindGBSurface;          /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */
+
+/*
+ * Update an image in a guest-backed surface.
+ * (Inform the device that the guest-contents have been updated.)
+ */
+
+typedef
+struct SVGA3dCmdUpdateGBImage {
+   SVGA3dSurfaceImageId image;
+   SVGA3dBox box;
+} SVGA3dCmdUpdateGBImage;   /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
+
+/*
+ * Update an entire guest-backed surface.
+ * (Inform the device that the guest-contents have been updated.)
+ */
+
+typedef
+struct SVGA3dCmdUpdateGBSurface {
+   uint32 sid;
+} SVGA3dCmdUpdateGBSurface;   /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
+
+/*
+ * Readback an image in a guest-backed surface.
+ * (Request the device to flush the dirty contents into the guest.)
+ */
+
+typedef
+struct SVGA3dCmdReadbackGBImage {
+   SVGA3dSurfaceImageId image;
+} SVGA3dCmdReadbackGBImage;   /* SVGA_3D_CMD_READBACK_GB_IMAGE*/
+
+/*
+ * Readback an entire guest-backed surface.
+ * (Request the device to flush the dirty contents into the guest.)
+ */
+
+typedef
+struct SVGA3dCmdReadbackGBSurface {
+   uint32 sid;
+} SVGA3dCmdReadbackGBSurface;   /* SVGA_3D_CMD_READBACK_GB_SURFACE */
+
+/*
+ * Readback a sub rect of an image in a guest-backed surface.  After
+ * issuing this command the driver is required to issue an update call
+ * of the same region before issuing any other commands that reference
+ * this surface or rendering is not guaranteed.
+ */
+
+typedef
+struct SVGA3dCmdReadbackGBImagePartial {
+   SVGA3dSurfaceImageId image;
+   SVGA3dBox box;
+   uint32 invertBox;
+}
+SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */
+
+/*
+ * Invalidate an image in a guest-backed surface.
+ * (Notify the device that the contents can be lost.)
+ */
+
+typedef
+struct SVGA3dCmdInvalidateGBImage {
+   SVGA3dSurfaceImageId image;
+} SVGA3dCmdInvalidateGBImage;   /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
+
+/*
+ * Invalidate an entire guest-backed surface.
+ * (Notify the device that the contents if all images can be lost.)
+ */
+
+typedef
+struct SVGA3dCmdInvalidateGBSurface {
+   uint32 sid;
+} SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
+
+/*
+ * Invalidate a sub rect of an image in a guest-backed surface.  After
+ * issuing this command the driver is required to issue an update call
+ * of the same region before issuing any other commands that reference
+ * this surface or rendering is not guaranteed.
+ */
+
+typedef
+struct SVGA3dCmdInvalidateGBImagePartial {
+   SVGA3dSurfaceImageId image;
+   SVGA3dBox box;
+   uint32 invertBox;
+}
+SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */
+
+/*
+ * Define a guest-backed context.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBContext {
+   uint32 cid;
+} SVGA3dCmdDefineGBContext;   /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
+
+/*
+ * Destroy a guest-backed context.
+ */
+
+typedef
+struct SVGA3dCmdDestroyGBContext {
+   uint32 cid;
+} SVGA3dCmdDestroyGBContext;   /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
+
+/*
+ * Bind a guest-backed context.
+ *
+ * validContents should be set to 0 for new contexts,
+ * and 1 if this is an old context which is getting paged
+ * back on to the device.
+ *
+ * For new contexts, it is recommended that the driver
+ * issue commands to initialize all interesting state
+ * prior to rendering.
+ */
+
+typedef
+struct SVGA3dCmdBindGBContext {
+   uint32 cid;
+   SVGAMobId mobid;
+   uint32 validContents;
+} SVGA3dCmdBindGBContext;   /* SVGA_3D_CMD_BIND_GB_CONTEXT */
+
+/*
+ * Readback a guest-backed context.
+ * (Request that the device flush the contents back into guest memory.)
+ */
+
+typedef
+struct SVGA3dCmdReadbackGBContext {
+   uint32 cid;
+} SVGA3dCmdReadbackGBContext;   /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
+
+/*
+ * Invalidate a guest-backed context.
+ */
+typedef
+struct SVGA3dCmdInvalidateGBContext {
+   uint32 cid;
+} SVGA3dCmdInvalidateGBContext;   /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
+
+/*
+ * Define a guest-backed shader.
+ */
+
+typedef
+struct SVGA3dCmdDefineGBShader {
+   uint32 shid;
+   SVGA3dShaderType type;
+   uint32 sizeInBytes;
+} SVGA3dCmdDefineGBShader;   /* SVGA_3D_CMD_DEFINE_GB_SHADER */
+
+/*
+ * Bind a guest-backed shader.
+ */
+
+typedef struct SVGA3dCmdBindGBShader {
+   uint32 shid;
+   SVGAMobId mobid;
+   uint32 offsetInBytes;
+} SVGA3dCmdBindGBShader;   /* SVGA_3D_CMD_BIND_GB_SHADER */
+
+/*
+ * Destroy a guest-backed shader.
+ */
+
+typedef struct SVGA3dCmdDestroyGBShader {
+   uint32 shid;
+} SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */
+
+typedef
+struct {
+   uint32                  cid;
+   uint32                  regStart;
+   SVGA3dShaderType        shaderType;
+   SVGA3dShaderConstType   constType;
+
+   /*
+    * Followed by a variable number of shader constants.
+    *
+    * Note that FLOAT and INT constants are 4-dwords in length, while
+    * BOOL constants are 1-dword in length.
+    */
+} SVGA3dCmdSetGBShaderConstInline;
+/* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+} SVGA3dCmdBeginGBQuery;           /* SVGA_3D_CMD_BEGIN_GB_QUERY */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+   SVGAMobId mobid;
+   uint32 offset;
+} SVGA3dCmdEndGBQuery;                  /* SVGA_3D_CMD_END_GB_QUERY */
+
+
+/*
+ * SVGA_3D_CMD_WAIT_FOR_GB_QUERY --
+ *
+ *    The semantics of this command are identical to the
+ *    SVGA_3D_CMD_WAIT_FOR_QUERY except that the results are written
+ *    to a Mob instead of a GMR.
+ */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+   SVGAMobId mobid;
+   uint32 offset;
+} SVGA3dCmdWaitForGBQuery;          /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
+
+typedef
+struct {
+   SVGAMobId mobid;
+   uint32 fbOffset;
+   uint32 initalized;
+}
+SVGA3dCmdEnableGart;              /* SVGA_3D_CMD_ENABLE_GART */
+
+typedef
+struct {
+   SVGAMobId mobid;
+   uint32 gartOffset;
+}
+SVGA3dCmdMapMobIntoGart;          /* SVGA_3D_CMD_MAP_MOB_INTO_GART */
+
+
+typedef
+struct {
+   uint32 gartOffset;
+   uint32 numPages;
+}
+SVGA3dCmdUnmapGartRange;          /* SVGA_3D_CMD_UNMAP_GART_RANGE */
+
+
+/*
+ * Screen Targets
+ */
+#define SVGA_STFLAG_PRIMARY (1 << 0)
+
+typedef
+struct {
+   uint32 stid;
+   uint32 width;
+   uint32 height;
+   int32 xRoot;
+   int32 yRoot;
+   uint32 flags;
+}
+SVGA3dCmdDefineGBScreenTarget;    /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */
+
+typedef
+struct {
+   uint32 stid;
+}
+SVGA3dCmdDestroyGBScreenTarget;  /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */
+
+typedef
+struct {
+   uint32 stid;
+   SVGA3dSurfaceImageId image;
+}
+SVGA3dCmdBindGBScreenTarget;  /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */
+
+typedef
+struct {
+   uint32 stid;
+   SVGA3dBox box;
+}
+SVGA3dCmdUpdateGBScreenTarget;  /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */
+
 /*
  * Capability query index.
  *
@@ -1879,10 +2538,41 @@ typedef enum {
    SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM              = 83,
 
    /*
-    * Don't add new caps into the previous section; the values in this
-    * enumeration must not change. You can put new values right before
-    * SVGA3D_DEVCAP_MAX.
+    * Deprecated.
     */
+   SVGA3D_DEVCAP_VGPU10                            = 84,
+
+   /*
+    * This contains several SVGA_3D_CAPS_VIDEO_DECODE elements
+    * ored together, one for every type of video decoding supported.
+    */
+   SVGA3D_DEVCAP_VIDEO_DECODE                      = 85,
+
+   /*
+    * This contains several SVGA_3D_CAPS_VIDEO_PROCESS elements
+    * ored together, one for every type of video processing supported.
+    */
+   SVGA3D_DEVCAP_VIDEO_PROCESS                     = 86,
+
+   SVGA3D_DEVCAP_LINE_AA                           = 87,  /* boolean */
+   SVGA3D_DEVCAP_LINE_STIPPLE                      = 88,  /* boolean */
+   SVGA3D_DEVCAP_MAX_LINE_WIDTH                    = 89,  /* float */
+   SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH                 = 90,  /* float */
+
+   SVGA3D_DEVCAP_SURFACEFMT_YV12                   = 91,
+
+   /*
+    * Does the host support the SVGA logic ops commands?
+    */
+   SVGA3D_DEVCAP_LOGICOPS                          = 92,
+
+   /*
+    * What support does the host have for screen targets?
+    *
+    * See the SVGA3D_SCREENTARGET_CAP bits below.
+    */
+   SVGA3D_DEVCAP_SCREENTARGETS                     = 93,
+
    SVGA3D_DEVCAP_MAX                                  /* This must be the last index. */
 } SVGA3dDevCapIndex;
 
index 01f63cb49678f6971e5c704bbb67c77cc51df4ed..71defa4d2d7528a247b8e985a7b14cd1197e2a58 100644 (file)
@@ -169,7 +169,10 @@ enum {
    SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
    SVGA_REG_GMRS_MAX_PAGES = 46,    /* Maximum number of 4KB pages for all GMRs */
    SVGA_REG_MEMORY_SIZE = 47,       /* Total dedicated device memory excluding FIFO */
-   SVGA_REG_TOP = 48,               /* Must be 1 more than the last register */
+   SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM = 50,   /* Max primary memory */
+   SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51, /* Suggested limit on mob mem */
+   SVGA_REG_DEV_CAP = 52,           /* Write dev cap index, read value */
+   SVGA_REG_TOP = 53,               /* Must be 1 more than the last register */
 
    SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
    /* Next 768 (== 256*3) registers exist for colormap */
@@ -431,7 +434,10 @@ struct SVGASignedPoint {
 #define SVGA_CAP_TRACES             0x00200000
 #define SVGA_CAP_GMR2               0x00400000
 #define SVGA_CAP_SCREEN_OBJECT_2    0x00800000
-
+#define SVGA_CAP_COMMAND_BUFFERS    0x01000000
+#define SVGA_CAP_DEAD1              0x02000000
+#define SVGA_CAP_CMD_BUFFERS_2      0x04000000
+#define SVGA_CAP_GBOBJECTS          0x08000000
 
 /*
  * FIFO register indices.
index 0489c61524826f2e2b673628783393639f0c591e..6327cfc36805f46364402a004ce76cd9bb19ecd5 100644 (file)
@@ -40,6 +40,10 @@ static uint32_t vram_ne_placement_flags = TTM_PL_FLAG_VRAM |
 static uint32_t sys_placement_flags = TTM_PL_FLAG_SYSTEM |
        TTM_PL_FLAG_CACHED;
 
+static uint32_t sys_ne_placement_flags = TTM_PL_FLAG_SYSTEM |
+       TTM_PL_FLAG_CACHED |
+       TTM_PL_FLAG_NO_EVICT;
+
 static uint32_t gmr_placement_flags = VMW_PL_FLAG_GMR |
        TTM_PL_FLAG_CACHED;
 
@@ -47,6 +51,9 @@ static uint32_t gmr_ne_placement_flags = VMW_PL_FLAG_GMR |
        TTM_PL_FLAG_CACHED |
        TTM_PL_FLAG_NO_EVICT;
 
+static uint32_t mob_placement_flags = VMW_PL_FLAG_MOB |
+       TTM_PL_FLAG_CACHED;
+
 struct ttm_placement vmw_vram_placement = {
        .fpfn = 0,
        .lpfn = 0,
@@ -116,16 +123,26 @@ struct ttm_placement vmw_sys_placement = {
        .busy_placement = &sys_placement_flags
 };
 
+struct ttm_placement vmw_sys_ne_placement = {
+       .fpfn = 0,
+       .lpfn = 0,
+       .num_placement = 1,
+       .placement = &sys_ne_placement_flags,
+       .num_busy_placement = 1,
+       .busy_placement = &sys_ne_placement_flags
+};
+
 static uint32_t evictable_placement_flags[] = {
        TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED,
        TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED,
-       VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED
+       VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED,
+       VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED
 };
 
 struct ttm_placement vmw_evictable_placement = {
        .fpfn = 0,
        .lpfn = 0,
-       .num_placement = 3,
+       .num_placement = 4,
        .placement = evictable_placement_flags,
        .num_busy_placement = 1,
        .busy_placement = &sys_placement_flags
@@ -140,10 +157,21 @@ struct ttm_placement vmw_srf_placement = {
        .busy_placement = gmr_vram_placement_flags
 };
 
+struct ttm_placement vmw_mob_placement = {
+       .fpfn = 0,
+       .lpfn = 0,
+       .num_placement = 1,
+       .num_busy_placement = 1,
+       .placement = &mob_placement_flags,
+       .busy_placement = &mob_placement_flags
+};
+
 struct vmw_ttm_tt {
        struct ttm_dma_tt dma_ttm;
        struct vmw_private *dev_priv;
        int gmr_id;
+       struct vmw_mob *mob;
+       int mem_type;
        struct sg_table sgt;
        struct vmw_sg_table vsgt;
        uint64_t sg_alloc_size;
@@ -244,6 +272,7 @@ void vmw_piter_start(struct vmw_piter *viter, const struct vmw_sg_table *vsgt,
                viter->dma_address = &__vmw_piter_dma_addr;
                viter->page = &__vmw_piter_non_sg_page;
                viter->addrs = vsgt->addrs;
+               viter->pages = vsgt->pages;
                break;
        case vmw_dma_map_populate:
        case vmw_dma_map_bind:
@@ -424,6 +453,63 @@ static void vmw_ttm_unmap_dma(struct vmw_ttm_tt *vmw_tt)
        vmw_tt->mapped = false;
 }
 
+
+/**
+ * vmw_bo_map_dma - Make sure buffer object pages are visible to the device
+ *
+ * @bo: Pointer to a struct ttm_buffer_object
+ *
+ * Wrapper around vmw_ttm_map_dma, that takes a TTM buffer object pointer
+ * instead of a pointer to a struct vmw_ttm_backend as argument.
+ * Note that the buffer object must be either pinned or reserved before
+ * calling this function.
+ */
+int vmw_bo_map_dma(struct ttm_buffer_object *bo)
+{
+       struct vmw_ttm_tt *vmw_tt =
+               container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+
+       return vmw_ttm_map_dma(vmw_tt);
+}
+
+
+/**
+ * vmw_bo_unmap_dma - Make sure buffer object pages are visible to the device
+ *
+ * @bo: Pointer to a struct ttm_buffer_object
+ *
+ * Wrapper around vmw_ttm_unmap_dma, that takes a TTM buffer object pointer
+ * instead of a pointer to a struct vmw_ttm_backend as argument.
+ */
+void vmw_bo_unmap_dma(struct ttm_buffer_object *bo)
+{
+       struct vmw_ttm_tt *vmw_tt =
+               container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+
+       vmw_ttm_unmap_dma(vmw_tt);
+}
+
+
+/**
+ * vmw_bo_sg_table - Return a struct vmw_sg_table object for a
+ * TTM buffer object
+ *
+ * @bo: Pointer to a struct ttm_buffer_object
+ *
+ * Returns a pointer to a struct vmw_sg_table object. The object should
+ * not be freed after use.
+ * Note that for the device addresses to be valid, the buffer object must
+ * either be reserved or pinned.
+ */
+const struct vmw_sg_table *vmw_bo_sg_table(struct ttm_buffer_object *bo)
+{
+       struct vmw_ttm_tt *vmw_tt =
+               container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm);
+
+       return &vmw_tt->vsgt;
+}
+
+
 static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
 {
        struct vmw_ttm_tt *vmw_be =
@@ -435,9 +521,27 @@ static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem)
                return ret;
 
        vmw_be->gmr_id = bo_mem->start;
+       vmw_be->mem_type = bo_mem->mem_type;
+
+       switch (bo_mem->mem_type) {
+       case VMW_PL_GMR:
+               return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt,
+                                   ttm->num_pages, vmw_be->gmr_id);
+       case VMW_PL_MOB:
+               if (unlikely(vmw_be->mob == NULL)) {
+                       vmw_be->mob =
+                               vmw_mob_create(ttm->num_pages);
+                       if (unlikely(vmw_be->mob == NULL))
+                               return -ENOMEM;
+               }
 
-       return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt,
-                           ttm->num_pages, vmw_be->gmr_id);
+               return vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob,
+                                   &vmw_be->vsgt, ttm->num_pages,
+                                   vmw_be->gmr_id);
+       default:
+               BUG();
+       }
+       return 0;
 }
 
 static int vmw_ttm_unbind(struct ttm_tt *ttm)
@@ -445,7 +549,16 @@ static int vmw_ttm_unbind(struct ttm_tt *ttm)
        struct vmw_ttm_tt *vmw_be =
                container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm);
 
-       vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id);
+       switch (vmw_be->mem_type) {
+       case VMW_PL_GMR:
+               vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id);
+               break;
+       case VMW_PL_MOB:
+               vmw_mob_unbind(vmw_be->dev_priv, vmw_be->mob);
+               break;
+       default:
+               BUG();
+       }
 
        if (vmw_be->dev_priv->map_mode == vmw_dma_map_bind)
                vmw_ttm_unmap_dma(vmw_be);
@@ -453,6 +566,7 @@ static int vmw_ttm_unbind(struct ttm_tt *ttm)
        return 0;
 }
 
+
 static void vmw_ttm_destroy(struct ttm_tt *ttm)
 {
        struct vmw_ttm_tt *vmw_be =
@@ -463,9 +577,14 @@ static void vmw_ttm_destroy(struct ttm_tt *ttm)
                ttm_dma_tt_fini(&vmw_be->dma_ttm);
        else
                ttm_tt_fini(ttm);
+
+       if (vmw_be->mob)
+               vmw_mob_destroy(vmw_be->mob);
+
        kfree(vmw_be);
 }
 
+
 static int vmw_ttm_populate(struct ttm_tt *ttm)
 {
        struct vmw_ttm_tt *vmw_tt =
@@ -500,6 +619,12 @@ static void vmw_ttm_unpopulate(struct ttm_tt *ttm)
        struct vmw_private *dev_priv = vmw_tt->dev_priv;
        struct ttm_mem_global *glob = vmw_mem_glob(dev_priv);
 
+
+       if (vmw_tt->mob) {
+               vmw_mob_destroy(vmw_tt->mob);
+               vmw_tt->mob = NULL;
+       }
+
        vmw_ttm_unmap_dma(vmw_tt);
        if (dev_priv->map_mode == vmw_dma_alloc_coherent) {
                size_t size =
@@ -517,7 +642,7 @@ static struct ttm_backend_func vmw_ttm_func = {
        .destroy = vmw_ttm_destroy,
 };
 
-struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,
+static struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,
                                 unsigned long size, uint32_t page_flags,
                                 struct page *dummy_read_page)
 {
@@ -530,6 +655,7 @@ struct ttm_tt *vmw_ttm_tt_create(struct ttm_bo_device *bdev,
 
        vmw_be->dma_ttm.ttm.func = &vmw_ttm_func;
        vmw_be->dev_priv = container_of(bdev, struct vmw_private, bdev);
+       vmw_be->mob = NULL;
 
        if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
                ret = ttm_dma_tt_init(&vmw_be->dma_ttm, bdev, size, page_flags,
@@ -546,12 +672,12 @@ out_no_init:
        return NULL;
 }
 
-int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
+static int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
 {
        return 0;
 }
 
-int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
                      struct ttm_mem_type_manager *man)
 {
        switch (type) {
@@ -571,6 +697,7 @@ int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
                man->default_caching = TTM_PL_FLAG_CACHED;
                break;
        case VMW_PL_GMR:
+       case VMW_PL_MOB:
                /*
                 * "Guest Memory Regions" is an aperture like feature with
                 *  one slot per bo. There is an upper limit of the number of
@@ -589,7 +716,7 @@ int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
        return 0;
 }
 
-void vmw_evict_flags(struct ttm_buffer_object *bo,
+static void vmw_evict_flags(struct ttm_buffer_object *bo,
                     struct ttm_placement *placement)
 {
        *placement = vmw_sys_placement;
@@ -618,6 +745,7 @@ static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg
        switch (mem->mem_type) {
        case TTM_PL_SYSTEM:
        case VMW_PL_GMR:
+       case VMW_PL_MOB:
                return 0;
        case TTM_PL_VRAM:
                mem->bus.offset = mem->start << PAGE_SHIFT;
@@ -677,6 +805,38 @@ static int vmw_sync_obj_wait(void *sync_obj, bool lazy, bool interruptible)
                                  VMW_FENCE_WAIT_TIMEOUT);
 }
 
+/**
+ * vmw_move_notify - TTM move_notify_callback
+ *
+ * @bo:             The TTM buffer object about to move.
+ * @mem:            The truct ttm_mem_reg indicating to what memory
+ *                  region the move is taking place.
+ *
+ * Calls move_notify for all subsystems needing it.
+ * (currently only resources).
+ */
+static void vmw_move_notify(struct ttm_buffer_object *bo,
+                           struct ttm_mem_reg *mem)
+{
+       vmw_resource_move_notify(bo, mem);
+}
+
+
+/**
+ * vmw_swap_notify - TTM move_notify_callback
+ *
+ * @bo:             The TTM buffer object about to be swapped out.
+ */
+static void vmw_swap_notify(struct ttm_buffer_object *bo)
+{
+       struct ttm_bo_device *bdev = bo->bdev;
+
+       spin_lock(&bdev->fence_lock);
+       ttm_bo_wait(bo, false, false, false);
+       spin_unlock(&bdev->fence_lock);
+}
+
+
 struct ttm_bo_driver vmw_bo_driver = {
        .ttm_tt_create = &vmw_ttm_tt_create,
        .ttm_tt_populate = &vmw_ttm_populate,
@@ -691,8 +851,8 @@ struct ttm_bo_driver vmw_bo_driver = {
        .sync_obj_flush = vmw_sync_obj_flush,
        .sync_obj_unref = vmw_sync_obj_unref,
        .sync_obj_ref = vmw_sync_obj_ref,
-       .move_notify = NULL,
-       .swap_notify = NULL,
+       .move_notify = vmw_move_notify,
+       .swap_notify = vmw_swap_notify,
        .fault_reserve_notify = &vmw_ttm_fault_reserve_notify,
        .io_mem_reserve = &vmw_ttm_io_mem_reserve,
        .io_mem_free = &vmw_ttm_io_mem_free,
index 00ae0925aca87e17994288743e079852c0b14dc2..82c41daebc0e35be6fb3629b602a083a6520f6a3 100644 (file)
 struct vmw_user_context {
        struct ttm_base_object base;
        struct vmw_resource res;
+       struct vmw_ctx_binding_state cbs;
 };
 
+
+
+typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *);
+
 static void vmw_user_context_free(struct vmw_resource *res);
 static struct vmw_resource *
 vmw_user_context_base_to_res(struct ttm_base_object *base);
 
+static int vmw_gb_context_create(struct vmw_resource *res);
+static int vmw_gb_context_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf);
+static int vmw_gb_context_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf);
+static int vmw_gb_context_destroy(struct vmw_resource *res);
+static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi);
+static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi);
+static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi);
+static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs);
 static uint64_t vmw_user_context_size;
 
 static const struct vmw_user_resource_conv user_context_conv = {
@@ -62,6 +78,23 @@ static const struct vmw_res_func vmw_legacy_context_func = {
        .unbind = NULL
 };
 
+static const struct vmw_res_func vmw_gb_context_func = {
+       .res_type = vmw_res_context,
+       .needs_backup = true,
+       .may_evict = true,
+       .type_name = "guest backed contexts",
+       .backup_placement = &vmw_mob_placement,
+       .create = vmw_gb_context_create,
+       .destroy = vmw_gb_context_destroy,
+       .bind = vmw_gb_context_bind,
+       .unbind = vmw_gb_context_unbind
+};
+
+static const vmw_scrub_func vmw_scrub_funcs[vmw_ctx_binding_max] = {
+       [vmw_ctx_binding_shader] = vmw_context_scrub_shader,
+       [vmw_ctx_binding_rt] = vmw_context_scrub_render_target,
+       [vmw_ctx_binding_tex] = vmw_context_scrub_texture };
+
 /**
  * Context management:
  */
@@ -76,6 +109,16 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
        } *cmd;
 
 
+       if (res->func->destroy == vmw_gb_context_destroy) {
+               mutex_lock(&dev_priv->cmdbuf_mutex);
+               (void) vmw_gb_context_destroy(res);
+               if (dev_priv->pinned_bo != NULL &&
+                   !dev_priv->query_cid_valid)
+                       __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
+               mutex_unlock(&dev_priv->cmdbuf_mutex);
+               return;
+       }
+
        vmw_execbuf_release_pinned_bo(dev_priv);
        cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
        if (unlikely(cmd == NULL)) {
@@ -92,6 +135,33 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
        vmw_3d_resource_dec(dev_priv, false);
 }
 
+static int vmw_gb_context_init(struct vmw_private *dev_priv,
+                              struct vmw_resource *res,
+                              void (*res_free) (struct vmw_resource *res))
+{
+       int ret;
+       struct vmw_user_context *uctx =
+               container_of(res, struct vmw_user_context, res);
+
+       ret = vmw_resource_init(dev_priv, res, true,
+                               res_free, &vmw_gb_context_func);
+       res->backup_size = SVGA3D_CONTEXT_DATA_SIZE;
+
+       if (unlikely(ret != 0)) {
+               if (res_free)
+                       res_free(res);
+               else
+                       kfree(res);
+               return ret;
+       }
+
+       memset(&uctx->cbs, 0, sizeof(uctx->cbs));
+       INIT_LIST_HEAD(&uctx->cbs.list);
+
+       vmw_resource_activate(res, vmw_hw_context_destroy);
+       return 0;
+}
+
 static int vmw_context_init(struct vmw_private *dev_priv,
                            struct vmw_resource *res,
                            void (*res_free) (struct vmw_resource *res))
@@ -103,6 +173,9 @@ static int vmw_context_init(struct vmw_private *dev_priv,
                SVGA3dCmdDefineContext body;
        } *cmd;
 
+       if (dev_priv->has_mob)
+               return vmw_gb_context_init(dev_priv, res, res_free);
+
        ret = vmw_resource_init(dev_priv, res, false,
                                res_free, &vmw_legacy_context_func);
 
@@ -154,6 +227,184 @@ struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
        return (ret == 0) ? res : NULL;
 }
 
+
+static int vmw_gb_context_create(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       int ret;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineGBContext body;
+       } *cmd;
+
+       if (likely(res->id != -1))
+               return 0;
+
+       ret = vmw_resource_alloc_id(res);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to allocate a context id.\n");
+               goto out_no_id;
+       }
+
+       if (unlikely(res->id >= VMWGFX_NUM_GB_CONTEXT)) {
+               ret = -EBUSY;
+               goto out_no_fifo;
+       }
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for context "
+                         "creation.\n");
+               ret = -ENOMEM;
+               goto out_no_fifo;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DEFINE_GB_CONTEXT;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = res->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       (void) vmw_3d_resource_inc(dev_priv, false);
+
+       return 0;
+
+out_no_fifo:
+       vmw_resource_release_id(res);
+out_no_id:
+       return ret;
+}
+
+static int vmw_gb_context_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBContext body;
+       } *cmd;
+       struct ttm_buffer_object *bo = val_buf->bo;
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for context "
+                         "binding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = res->id;
+       cmd->body.mobid = bo->mem.start;
+       cmd->body.validContents = res->backup_dirty;
+       res->backup_dirty = false;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+static int vmw_gb_context_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct ttm_buffer_object *bo = val_buf->bo;
+       struct vmw_fence_obj *fence;
+       struct vmw_user_context *uctx =
+               container_of(res, struct vmw_user_context, res);
+
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdReadbackGBContext body;
+       } *cmd1;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBContext body;
+       } *cmd2;
+       uint32_t submit_size;
+       uint8_t *cmd;
+
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       mutex_lock(&dev_priv->binding_mutex);
+       vmw_context_binding_state_kill(&uctx->cbs);
+
+       submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
+
+       cmd = vmw_fifo_reserve(dev_priv, submit_size);
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for context "
+                         "unbinding.\n");
+               mutex_unlock(&dev_priv->binding_mutex);
+               return -ENOMEM;
+       }
+
+       cmd2 = (void *) cmd;
+       if (readback) {
+               cmd1 = (void *) cmd;
+               cmd1->header.id = SVGA_3D_CMD_READBACK_GB_CONTEXT;
+               cmd1->header.size = sizeof(cmd1->body);
+               cmd1->body.cid = res->id;
+               cmd2 = (void *) (&cmd1[1]);
+       }
+       cmd2->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
+       cmd2->header.size = sizeof(cmd2->body);
+       cmd2->body.cid = res->id;
+       cmd2->body.mobid = SVGA3D_INVALID_ID;
+
+       vmw_fifo_commit(dev_priv, submit_size);
+       mutex_unlock(&dev_priv->binding_mutex);
+
+       /*
+        * Create a fence object and fence the backup buffer.
+        */
+
+       (void) vmw_execbuf_fence_commands(NULL, dev_priv,
+                                         &fence, NULL);
+
+       vmw_fence_single_bo(bo, fence);
+
+       if (likely(fence != NULL))
+               vmw_fence_obj_unreference(&fence);
+
+       return 0;
+}
+
+static int vmw_gb_context_destroy(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyGBContext body;
+       } *cmd;
+       struct vmw_user_context *uctx =
+               container_of(res, struct vmw_user_context, res);
+
+       BUG_ON(!list_empty(&uctx->cbs.list));
+
+       if (likely(res->id == -1))
+               return 0;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for context "
+                         "destruction.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_CONTEXT;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = res->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       if (dev_priv->query_cid == res->id)
+               dev_priv->query_cid_valid = false;
+       vmw_resource_release_id(res);
+       vmw_3d_resource_dec(dev_priv, false);
+
+       return 0;
+}
+
 /**
  * User-space context management:
  */
@@ -272,3 +523,283 @@ out_unlock:
        return ret;
 
 }
+
+/**
+ * vmw_context_scrub_shader - scrub a shader binding from a context.
+ *
+ * @bi: single binding information.
+ */
+static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_private *dev_priv = bi->ctx->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetShader body;
+       } *cmd;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_SET_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = bi->ctx->id;
+       cmd->body.type = bi->i1.shader_type;
+       cmd->body.shid = SVGA3D_INVALID_ID;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+/**
+ * vmw_context_scrub_render_target - scrub a render target binding
+ * from a context.
+ *
+ * @bi: single binding information.
+ */
+static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_private *dev_priv = bi->ctx->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetRenderTarget body;
+       } *cmd;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for render target "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = bi->ctx->id;
+       cmd->body.type = bi->i1.rt_type;
+       cmd->body.target.sid = SVGA3D_INVALID_ID;
+       cmd->body.target.face = 0;
+       cmd->body.target.mipmap = 0;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+/**
+ * vmw_context_scrub_texture - scrub a texture binding from a context.
+ *
+ * @bi: single binding information.
+ *
+ * TODO: Possibly complement this function with a function that takes
+ * a list of texture bindings and combines them to a single command.
+ */
+static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_private *dev_priv = bi->ctx->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               struct {
+                       SVGA3dCmdSetTextureState c;
+                       SVGA3dTextureState s1;
+               } body;
+       } *cmd;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for texture "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+
+       cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.c.cid = bi->ctx->id;
+       cmd->body.s1.stage = bi->i1.texture_stage;
+       cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
+       cmd->body.s1.value = (uint32) SVGA3D_INVALID_ID;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+/**
+ * vmw_context_binding_drop: Stop tracking a context binding
+ *
+ * @cb: Pointer to binding tracker storage.
+ *
+ * Stops tracking a context binding, and re-initializes its storage.
+ * Typically used when the context binding is replaced with a binding to
+ * another (or the same, for that matter) resource.
+ */
+static void vmw_context_binding_drop(struct vmw_ctx_binding *cb)
+{
+       list_del(&cb->ctx_list);
+       if (!list_empty(&cb->res_list))
+               list_del(&cb->res_list);
+       cb->bi.ctx = NULL;
+}
+
+/**
+ * vmw_context_binding_add: Start tracking a context binding
+ *
+ * @cbs: Pointer to the context binding state tracker.
+ * @bi: Information about the binding to track.
+ *
+ * Performs basic checks on the binding to make sure arguments are within
+ * bounds and then starts tracking the binding in the context binding
+ * state structure @cbs.
+ */
+int vmw_context_binding_add(struct vmw_ctx_binding_state *cbs,
+                           const struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_ctx_binding *loc;
+
+       switch (bi->bt) {
+       case vmw_ctx_binding_rt:
+               if (unlikely((unsigned)bi->i1.rt_type >= SVGA3D_RT_MAX)) {
+                       DRM_ERROR("Illegal render target type %u.\n",
+                                 (unsigned) bi->i1.rt_type);
+                       return -EINVAL;
+               }
+               loc = &cbs->render_targets[bi->i1.rt_type];
+               break;
+       case vmw_ctx_binding_tex:
+               if (unlikely((unsigned)bi->i1.texture_stage >=
+                            SVGA3D_NUM_TEXTURE_UNITS)) {
+                       DRM_ERROR("Illegal texture/sampler unit %u.\n",
+                                 (unsigned) bi->i1.texture_stage);
+                       return -EINVAL;
+               }
+               loc = &cbs->texture_units[bi->i1.texture_stage];
+               break;
+       case vmw_ctx_binding_shader:
+               if (unlikely((unsigned)bi->i1.shader_type >=
+                            SVGA3D_SHADERTYPE_MAX)) {
+                       DRM_ERROR("Illegal shader type %u.\n",
+                                 (unsigned) bi->i1.shader_type);
+                       return -EINVAL;
+               }
+               loc = &cbs->shaders[bi->i1.shader_type];
+               break;
+       default:
+               BUG();
+       }
+
+       if (loc->bi.ctx != NULL)
+               vmw_context_binding_drop(loc);
+
+       loc->bi = *bi;
+       list_add_tail(&loc->ctx_list, &cbs->list);
+       INIT_LIST_HEAD(&loc->res_list);
+
+       return 0;
+}
+
+/**
+ * vmw_context_binding_transfer: Transfer a context binding tracking entry.
+ *
+ * @cbs: Pointer to the persistent context binding state tracker.
+ * @bi: Information about the binding to track.
+ *
+ */
+static void vmw_context_binding_transfer(struct vmw_ctx_binding_state *cbs,
+                                        const struct vmw_ctx_bindinfo *bi)
+{
+       struct vmw_ctx_binding *loc;
+
+       switch (bi->bt) {
+       case vmw_ctx_binding_rt:
+               loc = &cbs->render_targets[bi->i1.rt_type];
+               break;
+       case vmw_ctx_binding_tex:
+               loc = &cbs->texture_units[bi->i1.texture_stage];
+               break;
+       case vmw_ctx_binding_shader:
+               loc = &cbs->shaders[bi->i1.shader_type];
+               break;
+       default:
+               BUG();
+       }
+
+       if (loc->bi.ctx != NULL)
+               vmw_context_binding_drop(loc);
+
+       loc->bi = *bi;
+       list_add_tail(&loc->ctx_list, &cbs->list);
+       if (bi->res != NULL)
+               list_add_tail(&loc->res_list, &bi->res->binding_head);
+       else
+               INIT_LIST_HEAD(&loc->res_list);
+}
+
+/**
+ * vmw_context_binding_kill - Kill a binding on the device
+ * and stop tracking it.
+ *
+ * @cb: Pointer to binding tracker storage.
+ *
+ * Emits FIFO commands to scrub a binding represented by @cb.
+ * Then stops tracking the binding and re-initializes its storage.
+ */
+static void vmw_context_binding_kill(struct vmw_ctx_binding *cb)
+{
+       (void) vmw_scrub_funcs[cb->bi.bt](&cb->bi);
+       vmw_context_binding_drop(cb);
+}
+
+/**
+ * vmw_context_binding_state_kill - Kill all bindings associated with a
+ * struct vmw_ctx_binding state structure, and re-initialize the structure.
+ *
+ * @cbs: Pointer to the context binding state tracker.
+ *
+ * Emits commands to scrub all bindings associated with the
+ * context binding state tracker. Then re-initializes the whole structure.
+ */
+static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs)
+{
+       struct vmw_ctx_binding *entry, *next;
+
+       list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
+               vmw_context_binding_kill(entry);
+}
+
+/**
+ * vmw_context_binding_res_list_kill - Kill all bindings on a
+ * resource binding list
+ *
+ * @head: list head of resource binding list
+ *
+ * Kills all bindings associated with a specific resource. Typically
+ * called before the resource is destroyed.
+ */
+void vmw_context_binding_res_list_kill(struct list_head *head)
+{
+       struct vmw_ctx_binding *entry, *next;
+
+       list_for_each_entry_safe(entry, next, head, res_list)
+               vmw_context_binding_kill(entry);
+}
+
+/**
+ * vmw_context_binding_state_transfer - Commit staged binding info
+ *
+ * @ctx: Pointer to context to commit the staged binding info to.
+ * @from: Staged binding info built during execbuf.
+ *
+ * Transfers binding info from a temporary structure to the persistent
+ * structure in the context. This can be done once commands
+ */
+void vmw_context_binding_state_transfer(struct vmw_resource *ctx,
+                                       struct vmw_ctx_binding_state *from)
+{
+       struct vmw_user_context *uctx =
+               container_of(ctx, struct vmw_user_context, res);
+       struct vmw_ctx_binding *entry, *next;
+
+       list_for_each_entry_safe(entry, next, &from->list, ctx_list)
+               vmw_context_binding_transfer(&uctx->cbs, &entry->bi);
+}
index d4e54fcc0acd3e778bd74d1488f898798c740c73..a75840211b3c9682da3be63df8a54385de238824 100644 (file)
@@ -290,8 +290,7 @@ void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo,
 /**
  * vmw_bo_pin - Pin or unpin a buffer object without moving it.
  *
- * @bo: The buffer object. Must be reserved, and present either in VRAM
- * or GMR memory.
+ * @bo: The buffer object. Must be reserved.
  * @pin: Whether to pin or unpin.
  *
  */
@@ -303,10 +302,9 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
        int ret;
 
        lockdep_assert_held(&bo->resv->lock.base);
-       BUG_ON(old_mem_type != TTM_PL_VRAM &&
-              old_mem_type != VMW_PL_GMR);
 
-       pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
+       pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB
+               | TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED;
        if (pin)
                pl_flags |= TTM_PL_FLAG_NO_EVICT;
 
index c7a549694e59fb2614562627dcb7f167680babcd..9893328f8fdc04750ec78538c4cdb2ba89ddae30 100644 (file)
 #define DRM_IOCTL_VMW_UPDATE_LAYOUT                            \
        DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT,       \
                 struct drm_vmw_update_layout_arg)
+#define DRM_IOCTL_VMW_CREATE_SHADER                            \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_CREATE_SHADER,      \
+                struct drm_vmw_shader_create_arg)
+#define DRM_IOCTL_VMW_UNREF_SHADER                             \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_SHADER,        \
+                struct drm_vmw_shader_arg)
+#define DRM_IOCTL_VMW_GB_SURFACE_CREATE                                \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_CREATE,  \
+                union drm_vmw_gb_surface_create_arg)
+#define DRM_IOCTL_VMW_GB_SURFACE_REF                           \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_REF,     \
+                union drm_vmw_gb_surface_reference_arg)
+#define DRM_IOCTL_VMW_SYNCCPU                                  \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_SYNCCPU,             \
+                struct drm_vmw_synccpu_arg)
 
 /**
  * The core DRM version of this macro doesn't account for
@@ -177,6 +192,21 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
        VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
                      vmw_kms_update_layout_ioctl,
                      DRM_MASTER | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_CREATE_SHADER,
+                     vmw_shader_define_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_UNREF_SHADER,
+                     vmw_shader_destroy_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
+                     vmw_gb_surface_define_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
+                     vmw_gb_surface_reference_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
+       VMW_IOCTL_DEF(VMW_SYNCCPU,
+                     vmw_user_dmabuf_synccpu_ioctl,
+                     DRM_AUTH | DRM_UNLOCKED),
 };
 
 static struct pci_device_id vmw_pci_id_list[] = {
@@ -189,6 +219,7 @@ static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);
 static int vmw_force_iommu;
 static int vmw_restrict_iommu;
 static int vmw_force_coherent;
+static int vmw_restrict_dma_mask;
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
@@ -203,6 +234,8 @@ MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages");
 module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
 MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
 module_param_named(force_coherent, vmw_force_coherent, int, 0600);
+MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU");
+module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600);
 
 
 static void vmw_print_capabilities(uint32_t capabilities)
@@ -240,38 +273,52 @@ static void vmw_print_capabilities(uint32_t capabilities)
                DRM_INFO("  GMR2.\n");
        if (capabilities & SVGA_CAP_SCREEN_OBJECT_2)
                DRM_INFO("  Screen Object 2.\n");
+       if (capabilities & SVGA_CAP_COMMAND_BUFFERS)
+               DRM_INFO("  Command Buffers.\n");
+       if (capabilities & SVGA_CAP_CMD_BUFFERS_2)
+               DRM_INFO("  Command Buffers 2.\n");
+       if (capabilities & SVGA_CAP_GBOBJECTS)
+               DRM_INFO("  Guest Backed Resources.\n");
 }
 
-
 /**
- * vmw_execbuf_prepare_dummy_query - Initialize a query result structure at
- * the start of a buffer object.
+ * vmw_dummy_query_bo_create - create a bo to hold a dummy query result
  *
- * @dev_priv: The device private structure.
+ * @dev_priv: A device private structure.
  *
- * This function will idle the buffer using an uninterruptible wait, then
- * map the first page and initialize a pending occlusion query result structure,
- * Finally it will unmap the buffer.
+ * This function creates a small buffer object that holds the query
+ * result for dummy queries emitted as query barriers.
+ * The function will then map the first page and initialize a pending
+ * occlusion query result structure, Finally it will unmap the buffer.
+ * No interruptible waits are done within this function.
  *
- * TODO: Since we're only mapping a single page, we should optimize the map
- * to use kmap_atomic / iomap_atomic.
+ * Returns an error if bo creation or initialization fails.
  */
-static void vmw_dummy_query_bo_prepare(struct vmw_private *dev_priv)
+static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
 {
+       int ret;
+       struct ttm_buffer_object *bo;
        struct ttm_bo_kmap_obj map;
        volatile SVGA3dQueryResult *result;
        bool dummy;
-       int ret;
-       struct ttm_bo_device *bdev = &dev_priv->bdev;
-       struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
 
-       ttm_bo_reserve(bo, false, false, false, 0);
-       spin_lock(&bdev->fence_lock);
-       ret = ttm_bo_wait(bo, false, false, false);
-       spin_unlock(&bdev->fence_lock);
+       /*
+        * Create the bo as pinned, so that a tryreserve will
+        * immediately succeed. This is because we're the only
+        * user of the bo currently.
+        */
+       ret = ttm_bo_create(&dev_priv->bdev,
+                           PAGE_SIZE,
+                           ttm_bo_type_device,
+                           &vmw_sys_ne_placement,
+                           0, false, NULL,
+                           &bo);
+
        if (unlikely(ret != 0))
-               (void) vmw_fallback_wait(dev_priv, false, true, 0, false,
-                                        10*HZ);
+               return ret;
+
+       ret = ttm_bo_reserve(bo, false, true, false, 0);
+       BUG_ON(ret != 0);
 
        ret = ttm_bo_kmap(bo, 0, 1, &map);
        if (likely(ret == 0)) {
@@ -280,34 +327,19 @@ static void vmw_dummy_query_bo_prepare(struct vmw_private *dev_priv)
                result->state = SVGA3D_QUERYSTATE_PENDING;
                result->result32 = 0xff;
                ttm_bo_kunmap(&map);
-       } else
-               DRM_ERROR("Dummy query buffer map failed.\n");
+       }
+       vmw_bo_pin(bo, false);
        ttm_bo_unreserve(bo);
-}
 
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Dummy query buffer map failed.\n");
+               ttm_bo_unref(&bo);
+       } else
+               dev_priv->dummy_query_bo = bo;
 
-/**
- * vmw_dummy_query_bo_create - create a bo to hold a dummy query result
- *
- * @dev_priv: A device private structure.
- *
- * This function creates a small buffer object that holds the query
- * result for dummy queries emitted as query barriers.
- * No interruptible waits are done within this function.
- *
- * Returns an error if bo creation fails.
- */
-static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
-{
-       return ttm_bo_create(&dev_priv->bdev,
-                            PAGE_SIZE,
-                            ttm_bo_type_device,
-                            &vmw_vram_sys_placement,
-                            0, false, NULL,
-                            &dev_priv->dummy_query_bo);
+       return ret;
 }
 
-
 static int vmw_request_device(struct vmw_private *dev_priv)
 {
        int ret;
@@ -318,14 +350,24 @@ static int vmw_request_device(struct vmw_private *dev_priv)
                return ret;
        }
        vmw_fence_fifo_up(dev_priv->fman);
+       if (dev_priv->has_mob) {
+               ret = vmw_otables_setup(dev_priv);
+               if (unlikely(ret != 0)) {
+                       DRM_ERROR("Unable to initialize "
+                                 "guest Memory OBjects.\n");
+                       goto out_no_mob;
+               }
+       }
        ret = vmw_dummy_query_bo_create(dev_priv);
        if (unlikely(ret != 0))
                goto out_no_query_bo;
-       vmw_dummy_query_bo_prepare(dev_priv);
 
        return 0;
 
 out_no_query_bo:
+       if (dev_priv->has_mob)
+               vmw_otables_takedown(dev_priv);
+out_no_mob:
        vmw_fence_fifo_down(dev_priv->fman);
        vmw_fifo_release(dev_priv, &dev_priv->fifo);
        return ret;
@@ -341,10 +383,13 @@ static void vmw_release_device(struct vmw_private *dev_priv)
        BUG_ON(dev_priv->pinned_bo != NULL);
 
        ttm_bo_unref(&dev_priv->dummy_query_bo);
+       if (dev_priv->has_mob)
+               vmw_otables_takedown(dev_priv);
        vmw_fence_fifo_down(dev_priv->fman);
        vmw_fifo_release(dev_priv, &dev_priv->fifo);
 }
 
+
 /**
  * Increase the 3d resource refcount.
  * If the count was prevously zero, initialize the fifo, switching to svga
@@ -510,6 +555,33 @@ out_fixup:
        return 0;
 }
 
+/**
+ * vmw_dma_masks - set required page- and dma masks
+ *
+ * @dev: Pointer to struct drm-device
+ *
+ * With 32-bit we can only handle 32 bit PFNs. Optionally set that
+ * restriction also for 64-bit systems.
+ */
+#ifdef CONFIG_INTEL_IOMMU
+static int vmw_dma_masks(struct vmw_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+
+       if (intel_iommu_enabled &&
+           (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
+               DRM_INFO("Restricting DMA addresses to 44 bits.\n");
+               return dma_set_mask(dev->dev, DMA_BIT_MASK(44));
+       }
+       return 0;
+}
+#else
+static int vmw_dma_masks(struct vmw_private *dev_priv)
+{
+       return 0;
+}
+#endif
+
 static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
        struct vmw_private *dev_priv;
@@ -532,6 +604,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        mutex_init(&dev_priv->hw_mutex);
        mutex_init(&dev_priv->cmdbuf_mutex);
        mutex_init(&dev_priv->release_mutex);
+       mutex_init(&dev_priv->binding_mutex);
        rwlock_init(&dev_priv->resource_lock);
 
        for (i = vmw_res_context; i < vmw_res_max; ++i) {
@@ -578,14 +651,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 
        vmw_get_initial_size(dev_priv);
 
-       if (dev_priv->capabilities & SVGA_CAP_GMR) {
-               dev_priv->max_gmr_descriptors =
-                       vmw_read(dev_priv,
-                                SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
+       if (dev_priv->capabilities & SVGA_CAP_GMR2) {
                dev_priv->max_gmr_ids =
                        vmw_read(dev_priv, SVGA_REG_GMR_MAX_IDS);
-       }
-       if (dev_priv->capabilities & SVGA_CAP_GMR2) {
                dev_priv->max_gmr_pages =
                        vmw_read(dev_priv, SVGA_REG_GMRS_MAX_PAGES);
                dev_priv->memory_size =
@@ -598,23 +666,42 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                 */
                dev_priv->memory_size = 512*1024*1024;
        }
+       dev_priv->max_mob_pages = 0;
+       if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
+               uint64_t mem_size =
+                       vmw_read(dev_priv,
+                                SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);
+
+               dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
+               dev_priv->prim_bb_mem =
+                       vmw_read(dev_priv,
+                                SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
+       } else
+               dev_priv->prim_bb_mem = dev_priv->vram_size;
+
+       ret = vmw_dma_masks(dev_priv);
+       if (unlikely(ret != 0)) {
+               mutex_unlock(&dev_priv->hw_mutex);
+               goto out_err0;
+       }
+
+       if (unlikely(dev_priv->prim_bb_mem < dev_priv->vram_size))
+               dev_priv->prim_bb_mem = dev_priv->vram_size;
 
        mutex_unlock(&dev_priv->hw_mutex);
 
        vmw_print_capabilities(dev_priv->capabilities);
 
-       if (dev_priv->capabilities & SVGA_CAP_GMR) {
+       if (dev_priv->capabilities & SVGA_CAP_GMR2) {
                DRM_INFO("Max GMR ids is %u\n",
                         (unsigned)dev_priv->max_gmr_ids);
-               DRM_INFO("Max GMR descriptors is %u\n",
-                        (unsigned)dev_priv->max_gmr_descriptors);
-       }
-       if (dev_priv->capabilities & SVGA_CAP_GMR2) {
                DRM_INFO("Max number of GMR pages is %u\n",
                         (unsigned)dev_priv->max_gmr_pages);
                DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n",
                         (unsigned)dev_priv->memory_size / 1024);
        }
+       DRM_INFO("Maximum display memory size is %u kiB\n",
+                dev_priv->prim_bb_mem / 1024);
        DRM_INFO("VRAM at 0x%08x size is %u kiB\n",
                 dev_priv->vram_start, dev_priv->vram_size / 1024);
        DRM_INFO("MMIO at 0x%08x size is %u kiB\n",
@@ -649,12 +736,22 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        dev_priv->has_gmr = true;
        if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
            refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR,
-                                        dev_priv->max_gmr_ids) != 0) {
+                                        VMW_PL_GMR) != 0) {
                DRM_INFO("No GMR memory available. "
                         "Graphics memory resources are very limited.\n");
                dev_priv->has_gmr = false;
        }
 
+       if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
+               dev_priv->has_mob = true;
+               if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB,
+                                  VMW_PL_MOB) != 0) {
+                       DRM_INFO("No MOB memory available. "
+                                "3D will be disabled.\n");
+                       dev_priv->has_mob = false;
+               }
+       }
+
        dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start,
                                               dev_priv->mmio_size);
 
@@ -757,6 +854,8 @@ out_err4:
        iounmap(dev_priv->mmio_virt);
 out_err3:
        arch_phys_wc_del(dev_priv->mmio_mtrr);
+       if (dev_priv->has_mob)
+               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
        if (dev_priv->has_gmr)
                (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
        (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
@@ -801,6 +900,8 @@ static int vmw_driver_unload(struct drm_device *dev)
        ttm_object_device_release(&dev_priv->tdev);
        iounmap(dev_priv->mmio_virt);
        arch_phys_wc_del(dev_priv->mmio_mtrr);
+       if (dev_priv->has_mob)
+               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
        if (dev_priv->has_gmr)
                (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
        (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
index 20890ad8408bb5ef377c4ff54c80397c3105efaf..554e7fa330824cc7a2f1d728f4299c19c8ab8fb5 100644 (file)
@@ -40,9 +40,9 @@
 #include <drm/ttm/ttm_module.h>
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20120209"
+#define VMWGFX_DRIVER_DATE "20121114"
 #define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 4
+#define VMWGFX_DRIVER_MINOR 5
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
 #define VMWGFX_MAX_VALIDATIONS 2048
 #define VMWGFX_MAX_DISPLAYS 16
 #define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768
+#define VMWGFX_ENABLE_SCREEN_TARGET_OTABLE 0
+
+/*
+ * Perhaps we should have sysfs entries for these.
+ */
+#define VMWGFX_NUM_GB_CONTEXT 256
+#define VMWGFX_NUM_GB_SHADER 20000
+#define VMWGFX_NUM_GB_SURFACE 32768
+#define VMWGFX_NUM_GB_SCREEN_TARGET VMWGFX_MAX_DISPLAYS
+#define VMWGFX_NUM_MOB (VMWGFX_NUM_GB_CONTEXT +\
+                       VMWGFX_NUM_GB_SHADER +\
+                       VMWGFX_NUM_GB_SURFACE +\
+                       VMWGFX_NUM_GB_SCREEN_TARGET)
 
 #define VMW_PL_GMR TTM_PL_PRIV0
 #define VMW_PL_FLAG_GMR TTM_PL_FLAG_PRIV0
+#define VMW_PL_MOB TTM_PL_PRIV1
+#define VMW_PL_FLAG_MOB TTM_PL_FLAG_PRIV1
 
 #define VMW_RES_CONTEXT ttm_driver_type0
 #define VMW_RES_SURFACE ttm_driver_type1
 #define VMW_RES_STREAM ttm_driver_type2
 #define VMW_RES_FENCE ttm_driver_type3
+#define VMW_RES_SHADER ttm_driver_type4
 
 struct vmw_fpriv {
        struct drm_master *locked_master;
@@ -82,6 +98,7 @@ struct vmw_dma_buffer {
 struct vmw_validate_buffer {
        struct ttm_validate_buffer base;
        struct drm_hash_item hash;
+       bool validate_as_mob;
 };
 
 struct vmw_res_func;
@@ -98,6 +115,7 @@ struct vmw_resource {
        const struct vmw_res_func *func;
        struct list_head lru_head; /* Protected by the resource lock */
        struct list_head mob_head; /* Protected by @backup reserved */
+       struct list_head binding_head; /* Protected by binding_mutex */
        void (*res_free) (struct vmw_resource *res);
        void (*hw_destroy) (struct vmw_resource *res);
 };
@@ -106,6 +124,7 @@ enum vmw_res_type {
        vmw_res_context,
        vmw_res_surface,
        vmw_res_stream,
+       vmw_res_shader,
        vmw_res_max
 };
 
@@ -154,6 +173,7 @@ struct vmw_fifo_state {
 };
 
 struct vmw_relocation {
+       SVGAMobId *mob_loc;
        SVGAGuestPtr *location;
        uint32_t index;
 };
@@ -229,6 +249,71 @@ struct vmw_piter {
        struct page *(*page)(struct vmw_piter *);
 };
 
+/*
+ * enum vmw_ctx_binding_type - abstract resource to context binding types
+ */
+enum vmw_ctx_binding_type {
+       vmw_ctx_binding_shader,
+       vmw_ctx_binding_rt,
+       vmw_ctx_binding_tex,
+       vmw_ctx_binding_max
+};
+
+/**
+ * struct vmw_ctx_bindinfo - structure representing a single context binding
+ *
+ * @ctx: Pointer to the context structure. NULL means the binding is not
+ * active.
+ * @res: Non ref-counted pointer to the bound resource.
+ * @bt: The binding type.
+ * @i1: Union of information needed to unbind.
+ */
+struct vmw_ctx_bindinfo {
+       struct vmw_resource *ctx;
+       struct vmw_resource *res;
+       enum vmw_ctx_binding_type bt;
+       union {
+               SVGA3dShaderType shader_type;
+               SVGA3dRenderTargetType rt_type;
+               uint32 texture_stage;
+       } i1;
+};
+
+/**
+ * struct vmw_ctx_binding - structure representing a single context binding
+ *                        - suitable for tracking in a context
+ *
+ * @ctx_list: List head for context.
+ * @res_list: List head for bound resource.
+ * @bi: Binding info
+ */
+struct vmw_ctx_binding {
+       struct list_head ctx_list;
+       struct list_head res_list;
+       struct vmw_ctx_bindinfo bi;
+};
+
+
+/**
+ * struct vmw_ctx_binding_state - context binding state
+ *
+ * @list: linked list of individual bindings.
+ * @render_targets: Render target bindings.
+ * @texture_units: Texture units/samplers bindings.
+ * @shaders: Shader bindings.
+ *
+ * Note that this structure also provides storage space for the individual
+ * struct vmw_ctx_binding objects, so that no dynamic allocation is needed
+ * for individual bindings.
+ *
+ */
+struct vmw_ctx_binding_state {
+       struct list_head list;
+       struct vmw_ctx_binding render_targets[SVGA3D_RT_MAX];
+       struct vmw_ctx_binding texture_units[SVGA3D_NUM_TEXTURE_UNITS];
+       struct vmw_ctx_binding shaders[SVGA3D_SHADERTYPE_MAX];
+};
+
 struct vmw_sw_context{
        struct drm_open_hash res_ht;
        bool res_ht_initialized;
@@ -250,6 +335,7 @@ struct vmw_sw_context{
        struct vmw_resource *last_query_ctx;
        bool needs_post_query_barrier;
        struct vmw_resource *error_resource;
+       struct vmw_ctx_binding_state staged_bindings;
 };
 
 struct vmw_legacy_display;
@@ -281,6 +367,7 @@ struct vmw_private {
        unsigned int io_start;
        uint32_t vram_start;
        uint32_t vram_size;
+       uint32_t prim_bb_mem;
        uint32_t mmio_start;
        uint32_t mmio_size;
        uint32_t fb_max_width;
@@ -290,11 +377,12 @@ struct vmw_private {
        __le32 __iomem *mmio_virt;
        int mmio_mtrr;
        uint32_t capabilities;
-       uint32_t max_gmr_descriptors;
        uint32_t max_gmr_ids;
        uint32_t max_gmr_pages;
+       uint32_t max_mob_pages;
        uint32_t memory_size;
        bool has_gmr;
+       bool has_mob;
        struct mutex hw_mutex;
 
        /*
@@ -370,6 +458,7 @@ struct vmw_private {
 
        struct vmw_sw_context ctx;
        struct mutex cmdbuf_mutex;
+       struct mutex binding_mutex;
 
        /**
         * Operating mode.
@@ -415,6 +504,12 @@ struct vmw_private {
         * DMA mapping stuff.
         */
        enum vmw_dma_map_mode map_mode;
+
+       /*
+        * Guest Backed stuff
+        */
+       struct ttm_buffer_object *otable_bo;
+       struct vmw_otable *otables;
 };
 
 static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
@@ -471,23 +566,12 @@ extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id);
  * Resource utilities - vmwgfx_resource.c
  */
 struct vmw_user_resource_conv;
-extern const struct vmw_user_resource_conv *user_surface_converter;
-extern const struct vmw_user_resource_conv *user_context_converter;
 
-extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv);
 extern void vmw_resource_unreference(struct vmw_resource **p_res);
 extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
 extern int vmw_resource_validate(struct vmw_resource *res);
 extern int vmw_resource_reserve(struct vmw_resource *res, bool no_backup);
 extern bool vmw_resource_needs_backup(const struct vmw_resource *res);
-extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
-                                    struct drm_file *file_priv);
-extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv);
-extern int vmw_context_check(struct vmw_private *dev_priv,
-                            struct ttm_object_file *tfile,
-                            int id,
-                            struct vmw_resource **p_res);
 extern int vmw_user_lookup_handle(struct vmw_private *dev_priv,
                                  struct ttm_object_file *tfile,
                                  uint32_t handle,
@@ -499,18 +583,6 @@ extern int vmw_user_resource_lookup_handle(
        uint32_t handle,
        const struct vmw_user_resource_conv *converter,
        struct vmw_resource **p_res);
-extern void vmw_surface_res_free(struct vmw_resource *res);
-extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
-                                    struct drm_file *file_priv);
-extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv);
-extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
-                                      struct drm_file *file_priv);
-extern int vmw_surface_check(struct vmw_private *dev_priv,
-                            struct ttm_object_file *tfile,
-                            uint32_t handle, int *id);
-extern int vmw_surface_validate(struct vmw_private *dev_priv,
-                               struct vmw_surface *srf);
 extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
 extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
                           struct vmw_dma_buffer *vmw_bo,
@@ -519,10 +591,21 @@ extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
                           void (*bo_free) (struct ttm_buffer_object *bo));
 extern int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
                                  struct ttm_object_file *tfile);
+extern int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
+                                struct ttm_object_file *tfile,
+                                uint32_t size,
+                                bool shareable,
+                                uint32_t *handle,
+                                struct vmw_dma_buffer **p_dma_buf);
+extern int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
+                                    struct vmw_dma_buffer *dma_buf,
+                                    uint32_t *handle);
 extern int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
 extern int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
+extern int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data,
+                                        struct drm_file *file_priv);
 extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
                                         uint32_t cur_validate_node);
 extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo);
@@ -622,10 +705,16 @@ extern struct ttm_placement vmw_vram_sys_placement;
 extern struct ttm_placement vmw_vram_gmr_placement;
 extern struct ttm_placement vmw_vram_gmr_ne_placement;
 extern struct ttm_placement vmw_sys_placement;
+extern struct ttm_placement vmw_sys_ne_placement;
 extern struct ttm_placement vmw_evictable_placement;
 extern struct ttm_placement vmw_srf_placement;
+extern struct ttm_placement vmw_mob_placement;
 extern struct ttm_bo_driver vmw_bo_driver;
 extern int vmw_dma_quiescent(struct drm_device *dev);
+extern int vmw_bo_map_dma(struct ttm_buffer_object *bo);
+extern void vmw_bo_unmap_dma(struct ttm_buffer_object *bo);
+extern const struct vmw_sg_table *
+vmw_bo_sg_table(struct ttm_buffer_object *bo);
 extern void vmw_piter_start(struct vmw_piter *viter,
                            const struct vmw_sg_table *vsgt,
                            unsigned long p_offs);
@@ -701,7 +790,7 @@ extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
  * IRQs and wating - vmwgfx_irq.c
  */
 
-extern irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS);
+extern irqreturn_t vmw_irq_handler(int irq, void *arg);
 extern int vmw_wait_seqno(struct vmw_private *dev_priv, bool lazy,
                             uint32_t seqno, bool interruptible,
                             unsigned long timeout);
@@ -832,6 +921,76 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev,
                                  uint32_t handle, uint32_t flags,
                                  int *prime_fd);
 
+/*
+ * MemoryOBject management -  vmwgfx_mob.c
+ */
+struct vmw_mob;
+extern int vmw_mob_bind(struct vmw_private *dev_priv, struct vmw_mob *mob,
+                       const struct vmw_sg_table *vsgt,
+                       unsigned long num_data_pages, int32_t mob_id);
+extern void vmw_mob_unbind(struct vmw_private *dev_priv,
+                          struct vmw_mob *mob);
+extern void vmw_mob_destroy(struct vmw_mob *mob);
+extern struct vmw_mob *vmw_mob_create(unsigned long data_pages);
+extern int vmw_otables_setup(struct vmw_private *dev_priv);
+extern void vmw_otables_takedown(struct vmw_private *dev_priv);
+
+/*
+ * Context management - vmwgfx_context.c
+ */
+
+extern const struct vmw_user_resource_conv *user_context_converter;
+
+extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv);
+
+extern int vmw_context_check(struct vmw_private *dev_priv,
+                            struct ttm_object_file *tfile,
+                            int id,
+                            struct vmw_resource **p_res);
+extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
+                                    struct drm_file *file_priv);
+extern int vmw_context_binding_add(struct vmw_ctx_binding_state *cbs,
+                                  const struct vmw_ctx_bindinfo *ci);
+extern void
+vmw_context_binding_state_transfer(struct vmw_resource *res,
+                                  struct vmw_ctx_binding_state *cbs);
+extern void vmw_context_binding_res_list_kill(struct list_head *head);
+
+/*
+ * Surface management - vmwgfx_surface.c
+ */
+
+extern const struct vmw_user_resource_conv *user_surface_converter;
+
+extern void vmw_surface_res_free(struct vmw_resource *res);
+extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
+                                    struct drm_file *file_priv);
+extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
+                                      struct drm_file *file_priv);
+extern int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
+                                      struct drm_file *file_priv);
+extern int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
+                                         struct drm_file *file_priv);
+extern int vmw_surface_check(struct vmw_private *dev_priv,
+                            struct ttm_object_file *tfile,
+                            uint32_t handle, int *id);
+extern int vmw_surface_validate(struct vmw_private *dev_priv,
+                               struct vmw_surface *srf);
+
+/*
+ * Shader management - vmwgfx_shader.c
+ */
+
+extern const struct vmw_user_resource_conv *user_shader_converter;
+
+extern int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv);
+extern int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
 
 /**
  * Inline helper functions
index 599f6469a1ebb00c10b3d8047c44882aebd779d8..7a5f1eb55c5a0ad09adf8aa02c92367908c49c24 100644 (file)
@@ -54,6 +54,8 @@ struct vmw_resource_relocation {
  * @res: Ref-counted pointer to the resource.
  * @switch_backup: Boolean whether to switch backup buffer on unreserve.
  * @new_backup: Refcounted pointer to the new backup buffer.
+ * @staged_bindings: If @res is a context, tracks bindings set up during
+ * the command batch. Otherwise NULL.
  * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll.
  * @first_usage: Set to true the first time the resource is referenced in
  * the command stream.
@@ -65,11 +67,31 @@ struct vmw_resource_val_node {
        struct drm_hash_item hash;
        struct vmw_resource *res;
        struct vmw_dma_buffer *new_backup;
+       struct vmw_ctx_binding_state *staged_bindings;
        unsigned long new_backup_offset;
        bool first_usage;
        bool no_buffer_needed;
 };
 
+/**
+ * struct vmw_cmd_entry - Describe a command for the verifier
+ *
+ * @user_allow: Whether allowed from the execbuf ioctl.
+ * @gb_disable: Whether disabled if guest-backed objects are available.
+ * @gb_enable: Whether enabled iff guest-backed objects are available.
+ */
+struct vmw_cmd_entry {
+       int (*func) (struct vmw_private *, struct vmw_sw_context *,
+                    SVGA3dCmdHeader *);
+       bool user_allow;
+       bool gb_disable;
+       bool gb_enable;
+};
+
+#define VMW_CMD_DEF(_cmd, _func, _user_allow, _gb_disable, _gb_enable) \
+       [(_cmd) - SVGA_3D_CMD_BASE] = {(_func), (_user_allow),\
+                                      (_gb_disable), (_gb_enable)}
+
 /**
  * vmw_resource_unreserve - unreserve resources previously reserved for
  * command submission.
@@ -87,6 +109,16 @@ static void vmw_resource_list_unreserve(struct list_head *list,
                struct vmw_dma_buffer *new_backup =
                        backoff ? NULL : val->new_backup;
 
+               /*
+                * Transfer staged context bindings to the
+                * persistent context binding tracker.
+                */
+               if (unlikely(val->staged_bindings)) {
+                       vmw_context_binding_state_transfer
+                               (val->res, val->staged_bindings);
+                       kfree(val->staged_bindings);
+                       val->staged_bindings = NULL;
+               }
                vmw_resource_unreserve(res, new_backup,
                        val->new_backup_offset);
                vmw_dmabuf_unreference(&val->new_backup);
@@ -224,6 +256,7 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
  *
  * @sw_context: The software context used for this command submission batch.
  * @bo: The buffer object to add.
+ * @validate_as_mob: Validate this buffer as a MOB.
  * @p_val_node: If non-NULL Will be updated with the validate node number
  * on return.
  *
@@ -232,6 +265,7 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
  */
 static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
                                   struct ttm_buffer_object *bo,
+                                  bool validate_as_mob,
                                   uint32_t *p_val_node)
 {
        uint32_t val_node;
@@ -244,6 +278,10 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
                                    &hash) == 0)) {
                vval_buf = container_of(hash, struct vmw_validate_buffer,
                                        hash);
+               if (unlikely(vval_buf->validate_as_mob != validate_as_mob)) {
+                       DRM_ERROR("Inconsistent buffer usage.\n");
+                       return -EINVAL;
+               }
                val_buf = &vval_buf->base;
                val_node = vval_buf - sw_context->val_bufs;
        } else {
@@ -266,6 +304,7 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
                val_buf->bo = ttm_bo_reference(bo);
                val_buf->reserved = false;
                list_add_tail(&val_buf->head, &sw_context->validate_nodes);
+               vval_buf->validate_as_mob = validate_as_mob;
        }
 
        sw_context->fence_flags |= DRM_VMW_FENCE_FLAG_EXEC;
@@ -302,7 +341,8 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context)
                        struct ttm_buffer_object *bo = &res->backup->base;
 
                        ret = vmw_bo_to_validate_list
-                               (sw_context, bo, NULL);
+                               (sw_context, bo,
+                                vmw_resource_needs_backup(res), NULL);
 
                        if (unlikely(ret != 0))
                                return ret;
@@ -362,8 +402,15 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv,
        struct vmw_resource_val_node *node;
        int ret;
 
-       if (*id == SVGA3D_INVALID_ID)
+       if (*id == SVGA3D_INVALID_ID) {
+               if (p_val)
+                       *p_val = NULL;
+               if (res_type == vmw_res_context) {
+                       DRM_ERROR("Illegal context invalid id.\n");
+                       return -EINVAL;
+               }
                return 0;
+       }
 
        /*
         * Fastpath in case of repeated commands referencing the same
@@ -411,6 +458,18 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv,
        rcache->node = node;
        if (p_val)
                *p_val = node;
+
+       if (node->first_usage && res_type == vmw_res_context) {
+               node->staged_bindings =
+                       kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
+               if (node->staged_bindings == NULL) {
+                       DRM_ERROR("Failed to allocate context binding "
+                                 "information.\n");
+                       goto out_no_reloc;
+               }
+               INIT_LIST_HEAD(&node->staged_bindings->list);
+       }
+
        vmw_resource_unreference(&res);
        return 0;
 
@@ -453,17 +512,35 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
                SVGA3dCmdHeader header;
                SVGA3dCmdSetRenderTarget body;
        } *cmd;
+       struct vmw_resource_val_node *ctx_node;
+       struct vmw_resource_val_node *res_node;
        int ret;
 
-       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       cmd = container_of(header, struct vmw_sid_cmd, header);
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->body.cid,
+                               &ctx_node);
        if (unlikely(ret != 0))
                return ret;
 
-       cmd = container_of(header, struct vmw_sid_cmd, header);
        ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                user_surface_converter,
-                               &cmd->body.target.sid, NULL);
-       return ret;
+                               &cmd->body.target.sid, &res_node);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (dev_priv->has_mob) {
+               struct vmw_ctx_bindinfo bi;
+
+               bi.ctx = ctx_node->res;
+               bi.res = res_node ? res_node->res : NULL;
+               bi.bt = vmw_ctx_binding_rt;
+               bi.i1.rt_type = cmd->body.type;
+               return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
+       }
+
+       return 0;
 }
 
 static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
@@ -519,11 +596,6 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
 
-       if (unlikely(!sw_context->kernel)) {
-               DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
-               return -EPERM;
-       }
-
        return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                 user_surface_converter,
                                 &cmd->body.srcImage.sid, NULL);
@@ -541,11 +613,6 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
 
        cmd = container_of(header, struct vmw_sid_cmd, header);
 
-       if (unlikely(!sw_context->kernel)) {
-               DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id);
-               return -EPERM;
-       }
-
        return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                 user_surface_converter, &cmd->body.sid,
                                 NULL);
@@ -586,7 +653,7 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
                        sw_context->needs_post_query_barrier = true;
                        ret = vmw_bo_to_validate_list(sw_context,
                                                      sw_context->cur_query_bo,
-                                                     NULL);
+                                                     dev_priv->has_mob, NULL);
                        if (unlikely(ret != 0))
                                return ret;
                }
@@ -594,7 +661,7 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
 
                ret = vmw_bo_to_validate_list(sw_context,
                                              dev_priv->dummy_query_bo,
-                                             NULL);
+                                             dev_priv->has_mob, NULL);
                if (unlikely(ret != 0))
                        return ret;
 
@@ -671,6 +738,66 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
        }
 }
 
+/**
+ * vmw_translate_mob_pointer - Prepare to translate a user-space buffer
+ * handle to a MOB id.
+ *
+ * @dev_priv: Pointer to a device private structure.
+ * @sw_context: The software context used for this command batch validation.
+ * @id: Pointer to the user-space handle to be translated.
+ * @vmw_bo_p: Points to a location that, on successful return will carry
+ * a reference-counted pointer to the DMA buffer identified by the
+ * user-space handle in @id.
+ *
+ * This function saves information needed to translate a user-space buffer
+ * handle to a MOB id. The translation does not take place immediately, but
+ * during a call to vmw_apply_relocations(). This function builds a relocation
+ * list and a list of buffers to validate. The former needs to be freed using
+ * either vmw_apply_relocations() or vmw_free_relocations(). The latter
+ * needs to be freed using vmw_clear_validations.
+ */
+static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
+                                struct vmw_sw_context *sw_context,
+                                SVGAMobId *id,
+                                struct vmw_dma_buffer **vmw_bo_p)
+{
+       struct vmw_dma_buffer *vmw_bo = NULL;
+       struct ttm_buffer_object *bo;
+       uint32_t handle = *id;
+       struct vmw_relocation *reloc;
+       int ret;
+
+       ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Could not find or use MOB buffer.\n");
+               return -EINVAL;
+       }
+       bo = &vmw_bo->base;
+
+       if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
+               DRM_ERROR("Max number relocations per submission"
+                         " exceeded\n");
+               ret = -EINVAL;
+               goto out_no_reloc;
+       }
+
+       reloc = &sw_context->relocs[sw_context->cur_reloc++];
+       reloc->mob_loc = id;
+       reloc->location = NULL;
+
+       ret = vmw_bo_to_validate_list(sw_context, bo, true, &reloc->index);
+       if (unlikely(ret != 0))
+               goto out_no_reloc;
+
+       *vmw_bo_p = vmw_bo;
+       return 0;
+
+out_no_reloc:
+       vmw_dmabuf_unreference(&vmw_bo);
+       vmw_bo_p = NULL;
+       return ret;
+}
+
 /**
  * vmw_translate_guest_pointer - Prepare to translate a user-space buffer
  * handle to a valid SVGAGuestPtr
@@ -718,7 +845,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
        reloc = &sw_context->relocs[sw_context->cur_reloc++];
        reloc->location = ptr;
 
-       ret = vmw_bo_to_validate_list(sw_context, bo, &reloc->index);
+       ret = vmw_bo_to_validate_list(sw_context, bo, false, &reloc->index);
        if (unlikely(ret != 0))
                goto out_no_reloc;
 
@@ -731,6 +858,30 @@ out_no_reloc:
        return ret;
 }
 
+/**
+ * vmw_cmd_begin_gb_query - validate a  SVGA_3D_CMD_BEGIN_GB_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_begin_gb_query(struct vmw_private *dev_priv,
+                                 struct vmw_sw_context *sw_context,
+                                 SVGA3dCmdHeader *header)
+{
+       struct vmw_begin_gb_query_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBeginGBQuery q;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_begin_gb_query_cmd,
+                          header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                                user_context_converter, &cmd->q.cid,
+                                NULL);
+}
+
 /**
  * vmw_cmd_begin_query - validate a  SVGA_3D_CMD_BEGIN_QUERY command.
  *
@@ -750,11 +901,63 @@ static int vmw_cmd_begin_query(struct vmw_private *dev_priv,
        cmd = container_of(header, struct vmw_begin_query_cmd,
                           header);
 
+       if (unlikely(dev_priv->has_mob)) {
+               struct {
+                       SVGA3dCmdHeader header;
+                       SVGA3dCmdBeginGBQuery q;
+               } gb_cmd;
+
+               BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
+
+               gb_cmd.header.id = SVGA_3D_CMD_BEGIN_GB_QUERY;
+               gb_cmd.header.size = cmd->header.size;
+               gb_cmd.q.cid = cmd->q.cid;
+               gb_cmd.q.type = cmd->q.type;
+
+               memcpy(cmd, &gb_cmd, sizeof(*cmd));
+               return vmw_cmd_begin_gb_query(dev_priv, sw_context, header);
+       }
+
        return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
                                 user_context_converter, &cmd->q.cid,
                                 NULL);
 }
 
+/**
+ * vmw_cmd_end_gb_query - validate a  SVGA_3D_CMD_END_GB_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_end_gb_query(struct vmw_private *dev_priv,
+                               struct vmw_sw_context *sw_context,
+                               SVGA3dCmdHeader *header)
+{
+       struct vmw_dma_buffer *vmw_bo;
+       struct vmw_query_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdEndGBQuery q;
+       } *cmd;
+       int ret;
+
+       cmd = container_of(header, struct vmw_query_cmd, header);
+       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = vmw_translate_mob_ptr(dev_priv, sw_context,
+                                   &cmd->q.mobid,
+                                   &vmw_bo);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = vmw_query_bo_switch_prepare(dev_priv, &vmw_bo->base, sw_context);
+
+       vmw_dmabuf_unreference(&vmw_bo);
+       return ret;
+}
+
 /**
  * vmw_cmd_end_query - validate a  SVGA_3D_CMD_END_QUERY command.
  *
@@ -774,6 +977,25 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv,
        int ret;
 
        cmd = container_of(header, struct vmw_query_cmd, header);
+       if (dev_priv->has_mob) {
+               struct {
+                       SVGA3dCmdHeader header;
+                       SVGA3dCmdEndGBQuery q;
+               } gb_cmd;
+
+               BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
+
+               gb_cmd.header.id = SVGA_3D_CMD_END_GB_QUERY;
+               gb_cmd.header.size = cmd->header.size;
+               gb_cmd.q.cid = cmd->q.cid;
+               gb_cmd.q.type = cmd->q.type;
+               gb_cmd.q.mobid = cmd->q.guestResult.gmrId;
+               gb_cmd.q.offset = cmd->q.guestResult.offset;
+
+               memcpy(cmd, &gb_cmd, sizeof(*cmd));
+               return vmw_cmd_end_gb_query(dev_priv, sw_context, header);
+       }
+
        ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
        if (unlikely(ret != 0))
                return ret;
@@ -790,7 +1012,40 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv,
        return ret;
 }
 
-/*
+/**
+ * vmw_cmd_wait_gb_query - validate a  SVGA_3D_CMD_WAIT_GB_QUERY command.
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context used for this command submission.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv,
+                                struct vmw_sw_context *sw_context,
+                                SVGA3dCmdHeader *header)
+{
+       struct vmw_dma_buffer *vmw_bo;
+       struct vmw_query_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdWaitForGBQuery q;
+       } *cmd;
+       int ret;
+
+       cmd = container_of(header, struct vmw_query_cmd, header);
+       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = vmw_translate_mob_ptr(dev_priv, sw_context,
+                                   &cmd->q.mobid,
+                                   &vmw_bo);
+       if (unlikely(ret != 0))
+               return ret;
+
+       vmw_dmabuf_unreference(&vmw_bo);
+       return 0;
+}
+
+/**
  * vmw_cmd_wait_query - validate a  SVGA_3D_CMD_WAIT_QUERY command.
  *
  * @dev_priv: Pointer to a device private struct.
@@ -809,6 +1064,25 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
        int ret;
 
        cmd = container_of(header, struct vmw_query_cmd, header);
+       if (dev_priv->has_mob) {
+               struct {
+                       SVGA3dCmdHeader header;
+                       SVGA3dCmdWaitForGBQuery q;
+               } gb_cmd;
+
+               BUG_ON(sizeof(gb_cmd) != sizeof(*cmd));
+
+               gb_cmd.header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY;
+               gb_cmd.header.size = cmd->header.size;
+               gb_cmd.q.cid = cmd->q.cid;
+               gb_cmd.q.type = cmd->q.type;
+               gb_cmd.q.mobid = cmd->q.guestResult.gmrId;
+               gb_cmd.q.offset = cmd->q.guestResult.offset;
+
+               memcpy(cmd, &gb_cmd, sizeof(*cmd));
+               return vmw_cmd_wait_gb_query(dev_priv, sw_context, header);
+       }
+
        ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
        if (unlikely(ret != 0))
                return ret;
@@ -921,15 +1195,22 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
        struct vmw_tex_state_cmd {
                SVGA3dCmdHeader header;
                SVGA3dCmdSetTextureState state;
-       };
+       } *cmd;
 
        SVGA3dTextureState *last_state = (SVGA3dTextureState *)
          ((unsigned long) header + header->size + sizeof(header));
        SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
                ((unsigned long) header + sizeof(struct vmw_tex_state_cmd));
+       struct vmw_resource_val_node *ctx_node;
+       struct vmw_resource_val_node *res_node;
        int ret;
 
-       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       cmd = container_of(header, struct vmw_tex_state_cmd,
+                          header);
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->state.cid,
+                               &ctx_node);
        if (unlikely(ret != 0))
                return ret;
 
@@ -939,9 +1220,20 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
 
                ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                        user_surface_converter,
-                                       &cur_state->value, NULL);
+                                       &cur_state->value, &res_node);
                if (unlikely(ret != 0))
                        return ret;
+
+               if (dev_priv->has_mob) {
+                       struct vmw_ctx_bindinfo bi;
+
+                       bi.ctx = ctx_node->res;
+                       bi.res = res_node ? res_node->res : NULL;
+                       bi.bt = vmw_ctx_binding_tex;
+                       bi.i1.texture_stage = cur_state->stage;
+                       vmw_context_binding_add(ctx_node->staged_bindings,
+                                               &bi);
+               }
        }
 
        return 0;
@@ -970,6 +1262,222 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
        return ret;
 }
 
+/**
+ * vmw_cmd_switch_backup - Utility function to handle backup buffer switching
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @res_type: The resource type.
+ * @converter: Information about user-space binding for this resource type.
+ * @res_id: Pointer to the user-space resource handle in the command stream.
+ * @buf_id: Pointer to the user-space backup buffer handle in the command
+ * stream.
+ * @backup_offset: Offset of backup into MOB.
+ *
+ * This function prepares for registering a switch of backup buffers
+ * in the resource metadata just prior to unreserving.
+ */
+static int vmw_cmd_switch_backup(struct vmw_private *dev_priv,
+                                struct vmw_sw_context *sw_context,
+                                enum vmw_res_type res_type,
+                                const struct vmw_user_resource_conv
+                                *converter,
+                                uint32_t *res_id,
+                                uint32_t *buf_id,
+                                unsigned long backup_offset)
+{
+       int ret;
+       struct vmw_dma_buffer *dma_buf;
+       struct vmw_resource_val_node *val_node;
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, res_type,
+                               converter, res_id, &val_node);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &dma_buf);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (val_node->first_usage)
+               val_node->no_buffer_needed = true;
+
+       vmw_dmabuf_unreference(&val_node->new_backup);
+       val_node->new_backup = dma_buf;
+       val_node->new_backup_offset = backup_offset;
+
+       return 0;
+}
+
+/**
+ * vmw_cmd_bind_gb_surface - Validate an SVGA_3D_CMD_BIND_GB_SURFACE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_bind_gb_surface(struct vmw_private *dev_priv,
+                                  struct vmw_sw_context *sw_context,
+                                  SVGA3dCmdHeader *header)
+{
+       struct vmw_bind_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBSurface body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_bind_gb_surface_cmd, header);
+
+       return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_surface,
+                                    user_surface_converter,
+                                    &cmd->body.sid, &cmd->body.mobid,
+                                    0);
+}
+
+/**
+ * vmw_cmd_update_gb_image - Validate an SVGA_3D_CMD_UPDATE_GB_IMAGE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_update_gb_image(struct vmw_private *dev_priv,
+                                  struct vmw_sw_context *sw_context,
+                                  SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdUpdateGBImage body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.image.sid, NULL);
+}
+
+/**
+ * vmw_cmd_update_gb_surface - Validate an SVGA_3D_CMD_UPDATE_GB_SURFACE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_update_gb_surface(struct vmw_private *dev_priv,
+                                    struct vmw_sw_context *sw_context,
+                                    SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdUpdateGBSurface body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.sid, NULL);
+}
+
+/**
+ * vmw_cmd_readback_gb_image - Validate an SVGA_3D_CMD_READBACK_GB_IMAGE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_readback_gb_image(struct vmw_private *dev_priv,
+                                    struct vmw_sw_context *sw_context,
+                                    SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdReadbackGBImage body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.image.sid, NULL);
+}
+
+/**
+ * vmw_cmd_readback_gb_surface - Validate an SVGA_3D_CMD_READBACK_GB_SURFACE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_readback_gb_surface(struct vmw_private *dev_priv,
+                                      struct vmw_sw_context *sw_context,
+                                      SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdReadbackGBSurface body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.sid, NULL);
+}
+
+/**
+ * vmw_cmd_invalidate_gb_image - Validate an SVGA_3D_CMD_INVALIDATE_GB_IMAGE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_invalidate_gb_image(struct vmw_private *dev_priv,
+                                      struct vmw_sw_context *sw_context,
+                                      SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdInvalidateGBImage body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.image.sid, NULL);
+}
+
+/**
+ * vmw_cmd_invalidate_gb_surface - Validate an
+ * SVGA_3D_CMD_INVALIDATE_GB_SURFACE command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_invalidate_gb_surface(struct vmw_private *dev_priv,
+                                        struct vmw_sw_context *sw_context,
+                                        SVGA3dCmdHeader *header)
+{
+       struct vmw_gb_surface_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdInvalidateGBSurface body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_gb_surface_cmd, header);
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.sid, NULL);
+}
+
 /**
  * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER
  * command
@@ -986,18 +1494,64 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
                SVGA3dCmdHeader header;
                SVGA3dCmdSetShader body;
        } *cmd;
+       struct vmw_resource_val_node *ctx_node;
        int ret;
 
        cmd = container_of(header, struct vmw_set_shader_cmd,
                           header);
 
-       ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->body.cid,
+                               &ctx_node);
        if (unlikely(ret != 0))
                return ret;
 
+       if (dev_priv->has_mob) {
+               struct vmw_ctx_bindinfo bi;
+               struct vmw_resource_val_node *res_node;
+
+               ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_shader,
+                                       user_shader_converter,
+                                       &cmd->body.shid, &res_node);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               bi.ctx = ctx_node->res;
+               bi.res = res_node ? res_node->res : NULL;
+               bi.bt = vmw_ctx_binding_shader;
+               bi.i1.shader_type = cmd->body.type;
+               return vmw_context_binding_add(ctx_node->staged_bindings, &bi);
+       }
+
        return 0;
 }
 
+/**
+ * vmw_cmd_bind_gb_shader - Validate an SVGA_3D_CMD_BIND_GB_SHADER
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_bind_gb_shader(struct vmw_private *dev_priv,
+                                 struct vmw_sw_context *sw_context,
+                                 SVGA3dCmdHeader *header)
+{
+       struct vmw_bind_gb_shader_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBShader body;
+       } *cmd;
+
+       cmd = container_of(header, struct vmw_bind_gb_shader_cmd,
+                          header);
+
+       return vmw_cmd_switch_backup(dev_priv, sw_context, vmw_res_shader,
+                                    user_shader_converter,
+                                    &cmd->body.shid, &cmd->body.mobid,
+                                    cmd->body.offsetInBytes);
+}
+
 static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
                                struct vmw_sw_context *sw_context,
                                void *buf, uint32_t *size)
@@ -1041,50 +1595,173 @@ static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
        return 0;
 }
 
-typedef int (*vmw_cmd_func) (struct vmw_private *,
-                            struct vmw_sw_context *,
-                            SVGA3dCmdHeader *);
-
-#define VMW_CMD_DEF(cmd, func) \
-       [cmd - SVGA_3D_CMD_BASE] = func
-
-static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma),
-       VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check),
+static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check,
+                   true, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET,
-                   &vmw_cmd_set_render_target_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader),
-       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw),
-       VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query),
-       VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query),
-       VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query),
-       VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok),
+                   &vmw_cmd_set_render_target_check, true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check,
+                   true, true, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check,
+                   true, true, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check,
+                   true, true, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok,
+                   true, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN,
-                   &vmw_cmd_blt_surf_screen_check),
-       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid),
-       VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid),
+                   &vmw_cmd_blt_surf_screen_check, false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SCREEN_DMA, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_UNITY_SURFACE_COOKIE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_OPEN_CONTEXT_SURFACE, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_BITBLT, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_TRANSBLT, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_STRETCHBLT, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_COLORFILL, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_ALPHABLEND, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_OTABLE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_MOB, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_MOB, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_REDEFINE_GB_MOB, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SURFACE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SURFACE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SURFACE, &vmw_cmd_bind_gb_surface,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_COND_BIND_GB_SURFACE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_IMAGE, &vmw_cmd_update_gb_image,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SURFACE,
+                   &vmw_cmd_update_gb_surface, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE,
+                   &vmw_cmd_readback_gb_image, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_SURFACE,
+                   &vmw_cmd_readback_gb_surface, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE,
+                   &vmw_cmd_invalidate_gb_image, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_SURFACE,
+                   &vmw_cmd_invalidate_gb_surface, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SHADER, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SHADER, &vmw_cmd_bind_gb_shader,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SHADER, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_OTABLE_BASE64, &vmw_cmd_invalid,
+                   false, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_GB_QUERY, &vmw_cmd_begin_gb_query,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_END_GB_QUERY, &vmw_cmd_end_gb_query,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_GB_QUERY, &vmw_cmd_wait_gb_query,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_NOP, &vmw_cmd_ok,
+                   true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_ENABLE_GART, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DISABLE_GART, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_MAP_MOB_INTO_GART, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UNMAP_GART_RANGE, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_BIND_GB_SCREENTARGET, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL, &vmw_cmd_invalid,
+                   false, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE, &vmw_cmd_cid_check,
+                   true, false, true)
 };
 
 static int vmw_cmd_check(struct vmw_private *dev_priv,
@@ -1095,6 +1772,8 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
        uint32_t size_remaining = *size;
        SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
        int ret;
+       const struct vmw_cmd_entry *entry;
+       bool gb = dev_priv->capabilities & SVGA_CAP_GBOBJECTS;
 
        cmd_id = le32_to_cpu(((uint32_t *)buf)[0]);
        /* Handle any none 3D commands */
@@ -1107,18 +1786,40 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
 
        cmd_id -= SVGA_3D_CMD_BASE;
        if (unlikely(*size > size_remaining))
-               goto out_err;
+               goto out_invalid;
 
        if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE))
-               goto out_err;
+               goto out_invalid;
+
+       entry = &vmw_cmd_entries[cmd_id];
+       if (unlikely(!entry->user_allow && !sw_context->kernel))
+               goto out_privileged;
 
-       ret = vmw_cmd_funcs[cmd_id](dev_priv, sw_context, header);
+       if (unlikely(entry->gb_disable && gb))
+               goto out_old;
+
+       if (unlikely(entry->gb_enable && !gb))
+               goto out_new;
+
+       ret = entry->func(dev_priv, sw_context, header);
        if (unlikely(ret != 0))
-               goto out_err;
+               goto out_invalid;
 
        return 0;
-out_err:
-       DRM_ERROR("Illegal / Invalid SVGA3D command: %d\n",
+out_invalid:
+       DRM_ERROR("Invalid SVGA3D command: %d\n",
+                 cmd_id + SVGA_3D_CMD_BASE);
+       return -EINVAL;
+out_privileged:
+       DRM_ERROR("Privileged SVGA3D command: %d\n",
+                 cmd_id + SVGA_3D_CMD_BASE);
+       return -EPERM;
+out_old:
+       DRM_ERROR("Deprecated (disallowed) SVGA3D command: %d\n",
+                 cmd_id + SVGA_3D_CMD_BASE);
+       return -EINVAL;
+out_new:
+       DRM_ERROR("SVGA3D command: %d not supported by virtual hardware.\n",
                  cmd_id + SVGA_3D_CMD_BASE);
        return -EINVAL;
 }
@@ -1174,6 +1875,9 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
                case VMW_PL_GMR:
                        reloc->location->gmrId = bo->mem.start;
                        break;
+               case VMW_PL_MOB:
+                       *reloc->mob_loc = bo->mem.start;
+                       break;
                default:
                        BUG();
                }
@@ -1198,6 +1902,8 @@ static void vmw_resource_list_unreference(struct list_head *list)
        list_for_each_entry_safe(val, val_next, list, head) {
                list_del_init(&val->head);
                vmw_resource_unreference(&val->res);
+               if (unlikely(val->staged_bindings))
+                       kfree(val->staged_bindings);
                kfree(val);
        }
 }
@@ -1224,7 +1930,8 @@ static void vmw_clear_validations(struct vmw_sw_context *sw_context)
 }
 
 static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
-                                     struct ttm_buffer_object *bo)
+                                     struct ttm_buffer_object *bo,
+                                     bool validate_as_mob)
 {
        int ret;
 
@@ -1238,6 +1945,9 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
             dev_priv->dummy_query_bo_pinned))
                return 0;
 
+       if (validate_as_mob)
+               return ttm_bo_validate(bo, &vmw_mob_placement, true, false);
+
        /**
         * Put BO in VRAM if there is space, otherwise as a GMR.
         * If there is no space in VRAM and GMR ids are all used up,
@@ -1259,7 +1969,6 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
        return ret;
 }
 
-
 static int vmw_validate_buffers(struct vmw_private *dev_priv,
                                struct vmw_sw_context *sw_context)
 {
@@ -1267,7 +1976,8 @@ static int vmw_validate_buffers(struct vmw_private *dev_priv,
        int ret;
 
        list_for_each_entry(entry, &sw_context->validate_nodes, base.head) {
-               ret = vmw_validate_single_buffer(dev_priv, entry->base.bo);
+               ret = vmw_validate_single_buffer(dev_priv, entry->base.bo,
+                                                entry->validate_as_mob);
                if (unlikely(ret != 0))
                        return ret;
        }
@@ -1509,11 +2219,17 @@ int vmw_execbuf_process(struct drm_file *file_priv,
                        goto out_err;
        }
 
+       ret = mutex_lock_interruptible(&dev_priv->binding_mutex);
+       if (unlikely(ret != 0)) {
+               ret = -ERESTARTSYS;
+               goto out_err;
+       }
+
        cmd = vmw_fifo_reserve(dev_priv, command_size);
        if (unlikely(cmd == NULL)) {
                DRM_ERROR("Failed reserving fifo space for commands.\n");
                ret = -ENOMEM;
-               goto out_err;
+               goto out_unlock_binding;
        }
 
        vmw_apply_relocations(sw_context);
@@ -1538,6 +2254,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
                DRM_ERROR("Fence submission error. Syncing.\n");
 
        vmw_resource_list_unreserve(&sw_context->resource_list, false);
+       mutex_unlock(&dev_priv->binding_mutex);
+
        ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
                                    (void *) fence);
 
@@ -1568,6 +2286,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 
        return 0;
 
+out_unlock_binding:
+       mutex_unlock(&dev_priv->binding_mutex);
 out_err:
        vmw_resource_relocations_free(&sw_context->res_relocations);
        vmw_free_relocations(sw_context);
index c62d20e8a6f169cce1173c849b42f160c55a4f39..436b013b42316a06296dd62cb0dda23f5095c075 100644 (file)
@@ -271,7 +271,7 @@ void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p)
        spin_unlock_irq(&fman->lock);
 }
 
-void vmw_fences_perform_actions(struct vmw_fence_manager *fman,
+static void vmw_fences_perform_actions(struct vmw_fence_manager *fman,
                                struct list_head *list)
 {
        struct vmw_fence_action *action, *next_action;
@@ -897,7 +897,7 @@ static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action)
  * Note that the action callbacks may be executed before this function
  * returns.
  */
-void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
+static void vmw_fence_obj_add_action(struct vmw_fence_obj *fence,
                              struct vmw_fence_action *action)
 {
        struct vmw_fence_manager *fman = fence->fman;
@@ -993,7 +993,7 @@ struct vmw_event_fence_pending {
        struct drm_vmw_event_fence event;
 };
 
-int vmw_event_fence_action_create(struct drm_file *file_priv,
+static int vmw_event_fence_action_create(struct drm_file *file_priv,
                                  struct vmw_fence_obj *fence,
                                  uint32_t flags,
                                  uint64_t user_data,
@@ -1080,7 +1080,8 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
         */
        if (arg->handle) {
                struct ttm_base_object *base =
-                       ttm_base_object_lookup(vmw_fp->tfile, arg->handle);
+                       ttm_base_object_lookup_for_ref(dev_priv->tdev,
+                                                      arg->handle);
 
                if (unlikely(base == NULL)) {
                        DRM_ERROR("Fence event invalid fence object handle "
index 3eb148667d6382f003969757db0b9dd26555f909..6ccd993e26bf4ead66d0e8d1f1b4b592856d7599 100644 (file)
@@ -35,6 +35,23 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
        uint32_t fifo_min, hwversion;
        const struct vmw_fifo_state *fifo = &dev_priv->fifo;
 
+       if (!(dev_priv->capabilities & SVGA_CAP_3D))
+               return false;
+
+       if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
+               uint32_t result;
+
+               if (!dev_priv->has_mob)
+                       return false;
+
+               mutex_lock(&dev_priv->hw_mutex);
+               vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_3D);
+               result = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+               mutex_unlock(&dev_priv->hw_mutex);
+
+               return (result != 0);
+       }
+
        if (!(dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO))
                return false;
 
@@ -511,24 +528,16 @@ out_err:
 }
 
 /**
- * vmw_fifo_emit_dummy_query - emits a dummy query to the fifo.
+ * vmw_fifo_emit_dummy_legacy_query - emits a dummy query to the fifo using
+ * legacy query commands.
  *
  * @dev_priv: The device private structure.
  * @cid: The hardware context id used for the query.
  *
- * This function is used to emit a dummy occlusion query with
- * no primitives rendered between query begin and query end.
- * It's used to provide a query barrier, in order to know that when
- * this query is finished, all preceding queries are also finished.
- *
- * A Query results structure should have been initialized at the start
- * of the dev_priv->dummy_query_bo buffer object. And that buffer object
- * must also be either reserved or pinned when this function is called.
- *
- * Returns -ENOMEM on failure to reserve fifo space.
+ * See the vmw_fifo_emit_dummy_query documentation.
  */
-int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
-                             uint32_t cid)
+static int vmw_fifo_emit_dummy_legacy_query(struct vmw_private *dev_priv,
+                                           uint32_t cid)
 {
        /*
         * A query wait without a preceding query end will
@@ -566,3 +575,75 @@ int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
 
        return 0;
 }
+
+/**
+ * vmw_fifo_emit_dummy_gb_query - emits a dummy query to the fifo using
+ * guest-backed resource query commands.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context id used for the query.
+ *
+ * See the vmw_fifo_emit_dummy_query documentation.
+ */
+static int vmw_fifo_emit_dummy_gb_query(struct vmw_private *dev_priv,
+                                       uint32_t cid)
+{
+       /*
+        * A query wait without a preceding query end will
+        * actually finish all queries for this cid
+        * without writing to the query result structure.
+        */
+
+       struct ttm_buffer_object *bo = dev_priv->dummy_query_bo;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdWaitForGBQuery body;
+       } *cmd;
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Out of fifo space for dummy query.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_WAIT_FOR_GB_QUERY;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.cid = cid;
+       cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION;
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+       cmd->body.mobid = bo->mem.start;
+       cmd->body.offset = 0;
+
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+
+/**
+ * vmw_fifo_emit_dummy_gb_query - emits a dummy query to the fifo using
+ * appropriate resource query commands.
+ *
+ * @dev_priv: The device private structure.
+ * @cid: The hardware context id used for the query.
+ *
+ * This function is used to emit a dummy occlusion query with
+ * no primitives rendered between query begin and query end.
+ * It's used to provide a query barrier, in order to know that when
+ * this query is finished, all preceding queries are also finished.
+ *
+ * A Query results structure should have been initialized at the start
+ * of the dev_priv->dummy_query_bo buffer object. And that buffer object
+ * must also be either reserved or pinned when this function is called.
+ *
+ * Returns -ENOMEM on failure to reserve fifo space.
+ */
+int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv,
+                             uint32_t cid)
+{
+       if (dev_priv->has_mob)
+               return vmw_fifo_emit_dummy_gb_query(dev_priv, cid);
+
+       return vmw_fifo_emit_dummy_legacy_query(dev_priv, cid);
+}
index 6ef0b035becbc5959f78ecf7b978629f90ae98e2..61d8d803199fc97085ef7e7ada07e7cbbd89bb5f 100644 (file)
@@ -125,181 +125,27 @@ static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
 }
 
 
-static void vmw_gmr_free_descriptors(struct device *dev, dma_addr_t desc_dma,
-                                    struct list_head *desc_pages)
-{
-       struct page *page, *next;
-       struct svga_guest_mem_descriptor *page_virtual;
-       unsigned int desc_per_page = PAGE_SIZE /
-               sizeof(struct svga_guest_mem_descriptor) - 1;
-
-       if (list_empty(desc_pages))
-               return;
-
-       list_for_each_entry_safe(page, next, desc_pages, lru) {
-               list_del_init(&page->lru);
-
-               if (likely(desc_dma != DMA_ADDR_INVALID)) {
-                       dma_unmap_page(dev, desc_dma, PAGE_SIZE,
-                                      DMA_TO_DEVICE);
-               }
-
-               page_virtual = kmap_atomic(page);
-               desc_dma = (dma_addr_t)
-                       le32_to_cpu(page_virtual[desc_per_page].ppn) <<
-                       PAGE_SHIFT;
-               kunmap_atomic(page_virtual);
-
-               __free_page(page);
-       }
-}
-
-/**
- * FIXME: Adjust to the ttm lowmem / highmem storage to minimize
- * the number of used descriptors.
- *
- */
-
-static int vmw_gmr_build_descriptors(struct device *dev,
-                                    struct list_head *desc_pages,
-                                    struct vmw_piter *iter,
-                                    unsigned long num_pages,
-                                    dma_addr_t *first_dma)
-{
-       struct page *page;
-       struct svga_guest_mem_descriptor *page_virtual = NULL;
-       struct svga_guest_mem_descriptor *desc_virtual = NULL;
-       unsigned int desc_per_page;
-       unsigned long prev_pfn;
-       unsigned long pfn;
-       int ret;
-       dma_addr_t desc_dma;
-
-       desc_per_page = PAGE_SIZE /
-           sizeof(struct svga_guest_mem_descriptor) - 1;
-
-       while (likely(num_pages != 0)) {
-               page = alloc_page(__GFP_HIGHMEM);
-               if (unlikely(page == NULL)) {
-                       ret = -ENOMEM;
-                       goto out_err;
-               }
-
-               list_add_tail(&page->lru, desc_pages);
-               page_virtual = kmap_atomic(page);
-               desc_virtual = page_virtual - 1;
-               prev_pfn = ~(0UL);
-
-               while (likely(num_pages != 0)) {
-                       pfn = vmw_piter_dma_addr(iter) >> PAGE_SHIFT;
-
-                       if (pfn != prev_pfn + 1) {
-
-                               if (desc_virtual - page_virtual ==
-                                   desc_per_page - 1)
-                                       break;
-
-                               (++desc_virtual)->ppn = cpu_to_le32(pfn);
-                               desc_virtual->num_pages = cpu_to_le32(1);
-                       } else {
-                               uint32_t tmp =
-                                   le32_to_cpu(desc_virtual->num_pages);
-                               desc_virtual->num_pages = cpu_to_le32(tmp + 1);
-                       }
-                       prev_pfn = pfn;
-                       --num_pages;
-                       vmw_piter_next(iter);
-               }
-
-               (++desc_virtual)->ppn = DMA_PAGE_INVALID;
-               desc_virtual->num_pages = cpu_to_le32(0);
-               kunmap_atomic(page_virtual);
-       }
-
-       desc_dma = 0;
-       list_for_each_entry_reverse(page, desc_pages, lru) {
-               page_virtual = kmap_atomic(page);
-               page_virtual[desc_per_page].ppn = cpu_to_le32
-                       (desc_dma >> PAGE_SHIFT);
-               kunmap_atomic(page_virtual);
-               desc_dma = dma_map_page(dev, page, 0, PAGE_SIZE,
-                                       DMA_TO_DEVICE);
-
-               if (unlikely(dma_mapping_error(dev, desc_dma)))
-                       goto out_err;
-       }
-       *first_dma = desc_dma;
-
-       return 0;
-out_err:
-       vmw_gmr_free_descriptors(dev, DMA_ADDR_INVALID, desc_pages);
-       return ret;
-}
-
-static void vmw_gmr_fire_descriptors(struct vmw_private *dev_priv,
-                                    int gmr_id, dma_addr_t desc_dma)
-{
-       mutex_lock(&dev_priv->hw_mutex);
-
-       vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
-       wmb();
-       vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, desc_dma >> PAGE_SHIFT);
-       mb();
-
-       mutex_unlock(&dev_priv->hw_mutex);
-
-}
-
 int vmw_gmr_bind(struct vmw_private *dev_priv,
                 const struct vmw_sg_table *vsgt,
                 unsigned long num_pages,
                 int gmr_id)
 {
-       struct list_head desc_pages;
-       dma_addr_t desc_dma = 0;
-       struct device *dev = dev_priv->dev->dev;
        struct vmw_piter data_iter;
-       int ret;
 
        vmw_piter_start(&data_iter, vsgt, 0);
 
        if (unlikely(!vmw_piter_next(&data_iter)))
                return 0;
 
-       if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
-               return vmw_gmr2_bind(dev_priv, &data_iter, num_pages, gmr_id);
-
-       if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR)))
-               return -EINVAL;
-
-       if (vsgt->num_regions > dev_priv->max_gmr_descriptors)
+       if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR2)))
                return -EINVAL;
 
-       INIT_LIST_HEAD(&desc_pages);
-
-       ret = vmw_gmr_build_descriptors(dev, &desc_pages, &data_iter,
-                                       num_pages, &desc_dma);
-       if (unlikely(ret != 0))
-               return ret;
-
-       vmw_gmr_fire_descriptors(dev_priv, gmr_id, desc_dma);
-       vmw_gmr_free_descriptors(dev, desc_dma, &desc_pages);
-
-       return 0;
+       return vmw_gmr2_bind(dev_priv, &data_iter, num_pages, gmr_id);
 }
 
 
 void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
 {
-       if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) {
+       if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
                vmw_gmr2_unbind(dev_priv, gmr_id);
-               return;
-       }
-
-       mutex_lock(&dev_priv->hw_mutex);
-       vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
-       wmb();
-       vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, 0);
-       mb();
-       mutex_unlock(&dev_priv->hw_mutex);
 }
index c5c054ae9056aaea2479eb6a9018013098708ce2..b1273e8e9a6903e2d15d3b153177e9a99c806859 100644 (file)
@@ -125,10 +125,21 @@ static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man,
                return -ENOMEM;
 
        spin_lock_init(&gman->lock);
-       gman->max_gmr_pages = dev_priv->max_gmr_pages;
        gman->used_gmr_pages = 0;
        ida_init(&gman->gmr_ida);
-       gman->max_gmr_ids = p_size;
+
+       switch (p_size) {
+       case VMW_PL_GMR:
+               gman->max_gmr_ids = dev_priv->max_gmr_ids;
+               gman->max_gmr_pages = dev_priv->max_gmr_pages;
+               break;
+       case VMW_PL_MOB:
+               gman->max_gmr_ids = VMWGFX_NUM_MOB;
+               gman->max_gmr_pages = dev_priv->max_mob_pages;
+               break;
+       default:
+               BUG();
+       }
        man->priv = (void *) gman;
        return 0;
 }
index a51f48e3e917e0d3f5d4c73202be335df6f6919b..116c49736763ee81a4b4d664bfba2ab0a5e3d5cd 100644 (file)
@@ -53,7 +53,7 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                param->value = dev_priv->fifo.capabilities;
                break;
        case DRM_VMW_PARAM_MAX_FB_SIZE:
-               param->value = dev_priv->vram_size;
+               param->value = dev_priv->prim_bb_mem;
                break;
        case DRM_VMW_PARAM_FIFO_HW_VERSION:
        {
@@ -68,6 +68,20 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                                  SVGA_FIFO_3D_HWVERSION));
                break;
        }
+       case DRM_VMW_PARAM_MAX_SURF_MEMORY:
+               param->value = dev_priv->memory_size;
+               break;
+       case DRM_VMW_PARAM_3D_CAPS_SIZE:
+               if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
+                       param->value = SVGA3D_DEVCAP_MAX;
+               else
+                       param->value = (SVGA_FIFO_3D_CAPS_LAST -
+                                       SVGA_FIFO_3D_CAPS + 1);
+               param->value *= sizeof(uint32_t);
+               break;
+       case DRM_VMW_PARAM_MAX_MOB_MEMORY:
+               param->value = dev_priv->max_mob_pages * PAGE_SIZE;
+               break;
        default:
                DRM_ERROR("Illegal vmwgfx get param request: %d\n",
                          param->param);
@@ -89,13 +103,19 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
        void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
        void *bounce;
        int ret;
+       bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);
 
        if (unlikely(arg->pad64 != 0)) {
                DRM_ERROR("Illegal GET_3D_CAP argument.\n");
                return -EINVAL;
        }
 
-       size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) << 2;
+       if (gb_objects)
+               size = SVGA3D_DEVCAP_MAX;
+       else
+               size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1);
+
+       size *= sizeof(uint32_t);
 
        if (arg->max_size < size)
                size = arg->max_size;
@@ -106,8 +126,22 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
                return -ENOMEM;
        }
 
-       fifo_mem = dev_priv->mmio_virt;
-       memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
+       if (gb_objects) {
+               int i;
+               uint32_t *bounce32 = (uint32_t *) bounce;
+
+               mutex_lock(&dev_priv->hw_mutex);
+               for (i = 0; i < SVGA3D_DEVCAP_MAX; ++i) {
+                       vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
+                       *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+               }
+               mutex_unlock(&dev_priv->hw_mutex);
+
+       } else {
+
+               fifo_mem = dev_priv->mmio_virt;
+               memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
+       }
 
        ret = copy_to_user(buffer, bounce, size);
        if (ret)
index 4640adbcaf91b9609643895432d858313e56e2e4..0c423766c44119ca923825e879e3d05b7058cc90 100644 (file)
@@ -30,7 +30,7 @@
 
 #define VMW_FENCE_WRAP (1 << 24)
 
-irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS)
+irqreturn_t vmw_irq_handler(int irq, void *arg)
 {
        struct drm_device *dev = (struct drm_device *)arg;
        struct vmw_private *dev_priv = vmw_priv(dev);
index 03f1c203863193621d9941af3051169ea2f79afb..8a650413dea57c8e50212b41f8be00abba3ee8af 100644 (file)
@@ -40,7 +40,7 @@ struct vmw_clip_rect {
  * Clip @num_rects number of @rects against @clip storing the
  * results in @out_rects and the number of passed rects in @out_num.
  */
-void vmw_clip_cliprects(struct drm_clip_rect *rects,
+static void vmw_clip_cliprects(struct drm_clip_rect *rects,
                        int num_rects,
                        struct vmw_clip_rect clip,
                        SVGASignedRect *out_rects,
@@ -423,7 +423,7 @@ struct vmw_framebuffer_surface {
        struct drm_master *master;
 };
 
-void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
+static void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
 {
        struct vmw_framebuffer_surface *vfbs =
                vmw_framebuffer_to_vfbs(framebuffer);
@@ -589,7 +589,7 @@ out_free_tmp:
        return ret;
 }
 
-int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
+static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
                                  struct drm_file *file_priv,
                                  unsigned flags, unsigned color,
                                  struct drm_clip_rect *clips,
@@ -609,9 +609,13 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
        if (!dev_priv->sou_priv)
                return -EINVAL;
 
+       drm_modeset_lock_all(dev_priv->dev);
+
        ret = ttm_read_lock(&vmaster->lock, true);
-       if (unlikely(ret != 0))
+       if (unlikely(ret != 0)) {
+               drm_modeset_unlock_all(dev_priv->dev);
                return ret;
+       }
 
        if (!num_clips) {
                num_clips = 1;
@@ -629,6 +633,9 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
                                   clips, num_clips, inc, NULL);
 
        ttm_read_unlock(&vmaster->lock);
+
+       drm_modeset_unlock_all(dev_priv->dev);
+
        return 0;
 }
 
@@ -665,9 +672,9 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
 
        if (unlikely(surface->mip_levels[0] != 1 ||
                     surface->num_sizes != 1 ||
-                    surface->sizes[0].width < mode_cmd->width ||
-                    surface->sizes[0].height < mode_cmd->height ||
-                    surface->sizes[0].depth != 1)) {
+                    surface->base_size.width < mode_cmd->width ||
+                    surface->base_size.height < mode_cmd->height ||
+                    surface->base_size.depth != 1)) {
                DRM_ERROR("Incompatible surface dimensions "
                          "for requested mode.\n");
                return -EINVAL;
@@ -754,7 +761,7 @@ struct vmw_framebuffer_dmabuf {
        struct vmw_dma_buffer *buffer;
 };
 
-void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
+static void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
 {
        struct vmw_framebuffer_dmabuf *vfbd =
                vmw_framebuffer_to_vfbd(framebuffer);
@@ -940,7 +947,7 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv,
        return ret;
 }
 
-int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
+static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
                                 struct drm_file *file_priv,
                                 unsigned flags, unsigned color,
                                 struct drm_clip_rect *clips,
@@ -953,9 +960,13 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
        struct drm_clip_rect norect;
        int ret, increment = 1;
 
+       drm_modeset_lock_all(dev_priv->dev);
+
        ret = ttm_read_lock(&vmaster->lock, true);
-       if (unlikely(ret != 0))
+       if (unlikely(ret != 0)) {
+               drm_modeset_unlock_all(dev_priv->dev);
                return ret;
+       }
 
        if (!num_clips) {
                num_clips = 1;
@@ -979,6 +990,9 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
        }
 
        ttm_read_unlock(&vmaster->lock);
+
+       drm_modeset_unlock_all(dev_priv->dev);
+
        return ret;
 }
 
@@ -1631,7 +1645,7 @@ bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
                                uint32_t pitch,
                                uint32_t height)
 {
-       return ((u64) pitch * (u64) height) < (u64) dev_priv->vram_size;
+       return ((u64) pitch * (u64) height) < (u64) dev_priv->prim_bb_mem;
 }
 
 
@@ -1663,7 +1677,7 @@ void vmw_disable_vblank(struct drm_device *dev, int crtc)
  * Small shared kms functions.
  */
 
-int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
+static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
                         struct drm_vmw_rect *rects)
 {
        struct drm_device *dev = dev_priv->dev;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
new file mode 100644 (file)
index 0000000..4910e7b
--- /dev/null
@@ -0,0 +1,652 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2012 VMware, Inc., Palo Alto, CA., USA
+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_drv.h"
+
+/*
+ * If we set up the screen target otable, screen objects stop working.
+ */
+
+#define VMW_OTABLE_SETUP_SUB ((VMWGFX_ENABLE_SCREEN_TARGET_OTABLE) ? 0 : 1)
+
+#ifdef CONFIG_64BIT
+#define VMW_PPN_SIZE 8
+#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PTDEPTH64_0
+#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PTDEPTH64_1
+#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PTDEPTH64_2
+#else
+#define VMW_PPN_SIZE 4
+#define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PTDEPTH_0
+#define VMW_MOBFMT_PTDEPTH_1 SVGA3D_MOBFMT_PTDEPTH_1
+#define VMW_MOBFMT_PTDEPTH_2 SVGA3D_MOBFMT_PTDEPTH_2
+#endif
+
+/*
+ * struct vmw_mob - Structure containing page table and metadata for a
+ * Guest Memory OBject.
+ *
+ * @num_pages       Number of pages that make up the page table.
+ * @pt_level        The indirection level of the page table. 0-2.
+ * @pt_root_page    DMA address of the level 0 page of the page table.
+ */
+struct vmw_mob {
+       struct ttm_buffer_object *pt_bo;
+       unsigned long num_pages;
+       unsigned pt_level;
+       dma_addr_t pt_root_page;
+       uint32_t id;
+};
+
+/*
+ * struct vmw_otable - Guest Memory OBject table metadata
+ *
+ * @size:           Size of the table (page-aligned).
+ * @page_table:     Pointer to a struct vmw_mob holding the page table.
+ */
+struct vmw_otable {
+       unsigned long size;
+       struct vmw_mob *page_table;
+};
+
+static int vmw_mob_pt_populate(struct vmw_private *dev_priv,
+                              struct vmw_mob *mob);
+static void vmw_mob_pt_setup(struct vmw_mob *mob,
+                            struct vmw_piter data_iter,
+                            unsigned long num_data_pages);
+
+/*
+ * vmw_setup_otable_base - Issue an object table base setup command to
+ * the device
+ *
+ * @dev_priv:       Pointer to a device private structure
+ * @type:           Type of object table base
+ * @offset          Start of table offset into dev_priv::otable_bo
+ * @otable          Pointer to otable metadata;
+ *
+ * This function returns -ENOMEM if it fails to reserve fifo space,
+ * and may block waiting for fifo space.
+ */
+static int vmw_setup_otable_base(struct vmw_private *dev_priv,
+                                SVGAOTableType type,
+                                unsigned long offset,
+                                struct vmw_otable *otable)
+{
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetOTableBase64 body;
+       } *cmd;
+       struct vmw_mob *mob;
+       const struct vmw_sg_table *vsgt;
+       struct vmw_piter iter;
+       int ret;
+
+       BUG_ON(otable->page_table != NULL);
+
+       vsgt = vmw_bo_sg_table(dev_priv->otable_bo);
+       vmw_piter_start(&iter, vsgt, offset >> PAGE_SHIFT);
+       WARN_ON(!vmw_piter_next(&iter));
+
+       mob = vmw_mob_create(otable->size >> PAGE_SHIFT);
+       if (unlikely(mob == NULL)) {
+               DRM_ERROR("Failed creating OTable page table.\n");
+               return -ENOMEM;
+       }
+
+       if (otable->size <= PAGE_SIZE) {
+               mob->pt_level = VMW_MOBFMT_PTDEPTH_0;
+               mob->pt_root_page = vmw_piter_dma_addr(&iter);
+       } else if (vsgt->num_regions == 1) {
+               mob->pt_level = SVGA3D_MOBFMT_RANGE;
+               mob->pt_root_page = vmw_piter_dma_addr(&iter);
+       } else {
+               ret = vmw_mob_pt_populate(dev_priv, mob);
+               if (unlikely(ret != 0))
+                       goto out_no_populate;
+
+               vmw_mob_pt_setup(mob, iter, otable->size >> PAGE_SHIFT);
+               mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
+       }
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for OTable setup.\n");
+               goto out_no_fifo;
+       }
+
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE64;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.type = type;
+       cmd->body.baseAddress = cpu_to_le64(mob->pt_root_page >> PAGE_SHIFT);
+       cmd->body.sizeInBytes = otable->size;
+       cmd->body.validSizeInBytes = 0;
+       cmd->body.ptDepth = mob->pt_level;
+
+       /*
+        * The device doesn't support this, But the otable size is
+        * determined at compile-time, so this BUG shouldn't trigger
+        * randomly.
+        */
+       BUG_ON(mob->pt_level == VMW_MOBFMT_PTDEPTH_2);
+
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       otable->page_table = mob;
+
+       return 0;
+
+out_no_fifo:
+out_no_populate:
+       vmw_mob_destroy(mob);
+       return ret;
+}
+
+/*
+ * vmw_takedown_otable_base - Issue an object table base takedown command
+ * to the device
+ *
+ * @dev_priv:       Pointer to a device private structure
+ * @type:           Type of object table base
+ *
+ */
+static void vmw_takedown_otable_base(struct vmw_private *dev_priv,
+                                    SVGAOTableType type,
+                                    struct vmw_otable *otable)
+{
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetOTableBase body;
+       } *cmd;
+       struct ttm_buffer_object *bo;
+
+       if (otable->page_table == NULL)
+               return;
+
+       bo = otable->page_table->pt_bo;
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL))
+               DRM_ERROR("Failed reserving FIFO space for OTable setup.\n");
+
+       memset(cmd, 0, sizeof(*cmd));
+       cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.type = type;
+       cmd->body.baseAddress = 0;
+       cmd->body.sizeInBytes = 0;
+       cmd->body.validSizeInBytes = 0;
+       cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       if (bo) {
+               int ret;
+
+               ret = ttm_bo_reserve(bo, false, true, false, NULL);
+               BUG_ON(ret != 0);
+
+               vmw_fence_single_bo(bo, NULL);
+               ttm_bo_unreserve(bo);
+       }
+
+       vmw_mob_destroy(otable->page_table);
+       otable->page_table = NULL;
+}
+
+/*
+ * vmw_otables_setup - Set up guest backed memory object tables
+ *
+ * @dev_priv:       Pointer to a device private structure
+ *
+ * Takes care of the device guest backed surface
+ * initialization, by setting up the guest backed memory object tables.
+ * Returns 0 on success and various error codes on failure. A succesful return
+ * means the object tables can be taken down using the vmw_otables_takedown
+ * function.
+ */
+int vmw_otables_setup(struct vmw_private *dev_priv)
+{
+       unsigned long offset;
+       unsigned long bo_size;
+       struct vmw_otable *otables;
+       SVGAOTableType i;
+       int ret;
+
+       otables = kzalloc(SVGA_OTABLE_DX9_MAX * sizeof(*otables),
+                         GFP_KERNEL);
+       if (unlikely(otables == NULL)) {
+               DRM_ERROR("Failed to allocate space for otable "
+                         "metadata.\n");
+               return -ENOMEM;
+       }
+
+       otables[SVGA_OTABLE_MOB].size =
+               VMWGFX_NUM_MOB * SVGA3D_OTABLE_MOB_ENTRY_SIZE;
+       otables[SVGA_OTABLE_SURFACE].size =
+               VMWGFX_NUM_GB_SURFACE * SVGA3D_OTABLE_SURFACE_ENTRY_SIZE;
+       otables[SVGA_OTABLE_CONTEXT].size =
+               VMWGFX_NUM_GB_CONTEXT * SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE;
+       otables[SVGA_OTABLE_SHADER].size =
+               VMWGFX_NUM_GB_SHADER * SVGA3D_OTABLE_SHADER_ENTRY_SIZE;
+       otables[SVGA_OTABLE_SCREEN_TARGET].size =
+               VMWGFX_NUM_GB_SCREEN_TARGET *
+               SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE;
+
+       bo_size = 0;
+       for (i = 0; i < SVGA_OTABLE_DX9_MAX; ++i) {
+               otables[i].size =
+                       (otables[i].size + PAGE_SIZE - 1) & PAGE_MASK;
+               bo_size += otables[i].size;
+       }
+
+       ret = ttm_bo_create(&dev_priv->bdev, bo_size,
+                           ttm_bo_type_device,
+                           &vmw_sys_ne_placement,
+                           0, false, NULL,
+                           &dev_priv->otable_bo);
+
+       if (unlikely(ret != 0))
+               goto out_no_bo;
+
+       ret = ttm_bo_reserve(dev_priv->otable_bo, false, true, false, NULL);
+       BUG_ON(ret != 0);
+       ret = vmw_bo_driver.ttm_tt_populate(dev_priv->otable_bo->ttm);
+       if (unlikely(ret != 0))
+               goto out_unreserve;
+       ret = vmw_bo_map_dma(dev_priv->otable_bo);
+       if (unlikely(ret != 0))
+               goto out_unreserve;
+
+       ttm_bo_unreserve(dev_priv->otable_bo);
+
+       offset = 0;
+       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i) {
+               ret = vmw_setup_otable_base(dev_priv, i, offset,
+                                           &otables[i]);
+               if (unlikely(ret != 0))
+                       goto out_no_setup;
+               offset += otables[i].size;
+       }
+
+       dev_priv->otables = otables;
+       return 0;
+
+out_unreserve:
+       ttm_bo_unreserve(dev_priv->otable_bo);
+out_no_setup:
+       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i)
+               vmw_takedown_otable_base(dev_priv, i, &otables[i]);
+
+       ttm_bo_unref(&dev_priv->otable_bo);
+out_no_bo:
+       kfree(otables);
+       return ret;
+}
+
+
+/*
+ * vmw_otables_takedown - Take down guest backed memory object tables
+ *
+ * @dev_priv:       Pointer to a device private structure
+ *
+ * Take down the Guest Memory Object tables.
+ */
+void vmw_otables_takedown(struct vmw_private *dev_priv)
+{
+       SVGAOTableType i;
+       struct ttm_buffer_object *bo = dev_priv->otable_bo;
+       int ret;
+
+       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i)
+               vmw_takedown_otable_base(dev_priv, i,
+                                        &dev_priv->otables[i]);
+
+       ret = ttm_bo_reserve(bo, false, true, false, NULL);
+       BUG_ON(ret != 0);
+
+       vmw_fence_single_bo(bo, NULL);
+       ttm_bo_unreserve(bo);
+
+       ttm_bo_unref(&dev_priv->otable_bo);
+       kfree(dev_priv->otables);
+       dev_priv->otables = NULL;
+}
+
+
+/*
+ * vmw_mob_calculate_pt_pages - Calculate the number of page table pages
+ * needed for a guest backed memory object.
+ *
+ * @data_pages:  Number of data pages in the memory object buffer.
+ */
+static unsigned long vmw_mob_calculate_pt_pages(unsigned long data_pages)
+{
+       unsigned long data_size = data_pages * PAGE_SIZE;
+       unsigned long tot_size = 0;
+
+       while (likely(data_size > PAGE_SIZE)) {
+               data_size = DIV_ROUND_UP(data_size, PAGE_SIZE);
+               data_size *= VMW_PPN_SIZE;
+               tot_size += (data_size + PAGE_SIZE - 1) & PAGE_MASK;
+       }
+
+       return tot_size >> PAGE_SHIFT;
+}
+
+/*
+ * vmw_mob_create - Create a mob, but don't populate it.
+ *
+ * @data_pages:  Number of data pages of the underlying buffer object.
+ */
+struct vmw_mob *vmw_mob_create(unsigned long data_pages)
+{
+       struct vmw_mob *mob = kzalloc(sizeof(*mob), GFP_KERNEL);
+
+       if (unlikely(mob == NULL))
+               return NULL;
+
+       mob->num_pages = vmw_mob_calculate_pt_pages(data_pages);
+
+       return mob;
+}
+
+/*
+ * vmw_mob_pt_populate - Populate the mob pagetable
+ *
+ * @mob:         Pointer to the mob the pagetable of which we want to
+ *               populate.
+ *
+ * This function allocates memory to be used for the pagetable, and
+ * adjusts TTM memory accounting accordingly. Returns ENOMEM if
+ * memory resources aren't sufficient and may cause TTM buffer objects
+ * to be swapped out by using the TTM memory accounting function.
+ */
+static int vmw_mob_pt_populate(struct vmw_private *dev_priv,
+                              struct vmw_mob *mob)
+{
+       int ret;
+       BUG_ON(mob->pt_bo != NULL);
+
+       ret = ttm_bo_create(&dev_priv->bdev, mob->num_pages * PAGE_SIZE,
+                           ttm_bo_type_device,
+                           &vmw_sys_ne_placement,
+                           0, false, NULL, &mob->pt_bo);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_bo_reserve(mob->pt_bo, false, true, false, NULL);
+
+       BUG_ON(ret != 0);
+       ret = vmw_bo_driver.ttm_tt_populate(mob->pt_bo->ttm);
+       if (unlikely(ret != 0))
+               goto out_unreserve;
+       ret = vmw_bo_map_dma(mob->pt_bo);
+       if (unlikely(ret != 0))
+               goto out_unreserve;
+
+       ttm_bo_unreserve(mob->pt_bo);
+       
+       return 0;
+
+out_unreserve:
+       ttm_bo_unreserve(mob->pt_bo);
+       ttm_bo_unref(&mob->pt_bo);
+
+       return ret;
+}
+
+/**
+ * vmw_mob_assign_ppn - Assign a value to a page table entry
+ *
+ * @addr: Pointer to pointer to page table entry.
+ * @val: The page table entry
+ *
+ * Assigns a value to a page table entry pointed to by *@addr and increments
+ * *@addr according to the page table entry size.
+ */
+#if (VMW_PPN_SIZE == 8)
+static void vmw_mob_assign_ppn(__le32 **addr, dma_addr_t val)
+{
+       *((__le64 *) *addr) = cpu_to_le64(val >> PAGE_SHIFT);
+       *addr += 2;
+}
+#else
+static void vmw_mob_assign_ppn(__le32 **addr, dma_addr_t val)
+{
+       *(*addr)++ = cpu_to_le32(val >> PAGE_SHIFT);
+}
+#endif
+
+/*
+ * vmw_mob_build_pt - Build a pagetable
+ *
+ * @data_addr:      Array of DMA addresses to the underlying buffer
+ *                  object's data pages.
+ * @num_data_pages: Number of buffer object data pages.
+ * @pt_pages:       Array of page pointers to the page table pages.
+ *
+ * Returns the number of page table pages actually used.
+ * Uses atomic kmaps of highmem pages to avoid TLB thrashing.
+ */
+static unsigned long vmw_mob_build_pt(struct vmw_piter *data_iter,
+                                     unsigned long num_data_pages,
+                                     struct vmw_piter *pt_iter)
+{
+       unsigned long pt_size = num_data_pages * VMW_PPN_SIZE;
+       unsigned long num_pt_pages = DIV_ROUND_UP(pt_size, PAGE_SIZE);
+       unsigned long pt_page;
+       __le32 *addr, *save_addr;
+       unsigned long i;
+       struct page *page;
+
+       for (pt_page = 0; pt_page < num_pt_pages; ++pt_page) {
+               page = vmw_piter_page(pt_iter);
+
+               save_addr = addr = kmap_atomic(page);
+
+               for (i = 0; i < PAGE_SIZE / VMW_PPN_SIZE; ++i) {
+                       vmw_mob_assign_ppn(&addr,
+                                          vmw_piter_dma_addr(data_iter));
+                       if (unlikely(--num_data_pages == 0))
+                               break;
+                       WARN_ON(!vmw_piter_next(data_iter));
+               }
+               kunmap_atomic(save_addr);
+               vmw_piter_next(pt_iter);
+       }
+
+       return num_pt_pages;
+}
+
+/*
+ * vmw_mob_build_pt - Set up a multilevel mob pagetable
+ *
+ * @mob:            Pointer to a mob whose page table needs setting up.
+ * @data_addr       Array of DMA addresses to the buffer object's data
+ *                  pages.
+ * @num_data_pages: Number of buffer object data pages.
+ *
+ * Uses tail recursion to set up a multilevel mob page table.
+ */
+static void vmw_mob_pt_setup(struct vmw_mob *mob,
+                            struct vmw_piter data_iter,
+                            unsigned long num_data_pages)
+{
+       unsigned long num_pt_pages = 0;
+       struct ttm_buffer_object *bo = mob->pt_bo;
+       struct vmw_piter save_pt_iter;
+       struct vmw_piter pt_iter;
+       const struct vmw_sg_table *vsgt;
+       int ret;
+
+       ret = ttm_bo_reserve(bo, false, true, false, NULL);
+       BUG_ON(ret != 0);
+
+       vsgt = vmw_bo_sg_table(bo);
+       vmw_piter_start(&pt_iter, vsgt, 0);
+       BUG_ON(!vmw_piter_next(&pt_iter));
+       mob->pt_level = 0;
+       while (likely(num_data_pages > 1)) {
+               ++mob->pt_level;
+               BUG_ON(mob->pt_level > 2);
+               save_pt_iter = pt_iter;
+               num_pt_pages = vmw_mob_build_pt(&data_iter, num_data_pages,
+                                               &pt_iter);
+               data_iter = save_pt_iter;
+               num_data_pages = num_pt_pages;
+       }
+
+       mob->pt_root_page = vmw_piter_dma_addr(&save_pt_iter);
+       ttm_bo_unreserve(bo);
+}
+
+/*
+ * vmw_mob_destroy - Destroy a mob, unpopulating first if necessary.
+ *
+ * @mob:            Pointer to a mob to destroy.
+ */
+void vmw_mob_destroy(struct vmw_mob *mob)
+{
+       if (mob->pt_bo)
+               ttm_bo_unref(&mob->pt_bo);
+       kfree(mob);
+}
+
+/*
+ * vmw_mob_unbind - Hide a mob from the device.
+ *
+ * @dev_priv:       Pointer to a device private.
+ * @mob_id:         Device id of the mob to unbind.
+ */
+void vmw_mob_unbind(struct vmw_private *dev_priv,
+                   struct vmw_mob *mob)
+{
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyGBMob body;
+       } *cmd;
+       int ret;
+       struct ttm_buffer_object *bo = mob->pt_bo;
+
+       if (bo) {
+               ret = ttm_bo_reserve(bo, false, true, false, NULL);
+               /*
+                * Noone else should be using this buffer.
+                */
+               BUG_ON(ret != 0);
+       }
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for Memory "
+                         "Object unbinding.\n");
+       }
+       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.mobid = mob->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       if (bo) {
+               vmw_fence_single_bo(bo, NULL);
+               ttm_bo_unreserve(bo);
+       }
+       vmw_3d_resource_dec(dev_priv, false);
+}
+
+/*
+ * vmw_mob_bind - Make a mob visible to the device after first
+ *                populating it if necessary.
+ *
+ * @dev_priv:       Pointer to a device private.
+ * @mob:            Pointer to the mob we're making visible.
+ * @data_addr:      Array of DMA addresses to the data pages of the underlying
+ *                  buffer object.
+ * @num_data_pages: Number of data pages of the underlying buffer
+ *                  object.
+ * @mob_id:         Device id of the mob to bind
+ *
+ * This function is intended to be interfaced with the ttm_tt backend
+ * code.
+ */
+int vmw_mob_bind(struct vmw_private *dev_priv,
+                struct vmw_mob *mob,
+                const struct vmw_sg_table *vsgt,
+                unsigned long num_data_pages,
+                int32_t mob_id)
+{
+       int ret;
+       bool pt_set_up = false;
+       struct vmw_piter data_iter;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineGBMob64 body;
+       } *cmd;
+
+       mob->id = mob_id;
+       vmw_piter_start(&data_iter, vsgt, 0);
+       if (unlikely(!vmw_piter_next(&data_iter)))
+               return 0;
+
+       if (likely(num_data_pages == 1)) {
+               mob->pt_level = VMW_MOBFMT_PTDEPTH_0;
+               mob->pt_root_page = vmw_piter_dma_addr(&data_iter);
+       } else if (vsgt->num_regions == 1) {
+               mob->pt_level = SVGA3D_MOBFMT_RANGE;
+               mob->pt_root_page = vmw_piter_dma_addr(&data_iter);
+       } else if (unlikely(mob->pt_bo == NULL)) {
+               ret = vmw_mob_pt_populate(dev_priv, mob);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               vmw_mob_pt_setup(mob, data_iter, num_data_pages);
+               pt_set_up = true;
+               mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
+       }
+
+       (void) vmw_3d_resource_inc(dev_priv, false);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for Memory "
+                         "Object binding.\n");
+               goto out_no_cmd_space;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DEFINE_GB_MOB64;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.mobid = mob_id;
+       cmd->body.ptDepth = mob->pt_level;
+       cmd->body.base = cpu_to_le64(mob->pt_root_page >> PAGE_SHIFT);
+       cmd->body.sizeInBytes = num_data_pages * PAGE_SIZE;
+
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+
+out_no_cmd_space:
+       vmw_3d_resource_dec(dev_priv, false);
+       if (pt_set_up)
+               ttm_bo_unref(&mob->pt_bo);
+
+       return -ENOMEM;
+}
index 9b5ea2ac7ddff21562aa7ef52a2f96872c623116..6fdd82d42f6549d2af208516ad22b26d45785e28 100644 (file)
@@ -215,6 +215,7 @@ int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res,
        res->func = func;
        INIT_LIST_HEAD(&res->lru_head);
        INIT_LIST_HEAD(&res->mob_head);
+       INIT_LIST_HEAD(&res->binding_head);
        res->id = -1;
        res->backup = NULL;
        res->backup_offset = 0;
@@ -441,6 +442,21 @@ static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
        ttm_bo_unref(&bo);
 }
 
+static void vmw_user_dmabuf_ref_obj_release(struct ttm_base_object *base,
+                                           enum ttm_ref_type ref_type)
+{
+       struct vmw_user_dma_buffer *user_bo;
+       user_bo = container_of(base, struct vmw_user_dma_buffer, prime.base);
+
+       switch (ref_type) {
+       case TTM_REF_SYNCCPU_WRITE:
+               ttm_bo_synccpu_write_release(&user_bo->dma.base);
+               break;
+       default:
+               BUG();
+       }
+}
+
 /**
  * vmw_user_dmabuf_alloc - Allocate a user dma buffer
  *
@@ -471,6 +487,8 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
        }
 
        ret = vmw_dmabuf_init(dev_priv, &user_bo->dma, size,
+                             (dev_priv->has_mob) ?
+                             &vmw_sys_placement :
                              &vmw_vram_sys_placement, true,
                              &vmw_user_dmabuf_destroy);
        if (unlikely(ret != 0))
@@ -482,7 +500,8 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
                                    &user_bo->prime,
                                    shareable,
                                    ttm_buffer_type,
-                                   &vmw_user_dmabuf_release, NULL);
+                                   &vmw_user_dmabuf_release,
+                                   &vmw_user_dmabuf_ref_obj_release);
        if (unlikely(ret != 0)) {
                ttm_bo_unref(&tmp);
                goto out_no_base_object;
@@ -515,6 +534,130 @@ int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
                vmw_user_bo->prime.base.shareable) ? 0 : -EPERM;
 }
 
+/**
+ * vmw_user_dmabuf_synccpu_grab - Grab a struct vmw_user_dma_buffer for cpu
+ * access, idling previous GPU operations on the buffer and optionally
+ * blocking it for further command submissions.
+ *
+ * @user_bo: Pointer to the buffer object being grabbed for CPU access
+ * @tfile: Identifying the caller.
+ * @flags: Flags indicating how the grab should be performed.
+ *
+ * A blocking grab will be automatically released when @tfile is closed.
+ */
+static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo,
+                                       struct ttm_object_file *tfile,
+                                       uint32_t flags)
+{
+       struct ttm_buffer_object *bo = &user_bo->dma.base;
+       bool existed;
+       int ret;
+
+       if (flags & drm_vmw_synccpu_allow_cs) {
+               struct ttm_bo_device *bdev = bo->bdev;
+
+               spin_lock(&bdev->fence_lock);
+               ret = ttm_bo_wait(bo, false, true,
+                                 !!(flags & drm_vmw_synccpu_dontblock));
+               spin_unlock(&bdev->fence_lock);
+               return ret;
+       }
+
+       ret = ttm_bo_synccpu_write_grab
+               (bo, !!(flags & drm_vmw_synccpu_dontblock));
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_ref_object_add(tfile, &user_bo->prime.base,
+                                TTM_REF_SYNCCPU_WRITE, &existed);
+       if (ret != 0 || existed)
+               ttm_bo_synccpu_write_release(&user_bo->dma.base);
+
+       return ret;
+}
+
+/**
+ * vmw_user_dmabuf_synccpu_release - Release a previous grab for CPU access,
+ * and unblock command submission on the buffer if blocked.
+ *
+ * @handle: Handle identifying the buffer object.
+ * @tfile: Identifying the caller.
+ * @flags: Flags indicating the type of release.
+ */
+static int vmw_user_dmabuf_synccpu_release(uint32_t handle,
+                                          struct ttm_object_file *tfile,
+                                          uint32_t flags)
+{
+       if (!(flags & drm_vmw_synccpu_allow_cs))
+               return ttm_ref_object_base_unref(tfile, handle,
+                                                TTM_REF_SYNCCPU_WRITE);
+
+       return 0;
+}
+
+/**
+ * vmw_user_dmabuf_synccpu_release - ioctl function implementing the synccpu
+ * functionality.
+ *
+ * @dev: Identifies the drm device.
+ * @data: Pointer to the ioctl argument.
+ * @file_priv: Identifies the caller.
+ *
+ * This function checks the ioctl arguments for validity and calls the
+ * relevant synccpu functions.
+ */
+int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv)
+{
+       struct drm_vmw_synccpu_arg *arg =
+               (struct drm_vmw_synccpu_arg *) data;
+       struct vmw_dma_buffer *dma_buf;
+       struct vmw_user_dma_buffer *user_bo;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       int ret;
+
+       if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0
+           || (arg->flags & ~(drm_vmw_synccpu_read | drm_vmw_synccpu_write |
+                              drm_vmw_synccpu_dontblock |
+                              drm_vmw_synccpu_allow_cs)) != 0) {
+               DRM_ERROR("Illegal synccpu flags.\n");
+               return -EINVAL;
+       }
+
+       switch (arg->op) {
+       case drm_vmw_synccpu_grab:
+               ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               user_bo = container_of(dma_buf, struct vmw_user_dma_buffer,
+                                      dma);
+               ret = vmw_user_dmabuf_synccpu_grab(user_bo, tfile, arg->flags);
+               vmw_dmabuf_unreference(&dma_buf);
+               if (unlikely(ret != 0 && ret != -ERESTARTSYS &&
+                            ret != -EBUSY)) {
+                       DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n",
+                                 (unsigned int) arg->handle);
+                       return ret;
+               }
+               break;
+       case drm_vmw_synccpu_release:
+               ret = vmw_user_dmabuf_synccpu_release(arg->handle, tfile,
+                                                     arg->flags);
+               if (unlikely(ret != 0)) {
+                       DRM_ERROR("Failed synccpu release on handle 0x%08x.\n",
+                                 (unsigned int) arg->handle);
+                       return ret;
+               }
+               break;
+       default:
+               DRM_ERROR("Invalid synccpu operation.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
                           struct drm_file *file_priv)
 {
@@ -591,7 +734,8 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
 }
 
 int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
-                             struct vmw_dma_buffer *dma_buf)
+                             struct vmw_dma_buffer *dma_buf,
+                             uint32_t *handle)
 {
        struct vmw_user_dma_buffer *user_bo;
 
@@ -599,6 +743,8 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
                return -EINVAL;
 
        user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma);
+
+       *handle = user_bo->prime.base.hash.key;
        return ttm_ref_object_add(tfile, &user_bo->prime.base,
                                  TTM_REF_USAGE, NULL);
 }
@@ -1291,11 +1437,54 @@ void vmw_fence_single_bo(struct ttm_buffer_object *bo,
  * @mem:            The truct ttm_mem_reg indicating to what memory
  *                  region the move is taking place.
  *
- * For now does nothing.
+ * Evicts the Guest Backed hardware resource if the backup
+ * buffer is being moved out of MOB memory.
+ * Note that this function should not race with the resource
+ * validation code as long as it accesses only members of struct
+ * resource that remain static while bo::res is !NULL and
+ * while we have @bo reserved. struct resource::backup is *not* a
+ * static member. The resource validation code will take care
+ * to set @bo::res to NULL, while having @bo reserved when the
+ * buffer is no longer bound to the resource, so @bo:res can be
+ * used to determine whether there is a need to unbind and whether
+ * it is safe to unbind.
  */
 void vmw_resource_move_notify(struct ttm_buffer_object *bo,
                              struct ttm_mem_reg *mem)
 {
+       struct vmw_dma_buffer *dma_buf;
+
+       if (mem == NULL)
+               return;
+
+       if (bo->destroy != vmw_dmabuf_bo_free &&
+           bo->destroy != vmw_user_dmabuf_destroy)
+               return;
+
+       dma_buf = container_of(bo, struct vmw_dma_buffer, base);
+
+       if (mem->mem_type != VMW_PL_MOB) {
+               struct vmw_resource *res, *n;
+               struct ttm_bo_device *bdev = bo->bdev;
+               struct ttm_validate_buffer val_buf;
+
+               val_buf.bo = bo;
+
+               list_for_each_entry_safe(res, n, &dma_buf->res_list, mob_head) {
+
+                       if (unlikely(res->func->unbind == NULL))
+                               continue;
+
+                       (void) res->func->unbind(res, true, &val_buf);
+                       res->backup_dirty = true;
+                       res->res_dirty = false;
+                       list_del_init(&res->mob_head);
+               }
+
+               spin_lock(&bdev->fence_lock);
+               (void) ttm_bo_wait(bo, false, false, false);
+               spin_unlock(&bdev->fence_lock);
+       }
 }
 
 /**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
new file mode 100644 (file)
index 0000000..1457ec4
--- /dev/null
@@ -0,0 +1,441 @@
+/**************************************************************************
+ *
+ * Copyright Â© 2009-2012 VMware, Inc., Palo Alto, CA., USA
+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_drv.h"
+#include "vmwgfx_resource_priv.h"
+#include "ttm/ttm_placement.h"
+
+struct vmw_shader {
+       struct vmw_resource res;
+       SVGA3dShaderType type;
+       uint32_t size;
+};
+
+struct vmw_user_shader {
+       struct ttm_base_object base;
+       struct vmw_shader shader;
+};
+
+static void vmw_user_shader_free(struct vmw_resource *res);
+static struct vmw_resource *
+vmw_user_shader_base_to_res(struct ttm_base_object *base);
+
+static int vmw_gb_shader_create(struct vmw_resource *res);
+static int vmw_gb_shader_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf);
+static int vmw_gb_shader_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf);
+static int vmw_gb_shader_destroy(struct vmw_resource *res);
+
+static uint64_t vmw_user_shader_size;
+
+static const struct vmw_user_resource_conv user_shader_conv = {
+       .object_type = VMW_RES_SHADER,
+       .base_obj_to_res = vmw_user_shader_base_to_res,
+       .res_free = vmw_user_shader_free
+};
+
+const struct vmw_user_resource_conv *user_shader_converter =
+       &user_shader_conv;
+
+
+static const struct vmw_res_func vmw_gb_shader_func = {
+       .res_type = vmw_res_shader,
+       .needs_backup = true,
+       .may_evict = true,
+       .type_name = "guest backed shaders",
+       .backup_placement = &vmw_mob_placement,
+       .create = vmw_gb_shader_create,
+       .destroy = vmw_gb_shader_destroy,
+       .bind = vmw_gb_shader_bind,
+       .unbind = vmw_gb_shader_unbind
+};
+
+/**
+ * Shader management:
+ */
+
+static inline struct vmw_shader *
+vmw_res_to_shader(struct vmw_resource *res)
+{
+       return container_of(res, struct vmw_shader, res);
+}
+
+static void vmw_hw_shader_destroy(struct vmw_resource *res)
+{
+       (void) vmw_gb_shader_destroy(res);
+}
+
+static int vmw_gb_shader_init(struct vmw_private *dev_priv,
+                             struct vmw_resource *res,
+                             uint32_t size,
+                             uint64_t offset,
+                             SVGA3dShaderType type,
+                             struct vmw_dma_buffer *byte_code,
+                             void (*res_free) (struct vmw_resource *res))
+{
+       struct vmw_shader *shader = vmw_res_to_shader(res);
+       int ret;
+
+       ret = vmw_resource_init(dev_priv, res, true,
+                               res_free, &vmw_gb_shader_func);
+
+
+       if (unlikely(ret != 0)) {
+               if (res_free)
+                       res_free(res);
+               else
+                       kfree(res);
+               return ret;
+       }
+
+       res->backup_size = size;
+       if (byte_code) {
+               res->backup = vmw_dmabuf_reference(byte_code);
+               res->backup_offset = offset;
+       }
+       shader->size = size;
+       shader->type = type;
+
+       vmw_resource_activate(res, vmw_hw_shader_destroy);
+       return 0;
+}
+
+static int vmw_gb_shader_create(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct vmw_shader *shader = vmw_res_to_shader(res);
+       int ret;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineGBShader body;
+       } *cmd;
+
+       if (likely(res->id != -1))
+               return 0;
+
+       ret = vmw_resource_alloc_id(res);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to allocate a shader id.\n");
+               goto out_no_id;
+       }
+
+       if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) {
+               ret = -EBUSY;
+               goto out_no_fifo;
+       }
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "creation.\n");
+               ret = -ENOMEM;
+               goto out_no_fifo;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.shid = res->id;
+       cmd->body.type = shader->type;
+       cmd->body.sizeInBytes = shader->size;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       (void) vmw_3d_resource_inc(dev_priv, false);
+
+       return 0;
+
+out_no_fifo:
+       vmw_resource_release_id(res);
+out_no_id:
+       return ret;
+}
+
+static int vmw_gb_shader_bind(struct vmw_resource *res,
+                             struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBShader body;
+       } *cmd;
+       struct ttm_buffer_object *bo = val_buf->bo;
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "binding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.shid = res->id;
+       cmd->body.mobid = bo->mem.start;
+       cmd->body.offsetInBytes = 0;
+       res->backup_dirty = false;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       return 0;
+}
+
+static int vmw_gb_shader_unbind(struct vmw_resource *res,
+                               bool readback,
+                               struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBShader body;
+       } *cmd;
+       struct vmw_fence_obj *fence;
+
+       BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.shid = res->id;
+       cmd->body.mobid = SVGA3D_INVALID_ID;
+       cmd->body.offsetInBytes = 0;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+
+       /*
+        * Create a fence object and fence the backup buffer.
+        */
+
+       (void) vmw_execbuf_fence_commands(NULL, dev_priv,
+                                         &fence, NULL);
+
+       vmw_fence_single_bo(val_buf->bo, fence);
+
+       if (likely(fence != NULL))
+               vmw_fence_obj_unreference(&fence);
+
+       return 0;
+}
+
+static int vmw_gb_shader_destroy(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyGBShader body;
+       } *cmd;
+
+       if (likely(res->id == -1))
+               return 0;
+
+       mutex_lock(&dev_priv->binding_mutex);
+       vmw_context_binding_res_list_kill(&res->binding_head);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for shader "
+                         "destruction.\n");
+               mutex_unlock(&dev_priv->binding_mutex);
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.shid = res->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       mutex_unlock(&dev_priv->binding_mutex);
+       vmw_resource_release_id(res);
+       vmw_3d_resource_dec(dev_priv, false);
+
+       return 0;
+}
+
+/**
+ * User-space shader management:
+ */
+
+static struct vmw_resource *
+vmw_user_shader_base_to_res(struct ttm_base_object *base)
+{
+       return &(container_of(base, struct vmw_user_shader, base)->
+                shader.res);
+}
+
+static void vmw_user_shader_free(struct vmw_resource *res)
+{
+       struct vmw_user_shader *ushader =
+               container_of(res, struct vmw_user_shader, shader.res);
+       struct vmw_private *dev_priv = res->dev_priv;
+
+       ttm_base_object_kfree(ushader, base);
+       ttm_mem_global_free(vmw_mem_glob(dev_priv),
+                           vmw_user_shader_size);
+}
+
+/**
+ * This function is called when user space has no more references on the
+ * base object. It releases the base-object's reference on the resource object.
+ */
+
+static void vmw_user_shader_base_release(struct ttm_base_object **p_base)
+{
+       struct ttm_base_object *base = *p_base;
+       struct vmw_resource *res = vmw_user_shader_base_to_res(base);
+
+       *p_base = NULL;
+       vmw_resource_unreference(&res);
+}
+
+int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+
+       return ttm_ref_object_base_unref(tfile, arg->handle,
+                                        TTM_REF_USAGE);
+}
+
+int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct vmw_user_shader *ushader;
+       struct vmw_resource *res;
+       struct vmw_resource *tmp;
+       struct drm_vmw_shader_create_arg *arg =
+               (struct drm_vmw_shader_create_arg *)data;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       struct vmw_dma_buffer *buffer = NULL;
+       SVGA3dShaderType shader_type;
+       int ret;
+
+       if (arg->buffer_handle != SVGA3D_INVALID_ID) {
+               ret = vmw_user_dmabuf_lookup(tfile, arg->buffer_handle,
+                                            &buffer);
+               if (unlikely(ret != 0)) {
+                       DRM_ERROR("Could not find buffer for shader "
+                                 "creation.\n");
+                       return ret;
+               }
+
+               if ((u64)buffer->base.num_pages * PAGE_SIZE <
+                   (u64)arg->size + (u64)arg->offset) {
+                       DRM_ERROR("Illegal buffer- or shader size.\n");
+                       ret = -EINVAL;
+                       goto out_bad_arg;
+               }
+       }
+
+       switch (arg->shader_type) {
+       case drm_vmw_shader_type_vs:
+               shader_type = SVGA3D_SHADERTYPE_VS;
+               break;
+       case drm_vmw_shader_type_ps:
+               shader_type = SVGA3D_SHADERTYPE_PS;
+               break;
+       case drm_vmw_shader_type_gs:
+               shader_type = SVGA3D_SHADERTYPE_GS;
+               break;
+       default:
+               DRM_ERROR("Illegal shader type.\n");
+               ret = -EINVAL;
+               goto out_bad_arg;
+       }
+
+       /*
+        * Approximate idr memory usage with 128 bytes. It will be limited
+        * by maximum number_of shaders anyway.
+        */
+
+       if (unlikely(vmw_user_shader_size == 0))
+               vmw_user_shader_size = ttm_round_pot(sizeof(*ushader))
+                       + 128;
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+                                  vmw_user_shader_size,
+                                  false, true);
+       if (unlikely(ret != 0)) {
+               if (ret != -ERESTARTSYS)
+                       DRM_ERROR("Out of graphics memory for shader"
+                                 " creation.\n");
+               goto out_unlock;
+       }
+
+       ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
+       if (unlikely(ushader == NULL)) {
+               ttm_mem_global_free(vmw_mem_glob(dev_priv),
+                                   vmw_user_shader_size);
+               ret = -ENOMEM;
+               goto out_unlock;
+       }
+
+       res = &ushader->shader.res;
+       ushader->base.shareable = false;
+       ushader->base.tfile = NULL;
+
+       /*
+        * From here on, the destructor takes over resource freeing.
+        */
+
+       ret = vmw_gb_shader_init(dev_priv, res, arg->size,
+                                arg->offset, shader_type, buffer,
+                                vmw_user_shader_free);
+       if (unlikely(ret != 0))
+               goto out_unlock;
+
+       tmp = vmw_resource_reference(res);
+       ret = ttm_base_object_init(tfile, &ushader->base, false,
+                                  VMW_RES_SHADER,
+                                  &vmw_user_shader_base_release, NULL);
+
+       if (unlikely(ret != 0)) {
+               vmw_resource_unreference(&tmp);
+               goto out_err;
+       }
+
+       arg->shader_handle = ushader->base.hash.key;
+out_err:
+       vmw_resource_unreference(&res);
+out_unlock:
+       ttm_read_unlock(&vmaster->lock);
+out_bad_arg:
+       vmw_dmabuf_unreference(&buffer);
+
+       return ret;
+
+}
index 7de2ea8bd55357561913384bfa23196fe3479ec2..979da1c246a543a445257daee03787e794b266a1 100644 (file)
@@ -41,7 +41,6 @@ struct vmw_user_surface {
        struct ttm_prime_object prime;
        struct vmw_surface srf;
        uint32_t size;
-       uint32_t backup_handle;
 };
 
 /**
@@ -68,6 +67,14 @@ static int vmw_legacy_srf_unbind(struct vmw_resource *res,
                                 struct ttm_validate_buffer *val_buf);
 static int vmw_legacy_srf_create(struct vmw_resource *res);
 static int vmw_legacy_srf_destroy(struct vmw_resource *res);
+static int vmw_gb_surface_create(struct vmw_resource *res);
+static int vmw_gb_surface_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf);
+static int vmw_gb_surface_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf);
+static int vmw_gb_surface_destroy(struct vmw_resource *res);
+
 
 static const struct vmw_user_resource_conv user_surface_conv = {
        .object_type = VMW_RES_SURFACE,
@@ -93,6 +100,18 @@ static const struct vmw_res_func vmw_legacy_surface_func = {
        .unbind = &vmw_legacy_srf_unbind
 };
 
+static const struct vmw_res_func vmw_gb_surface_func = {
+       .res_type = vmw_res_surface,
+       .needs_backup = true,
+       .may_evict = true,
+       .type_name = "guest backed surfaces",
+       .backup_placement = &vmw_mob_placement,
+       .create = vmw_gb_surface_create,
+       .destroy = vmw_gb_surface_destroy,
+       .bind = vmw_gb_surface_bind,
+       .unbind = vmw_gb_surface_unbind
+};
+
 /**
  * struct vmw_surface_dma - SVGA3D DMA command
  */
@@ -291,6 +310,11 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
        struct vmw_surface *srf;
        void *cmd;
 
+       if (res->func->destroy == vmw_gb_surface_destroy) {
+               (void) vmw_gb_surface_destroy(res);
+               return;
+       }
+
        if (res->id != -1) {
 
                cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
@@ -549,12 +573,15 @@ static int vmw_surface_init(struct vmw_private *dev_priv,
        struct vmw_resource *res = &srf->res;
 
        BUG_ON(res_free == NULL);
-       (void) vmw_3d_resource_inc(dev_priv, false);
+       if (!dev_priv->has_mob)
+               (void) vmw_3d_resource_inc(dev_priv, false);
        ret = vmw_resource_init(dev_priv, res, true, res_free,
+                               (dev_priv->has_mob) ? &vmw_gb_surface_func :
                                &vmw_legacy_surface_func);
 
        if (unlikely(ret != 0)) {
-               vmw_3d_resource_dec(dev_priv, false);
+               if (!dev_priv->has_mob)
+                       vmw_3d_resource_dec(dev_priv, false);
                res_free(res);
                return ret;
        }
@@ -750,7 +777,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
 
        srf->base_size = *srf->sizes;
        srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
-       srf->multisample_count = 1;
+       srf->multisample_count = 0;
 
        cur_bo_offset = 0;
        cur_offset = srf->offsets;
@@ -843,6 +870,7 @@ out_unlock:
 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv)
 {
+       struct vmw_private *dev_priv = vmw_priv(dev);
        union drm_vmw_surface_reference_arg *arg =
            (union drm_vmw_surface_reference_arg *)data;
        struct drm_vmw_surface_arg *req = &arg->req;
@@ -854,7 +882,7 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
        struct ttm_base_object *base;
        int ret = -EINVAL;
 
-       base = ttm_base_object_lookup(tfile, req->sid);
+       base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
        if (unlikely(base == NULL)) {
                DRM_ERROR("Could not find surface to reference.\n");
                return -EINVAL;
@@ -893,3 +921,436 @@ out_no_reference:
 
        return ret;
 }
+
+/**
+ * vmw_surface_define_encode - Encode a surface_define command.
+ *
+ * @srf: Pointer to a struct vmw_surface object.
+ * @cmd_space: Pointer to memory area in which the commands should be encoded.
+ */
+static int vmw_gb_surface_create(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct vmw_surface *srf = vmw_res_to_srf(res);
+       uint32_t cmd_len, submit_len;
+       int ret;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineGBSurface body;
+       } *cmd;
+
+       if (likely(res->id != -1))
+               return 0;
+
+       (void) vmw_3d_resource_inc(dev_priv, false);
+       ret = vmw_resource_alloc_id(res);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed to allocate a surface id.\n");
+               goto out_no_id;
+       }
+
+       if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) {
+               ret = -EBUSY;
+               goto out_no_fifo;
+       }
+
+       cmd_len = sizeof(cmd->body);
+       submit_len = sizeof(*cmd);
+       cmd = vmw_fifo_reserve(dev_priv, submit_len);
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for surface "
+                         "creation.\n");
+               ret = -ENOMEM;
+               goto out_no_fifo;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SURFACE;
+       cmd->header.size = cmd_len;
+       cmd->body.sid = srf->res.id;
+       cmd->body.surfaceFlags = srf->flags;
+       cmd->body.format = cpu_to_le32(srf->format);
+       cmd->body.numMipLevels = srf->mip_levels[0];
+       cmd->body.multisampleCount = srf->multisample_count;
+       cmd->body.autogenFilter = srf->autogen_filter;
+       cmd->body.size.width = srf->base_size.width;
+       cmd->body.size.height = srf->base_size.height;
+       cmd->body.size.depth = srf->base_size.depth;
+       vmw_fifo_commit(dev_priv, submit_len);
+
+       return 0;
+
+out_no_fifo:
+       vmw_resource_release_id(res);
+out_no_id:
+       vmw_3d_resource_dec(dev_priv, false);
+       return ret;
+}
+
+
+static int vmw_gb_surface_bind(struct vmw_resource *res,
+                              struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBSurface body;
+       } *cmd1;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdUpdateGBSurface body;
+       } *cmd2;
+       uint32_t submit_size;
+       struct ttm_buffer_object *bo = val_buf->bo;
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);
+
+       cmd1 = vmw_fifo_reserve(dev_priv, submit_size);
+       if (unlikely(cmd1 == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for surface "
+                         "binding.\n");
+               return -ENOMEM;
+       }
+
+       cmd1->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
+       cmd1->header.size = sizeof(cmd1->body);
+       cmd1->body.sid = res->id;
+       cmd1->body.mobid = bo->mem.start;
+       if (res->backup_dirty) {
+               cmd2 = (void *) &cmd1[1];
+               cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE;
+               cmd2->header.size = sizeof(cmd2->body);
+               cmd2->body.sid = res->id;
+               res->backup_dirty = false;
+       }
+       vmw_fifo_commit(dev_priv, submit_size);
+
+       return 0;
+}
+
+static int vmw_gb_surface_unbind(struct vmw_resource *res,
+                                bool readback,
+                                struct ttm_validate_buffer *val_buf)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct ttm_buffer_object *bo = val_buf->bo;
+       struct vmw_fence_obj *fence;
+
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdReadbackGBSurface body;
+       } *cmd1;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdInvalidateGBSurface body;
+       } *cmd2;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdBindGBSurface body;
+       } *cmd3;
+       uint32_t submit_size;
+       uint8_t *cmd;
+
+
+       BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
+
+       submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2));
+       cmd = vmw_fifo_reserve(dev_priv, submit_size);
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for surface "
+                         "unbinding.\n");
+               return -ENOMEM;
+       }
+
+       if (readback) {
+               cmd1 = (void *) cmd;
+               cmd1->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE;
+               cmd1->header.size = sizeof(cmd1->body);
+               cmd1->body.sid = res->id;
+               cmd3 = (void *) &cmd1[1];
+       } else {
+               cmd2 = (void *) cmd;
+               cmd2->header.id = SVGA_3D_CMD_INVALIDATE_GB_SURFACE;
+               cmd2->header.size = sizeof(cmd2->body);
+               cmd2->body.sid = res->id;
+               cmd3 = (void *) &cmd2[1];
+       }
+
+       cmd3->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
+       cmd3->header.size = sizeof(cmd3->body);
+       cmd3->body.sid = res->id;
+       cmd3->body.mobid = SVGA3D_INVALID_ID;
+
+       vmw_fifo_commit(dev_priv, submit_size);
+
+       /*
+        * Create a fence object and fence the backup buffer.
+        */
+
+       (void) vmw_execbuf_fence_commands(NULL, dev_priv,
+                                         &fence, NULL);
+
+       vmw_fence_single_bo(val_buf->bo, fence);
+
+       if (likely(fence != NULL))
+               vmw_fence_obj_unreference(&fence);
+
+       return 0;
+}
+
+static int vmw_gb_surface_destroy(struct vmw_resource *res)
+{
+       struct vmw_private *dev_priv = res->dev_priv;
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyGBSurface body;
+       } *cmd;
+
+       if (likely(res->id == -1))
+               return 0;
+
+       mutex_lock(&dev_priv->binding_mutex);
+       vmw_context_binding_res_list_kill(&res->binding_head);
+
+       cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for surface "
+                         "destruction.\n");
+               mutex_unlock(&dev_priv->binding_mutex);
+               return -ENOMEM;
+       }
+
+       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SURFACE;
+       cmd->header.size = sizeof(cmd->body);
+       cmd->body.sid = res->id;
+       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       mutex_unlock(&dev_priv->binding_mutex);
+       vmw_resource_release_id(res);
+       vmw_3d_resource_dec(dev_priv, false);
+
+       return 0;
+}
+
+/**
+ * vmw_gb_surface_define_ioctl - Ioctl function implementing
+ *                               the user surface define functionality.
+ *
+ * @dev:            Pointer to a struct drm_device.
+ * @data:           Pointer to data copied from / to user-space.
+ * @file_priv:      Pointer to a drm file private structure.
+ */
+int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct vmw_user_surface *user_srf;
+       struct vmw_surface *srf;
+       struct vmw_resource *res;
+       struct vmw_resource *tmp;
+       union drm_vmw_gb_surface_create_arg *arg =
+           (union drm_vmw_gb_surface_create_arg *)data;
+       struct drm_vmw_gb_surface_create_req *req = &arg->req;
+       struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       int ret;
+       uint32_t size;
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       const struct svga3d_surface_desc *desc;
+       uint32_t backup_handle;
+
+       if (unlikely(vmw_user_surface_size == 0))
+               vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
+                       128;
+
+       size = vmw_user_surface_size + 128;
+
+       desc = svga3dsurface_get_desc(req->format);
+       if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
+               DRM_ERROR("Invalid surface format for surface creation.\n");
+               return -EINVAL;
+       }
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+                                  size, false, true);
+       if (unlikely(ret != 0)) {
+               if (ret != -ERESTARTSYS)
+                       DRM_ERROR("Out of graphics memory for surface"
+                                 " creation.\n");
+               goto out_unlock;
+       }
+
+       user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
+       if (unlikely(user_srf == NULL)) {
+               ret = -ENOMEM;
+               goto out_no_user_srf;
+       }
+
+       srf = &user_srf->srf;
+       res = &srf->res;
+
+       srf->flags = req->svga3d_flags;
+       srf->format = req->format;
+       srf->scanout = req->drm_surface_flags & drm_vmw_surface_flag_scanout;
+       srf->mip_levels[0] = req->mip_levels;
+       srf->num_sizes = 1;
+       srf->sizes = NULL;
+       srf->offsets = NULL;
+       user_srf->size = size;
+       srf->base_size = req->base_size;
+       srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
+       srf->multisample_count = req->multisample_count;
+       res->backup_size = svga3dsurface_get_serialized_size
+         (srf->format, srf->base_size, srf->mip_levels[0],
+          srf->flags & SVGA3D_SURFACE_CUBEMAP);
+
+       user_srf->prime.base.shareable = false;
+       user_srf->prime.base.tfile = NULL;
+
+       /**
+        * From this point, the generic resource management functions
+        * destroy the object on failure.
+        */
+
+       ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
+       if (unlikely(ret != 0))
+               goto out_unlock;
+
+       if (req->buffer_handle != SVGA3D_INVALID_ID) {
+               ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
+                                            &res->backup);
+       } else if (req->drm_surface_flags &
+                  drm_vmw_surface_flag_create_buffer)
+               ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
+                                           res->backup_size,
+                                           req->drm_surface_flags &
+                                           drm_vmw_surface_flag_shareable,
+                                           &backup_handle,
+                                           &res->backup);
+
+       if (unlikely(ret != 0)) {
+               vmw_resource_unreference(&res);
+               goto out_unlock;
+       }
+
+       tmp = vmw_resource_reference(&srf->res);
+       ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
+                                   req->drm_surface_flags &
+                                   drm_vmw_surface_flag_shareable,
+                                   VMW_RES_SURFACE,
+                                   &vmw_user_surface_base_release, NULL);
+
+       if (unlikely(ret != 0)) {
+               vmw_resource_unreference(&tmp);
+               vmw_resource_unreference(&res);
+               goto out_unlock;
+       }
+
+       rep->handle = user_srf->prime.base.hash.key;
+       rep->backup_size = res->backup_size;
+       if (res->backup) {
+               rep->buffer_map_handle =
+                       drm_vma_node_offset_addr(&res->backup->base.vma_node);
+               rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE;
+               rep->buffer_handle = backup_handle;
+       } else {
+               rep->buffer_map_handle = 0;
+               rep->buffer_size = 0;
+               rep->buffer_handle = SVGA3D_INVALID_ID;
+       }
+
+       vmw_resource_unreference(&res);
+
+       ttm_read_unlock(&vmaster->lock);
+       return 0;
+out_no_user_srf:
+       ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
+out_unlock:
+       ttm_read_unlock(&vmaster->lock);
+       return ret;
+}
+
+/**
+ * vmw_gb_surface_reference_ioctl - Ioctl function implementing
+ *                                  the user surface reference functionality.
+ *
+ * @dev:            Pointer to a struct drm_device.
+ * @data:           Pointer to data copied from / to user-space.
+ * @file_priv:      Pointer to a drm file private structure.
+ */
+int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       union drm_vmw_gb_surface_reference_arg *arg =
+           (union drm_vmw_gb_surface_reference_arg *)data;
+       struct drm_vmw_surface_arg *req = &arg->req;
+       struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep;
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       struct vmw_surface *srf;
+       struct vmw_user_surface *user_srf;
+       struct ttm_base_object *base;
+       uint32_t backup_handle;
+       int ret = -EINVAL;
+
+       base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
+       if (unlikely(base == NULL)) {
+               DRM_ERROR("Could not find surface to reference.\n");
+               return -EINVAL;
+       }
+
+       if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
+               goto out_bad_resource;
+
+       user_srf = container_of(base, struct vmw_user_surface, prime.base);
+       srf = &user_srf->srf;
+       if (srf->res.backup == NULL) {
+               DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
+               goto out_bad_resource;
+       }
+
+       ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
+                                TTM_REF_USAGE, NULL);
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Could not add a reference to a GB surface.\n");
+               goto out_bad_resource;
+       }
+
+       mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
+       ret = vmw_user_dmabuf_reference(tfile, srf->res.backup,
+                                       &backup_handle);
+       mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Could not add a reference to a GB surface "
+                         "backup buffer.\n");
+               (void) ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+                                                req->sid,
+                                                TTM_REF_USAGE);
+               goto out_bad_resource;
+       }
+
+       rep->creq.svga3d_flags = srf->flags;
+       rep->creq.format = srf->format;
+       rep->creq.mip_levels = srf->mip_levels[0];
+       rep->creq.drm_surface_flags = 0;
+       rep->creq.multisample_count = srf->multisample_count;
+       rep->creq.autogen_filter = srf->autogen_filter;
+       rep->creq.buffer_handle = backup_handle;
+       rep->creq.base_size = srf->base_size;
+       rep->crep.handle = user_srf->prime.base.hash.key;
+       rep->crep.backup_size = srf->res.backup_size;
+       rep->crep.buffer_handle = backup_handle;
+       rep->crep.buffer_map_handle =
+               drm_vma_node_offset_addr(&srf->res.backup->base.vma_node);
+       rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE;
+
+out_bad_resource:
+       ttm_base_object_unref(&base);
+
+       return ret;
+}
index 78be66176840d1c6abdf29dd632d7a107f6ad2d3..9425098928957350abda4a9bdf280a819fee15eb 100644 (file)
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
 
 #define BASE_SYSFS_ATTR_NO     2       /* Sysfs Base attr no for coretemp */
 #define NUM_REAL_CORES         32      /* Number of Real cores per cpu */
-#define CORETEMP_NAME_LENGTH   17      /* String Length of attrs */
+#define CORETEMP_NAME_LENGTH   19      /* String Length of attrs */
 #define MAX_CORE_ATTRS         4       /* Maximum no of basic attrs */
 #define TOTAL_ATTRS            (MAX_CORE_ATTRS + 1)
 #define MAX_CORE_DATA          (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
index 92d1206482a62ca57128690e49735dea2f00aaa3..797ed29a36ea7969765e90641d15f3a66e982db3 100644 (file)
@@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table;
  * which is also the index into the MWAIT hint array.
  * Thus C0 is a dummy.
  */
-static struct cpuidle_state nehalem_cstates[] __initdata = {
+static struct cpuidle_state nehalem_cstates[] = {
        {
                .name = "C1-NHM",
                .desc = "MWAIT 0x00",
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state snb_cstates[] __initdata = {
+static struct cpuidle_state snb_cstates[] = {
        {
                .name = "C1-SNB",
                .desc = "MWAIT 0x00",
@@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state ivb_cstates[] __initdata = {
+static struct cpuidle_state ivb_cstates[] = {
        {
                .name = "C1-IVB",
                .desc = "MWAIT 0x00",
@@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state hsw_cstates[] __initdata = {
+static struct cpuidle_state hsw_cstates[] = {
        {
                .name = "C1-HSW",
                .desc = "MWAIT 0x00",
@@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state atom_cstates[] __initdata = {
+static struct cpuidle_state atom_cstates[] = {
        {
                .name = "C1E-ATM",
                .desc = "MWAIT 0x00",
@@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = {
        {
                .enter = NULL }
 };
-static struct cpuidle_state avn_cstates[] __initdata = {
+static struct cpuidle_state avn_cstates[] = {
        {
                .name = "C1-AVN",
                .desc = "MWAIT 0x00",
@@ -344,6 +344,8 @@ static struct cpuidle_state avn_cstates[] __initdata = {
                .exit_latency = 15,
                .target_residency = 45,
                .enter = &intel_idle },
+       {
+               .enter = NULL }
 };
 
 /**
@@ -377,6 +379,9 @@ static int intel_idle(struct cpuidle_device *dev,
 
        if (!current_set_polling_and_test()) {
 
+               if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
+                       clflush((void *)&current_thread_info()->flags);
+
                __monitor((void *)&current_thread_info()->flags, 0, 0);
                smp_mb();
                if (!need_resched())
index acb7f90359a3460371c9d1e8a00cd15c3a77a26d..749a6cadab8b3708d9a9e2d50f9d086f6f17e80e 100644 (file)
@@ -200,7 +200,13 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
                        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                        .address = 1,
                        .scan_index = 1,
-                       .scan_type = IIO_ST('u', 12, 16, 0),
+                       .scan_type = {
+                               .sign = 'u',
+                               .realbits = 12,
+                               .storagebits = 16,
+                               .shift = 0,
+                               .endianness = IIO_BE,
+                       },
                },
                .channel[1] = {
                        .type = IIO_VOLTAGE,
@@ -210,7 +216,13 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
                        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                        .address = 0,
                        .scan_index = 0,
-                       .scan_type = IIO_ST('u', 12, 16, 0),
+                       .scan_type = {
+                               .sign = 'u',
+                               .realbits = 12,
+                               .storagebits = 16,
+                               .shift = 0,
+                               .endianness = IIO_BE,
+                       },
                },
                .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
                .int_vref_mv = 2500,
index 3fb7757a10287b1991b4ef23676a8e4d2b315dad..368660dfe135a51c3cac05dd90d7dcb75dacb7c2 100644 (file)
@@ -651,7 +651,12 @@ static const struct iio_chan_spec adis16448_channels[] = {
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = ADIS16448_BARO_OUT,
                .scan_index = ADIS16400_SCAN_BARO,
-               .scan_type = IIO_ST('s', 16, 16, 0),
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 16,
+                       .storagebits = 16,
+                       .endianness = IIO_BE,
+               },
        },
        ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
        IIO_CHAN_SOFT_TIMESTAMP(11)
index 21df5713001831f91f5dbd592df94837bf612186..0922e39b0ea979a8355ac5da395d527ab871d269 100644 (file)
@@ -387,7 +387,7 @@ static int cm36651_read_int_time(struct cm36651_data *cm36651,
                return -EINVAL;
        }
 
-       return IIO_VAL_INT_PLUS_MICRO;
+       return IIO_VAL_INT;
 }
 
 static int cm36651_write_int_time(struct cm36651_data *cm36651,
index c47c2034ca71f9a95f3153fbc31756fc34b1fde0..0717940ec3b5080083cb53e8d8526bdf692c829a 100644 (file)
@@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id)
 static void rem_ref(struct iw_cm_id *cm_id)
 {
        struct iwcm_id_private *cm_id_priv;
+       int cb_destroy;
+
        cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
-       if (iwcm_deref_id(cm_id_priv) &&
-           test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+
+       /*
+        * Test bit before deref in case the cm_id gets freed on another
+        * thread.
+        */
+       cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
+       if (iwcm_deref_id(cm_id_priv) && cb_destroy) {
                BUG_ON(!list_empty(&cm_id_priv->work_list));
                free_cm_id(cm_id_priv);
        }
index bdc842e9faefe4ba477b96c479975643bfdc6366..a283274a5a09fa17b0dede8f5819ef9dfaf4458b 100644 (file)
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)                      \
        do {                                                            \
-               (udata)->inbuf  = (void __user *) (ibuf);               \
+               (udata)->inbuf  = (const void __user *) (ibuf);         \
                (udata)->outbuf = (void __user *) (obuf);               \
                (udata)->inlen  = (ilen);                               \
                (udata)->outlen = (olen);                               \
        } while (0)
 
+#define INIT_UDATA_BUF_OR_NULL(udata, ibuf, obuf, ilen, olen)                  \
+       do {                                                                    \
+               (udata)->inbuf  = (ilen) ? (const void __user *) (ibuf) : NULL; \
+               (udata)->outbuf = (olen) ? (void __user *) (obuf) : NULL;       \
+               (udata)->inlen  = (ilen);                                       \
+               (udata)->outlen = (olen);                                       \
+       } while (0)
+
 /*
  * Our lifetime rules for these structs are the following:
  *
index 65f6e7dc380c382cc0335e495fb2f583a4eef7b7..f1cc83855af65dd334a21d7c82a94f252413e42a 100644 (file)
@@ -2593,6 +2593,9 @@ out_put:
 static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
                                union ib_flow_spec *ib_spec)
 {
+       if (kern_spec->reserved)
+               return -EINVAL;
+
        ib_spec->type = kern_spec->type;
 
        switch (ib_spec->type) {
@@ -2646,6 +2649,9 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
        void *ib_spec;
        int i;
 
+       if (ucore->inlen < sizeof(cmd))
+               return -EINVAL;
+
        if (ucore->outlen < sizeof(resp))
                return -ENOSPC;
 
@@ -2671,6 +2677,10 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
            (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec)))
                return -EINVAL;
 
+       if (cmd.flow_attr.reserved[0] ||
+           cmd.flow_attr.reserved[1])
+               return -EINVAL;
+
        if (cmd.flow_attr.num_of_specs) {
                kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size,
                                         GFP_KERNEL);
@@ -2731,6 +2741,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
        if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) {
                pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n",
                        i, cmd.flow_attr.size);
+               err = -EINVAL;
                goto err_free;
        }
        flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER);
@@ -2791,10 +2802,16 @@ int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file,
        struct ib_uobject               *uobj;
        int                             ret;
 
+       if (ucore->inlen < sizeof(cmd))
+               return -EINVAL;
+
        ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
        if (ret)
                return ret;
 
+       if (cmd.comp_mask)
+               return -EINVAL;
+
        uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle,
                              file->ucontext);
        if (!uobj)
index 34386943ebcff4cf18849082add568f5fc73bc5a..08219fb3338b0652f350da1af864b4cfb355ff3c 100644 (file)
@@ -668,25 +668,30 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
                if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count)
                        return -EINVAL;
 
+               if (ex_hdr.cmd_hdr_reserved)
+                       return -EINVAL;
+
                if (ex_hdr.response) {
                        if (!hdr.out_words && !ex_hdr.provider_out_words)
                                return -EINVAL;
+
+                       if (!access_ok(VERIFY_WRITE,
+                                      (void __user *) (unsigned long) ex_hdr.response,
+                                      (hdr.out_words + ex_hdr.provider_out_words) * 8))
+                               return -EFAULT;
                } else {
                        if (hdr.out_words || ex_hdr.provider_out_words)
                                return -EINVAL;
                }
 
-               INIT_UDATA(&ucore,
-                          (hdr.in_words) ? buf : 0,
-                          (unsigned long)ex_hdr.response,
-                          hdr.in_words * 8,
-                          hdr.out_words * 8);
-
-               INIT_UDATA(&uhw,
-                          (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0,
-                          (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0,
-                          ex_hdr.provider_in_words * 8,
-                          ex_hdr.provider_out_words * 8);
+               INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response,
+                                      hdr.in_words * 8, hdr.out_words * 8);
+
+               INIT_UDATA_BUF_OR_NULL(&uhw,
+                                      buf + ucore.inlen,
+                                      (unsigned long) ex_hdr.response + ucore.outlen,
+                                      ex_hdr.provider_in_words * 8,
+                                      ex_hdr.provider_out_words * 8);
 
                err = uverbs_ex_cmd_table[command](file,
                                                   &ucore,
index 12fef76c791c524454bd9a0c48d5b4a967ac19af..45126879ad28a2149351232a1f9c4a2551f06c09 100644 (file)
@@ -524,50 +524,6 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
        return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
-#define VLAN_NONE 0xfff
-#define FILTER_SEL_VLAN_NONE 0xffff
-#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
-#define FILTER_SEL_WIDTH_VIN_P_FC \
-       (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
-#define FILTER_SEL_WIDTH_TAG_P_FC \
-       (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
-#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
-
-static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
-                                 struct l2t_entry *l2t)
-{
-       unsigned int ntuple = 0;
-       u32 viid;
-
-       switch (dev->rdev.lldi.filt_mode) {
-
-       /* default filter mode */
-       case HW_TPL_FR_MT_PR_IV_P_FC:
-               if (l2t->vlan == VLAN_NONE)
-                       ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
-               else {
-                       ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
-                       ntuple |= 1 << FILTER_SEL_WIDTH_TAG_P_FC;
-               }
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       case HW_TPL_FR_MT_PR_OV_P_FC: {
-               viid = cxgb4_port_viid(l2t->neigh->dev);
-
-               ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
-               ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
-               ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       }
-       default:
-               break;
-       }
-       return ntuple;
-}
-
 static int send_connect(struct c4iw_ep *ep)
 {
        struct cpl_act_open_req *req;
@@ -641,8 +597,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req->local_ip = la->sin_addr.s_addr;
                        req->peer_ip = ra->sin_addr.s_addr;
                        req->opt0 = cpu_to_be64(opt0);
-                       req->params = cpu_to_be32(select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t));
+                       req->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req->opt2 = cpu_to_be32(opt2);
                } else {
                        req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
@@ -662,9 +619,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req6->peer_ip_lo = *((__be64 *)
                                                (ra6->sin6_addr.s6_addr + 8));
                        req6->opt0 = cpu_to_be64(opt0);
-                       req6->params = cpu_to_be32(
-                                       select_ntuple(ep->com.dev, ep->dst,
-                                                     ep->l2t));
+                       req6->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req6->opt2 = cpu_to_be32(opt2);
                }
        } else {
@@ -681,8 +638,9 @@ static int send_connect(struct c4iw_ep *ep)
                        t5_req->peer_ip = ra->sin_addr.s_addr;
                        t5_req->opt0 = cpu_to_be64(opt0);
                        t5_req->params = cpu_to_be64(V_FILTER_TUPLE(
-                                               select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t)));
+                                                    cxgb4_select_ntuple(
+                                            ep->com.dev->rdev.lldi.ports[0],
+                                            ep->l2t)));
                        t5_req->opt2 = cpu_to_be32(opt2);
                } else {
                        t5_req6 = (struct cpl_t5_act_open_req6 *)
@@ -703,7 +661,9 @@ static int send_connect(struct c4iw_ep *ep)
                                                (ra6->sin6_addr.s6_addr + 8));
                        t5_req6->opt0 = cpu_to_be64(opt0);
                        t5_req6->params = (__force __be64)cpu_to_be32(
-                               select_ntuple(ep->com.dev, ep->dst, ep->l2t));
+                                                       cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        t5_req6->opt2 = cpu_to_be32(opt2);
                }
        }
@@ -1630,7 +1590,8 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
        memset(req, 0, sizeof(*req));
        req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR));
        req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
-       req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst,
+       req->le.filter = cpu_to_be32(cxgb4_select_ntuple(
+                                    ep->com.dev->rdev.lldi.ports[0],
                                     ep->l2t));
        sin = (struct sockaddr_in *)&ep->com.local_addr;
        req->le.lport = sin->sin_port;
@@ -2938,7 +2899,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
        /*
         * Allocate a server TID.
         */
-       if (dev->rdev.lldi.enable_fw_ofld_conn)
+       if (dev->rdev.lldi.enable_fw_ofld_conn &&
+           ep->com.local_addr.ss_family == AF_INET)
                ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids,
                                             cm_id->local_addr.ss_family, ep);
        else
@@ -3323,9 +3285,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        /*
         * Calculate the server tid from filter hit index from cpl_rx_pkt.
         */
-       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val)
-                                         - dev->rdev.lldi.tids->sftid_base
-                                         + dev->rdev.lldi.tids->nstids;
+       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val);
 
        lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
        if (!lep) {
@@ -3397,7 +3357,9 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        window = (__force u16) htons((__force u16)tcph->window);
 
        /* Calcuate filter portion for LE region. */
-       filter = (__force unsigned int) cpu_to_be32(select_ntuple(dev, dst, e));
+       filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple(
+                                                   dev->rdev.lldi.ports[0],
+                                                   e));
 
        /*
         * Synthesize the cpl_pass_accept_req. We have everything except the
index 4cb8eb24497cfa61821b4863c4026ff5a061405a..84e45006451cd3983cd1b28bfb22d2c0a9c02ef7 100644 (file)
@@ -173,7 +173,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
        return ret;
 }
 
-int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
+static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
 {
        u32 remain = len;
        u32 dmalen;
index c29b5c8388331458bb2a2caf85580d76031f1dcb..cdc7df4fdb8aedea8c9026de82d774e5f5fe502b 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/if_arp.h>      /* For ARPHRD_xxx */
 #include <linux/module.h>
 #include <net/rtnetlink.h>
 #include "ipoib.h"
@@ -103,7 +104,7 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
                return -EINVAL;
 
        pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
-       if (!pdev)
+       if (!pdev || pdev->type != ARPHRD_INFINIBAND)
                return -ENODEV;
 
        ppriv = netdev_priv(pdev);
index 6be57c38638d28dd0a39464bffe391c4a093f478..9804fca6bf0605a074c13f470e4bf6cf8413bd66 100644 (file)
@@ -207,7 +207,9 @@ isert_free_rx_descriptors(struct isert_conn *isert_conn)
        isert_conn->conn_rx_descs = NULL;
 }
 
+static void isert_cq_tx_work(struct work_struct *);
 static void isert_cq_tx_callback(struct ib_cq *, void *);
+static void isert_cq_rx_work(struct work_struct *);
 static void isert_cq_rx_callback(struct ib_cq *, void *);
 
 static int
@@ -259,26 +261,36 @@ isert_create_device_ib_res(struct isert_device *device)
                cq_desc[i].device = device;
                cq_desc[i].cq_index = i;
 
+               INIT_WORK(&cq_desc[i].cq_rx_work, isert_cq_rx_work);
                device->dev_rx_cq[i] = ib_create_cq(device->ib_device,
                                                isert_cq_rx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
                                                ISER_MAX_RX_CQ_LEN, i);
-               if (IS_ERR(device->dev_rx_cq[i]))
+               if (IS_ERR(device->dev_rx_cq[i])) {
+                       ret = PTR_ERR(device->dev_rx_cq[i]);
+                       device->dev_rx_cq[i] = NULL;
                        goto out_cq;
+               }
 
+               INIT_WORK(&cq_desc[i].cq_tx_work, isert_cq_tx_work);
                device->dev_tx_cq[i] = ib_create_cq(device->ib_device,
                                                isert_cq_tx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
                                                ISER_MAX_TX_CQ_LEN, i);
-               if (IS_ERR(device->dev_tx_cq[i]))
+               if (IS_ERR(device->dev_tx_cq[i])) {
+                       ret = PTR_ERR(device->dev_tx_cq[i]);
+                       device->dev_tx_cq[i] = NULL;
                        goto out_cq;
+               }
 
-               if (ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP))
+               ret = ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP);
+               if (ret)
                        goto out_cq;
 
-               if (ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP))
+               ret = ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP);
+               if (ret)
                        goto out_cq;
        }
 
@@ -1724,7 +1736,6 @@ isert_cq_tx_callback(struct ib_cq *cq, void *context)
 {
        struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context;
 
-       INIT_WORK(&cq_desc->cq_tx_work, isert_cq_tx_work);
        queue_work(isert_comp_wq, &cq_desc->cq_tx_work);
 }
 
@@ -1768,7 +1779,6 @@ isert_cq_rx_callback(struct ib_cq *cq, void *context)
 {
        struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context;
 
-       INIT_WORK(&cq_desc->cq_rx_work, isert_cq_rx_work);
        queue_work(isert_rx_wq, &cq_desc->cq_rx_work);
 }
 
index 846ccdd905b19b66872762fd05db29ea0552a8cb..d2965e4b32243a90f40db55a7722c3229d4edb3a 100644 (file)
@@ -1871,6 +1871,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
                break;
 
        case EV_ABS:
+               input_alloc_absinfo(dev);
+               if (!dev->absinfo)
+                       return;
+
                __set_bit(code, dev->absbit);
                break;
 
index 75762d6ff3ba70934190bb2fe70ef6d6135d49c5..aa127ba392a45cbabe9f95180876543dd6441865 100644 (file)
@@ -455,7 +455,18 @@ static void zforce_complete(struct zforce_ts *ts, int cmd, int result)
        }
 }
 
-static irqreturn_t zforce_interrupt(int irq, void *dev_id)
+static irqreturn_t zforce_irq(int irq, void *dev_id)
+{
+       struct zforce_ts *ts = dev_id;
+       struct i2c_client *client = ts->client;
+
+       if (ts->suspended && device_may_wakeup(&client->dev))
+               pm_wakeup_event(&client->dev, 500);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 {
        struct zforce_ts *ts = dev_id;
        struct i2c_client *client = ts->client;
@@ -465,12 +476,10 @@ static irqreturn_t zforce_interrupt(int irq, void *dev_id)
        u8 *payload;
 
        /*
-        * When suspended, emit a wakeup signal if necessary and return.
+        * When still suspended, return.
         * Due to the level-interrupt we will get re-triggered later.
         */
        if (ts->suspended) {
-               if (device_may_wakeup(&client->dev))
-                       pm_wakeup_event(&client->dev, 500);
                msleep(20);
                return IRQ_HANDLED;
        }
@@ -763,8 +772,8 @@ static int zforce_probe(struct i2c_client *client,
         * Therefore we can trigger the interrupt anytime it is low and do
         * not need to limit it to the interrupt edge.
         */
-       ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                       zforce_interrupt,
+       ret = devm_request_threaded_irq(&client->dev, client->irq,
+                                       zforce_irq, zforce_irq_thread,
                                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                        input_dev->name, ts);
        if (ret) {
index 82cec63a90112e184c96a2e21e612df977adf7b7..3ee78f02e5d7d940d531aa6ab03c8dc681c9cb3c 100644 (file)
@@ -149,8 +149,9 @@ static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
 static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
                                         int irq, int do_mask)
 {
-       int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
-       int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
+       /* The PRIO register is assumed to be 32-bit with fixed 4-bit fields. */
+       int bitfield_width = 4;
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
                                      shift, bitfield_width,
@@ -159,8 +160,9 @@ static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
 
 static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
 {
+       /* The SENSE register is assumed to be 32-bit. */
        int bitfield_width = p->config.sense_bitfield_width;
-       int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
 
index 497bd026c2378eec6e781df68d007c135be4c1f7..4a48255281887e8c03f9dbacccf404f4f9c52476 100644 (file)
@@ -1643,10 +1643,6 @@ setup_hfcpci(struct IsdnCard *card)
        int i;
        struct pci_dev *tmp_hfcpci = NULL;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, hfcpci_revision);
        printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
 
index f6ab63aa699590278531ba9ae6ceabe75ba90813..33eeb4602c7e7131078d78d97b24f09971b8396e 100644 (file)
@@ -290,10 +290,6 @@ int setup_telespci(struct IsdnCard *card)
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, telespci_revision);
        printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_TELESPCI)
index 05188351711d2d80f5ac8cd0a006159b732b2c90..a97263e902ffc6b927db6b935cb290902909f21e 100644 (file)
@@ -244,18 +244,12 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       mutex_lock(&chip->lock);
-
        for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) {
                ret = lp55xx_write(chip, addr[idx] + i, pattern[i]);
-               if (ret) {
-                       mutex_unlock(&chip->lock);
+               if (ret)
                        return -EINVAL;
-               }
        }
 
-       mutex_unlock(&chip->lock);
-
        return size;
 
 err:
@@ -427,15 +421,17 @@ static ssize_t store_engine_load(struct device *dev,
 {
        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
        struct lp55xx_chip *chip = led->chip;
+       int ret;
 
        mutex_lock(&chip->lock);
 
        chip->engine_idx = nr;
        lp5521_load_engine(chip);
+       ret = lp5521_update_program_memory(chip, buf, len);
 
        mutex_unlock(&chip->lock);
 
-       return lp5521_update_program_memory(chip, buf, len);
+       return ret;
 }
 store_load(1)
 store_load(2)
index 6b553d9f4266d570eec78a2180eee9b56194d62c..fd9ab5f61441c50716620138bf55b175c2ac1045 100644 (file)
@@ -337,18 +337,12 @@ static int lp5523_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       mutex_lock(&chip->lock);
-
        for (i = 0; i < LP5523_PROGRAM_LENGTH; i++) {
                ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + i, pattern[i]);
-               if (ret) {
-                       mutex_unlock(&chip->lock);
+               if (ret)
                        return -EINVAL;
-               }
        }
 
-       mutex_unlock(&chip->lock);
-
        return size;
 
 err:
@@ -548,15 +542,17 @@ static ssize_t store_engine_load(struct device *dev,
 {
        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
        struct lp55xx_chip *chip = led->chip;
+       int ret;
 
        mutex_lock(&chip->lock);
 
        chip->engine_idx = nr;
        lp5523_load_engine_and_select_page(chip);
+       ret = lp5523_update_program_memory(chip, buf, len);
 
        mutex_unlock(&chip->lock);
 
-       return lp5523_update_program_memory(chip, buf, len);
+       return ret;
 }
 store_load(1)
 store_load(2)
index 2b46bf1d7e40ca7375517ebb97a2225475844a91..4c9852d92b0a909d5b103510ae77d55f4bb05ad0 100644 (file)
@@ -421,9 +421,11 @@ out:
 
        if (watermark <= WATERMARK_METADATA) {
                SET_GC_MARK(b, GC_MARK_METADATA);
+               SET_GC_MOVE(b, 0);
                b->prio = BTREE_PRIO;
        } else {
                SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
+               SET_GC_MOVE(b, 0);
                b->prio = INITIAL_PRIO;
        }
 
index 4beb55a0ff30dc9da10c340270e9cbd1c0e1c0b0..754f4317748322e7450d69da9591b6b72aff6dc4 100644 (file)
@@ -197,7 +197,7 @@ struct bucket {
        uint8_t         disk_gen;
        uint8_t         last_gc; /* Most out of date gen in the btree */
        uint8_t         gc_gen;
-       uint16_t        gc_mark;
+       uint16_t        gc_mark; /* Bitfield used by GC. See below for field */
 };
 
 /*
@@ -209,7 +209,8 @@ BITMASK(GC_MARK,     struct bucket, gc_mark, 0, 2);
 #define GC_MARK_RECLAIMABLE    0
 #define GC_MARK_DIRTY          1
 #define GC_MARK_METADATA       2
-BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 14);
+BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 13);
+BITMASK(GC_MOVE, struct bucket, gc_mark, 15, 1);
 
 #include "journal.h"
 #include "stats.h"
@@ -372,14 +373,14 @@ struct cached_dev {
        unsigned char           writeback_percent;
        unsigned                writeback_delay;
 
-       int                     writeback_rate_change;
-       int64_t                 writeback_rate_derivative;
        uint64_t                writeback_rate_target;
+       int64_t                 writeback_rate_proportional;
+       int64_t                 writeback_rate_derivative;
+       int64_t                 writeback_rate_change;
 
        unsigned                writeback_rate_update_seconds;
        unsigned                writeback_rate_d_term;
        unsigned                writeback_rate_p_term_inverse;
-       unsigned                writeback_rate_d_smooth;
 };
 
 enum alloc_watermarks {
@@ -445,7 +446,6 @@ struct cache {
         * call prio_write() to keep gens from wrapping.
         */
        uint8_t                 need_save_prio;
-       unsigned                gc_move_threshold;
 
        /*
         * If nonzero, we know we aren't going to find any buckets to invalidate
index 5e2765aadce174e9b7cffd479667a2c48bcf500f..31bb53fcc67a40806cf73659a596f98297d36128 100644 (file)
@@ -1561,6 +1561,28 @@ size_t bch_btree_gc_finish(struct cache_set *c)
                SET_GC_MARK(PTR_BUCKET(c, &c->uuid_bucket, i),
                            GC_MARK_METADATA);
 
+       /* don't reclaim buckets to which writeback keys point */
+       rcu_read_lock();
+       for (i = 0; i < c->nr_uuids; i++) {
+               struct bcache_device *d = c->devices[i];
+               struct cached_dev *dc;
+               struct keybuf_key *w, *n;
+               unsigned j;
+
+               if (!d || UUID_FLASH_ONLY(&c->uuids[i]))
+                       continue;
+               dc = container_of(d, struct cached_dev, disk);
+
+               spin_lock(&dc->writeback_keys.lock);
+               rbtree_postorder_for_each_entry_safe(w, n,
+                                       &dc->writeback_keys.keys, node)
+                       for (j = 0; j < KEY_PTRS(&w->key); j++)
+                               SET_GC_MARK(PTR_BUCKET(c, &w->key, j),
+                                           GC_MARK_DIRTY);
+               spin_unlock(&dc->writeback_keys.lock);
+       }
+       rcu_read_unlock();
+
        for_each_cache(ca, c, i) {
                uint64_t *i;
 
@@ -1817,7 +1839,8 @@ static bool fix_overlapping_extents(struct btree *b, struct bkey *insert,
                        if (KEY_START(k) > KEY_START(insert) + sectors_found)
                                goto check_failed;
 
-                       if (KEY_PTRS(replace_key) != KEY_PTRS(k))
+                       if (KEY_PTRS(k) != KEY_PTRS(replace_key) ||
+                           KEY_DIRTY(k) != KEY_DIRTY(replace_key))
                                goto check_failed;
 
                        /* skip past gen */
@@ -2217,7 +2240,7 @@ struct btree_insert_op {
        struct bkey     *replace_key;
 };
 
-int btree_insert_fn(struct btree_op *b_op, struct btree *b)
+static int btree_insert_fn(struct btree_op *b_op, struct btree *b)
 {
        struct btree_insert_op *op = container_of(b_op,
                                        struct btree_insert_op, op);
index 7c1275e66025b691ec8ee4896448d46e28a2c5d9..f2f0998c4a91872407dd036a54fe72d243885fed 100644 (file)
@@ -25,10 +25,9 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
        unsigned i;
 
        for (i = 0; i < KEY_PTRS(k); i++) {
-               struct cache *ca = PTR_CACHE(c, k, i);
                struct bucket *g = PTR_BUCKET(c, k, i);
 
-               if (GC_SECTORS_USED(g) < ca->gc_move_threshold)
+               if (GC_MOVE(g))
                        return true;
        }
 
@@ -65,11 +64,16 @@ static void write_moving_finish(struct closure *cl)
 
 static void read_moving_endio(struct bio *bio, int error)
 {
+       struct bbio *b = container_of(bio, struct bbio, bio);
        struct moving_io *io = container_of(bio->bi_private,
                                            struct moving_io, cl);
 
        if (error)
                io->op.error = error;
+       else if (!KEY_DIRTY(&b->key) &&
+                ptr_stale(io->op.c, &b->key, 0)) {
+               io->op.error = -EINTR;
+       }
 
        bch_bbio_endio(io->op.c, bio, error, "reading data to move");
 }
@@ -141,6 +145,11 @@ static void read_moving(struct cache_set *c)
                if (!w)
                        break;
 
+               if (ptr_stale(c, &w->key, 0)) {
+                       bch_keybuf_del(&c->moving_gc_keys, w);
+                       continue;
+               }
+
                io = kzalloc(sizeof(struct moving_io) + sizeof(struct bio_vec)
                             * DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
                             GFP_KERNEL);
@@ -184,7 +193,8 @@ static bool bucket_cmp(struct bucket *l, struct bucket *r)
 
 static unsigned bucket_heap_top(struct cache *ca)
 {
-       return GC_SECTORS_USED(heap_peek(&ca->heap));
+       struct bucket *b;
+       return (b = heap_peek(&ca->heap)) ? GC_SECTORS_USED(b) : 0;
 }
 
 void bch_moving_gc(struct cache_set *c)
@@ -226,9 +236,8 @@ void bch_moving_gc(struct cache_set *c)
                        sectors_to_move -= GC_SECTORS_USED(b);
                }
 
-               ca->gc_move_threshold = bucket_heap_top(ca);
-
-               pr_debug("threshold %u", ca->gc_move_threshold);
+               while (heap_pop(&ca->heap, b, bucket_cmp))
+                       SET_GC_MOVE(b, 1);
        }
 
        mutex_unlock(&c->bucket_lock);
index dec15cd2d797eaaa7fa0585abf8867c9f70a4cef..c57bfa071a57c58b06fabeb194cbf98f5f4fbf56 100644 (file)
@@ -1676,7 +1676,7 @@ err:
 static bool can_attach_cache(struct cache *ca, struct cache_set *c)
 {
        return ca->sb.block_size        == c->sb.block_size &&
-               ca->sb.bucket_size      == c->sb.block_size &&
+               ca->sb.bucket_size      == c->sb.bucket_size &&
                ca->sb.nr_in_set        == c->sb.nr_in_set;
 }
 
index 80d4c2bee18aa3fd1af0f58c050145af8e0a1c98..a1f85612f0b3dfc5c90b768aaef48118034c02c7 100644 (file)
@@ -83,7 +83,6 @@ rw_attribute(writeback_rate);
 rw_attribute(writeback_rate_update_seconds);
 rw_attribute(writeback_rate_d_term);
 rw_attribute(writeback_rate_p_term_inverse);
-rw_attribute(writeback_rate_d_smooth);
 read_attribute(writeback_rate_debug);
 
 read_attribute(stripe_size);
@@ -129,31 +128,41 @@ SHOW(__bch_cached_dev)
        var_printf(writeback_running,   "%i");
        var_print(writeback_delay);
        var_print(writeback_percent);
-       sysfs_print(writeback_rate,     dc->writeback_rate.rate);
+       sysfs_hprint(writeback_rate,    dc->writeback_rate.rate << 9);
 
        var_print(writeback_rate_update_seconds);
        var_print(writeback_rate_d_term);
        var_print(writeback_rate_p_term_inverse);
-       var_print(writeback_rate_d_smooth);
 
        if (attr == &sysfs_writeback_rate_debug) {
+               char rate[20];
                char dirty[20];
-               char derivative[20];
                char target[20];
-               bch_hprint(dirty,
-                          bcache_dev_sectors_dirty(&dc->disk) << 9);
-               bch_hprint(derivative,  dc->writeback_rate_derivative << 9);
+               char proportional[20];
+               char derivative[20];
+               char change[20];
+               s64 next_io;
+
+               bch_hprint(rate,        dc->writeback_rate.rate << 9);
+               bch_hprint(dirty,       bcache_dev_sectors_dirty(&dc->disk) << 9);
                bch_hprint(target,      dc->writeback_rate_target << 9);
+               bch_hprint(proportional,dc->writeback_rate_proportional << 9);
+               bch_hprint(derivative,  dc->writeback_rate_derivative << 9);
+               bch_hprint(change,      dc->writeback_rate_change << 9);
+
+               next_io = div64_s64(dc->writeback_rate.next - local_clock(),
+                                   NSEC_PER_MSEC);
 
                return sprintf(buf,
-                              "rate:\t\t%u\n"
-                              "change:\t\t%i\n"
+                              "rate:\t\t%s/sec\n"
                               "dirty:\t\t%s\n"
+                              "target:\t\t%s\n"
+                              "proportional:\t%s\n"
                               "derivative:\t%s\n"
-                              "target:\t\t%s\n",
-                              dc->writeback_rate.rate,
-                              dc->writeback_rate_change,
-                              dirty, derivative, target);
+                              "change:\t\t%s/sec\n"
+                              "next io:\t%llims\n",
+                              rate, dirty, target, proportional,
+                              derivative, change, next_io);
        }
 
        sysfs_hprint(dirty_data,
@@ -189,6 +198,7 @@ STORE(__cached_dev)
        struct kobj_uevent_env *env;
 
 #define d_strtoul(var)         sysfs_strtoul(var, dc->var)
+#define d_strtoul_nonzero(var) sysfs_strtoul_clamp(var, dc->var, 1, INT_MAX)
 #define d_strtoi_h(var)                sysfs_hatoi(var, dc->var)
 
        sysfs_strtoul(data_csum,        dc->disk.data_csum);
@@ -197,16 +207,15 @@ STORE(__cached_dev)
        d_strtoul(writeback_metadata);
        d_strtoul(writeback_running);
        d_strtoul(writeback_delay);
-       sysfs_strtoul_clamp(writeback_rate,
-                           dc->writeback_rate.rate, 1, 1000000);
+
        sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40);
 
-       d_strtoul(writeback_rate_update_seconds);
+       sysfs_strtoul_clamp(writeback_rate,
+                           dc->writeback_rate.rate, 1, INT_MAX);
+
+       d_strtoul_nonzero(writeback_rate_update_seconds);
        d_strtoul(writeback_rate_d_term);
-       d_strtoul(writeback_rate_p_term_inverse);
-       sysfs_strtoul_clamp(writeback_rate_p_term_inverse,
-                           dc->writeback_rate_p_term_inverse, 1, INT_MAX);
-       d_strtoul(writeback_rate_d_smooth);
+       d_strtoul_nonzero(writeback_rate_p_term_inverse);
 
        d_strtoi_h(sequential_cutoff);
        d_strtoi_h(readahead);
@@ -313,7 +322,6 @@ static struct attribute *bch_cached_dev_files[] = {
        &sysfs_writeback_rate_update_seconds,
        &sysfs_writeback_rate_d_term,
        &sysfs_writeback_rate_p_term_inverse,
-       &sysfs_writeback_rate_d_smooth,
        &sysfs_writeback_rate_debug,
        &sysfs_dirty_data,
        &sysfs_stripe_size,
index 462214eeacbedbd9548e725be2e625723cda0d7e..bb37618e76648b7bc3caf99532e4f81b48666dfe 100644 (file)
@@ -209,7 +209,13 @@ uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done)
 {
        uint64_t now = local_clock();
 
-       d->next += div_u64(done, d->rate);
+       d->next += div_u64(done * NSEC_PER_SEC, d->rate);
+
+       if (time_before64(now + NSEC_PER_SEC, d->next))
+               d->next = now + NSEC_PER_SEC;
+
+       if (time_after64(now - NSEC_PER_SEC * 2, d->next))
+               d->next = now - NSEC_PER_SEC * 2;
 
        return time_after64(d->next, now)
                ? div_u64(d->next - now, NSEC_PER_SEC / HZ)
index 362c4b3f8b4a00e70d2e36af9ee7ec8cbe67e39e..1030c6020e986934e21c94628794e5e342271b49 100644 (file)
@@ -110,7 +110,7 @@ do {                                                                        \
        _r;                                                             \
 })
 
-#define heap_peek(h)   ((h)->size ? (h)->data[0] : NULL)
+#define heap_peek(h)   ((h)->used ? (h)->data[0] : NULL)
 
 #define heap_full(h)   ((h)->used == (h)->size)
 
index 99053b1251bea1049c627580f3614d1c18f89b60..6c44fe059c2769a4b2c317f25878596268726f0d 100644 (file)
@@ -30,38 +30,40 @@ static void __update_writeback_rate(struct cached_dev *dc)
 
        /* PD controller */
 
-       int change = 0;
-       int64_t error;
        int64_t dirty = bcache_dev_sectors_dirty(&dc->disk);
        int64_t derivative = dirty - dc->disk.sectors_dirty_last;
+       int64_t proportional = dirty - target;
+       int64_t change;
 
        dc->disk.sectors_dirty_last = dirty;
 
-       derivative *= dc->writeback_rate_d_term;
-       derivative = clamp(derivative, -dirty, dirty);
+       /* Scale to sectors per second */
 
-       derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
-                             dc->writeback_rate_d_smooth, 0);
+       proportional *= dc->writeback_rate_update_seconds;
+       proportional = div_s64(proportional, dc->writeback_rate_p_term_inverse);
 
-       /* Avoid divide by zero */
-       if (!target)
-               goto out;
+       derivative = div_s64(derivative, dc->writeback_rate_update_seconds);
 
-       error = div64_s64((dirty + derivative - target) << 8, target);
+       derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
+                             (dc->writeback_rate_d_term /
+                              dc->writeback_rate_update_seconds) ?: 1, 0);
+
+       derivative *= dc->writeback_rate_d_term;
+       derivative = div_s64(derivative, dc->writeback_rate_p_term_inverse);
 
-       change = div_s64((dc->writeback_rate.rate * error) >> 8,
-                        dc->writeback_rate_p_term_inverse);
+       change = proportional + derivative;
 
        /* Don't increase writeback rate if the device isn't keeping up */
        if (change > 0 &&
            time_after64(local_clock(),
-                        dc->writeback_rate.next + 10 * NSEC_PER_MSEC))
+                        dc->writeback_rate.next + NSEC_PER_MSEC))
                change = 0;
 
        dc->writeback_rate.rate =
-               clamp_t(int64_t, dc->writeback_rate.rate + change,
+               clamp_t(int64_t, (int64_t) dc->writeback_rate.rate + change,
                        1, NSEC_PER_MSEC);
-out:
+
+       dc->writeback_rate_proportional = proportional;
        dc->writeback_rate_derivative = derivative;
        dc->writeback_rate_change = change;
        dc->writeback_rate_target = target;
@@ -87,15 +89,11 @@ static void update_writeback_rate(struct work_struct *work)
 
 static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
 {
-       uint64_t ret;
-
        if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
            !dc->writeback_percent)
                return 0;
 
-       ret = bch_next_delay(&dc->writeback_rate, sectors * 10000000ULL);
-
-       return min_t(uint64_t, ret, HZ);
+       return bch_next_delay(&dc->writeback_rate, sectors);
 }
 
 struct dirty_io {
@@ -241,7 +239,7 @@ static void read_dirty(struct cached_dev *dc)
                if (KEY_START(&w->key) != dc->last_read ||
                    jiffies_to_msecs(delay) > 50)
                        while (!kthread_should_stop() && delay)
-                               delay = schedule_timeout_interruptible(delay);
+                               delay = schedule_timeout_uninterruptible(delay);
 
                dc->last_read   = KEY_OFFSET(&w->key);
 
@@ -438,7 +436,7 @@ static int bch_writeback_thread(void *arg)
                        while (delay &&
                               !kthread_should_stop() &&
                               !test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
-                               delay = schedule_timeout_interruptible(delay);
+                               delay = schedule_timeout_uninterruptible(delay);
                }
        }
 
@@ -476,6 +474,8 @@ void bch_sectors_dirty_init(struct cached_dev *dc)
 
        bch_btree_map_keys(&op.op, dc->disk.c, &KEY(op.inode, 0, 0),
                           sectors_dirty_init_fn, 0);
+
+       dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk);
 }
 
 int bch_cached_dev_writeback_init(struct cached_dev *dc)
@@ -490,18 +490,15 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc)
        dc->writeback_delay             = 30;
        dc->writeback_rate.rate         = 1024;
 
-       dc->writeback_rate_update_seconds = 30;
-       dc->writeback_rate_d_term       = 16;
-       dc->writeback_rate_p_term_inverse = 64;
-       dc->writeback_rate_d_smooth     = 8;
+       dc->writeback_rate_update_seconds = 5;
+       dc->writeback_rate_d_term       = 30;
+       dc->writeback_rate_p_term_inverse = 6000;
 
        dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
                                              "bcache_writeback");
        if (IS_ERR(dc->writeback_thread))
                return PTR_ERR(dc->writeback_thread);
 
-       set_task_state(dc->writeback_thread, TASK_INTERRUPTIBLE);
-
        INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
        schedule_delayed_work(&dc->writeback_rate_update,
                              dc->writeback_rate_update_seconds * HZ);
index 21f4d7ff0da22ee16e7556958502a2fb9ea74502..369d919bdafef4a6418ff1ff6c328fe2c74933ae 100644 (file)
@@ -1077,6 +1077,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
        rdev->raid_disk = -1;
        clear_bit(Faulty, &rdev->flags);
        clear_bit(In_sync, &rdev->flags);
+       clear_bit(Bitmap_sync, &rdev->flags);
        clear_bit(WriteMostly, &rdev->flags);
 
        if (mddev->raid_disks == 0) {
@@ -1155,6 +1156,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
                 */
                if (ev1 < mddev->bitmap->events_cleared)
                        return 0;
+               if (ev1 < mddev->events)
+                       set_bit(Bitmap_sync, &rdev->flags);
        } else {
                if (ev1 < mddev->events)
                        /* just a hot-add of a new device, leave raid_disk at -1 */
@@ -1563,6 +1566,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
        rdev->raid_disk = -1;
        clear_bit(Faulty, &rdev->flags);
        clear_bit(In_sync, &rdev->flags);
+       clear_bit(Bitmap_sync, &rdev->flags);
        clear_bit(WriteMostly, &rdev->flags);
 
        if (mddev->raid_disks == 0) {
@@ -1645,6 +1649,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
                 */
                if (ev1 < mddev->bitmap->events_cleared)
                        return 0;
+               if (ev1 < mddev->events)
+                       set_bit(Bitmap_sync, &rdev->flags);
        } else {
                if (ev1 < mddev->events)
                        /* just a hot-add of a new device, leave raid_disk at -1 */
@@ -2788,6 +2794,7 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
                else
                        rdev->saved_raid_disk = -1;
                clear_bit(In_sync, &rdev->flags);
+               clear_bit(Bitmap_sync, &rdev->flags);
                err = rdev->mddev->pers->
                        hot_add_disk(rdev->mddev, rdev);
                if (err) {
@@ -5760,6 +5767,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
                            info->raid_disk < mddev->raid_disks) {
                                rdev->raid_disk = info->raid_disk;
                                set_bit(In_sync, &rdev->flags);
+                               clear_bit(Bitmap_sync, &rdev->flags);
                        } else
                                rdev->raid_disk = -1;
                } else
@@ -7706,7 +7714,8 @@ static int remove_and_add_spares(struct mddev *mddev,
                if (test_bit(Faulty, &rdev->flags))
                        continue;
                if (mddev->ro &&
-                   rdev->saved_raid_disk < 0)
+                   ! (rdev->saved_raid_disk >= 0 &&
+                      !test_bit(Bitmap_sync, &rdev->flags)))
                        continue;
 
                rdev->recovery_offset = 0;
@@ -7787,9 +7796,12 @@ void md_check_recovery(struct mddev *mddev)
                         * As we only add devices that are already in-sync,
                         * we can activate the spares immediately.
                         */
-                       clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                        remove_and_add_spares(mddev, NULL);
-                       mddev->pers->spare_active(mddev);
+                       /* There is no thread, but we need to call
+                        * ->spare_active and clear saved_raid_disk
+                        */
+                       md_reap_sync_thread(mddev);
+                       clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                        goto unlock;
                }
 
index 2f5cc8a7ef3ed8e80d957ca48b5de5e775ce1ee7..0095ec84ffc7bec45547f87696770f0685fe62a9 100644 (file)
@@ -129,6 +129,9 @@ struct md_rdev {
 enum flag_bits {
        Faulty,                 /* device is known to have a fault */
        In_sync,                /* device is in_sync with rest of array */
+       Bitmap_sync,            /* ..actually, not quite In_sync.  Need a
+                                * bitmap-based recovery to get fully in sync
+                                */
        Unmerged,               /* device is being added to array and should
                                 * be considerred for bvec_merge_fn but not
                                 * yet for actual IO
index 1e5a540995e932852df5ff484a96bfcc8636a432..a49cfcc7a343188a5579350886795ce6fef35c4f 100644 (file)
@@ -924,9 +924,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio)
                                conf->next_window_requests++;
                        else
                                conf->current_window_requests++;
-               }
-               if (bio->bi_sector >= conf->start_next_window)
                        sector = conf->start_next_window;
+               }
        }
 
        conf->nr_pending++;
index c504e8389e69e3ab9ad717b9f83d0c19c2008d68..06eeb99ea6fc55cf3f8a51e470a430903769110b 100644 (file)
@@ -1319,7 +1319,7 @@ read_again:
                        /* Could not read all from this device, so we will
                         * need another r10_bio.
                         */
-                       sectors_handled = (r10_bio->sectors + max_sectors
+                       sectors_handled = (r10_bio->sector + max_sectors
                                           - bio->bi_sector);
                        r10_bio->sectors = max_sectors;
                        spin_lock_irq(&conf->device_lock);
@@ -1327,7 +1327,7 @@ read_again:
                                bio->bi_phys_segments = 2;
                        else
                                bio->bi_phys_segments++;
-                       spin_unlock(&conf->device_lock);
+                       spin_unlock_irq(&conf->device_lock);
                        /* Cannot call generic_make_request directly
                         * as that will be queued in __generic_make_request
                         * and subsequent mempool_alloc might block
@@ -3218,10 +3218,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                        if (j == conf->copies) {
                                /* Cannot recover, so abort the recovery or
                                 * record a bad block */
-                               put_buf(r10_bio);
-                               if (rb2)
-                                       atomic_dec(&rb2->remaining);
-                               r10_bio = rb2;
                                if (any_working) {
                                        /* problem is that there are bad blocks
                                         * on other device(s)
@@ -3253,6 +3249,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                                        mirror->recovery_disabled
                                                = mddev->recovery_disabled;
                                }
+                               put_buf(r10_bio);
+                               if (rb2)
+                                       atomic_dec(&rb2->remaining);
+                               r10_bio = rb2;
                                break;
                        }
                }
index cc055da02e2a300706548041dc4d9cf63957978c..cbb15716a5db31cf39a08b6a8a9df45d0bc9e0dc 100644 (file)
@@ -687,7 +687,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
                        } else {
                                if (!test_bit(STRIPE_HANDLE, &sh->state))
                                        atomic_inc(&conf->active_stripes);
-                               BUG_ON(list_empty(&sh->lru));
+                               BUG_ON(list_empty(&sh->lru) &&
+                                      !test_bit(STRIPE_EXPANDING, &sh->state));
                                list_del_init(&sh->lru);
                                if (sh->group) {
                                        sh->group->stripes_cnt--;
@@ -3608,7 +3609,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
                         */
                        set_bit(R5_Insync, &dev->flags);
 
-               if (rdev && test_bit(R5_WriteError, &dev->flags)) {
+               if (test_bit(R5_WriteError, &dev->flags)) {
                        /* This flag does not apply to '.replacement'
                         * only to .rdev, so make sure to check that*/
                        struct md_rdev *rdev2 = rcu_dereference(
@@ -3621,7 +3622,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
                        } else
                                clear_bit(R5_WriteError, &dev->flags);
                }
-               if (rdev && test_bit(R5_MadeGood, &dev->flags)) {
+               if (test_bit(R5_MadeGood, &dev->flags)) {
                        /* This flag does not apply to '.replacement'
                         * only to .rdev, so make sure to check that*/
                        struct md_rdev *rdev2 = rcu_dereference(
index 11e20afbdcacb7d31e49798db6d2dfbf0504afd8..705698fd2c7ed0f8f5e4fcada7b060627352be05 100644 (file)
@@ -1228,8 +1228,14 @@ static void rtsx_pci_remove(struct pci_dev *pcidev)
 
        pcr->remove_pci = true;
 
-       cancel_delayed_work(&pcr->carddet_work);
-       cancel_delayed_work(&pcr->idle_work);
+       /* Disable interrupts at the pcr level */
+       spin_lock_irq(&pcr->lock);
+       rtsx_pci_writel(pcr, RTSX_BIER, 0);
+       pcr->bier = 0;
+       spin_unlock_irq(&pcr->lock);
+
+       cancel_delayed_work_sync(&pcr->carddet_work);
+       cancel_delayed_work_sync(&pcr->idle_work);
 
        mfd_remove_devices(&pcidev->dev);
 
index d210d131fef255da97e7d277574ac80f01a66341..0f55589a56b815af4c00bc521c504db468774fa5 100644 (file)
@@ -73,7 +73,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        info->map.cached =
-               ioremap_cached(info->map.phys, info->map.size);
+               ioremap_cache(info->map.phys, info->map.size);
        if (!info->map.cached)
                printk(KERN_WARNING "Failed to ioremap cached %s\n",
                       info->map.name);
index 187b1b7772ef1b873303fc46998a591137bec7b7..4ced59436558e65a723df9975e8302fcec2cbb62 100644 (file)
@@ -2201,20 +2201,25 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("Warning: %s: speed changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                (__get_link_speed(port) << 1);
        pr_debug("Port %d changed speed\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2229,20 +2234,25 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                __get_duplex(port);
        pr_debug("Port %d changed duplex\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2258,15 +2268,21 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("Warning: %s: link status changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
-       // on link down we are zeroing duplex and speed since some of the adaptors(ce1000.lan) report full duplex/speed instead of N/A(duplex) / 0(speed)
-       // on link up we are forcing recheck on the duplex and speed since some of he adaptors(ce1000.lan) report
+       __get_state_machine_lock(port);
+       /* on link down we are zeroing duplex and speed since
+        * some of the adaptors(ce1000.lan) report full duplex/speed
+        * instead of N/A(duplex) / 0(speed).
+        *
+        * on link up we are forcing recheck on the duplex and speed since
+        * some of he adaptors(ce1000.lan) report.
+        */
        if (link == BOND_LINK_UP) {
                port->is_enabled = true;
                port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
@@ -2282,10 +2298,15 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
                port->actor_oper_port_key = (port->actor_admin_port_key &=
                                             ~AD_SPEED_KEY_BITS);
        }
-       //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       pr_debug("Port %d changed link status to %s",
+               port->actor_port_number,
+               (link == BOND_LINK_UP) ? "UP" : "DOWN");
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /*
index 398e299ee1bded33a57d7eb91318b00b24513658..4b8c58b0ec243575bbc17a547f7370b8d0b26d54 100644 (file)
@@ -3732,7 +3732,8 @@ static inline int bond_slave_override(struct bonding *bond,
 }
 
 
-static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb,
+                            void *accel_priv)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 5f9a7ad9b964da35190f01154492189965ba28ac..8aeec0b4601a2e8fe45290643a910a4fd8e4137b 100644 (file)
@@ -625,6 +625,7 @@ static int ems_usb_start(struct ems_usb *dev)
                        usb_unanchor_urb(urb);
                        usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
                                          urb->transfer_dma);
+                       usb_free_urb(urb);
                        break;
                }
 
@@ -798,8 +799,8 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
         * allowed (MAX_TX_URBS).
         */
        if (!context) {
-               usb_unanchor_urb(urb);
                usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
+               usb_free_urb(urb);
 
                netdev_warn(netdev, "couldn't find free context\n");
 
index 8ee9d1556e6e4eb3b8d32cfb988ba9870fccffaa..263dd921edc42342bba78ce9f2885862f0fc3087 100644 (file)
@@ -927,6 +927,9 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
        /* set LED in default state (end of init phase) */
        pcan_usb_pro_set_led(dev, 0, 1);
 
+       kfree(bi);
+       kfree(fi);
+
        return 0;
 
  err_out:
index b2ffad1304d221ef54e60cd1a82138a4d8344975..248baf6273fb76a2b179c50fe068aeddff51a42e 100644 (file)
@@ -565,6 +565,8 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
        /* Make sure pointer to data buffer is set */
        wmb();
 
+       skb_tx_timestamp(skb);
+
        *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len);
 
        /* Increment index to point to the next BD */
@@ -579,8 +581,6 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
 
        arc_reg_set(priv, R_STATUS, TXPL_MASK);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
index a36a760ada28af64272a5132a60648c543963bed..29801750f239b247389c7040f6616f9b79d14983 100644 (file)
@@ -145,9 +145,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
         * Mask some pcie error bits
         */
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
-       pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
-       data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
-       pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       if (pos) {
+               pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
+               data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
+               pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       }
        /* clear error status */
        pcie_capability_write_word(pdev, PCI_EXP_DEVSTA,
                        PCI_EXP_DEVSTA_NFED |
index a1f66e2c9a8694c9d83471dd63f6659d431840eb..ec6119089b82b8445cd573d961378c70b28632e5 100644 (file)
@@ -520,10 +520,12 @@ struct bnx2x_fastpath {
 #define BNX2X_FP_STATE_IDLE                  0
 #define BNX2X_FP_STATE_NAPI            (1 << 0)    /* NAPI owns this FP */
 #define BNX2X_FP_STATE_POLL            (1 << 1)    /* poll owns this FP */
-#define BNX2X_FP_STATE_NAPI_YIELD      (1 << 2)    /* NAPI yielded this FP */
-#define BNX2X_FP_STATE_POLL_YIELD      (1 << 3)    /* poll yielded this FP */
+#define BNX2X_FP_STATE_DISABLED                (1 << 2)
+#define BNX2X_FP_STATE_NAPI_YIELD      (1 << 3)    /* NAPI yielded this FP */
+#define BNX2X_FP_STATE_POLL_YIELD      (1 << 4)    /* poll yielded this FP */
+#define BNX2X_FP_OWNED (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL)
 #define BNX2X_FP_YIELD (BNX2X_FP_STATE_NAPI_YIELD | BNX2X_FP_STATE_POLL_YIELD)
-#define BNX2X_FP_LOCKED        (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL)
+#define BNX2X_FP_LOCKED        (BNX2X_FP_OWNED | BNX2X_FP_STATE_DISABLED)
 #define BNX2X_FP_USER_PEND (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_POLL_YIELD)
        /* protect state */
        spinlock_t lock;
@@ -613,7 +615,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
 {
        bool rc = true;
 
-       spin_lock(&fp->lock);
+       spin_lock_bh(&fp->lock);
        if (fp->state & BNX2X_FP_LOCKED) {
                WARN_ON(fp->state & BNX2X_FP_STATE_NAPI);
                fp->state |= BNX2X_FP_STATE_NAPI_YIELD;
@@ -622,7 +624,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
                /* we don't care if someone yielded */
                fp->state = BNX2X_FP_STATE_NAPI;
        }
-       spin_unlock(&fp->lock);
+       spin_unlock_bh(&fp->lock);
        return rc;
 }
 
@@ -631,14 +633,16 @@ static inline bool bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp)
 {
        bool rc = false;
 
-       spin_lock(&fp->lock);
+       spin_lock_bh(&fp->lock);
        WARN_ON(fp->state &
                (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_NAPI_YIELD));
 
        if (fp->state & BNX2X_FP_STATE_POLL_YIELD)
                rc = true;
-       fp->state = BNX2X_FP_STATE_IDLE;
-       spin_unlock(&fp->lock);
+
+       /* state ==> idle, unless currently disabled */
+       fp->state &= BNX2X_FP_STATE_DISABLED;
+       spin_unlock_bh(&fp->lock);
        return rc;
 }
 
@@ -669,7 +673,9 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
 
        if (fp->state & BNX2X_FP_STATE_POLL_YIELD)
                rc = true;
-       fp->state = BNX2X_FP_STATE_IDLE;
+
+       /* state ==> idle, unless currently disabled */
+       fp->state &= BNX2X_FP_STATE_DISABLED;
        spin_unlock_bh(&fp->lock);
        return rc;
 }
@@ -677,9 +683,23 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
 /* true if a socket is polling, even if it did not get the lock */
 static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
 {
-       WARN_ON(!(fp->state & BNX2X_FP_LOCKED));
+       WARN_ON(!(fp->state & BNX2X_FP_OWNED));
        return fp->state & BNX2X_FP_USER_PEND;
 }
+
+/* false if fp is currently owned */
+static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
+{
+       int rc = true;
+
+       spin_lock_bh(&fp->lock);
+       if (fp->state & BNX2X_FP_OWNED)
+               rc = false;
+       fp->state |= BNX2X_FP_STATE_DISABLED;
+       spin_unlock_bh(&fp->lock);
+
+       return rc;
+}
 #else
 static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp)
 {
@@ -709,6 +729,10 @@ static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
 {
        return false;
 }
+static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
+{
+       return true;
+}
 #endif /* CONFIG_NET_RX_BUSY_POLL */
 
 /* Use 2500 as a mini-jumbo MTU for FCoE */
@@ -1250,7 +1274,10 @@ struct bnx2x_slowpath {
         * Therefore, if they would have been defined in the same union,
         * data can get corrupted.
         */
-       struct afex_vif_list_ramrod_data func_afex_rdata;
+       union {
+               struct afex_vif_list_ramrod_data        viflist_data;
+               struct function_update_data             func_update;
+       } func_afex_rdata;
 
        /* used by dmae command executer */
        struct dmae_command             dmae[MAX_DMAE_C];
@@ -2499,4 +2526,6 @@ void bnx2x_set_local_cmng(struct bnx2x *bp);
 #define MCPR_SCRATCH_BASE(bp) \
        (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
 
+#define E1H_MAX_MF_SB_COUNT (HC_SB_MAX_SB_E1X/(E1HVN_MAX * PORT_MAX))
+
 #endif /* bnx2x.h */
index ec96130533cc54630c3f26f6253e58b5a0f5a7cf..bf811565ee245a0472cffc0ea5f70b30da053beb 100644 (file)
@@ -160,6 +160,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        struct sk_buff *skb = tx_buf->skb;
        u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
        int nbd;
+       u16 split_bd_len = 0;
 
        /* prefetch skb end pointer to speedup dev_kfree_skb() */
        prefetch(&skb->end);
@@ -167,10 +168,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        DP(NETIF_MSG_TX_DONE, "fp[%d]: pkt_idx %d  buff @(%p)->skb %p\n",
           txdata->txq_index, idx, tx_buf, skb);
 
-       /* unmap first bd */
        tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd;
-       dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
-                        BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
 
        nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
 #ifdef BNX2X_STOP_ON_ERROR
@@ -188,12 +186,19 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        --nbd;
        bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
 
-       /* ...and the TSO split header bd since they have no mapping */
+       /* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */
        if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) {
+               tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd;
+               split_bd_len = BD_UNMAP_LEN(tx_data_bd);
                --nbd;
                bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
        }
 
+       /* unmap first bd */
+       dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
+                        BD_UNMAP_LEN(tx_start_bd) + split_bd_len,
+                        DMA_TO_DEVICE);
+
        /* now free frags */
        while (nbd > 0) {
 
@@ -1790,26 +1795,22 @@ static void bnx2x_napi_disable_cnic(struct bnx2x *bp)
 {
        int i;
 
-       local_bh_disable();
        for_each_rx_queue_cnic(bp, i) {
                napi_disable(&bnx2x_fp(bp, i, napi));
-               while (!bnx2x_fp_lock_napi(&bp->fp[i]))
-                       mdelay(1);
+               while (!bnx2x_fp_ll_disable(&bp->fp[i]))
+                       usleep_range(1000, 2000);
        }
-       local_bh_enable();
 }
 
 static void bnx2x_napi_disable(struct bnx2x *bp)
 {
        int i;
 
-       local_bh_disable();
        for_each_eth_queue(bp, i) {
                napi_disable(&bnx2x_fp(bp, i, napi));
-               while (!bnx2x_fp_lock_napi(&bp->fp[i]))
-                       mdelay(1);
+               while (!bnx2x_fp_ll_disable(&bp->fp[i]))
+                       usleep_range(1000, 2000);
        }
-       local_bh_enable();
 }
 
 void bnx2x_netif_start(struct bnx2x *bp)
@@ -1832,7 +1833,8 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
                bnx2x_napi_disable_cnic(bp);
 }
 
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
+                      void *accel_priv)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
index da8fcaa74495475cb2c2c3984f3aa3cf85fc83ba..41f3ca5ad972b396498cbe5b7d7ad72ea9bdb1a7 100644 (file)
@@ -524,7 +524,8 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac);
 int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos);
 
 /* select_queue callback */
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
+                      void *accel_priv);
 
 static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
                                        struct bnx2x_fastpath *fp,
index 20dcc02431cac441a8bf3076a7fe6db1abfb04e9..11fc79585491f484f7ffd56d7a2e8e876ebb8e79 100644 (file)
@@ -3865,6 +3865,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
                bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
        } else {
+               /* Enable Auto-Detect to support 1G over CL37 as well */
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x10);
+
+               /* Force cl48 sync_status LOW to avoid getting stuck in CL73
+                * parallel-detect loop when CL73 and CL37 are enabled.
+                */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI, 0x0800);
+               bnx2x_set_aer_mmd(params, phy);
+
                bnx2x_disable_kr2(params, vars, phy);
        }
 
@@ -8120,17 +8133,20 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                                *edc_mode = EDC_MODE_ACTIVE_DAC;
                        else
                                check_limiting_mode = 1;
-               } else if (copper_module_type &
-                       SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
+               } else {
+                       *edc_mode = EDC_MODE_PASSIVE_DAC;
+                       /* Even in case PASSIVE_DAC indication is not set,
+                        * treat it as a passive DAC cable, since some cables
+                        * don't have this indication.
+                        */
+                       if (copper_module_type &
+                           SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
                                DP(NETIF_MSG_LINK,
                                   "Passive Copper cable detected\n");
-                               *edc_mode =
-                                     EDC_MODE_PASSIVE_DAC;
-               } else {
-                       DP(NETIF_MSG_LINK,
-                          "Unknown copper-cable-type 0x%x !!!\n",
-                          copper_module_type);
-                       return -EINVAL;
+                       } else {
+                               DP(NETIF_MSG_LINK,
+                                  "Unknown copper-cable-type\n");
+                       }
                }
                break;
        }
@@ -10825,9 +10841,9 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                           (1<<11));
 
        if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-                       (phy->req_line_speed == SPEED_1000)) {
+            (phy->speed_cap_mask &
+             PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+           (phy->req_line_speed == SPEED_1000)) {
                an_1000_val |= (1<<8);
                autoneg_val |= (1<<9 | 1<<12);
                if (phy->req_duplex == DUPLEX_FULL)
@@ -10843,30 +10859,32 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                        0x09,
                        &an_1000_val);
 
-       /* Set 100 speed advertisement */
-       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)))) {
-               an_10_100_val |= (1<<7);
-               /* Enable autoneg and restart autoneg for legacy speeds */
-               autoneg_val |= (1<<9 | 1<<12);
-
-               if (phy->req_duplex == DUPLEX_FULL)
-                       an_10_100_val |= (1<<8);
-               DP(NETIF_MSG_LINK, "Advertising 100M\n");
-       }
-
-       /* Set 10 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
-               an_10_100_val |= (1<<5);
-               autoneg_val |= (1<<9 | 1<<12);
-               if (phy->req_duplex == DUPLEX_FULL)
+       /* Advertise 10/100 link speed */
+       if (phy->req_line_speed == SPEED_AUTO_NEG) {
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) {
+                       an_10_100_val |= (1<<5);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) {
                        an_10_100_val |= (1<<6);
-               DP(NETIF_MSG_LINK, "Advertising 10M\n");
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-FD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
+                       an_10_100_val |= (1<<7);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
+                       an_10_100_val |= (1<<8);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-FD\n");
+               }
        }
 
        /* Only 10/100 are allowed to work in FORCE mode */
@@ -13342,6 +13360,10 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
        DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
           old_status, status);
 
+       /* Do not touch the link in case physical link down */
+       if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
+               return 1;
+
        /* a. Update shmem->link_status accordingly
         * b. Update link_vars->link_up
         */
@@ -13550,7 +13572,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
         */
        not_kr2_device = (((base_page & 0x8000) == 0) ||
                          (((base_page & 0x8000) &&
-                           ((next_page & 0xe0) == 0x2))));
+                           ((next_page & 0xe0) == 0x20))));
 
        /* In case KR2 is already disabled, check if we need to re-enable it */
        if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
index 814d0eca9b334ea86c862bc617a46f137f04d475..0067b975873f1592f0fbc2f7dc4a67de91d8c900 100644 (file)
@@ -11447,9 +11447,9 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
                }
        }
 
-       /* adjust igu_sb_cnt to MF for E1x */
-       if (CHIP_IS_E1x(bp) && IS_MF(bp))
-               bp->igu_sb_cnt /= E1HVN_MAX;
+       /* adjust igu_sb_cnt to MF for E1H */
+       if (CHIP_IS_E1H(bp) && IS_MF(bp))
+               bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, E1H_MAX_MF_SB_COUNT);
 
        /* port info */
        bnx2x_get_port_hwinfo(bp);
@@ -12942,25 +12942,26 @@ static void __bnx2x_remove(struct pci_dev *pdev,
                pci_set_power_state(pdev, PCI_D3hot);
        }
 
-       if (bp->regview)
-               iounmap(bp->regview);
+       if (remove_netdev) {
+               if (bp->regview)
+                       iounmap(bp->regview);
 
-       /* for vf doorbells are part of the regview and were unmapped along with
-        * it. FW is only loaded by PF.
-        */
-       if (IS_PF(bp)) {
-               if (bp->doorbells)
-                       iounmap(bp->doorbells);
+               /* For vfs, doorbells are part of the regview and were unmapped
+                * along with it. FW is only loaded by PF.
+                */
+               if (IS_PF(bp)) {
+                       if (bp->doorbells)
+                               iounmap(bp->doorbells);
 
-               bnx2x_release_firmware(bp);
-       }
-       bnx2x_free_mem_bp(bp);
+                       bnx2x_release_firmware(bp);
+               }
+               bnx2x_free_mem_bp(bp);
 
-       if (remove_netdev)
                free_netdev(dev);
 
-       if (atomic_read(&pdev->enable_cnt) == 1)
-               pci_release_regions(pdev);
+               if (atomic_read(&pdev->enable_cnt) == 1)
+                       pci_release_regions(pdev);
+       }
 
        pci_disable_device(pdev);
 }
index 3efbb35267c853d576cc3a4d3104ec4ba1a18d1d..14ffb6e56e593d6a371e1036edf02ff7c193eb08 100644 (file)
@@ -7179,6 +7179,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_RX1_PCI_CTRL                       0x80ca
 #define MDIO_WC_REG_RX2_PCI_CTRL                       0x80da
 #define MDIO_WC_REG_RX3_PCI_CTRL                       0x80ea
+#define MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI             0x80fa
 #define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G          0x8104
 #define MDIO_WC_REG_XGXS_STATUS3                       0x8129
 #define MDIO_WC_REG_PAR_DET_10G_STATUS                 0x8130
index 32c92abf50949fa1494812ab9d3734a5a2f3db1f..18438a504d573082239fe53532035d5516ff2881 100644 (file)
@@ -2038,6 +2038,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        struct bnx2x_vlan_mac_ramrod_params p;
        struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
        struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+       unsigned long flags;
        int read_lock;
        int rc = 0;
 
@@ -2046,8 +2047,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        spin_lock_bh(&exeq->lock);
 
        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) {
+               flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        rc = exeq->remove(bp, exeq->owner, exeq_pos);
                        if (rc) {
                                BNX2X_ERR("Failed to remove command\n");
@@ -2080,7 +2082,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
                return read_lock;
 
        list_for_each_entry(pos, &o->head, link) {
-               if (pos->vlan_mac_flags == *vlan_mac_flags) {
+               flags = pos->vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
                        memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
                        rc = bnx2x_config_vlan_mac(bp, &p);
@@ -4382,8 +4386,11 @@ int bnx2x_config_rss(struct bnx2x *bp,
        struct bnx2x_raw_obj *r = &o->raw;
 
        /* Do nothing if only driver cleanup was requested */
-       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
+       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+               DP(BNX2X_MSG_SP, "Not configuring RSS ramrod_flags=%lx\n",
+                  p->ramrod_flags);
                return 0;
+       }
 
        r->set_pending(r);
 
index 658f4e33abf9281d76e083873cb963c9b47b05f1..6a53c15c85a338c8efbb45ecf3348913272e038a 100644 (file)
@@ -266,6 +266,13 @@ enum {
        BNX2X_DONT_CONSUME_CAM_CREDIT,
        BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
 };
+/* When looking for matching filters, some flags are not interesting */
+#define BNX2X_VLAN_MAC_CMP_MASK        (1 << BNX2X_UC_LIST_MAC | \
+                                1 << BNX2X_ETH_MAC | \
+                                1 << BNX2X_ISCSI_ETH_MAC | \
+                                1 << BNX2X_NETQ_ETH_MAC)
+#define BNX2X_VLAN_MAC_CMP_FLAGS(flags) \
+       ((flags) & BNX2X_VLAN_MAC_CMP_MASK)
 
 struct bnx2x_vlan_mac_ramrod_params {
        /* Object to run the command from */
index 2e46c28fc6019a892f7792c6017effe3f7db7063..e7845e5be1c76fb452d8ecb94943326844ab5eaa 100644 (file)
@@ -1209,6 +1209,11 @@ static void bnx2x_vfop_rxmode(struct bnx2x *bp, struct bnx2x_virtf *vf)
                /* next state */
                vfop->state = BNX2X_VFOP_RXMODE_DONE;
 
+               /* record the accept flags in vfdb so hypervisor can modify them
+                * if necessary
+                */
+               bnx2x_vfq(vf, ramrod->cl_id - vf->igu_base_id, accept_flags) =
+                       ramrod->rx_accept_flags;
                vfop->rc = bnx2x_config_rx_mode(bp, ramrod);
                bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
 op_err:
@@ -1224,39 +1229,43 @@ op_pending:
        return;
 }
 
+static void bnx2x_vf_prep_rx_mode(struct bnx2x *bp, u8 qid,
+                                 struct bnx2x_rx_mode_ramrod_params *ramrod,
+                                 struct bnx2x_virtf *vf,
+                                 unsigned long accept_flags)
+{
+       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
+
+       memset(ramrod, 0, sizeof(*ramrod));
+       ramrod->cid = vfq->cid;
+       ramrod->cl_id = vfq_cl_id(vf, vfq);
+       ramrod->rx_mode_obj = &bp->rx_mode_obj;
+       ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
+       ramrod->rx_accept_flags = accept_flags;
+       ramrod->tx_accept_flags = accept_flags;
+       ramrod->pstate = &vf->filter_state;
+       ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
+
+       set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
+       set_bit(RAMROD_RX, &ramrod->ramrod_flags);
+       set_bit(RAMROD_TX, &ramrod->ramrod_flags);
+
+       ramrod->rdata = bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
+       ramrod->rdata_mapping = bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+}
+
 int bnx2x_vfop_rxmode_cmd(struct bnx2x *bp,
                          struct bnx2x_virtf *vf,
                          struct bnx2x_vfop_cmd *cmd,
                          int qid, unsigned long accept_flags)
 {
-       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
        struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
 
        if (vfop) {
                struct bnx2x_rx_mode_ramrod_params *ramrod =
                        &vf->op_params.rx_mode;
 
-               memset(ramrod, 0, sizeof(*ramrod));
-
-               /* Prepare ramrod parameters */
-               ramrod->cid = vfq->cid;
-               ramrod->cl_id = vfq_cl_id(vf, vfq);
-               ramrod->rx_mode_obj = &bp->rx_mode_obj;
-               ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
-
-               ramrod->rx_accept_flags = accept_flags;
-               ramrod->tx_accept_flags = accept_flags;
-               ramrod->pstate = &vf->filter_state;
-               ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
-
-               set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
-               set_bit(RAMROD_RX, &ramrod->ramrod_flags);
-               set_bit(RAMROD_TX, &ramrod->ramrod_flags);
-
-               ramrod->rdata =
-                       bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
-               ramrod->rdata_mapping =
-                       bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+               bnx2x_vf_prep_rx_mode(bp, qid, ramrod, vf, accept_flags);
 
                bnx2x_vfop_opset(BNX2X_VFOP_RXMODE_CONFIG,
                                 bnx2x_vfop_rxmode, cmd->done);
@@ -3202,13 +3211,16 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
                bnx2x_iov_static_resc(bp, vf);
        }
 
-       /* prepare msix vectors in VF configuration space */
+       /* prepare msix vectors in VF configuration space - the value in the
+        * PCI configuration space should be the index of the last entry,
+        * namely one less than the actual size of the table
+        */
        for (vf_idx = first_vf; vf_idx < first_vf + req_vfs; vf_idx++) {
                bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf_idx));
                REG_WR(bp, PCICFG_OFFSET + GRC_CONFIG_REG_VF_MSIX_CONTROL,
-                      num_vf_queues);
+                      num_vf_queues - 1);
                DP(BNX2X_MSG_IOV, "set msix vec num in VF %d cfg space to %d\n",
-                  vf_idx, num_vf_queues);
+                  vf_idx, num_vf_queues - 1);
        }
        bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 
@@ -3436,10 +3448,18 @@ out:
 
 int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 {
+       struct bnx2x_queue_state_params q_params = {NULL};
+       struct bnx2x_vlan_mac_ramrod_params ramrod_param;
+       struct bnx2x_queue_update_params *update_params;
+       struct pf_vf_bulletin_content *bulletin = NULL;
+       struct bnx2x_rx_mode_ramrod_params rx_ramrod;
        struct bnx2x *bp = netdev_priv(dev);
-       int rc, q_logical_state;
+       struct bnx2x_vlan_mac_obj *vlan_obj;
+       unsigned long vlan_mac_flags = 0;
+       unsigned long ramrod_flags = 0;
        struct bnx2x_virtf *vf = NULL;
-       struct pf_vf_bulletin_content *bulletin = NULL;
+       unsigned long accept_flags;
+       int rc;
 
        /* sanity and init */
        rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
@@ -3457,104 +3477,118 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
        /* update PF's copy of the VF's bulletin. No point in posting the vlan
         * to the VF since it doesn't have anything to do with it. But it useful
         * to store it here in case the VF is not up yet and we can only
-        * configure the vlan later when it does.
+        * configure the vlan later when it does. Treat vlan id 0 as remove the
+        * Host tag.
         */
-       bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       if (vlan > 0)
+               bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       else
+               bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
        bulletin->vlan = vlan;
 
        /* is vf initialized and queue set up? */
-       q_logical_state =
-               bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj));
-       if (vf->state == VF_ENABLED &&
-           q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
-               /* configure the vlan in device on this vf's queue */
-               unsigned long ramrod_flags = 0;
-               unsigned long vlan_mac_flags = 0;
-               struct bnx2x_vlan_mac_obj *vlan_obj =
-                       &bnx2x_leading_vfq(vf, vlan_obj);
-               struct bnx2x_vlan_mac_ramrod_params ramrod_param;
-               struct bnx2x_queue_state_params q_params = {NULL};
-               struct bnx2x_queue_update_params *update_params;
+       if (vf->state != VF_ENABLED ||
+           bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj)) !=
+           BNX2X_Q_LOGICAL_STATE_ACTIVE)
+               return rc;
 
-               rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
-               if (rc)
-                       return rc;
-               memset(&ramrod_param, 0, sizeof(ramrod_param));
+       /* configure the vlan in device on this vf's queue */
+       vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
+       rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
+       if (rc)
+               return rc;
 
-               /* must lock vfpf channel to protect against vf flows */
-               bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+       /* must lock vfpf channel to protect against vf flows */
+       bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
 
-               /* remove existing vlans */
-               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-               rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
-                                         &ramrod_flags);
-               if (rc) {
-                       BNX2X_ERR("failed to delete vlans\n");
-                       rc = -EINVAL;
-                       goto out;
-               }
+       /* remove existing vlans */
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
+                                 &ramrod_flags);
+       if (rc) {
+               BNX2X_ERR("failed to delete vlans\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       /* need to remove/add the VF's accept_any_vlan bit */
+       accept_flags = bnx2x_leading_vfq(vf, accept_flags);
+       if (vlan)
+               clear_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+       else
+               set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+
+       bnx2x_vf_prep_rx_mode(bp, LEADING_IDX, &rx_ramrod, vf,
+                             accept_flags);
+       bnx2x_leading_vfq(vf, accept_flags) = accept_flags;
+       bnx2x_config_rx_mode(bp, &rx_ramrod);
+
+       /* configure the new vlan to device */
+       memset(&ramrod_param, 0, sizeof(ramrod_param));
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       ramrod_param.vlan_mac_obj = vlan_obj;
+       ramrod_param.ramrod_flags = ramrod_flags;
+       set_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+               &ramrod_param.user_req.vlan_mac_flags);
+       ramrod_param.user_req.u.vlan.vlan = vlan;
+       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+       if (rc) {
+               BNX2X_ERR("failed to configure vlan\n");
+               rc =  -EINVAL;
+               goto out;
+       }
 
-               /* send queue update ramrod to configure default vlan and silent
-                * vlan removal
+       /* send queue update ramrod to configure default vlan and silent
+        * vlan removal
+        */
+       __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+       q_params.cmd = BNX2X_Q_CMD_UPDATE;
+       q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
+       update_params = &q_params.params.update;
+       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+                 &update_params->update_flags);
+       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+                 &update_params->update_flags);
+       if (vlan == 0) {
+               /* if vlan is 0 then we want to leave the VF traffic
+                * untagged, and leave the incoming traffic untouched
+                * (i.e. do not remove any vlan tags).
                 */
-               __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-               q_params.cmd = BNX2X_Q_CMD_UPDATE;
-               q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
-               update_params = &q_params.params.update;
-               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+               __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                           &update_params->update_flags);
+               __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                           &update_params->update_flags);
+       } else {
+               /* configure default vlan to vf queue and set silent
+                * vlan removal (the vf remains unaware of this vlan).
+                */
+               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
                          &update_params->update_flags);
-               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
                          &update_params->update_flags);
+               update_params->def_vlan = vlan;
+               update_params->silent_removal_value =
+                       vlan & VLAN_VID_MASK;
+               update_params->silent_removal_mask = VLAN_VID_MASK;
+       }
 
-               if (vlan == 0) {
-                       /* if vlan is 0 then we want to leave the VF traffic
-                        * untagged, and leave the incoming traffic untouched
-                        * (i.e. do not remove any vlan tags).
-                        */
-                       __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                   &update_params->update_flags);
-                       __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                   &update_params->update_flags);
-               } else {
-                       /* configure the new vlan to device */
-                       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-                       ramrod_param.vlan_mac_obj = vlan_obj;
-                       ramrod_param.ramrod_flags = ramrod_flags;
-                       ramrod_param.user_req.u.vlan.vlan = vlan;
-                       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
-                       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
-                       if (rc) {
-                               BNX2X_ERR("failed to configure vlan\n");
-                               rc =  -EINVAL;
-                               goto out;
-                       }
-
-                       /* configure default vlan to vf queue and set silent
-                        * vlan removal (the vf remains unaware of this vlan).
-                        */
-                       update_params = &q_params.params.update;
-                       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                 &update_params->update_flags);
-                       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                 &update_params->update_flags);
-                       update_params->def_vlan = vlan;
-               }
+       /* Update the Queue state */
+       rc = bnx2x_queue_state_change(bp, &q_params);
+       if (rc) {
+               BNX2X_ERR("Failed to configure default VLAN\n");
+               goto out;
+       }
 
-               /* Update the Queue state */
-               rc = bnx2x_queue_state_change(bp, &q_params);
-               if (rc) {
-                       BNX2X_ERR("Failed to configure default VLAN\n");
-                       goto out;
-               }
 
-               /* clear the flag indicating that this VF needs its vlan
-                * (will only be set if the HV configured the Vlan before vf was
-                * up and we were called because the VF came up later
-                */
+       /* clear the flag indicating that this VF needs its vlan
+        * (will only be set if the HV configured the Vlan before vf was
+        * up and we were called because the VF came up later
+        */
 out:
-               vf->cfg_flags &= ~VF_CFG_VLAN;
-               bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
-       }
+       vf->cfg_flags &= ~VF_CFG_VLAN;
+       bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+
        return rc;
 }
 
index 1ff6a9366629ed88fe79a079391c92e95d1e9baf..8c213fa52174f918d4f445dae554b593b54845db 100644 (file)
@@ -74,6 +74,7 @@ struct bnx2x_vf_queue {
        /* VLANs object */
        struct bnx2x_vlan_mac_obj       vlan_obj;
        atomic_t vlan_count;            /* 0 means vlan-0 is set  ~ untagged */
+       unsigned long accept_flags;     /* last accept flags configured */
 
        /* Queue Slow-path State object */
        struct bnx2x_queue_sp_obj       sp_obj;
index efa8a151d78907d4b17d5f5dd07eaed9b1f2c02c..0756d7dabdd59ae0e58139e07081d9ba02ca5a10 100644 (file)
@@ -208,7 +208,7 @@ static int bnx2x_get_vf_id(struct bnx2x *bp, u32 *vf_id)
                return -EINVAL;
        }
 
-       BNX2X_ERR("valid ME register value: 0x%08x\n", me_reg);
+       DP(BNX2X_MSG_IOV, "valid ME register value: 0x%08x\n", me_reg);
 
        *vf_id = (me_reg & ME_REG_VF_NUM_MASK) >> ME_REG_VF_NUM_SHIFT;
 
@@ -1598,6 +1598,8 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
 
                if (msg->flags & VFPF_SET_Q_FILTERS_RX_MASK_CHANGED) {
                        unsigned long accept = 0;
+                       struct pf_vf_bulletin_content *bulletin =
+                               BP_VF_BULLETIN(bp, vf->index);
 
                        /* covert VF-PF if mask to bnx2x accept flags */
                        if (msg->rx_mask & VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST)
@@ -1617,9 +1619,11 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
                                __set_bit(BNX2X_ACCEPT_BROADCAST, &accept);
 
                        /* A packet arriving the vf's mac should be accepted
-                        * with any vlan
+                        * with any vlan, unless a vlan has already been
+                        * configured.
                         */
-                       __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
+                       if (!(bulletin->valid_bitmap & (1 << VLAN_VALID)))
+                               __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
 
                        /* set rx-mode */
                        rc = bnx2x_vfop_rxmode_cmd(bp, vf, &cmd,
@@ -1710,6 +1714,21 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
                        goto response;
                }
        }
+       /* if vlan was set by hypervisor we don't allow guest to config vlan */
+       if (bulletin->valid_bitmap & 1 << VLAN_VALID) {
+               int i;
+
+               /* search for vlan filters */
+               for (i = 0; i < filters->n_mac_vlan_filters; i++) {
+                       if (filters->filters[i].flags &
+                           VFPF_Q_FILTER_VLAN_TAG_VALID) {
+                               BNX2X_ERR("VF[%d] attempted to configure vlan but one was already set by Hypervisor. Aborting request\n",
+                                         vf->abs_vfid);
+                               vf->op_rc = -EPERM;
+                               goto response;
+                       }
+               }
+       }
 
        /* verify vf_qid */
        if (filters->vf_qid > vf_rxq_count(vf))
@@ -1805,6 +1824,9 @@ static void bnx2x_vf_mbx_update_rss(struct bnx2x *bp, struct bnx2x_virtf *vf,
        vf_op_params->rss_result_mask = rss_tlv->rss_result_mask;
 
        /* flags handled individually for backward/forward compatability */
+       vf_op_params->rss_flags = 0;
+       vf_op_params->ramrod_flags = 0;
+
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_DISABLED)
                __set_bit(BNX2X_RSS_MODE_DISABLED, &vf_op_params->rss_flags);
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_REGULAR)
index f3dd93b4aeaac1bc8cdff71c9113d6668e085fd2..15a66e4b1f57a19d2d1e7feb31b557e3809fe6b0 100644 (file)
@@ -7622,7 +7622,7 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
 {
        u32 base = (u32) mapping & 0xffffffff;
 
-       return (base > 0xffffdcc0) && (base + len + 8 < base);
+       return base + len + 8 < base;
 }
 
 /* Test for TSO DMA buffers that cross into regions which are within MSS bytes
index 6c9308850453bf1ecd21173afa1d1cf11681c8c7..56e0415f8cdff396aca4d6462f2432278e258018 100644 (file)
@@ -228,6 +228,25 @@ struct tp_params {
 
        uint32_t dack_re;            /* DACK timer resolution */
        unsigned short tx_modq[NCHAN];  /* channel to modulation queue map */
+
+       u32 vlan_pri_map;               /* cached TP_VLAN_PRI_MAP */
+       u32 ingress_config;             /* cached TP_INGRESS_CONFIG */
+
+       /* TP_VLAN_PRI_MAP Compressed Filter Tuple field offsets.  This is a
+        * subset of the set of fields which may be present in the Compressed
+        * Filter Tuple portion of filters and TCP TCB connections.  The
+        * fields which are present are controlled by the TP_VLAN_PRI_MAP.
+        * Since a variable number of fields may or may not be present, their
+        * shifted field positions within the Compressed Filter Tuple may
+        * vary, or not even be present if the field isn't selected in
+        * TP_VLAN_PRI_MAP.  Since some of these fields are needed in various
+        * places we store their offsets here, or a -1 if the field isn't
+        * present.
+        */
+       int vlan_shift;
+       int vnic_shift;
+       int port_shift;
+       int protocol_shift;
 };
 
 struct vpd_params {
@@ -926,6 +945,8 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
               const u8 *fw_data, unsigned int fw_size,
               struct fw_hdr *card_fw, enum dev_state state, int *reset);
 int t4_prep_adapter(struct adapter *adapter);
+int t4_init_tp_params(struct adapter *adap);
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
 int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
index d6b12e035a7d9f27d84d397dc2921713c7fed46f..fff02ed1295e5ef7bab408cbe19c46dbd5eedd52 100644 (file)
@@ -2986,7 +2986,14 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
                stid += t->stid_base;
-               t->stids_in_use++;
+               /* IPv6 requires max of 520 bits or 16 cells in TCAM
+                * This is equivalent to 4 TIDs. With CLIP enabled it
+                * needs 2 TIDs.
+                */
+               if (family == PF_INET)
+                       t->stids_in_use++;
+               else
+                       t->stids_in_use += 4;
        }
        spin_unlock_bh(&t->stid_lock);
        return stid;
@@ -3012,7 +3019,8 @@ int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
        }
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
-               stid += t->stid_base;
+               stid -= t->nstids;
+               stid += t->sftid_base;
                t->stids_in_use++;
        }
        spin_unlock_bh(&t->stid_lock);
@@ -3024,14 +3032,24 @@ EXPORT_SYMBOL(cxgb4_alloc_sftid);
  */
 void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        spin_lock_bh(&t->stid_lock);
        if (family == PF_INET)
                __clear_bit(stid, t->stid_bmap);
        else
                bitmap_release_region(t->stid_bmap, stid, 2);
        t->stid_tab[stid].data = NULL;
-       t->stids_in_use--;
+       if (family == PF_INET)
+               t->stids_in_use--;
+       else
+               t->stids_in_use -= 4;
        spin_unlock_bh(&t->stid_lock);
 }
 EXPORT_SYMBOL(cxgb4_free_stid);
@@ -3134,6 +3152,7 @@ static int tid_init(struct tid_info *t)
        size_t size;
        unsigned int stid_bmap_size;
        unsigned int natids = t->natids;
+       struct adapter *adap = container_of(t, struct adapter, tids);
 
        stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
        size = t->ntids * sizeof(*t->tid_tab) +
@@ -3167,6 +3186,11 @@ static int tid_init(struct tid_info *t)
                t->afree = t->atid_tab;
        }
        bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
+       /* Reserve stid 0 for T4/T5 adapters */
+       if (!t->stid_base &&
+           (is_t4(adap->params.chip) || is_t5(adap->params.chip)))
+               __set_bit(0, t->stid_bmap);
+
        return 0;
 }
 
@@ -3731,7 +3755,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
                        (adap->fn * 4));
-       lli.filt_mode = adap->filter_mode;
+       lli.filt_mode = adap->params.tp.vlan_pri_map;
        /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
        for (i = 0; i < NCHAN; i++)
                lli.tx_modq[i] = i;
@@ -4179,7 +4203,7 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        /* Check to make sure the filter requested is writable ...
@@ -4205,12 +4229,17 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
                        f->fs.val.lip[i] = val[i];
                        f->fs.mask.lip[i] = ~0;
                }
-               if (adap->filter_mode & F_PORT) {
+               if (adap->params.tp.vlan_pri_map & F_PORT) {
                        f->fs.val.iport = port;
                        f->fs.mask.iport = mask;
                }
        }
 
+       if (adap->params.tp.vlan_pri_map & F_PROTOCOL) {
+               f->fs.val.proto = IPPROTO_TCP;
+               f->fs.mask.proto = ~0;
+       }
+
        f->fs.dirsteer = 1;
        f->fs.iq = queue;
        /* Mark filter as locked */
@@ -4237,7 +4266,7 @@ int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        f = &adap->tids.ftid_tab[stid];
@@ -5092,7 +5121,7 @@ static int adap_init0(struct adapter *adap)
        enum dev_state state;
        u32 params[7], val[7];
        struct fw_caps_config_cmd caps_cmd;
-       int reset = 1, j;
+       int reset = 1;
 
        /*
         * Contact FW, advertising Master capability (and potentially forcing
@@ -5434,21 +5463,11 @@ static int adap_init0(struct adapter *adap)
        /*
         * These are finalized by FW initialization, load their values now.
         */
-       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
-       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
-       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
        t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
        t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
                     adap->params.b_wnd);
 
-       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
-       for (j = 0; j < NCHAN; j++)
-               adap->params.tp.tx_modq[j] = j;
-
-       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
-                        &adap->filter_mode, 1,
-                        TP_VLAN_PRI_MAP);
-
+       t4_init_tp_params(adap);
        adap->flags |= FW_OK;
        return 0;
 
index 6f21f2451c3052a24ecd2e8d8d16ee9bdf9996fe..4dd0a82533e442f8b330c5ede554359ea450a087 100644 (file)
@@ -131,7 +131,14 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
 
 static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL;
 }
 
index 29878098101eb07771626399a1c5050a9544d055..81e8402a74b41c910114b4d10b3b796161ed0ea2 100644 (file)
@@ -45,6 +45,7 @@
 #include "l2t.h"
 #include "t4_msg.h"
 #include "t4fw_api.h"
+#include "t4_regs.h"
 
 #define VLAN_NONE 0xfff
 
@@ -411,6 +412,40 @@ done:
 }
 EXPORT_SYMBOL(cxgb4_l2t_get);
 
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t)
+{
+       struct adapter *adap = netdev2adap(dev);
+       struct tp_params *tp = &adap->params.tp;
+       u64 ntuple = 0;
+
+       /* Initialize each of the fields which we care about which are present
+        * in the Compressed Filter Tuple.
+        */
+       if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE)
+               ntuple |= (u64)(F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift;
+
+       if (tp->port_shift >= 0)
+               ntuple |= (u64)l2t->lport << tp->port_shift;
+
+       if (tp->protocol_shift >= 0)
+               ntuple |= (u64)IPPROTO_TCP << tp->protocol_shift;
+
+       if (tp->vnic_shift >= 0) {
+               u32 viid = cxgb4_port_viid(dev);
+               u32 vf = FW_VIID_VIN_GET(viid);
+               u32 pf = FW_VIID_PFN_GET(viid);
+               u32 vld = FW_VIID_VIVLD_GET(viid);
+
+               ntuple |= (u64)(V_FT_VNID_ID_VF(vf) |
+                               V_FT_VNID_ID_PF(pf) |
+                               V_FT_VNID_ID_VLD(vld)) << tp->vnic_shift;
+       }
+
+       return ntuple;
+}
+EXPORT_SYMBOL(cxgb4_select_ntuple);
+
 /*
  * Called when address resolution fails for an L2T entry to handle packets
  * on the arpq head.  If a packet specifies a failure handler it is invoked,
index 108c0f1fce1c4e5776b687538d741cd6f771a909..85eb5c71358d80ad91e21df648289047165dbf39 100644 (file)
@@ -98,7 +98,8 @@ int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
 struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
                                const struct net_device *physdev,
                                unsigned int priority);
-
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t);
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
 struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
 int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
index cc380c36e1a8687cd1c7f3b4c3dbf2d0b8c1bf47..cc3511a5cd0c0f9ea54e0d186878821f3dad8096 100644 (file)
@@ -2581,7 +2581,7 @@ static int t4_sge_init_soft(struct adapter *adap)
        #undef READ_FL_BUF
 
        if (fl_small_pg != PAGE_SIZE ||
-           (fl_large_pg != 0 && (fl_large_pg <= fl_small_pg ||
+           (fl_large_pg != 0 && (fl_large_pg < fl_small_pg ||
                                  (fl_large_pg & (fl_large_pg-1)) != 0))) {
                dev_err(adap->pdev_dev, "bad SGE FL page buffer sizes [%d, %d]\n",
                        fl_small_pg, fl_large_pg);
index 74a6fce5a15a6914faf74bbf903dcc76ec717775..e1413eacdbd20ab2233fd3217222bb76e6b779d1 100644 (file)
@@ -3808,6 +3808,109 @@ int t4_prep_adapter(struct adapter *adapter)
        return 0;
 }
 
+/**
+ *      t4_init_tp_params - initialize adap->params.tp
+ *      @adap: the adapter
+ *
+ *      Initialize various fields of the adapter's TP Parameters structure.
+ */
+int t4_init_tp_params(struct adapter *adap)
+{
+       int chan;
+       u32 v;
+
+       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
+       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
+       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
+
+       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
+       for (chan = 0; chan < NCHAN; chan++)
+               adap->params.tp.tx_modq[chan] = chan;
+
+       /* Cache the adapter's Compressed Filter Mode and global Incress
+        * Configuration.
+        */
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.vlan_pri_map, 1,
+                        TP_VLAN_PRI_MAP);
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.ingress_config, 1,
+                        TP_INGRESS_CONFIG);
+
+       /* Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
+        * shift positions of several elements of the Compressed Filter Tuple
+        * for this adapter which we need frequently ...
+        */
+       adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
+       adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
+       adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
+       adap->params.tp.protocol_shift = t4_filter_field_shift(adap,
+                                                              F_PROTOCOL);
+
+       /* If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
+        * represents the presense of an Outer VLAN instead of a VNIC ID.
+        */
+       if ((adap->params.tp.ingress_config & F_VNIC) == 0)
+               adap->params.tp.vnic_shift = -1;
+
+       return 0;
+}
+
+/**
+ *      t4_filter_field_shift - calculate filter field shift
+ *      @adap: the adapter
+ *      @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
+ *
+ *      Return the shift position of a filter field within the Compressed
+ *      Filter Tuple.  The filter field is specified via its selection bit
+ *      within TP_VLAN_PRI_MAL (filter mode).  E.g. F_VLAN.
+ */
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
+{
+       unsigned int filter_mode = adap->params.tp.vlan_pri_map;
+       unsigned int sel;
+       int field_shift;
+
+       if ((filter_mode & filter_sel) == 0)
+               return -1;
+
+       for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
+               switch (filter_mode & sel) {
+               case F_FCOE:
+                       field_shift += W_FT_FCOE;
+                       break;
+               case F_PORT:
+                       field_shift += W_FT_PORT;
+                       break;
+               case F_VNIC_ID:
+                       field_shift += W_FT_VNIC_ID;
+                       break;
+               case F_VLAN:
+                       field_shift += W_FT_VLAN;
+                       break;
+               case F_TOS:
+                       field_shift += W_FT_TOS;
+                       break;
+               case F_PROTOCOL:
+                       field_shift += W_FT_PROTOCOL;
+                       break;
+               case F_ETHERTYPE:
+                       field_shift += W_FT_ETHERTYPE;
+                       break;
+               case F_MACMATCH:
+                       field_shift += W_FT_MACMATCH;
+                       break;
+               case F_MPSHITTYPE:
+                       field_shift += W_FT_MPSHITTYPE;
+                       break;
+               case F_FRAGMENTATION:
+                       field_shift += W_FT_FRAGMENTATION;
+                       break;
+               }
+       }
+       return field_shift;
+}
+
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
        u8 addr[6];
index 0a8205d69d2c290aae4dbec30245c9dc3e18bd39..4082522d81408bf0a23cff8eaf9700bef14533a9 100644 (file)
 
 #define A_TP_TX_SCHED_PCMD 0x25
 
+#define S_VNIC    11
+#define V_VNIC(x) ((x) << S_VNIC)
+#define F_VNIC    V_VNIC(1U)
+
+#define S_FRAGMENTATION    9
+#define V_FRAGMENTATION(x) ((x) << S_FRAGMENTATION)
+#define F_FRAGMENTATION    V_FRAGMENTATION(1U)
+
+#define S_MPSHITTYPE    8
+#define V_MPSHITTYPE(x) ((x) << S_MPSHITTYPE)
+#define F_MPSHITTYPE    V_MPSHITTYPE(1U)
+
+#define S_MACMATCH    7
+#define V_MACMATCH(x) ((x) << S_MACMATCH)
+#define F_MACMATCH    V_MACMATCH(1U)
+
+#define S_ETHERTYPE    6
+#define V_ETHERTYPE(x) ((x) << S_ETHERTYPE)
+#define F_ETHERTYPE    V_ETHERTYPE(1U)
+
+#define S_PROTOCOL    5
+#define V_PROTOCOL(x) ((x) << S_PROTOCOL)
+#define F_PROTOCOL    V_PROTOCOL(1U)
+
+#define S_TOS    4
+#define V_TOS(x) ((x) << S_TOS)
+#define F_TOS    V_TOS(1U)
+
+#define S_VLAN    3
+#define V_VLAN(x) ((x) << S_VLAN)
+#define F_VLAN    V_VLAN(1U)
+
+#define S_VNIC_ID    2
+#define V_VNIC_ID(x) ((x) << S_VNIC_ID)
+#define F_VNIC_ID    V_VNIC_ID(1U)
+
 #define S_PORT    1
 #define V_PORT(x) ((x) << S_PORT)
 #define F_PORT    V_PORT(1U)
 
+#define S_FCOE    0
+#define V_FCOE(x) ((x) << S_FCOE)
+#define F_FCOE    V_FCOE(1U)
+
 #define NUM_MPS_CLS_SRAM_L_INSTANCES 336
 #define NUM_MPS_T5_CLS_SRAM_L_INSTANCES 512
 
 #define V_CHIPID(x) ((x) << S_CHIPID)
 #define G_CHIPID(x) (((x) >> S_CHIPID) & M_CHIPID)
 
+/* TP_VLAN_PRI_MAP controls which subset of fields will be present in the
+ * Compressed Filter Tuple for LE filters.  Each bit set in TP_VLAN_PRI_MAP
+ * selects for a particular field being present.  These fields, when present
+ * in the Compressed Filter Tuple, have the following widths in bits.
+ */
+#define W_FT_FCOE                       1
+#define W_FT_PORT                       3
+#define W_FT_VNIC_ID                    17
+#define W_FT_VLAN                       17
+#define W_FT_TOS                        8
+#define W_FT_PROTOCOL                   8
+#define W_FT_ETHERTYPE                  16
+#define W_FT_MACMATCH                   9
+#define W_FT_MPSHITTYPE                 3
+#define W_FT_FRAGMENTATION              1
+
+/* Some of the Compressed Filter Tuple fields have internal structure.  These
+ * bit shifts/masks describe those structures.  All shifts are relative to the
+ * base position of the fields within the Compressed Filter Tuple
+ */
+#define S_FT_VLAN_VLD                   16
+#define V_FT_VLAN_VLD(x)                ((x) << S_FT_VLAN_VLD)
+#define F_FT_VLAN_VLD                   V_FT_VLAN_VLD(1U)
+
+#define S_FT_VNID_ID_VF                 0
+#define V_FT_VNID_ID_VF(x)              ((x) << S_FT_VNID_ID_VF)
+
+#define S_FT_VNID_ID_PF                 7
+#define V_FT_VNID_ID_PF(x)              ((x) << S_FT_VNID_ID_PF)
+
+#define S_FT_VNID_ID_VLD                16
+#define V_FT_VNID_ID_VLD(x)             ((x) << S_FT_VNID_ID_VLD)
+
 #endif /* __T4_REGS_H */
index 5878df619b531ad0b3ea96167f53e8909ff9fd21..4ccaf9af6fc90cde0d9d13490fa5753e480c543e 100644 (file)
@@ -104,6 +104,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE3_MAX_RSS_QS         16
 #define BE3_MAX_TX_QS          16
 #define BE3_MAX_EVT_QS         16
+#define BE3_SRIOV_MAX_EVT_QS   8
 
 #define MAX_RX_QS              32
 #define MAX_EVT_QS             32
@@ -480,7 +481,7 @@ struct be_adapter {
        struct list_head entry;
 
        u32 flash_status;
-       struct completion flash_compl;
+       struct completion et_cmd_compl;
 
        struct be_resources res;        /* resources available for the func */
        u16 num_vfs;                    /* Number of VFs provisioned by PF */
index e0e8bc1ef14c47e93336df2c784d1ff14e6b4143..94c35c8d799d9f1e4f4b9fd78121600ad600505e 100644 (file)
@@ -141,11 +141,17 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
                subsystem = resp_hdr->subsystem;
        }
 
+       if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
+           subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
+               complete(&adapter->et_cmd_compl);
+               return 0;
+       }
+
        if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
             (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
            (subsystem == CMD_SUBSYSTEM_COMMON)) {
                adapter->flash_status = compl_status;
-               complete(&adapter->flash_compl);
+               complete(&adapter->et_cmd_compl);
        }
 
        if (compl_status == MCC_STATUS_SUCCESS) {
@@ -2017,6 +2023,9 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
                        0x3ea83c02, 0x4a110304};
        int status;
 
+       if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
+               return 0;
+
        if (mutex_lock_interruptible(&adapter->mbox_lock))
                return -1;
 
@@ -2160,7 +2169,7 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
                                         msecs_to_jiffies(60000)))
                status = -1;
        else
@@ -2255,8 +2264,8 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
-                       msecs_to_jiffies(40000)))
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
+                                        msecs_to_jiffies(40000)))
                status = -1;
        else
                status = adapter->flash_status;
@@ -2367,6 +2376,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_loopback_test *req;
+       struct be_cmd_resp_loopback_test *resp;
        int status;
 
        spin_lock_bh(&adapter->mcc_lock);
@@ -2381,8 +2391,8 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
                        OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, NULL);
-       req->hdr.timeout = cpu_to_le32(4);
 
+       req->hdr.timeout = cpu_to_le32(15);
        req->pattern = cpu_to_le64(pattern);
        req->src_port = cpu_to_le32(port_num);
        req->dest_port = cpu_to_le32(port_num);
@@ -2390,12 +2400,15 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
        req->num_pkts = cpu_to_le32(num_pkts);
        req->loopback_type = cpu_to_le32(loopback_type);
 
-       status = be_mcc_notify_wait(adapter);
-       if (!status) {
-               struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb);
-               status = le32_to_cpu(resp->status);
-       }
+       be_mcc_notify(adapter);
+
+       spin_unlock_bh(&adapter->mcc_lock);
 
+       wait_for_completion(&adapter->et_cmd_compl);
+       resp = embedded_payload(wrb);
+       status = le32_to_cpu(resp->status);
+
+       return status;
 err:
        spin_unlock_bh(&adapter->mcc_lock);
        return status;
index 0fde69d5cb6afd610db5f2a57325e5d2e9f5ed94..a37039d353c57e999a9235a0af2ca3d48f3c3b14 100644 (file)
@@ -1776,6 +1776,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
        struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
        struct be_queue_info *rxq = &rxo->q;
        struct page *pagep = NULL;
+       struct device *dev = &adapter->pdev->dev;
        struct be_eth_rx_d *rxd;
        u64 page_dmaaddr = 0, frag_dmaaddr;
        u32 posted, page_offset = 0;
@@ -1788,9 +1789,15 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
                                rx_stats(rxo)->rx_post_fail++;
                                break;
                        }
-                       page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep,
-                                                   0, adapter->big_page_size,
+                       page_dmaaddr = dma_map_page(dev, pagep, 0,
+                                                   adapter->big_page_size,
                                                    DMA_FROM_DEVICE);
+                       if (dma_mapping_error(dev, page_dmaaddr)) {
+                               put_page(pagep);
+                               pagep = NULL;
+                               rx_stats(rxo)->rx_post_fail++;
+                               break;
+                       }
                        page_info->page_offset = 0;
                } else {
                        get_page(pagep);
@@ -2744,13 +2751,16 @@ static int be_rx_qs_create(struct be_adapter *adapter)
                if (!BEx_chip(adapter))
                        adapter->rss_flags |= RSS_ENABLE_UDP_IPV4 |
                                                RSS_ENABLE_UDP_IPV6;
+       } else {
+               /* Disable RSS, if only default RX Q is created */
+               adapter->rss_flags = RSS_ENABLE_NONE;
+       }
 
-               rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
-                                      128);
-               if (rc) {
-                       adapter->rss_flags = 0;
-                       return rc;
-               }
+       rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
+                              128);
+       if (rc) {
+               adapter->rss_flags = RSS_ENABLE_NONE;
+               return rc;
        }
 
        /* First time posting */
@@ -3124,11 +3134,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
 {
        struct pci_dev *pdev = adapter->pdev;
        bool use_sriov = false;
+       int max_vfs;
 
-       if (BE3_chip(adapter) && sriov_want(adapter)) {
-               int max_vfs;
+       max_vfs = pci_sriov_get_totalvfs(pdev);
 
-               max_vfs = pci_sriov_get_totalvfs(pdev);
+       if (BE3_chip(adapter) && sriov_want(adapter)) {
                res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
                use_sriov = res->max_vfs;
        }
@@ -3159,7 +3169,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
                                           BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
        res->max_rx_qs = res->max_rss_qs + 1;
 
-       res->max_evt_qs = be_physfn(adapter) ? BE3_MAX_EVT_QS : 1;
+       if (be_physfn(adapter))
+               res->max_evt_qs = (max_vfs > 0) ?
+                                       BE3_SRIOV_MAX_EVT_QS : BE3_MAX_EVT_QS;
+       else
+               res->max_evt_qs = 1;
 
        res->if_cap_flags = BE_IF_CAP_FLAGS_WANT;
        if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS))
@@ -4205,7 +4219,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
        spin_lock_init(&adapter->mcc_lock);
        spin_lock_init(&adapter->mcc_cq_lock);
 
-       init_completion(&adapter->flash_compl);
+       init_completion(&adapter->et_cmd_compl);
        pci_save_state(adapter->pdev);
        return 0;
 
index e7c8b749c5a53f969096e3f442195d88f82597d7..50bb71c663e20a010c9a4390c3d1c38726037c85 100644 (file)
@@ -428,6 +428,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* If this was the last BD in the ring, start at the beginning again. */
        bdp = fec_enet_get_nextdesc(bdp, fep);
 
+       skb_tx_timestamp(skb);
+
        fep->cur_tx = bdp;
 
        if (fep->cur_tx == fep->dirty_tx)
@@ -436,8 +438,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* Trigger transmission start */
        writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
index 895450e9bb3cfe81d22f19148b4a52d9fc14352a..ff2d806eaef71bc2a7a861a8971c228cd6856e2a 100644 (file)
@@ -718,8 +718,11 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
        e1000_release_phy_80003es2lan(hw);
 
        /* Disable IBIST slave mode (far-end loopback) */
-       e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-                                       &kum_reg_data);
+       ret_val =
+           e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+                                           &kum_reg_data);
+       if (ret_val)
+               return ret_val;
        kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
        e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
                                         kum_reg_data);
index 8d3945ab7334840684db42ea6eefa9bafc52c061..6d14eea1791846c59077f98478ab95f480538624 100644 (file)
@@ -7015,13 +7015,11 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
 };
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
-#ifdef CONFIG_PM
 static const struct dev_pm_ops e1000_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume)
        SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume,
                           e1000_idle)
 };
-#endif
 
 /* PCI Device API Driver */
 static struct pci_driver e1000_driver = {
@@ -7029,11 +7027,9 @@ static struct pci_driver e1000_driver = {
        .id_table = e1000_pci_tbl,
        .probe    = e1000_probe,
        .remove   = e1000_remove,
-#ifdef CONFIG_PM
        .driver   = {
                .pm = &e1000_pm_ops,
        },
-#endif
        .shutdown = e1000_shutdown,
        .err_handler = &e1000_err_handler
 };
index da2be59505c06226b4cd79f9e8cc120945ca1d17..20e71f4ca4261f99694b04eccd3647906326239d 100644 (file)
@@ -1757,19 +1757,23 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                 * it across the board.
                 */
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
-               if (ret_val)
+               if (ret_val) {
                        /* If the first read fails, another entity may have
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
-                       udelay(usec_interval);
+                       if (usec_interval >= 1000)
+                               msleep(usec_interval / 1000);
+                       else
+                               udelay(usec_interval);
+               }
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
                if (ret_val)
                        break;
                if (phy_status & BMSR_LSTATUS)
                        break;
                if (usec_interval >= 1000)
-                       mdelay(usec_interval / 1000);
+                       msleep(usec_interval / 1000);
                else
                        udelay(usec_interval);
        }
index cc06854296a379a6f5d1fac21ecf9412d94d477b..5bcc870f8367f803c309f5c28115cded7284748c 100644 (file)
@@ -6827,12 +6827,20 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
        return __ixgbe_maybe_stop_tx(tx_ring, size);
 }
 
-#ifdef IXGBE_FCOE
-static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
+                             void *accel_priv)
 {
+       struct ixgbe_fwd_adapter *fwd_adapter = accel_priv;
+#ifdef IXGBE_FCOE
        struct ixgbe_adapter *adapter;
        struct ixgbe_ring_feature *f;
        int txq;
+#endif
+
+       if (fwd_adapter)
+               return skb->queue_mapping + fwd_adapter->tx_base_queue;
+
+#ifdef IXGBE_FCOE
 
        /*
         * only execute the code below if protocol is FCoE
@@ -6858,9 +6866,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
                txq -= f->indices;
 
        return txq + f->offset;
+#else
+       return __netdev_pick_tx(dev, skb);
+#endif
 }
 
-#endif
 netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                          struct ixgbe_adapter *adapter,
                          struct ixgbe_ring *tx_ring)
@@ -7629,27 +7639,11 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
        kfree(fwd_adapter);
 }
 
-static netdev_tx_t ixgbe_fwd_xmit(struct sk_buff *skb,
-                                 struct net_device *dev,
-                                 void *priv)
-{
-       struct ixgbe_fwd_adapter *fwd_adapter = priv;
-       unsigned int queue;
-       struct ixgbe_ring *tx_ring;
-
-       queue = skb->queue_mapping + fwd_adapter->tx_base_queue;
-       tx_ring = fwd_adapter->real_adapter->tx_ring[queue];
-
-       return __ixgbe_xmit_frame(skb, dev, tx_ring);
-}
-
 static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_open               = ixgbe_open,
        .ndo_stop               = ixgbe_close,
        .ndo_start_xmit         = ixgbe_xmit_frame,
-#ifdef IXGBE_FCOE
        .ndo_select_queue       = ixgbe_select_queue,
-#endif
        .ndo_set_rx_mode        = ixgbe_set_rx_mode,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ixgbe_set_mac,
@@ -7689,7 +7683,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_bridge_getlink     = ixgbe_ndo_bridge_getlink,
        .ndo_dfwd_add_station   = ixgbe_fwd_add,
        .ndo_dfwd_del_station   = ixgbe_fwd_del,
-       .ndo_dfwd_start_xmit    = ixgbe_fwd_xmit,
 };
 
 /**
index d6f0c0d8cf11ddb395617e2749bbf25329cae42c..72084f70adbba84c5b3e4df8f890155c2643a13b 100644 (file)
@@ -291,7 +291,9 @@ static int ixgbe_pci_sriov_disable(struct pci_dev *dev)
 {
        struct ixgbe_adapter *adapter = pci_get_drvdata(dev);
        int err;
+#ifdef CONFIG_PCI_IOV
        u32 current_flags = adapter->flags;
+#endif
 
        err = ixgbe_disable_sriov(adapter);
 
index 6a6c1f76d8e04406b1c6de12820a48a7d27337fd..ec94a20d709952d1f678f69ac7778205f75e8ffe 100644 (file)
@@ -619,7 +619,8 @@ ltq_etop_set_multicast_list(struct net_device *dev)
 }
 
 static u16
-ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb)
+ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     void *accel_priv)
 {
        /* we are currently only using the first queue */
        return 0;
index 7354960b583bc83b45a8aadd001c03c456912f81..c4eeb69a5beee6f4e4214746b9c958c614e64beb 100644 (file)
@@ -92,6 +92,12 @@ static int orion_mdio_wait_ready(struct mii_bus *bus)
                        if (time_is_before_jiffies(end))
                                ++timedout;
                } else {
+                       /* wait_event_timeout does not guarantee a delay of at
+                        * least one whole jiffie, so timeout must be no less
+                        * than two.
+                        */
+                       if (timeout < 2)
+                               timeout = 2;
                        wait_event_timeout(dev->smi_busy_wait,
                                           orion_mdio_smi_is_done(dev),
                                           timeout);
index f54ebd5a1702457524bf5fc6918fbdf191a5d73f..a7fcd593b2dbb397bdf3d2a810ff42f71d0806b6 100644 (file)
@@ -592,7 +592,8 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
        }
 }
 
-u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+                        void *accel_priv)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        u16 rings_p_up = priv->num_tx_rings_p_up;
index f3758de59c05f5adeb195661814ff4041b405c4a..d5758adceaa2f264b74d83e99f8091b7e1ead948 100644 (file)
@@ -714,7 +714,8 @@ int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 
 void mlx4_en_tx_irq(struct mlx4_cq *mcq);
-u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb);
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+                        void *accel_priv);
 netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
 
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
index 7692dfd4f262db9045f285aadc194c1713fb724a..cc68657f05368d5642b62091bc6dbec1bc00bd1c 100644 (file)
@@ -1604,13 +1604,13 @@ netxen_process_lro(struct netxen_adapter *adapter,
        u32 seq_number;
        u8 vhdr_len = 0;
 
-       if (unlikely(ring > adapter->max_rds_rings))
+       if (unlikely(ring >= adapter->max_rds_rings))
                return NULL;
 
        rds_ring = &recv_ctx->rds_rings[ring];
 
        index = netxen_get_lro_sts_refhandle(sts_data0);
-       if (unlikely(index > rds_ring->num_desc))
+       if (unlikely(index >= rds_ring->num_desc))
                return NULL;
 
        buffer = &rds_ring->rx_buf_arr[index];
index 631ea0ac1cd89c47bddb863c56f04c28469bd745..f2a7c7166e2408a747dd03ef0fc456ba6121486c 100644 (file)
@@ -487,6 +487,7 @@ struct qlcnic_hardware_context {
        struct qlcnic_mailbox *mailbox;
        u8 extend_lb_time;
        u8 phys_port_id[ETH_ALEN];
+       u8 lb_mode;
 };
 
 struct qlcnic_adapter_stats {
@@ -578,6 +579,8 @@ struct qlcnic_host_tx_ring {
        dma_addr_t phys_addr;
        dma_addr_t hw_cons_phys_addr;
        struct netdev_queue *txq;
+       /* Lock to protect Tx descriptors cleanup */
+       spinlock_t tx_clean_lock;
 } ____cacheline_internodealigned_in_smp;
 
 /*
@@ -808,6 +811,7 @@ struct qlcnic_mac_list_s {
 
 #define QLCNIC_ILB_MODE                0x1
 #define QLCNIC_ELB_MODE                0x2
+#define QLCNIC_LB_MODE_MASK    0x3
 
 #define QLCNIC_LINKEVENT       0x1
 #define QLCNIC_LB_RESPONSE     0x2
@@ -1093,7 +1097,6 @@ struct qlcnic_adapter {
        struct qlcnic_filter_hash rx_fhash;
        struct list_head vf_mc_list;
 
-       spinlock_t tx_clean_lock;
        spinlock_t mac_learn_lock;
        /* spinlock for catching rcv filters for eswitch traffic */
        spinlock_t rx_mac_learn_lock;
@@ -1708,6 +1711,7 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *);
 void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *);
 void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx);
 void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx);
+void qlcnic_update_stats(struct qlcnic_adapter *);
 
 /* Adapter hardware abstraction */
 struct qlcnic_hardware_ops {
index b1cb0ffb15c70d1970f3cbebab28ff7f8e8530ce..f776f99f79155ea42d3371b7e9aadcc901421898 100644 (file)
@@ -447,8 +447,9 @@ irqreturn_t qlcnic_83xx_intr(int irq, void *data)
 
        qlcnic_83xx_poll_process_aen(adapter);
 
-       if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
-               ahw->diag_cnt++;
+       if (ahw->diag_test) {
+               if (ahw->diag_test == QLCNIC_INTERRUPT_TEST)
+                       ahw->diag_cnt++;
                qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
                return IRQ_HANDLED;
        }
@@ -1345,11 +1346,6 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
        }
 
        if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               /* disable and free mailbox interrupt */
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       qlcnic_83xx_enable_mbx_poll(adapter);
-                       qlcnic_83xx_free_mbx_intr(adapter);
-               }
                adapter->ahw->loopback_state = 0;
                adapter->ahw->hw_ops->setup_link_event(adapter, 1);
        }
@@ -1363,33 +1359,20 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_host_sds_ring *sds_ring;
-       int ring, err;
+       int ring;
 
        clear_bit(__QLCNIC_DEV_UP, &adapter->state);
        if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
-                       qlcnic_83xx_disable_intr(adapter, sds_ring);
-                       if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
-                               qlcnic_83xx_enable_mbx_poll(adapter);
+                       if (adapter->flags & QLCNIC_MSIX_ENABLED)
+                               qlcnic_83xx_disable_intr(adapter, sds_ring);
                }
        }
 
        qlcnic_fw_destroy_ctx(adapter);
        qlcnic_detach(adapter);
 
-       if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       err = qlcnic_83xx_setup_mbx_intr(adapter);
-                       qlcnic_83xx_disable_mbx_poll(adapter);
-                       if (err) {
-                               dev_err(&adapter->pdev->dev,
-                                       "%s: failed to setup mbx interrupt\n",
-                                       __func__);
-                               goto out;
-                       }
-               }
-       }
        adapter->ahw->diag_test = 0;
        adapter->drv_sds_rings = drv_sds_rings;
 
@@ -1399,9 +1382,6 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
        if (netif_running(netdev))
                __qlcnic_up(adapter, netdev);
 
-       if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST &&
-           !(adapter->flags & QLCNIC_MSIX_ENABLED))
-               qlcnic_83xx_disable_mbx_poll(adapter);
 out:
        netif_device_attach(netdev);
 }
@@ -1704,12 +1684,6 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
                }
        } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
 
-       /* Make sure carrier is off and queue is stopped during loopback */
-       if (netif_running(netdev)) {
-               netif_carrier_off(netdev);
-               netif_tx_stop_all_queues(netdev);
-       }
-
        ret = qlcnic_do_lb_test(adapter, mode);
 
        qlcnic_83xx_clear_lb_mode(adapter, mode);
@@ -2141,6 +2115,7 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
        ahw->link_autoneg = MSB(MSW(data[3]));
        ahw->module_type = MSB(LSW(data[3]));
        ahw->has_link_events = 1;
+       ahw->lb_mode = data[4] & QLCNIC_LB_MODE_MASK;
        qlcnic_advert_link_change(adapter, link_status);
 }
 
@@ -3754,6 +3729,19 @@ static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter,
        return;
 }
 
+static inline void qlcnic_dump_mailbox_registers(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 offset;
+
+       offset = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
+       dev_info(&adapter->pdev->dev, "Mbx interrupt mask=0x%x, Mbx interrupt enable=0x%x, Host mbx control=0x%x, Fw mbx control=0x%x",
+                readl(ahw->pci_base0 + offset),
+                QLCRDX(ahw, QLCNIC_MBX_INTR_ENBL),
+                QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL),
+                QLCRDX(ahw, QLCNIC_FW_MBX_CTRL));
+}
+
 static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
 {
        struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
@@ -3798,6 +3786,8 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
                                __func__, cmd->cmd_op, cmd->type, ahw->pci_func,
                                ahw->op_mode);
                        clear_bit(QLC_83XX_MBX_READY, &mbx->status);
+                       qlcnic_dump_mailbox_registers(adapter);
+                       qlcnic_83xx_get_mbx_data(adapter, cmd);
                        qlcnic_dump_mbx(adapter, cmd);
                        qlcnic_83xx_idc_request_reset(adapter,
                                                      QLCNIC_FORCE_FW_DUMP_KEY);
index 4cae6caa6bfa42476ff79b881784dd2f42a36db6..a6a33508e40137b124541f07e3433361b086afec 100644 (file)
@@ -662,4 +662,5 @@ pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *,
                                               pci_channel_state_t);
 pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *);
 void qlcnic_83xx_io_resume(struct pci_dev *);
+void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);
 #endif
index 89208e5b25d6a1bc5c829a52ea2d79edcb5d110e..918e18ddf0381acd2f8a3097603ec6bd914fc5a8 100644 (file)
@@ -740,6 +740,7 @@ static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter)
        adapter->ahw->idc.err_code = -EIO;
        dev_err(&adapter->pdev->dev,
                "%s: Device in unknown state\n", __func__);
+       clear_bit(__QLCNIC_RESETTING, &adapter->state);
        return 0;
 }
 
@@ -818,7 +819,6 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_mailbox *mbx = ahw->mailbox;
        int ret = 0;
-       u32 owner;
        u32 val;
 
        /* Perform NIC configuration based ready state entry actions */
@@ -848,9 +848,9 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
                        set_bit(__QLCNIC_RESETTING, &adapter->state);
                        qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
                }  else {
-                       owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
-                       if (ahw->pci_func == owner)
-                               qlcnic_dump_fw(adapter);
+                       netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                                   __func__);
+                       qlcnic_83xx_idc_enter_failed_state(adapter, 1);
                }
                return -EIO;
        }
@@ -948,13 +948,26 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
        return 0;
 }
 
-static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
+static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
 {
-       dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 val, owner;
+
+       val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
+               if (ahw->pci_func == owner) {
+                       qlcnic_83xx_stop_hw(adapter);
+                       qlcnic_dump_fw(adapter);
+               }
+       }
+
+       netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",
+                   __func__);
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
-       adapter->ahw->idc.err_code = -EIO;
+       ahw->idc.err_code = -EIO;
 
-       return 0;
+       return;
 }
 
 static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)
@@ -1063,12 +1076,6 @@ void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)
        adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
        qlcnic_83xx_periodic_tasks(adapter);
 
-       /* Do not reschedule if firmaware is in hanged state and auto
-        * recovery is disabled
-        */
-       if ((adapter->flags & QLCNIC_FW_HANG) && !qlcnic_auto_fw_reset)
-               return;
-
        /* Re-schedule the function */
        if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
                qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
@@ -1219,10 +1226,10 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
        }
 
        val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
-       if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) ||
-           !qlcnic_auto_fw_reset) {
-               dev_err(&adapter->pdev->dev,
-                       "%s:failed, device in non reset mode\n", __func__);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                           __func__);
+               qlcnic_83xx_idc_enter_failed_state(adapter, 0);
                qlcnic_83xx_unlock_driver(adapter);
                return;
        }
@@ -1254,24 +1261,24 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
        if (size & 0xF)
                size = (size + 16) & ~0xF;
 
-       p_cache = kzalloc(size, GFP_KERNEL);
+       p_cache = vzalloc(size);
        if (p_cache == NULL)
                return -ENOMEM;
 
        ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,
                                                size / sizeof(u32));
        if (ret) {
-               kfree(p_cache);
+               vfree(p_cache);
                return ret;
        }
        /* 16 byte write to MS memory */
        ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache,
                                          size / 16);
        if (ret) {
-               kfree(p_cache);
+               vfree(p_cache);
                return ret;
        }
-       kfree(p_cache);
+       vfree(p_cache);
 
        return ret;
 }
@@ -1939,7 +1946,7 @@ static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev,
        p_dev->ahw->reset.seq_index = index;
 }
 
-static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
+void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
 {
        p_dev->ahw->reset.seq_index = 0;
 
@@ -1994,6 +2001,14 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
        val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
        if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))
                qlcnic_dump_fw(adapter);
+
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                           __func__);
+               qlcnic_83xx_idc_enter_failed_state(adapter, 1);
+               return err;
+       }
+
        qlcnic_83xx_init_hw(adapter);
 
        if (qlcnic_83xx_copy_bootloader(adapter))
@@ -2073,8 +2088,8 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
                ahw->nic_mode = QLCNIC_DEFAULT_MODE;
                adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
                ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
-               adapter->max_sds_rings = ahw->max_rx_ques;
-               adapter->max_tx_rings = ahw->max_tx_ques;
+               adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
+               adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
        } else {
                return -EIO;
        }
index b36c02fafcfd1ebe6f6ce8da49e73f73364f64b5..6b08194aa0d4900f8e29a4c5eca433f1d1709d9c 100644 (file)
@@ -167,27 +167,35 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 
 #define QLCNIC_TEST_LEN        ARRAY_SIZE(qlcnic_gstrings_test)
 
-static inline int qlcnic_82xx_statistics(void)
+static inline int qlcnic_82xx_statistics(struct qlcnic_adapter *adapter)
 {
-       return ARRAY_SIZE(qlcnic_device_gstrings_stats) +
-              ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
+       return ARRAY_SIZE(qlcnic_gstrings_stats) +
+              ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
+              QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
 }
 
-static inline int qlcnic_83xx_statistics(void)
+static inline int qlcnic_83xx_statistics(struct qlcnic_adapter *adapter)
 {
-       return ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
+       return ARRAY_SIZE(qlcnic_gstrings_stats) +
+              ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
               ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
-              ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
+              ARRAY_SIZE(qlcnic_83xx_rx_stats_strings) +
+              QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
 }
 
 static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
 {
-       if (qlcnic_82xx_check(adapter))
-               return qlcnic_82xx_statistics();
-       else if (qlcnic_83xx_check(adapter))
-               return qlcnic_83xx_statistics();
-       else
-               return -1;
+       int len = -1;
+
+       if (qlcnic_82xx_check(adapter)) {
+               len = qlcnic_82xx_statistics(adapter);
+               if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+                       len += ARRAY_SIZE(qlcnic_device_gstrings_stats);
+       } else if (qlcnic_83xx_check(adapter)) {
+               len = qlcnic_83xx_statistics(adapter);
+       }
+
+       return len;
 }
 
 #define        QLCNIC_TX_INTR_NOT_CONFIGURED   0X78563412
@@ -667,30 +675,25 @@ qlcnic_set_ringparam(struct net_device *dev,
 static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
                                      u8 rx_ring, u8 tx_ring)
 {
+       if (rx_ring == 0 || tx_ring == 0)
+               return -EINVAL;
+
        if (rx_ring != 0) {
                if (rx_ring > adapter->max_sds_rings) {
-                       netdev_err(adapter->netdev, "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
+                       netdev_err(adapter->netdev,
+                                  "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
                                   rx_ring, adapter->max_sds_rings);
                        return -EINVAL;
                }
        }
 
         if (tx_ring != 0) {
-               if (qlcnic_82xx_check(adapter) &&
-                   (tx_ring > adapter->max_tx_rings)) {
+               if (tx_ring > adapter->max_tx_rings) {
                        netdev_err(adapter->netdev,
                                   "Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
                                   tx_ring, adapter->max_tx_rings);
                        return -EINVAL;
                }
-
-               if (qlcnic_83xx_check(adapter) &&
-                   (tx_ring > QLCNIC_SINGLE_RING)) {
-                       netdev_err(adapter->netdev,
-                                  "Invalid ring count, Tx ring count %d should not be greater than %d driver Tx rings.\n",
-                                  tx_ring, QLCNIC_SINGLE_RING);
-                        return -EINVAL;
-               }
        }
 
        return 0;
@@ -925,18 +928,13 @@ static int qlcnic_eeprom_test(struct net_device *dev)
 
 static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 {
-       int len;
 
        struct qlcnic_adapter *adapter = netdev_priv(dev);
        switch (sset) {
        case ETH_SS_TEST:
                return QLCNIC_TEST_LEN;
        case ETH_SS_STATS:
-               len = qlcnic_dev_statistics_len(adapter) + QLCNIC_STATS_LEN;
-               if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-                   qlcnic_83xx_check(adapter))
-                       return len;
-               return qlcnic_82xx_statistics();
+               return qlcnic_dev_statistics_len(adapter);
        default:
                return -EOPNOTSUPP;
        }
@@ -948,6 +946,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_cmd_args cmd;
        int ret, drv_sds_rings = adapter->drv_sds_rings;
+       int drv_tx_rings = adapter->drv_tx_rings;
 
        if (qlcnic_83xx_check(adapter))
                return qlcnic_83xx_interrupt_test(netdev);
@@ -980,6 +979,7 @@ free_diag_res:
 
 clear_diag_irq:
        adapter->drv_sds_rings = drv_sds_rings;
+       adapter->drv_tx_rings = drv_tx_rings;
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 
        return ret;
@@ -1270,7 +1270,7 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
        return data;
 }
 
-static void qlcnic_update_stats(struct qlcnic_adapter *adapter)
+void qlcnic_update_stats(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_host_tx_ring *tx_ring;
        int ring;
index e9c21e5d0ca95c7cc08df0c5f29cca2f7b473ba4..c4262c23ed7c77b009f6c5cebf233a54ebfd685b 100644 (file)
@@ -134,6 +134,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
        struct qlcnic_skb_frag *buffrag;
        int i, j;
 
+       spin_lock(&tx_ring->tx_clean_lock);
+
        cmd_buf = tx_ring->cmd_buf_arr;
        for (i = 0; i < tx_ring->num_desc; i++) {
                buffrag = cmd_buf->frag_array;
@@ -157,6 +159,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
                }
                cmd_buf++;
        }
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 }
 
 void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
index 0149c94953474e6ad0ffd56b93cc440c67e77687..ad1531ae3aa8f8e3cda7f56c36bb12ec46694464 100644 (file)
@@ -687,17 +687,15 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
        if (adapter->ahw->linkup && !linkup) {
                netdev_info(netdev, "NIC Link is down\n");
                adapter->ahw->linkup = 0;
-               if (netif_running(netdev)) {
-                       netif_carrier_off(netdev);
-                       netif_tx_stop_all_queues(netdev);
-               }
+               netif_carrier_off(netdev);
        } else if (!adapter->ahw->linkup && linkup) {
+               /* Do not advertise Link up if the port is in loopback mode */
+               if (qlcnic_83xx_check(adapter) && adapter->ahw->lb_mode)
+                       return;
+
                netdev_info(netdev, "NIC Link is up\n");
                adapter->ahw->linkup = 1;
-               if (netif_running(netdev)) {
-                       netif_carrier_on(netdev);
-                       netif_wake_queue(netdev);
-               }
+               netif_carrier_on(netdev);
        }
 }
 
@@ -784,7 +782,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
        struct net_device *netdev = adapter->netdev;
        struct qlcnic_skb_frag *frag;
 
-       if (!spin_trylock(&adapter->tx_clean_lock))
+       if (!spin_trylock(&tx_ring->tx_clean_lock))
                return 1;
 
        sw_consumer = tx_ring->sw_consumer;
@@ -813,8 +811,9 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
                        break;
        }
 
+       tx_ring->sw_consumer = sw_consumer;
+
        if (count && netif_running(netdev)) {
-               tx_ring->sw_consumer = sw_consumer;
                smp_mb();
                if (netif_tx_queue_stopped(tx_ring->txq) &&
                    netif_carrier_ok(netdev)) {
@@ -840,7 +839,8 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
         */
        hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
        done = (sw_consumer == hw_consumer);
-       spin_unlock(&adapter->tx_clean_lock);
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 
        return done;
 }
index 05c1eef8df1325359ef1bf73df8344492a95876d..550791b8fbae98404f4be790520d0c4985871802 100644 (file)
@@ -1178,6 +1178,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
        } else {
                adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
                adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS;
+               adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
        }
 
@@ -1755,7 +1756,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
        if (qlcnic_sriov_vf_check(adapter))
                qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
        smp_mb();
-       spin_lock(&adapter->tx_clean_lock);
        netif_carrier_off(netdev);
        adapter->ahw->linkup = 0;
        netif_tx_disable(netdev);
@@ -1776,7 +1776,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
 
        for (ring = 0; ring < adapter->drv_tx_rings; ring++)
                qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
-       spin_unlock(&adapter->tx_clean_lock);
 }
 
 /* Usage: During suspend and firmware recovery module */
@@ -1940,7 +1939,6 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
        qlcnic_detach(adapter);
 
        adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
-       adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
        adapter->ahw->diag_test = test;
        adapter->ahw->linkup = 0;
 
@@ -2172,6 +2170,7 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
                }
                memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
                tx_ring->cmd_buf_arr = cmd_buf_arr;
+               spin_lock_init(&tx_ring->tx_clean_lock);
        }
 
        if (qlcnic_83xx_check(adapter) ||
@@ -2299,7 +2298,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        rwlock_init(&adapter->ahw->crb_lock);
        mutex_init(&adapter->ahw->mem_lock);
 
-       spin_lock_init(&adapter->tx_clean_lock);
        INIT_LIST_HEAD(&adapter->mac_list);
 
        qlcnic_register_dcb(adapter);
@@ -2782,6 +2780,9 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct net_device_stats *stats = &netdev->stats;
 
+       if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+               qlcnic_update_stats(adapter);
+
        stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
        stats->tx_packets = adapter->stats.xmitfinished;
        stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
index 686f460b15022b4b2b7759ad29493a64a1f84592..024f8161d2fe1cccd0e97cc2a1eccd67371b8ab4 100644 (file)
@@ -75,7 +75,6 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
        num_vfs = sriov->num_vfs;
        max = num_vfs + 1;
        info->bit_offsets = 0xffff;
-       info->max_tx_ques = res->num_tx_queues / max;
        info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
        num_vf_macs = QLCNIC_SRIOV_VF_MAX_MAC;
 
@@ -86,6 +85,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                info->max_tx_mac_filters = temp;
                info->min_tx_bw = 0;
                info->max_tx_bw = MAX_BW;
+               info->max_tx_ques = res->num_tx_queues - sriov->num_vfs;
        } else {
                id = qlcnic_sriov_func_to_index(adapter, func);
                if (id < 0)
@@ -95,6 +95,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                info->max_tx_bw = vp->max_tx_bw;
                info->max_rx_ucast_mac_filters = num_vf_macs;
                info->max_tx_mac_filters = num_vf_macs;
+               info->max_tx_ques = QLCNIC_SINGLE_RING;
        }
 
        info->max_rx_ip_addr = res->num_destip / max;
index 449f506d2e8ff3e71abc22bba6ce8e67bcf45305..f705aeeba767eec647670c8d9b1a0e210f9f5e40 100644 (file)
@@ -4765,6 +4765,8 @@ static int qlge_probe(struct pci_dev *pdev,
                            NETIF_F_RXCSUM;
        ndev->features = ndev->hw_features;
        ndev->vlan_features = ndev->hw_features;
+       /* vlan gets same features (except vlan filter) */
+       ndev->vlan_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
 
        if (test_bit(QL_DMA64, &qdev->flags))
                ndev->features |= NETIF_F_HIGHDMA;
index 8a7a23a84ac5c3b6a7b7d4979e8c5866097895a5..797b56a0efc4a4e7ab1ff5c9af1f0e50f29e9d17 100644 (file)
@@ -622,17 +622,15 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
        if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
                return -EOPNOTSUPP;
 
-       if (netif_msg_hw(priv)) {
-               if (priv->dma_cap.time_stamp) {
-                       pr_debug("IEEE 1588-2002 Time Stamp supported\n");
-                       priv->adv_ts = 0;
-               }
-               if (priv->dma_cap.atime_stamp && priv->extend_desc) {
-                       pr_debug
-                           ("IEEE 1588-2008 Advanced Time Stamp supported\n");
-                       priv->adv_ts = 1;
-               }
-       }
+       priv->adv_ts = 0;
+       if (priv->dma_cap.atime_stamp && priv->extend_desc)
+               priv->adv_ts = 1;
+
+       if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
+               pr_debug("IEEE 1588-2002 Time Stamp supported\n");
+
+       if (netif_msg_hw(priv) && priv->adv_ts)
+               pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
 
        priv->hw->ptp = &stmmac_ptp;
        priv->hwts_tx_en = 0;
index b8b0eeed0f92bb68f34e1dac22e1f072faec77ce..7680581ebe12fe58a60de42b419467e3f2f065f7 100644 (file)
@@ -56,7 +56,7 @@ static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
 
        priv->hw->ptp->config_addend(priv->ioaddr, addend);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
@@ -91,7 +91,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
 
        priv->hw->ptp->adjust_systime(priv->ioaddr, sec, nsec, neg_adj);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
index 5120d9ce1dd4cdbdd8608550f87392d0a5f6bbb9..5330fd298705e06181b7d1a2a1557e0cea27e85c 100644 (file)
@@ -740,6 +740,8 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
                /* set speed_in input in case RMII mode is used in 100Mbps */
                if (phy->speed == 100)
                        mac_control |= BIT(15);
+               else if (phy->speed == 10)
+                       mac_control |= BIT(18); /* In Band mode */
 
                *link = true;
        } else {
@@ -2106,7 +2108,7 @@ static int cpsw_probe(struct platform_device *pdev)
        while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
                for (i = res->start; i <= res->end; i++) {
                        if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0,
-                                            dev_name(priv->dev), priv)) {
+                                            dev_name(&pdev->dev), priv)) {
                                dev_err(priv->dev, "error attaching irq\n");
                                goto clean_ale_ret;
                        }
index 628b736e5ae776fcf00333bed8c355e4b518314e..0e9fb3301b1136e333cdd3d9bc62bcacc89dd4bb 100644 (file)
@@ -2080,7 +2080,8 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 }
 
 /* Return subqueue id on this core (one per core). */
-static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb,
+                                void *accel_priv)
 {
        return smp_processor_id();
 }
index cce6c4bc556a97e03fbe5f1648396aed6bf7070a..ef312bc6b8658deabae28d179c39237564b8ede4 100644 (file)
@@ -1618,6 +1618,7 @@ static void rhine_reset_task(struct work_struct *work)
                goto out_unlock;
 
        napi_disable(&rp->napi);
+       netif_tx_disable(dev);
        spin_lock_bh(&rp->lock);
 
        /* clear all descriptors */
index 3169252613faae400904201fa5ad9f1a7decf1cf..5d78c1d08abd60fcc6bcee5dea5ab178a2a166da 100644 (file)
@@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case HDLCDRVCTL_CALIBRATE:
                if(!capable(CAP_SYS_RAWIO))
                        return -EPERM;
+               if (bi.data.calibrate > INT_MAX / s->par.bitrate)
+                       return -EINVAL;
                s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
                return 0;
 
index 1971411574db1c7ae2dd6549490ab6975e816cd1..61dd2447e1bb4eedb5d8e6b72abcf21e9f273afb 100644 (file)
@@ -1057,6 +1057,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                break;
 
        case SIOCYAMGCFG:
+               memset(&yi, 0, sizeof(yi));
                yi.cfg.mask = 0xffffffff;
                yi.cfg.iobase = yp->iobase;
                yi.cfg.irq = yp->irq;
index 524f713f60170b2d5632bbac6958ae0529a80b1c..71baeb3ed905cfa9ed930ab9f7ac63c3edd206b7 100644 (file)
@@ -261,9 +261,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
        struct sk_buff *skb;
 
        net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev;
-       if (!net) {
-               netdev_err(net, "got receive callback but net device"
-                       " not initialized yet\n");
+       if (!net || net->reg_state != NETREG_REGISTERED) {
                packet->status = NVSP_STAT_FAIL;
                return 0;
        }
@@ -327,7 +325,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
                return -EINVAL;
 
        nvdev->start_remove = true;
-       cancel_delayed_work_sync(&ndevctx->dwork);
        cancel_work_sync(&ndevctx->work);
        netif_tx_disable(ndev);
        rndis_filter_device_remove(hdev);
@@ -436,19 +433,11 @@ static int netvsc_probe(struct hv_device *dev,
        SET_ETHTOOL_OPS(net, &ethtool_ops);
        SET_NETDEV_DEV(net, &dev->device);
 
-       ret = register_netdev(net);
-       if (ret != 0) {
-               pr_err("Unable to register netdev.\n");
-               free_netdev(net);
-               goto out;
-       }
-
        /* Notify the netvsc driver of the new device */
        device_info.ring_size = ring_size;
        ret = rndis_filter_device_add(dev, &device_info);
        if (ret != 0) {
                netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
-               unregister_netdev(net);
                free_netdev(net);
                hv_set_drvdata(dev, NULL);
                return ret;
@@ -457,7 +446,13 @@ static int netvsc_probe(struct hv_device *dev,
 
        netif_carrier_on(net);
 
-out:
+       ret = register_netdev(net);
+       if (ret != 0) {
+               pr_err("Unable to register netdev.\n");
+               rndis_filter_device_remove(dev);
+               free_netdev(net);
+       }
+
        return ret;
 }
 
index acf93798dc675929394e82ffed96cd1616c3a31d..bc8faaec33f5afb0bbf7efdd88cd082122c3cc7f 100644 (file)
@@ -299,7 +299,7 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
 
        if (vlan->fwd_priv) {
                skb->dev = vlan->lowerdev;
-               ret = dev_hard_start_xmit(skb, skb->dev, NULL, vlan->fwd_priv);
+               ret = dev_queue_xmit_accel(skb, vlan->fwd_priv);
        } else {
                ret = macvlan_queue_xmit(skb, dev);
        }
@@ -338,6 +338,8 @@ static const struct header_ops macvlan_hard_header_ops = {
        .cache_update   = eth_header_cache_update,
 };
 
+static struct rtnl_link_ops macvlan_link_ops;
+
 static int macvlan_open(struct net_device *dev)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
@@ -353,7 +355,8 @@ static int macvlan_open(struct net_device *dev)
                goto hash_add;
        }
 
-       if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
+       if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD &&
+           dev->rtnl_link_ops == &macvlan_link_ops) {
                vlan->fwd_priv =
                      lowerdev->netdev_ops->ndo_dfwd_add_station(lowerdev, dev);
 
@@ -362,10 +365,8 @@ static int macvlan_open(struct net_device *dev)
                 */
                if (IS_ERR_OR_NULL(vlan->fwd_priv)) {
                        vlan->fwd_priv = NULL;
-               } else {
-                       dev->features &= ~NETIF_F_LLTX;
+               } else
                        return 0;
-               }
        }
 
        err = -EBUSY;
@@ -690,8 +691,18 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
                                              netdev_features_t features)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
+       netdev_features_t mask;
+
+       features |= NETIF_F_ALL_FOR_ALL;
+       features &= (vlan->set_features | ~MACVLAN_FEATURES);
+       mask = features;
+
+       features = netdev_increment_features(vlan->lowerdev->features,
+                                            features,
+                                            mask);
+       features |= NETIF_F_LLTX;
 
-       return features & (vlan->set_features | ~MACVLAN_FEATURES);
+       return features;
 }
 
 static const struct ethtool_ops macvlan_ethtool_ops = {
@@ -1019,9 +1030,8 @@ static int macvlan_device_event(struct notifier_block *unused,
                break;
        case NETDEV_FEAT_CHANGE:
                list_for_each_entry(vlan, &port->vlans, list) {
-                       vlan->dev->features = dev->features & MACVLAN_FEATURES;
                        vlan->dev->gso_max_size = dev->gso_max_size;
-                       netdev_features_change(vlan->dev);
+                       netdev_update_features(vlan->dev);
                }
                break;
        case NETDEV_UNREGISTER:
index 36c6994436b7ce7edb9ff9a0d9725c1aa09a4407..98434b84f0415ef2bfd635ba9dc4bc2f7a9ea762 100644 (file)
@@ -565,10 +565,8 @@ int phy_start_interrupts(struct phy_device *phydev)
        int err = 0;
 
        atomic_set(&phydev->irq_disable, 0);
-       if (request_irq(phydev->irq, phy_interrupt,
-                               IRQF_SHARED,
-                               "phy_interrupt",
-                               phydev) < 0) {
+       if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt",
+                       phydev) < 0) {
                pr_warn("%s: Can't get IRQ %d (PHY)\n",
                        phydev->bus->name, phydev->irq);
                phydev->irq = PHY_POLL;
index 736050d6b4516b3de85eb2c214d0464ff690d99f..b75ae5bde6734c1c70b196c00a841d84f0f984dd 100644 (file)
@@ -1647,7 +1647,8 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
+                            void *accel_priv)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 7c8343a4f91823a579910cbcccc5827a2eb1d986..ecec8029c5e84c557374817429c29a505f699c0d 100644 (file)
@@ -348,7 +348,8 @@ unlock:
  * different rxq no. here. If we could not get rxhash, then we would
  * hope the rxq no. may help here.
  */
-static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        struct tun_struct *tun = netdev_priv(dev);
        struct tun_flow_entry *e;
index 85e4a01670f06e207609299ecacd035df3e098f3..47b0f732b0b10d21a07d4567e778efcbe4a7fddb 100644 (file)
@@ -276,12 +276,12 @@ config USB_NET_CDC_MBIM
          module will be called cdc_mbim.
 
 config USB_NET_DM9601
-       tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
+       tristate "Davicom DM96xx based USB 10/100 ethernet devices"
        depends on USB_USBNET
        select CRC32
        help
-         This option adds support for Davicom DM9601 based USB 1.1
-         10/100 Ethernet adapters.
+         This option adds support for Davicom DM9601/DM9620/DM9621A
+         based USB 10/100 Ethernet adapters.
 
 config USB_NET_SR9700
        tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices"
index c6867f926cffc18a981c7682e5493ae36924d988..e80219877730973a74e04791a42eae6a3eee038b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices
+ * Davicom DM96xx USB 10/100Mbps ethernet devices
  *
  * Peter Korsgaard <jacmet@sunsite.dk>
  *
@@ -364,7 +364,12 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->ethtool_ops = &dm9601_ethtool_ops;
        dev->net->hard_header_len += DM_TX_OVERHEAD;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD;
+
+       /* dm9620/21a require room for 4 byte padding, even in dm9601
+        * mode, so we need +1 to be able to receive full size
+        * ethernet frames.
+        */
+       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;
 
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = dm9601_mdio_read;
@@ -468,7 +473,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
                                       gfp_t flags)
 {
-       int len;
+       int len, pad;
 
        /* format:
           b1: packet length low
@@ -476,12 +481,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
           b3..n: packet data
        */
 
-       len = skb->len;
+       len = skb->len + DM_TX_OVERHEAD;
 
-       if (skb_headroom(skb) < DM_TX_OVERHEAD) {
+       /* workaround for dm962x errata with tx fifo getting out of
+        * sync if a USB bulk transfer retry happens right after a
+        * packet with odd / maxpacket length by adding up to 3 bytes
+        * padding.
+        */
+       while ((len & 1) || !(len % dev->maxpacket))
+               len++;
+
+       len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
+       pad = len - skb->len;
+
+       if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
                struct sk_buff *skb2;
 
-               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags);
+               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
                dev_kfree_skb_any(skb);
                skb = skb2;
                if (!skb)
@@ -490,10 +506,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 
        __skb_push(skb, DM_TX_OVERHEAD);
 
-       /* usbnet adds padding if length is a multiple of packet size
-          if so, adjust length value in header */
-       if ((skb->len % dev->maxpacket) == 0)
-               len++;
+       if (pad) {
+               memset(skb->data + skb->len, 0, pad);
+               __skb_put(skb, pad);
+       }
 
        skb->data[0] = len;
        skb->data[1] = len >> 8;
@@ -543,7 +559,7 @@ static int dm9601_link_reset(struct usbnet *dev)
 }
 
 static const struct driver_info dm9601_info = {
-       .description    = "Davicom DM9601 USB Ethernet",
+       .description    = "Davicom DM96xx USB 10/100 Ethernet",
        .flags          = FLAG_ETHER | FLAG_LINK_INTR,
        .bind           = dm9601_bind,
        .rx_fixup       = dm9601_rx_fixup,
@@ -594,6 +610,22 @@ static const struct usb_device_id products[] = {
         USB_DEVICE(0x0a46, 0x9620),    /* DM9620 USB to Fast Ethernet Adapter */
         .driver_info = (unsigned long)&dm9601_info,
         },
+       {
+        USB_DEVICE(0x0a46, 0x9621),    /* DM9621A USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
+       {
+        USB_DEVICE(0x0a46, 0x9622),    /* DM9622 USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
+       {
+        USB_DEVICE(0x0a46, 0x0269),    /* DM962OA USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
+       {
+        USB_DEVICE(0x0a46, 0x1269),    /* DM9621A USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
        {},                     // END
 };
 
@@ -612,5 +644,5 @@ static struct usb_driver dm9601_driver = {
 module_usb_driver(dm9601_driver);
 
 MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
-MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices");
+MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");
 MODULE_LICENSE("GPL");
index 86292e6aaf4955c4412ead6579f74e6848bcd089..1a482344b3f507e97486059d56280dfd3f23d37c 100644 (file)
@@ -185,7 +185,6 @@ enum rx_ctrl_state{
 #define BM_REQUEST_TYPE (0xa1)
 #define B_NOTIFICATION  (0x20)
 #define W_VALUE         (0x0)
-#define W_INDEX         (0x2)
 #define W_LENGTH        (0x2)
 
 #define B_OVERRUN       (0x1<<6)
@@ -1487,6 +1486,7 @@ static void tiocmget_intr_callback(struct urb *urb)
        struct uart_icount *icount;
        struct hso_serial_state_notification *serial_state_notification;
        struct usb_device *usb;
+       int if_num;
 
        /* Sanity checks */
        if (!serial)
@@ -1495,15 +1495,24 @@ static void tiocmget_intr_callback(struct urb *urb)
                handle_usb_error(status, __func__, serial->parent);
                return;
        }
+
+       /* tiocmget is only supported on HSO_PORT_MODEM */
        tiocmget = serial->tiocmget;
        if (!tiocmget)
                return;
+       BUG_ON((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM);
+
        usb = serial->parent->usb;
+       if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber;
+
+       /* wIndex should be the USB interface number of the port to which the
+        * notification applies, which should always be the Modem port.
+        */
        serial_state_notification = &tiocmget->serial_state_notification;
        if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
            serial_state_notification->bNotification != B_NOTIFICATION ||
            le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
-           le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
+           le16_to_cpu(serial_state_notification->wIndex) != if_num ||
            le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
                dev_warn(&usb->dev,
                         "hso received invalid serial state notification\n");
index 03832d3780aa6134059dc4768bb7614d71075b82..f54637828574f6b4af868d978288d4920aa3061a 100644 (file)
@@ -117,7 +117,6 @@ enum {
 struct mcs7830_data {
        u8 multi_filter[8];
        u8 config;
-       u8 link_counter;
 };
 
 static const char driver_name[] = "MOSCHIP usb-ethernet driver";
@@ -561,26 +560,16 @@ static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 {
        u8 *buf = urb->transfer_buffer;
        bool link, link_changed;
-       struct mcs7830_data *data = mcs7830_get_data(dev);
 
        if (urb->actual_length < 16)
                return;
 
-       link = !(buf[1] & 0x20);
+       link = !(buf[1] == 0x20);
        link_changed = netif_carrier_ok(dev->net) != link;
        if (link_changed) {
-               data->link_counter++;
-               /*
-                  track link state 20 times to guard against erroneous
-                  link state changes reported sometimes by the chip
-                */
-               if (data->link_counter > 20) {
-                       data->link_counter = 0;
-                       usbnet_link_change(dev, link, 0);
-                       netdev_dbg(dev->net, "Link Status is: %d\n", link);
-               }
-       } else
-               data->link_counter = 0;
+               usbnet_link_change(dev, link, 0);
+               netdev_dbg(dev->net, "Link Status is: %d\n", link);
+       }
 }
 
 static const struct driver_info moschip_info = {
index 8494bb53ebdc9f33abee1d8e5a27f7d0dea3cc17..aba04f56176008aa12d0eaf72590d239f0affce8 100644 (file)
@@ -1245,7 +1245,7 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
                return -ENOMEM;
 
        urb->num_sgs = num_sgs;
-       sg_init_table(urb->sg, urb->num_sgs);
+       sg_init_table(urb->sg, urb->num_sgs + 1);
 
        sg_set_buf(&urb->sg[s++], skb->data, skb_headlen(skb));
        total_len += skb_headlen(skb);
index d208f860498106013913211183baa39a37f33982..5d776447d9c33e2da56b622a2537536cf950ca0c 100644 (file)
@@ -1797,16 +1797,17 @@ static int virtnet_restore(struct virtio_device *vdev)
        if (err)
                return err;
 
-       if (netif_running(vi->dev))
+       if (netif_running(vi->dev)) {
+               for (i = 0; i < vi->curr_queue_pairs; i++)
+                       if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+                               schedule_delayed_work(&vi->refill, 0);
+
                for (i = 0; i < vi->max_queue_pairs; i++)
                        virtnet_napi_enable(&vi->rq[i]);
+       }
 
        netif_device_attach(vi->dev);
 
-       for (i = 0; i < vi->curr_queue_pairs; i++)
-               if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
-                       schedule_delayed_work(&vi->refill, 0);
-
        mutex_lock(&vi->config_lock);
        vi->config_enable = true;
        mutex_unlock(&vi->config_lock);
index 249e01c5600c9010a19ca07c175867ec9e5fb91d..ed384fee76ac9ffa12eff0563864424f95ab2d01 100644 (file)
@@ -2440,7 +2440,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                /* update header length based on lower device */
                dev->hard_header_len = lowerdev->hard_header_len +
                                       (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
-       }
+       } else if (use_ipv6)
+               vxlan->flags |= VXLAN_F_IPV6;
 
        if (data[IFLA_VXLAN_TOS])
                vxlan->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);
index 8d78253c26cee6f459121e7e8ef5c3e0e44b8b2a..a366d6b4626f5fdd0bcf04b1d6b9c6063a70afbd 100644 (file)
@@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                                mask2 |= ATH9K_INT_CST;
                        if (isr2 & AR_ISR_S2_TSFOOR)
                                mask2 |= ATH9K_INT_TSFOOR;
+
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                               REG_WRITE(ah, AR_ISR_S2, isr2);
+                               isr &= ~AR_ISR_BCNMISC;
+                       }
                }
 
-               isr = REG_READ(ah, AR_ISR_RAC);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+                       isr = REG_READ(ah, AR_ISR_RAC);
+
                if (isr == 0xffffffff) {
                        *masked = 0;
                        return false;
@@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 
                        *masked |= ATH9K_INT_TX;
 
-                       s0_s = REG_READ(ah, AR_ISR_S0_S);
+                       if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                               s0_s = REG_READ(ah, AR_ISR_S0_S);
+                               s1_s = REG_READ(ah, AR_ISR_S1_S);
+                       } else {
+                               s0_s = REG_READ(ah, AR_ISR_S0);
+                               REG_WRITE(ah, AR_ISR_S0, s0_s);
+                               s1_s = REG_READ(ah, AR_ISR_S1);
+                               REG_WRITE(ah, AR_ISR_S1, s1_s);
+
+                               isr &= ~(AR_ISR_TXOK |
+                                        AR_ISR_TXDESC |
+                                        AR_ISR_TXERR |
+                                        AR_ISR_TXEOL);
+                       }
+
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
-                       s1_s = REG_READ(ah, AR_ISR_S1_S);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
                }
@@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                *masked |= mask2;
        }
 
-       if (AR_SREV_9100(ah))
-               return true;
-
-       if (isr & AR_ISR_GENTMR) {
+       if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) {
                u32 s5_s;
 
-               s5_s = REG_READ(ah, AR_ISR_S5_S);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                       s5_s = REG_READ(ah, AR_ISR_S5_S);
+               } else {
+                       s5_s = REG_READ(ah, AR_ISR_S5);
+               }
+
                ah->intr_gen_timer_trigger =
                                MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
 
@@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
                    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
                        *masked |= ATH9K_INT_TIM_TIMER;
+
+               if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                       REG_WRITE(ah, AR_ISR_S5, s5_s);
+                       isr &= ~AR_ISR_GENTMR;
+               }
        }
 
+       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+               REG_WRITE(ah, AR_ISR, isr);
+               REG_READ(ah, AR_ISR);
+       }
+
+       if (AR_SREV_9100(ah))
+               return true;
+
        if (sync_cause) {
                ath9k_debug_sync_cause(common, sync_cause);
                fatal_int =
index 9a2657fdd9ccd4ec62f96f8a639182e2ded29fec..608d739d13782233db4271f9248c3472601b1a5f 100644 (file)
@@ -127,21 +127,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
        struct ath9k_vif_iter_data *iter_data = data;
        int i;
 
-       for (i = 0; i < ETH_ALEN; i++)
-               iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       if (iter_data->hw_macaddr != NULL) {
+               for (i = 0; i < ETH_ALEN; i++)
+                       iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       } else {
+               iter_data->hw_macaddr = mac;
+       }
 }
 
-static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv,
                                     struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(priv->ah);
        struct ath9k_vif_iter_data iter_data;
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
-       iter_data.hw_macaddr = common->macaddr;
+       iter_data.hw_macaddr = NULL;
        memset(&iter_data.mask, 0xff, ETH_ALEN);
 
        if (vif)
@@ -153,6 +158,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
                ath9k_htc_bssid_iter, &iter_data);
 
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+
+       if (iter_data.hw_macaddr)
+               memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
+
        ath_hw_setbssidmask(common);
 }
 
@@ -1063,7 +1072,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        priv->vif_slot |= (1 << avp->index);
        priv->nvifs++;
@@ -1128,7 +1137,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 
        ath9k_htc_set_opmode(priv);
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        /*
         * Stop ANI only if there are no associated station interfaces.
index 74f452c7b1667c47a65506a077042f2b0668c3a8..21aa09e0e825df1161a4fcca3753ca08e9632558 100644 (file)
@@ -965,8 +965,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
        struct ath_common *common = ath9k_hw_common(ah);
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
        memset(iter_data, 0, sizeof(*iter_data));
        memset(&iter_data->mask, 0xff, ETH_ALEN);
index 86605027c41d6b4187c15ba874ef8fe25056676e..e6272546395a982d6d3e6e23239eaddc1bc3bf60 100644 (file)
@@ -357,21 +357,27 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095B, 0x5012, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095B, 0x500A, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5420, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5090, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5190, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
 #endif /* CONFIG_IWLMVM */
index c72438bb2fafd24b8e59f416d4e4311752dce941..a1b32ee9594a6b9b899caa03cea53f3d9a0ddf90 100644 (file)
@@ -2011,7 +2011,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
           (hwsim_flags & HWSIM_TX_STAT_ACK)) {
                if (skb->len >= 16) {
                        hdr = (struct ieee80211_hdr *) skb->data;
-                       mac80211_hwsim_monitor_ack(txi->rate_driver_data[0],
+                       mac80211_hwsim_monitor_ack(data2->channel,
                                                   hdr->addr2);
                }
                txi->flags |= IEEE80211_TX_STAT_ACK;
index 78e8a6666cc6edad81bd87c98dcf0353af371866..8bb8988c435cf04b0280aef69d4e9d01acc24fee 100644 (file)
@@ -746,7 +746,8 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
 }
 
 static u16
-mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb)
+mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
+                               void *accel_priv)
 {
        skb->priority = cfg80211_classify8021d(skb);
        return mwifiex_1d_to_wmm_queue[skb->priority];
index 0f494444bcd1d90b457b927d704bf77abe0592ca..5a53195d016b61da57f3198ad1f616343e1ebd3d 100644 (file)
@@ -740,6 +740,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
        };
        int index = rtlpci->rx_ring[rx_queue_idx].idx;
 
+       if (rtlpci->driver_is_goingto_unload)
+               return;
        /*RX NORMAL PKT */
        while (count--) {
                /*rx descriptor */
@@ -1636,6 +1638,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
         */
        set_hal_stop(rtlhal);
 
+       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->disable_interrupt(hw);
        cancel_work_sync(&rtlpriv->works.lps_change_work);
 
@@ -1653,7 +1656,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
        ppsc->rfchange_inprogress = true;
        spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
 
-       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->hw_disable(hw);
        /* some things are not needed if firmware not available */
        if (!rtlpriv->max_fw_size)
index 08ae01b41c832d7144bdeceb70b976adaf281d4c..c47794b9d42f9bfd71d2761a48f8429a8b4633c5 100644 (file)
@@ -101,6 +101,13 @@ struct xenvif_rx_meta {
 
 #define MAX_PENDING_REQS 256
 
+/* It's possible for an skb to have a maximal number of frags
+ * but still be less than MAX_BUFFER_OFFSET in size. Thus the
+ * worst-case number of copy operations is MAX_SKB_FRAGS per
+ * ring slot.
+ */
+#define MAX_GRANT_COPY_OPS (MAX_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE)
+
 struct xenvif {
        /* Unique identifier for this interface. */
        domid_t          domid;
@@ -143,13 +150,13 @@ struct xenvif {
         */
        RING_IDX rx_req_cons_peek;
 
-       /* Given MAX_BUFFER_OFFSET of 4096 the worst case is that each
-        * head/fragment page uses 2 copy operations because it
-        * straddles two buffers in the frontend.
-        */
-       struct gnttab_copy grant_copy_op[2*XEN_NETIF_RX_RING_SIZE];
-       struct xenvif_rx_meta meta[2*XEN_NETIF_RX_RING_SIZE];
+       /* This array is allocated seperately as it is large */
+       struct gnttab_copy *grant_copy_op;
 
+       /* We create one meta structure per ring request we consume, so
+        * the maximum number is the same as the ring size.
+        */
+       struct xenvif_rx_meta meta[XEN_NETIF_RX_RING_SIZE];
 
        u8               fe_dev_addr[6];
 
index 870f1fa583702ee4bc61d9acab3e4925a4d984e0..fff8cddfed816d3479fac57a6f91b4d827272033 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
+#include <linux/vmalloc.h>
 
 #include <xen/events.h>
 #include <asm/xen/hypercall.h>
@@ -307,6 +308,15 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
        SET_NETDEV_DEV(dev, parent);
 
        vif = netdev_priv(dev);
+
+       vif->grant_copy_op = vmalloc(sizeof(struct gnttab_copy) *
+                                    MAX_GRANT_COPY_OPS);
+       if (vif->grant_copy_op == NULL) {
+               pr_warn("Could not allocate grant copy space for %s\n", name);
+               free_netdev(dev);
+               return ERR_PTR(-ENOMEM);
+       }
+
        vif->domid  = domid;
        vif->handle = handle;
        vif->can_sg = 1;
@@ -487,6 +497,7 @@ void xenvif_free(struct xenvif *vif)
 
        unregister_netdev(vif->dev);
 
+       vfree(vif->grant_copy_op);
        free_netdev(vif->dev);
 
        module_put(THIS_MODULE);
index e884ee1fe7edf7e3fa41dd9998eb00be8ecc6d08..78425554a537579b01378b99295913c1706f0b0a 100644 (file)
@@ -608,7 +608,7 @@ void xenvif_rx_action(struct xenvif *vif)
        if (!npo.copy_prod)
                return;
 
-       BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op));
+       BUG_ON(npo.copy_prod > MAX_GRANT_COPY_OPS);
        gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod);
 
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
@@ -1197,6 +1197,9 @@ static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
 
        err = -EPROTO;
 
+       if (fragment)
+               goto out;
+
        switch (ip_hdr(skb)->protocol) {
        case IPPROTO_TCP:
                err = maybe_pull_tail(skb,
@@ -1206,8 +1209,10 @@ static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        tcp_hdr(skb)->check =
@@ -1224,8 +1229,10 @@ static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        udp_hdr(skb)->check =
@@ -1347,8 +1354,10 @@ static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        tcp_hdr(skb)->check =
@@ -1365,8 +1374,10 @@ static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                        goto out;
 
                if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
                        goto out;
+               }
 
                if (recalculate_partial_csum)
                        udp_hdr(skb)->check =
index de6f8990246fefc8aaef7c0e88e0371143ae9859..c6973f101a3e4ae9e00c604cd9e1708d1bd88485 100644 (file)
@@ -20,7 +20,7 @@ config OF_SELFTEST
        depends on OF_IRQ
        help
          This option builds in test cases for the device tree infrastructure
-         that are executed one at boot time, and the results dumped to the
+         that are executed once at boot time, and the results dumped to the
          console.
 
          If unsure, say N here, but this option is safe to enable.
index 4b9317bdb81ce85209573e6c28f86492e643962b..d3dd41c840f1cd8d6784e4a61382cb3e4987ad1a 100644 (file)
@@ -69,14 +69,6 @@ static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
                 (unsigned long long)cp, (unsigned long long)s,
                 (unsigned long long)da);
 
-       /*
-        * If the number of address cells is larger than 2 we assume the
-        * mapping doesn't specify a physical address. Rather, the address
-        * specifies an identifier that must match exactly.
-        */
-       if (na > 2 && memcmp(range, addr, na * 4) != 0)
-               return OF_BAD_ADDR;
-
        if (da < cp || da >= (cp + s))
                return OF_BAD_ADDR;
        return da - cp;
index 2fa024b97c4350c680e384c645dc17d0fc5dc177..758b4f8b30b7d237c92b6a541f01db535d37101b 100644 (file)
@@ -922,8 +922,16 @@ void __init unflatten_device_tree(void)
  */
 void __init unflatten_and_copy_device_tree(void)
 {
-       int size = __be32_to_cpu(initial_boot_params->totalsize);
-       void *dt = early_init_dt_alloc_memory_arch(size,
+       int size;
+       void *dt;
+
+       if (!initial_boot_params) {
+               pr_warn("No valid device tree found, continuing without\n");
+               return;
+       }
+
+       size = __be32_to_cpu(initial_boot_params->totalsize);
+       dt = early_init_dt_alloc_memory_arch(size,
                __alignof__(struct boot_param_header));
 
        if (dt) {
index 786b0b47fae46802503ecbecee5719887830c44c..27212402c53247819cf4edf09e576d2cc69f3136 100644 (file)
@@ -165,7 +165,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                if (of_get_property(ipar, "interrupt-controller", NULL) !=
                                NULL) {
                        pr_debug(" -> got it !\n");
-                       of_node_put(old);
                        return 0;
                }
 
@@ -250,8 +249,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                 * Successfully parsed an interrrupt-map translation; copy new
                 * interrupt specifier into the out_irq structure
                 */
-               of_node_put(out_irq->np);
-               out_irq->np = of_node_get(newpar);
+               out_irq->np = newpar;
 
                match_array = imap - newaddrsize - newintsize;
                for (i = 0; i < newintsize; i++)
@@ -268,7 +266,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
        }
  fail:
        of_node_put(ipar);
-       of_node_put(out_irq->np);
        of_node_put(newpar);
 
        return -EINVAL;
index 1cf605f6767357947e9a097981caa7d7869ca2f0..e86439283a5d1911933eed185e22a50146093968 100644 (file)
@@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 
        status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
        if (ACPI_FAILURE(status)) {
-               acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status);
+               if (status != AE_NOT_FOUND)
+                       acpi_handle_warn(handle,
+                               "can't evaluate _ADR (%#x)\n", status);
                return AE_OK;
        }
 
@@ -643,6 +645,24 @@ static void disable_slot(struct acpiphp_slot *slot)
        slot->flags &= (~SLOT_ENABLED);
 }
 
+static bool acpiphp_no_hotplug(acpi_handle handle)
+{
+       struct acpi_device *adev = NULL;
+
+       acpi_bus_get_device(handle, &adev);
+       return adev && adev->flags.no_hotplug;
+}
+
+static bool slot_no_hotplug(struct acpiphp_slot *slot)
+{
+       struct acpiphp_func *func;
+
+       list_for_each_entry(func, &slot->funcs, sibling)
+               if (acpiphp_no_hotplug(func_to_handle(func)))
+                       return true;
+
+       return false;
+}
 
 /**
  * get_slot_status - get ACPI slot status
@@ -701,7 +721,8 @@ static void trim_stale_devices(struct pci_dev *dev)
                unsigned long long sta;
 
                status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-               alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL;
+               alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
+                       || acpiphp_no_hotplug(handle);
        }
        if (!alive) {
                u32 v;
@@ -741,8 +762,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
                struct pci_dev *dev, *tmp;
 
                mutex_lock(&slot->crit_sect);
-               /* wake up all functions */
-               if (get_slot_status(slot) == ACPI_STA_ALL) {
+               if (slot_no_hotplug(slot)) {
+                       ; /* do nothing */
+               } else if (get_slot_status(slot) == ACPI_STA_ALL) {
                        /* remove stale devices if any */
                        list_for_each_entry_safe(dev, tmp, &bus->devices,
                                                 bus_list)
index 577074efbe62f93f39ac00c6f5c4963d53bd2b0d..f7ebdba14bde9bc1c7e3dd702bc6e47506067ff5 100644 (file)
@@ -330,29 +330,32 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 static void pci_acpi_setup(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       acpi_handle handle = ACPI_HANDLE(dev);
-       struct acpi_device *adev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
 
-       if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
+       if (!adev)
+               return;
+
+       pci_acpi_add_pm_notifier(adev, pci_dev);
+       if (!adev->wakeup.flags.valid)
                return;
 
        device_set_wakeup_capable(dev, true);
        acpi_pci_sleep_wake(pci_dev, false);
-
-       pci_acpi_add_pm_notifier(adev, pci_dev);
        if (adev->wakeup.flags.run_wake)
                device_set_run_wake(dev, true);
 }
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-       acpi_handle handle = ACPI_HANDLE(dev);
-       struct acpi_device *adev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+
+       if (!adev)
+               return;
 
-       if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) {
+       pci_acpi_remove_pm_notifier(adev);
+       if (adev->wakeup.flags.valid) {
                device_set_wakeup_capable(dev, false);
                device_set_run_wake(dev, false);
-               pci_acpi_remove_pm_notifier(adev);
        }
 }
 
index a344f3d52361f0eed4d2a0d1fdc81a957e3a7967..330ef2d065670eb91b84a6d553bdf1df2dabf79f 100644 (file)
@@ -24,8 +24,8 @@ config PHY_EXYNOS_MIPI_VIDEO
 config OMAP_USB2
        tristate "OMAP USB2 PHY Driver"
        depends on ARCH_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        select OMAP_CONTROL_USB
        help
          Enable this to support the transceiver that is part of SOC. This
@@ -36,8 +36,8 @@ config OMAP_USB2
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
        depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        help
          Enable this to support the USB OTG transceiver on TWL4030
          family chips (including the TWL5030 and TPS659x0 devices).
index 03cf8fb815543537fb14995fde36a5216706dab9..58e0e97390287364287eae1eecdf8b43ba7b72f1 100644 (file)
@@ -437,23 +437,18 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
        int id;
        struct phy *phy;
 
-       if (!dev) {
-               dev_WARN(dev, "no device provided for PHY\n");
-               ret = -EINVAL;
-               goto err0;
-       }
+       if (WARN_ON(!dev))
+               return ERR_PTR(-EINVAL);
 
        phy = kzalloc(sizeof(*phy), GFP_KERNEL);
-       if (!phy) {
-               ret = -ENOMEM;
-               goto err0;
-       }
+       if (!phy)
+               return ERR_PTR(-ENOMEM);
 
        id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL);
        if (id < 0) {
                dev_err(dev, "unable to get id\n");
                ret = id;
-               goto err0;
+               goto free_phy;
        }
 
        device_initialize(&phy->dev);
@@ -468,11 +463,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        ret = device_add(&phy->dev);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        if (pm_runtime_enabled(dev)) {
                pm_runtime_enable(&phy->dev);
@@ -481,12 +476,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        return phy;
 
-err1:
-       ida_remove(&phy_ida, phy->id);
+put_dev:
        put_device(&phy->dev);
+       ida_remove(&phy_ida, phy->id);
+free_phy:
        kfree(phy);
-
-err0:
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(phy_create);
index 11bd0d970a5246a378185e77955e957d7b4e7376..e2142956a8e5fff5bd1363f3e6837e00b1064bff 100644 (file)
@@ -254,7 +254,7 @@ struct sh_pfc_soc_info {
 #define PINMUX_GPIO(_pin)                                              \
        [GPIO_##_pin] = {                                               \
                .pin = (u16)-1,                                         \
-               .name = __stringify(name),                              \
+               .name = __stringify(GPIO_##_pin),                       \
                .enum_id = _pin##_DATA,                                 \
        }
 
index 5e2054afe840e9d6412a28c5250f34d1017aa7b2..85ad58c6da17233a9503650500b69579887c84bb 100644 (file)
@@ -196,6 +196,7 @@ config BATTERY_MAX17040
 config BATTERY_MAX17042
        tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge"
        depends on I2C
+       select REGMAP_I2C
        help
          MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries
          in handheld and portable equipment. The MAX17042 is configured
index 00e6672963601754262ced9e842f31c27e07c69e..557af943b2f53d0a3ee2a280122e42e69db94c67 100644 (file)
@@ -511,6 +511,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        dev_set_drvdata(dev, psy);
        psy->dev = dev;
 
+       rc = dev_set_name(dev, "%s", psy->name);
+       if (rc)
+               goto dev_set_name_failed;
+
        INIT_WORK(&psy->changed_work, power_supply_changed_work);
 
        rc = power_supply_check_supplies(psy);
@@ -524,10 +528,6 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        if (rc)
                goto wakeup_init_failed;
 
-       rc = kobject_set_name(&dev->kobj, "%s", psy->name);
-       if (rc)
-               goto kobject_set_name_failed;
-
        rc = device_add(dev);
        if (rc)
                goto device_add_failed;
@@ -553,11 +553,11 @@ create_triggers_failed:
 register_cooler_failed:
        psy_unregister_thermal(psy);
 register_thermal_failed:
-wakeup_init_failed:
        device_del(dev);
-kobject_set_name_failed:
 device_add_failed:
+wakeup_init_failed:
 check_supplies_failed:
+dev_set_name_failed:
        put_device(dev);
 success:
        return rc;
index 2a786c504460f5be0246c363fab622223ebd990e..3c6768378a94600bc487c61bc9d3fffcbf581750 100644 (file)
@@ -833,6 +833,11 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
        return 0;
 }
 
+static const struct x86_cpu_id energy_unit_quirk_ids[] = {
+       { X86_VENDOR_INTEL, 6, 0x37},/* VLV */
+       {}
+};
+
 static int rapl_check_unit(struct rapl_package *rp, int cpu)
 {
        u64 msr_val;
@@ -853,8 +858,11 @@ static int rapl_check_unit(struct rapl_package *rp, int cpu)
         * time unit: 1/time_unit_divisor Seconds
         */
        value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
-       rp->energy_unit_divisor = 1 << value;
-
+       /* some CPUs have different way to calculate energy unit */
+       if (x86_match_cpu(energy_unit_quirk_ids))
+               rp->energy_unit_divisor = 1000000 / (1 << value);
+       else
+               rp->energy_unit_divisor = 1 << value;
 
        value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
        rp->power_unit_divisor = 1 << value;
@@ -941,6 +949,7 @@ static void package_power_limit_irq_restore(int package_id)
 static const struct x86_cpu_id rapl_ids[] = {
        { X86_VENDOR_INTEL, 6, 0x2a},/* SNB */
        { X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */
+       { X86_VENDOR_INTEL, 6, 0x37},/* VLV */
        { X86_VENDOR_INTEL, 6, 0x3a},/* IVB */
        { X86_VENDOR_INTEL, 6, 0x45},/* HSW */
        /* TODO: Add more CPU IDs after testing */
index 333677d68d0ee31f784e76906bc930b592fc7257..9e61922d82302372c08ab5499b676a4b51363248 100644 (file)
@@ -438,7 +438,7 @@ common_reg:
        platform_set_drvdata(pdev, s2mps11);
 
        config.dev = &pdev->dev;
-       config.regmap = iodev->regmap;
+       config.regmap = iodev->regmap_pmic;
        config.driver_data = s2mps11;
        for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
                if (!reg_np) {
index 3f4ca4e09a4ccc4d49fba39d64094fafe1f1fdc7..34629ea913d4eb3bd77fefee02bd301e946cf5a3 100644 (file)
@@ -942,7 +942,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
                return rc;
        }
 
-       tp->screen = tty3270_alloc_screen(tp->view.cols, tp->view.rows);
+       tp->screen = tty3270_alloc_screen(tp->view.rows, tp->view.cols);
        if (IS_ERR(tp->screen)) {
                rc = PTR_ERR(tp->screen);
                raw3270_put_view(&tp->view);
index 596480022b0a4b88eb7a3d855e472200d5ab4fef..38a1257e76e1ec432c6cc81893b54a27ee30081a 100644 (file)
@@ -471,7 +471,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
                schedule_delayed_work(&tgt->sess_del_work, 0);
        else
                schedule_delayed_work(&tgt->sess_del_work,
-                   jiffies - sess->expires);
+                   sess->expires - jiffies);
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -550,13 +550,14 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
        struct scsi_qla_host *vha = tgt->vha;
        struct qla_hw_data *ha = vha->hw;
        struct qla_tgt_sess *sess;
-       unsigned long flags;
+       unsigned long flags, elapsed;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
        while (!list_empty(&tgt->del_sess_list)) {
                sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
                    del_list_entry);
-               if (time_after_eq(jiffies, sess->expires)) {
+               elapsed = jiffies;
+               if (time_after_eq(elapsed, sess->expires)) {
                        qlt_undelete_sess(sess);
 
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
@@ -566,7 +567,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
                        ha->tgt.tgt_ops->put_sess(sess);
                } else {
                        schedule_delayed_work(&tgt->sess_del_work,
-                           jiffies - sess->expires);
+                           sess->expires - elapsed);
                        break;
                }
        }
@@ -4290,6 +4291,7 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn,
                if (rc != 0) {
                        ha->tgt.tgt_ops = NULL;
                        ha->tgt.target_lport_ptr = NULL;
+                       scsi_host_put(host);
                }
                mutex_unlock(&qla_tgt_mutex);
                return rc;
index 53fee2f9a498866c6a19d3d6c3ca1d078fd7206e..8dfdd2732bdc329b3865c010d0afdb8e1e248337 100644 (file)
@@ -39,7 +39,8 @@ static INT bcm_close(struct net_device *dev)
        return 0;
 }
 
-static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        return ClassifyPacket(netdev_priv(dev), skb);
 }
index 8f02bf66e20b2002b3b52655919a89f95c0fcad9..4964d2a2fc7d54ba099541b3f9c2c61be4799936 100644 (file)
@@ -446,7 +446,7 @@ int comedi_load_firmware(struct comedi_device *dev,
                release_firmware(fw);
        }
 
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 EXPORT_SYMBOL_GPL(comedi_load_firmware);
 
index 432e3f9c3301ecc7ce6f6d633913bf1e1e85f4e4..c55f234b29e6052e541dc7b7043d0a877682b4cb 100644 (file)
@@ -63,7 +63,8 @@ enum pci_8255_boardid {
        BOARD_ADLINK_PCI7296,
        BOARD_CB_PCIDIO24,
        BOARD_CB_PCIDIO24H,
-       BOARD_CB_PCIDIO48H,
+       BOARD_CB_PCIDIO48H_OLD,
+       BOARD_CB_PCIDIO48H_NEW,
        BOARD_CB_PCIDIO96H,
        BOARD_NI_PCIDIO96,
        BOARD_NI_PCIDIO96B,
@@ -106,11 +107,16 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = {
                .dio_badr       = 2,
                .n_8255         = 1,
        },
-       [BOARD_CB_PCIDIO48H] = {
+       [BOARD_CB_PCIDIO48H_OLD] = {
                .name           = "cb_pci-dio48h",
                .dio_badr       = 1,
                .n_8255         = 2,
        },
+       [BOARD_CB_PCIDIO48H_NEW] = {
+               .name           = "cb_pci-dio48h",
+               .dio_badr       = 2,
+               .n_8255         = 2,
+       },
        [BOARD_CB_PCIDIO96H] = {
                .name           = "cb_pci-dio96h",
                .dio_badr       = 2,
@@ -263,7 +269,10 @@ static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = {
        { PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 },
        { PCI_VDEVICE(CB, 0x0028), BOARD_CB_PCIDIO24 },
        { PCI_VDEVICE(CB, 0x0014), BOARD_CB_PCIDIO24H },
-       { PCI_VDEVICE(CB, 0x000b), BOARD_CB_PCIDIO48H },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, 0x0000, 0x0000),
+         .driver_data = BOARD_CB_PCIDIO48H_OLD },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, PCI_VENDOR_ID_CB, 0x000b),
+         .driver_data = BOARD_CB_PCIDIO48H_NEW },
        { PCI_VDEVICE(CB, 0x0017), BOARD_CB_PCIDIO96H },
        { PCI_VDEVICE(NI, 0x0160), BOARD_NI_PCIDIO96 },
        { PCI_VDEVICE(NI, 0x1630), BOARD_NI_PCIDIO96B },
index 99421f90d1895f6a0691d4443c457f5aac2335db..0485d7f398672a61045367b7ac85a267b34b6e8d 100644 (file)
@@ -451,7 +451,12 @@ done:
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
                        BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
                .scan_index = idx,                                      \
-               .scan_type = IIO_ST('s', 16, 16, IIO_BE),               \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 16,                                 \
+                       .storagebits = 16,                              \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
        }
 
 static const struct iio_chan_spec hmc5843_channels[] = {
index 6bd015ac9d683474a034924f8ffec3e752e1d382..09ef5fb8bae6f9cb4b99f936b2fcb52739f9edd9 100644 (file)
@@ -88,8 +88,9 @@ static int imx_drm_driver_unload(struct drm_device *drm)
 
        imx_drm_device_put();
 
-       drm_mode_config_cleanup(imxdrm->drm);
+       drm_vblank_cleanup(imxdrm->drm);
        drm_kms_helper_poll_fini(imxdrm->drm);
+       drm_mode_config_cleanup(imxdrm->drm);
 
        return 0;
 }
@@ -199,8 +200,8 @@ static void imx_drm_driver_preclose(struct drm_device *drm,
        if (!file->is_master)
                return;
 
-       for (i = 0; i < 4; i++)
-               imx_drm_disable_vblank(drm , i);
+       for (i = 0; i < MAX_CRTC; i++)
+               imx_drm_disable_vblank(drm, i);
 }
 
 static const struct file_operations imx_drm_driver_fops = {
@@ -376,8 +377,6 @@ static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
        struct imx_drm_device *imxdrm = __imx_drm_device();
        int ret;
 
-       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc,
-                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
        ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
        if (ret)
                return ret;
@@ -385,6 +384,9 @@ static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
        drm_crtc_helper_add(imx_drm_crtc->crtc,
                        imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
 
+       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc,
+                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
+
        drm_mode_group_reinit(imxdrm->drm);
 
        return 0;
@@ -428,11 +430,11 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
        ret = drm_mode_group_init_legacy_group(imxdrm->drm,
                        &imxdrm->drm->primary->mode_group);
        if (ret)
-               goto err_init;
+               goto err_kms;
 
        ret = drm_vblank_init(imxdrm->drm, MAX_CRTC);
        if (ret)
-               goto err_init;
+               goto err_kms;
 
        /*
         * with vblank_disable_allowed = true, vblank interrupt will be disabled
@@ -441,12 +443,20 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
         */
        imxdrm->drm->vblank_disable_allowed = true;
 
-       if (!imx_drm_device_get())
+       if (!imx_drm_device_get()) {
                ret = -EINVAL;
+               goto err_vblank;
+       }
 
-       ret = 0;
+       platform_set_drvdata(drm->platformdev, drm);
+       mutex_unlock(&imxdrm->mutex);
+       return 0;
 
-err_init:
+err_vblank:
+       drm_vblank_cleanup(drm);
+err_kms:
+       drm_kms_helper_poll_fini(drm);
+       drm_mode_config_cleanup(drm);
        mutex_unlock(&imxdrm->mutex);
 
        return ret;
@@ -492,6 +502,15 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
 
        mutex_lock(&imxdrm->mutex);
 
+       /*
+        * The vblank arrays are dimensioned by MAX_CRTC - we can't
+        * pass IDs greater than this to those functions.
+        */
+       if (imxdrm->pipes >= MAX_CRTC) {
+               ret = -EINVAL;
+               goto err_busy;
+       }
+
        if (imxdrm->drm->open_count) {
                ret = -EBUSY;
                goto err_busy;
@@ -528,6 +547,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
        return 0;
 
 err_register:
+       list_del(&imx_drm_crtc->list);
        kfree(imx_drm_crtc);
 err_alloc:
 err_busy:
@@ -829,7 +849,7 @@ static int imx_drm_platform_probe(struct platform_device *pdev)
 
 static int imx_drm_platform_remove(struct platform_device *pdev)
 {
-       drm_platform_exit(&imx_drm_driver, pdev);
+       drm_put_dev(platform_get_drvdata(pdev));
 
        return 0;
 }
index 680f4c8fa0815481a410621eb616879dbb149109..2c44fef8d58b327df92e97667f0661c45e3e57d6 100644 (file)
@@ -114,7 +114,6 @@ struct imx_tve {
        struct drm_encoder encoder;
        struct imx_drm_encoder *imx_drm_encoder;
        struct device *dev;
-       spinlock_t enable_lock; /* serializes tve_enable/disable */
        spinlock_t lock;        /* register lock */
        bool enabled;
        int mode;
@@ -146,10 +145,8 @@ __releases(&tve->lock)
 
 static void tve_enable(struct imx_tve *tve)
 {
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&tve->enable_lock, flags);
        if (!tve->enabled) {
                tve->enabled = true;
                clk_prepare_enable(tve->clk);
@@ -169,23 +166,18 @@ static void tve_enable(struct imx_tve *tve)
                             TVE_CD_SM_IEN |
                             TVE_CD_LM_IEN |
                             TVE_CD_MON_END_IEN);
-
-       spin_unlock_irqrestore(&tve->enable_lock, flags);
 }
 
 static void tve_disable(struct imx_tve *tve)
 {
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&tve->enable_lock, flags);
        if (tve->enabled) {
                tve->enabled = false;
                ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
                                         TVE_IPU_CLK_EN | TVE_EN, 0);
                clk_disable_unprepare(tve->clk);
        }
-       spin_unlock_irqrestore(&tve->enable_lock, flags);
 }
 
 static int tve_setup_tvout(struct imx_tve *tve)
@@ -601,7 +593,6 @@ static int imx_tve_probe(struct platform_device *pdev)
 
        tve->dev = &pdev->dev;
        spin_lock_init(&tve->lock);
-       spin_lock_init(&tve->enable_lock);
 
        ddc_node = of_parse_phandle(np, "ddc", 0);
        if (ddc_node) {
index 7a22ce619ed264ba536de785650700b02f6d3ef3..97ca6924dbb3fce7b5db813aefb781adb273187a 100644 (file)
@@ -996,35 +996,35 @@ static const struct ipu_platform_reg client_reg[] = {
        },
 };
 
+static DEFINE_MUTEX(ipu_client_id_mutex);
 static int ipu_client_id;
 
-static int ipu_add_subdevice_pdata(struct device *dev,
-               const struct ipu_platform_reg *reg)
-{
-       struct platform_device *pdev;
-
-       pdev = platform_device_register_data(dev, reg->name, ipu_client_id++,
-                       &reg->pdata, sizeof(struct ipu_platform_reg));
-
-       return PTR_ERR_OR_ZERO(pdev);
-}
-
 static int ipu_add_client_devices(struct ipu_soc *ipu)
 {
-       int ret;
-       int i;
+       struct device *dev = ipu->dev;
+       unsigned i;
+       int id, ret;
+
+       mutex_lock(&ipu_client_id_mutex);
+       id = ipu_client_id;
+       ipu_client_id += ARRAY_SIZE(client_reg);
+       mutex_unlock(&ipu_client_id_mutex);
 
        for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
                const struct ipu_platform_reg *reg = &client_reg[i];
-               ret = ipu_add_subdevice_pdata(ipu->dev, reg);
-               if (ret)
+               struct platform_device *pdev;
+
+               pdev = platform_device_register_data(dev, reg->name,
+                       id++, &reg->pdata, sizeof(reg->pdata));
+
+               if (IS_ERR(pdev))
                        goto err_register;
        }
 
        return 0;
 
 err_register:
-       platform_device_unregister_children(to_platform_device(ipu->dev));
+       platform_device_unregister_children(to_platform_device(dev));
 
        return ret;
 }
index 235d2b1ec593c4dfba7a83c4eb5fd0f578e0c5c4..eedffed17e391d3243443c443ff9338bf494c440 100644 (file)
@@ -306,7 +306,8 @@ static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb,
        return NETDEV_TX_OK;
 }
 
-static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb)
+static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb,
+                               void *accel_priv)
 {
        return (u16)smp_processor_id();
 }
index 17659bb04befc24fabded5439be74aba9fdcb5d1..dd69e344e4099c852ffd0bd5ef11ef859a0e274c 100644 (file)
@@ -652,7 +652,8 @@ static unsigned int rtw_classify8021d(struct sk_buff *skb)
        return dscp >> 5;
 }
 
-static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        struct adapter  *padapter = rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
index d70e9119e906cba0c0f38da61948ce745bc5d6e5..00867190413c78d1f3226348e5c68718077c0b9f 100644 (file)
@@ -465,6 +465,7 @@ int iscsit_del_np(struct iscsi_np *np)
                 */
                send_sig(SIGINT, np->np_thread, 1);
                kthread_stop(np->np_thread);
+               np->np_thread = NULL;
        }
 
        np->np_transport->iscsit_free_np(np);
@@ -823,24 +824,22 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
             (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
                /*
-                * Vmware ESX v3.0 uses a modified Cisco Initiator (v3.4.2)
-                * that adds support for RESERVE/RELEASE.  There is a bug
-                * add with this new functionality that sets R/W bits when
-                * neither CDB carries any READ or WRITE datapayloads.
+                * From RFC-3720 Section 10.3.1:
+                *
+                * "Either or both of R and W MAY be 1 when either the
+                *  Expected Data Transfer Length and/or Bidirectional Read
+                *  Expected Data Transfer Length are 0"
+                *
+                * For this case, go ahead and clear the unnecssary bits
+                * to avoid any confusion with ->data_direction.
                 */
-               if ((hdr->cdb[0] == 0x16) || (hdr->cdb[0] == 0x17)) {
-                       hdr->flags &= ~ISCSI_FLAG_CMD_READ;
-                       hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
-                       goto done;
-               }
+               hdr->flags &= ~ISCSI_FLAG_CMD_READ;
+               hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
 
-               pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
+               pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
                        " set when Expected Data Transfer Length is 0 for"
-                       " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]);
-               return iscsit_add_reject_cmd(cmd,
-                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
+                       " CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]);
        }
-done:
 
        if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
            !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
index e3318edb233dbe91b8e35f9fe1a7fff58508fb6b..1c0088fe9e99368c2dfb50b378dee6033cd42cab 100644 (file)
@@ -474,7 +474,8 @@ static ssize_t __iscsi_##prefix##_store_##name(                             \
                                                                        \
        if (!capable(CAP_SYS_ADMIN))                                    \
                return -EPERM;                                          \
-                                                                       \
+       if (count >= sizeof(auth->name))                                \
+               return -EINVAL;                                         \
        snprintf(auth->name, sizeof(auth->name), "%s", page);           \
        if (!strncmp("NULL", auth->name, 4))                            \
                auth->naf_flags &= ~flags;                              \
index 4eb93b2b6473bcce92f912908a0790485db15e85..e29279e6b577dd564e8271f95c171838ead5ca39 100644 (file)
@@ -1403,11 +1403,6 @@ old_sess_out:
 
 out:
        stop = kthread_should_stop();
-       if (!stop && signal_pending(current)) {
-               spin_lock_bh(&np->np_thread_lock);
-               stop = (np->np_thread_state == ISCSI_NP_THREAD_SHUTDOWN);
-               spin_unlock_bh(&np->np_thread_lock);
-       }
        /* Wait for another socket.. */
        if (!stop)
                return 1;
@@ -1415,7 +1410,6 @@ exit:
        iscsi_stop_login_thread_timer(np);
        spin_lock_bh(&np->np_thread_lock);
        np->np_thread_state = ISCSI_NP_THREAD_EXIT;
-       np->np_thread = NULL;
        spin_unlock_bh(&np->np_thread_lock);
 
        return 0;
index 207b340498a3645231dbb2ae449e48f052e3313f..d06de84b069bb0c283495bdf09da4b3e9b96ba2f 100644 (file)
@@ -1106,6 +1106,11 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size)
        dev->dev_attrib.block_size = block_size;
        pr_debug("dev[%p]: SE Device block_size changed to %u\n",
                        dev, block_size);
+
+       if (dev->dev_attrib.max_bytes_per_io)
+               dev->dev_attrib.hw_max_sectors =
+                       dev->dev_attrib.max_bytes_per_io / block_size;
+
        return 0;
 }
 
index 0e34cda3271e9bb3291b06a934c1ef7136488811..78241a53b555fc5600d0a6ffe7b8d8b4e15687d0 100644 (file)
@@ -66,9 +66,8 @@ static int fd_attach_hba(struct se_hba *hba, u32 host_id)
        pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"
                " Target Core Stack %s\n", hba->hba_id, FD_VERSION,
                TARGET_CORE_MOD_VERSION);
-       pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic"
-               " MaxSectors: %u\n",
-               hba->hba_id, fd_host->fd_host_id, FD_MAX_SECTORS);
+       pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic\n",
+               hba->hba_id, fd_host->fd_host_id);
 
        return 0;
 }
@@ -220,7 +219,8 @@ static int fd_configure_device(struct se_device *dev)
        }
 
        dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;
-       dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
+       dev->dev_attrib.max_bytes_per_io = FD_MAX_BYTES;
+       dev->dev_attrib.hw_max_sectors = FD_MAX_BYTES / fd_dev->fd_block_size;
        dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
 
        if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
index 37ffc5bd23992a5f1e1124b2c6eba9889e7119ff..d7772c167685fecc89caf699884198b9a9d9f999 100644 (file)
@@ -7,7 +7,10 @@
 #define FD_DEVICE_QUEUE_DEPTH  32
 #define FD_MAX_DEVICE_QUEUE_DEPTH 128
 #define FD_BLOCKSIZE           512
-#define FD_MAX_SECTORS         2048
+/*
+ * Limited by the number of iovecs (2048) per vfs_[writev,readv] call
+ */
+#define FD_MAX_BYTES           8388608
 
 #define RRF_EMULATE_CDB                0x01
 #define RRF_GOT_LBA            0x02
index f697f8baec5418d13484904bf3730880f90639fd..2a573de19a9fdceea07d233f15a699be6c10c770 100644 (file)
@@ -278,7 +278,6 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
        acl->se_tpg = tpg;
        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
-       spin_lock_init(&acl->stats_lock);
        acl->dynamic_node_acl = 1;
 
        tpg->se_tpg_tfo->set_default_node_attributes(acl);
@@ -406,7 +405,6 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
        acl->se_tpg = tpg;
        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
-       spin_lock_init(&acl->stats_lock);
 
        tpg->se_tpg_tfo->set_default_node_attributes(acl);
 
@@ -658,15 +656,9 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
        spin_lock_init(&lun->lun_sep_lock);
        init_completion(&lun->lun_ref_comp);
 
-       ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release);
-       if (ret < 0)
-               return ret;
-
        ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev);
-       if (ret < 0) {
-               percpu_ref_cancel_init(&lun->lun_ref);
+       if (ret < 0)
                return ret;
-       }
 
        return 0;
 }
index 268b62768f2b41eab5f7db4d4c5c8b9111f248b6..34aacaaae14ab9b595ea41744504c2cbc65b9ff3 100644 (file)
@@ -93,6 +93,7 @@ struct n_tty_data {
        size_t canon_head;
        size_t echo_head;
        size_t echo_commit;
+       size_t echo_mark;
        DECLARE_BITMAP(char_map, 256);
 
        /* private to n_tty_receive_overrun (single-threaded) */
@@ -336,6 +337,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
 {
        ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
        ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
+       ldata->echo_mark = 0;
        ldata->line_start = 0;
 
        ldata->erasing = 0;
@@ -787,6 +789,7 @@ static void commit_echoes(struct tty_struct *tty)
        size_t head;
 
        head = ldata->echo_head;
+       ldata->echo_mark = head;
        old = ldata->echo_commit - ldata->echo_tail;
 
        /* Process committed echoes if the accumulated # of bytes
@@ -811,10 +814,11 @@ static void process_echoes(struct tty_struct *tty)
        size_t echoed;
 
        if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
-           ldata->echo_commit == ldata->echo_tail)
+           ldata->echo_mark == ldata->echo_tail)
                return;
 
        mutex_lock(&ldata->output_lock);
+       ldata->echo_commit = ldata->echo_mark;
        echoed = __process_echoes(tty);
        mutex_unlock(&ldata->output_lock);
 
@@ -822,6 +826,7 @@ static void process_echoes(struct tty_struct *tty)
                tty->ops->flush_chars(tty);
 }
 
+/* NB: echo_mark and echo_head should be equivalent here */
 static void flush_echoes(struct tty_struct *tty)
 {
        struct n_tty_data *ldata = tty->disc_data;
index 4658e3e0ec4256d9b2e31f890ea72822abf47f93..06525f10e3641bc2140b140a50d8b994acd662d3 100644 (file)
@@ -96,7 +96,8 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR) {
                int tries = 1000;
                while (tries--) {
-                       if (value == p->serial_in(p, UART_LCR))
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
                                return;
                        dw8250_force_idle(p);
                        writeb(value, p->membase + (UART_LCR << p->regshift));
@@ -132,7 +133,8 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR) {
                int tries = 1000;
                while (tries--) {
-                       if (value == p->serial_in(p, UART_LCR))
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
                                return;
                        dw8250_force_idle(p);
                        writel(value, p->membase + (UART_LCR << p->regshift));
@@ -455,6 +457,8 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
 static const struct acpi_device_id dw8250_acpi_match[] = {
        { "INT33C4", 0 },
        { "INT33C5", 0 },
+       { "INT3434", 0 },
+       { "INT3435", 0 },
        { "80860F0A", 0 },
        { },
 };
index e46e9f3f19b90d34476b60a2e21aa656fc3c8fae..f619ad5b5eaefc891b6857c03edd942492198e18 100644 (file)
@@ -240,6 +240,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
                                        continue;
                        }
 
+#ifdef SUPPORT_SYSRQ
                        /*
                         * uart_handle_sysrq_char() doesn't work if
                         * spinlocked, for some reason
@@ -253,6 +254,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
                                }
                                spin_lock(&port->lock);
                        }
+#endif
 
                        port->icount.rx++;
 
index 22fad8ad5ac206c4cf22f820e9a4cf5c3f6cd8bd..d8a55e87877f06f3141602e4f08cdcb668c465b0 100644 (file)
@@ -86,11 +86,21 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem)
        return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
 }
 
+/*
+ * ldsem_cmpxchg() updates @*old with the last-known sem->count value.
+ * Returns 1 if count was successfully changed; @*old will have @new value.
+ * Returns 0 if count was not changed; @*old will have most recent sem->count
+ */
 static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem)
 {
-       long tmp = *old;
-       *old = atomic_long_cmpxchg(&sem->count, *old, new);
-       return *old == tmp;
+       long tmp = atomic_long_cmpxchg(&sem->count, *old, new);
+       if (tmp == *old) {
+               *old = new;
+               return 1;
+       } else {
+               *old = tmp;
+               return 0;
+       }
 }
 
 /*
index 5d8981c5235e50e42776cfb9f672977c11a61ef0..6e73f8cd60e513ca44de8d6bd00fe69085e4453f 100644 (file)
@@ -642,6 +642,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                        : CI_ROLE_GADGET;
        }
 
+       /* only update vbus status for peripheral */
+       if (ci->role == CI_ROLE_GADGET)
+               ci_handle_vbus_change(ci);
+
        ret = ci_role_start(ci, ci->role);
        if (ret) {
                dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
index 59e6020ea7539e5e331364ac067c9a16f27855ba..526cd77563d8a89c29f5444901ee3ba366b1575a 100644 (file)
@@ -88,7 +88,8 @@ static int host_start(struct ci_hdrc *ci)
        return ret;
 
 disable_reg:
-       regulator_disable(ci->platdata->reg_vbus);
+       if (ci->platdata->reg_vbus)
+               regulator_disable(ci->platdata->reg_vbus);
 
 put_hcd:
        usb_put_hcd(hcd);
index b34c81969cba672a7e880f405f2445adf36b7e6f..69d20fbb38a26a32357cc9f5d7fc4f81efa08cca 100644 (file)
@@ -1795,9 +1795,6 @@ static int udc_start(struct ci_hdrc *ci)
        pm_runtime_no_callbacks(&ci->gadget.dev);
        pm_runtime_enable(&ci->gadget.dev);
 
-       /* Update ci->vbus_active */
-       ci_handle_vbus_change(ci);
-
        return retval;
 
 destroy_eps:
index 4d387596f3f0a6e531caa1a9049a383d605091b4..0b23a8639311b182ee9e2afddcec1cb888269257 100644 (file)
@@ -854,13 +854,11 @@ static int wdm_manage_power(struct usb_interface *intf, int on)
 {
        /* need autopm_get/put here to ensure the usbcore sees the new value */
        int rv = usb_autopm_get_interface(intf);
-       if (rv < 0)
-               goto err;
 
        intf->needs_remote_wakeup = on;
-       usb_autopm_put_interface(intf);
-err:
-       return rv;
+       if (!rv)
+               usb_autopm_put_interface(intf);
+       return 0;
 }
 
 static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
index 74f9cf02da070a6d1c23b643a56f76e3264fb8cd..a49217ae35333846bb76912666f0efa12bca6813 100644 (file)
@@ -455,9 +455,6 @@ static int dwc3_probe(struct platform_device *pdev)
        if (IS_ERR(regs))
                return PTR_ERR(regs);
 
-       usb_phy_set_suspend(dwc->usb2_phy, 0);
-       usb_phy_set_suspend(dwc->usb3_phy, 0);
-
        spin_lock_init(&dwc->lock);
        platform_set_drvdata(pdev, dwc);
 
@@ -488,6 +485,9 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err0;
        }
 
+       usb_phy_set_suspend(dwc->usb2_phy, 0);
+       usb_phy_set_suspend(dwc->usb3_phy, 0);
+
        ret = dwc3_event_buffers_setup(dwc);
        if (ret) {
                dev_err(dwc->dev, "failed to setup event buffers\n");
@@ -569,6 +569,8 @@ err2:
        dwc3_event_buffers_cleanup(dwc);
 
 err1:
+       usb_phy_set_suspend(dwc->usb2_phy, 1);
+       usb_phy_set_suspend(dwc->usb3_phy, 1);
        dwc3_core_exit(dwc);
 
 err0:
index 418444ebb1b8bb1fd1862fc9233c7562c5c40d81..8c356af79409f9ef4647d141bc6aa5146791496b 100644 (file)
@@ -136,23 +136,27 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        struct ohci_hcd *ohci;
        int retval;
        struct usb_hcd *hcd = NULL;
-
-       if (pdev->num_resources != 2) {
-               pr_debug("hcd probe: invalid num_resources");
-               return -ENODEV;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int irq;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_dbg(dev, "hcd probe: missing memory resource\n");
+               return -ENXIO;
        }
 
-       if ((pdev->resource[0].flags != IORESOURCE_MEM)
-                       || (pdev->resource[1].flags != IORESOURCE_IRQ)) {
-               pr_debug("hcd probe: invalid resource type\n");
-               return -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_dbg(dev, "hcd probe: missing irq resource\n");
+               return irq;
        }
 
        hcd = usb_create_hcd(driver, &pdev->dev, "at91");
        if (!hcd)
                return -ENOMEM;
-       hcd->rsrc_start = pdev->resource[0].start;
-       hcd->rsrc_len = resource_size(&pdev->resource[0]);
+       hcd->rsrc_start = res->start;
+       hcd->rsrc_len = resource_size(res);
 
        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
                pr_debug("request_mem_region failed\n");
@@ -199,7 +203,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        ohci->num_ports = board->ports;
        at91_start_hc(pdev);
 
-       retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (retval == 0)
                return retval;
 
index b8dffd59eb256e52786328e5e4f1919846a80d9c..73f5208714a4a4d8270bd85acd1ec625fb9abf71 100644 (file)
@@ -128,7 +128,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 * any other sleep) on Haswell machines with LPT and LPT-LP
                 * with the new Intel BIOS
                 */
-               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+               /* Limit the quirk to only known vendors, as this triggers
+                * yet another BIOS bug on some other machines
+                * https://bugzilla.kernel.org/show_bug.cgi?id=66171
+                */
+               if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)
+                       xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
index 08e2f39027ec00ae0a7c5ae07b46fdd1cdbfae8f..2b41c636a52a7a1ecf3ae0e3df622d141307c038 100644 (file)
@@ -19,8 +19,9 @@ config AB8500_USB
          in host mode, low speed.
 
 config FSL_USB2_OTG
-       bool "Freescale USB OTG Transceiver Driver"
+       tristate "Freescale USB OTG Transceiver Driver"
        depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
+       depends on USB
        select USB_OTG
        select USB_PHY
        help
@@ -29,6 +30,7 @@ config FSL_USB2_OTG
 config ISP1301_OMAP
        tristate "Philips ISP1301 with OMAP OTG"
        depends on I2C && ARCH_OMAP_OTG
+       depends on USB
        select USB_PHY
        help
          If you say yes here you get support for the Philips ISP1301
index 82232acf1ab61b17cfbe9d084c3ed2188d554b18..bbe4f8e6e8d7492be10cc54cfe2f37e8001f2db6 100644 (file)
@@ -876,7 +876,7 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
 
        tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
                resource_size(res));
-       if (!tegra_phy->regs) {
+       if (!tegra_phy->pad_regs) {
                dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
                return -ENOMEM;
        }
index 30e8a61552d4d0526d999c0b49651593f04a5530..bad57ce77ba508e0f6ff8c07fa516e9477606a3c 100644 (file)
@@ -127,7 +127,8 @@ static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
 
 static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
 {
-       u8 data, ret = 0;
+       u8 data;
+       int ret;
 
        ret = twl_i2c_read_u8(module, &data, address);
        if (ret >= 0)
index 496b7e39d5bee4d64ac91b7e0187cd1771fd565a..cc7a24154490b29ebb39d4b9d3e72785c4320285 100644 (file)
@@ -251,6 +251,7 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
 #define ZTE_PRODUCT_MC2718                     0xffe8
+#define ZTE_PRODUCT_AC2726                     0xfff1
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -1453,6 +1454,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
index fca4c752a4ed233199d82a787c0ebfbfff32e71c..eae2c873b39ff7dbb2ecd8d7624a1e2aec14e8ca 100644 (file)
@@ -281,8 +281,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x19d2, 0xfffd) },
        { USB_DEVICE(0x19d2, 0xfffc) },
        { USB_DEVICE(0x19d2, 0xfffb) },
-       /* AC2726, AC8710_V3 */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfff1, 0xff, 0xff, 0xff) },
+       /* AC8710_V3 */
        { USB_DEVICE(0x19d2, 0xfff6) },
        { USB_DEVICE(0x19d2, 0xfff7) },
        { USB_DEVICE(0x19d2, 0xfff8) },
index 010d19105ebc4b9651eaf7c53bfd40a90bf36322..e296967a3abb69880e8afa97e31dc55a08a599ad 100644 (file)
@@ -1577,10 +1577,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena,
 static int do_unregister_framebuffer(struct fb_info *fb_info);
 
 #define VGA_FB_PHYS 0xA0000
-static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
-                                    const char *name, bool primary)
+static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
+                                             const char *name, bool primary)
 {
-       int i;
+       int i, ret;
 
        /* check all firmware fbs and kick off if the base addr overlaps */
        for (i = 0 ; i < FB_MAX; i++) {
@@ -1599,22 +1599,29 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
                        printk(KERN_INFO "fb: conflicting fb hw usage "
                               "%s vs %s - removing generic driver\n",
                               name, registered_fb[i]->fix.id);
-                       do_unregister_framebuffer(registered_fb[i]);
+                       ret = do_unregister_framebuffer(registered_fb[i]);
+                       if (ret)
+                               return ret;
                }
        }
+
+       return 0;
 }
 
 static int do_register_framebuffer(struct fb_info *fb_info)
 {
-       int i;
+       int i, ret;
        struct fb_event event;
        struct fb_videomode mode;
 
        if (fb_check_foreignness(fb_info))
                return -ENOSYS;
 
-       do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
-                                        fb_is_primary_device(fb_info));
+       ret = do_remove_conflicting_framebuffers(fb_info->apertures,
+                                                fb_info->fix.id,
+                                                fb_is_primary_device(fb_info));
+       if (ret)
+               return ret;
 
        if (num_registered_fb == FB_MAX)
                return -ENXIO;
@@ -1739,12 +1746,16 @@ int unlink_framebuffer(struct fb_info *fb_info)
 }
 EXPORT_SYMBOL(unlink_framebuffer);
 
-void remove_conflicting_framebuffers(struct apertures_struct *a,
-                                    const char *name, bool primary)
+int remove_conflicting_framebuffers(struct apertures_struct *a,
+                                   const char *name, bool primary)
 {
+       int ret;
+
        mutex_lock(&registration_lock);
-       do_remove_conflicting_framebuffers(a, name, primary);
+       ret = do_remove_conflicting_framebuffers(a, name, primary);
        mutex_unlock(&registration_lock);
+
+       return ret;
 }
 EXPORT_SYMBOL(remove_conflicting_framebuffers);
 
index 4ec59ca72e5d0392518b2437483cea24533a2355..91c687fd002e5447d466b6e8e75f9c0c03dac32c 100644 (file)
@@ -3691,7 +3691,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
        }
 
        pm_runtime_enable(&pdev->dev);
-       pm_runtime_irq_safe(&pdev->dev);
 
        r = dispc_runtime_get();
        if (r)
index c444654fc33fb6f7e858824eb8ed816186bf3bda..5c4a95b516cf9e576884c8f84e566f03b396facb 100644 (file)
@@ -285,7 +285,7 @@ static void update_balloon_size(struct virtio_balloon *vb)
 {
        __le32 actual = cpu_to_le32(vb->num_pages);
 
-       virtio_cwrite(vb->vdev, struct virtio_balloon_config, num_pages,
+       virtio_cwrite(vb->vdev, struct virtio_balloon_config, actual,
                      &actual);
 }
 
index 55ea73f7c70b52e49ca3b4f2b40f5baa064928e9..4c02e2b9410377d9e6b77fe1bc2b50d929774551 100644 (file)
@@ -350,17 +350,19 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 
                pfn = page_to_pfn(page);
 
-               set_phys_to_machine(pfn, frame_list[i]);
-
 #ifdef CONFIG_XEN_HAVE_PVMMU
-               /* Link back into the page tables if not highmem. */
-               if (xen_pv_domain() && !PageHighMem(page)) {
-                       int ret;
-                       ret = HYPERVISOR_update_va_mapping(
-                               (unsigned long)__va(pfn << PAGE_SHIFT),
-                               mfn_pte(frame_list[i], PAGE_KERNEL),
-                               0);
-                       BUG_ON(ret);
+               if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+                       set_phys_to_machine(pfn, frame_list[i]);
+
+                       /* Link back into the page tables if not highmem. */
+                       if (!PageHighMem(page)) {
+                               int ret;
+                               ret = HYPERVISOR_update_va_mapping(
+                                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                                               mfn_pte(frame_list[i], PAGE_KERNEL),
+                                               0);
+                               BUG_ON(ret);
+                       }
                }
 #endif
 
@@ -378,7 +380,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
        enum bp_state state = BP_DONE;
        unsigned long  pfn, i;
        struct page   *page;
-       struct page   *scratch_page;
        int ret;
        struct xen_memory_reservation reservation = {
                .address_bits = 0,
@@ -411,27 +412,29 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
                scrub_page(page);
 
+#ifdef CONFIG_XEN_HAVE_PVMMU
                /*
                 * Ballooned out frames are effectively replaced with
                 * a scratch frame.  Ensure direct mappings and the
                 * p2m are consistent.
                 */
-               scratch_page = get_balloon_scratch_page();
-#ifdef CONFIG_XEN_HAVE_PVMMU
-               if (xen_pv_domain() && !PageHighMem(page)) {
-                       ret = HYPERVISOR_update_va_mapping(
-                               (unsigned long)__va(pfn << PAGE_SHIFT),
-                               pfn_pte(page_to_pfn(scratch_page),
-                                       PAGE_KERNEL_RO), 0);
-                       BUG_ON(ret);
-               }
-#endif
                if (!xen_feature(XENFEAT_auto_translated_physmap)) {
                        unsigned long p;
+                       struct page   *scratch_page = get_balloon_scratch_page();
+
+                       if (!PageHighMem(page)) {
+                               ret = HYPERVISOR_update_va_mapping(
+                                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                                               pfn_pte(page_to_pfn(scratch_page),
+                                                       PAGE_KERNEL_RO), 0);
+                               BUG_ON(ret);
+                       }
                        p = page_to_pfn(scratch_page);
                        __set_phys_to_machine(pfn, pfn_to_mfn(p));
+
+                       put_balloon_scratch_page();
                }
-               put_balloon_scratch_page();
+#endif
 
                balloon_append(pfn_to_page(pfn));
        }
@@ -627,15 +630,17 @@ static int __init balloon_init(void)
        if (!xen_domain())
                return -ENODEV;
 
-       for_each_online_cpu(cpu)
-       {
-               per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL);
-               if (per_cpu(balloon_scratch_page, cpu) == NULL) {
-                       pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu);
-                       return -ENOMEM;
+       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+               for_each_online_cpu(cpu)
+               {
+                       per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL);
+                       if (per_cpu(balloon_scratch_page, cpu) == NULL) {
+                               pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu);
+                               return -ENOMEM;
+                       }
                }
+               register_cpu_notifier(&balloon_cpu_notifier);
        }
-       register_cpu_notifier(&balloon_cpu_notifier);
 
        pr_info("Initialising balloon driver\n");
 
index 028387192b608b04a9fd9483a9916404cb861f76..aa846a48f4009eaac8271a8a653716c27aa1dc01 100644 (file)
@@ -1176,7 +1176,8 @@ static int gnttab_setup(void)
                gnttab_shared.addr = xen_remap(xen_hvm_resume_frames,
                                                PAGE_SIZE * max_nr_gframes);
                if (gnttab_shared.addr == NULL) {
-                       pr_warn("Failed to ioremap gnttab share frames!\n");
+                       pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n",
+                                       xen_hvm_resume_frames);
                        return -ENOMEM;
                }
        }
index 8e74590fa1bb5d9149e17550c3f4ec7b74142983..569a13b9e856de5c3900050d583844f401243e96 100644 (file)
@@ -533,12 +533,17 @@ static void privcmd_close(struct vm_area_struct *vma)
 {
        struct page **pages = vma->vm_private_data;
        int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       int rc;
 
        if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages)
                return;
 
-       xen_unmap_domain_mfn_range(vma, numpgs, pages);
-       free_xenballooned_pages(numpgs, pages);
+       rc = xen_unmap_domain_mfn_range(vma, numpgs, pages);
+       if (rc == 0)
+               free_xenballooned_pages(numpgs, pages);
+       else
+               pr_crit("unable to unmap MFN range: leaking %d pages. rc=%d\n",
+                       numpgs, rc);
        kfree(pages);
 }
 
index 6efb7f6cb22e9ba5aabb5f111129ef69b7dac370..062a5f6a1448c6cff1cd1dc09e84db3f0d59cc27 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -244,9 +244,14 @@ static void aio_free_ring(struct kioctx *ctx)
        int i;
 
        for (i = 0; i < ctx->nr_pages; i++) {
+               struct page *page;
                pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i,
                                page_count(ctx->ring_pages[i]));
-               put_page(ctx->ring_pages[i]);
+               page = ctx->ring_pages[i];
+               if (!page)
+                       continue;
+               ctx->ring_pages[i] = NULL;
+               put_page(page);
        }
 
        put_aio_ring_file(ctx);
@@ -280,18 +285,38 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
        unsigned long flags;
        int rc;
 
+       rc = 0;
+
+       /* Make sure the old page hasn't already been changed */
+       spin_lock(&mapping->private_lock);
+       ctx = mapping->private_data;
+       if (ctx) {
+               pgoff_t idx;
+               spin_lock_irqsave(&ctx->completion_lock, flags);
+               idx = old->index;
+               if (idx < (pgoff_t)ctx->nr_pages) {
+                       if (ctx->ring_pages[idx] != old)
+                               rc = -EAGAIN;
+               } else
+                       rc = -EINVAL;
+               spin_unlock_irqrestore(&ctx->completion_lock, flags);
+       } else
+               rc = -EINVAL;
+       spin_unlock(&mapping->private_lock);
+
+       if (rc != 0)
+               return rc;
+
        /* Writeback must be complete */
        BUG_ON(PageWriteback(old));
-       put_page(old);
+       get_page(new);
 
-       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode);
+       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1);
        if (rc != MIGRATEPAGE_SUCCESS) {
-               get_page(old);
+               put_page(new);
                return rc;
        }
 
-       get_page(new);
-
        /* We can potentially race against kioctx teardown here.  Use the
         * address_space's private data lock to protect the mapping's
         * private_data.
@@ -303,13 +328,24 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
                spin_lock_irqsave(&ctx->completion_lock, flags);
                migrate_page_copy(new, old);
                idx = old->index;
-               if (idx < (pgoff_t)ctx->nr_pages)
-                       ctx->ring_pages[idx] = new;
+               if (idx < (pgoff_t)ctx->nr_pages) {
+                       /* And only do the move if things haven't changed */
+                       if (ctx->ring_pages[idx] == old)
+                               ctx->ring_pages[idx] = new;
+                       else
+                               rc = -EAGAIN;
+               } else
+                       rc = -EINVAL;
                spin_unlock_irqrestore(&ctx->completion_lock, flags);
        } else
                rc = -EBUSY;
        spin_unlock(&mapping->private_lock);
 
+       if (rc == MIGRATEPAGE_SUCCESS)
+               put_page(old);
+       else
+               put_page(new);
+
        return rc;
 }
 #endif
@@ -326,7 +362,7 @@ static int aio_setup_ring(struct kioctx *ctx)
        struct aio_ring *ring;
        unsigned nr_events = ctx->max_reqs;
        struct mm_struct *mm = current->mm;
-       unsigned long size, populate;
+       unsigned long size, unused;
        int nr_pages;
        int i;
        struct file *file;
@@ -347,6 +383,20 @@ static int aio_setup_ring(struct kioctx *ctx)
                return -EAGAIN;
        }
 
+       ctx->aio_ring_file = file;
+       nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
+                       / sizeof(struct io_event);
+
+       ctx->ring_pages = ctx->internal_pages;
+       if (nr_pages > AIO_RING_PAGES) {
+               ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
+                                         GFP_KERNEL);
+               if (!ctx->ring_pages) {
+                       put_aio_ring_file(ctx);
+                       return -ENOMEM;
+               }
+       }
+
        for (i = 0; i < nr_pages; i++) {
                struct page *page;
                page = find_or_create_page(file->f_inode->i_mapping,
@@ -358,19 +408,14 @@ static int aio_setup_ring(struct kioctx *ctx)
                SetPageUptodate(page);
                SetPageDirty(page);
                unlock_page(page);
+
+               ctx->ring_pages[i] = page;
        }
-       ctx->aio_ring_file = file;
-       nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
-                       / sizeof(struct io_event);
+       ctx->nr_pages = i;
 
-       ctx->ring_pages = ctx->internal_pages;
-       if (nr_pages > AIO_RING_PAGES) {
-               ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
-                                         GFP_KERNEL);
-               if (!ctx->ring_pages) {
-                       put_aio_ring_file(ctx);
-                       return -ENOMEM;
-               }
+       if (unlikely(i != nr_pages)) {
+               aio_free_ring(ctx);
+               return -EAGAIN;
        }
 
        ctx->mmap_size = nr_pages * PAGE_SIZE;
@@ -379,9 +424,9 @@ static int aio_setup_ring(struct kioctx *ctx)
        down_write(&mm->mmap_sem);
        ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
                                       PROT_READ | PROT_WRITE,
-                                      MAP_SHARED | MAP_POPULATE, 0, &populate);
+                                      MAP_SHARED, 0, &unused);
+       up_write(&mm->mmap_sem);
        if (IS_ERR((void *)ctx->mmap_base)) {
-               up_write(&mm->mmap_sem);
                ctx->mmap_size = 0;
                aio_free_ring(ctx);
                return -EAGAIN;
@@ -389,27 +434,6 @@ static int aio_setup_ring(struct kioctx *ctx)
 
        pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base);
 
-       /* We must do this while still holding mmap_sem for write, as we
-        * need to be protected against userspace attempting to mremap()
-        * or munmap() the ring buffer.
-        */
-       ctx->nr_pages = get_user_pages(current, mm, ctx->mmap_base, nr_pages,
-                                      1, 0, ctx->ring_pages, NULL);
-
-       /* Dropping the reference here is safe as the page cache will hold
-        * onto the pages for us.  It is also required so that page migration
-        * can unmap the pages and get the right reference count.
-        */
-       for (i = 0; i < ctx->nr_pages; i++)
-               put_page(ctx->ring_pages[i]);
-
-       up_write(&mm->mmap_sem);
-
-       if (unlikely(ctx->nr_pages != nr_pages)) {
-               aio_free_ring(ctx);
-               return -EAGAIN;
-       }
-
        ctx->user_id = ctx->mmap_base;
        ctx->nr_events = nr_events; /* trusted copy */
 
@@ -652,7 +676,8 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
        aio_nr += ctx->max_reqs;
        spin_unlock(&aio_nr_lock);
 
-       percpu_ref_get(&ctx->users); /* io_setup() will drop this ref */
+       percpu_ref_get(&ctx->users);    /* io_setup() will drop this ref */
+       percpu_ref_get(&ctx->reqs);     /* free_ioctx_users() will drop this */
 
        err = ioctx_add_table(ctx, mm);
        if (err)
index 1e561c059539542e83a118edb003ffabca08506b..ec3ba43b9faae73fba6d6352da9515a812ec9f36 100644 (file)
@@ -210,9 +210,13 @@ static int readpage_nounlock(struct file *filp, struct page *page)
        if (err < 0) {
                SetPageError(page);
                goto out;
-       } else if (err < PAGE_CACHE_SIZE) {
+       } else {
+               if (err < PAGE_CACHE_SIZE) {
                /* zero fill remainder of page */
-               zero_user_segment(page, err, PAGE_CACHE_SIZE);
+                       zero_user_segment(page, err, PAGE_CACHE_SIZE);
+               } else {
+                       flush_dcache_page(page);
+               }
        }
        SetPageUptodate(page);
 
index 9a8e396aed89a43a0c824c3b682f96ac817ebc1c..278fd28912880b5cc09989ed7dcb8e7fbbfcb3ef 100644 (file)
@@ -978,7 +978,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
        struct ceph_mds_reply_inode *ininfo;
        struct ceph_vino vino;
        struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
-       int i = 0;
        int err = 0;
 
        dout("fill_trace %p is_dentry %d is_target %d\n", req,
@@ -1039,6 +1038,29 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                }
        }
 
+       if (rinfo->head->is_target) {
+               vino.ino = le64_to_cpu(rinfo->targeti.in->ino);
+               vino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
+
+               in = ceph_get_inode(sb, vino);
+               if (IS_ERR(in)) {
+                       err = PTR_ERR(in);
+                       goto done;
+               }
+               req->r_target_inode = in;
+
+               err = fill_inode(in, &rinfo->targeti, NULL,
+                               session, req->r_request_started,
+                               (le32_to_cpu(rinfo->head->result) == 0) ?
+                               req->r_fmode : -1,
+                               &req->r_caps_reservation);
+               if (err < 0) {
+                       pr_err("fill_inode badness %p %llx.%llx\n",
+                               in, ceph_vinop(in));
+                       goto done;
+               }
+       }
+
        /*
         * ignore null lease/binding on snapdir ENOENT, or else we
         * will have trouble splicing in the virtual snapdir later
@@ -1108,7 +1130,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                             ceph_dentry(req->r_old_dentry)->offset);
 
                        dn = req->r_old_dentry;  /* use old_dentry */
-                       in = dn->d_inode;
                }
 
                /* null dentry? */
@@ -1130,44 +1151,28 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                }
 
                /* attach proper inode */
-               ininfo = rinfo->targeti.in;
-               vino.ino = le64_to_cpu(ininfo->ino);
-               vino.snap = le64_to_cpu(ininfo->snapid);
-               in = dn->d_inode;
-               if (!in) {
-                       in = ceph_get_inode(sb, vino);
-                       if (IS_ERR(in)) {
-                               pr_err("fill_trace bad get_inode "
-                                      "%llx.%llx\n", vino.ino, vino.snap);
-                               err = PTR_ERR(in);
-                               d_drop(dn);
-                               goto done;
-                       }
+               if (!dn->d_inode) {
+                       ihold(in);
                        dn = splice_dentry(dn, in, &have_lease, true);
                        if (IS_ERR(dn)) {
                                err = PTR_ERR(dn);
                                goto done;
                        }
                        req->r_dentry = dn;  /* may have spliced */
-                       ihold(in);
-               } else if (ceph_ino(in) == vino.ino &&
-                          ceph_snap(in) == vino.snap) {
-                       ihold(in);
-               } else {
+               } else if (dn->d_inode && dn->d_inode != in) {
                        dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
-                            dn, in, ceph_ino(in), ceph_snap(in),
-                            vino.ino, vino.snap);
+                            dn, dn->d_inode, ceph_vinop(dn->d_inode),
+                            ceph_vinop(in));
                        have_lease = false;
-                       in = NULL;
                }
 
                if (have_lease)
                        update_dentry_lease(dn, rinfo->dlease, session,
                                            req->r_request_started);
                dout(" final dn %p\n", dn);
-               i++;
-       } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
-                  req->r_op == CEPH_MDS_OP_MKSNAP) && !req->r_aborted) {
+       } else if (!req->r_aborted &&
+                  (req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
+                   req->r_op == CEPH_MDS_OP_MKSNAP)) {
                struct dentry *dn = req->r_dentry;
 
                /* fill out a snapdir LOOKUPSNAP dentry */
@@ -1177,52 +1182,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                ininfo = rinfo->targeti.in;
                vino.ino = le64_to_cpu(ininfo->ino);
                vino.snap = le64_to_cpu(ininfo->snapid);
-               in = ceph_get_inode(sb, vino);
-               if (IS_ERR(in)) {
-                       pr_err("fill_inode get_inode badness %llx.%llx\n",
-                              vino.ino, vino.snap);
-                       err = PTR_ERR(in);
-                       d_delete(dn);
-                       goto done;
-               }
                dout(" linking snapped dir %p to dn %p\n", in, dn);
+               ihold(in);
                dn = splice_dentry(dn, in, NULL, true);
                if (IS_ERR(dn)) {
                        err = PTR_ERR(dn);
                        goto done;
                }
                req->r_dentry = dn;  /* may have spliced */
-               ihold(in);
-               rinfo->head->is_dentry = 1;  /* fool notrace handlers */
-       }
-
-       if (rinfo->head->is_target) {
-               vino.ino = le64_to_cpu(rinfo->targeti.in->ino);
-               vino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
-
-               if (in == NULL || ceph_ino(in) != vino.ino ||
-                   ceph_snap(in) != vino.snap) {
-                       in = ceph_get_inode(sb, vino);
-                       if (IS_ERR(in)) {
-                               err = PTR_ERR(in);
-                               goto done;
-                       }
-               }
-               req->r_target_inode = in;
-
-               err = fill_inode(in,
-                                &rinfo->targeti, NULL,
-                                session, req->r_request_started,
-                                (le32_to_cpu(rinfo->head->result) == 0) ?
-                                req->r_fmode : -1,
-                                &req->r_caps_reservation);
-               if (err < 0) {
-                       pr_err("fill_inode badness %p %llx.%llx\n",
-                              in, ceph_vinop(in));
-                       goto done;
-               }
        }
-
 done:
        dout("fill_trace done err=%d\n", err);
        return err;
@@ -1272,7 +1240,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
        struct qstr dname;
        struct dentry *dn;
        struct inode *in;
-       int err = 0, i;
+       int err = 0, ret, i;
        struct inode *snapdir = NULL;
        struct ceph_mds_request_head *rhead = req->r_request->front.iov_base;
        struct ceph_dentry_info *di;
@@ -1305,6 +1273,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
                        ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir);
        }
 
+       /* FIXME: release caps/leases if error occurs */
        for (i = 0; i < rinfo->dir_nr; i++) {
                struct ceph_vino vino;
 
@@ -1329,9 +1298,10 @@ retry_lookup:
                                err = -ENOMEM;
                                goto out;
                        }
-                       err = ceph_init_dentry(dn);
-                       if (err < 0) {
+                       ret = ceph_init_dentry(dn);
+                       if (ret < 0) {
                                dput(dn);
+                               err = ret;
                                goto out;
                        }
                } else if (dn->d_inode &&
@@ -1351,9 +1321,6 @@ retry_lookup:
                        spin_unlock(&parent->d_lock);
                }
 
-               di = dn->d_fsdata;
-               di->offset = ceph_make_fpos(frag, i + r_readdir_offset);
-
                /* inode */
                if (dn->d_inode) {
                        in = dn->d_inode;
@@ -1366,26 +1333,39 @@ retry_lookup:
                                err = PTR_ERR(in);
                                goto out;
                        }
-                       dn = splice_dentry(dn, in, NULL, false);
-                       if (IS_ERR(dn))
-                               dn = NULL;
                }
 
                if (fill_inode(in, &rinfo->dir_in[i], NULL, session,
                               req->r_request_started, -1,
                               &req->r_caps_reservation) < 0) {
                        pr_err("fill_inode badness on %p\n", in);
+                       if (!dn->d_inode)
+                               iput(in);
+                       d_drop(dn);
                        goto next_item;
                }
-               if (dn)
-                       update_dentry_lease(dn, rinfo->dir_dlease[i],
-                                           req->r_session,
-                                           req->r_request_started);
+
+               if (!dn->d_inode) {
+                       dn = splice_dentry(dn, in, NULL, false);
+                       if (IS_ERR(dn)) {
+                               err = PTR_ERR(dn);
+                               dn = NULL;
+                               goto next_item;
+                       }
+               }
+
+               di = dn->d_fsdata;
+               di->offset = ceph_make_fpos(frag, i + r_readdir_offset);
+
+               update_dentry_lease(dn, rinfo->dir_dlease[i],
+                                   req->r_session,
+                                   req->r_request_started);
 next_item:
                if (dn)
                        dput(dn);
        }
-       req->r_did_prepopulate = true;
+       if (err == 0)
+               req->r_did_prepopulate = true;
 
 out:
        if (snapdir) {
index aa3397620342d20beba92abc732845273d3663ca..2c29db6a247e4788256461100bed11ac79648d26 100644 (file)
@@ -477,9 +477,10 @@ extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
                        const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
 extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
-extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-               const unsigned char *path,
-               struct cifs_sb_info *cifs_sb, unsigned int xid);
+extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                             struct cifs_sb_info *cifs_sb,
+                             struct cifs_fattr *fattr,
+                             const unsigned char *path);
 extern int mdfour(unsigned char *, unsigned char *, int);
 extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
                        const struct nls_table *codepage);
index 124aa0230c1b8738edb8d04ca5d764f0a6cc5b12..d707edb6b852695f0de3993c9ef9cd12a3f909f3 100644 (file)
@@ -4010,7 +4010,7 @@ QFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4179,7 +4179,7 @@ UnixQFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4263,7 +4263,7 @@ UnixQPathInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
index 11ff5f116b20e663bf5e0428a940b437d9b232aa..a514e0a65f69b5936fbd60934b33938666f70dd0 100644 (file)
@@ -193,7 +193,7 @@ check_name(struct dentry *direntry)
 static int
 cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
               struct tcon_link *tlink, unsigned oflags, umode_t mode,
-              __u32 *oplock, struct cifs_fid *fid, int *created)
+              __u32 *oplock, struct cifs_fid *fid)
 {
        int rc = -ENOENT;
        int create_options = CREATE_NOT_DIR;
@@ -349,7 +349,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
                                .device = 0,
                };
 
-               *created |= FILE_CREATED;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                        args.uid = current_fsuid();
                        if (inode->i_mode & S_ISGID)
@@ -480,13 +479,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
        cifs_add_pending_open(&fid, tlink, &open);
 
        rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
-                           &oplock, &fid, opened);
+                           &oplock, &fid);
 
        if (rc) {
                cifs_del_pending_open(&open);
                goto out;
        }
 
+       if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               *opened |= FILE_CREATED;
+
        rc = finish_open(file, direntry, generic_file_open, opened);
        if (rc) {
                if (server->ops->close)
@@ -529,7 +531,6 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
        struct TCP_Server_Info *server;
        struct cifs_fid fid;
        __u32 oplock;
-       int created = FILE_CREATED;
 
        cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p\n",
                 inode, direntry->d_name.name, direntry);
@@ -546,7 +547,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                server->ops->new_lease_key(&fid);
 
        rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
-                           &oplock, &fid, &created);
+                           &oplock, &fid);
        if (!rc && server->ops->close)
                server->ops->close(xid, tcon, &fid);
 
index 36f9ebb93ceba676c363cdf7b973f3936a9dde8f..49719b8228e58bd44b373fd4b39d844be9e2043b 100644 (file)
@@ -383,7 +383,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                              full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
@@ -799,7 +800,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                          full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
index cc0234710ddbb780cae5037b717a93d8a7d3d54d..92aee08483a52e100011fb05e1fcfc5255b340ac 100644 (file)
@@ -354,34 +354,30 @@ open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
 
 
 int
-CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-                  const unsigned char *path,
-                  struct cifs_sb_info *cifs_sb, unsigned int xid)
+CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                  struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+                  const unsigned char *path)
 {
-       int rc = 0;
+       int rc;
        u8 *buf = NULL;
        unsigned int link_len = 0;
        unsigned int bytes_read = 0;
-       struct cifs_tcon *ptcon;
 
        if (!CIFSCouldBeMFSymlink(fattr))
                /* it's not a symlink */
                return 0;
 
        buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
-       if (!buf) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       if (!buf)
+               return -ENOMEM;
 
-       ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb));
-       if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink))
-               rc = ptcon->ses->server->ops->query_mf_symlink(path, buf,
-                                                &bytes_read, cifs_sb, xid);
+       if (tcon->ses->server->ops->query_mf_symlink)
+               rc = tcon->ses->server->ops->query_mf_symlink(path, buf,
+                                               &bytes_read, cifs_sb, xid);
        else
-               goto out;
+               rc = -ENOSYS;
 
-       if (rc != 0)
+       if (rc)
                goto out;
 
        if (bytes_read == 0) /* not a symlink */
index 6055d61811d30f6d037daed87ffb11924b0ac5e5..cb4a10690868263cb58e28012ee8f9abc4880da5 100644 (file)
@@ -3061,8 +3061,13 @@ char *d_path(const struct path *path, char *buf, int buflen)
         * thus don't need to be hashed.  They also don't need a name until a
         * user wants to identify the object in /proc/pid/fd/.  The little hack
         * below allows us to generate a name for these objects on demand:
+        *
+        * Some pseudo inodes are mountable.  When they are mounted
+        * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
+        * and instead have d_path return the mounted path.
         */
-       if (path->dentry->d_op && path->dentry->d_op->d_dname)
+       if (path->dentry->d_op && path->dentry->d_op->d_dname &&
+           (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
                return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 
        rcu_read_lock();
index 8b5e2584c840903bc9aeffab1a31aa0a2149b595..af903128891cfa0365f7fac36ba8fc052cc584a4 100644 (file)
@@ -1907,10 +1907,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                        }
                }
        }
-       if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) {
-               tep = tf.file->private_data;
-               mutex_lock_nested(&tep->mtx, 1);
-       }
 
        /*
         * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
index 288534920fe5cc4960f99ae636777344c5d42db6..20d6697bd6386560a679dda5e8b8592a65d63798 100644 (file)
@@ -1493,6 +1493,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
                                sb->s_blocksize - offset : towrite;
 
                tmp_bh.b_state = 0;
+               tmp_bh.b_size = sb->s_blocksize;
                err = ext2_get_block(inode, blk, &tmp_bh, 1);
                if (err < 0)
                        goto out;
index e6185031c1ccb5d7ef6c35185d77e5b06d648a5d..ece55565b9cd35575c454d44656c63321d89e0f9 100644 (file)
@@ -268,6 +268,16 @@ struct ext4_io_submit {
 /* Translate # of blks to # of clusters */
 #define EXT4_NUM_B2C(sbi, blks)        (((blks) + (sbi)->s_cluster_ratio - 1) >> \
                                 (sbi)->s_cluster_bits)
+/* Mask out the low bits to get the starting block of the cluster */
+#define EXT4_PBLK_CMASK(s, pblk) ((pblk) &                             \
+                                 ~((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
+#define EXT4_LBLK_CMASK(s, lblk) ((lblk) &                             \
+                                 ~((ext4_lblk_t) (s)->s_cluster_ratio - 1))
+/* Get the cluster offset */
+#define EXT4_PBLK_COFF(s, pblk) ((pblk) &                              \
+                                ((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
+#define EXT4_LBLK_COFF(s, lblk) ((lblk) &                              \
+                                ((ext4_lblk_t) (s)->s_cluster_ratio - 1))
 
 /*
  * Structure of a blocks group descriptor
index 17ac112ab1012bd88ff32d145f27a29f025efdde..3fe29de832c825e390b8d59d818b5ec37a8eb61f 100644 (file)
@@ -259,6 +259,15 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
                if (WARN_ON_ONCE(err)) {
                        ext4_journal_abort_handle(where, line, __func__, bh,
                                                  handle, err);
+                       ext4_error_inode(inode, where, line,
+                                        bh->b_blocknr,
+                                        "journal_dirty_metadata failed: "
+                                        "handle type %u started at line %u, "
+                                        "credits %u/%u, errcode %d",
+                                        handle->h_type,
+                                        handle->h_line_no,
+                                        handle->h_requested_credits,
+                                        handle->h_buffer_credits, err);
                }
        } else {
                if (inode)
index 35f65cf4f318d72bce4e79995ddbc85d0e4bbfa3..3384dc4bed4034921beffb84783327024e4cf22e 100644 (file)
@@ -360,8 +360,10 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
 {
        ext4_fsblk_t block = ext4_ext_pblock(ext);
        int len = ext4_ext_get_actual_len(ext);
+       ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
+       ext4_lblk_t last = lblock + len - 1;
 
-       if (len == 0)
+       if (lblock > last)
                return 0;
        return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
@@ -387,11 +389,26 @@ static int ext4_valid_extent_entries(struct inode *inode,
        if (depth == 0) {
                /* leaf entries */
                struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
+               struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+               ext4_fsblk_t pblock = 0;
+               ext4_lblk_t lblock = 0;
+               ext4_lblk_t prev = 0;
+               int len = 0;
                while (entries) {
                        if (!ext4_valid_extent(inode, ext))
                                return 0;
+
+                       /* Check for overlapping extents */
+                       lblock = le32_to_cpu(ext->ee_block);
+                       len = ext4_ext_get_actual_len(ext);
+                       if ((lblock <= prev) && prev) {
+                               pblock = ext4_ext_pblock(ext);
+                               es->s_last_error_block = cpu_to_le64(pblock);
+                               return 0;
+                       }
                        ext++;
                        entries--;
+                       prev = lblock + len - 1;
                }
        } else {
                struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh);
@@ -1834,8 +1851,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
        depth = ext_depth(inode);
        if (!path[depth].p_ext)
                goto out;
-       b2 = le32_to_cpu(path[depth].p_ext->ee_block);
-       b2 &= ~(sbi->s_cluster_ratio - 1);
+       b2 = EXT4_LBLK_CMASK(sbi, le32_to_cpu(path[depth].p_ext->ee_block));
 
        /*
         * get the next allocated block if the extent in the path
@@ -1845,7 +1861,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
                b2 = ext4_ext_next_allocated_block(path);
                if (b2 == EXT_MAX_BLOCKS)
                        goto out;
-               b2 &= ~(sbi->s_cluster_ratio - 1);
+               b2 = EXT4_LBLK_CMASK(sbi, b2);
        }
 
        /* check for wrap through zero on extent logical start block*/
@@ -2504,7 +2520,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
                 * extent, we have to mark the cluster as used (store negative
                 * cluster number in partial_cluster).
                 */
-               unaligned = pblk & (sbi->s_cluster_ratio - 1);
+               unaligned = EXT4_PBLK_COFF(sbi, pblk);
                if (unaligned && (ee_len == num) &&
                    (*partial_cluster != -((long long)EXT4_B2C(sbi, pblk))))
                        *partial_cluster = EXT4_B2C(sbi, pblk);
@@ -2598,7 +2614,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
                         * accidentally freeing it later on
                         */
                        pblk = ext4_ext_pblock(ex);
-                       if (pblk & (sbi->s_cluster_ratio - 1))
+                       if (EXT4_PBLK_COFF(sbi, pblk))
                                *partial_cluster =
                                        -((long long)EXT4_B2C(sbi, pblk));
                        ex--;
@@ -3753,7 +3769,7 @@ int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        ext4_lblk_t lblk_start, lblk_end;
-       lblk_start = lblk & (~(sbi->s_cluster_ratio - 1));
+       lblk_start = EXT4_LBLK_CMASK(sbi, lblk);
        lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
 
        return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
@@ -3812,9 +3828,9 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
        trace_ext4_get_reserved_cluster_alloc(inode, lblk_start, num_blks);
 
        /* Check towards left side */
-       c_offset = lblk_start & (sbi->s_cluster_ratio - 1);
+       c_offset = EXT4_LBLK_COFF(sbi, lblk_start);
        if (c_offset) {
-               lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1));
+               lblk_from = EXT4_LBLK_CMASK(sbi, lblk_start);
                lblk_to = lblk_from + c_offset - 1;
 
                if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
@@ -3822,7 +3838,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
        }
 
        /* Now check towards right. */
-       c_offset = (lblk_start + num_blks) & (sbi->s_cluster_ratio - 1);
+       c_offset = EXT4_LBLK_COFF(sbi, lblk_start + num_blks);
        if (allocated_clusters && c_offset) {
                lblk_from = lblk_start + num_blks;
                lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
@@ -4030,7 +4046,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
                                     struct ext4_ext_path *path)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+       ext4_lblk_t c_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
        ext4_lblk_t ex_cluster_start, ex_cluster_end;
        ext4_lblk_t rr_cluster_start;
        ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
@@ -4048,8 +4064,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
            (rr_cluster_start == ex_cluster_start)) {
                if (rr_cluster_start == ex_cluster_end)
                        ee_start += ee_len - 1;
-               map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) +
-                       c_offset;
+               map->m_pblk = EXT4_PBLK_CMASK(sbi, ee_start) + c_offset;
                map->m_len = min(map->m_len,
                                 (unsigned) sbi->s_cluster_ratio - c_offset);
                /*
@@ -4203,7 +4218,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         */
        map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
        newex.ee_block = cpu_to_le32(map->m_lblk);
-       cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+       cluster_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
 
        /*
         * If we are doing bigalloc, check to see if the extent returned
@@ -4271,7 +4286,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         * needed so that future calls to get_implied_cluster_alloc()
         * work correctly.
         */
-       offset = map->m_lblk & (sbi->s_cluster_ratio - 1);
+       offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
        ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
        ar.goal -= offset;
        ar.logical -= offset;
index 0757634741187a568cc2255187bcd2cf250d852b..61d49ff22c81f844cb8bc6324ad3aa70d649fb7b 100644 (file)
@@ -1206,7 +1206,6 @@ static int ext4_journalled_write_end(struct file *file,
  */
 static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
 {
-       int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int md_needed;
@@ -1218,7 +1217,6 @@ static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
         * in order to allocate nrblocks
         * worse case is one extent per block
         */
-repeat:
        spin_lock(&ei->i_block_reservation_lock);
        /*
         * ext4_calc_metadata_amount() has side effects, which we have
@@ -1238,10 +1236,6 @@ repeat:
                ei->i_da_metadata_calc_len = save_len;
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
-               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       cond_resched();
-                       goto repeat;
-               }
                return -ENOSPC;
        }
        ei->i_reserved_meta_blocks += md_needed;
@@ -1255,7 +1249,6 @@ repeat:
  */
 static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
 {
-       int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int md_needed;
@@ -1277,7 +1270,6 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
         * in order to allocate nrblocks
         * worse case is one extent per block
         */
-repeat:
        spin_lock(&ei->i_block_reservation_lock);
        /*
         * ext4_calc_metadata_amount() has side effects, which we have
@@ -1297,10 +1289,6 @@ repeat:
                ei->i_da_metadata_calc_len = save_len;
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
-               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       cond_resched();
-                       goto repeat;
-               }
                dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
                return -ENOSPC;
        }
index 4d113efa024c8439f4000a0fa59ed643f2489166..04a5c7504be9d6dbe55174d451f559064a7a05cf 100644 (file)
@@ -3442,6 +3442,9 @@ static void ext4_mb_pa_callback(struct rcu_head *head)
 {
        struct ext4_prealloc_space *pa;
        pa = container_of(head, struct ext4_prealloc_space, u.pa_rcu);
+
+       BUG_ON(atomic_read(&pa->pa_count));
+       BUG_ON(pa->pa_deleted == 0);
        kmem_cache_free(ext4_pspace_cachep, pa);
 }
 
@@ -3455,11 +3458,13 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
        ext4_group_t grp;
        ext4_fsblk_t grp_blk;
 
-       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
-               return;
-
        /* in this short window concurrent discard can set pa_deleted */
        spin_lock(&pa->pa_lock);
+       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) {
+               spin_unlock(&pa->pa_lock);
+               return;
+       }
+
        if (pa->pa_deleted == 1) {
                spin_unlock(&pa->pa_lock);
                return;
@@ -4121,7 +4126,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
        ext4_get_group_no_and_offset(sb, goal, &group, &block);
 
        /* set up allocation goals */
-       ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1);
+       ac->ac_b_ex.fe_logical = EXT4_LBLK_CMASK(sbi, ar->logical);
        ac->ac_status = AC_STATUS_CONTINUE;
        ac->ac_sb = sb;
        ac->ac_inode = ar->inode;
@@ -4663,7 +4668,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
         * blocks at the beginning or the end unless we are explicitly
         * requested to avoid doing so.
         */
-       overflow = block & (sbi->s_cluster_ratio - 1);
+       overflow = EXT4_PBLK_COFF(sbi, block);
        if (overflow) {
                if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
                        overflow = sbi->s_cluster_ratio - overflow;
@@ -4677,7 +4682,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
                        count += overflow;
                }
        }
-       overflow = count & (sbi->s_cluster_ratio - 1);
+       overflow = EXT4_LBLK_COFF(sbi, count);
        if (overflow) {
                if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
                        if (count > overflow)
index c977f4e4e63be6c4cf3b477f628e4fc7d323d1f5..1f7784de05b6c6afad4d7437202ceb6efeec3399 100644 (file)
@@ -792,7 +792,7 @@ static void ext4_put_super(struct super_block *sb)
        }
 
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        ext4_release_system_zone(sb);
        ext4_mb_release(sb);
        ext4_ext_release(sb);
@@ -3316,10 +3316,18 @@ int ext4_calculate_overhead(struct super_block *sb)
 }
 
 
-static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
+static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
 {
        ext4_fsblk_t resv_clusters;
 
+       /*
+        * There's no need to reserve anything when we aren't using extents.
+        * The space estimates are exact, there are no unwritten extents,
+        * hole punching doesn't need new metadata... This is needed especially
+        * to keep ext2/3 backward compatibility.
+        */
+       if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
+               return 0;
        /*
         * By default we reserve 2% or 4096 clusters, whichever is smaller.
         * This should cover the situations where we can not afford to run
@@ -3328,7 +3336,8 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
         * allocation would require 1, or 2 blocks, higher numbers are
         * very rare.
         */
-       resv_clusters = ext4_blocks_count(sbi->s_es) >> sbi->s_cluster_bits;
+       resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >>
+                       EXT4_SB(sb)->s_cluster_bits;
 
        do_div(resv_clusters, 50);
        resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
@@ -4071,10 +4080,10 @@ no_journal:
                         "available");
        }
 
-       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sbi));
+       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb));
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
-                        "reserved pool", ext4_calculate_resv_clusters(sbi));
+                        "reserved pool", ext4_calculate_resv_clusters(sb));
                goto failed_mount4a;
        }
 
@@ -4184,7 +4193,7 @@ failed_mount_wq:
        }
 failed_mount3:
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        if (sbi->s_flex_groups)
                ext4_kvfree(sbi->s_flex_groups);
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
index 1f4a10ece2f1249d5ae9991bfdde4874019b3462..e0259a163f98e69000c28bdb78fcf2b77c2bed2d 100644 (file)
@@ -516,13 +516,16 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
        }
        WARN_ON(inode->i_state & I_SYNC);
        /*
-        * Skip inode if it is clean. We don't want to mess with writeback
-        * lists in this function since flusher thread may be doing for example
-        * sync in parallel and if we move the inode, it could get skipped. So
-        * here we make sure inode is on some writeback list and leave it there
-        * unless we have completely cleaned the inode.
+        * Skip inode if it is clean and we have no outstanding writeback in
+        * WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
+        * function since flusher thread may be doing for example sync in
+        * parallel and if we move the inode, it could get skipped. So here we
+        * make sure inode is on some writeback list and leave it there unless
+        * we have completely cleaned the inode.
         */
-       if (!(inode->i_state & I_DIRTY))
+       if (!(inode->i_state & I_DIRTY) &&
+           (wbc->sync_mode != WB_SYNC_ALL ||
+            !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
                goto out;
        inode->i_state |= I_SYNC;
        spin_unlock(&inode->i_lock);
index b7fc035a6943cc40f649f1cca7be5858fbcf1cbc..73f3e4ee403793e1ae39c75b5d652f64c6a4b52a 100644 (file)
@@ -986,6 +986,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
+       struct address_space *mapping = inode->i_mapping;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int rv;
@@ -1006,6 +1007,35 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
        if (rv != 1)
                goto out; /* dio not valid, fall back to buffered i/o */
 
+       /*
+        * Now since we are holding a deferred (CW) lock at this point, you
+        * might be wondering why this is ever needed. There is a case however
+        * where we've granted a deferred local lock against a cached exclusive
+        * glock. That is ok provided all granted local locks are deferred, but
+        * it also means that it is possible to encounter pages which are
+        * cached and possibly also mapped. So here we check for that and sort
+        * them out ahead of the dio. The glock state machine will take care of
+        * everything else.
+        *
+        * If in fact the cached glock state (gl->gl_state) is deferred (CW) in
+        * the first place, mapping->nr_pages will always be zero.
+        */
+       if (mapping->nrpages) {
+               loff_t lstart = offset & (PAGE_CACHE_SIZE - 1);
+               loff_t len = iov_length(iov, nr_segs);
+               loff_t end = PAGE_ALIGN(offset + len) - 1;
+
+               rv = 0;
+               if (len == 0)
+                       goto out;
+               if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+                       unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len);
+               rv = filemap_write_and_wait_range(mapping, lstart, end);
+               if (rv)
+                       return rv;
+               truncate_inode_pages_range(mapping, lstart, end);
+       }
+
        rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                  offset, nr_segs, gfs2_get_block_direct,
                                  NULL, NULL, 0);
index c8420f7e4db604da3663da61c5ae4556b6439783..6f7a47c052592145d7601c0e9ab0341c4dd8c4d7 100644 (file)
@@ -1655,6 +1655,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
        struct task_struct *gh_owner = NULL;
        char flags_buf[32];
 
+       rcu_read_lock();
        if (gh->gh_owner_pid)
                gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID);
        gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS\n",
@@ -1664,6 +1665,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
                       gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1,
                       gh_owner ? gh_owner->comm : "(ended)",
                       (void *)gh->gh_ip);
+       rcu_read_unlock();
        return 0;
 }
 
index db908f697139cfffbca462d3a7528e13139576b5..f88dcd92501098e4a9bca28724da34e8df5a0154 100644 (file)
@@ -192,8 +192,11 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
        if (ip && !S_ISREG(ip->i_inode.i_mode))
                ip = NULL;
-       if (ip && test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
-               unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+       if (ip) {
+               if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+                       unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+               inode_dio_wait(&ip->i_inode);
+       }
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
                return;
 
@@ -410,6 +413,9 @@ static int inode_go_lock(struct gfs2_holder *gh)
                        return error;
        }
 
+       if (gh->gh_state != LM_ST_DEFERRED)
+               inode_dio_wait(&ip->i_inode);
+
        if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) &&
            (gl->gl_state == LM_ST_EXCLUSIVE) &&
            (gh->gh_state == LM_ST_EXCLUSIVE)) {
index 610613fb65b552dccfdf9853ac96d2f667bd36d4..9dcb9777a5f80eb32bcfce88aca3a8026776f047 100644 (file)
@@ -551,10 +551,10 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct buffer_head *bh = bd->bd_bh;
        struct gfs2_glock *gl = bd->bd_gl;
 
-       gfs2_remove_from_ail(bd);
-       bd->bd_bh = NULL;
        bh->b_private = NULL;
        bd->bd_blkno = bh->b_blocknr;
+       gfs2_remove_from_ail(bd); /* drops ref on bh */
+       bd->bd_bh = NULL;
        bd->bd_ops = &gfs2_revoke_lops;
        sdp->sd_log_num_revoke++;
        atomic_inc(&gl->gl_revokes);
index 932415050540e2a1bdefc6d957e68ef7a0d82d01..52f177be3bf861309ed2439d33da7617bba8dba8 100644 (file)
@@ -258,6 +258,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
        struct address_space *mapping = bh->b_page->mapping;
        struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
        struct gfs2_bufdata *bd = bh->b_private;
+       int was_pinned = 0;
 
        if (test_clear_buffer_pinned(bh)) {
                trace_gfs2_pin(bd, 0);
@@ -273,12 +274,16 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
                        tr->tr_num_databuf_rm++;
                }
                tr->tr_touched = 1;
+               was_pinned = 1;
                brelse(bh);
        }
        if (bd) {
                spin_lock(&sdp->sd_ail_lock);
                if (bd->bd_tr) {
                        gfs2_trans_add_revoke(sdp, bd);
+               } else if (was_pinned) {
+                       bh->b_private = NULL;
+                       kmem_cache_free(gfs2_bufdata_cachep, bd);
                }
                spin_unlock(&sdp->sd_ail_lock);
        }
index 82303b4749582cd3c00d402a9f42b9972b1de677..52fa88314f5cdf8ef98ed95e44791a5065cbfccd 100644 (file)
@@ -1366,8 +1366,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
        if (IS_ERR(s))
                goto error_bdev;
 
-       if (s->s_root)
+       if (s->s_root) {
+               /*
+                * s_umount nests inside bd_mutex during
+                * __invalidate_device().  blkdev_put() acquires
+                * bd_mutex and can't be called under s_umount.  Drop
+                * s_umount temporarily.  This is safe as we're
+                * holding an active reference.
+                */
+               up_write(&s->s_umount);
                blkdev_put(bdev, mode);
+               down_write(&s->s_umount);
+       }
 
        memset(&args, 0, sizeof(args));
        args.ar_quota = GFS2_QUOTA_DEFAULT;
index 52032647dd4a32f7c8efaea95227634071f8d7d3..5fa344afb49ae8642be889ce2b3f69d176af548e 100644 (file)
@@ -702,7 +702,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        read_lock(&journal->j_state_lock);
 #ifdef CONFIG_JBD2_DEBUG
        if (!tid_geq(journal->j_commit_request, tid)) {
-               printk(KERN_EMERG
+               printk(KERN_ERR
                       "%s: error: j_commit_request=%d, tid=%d\n",
                       __func__, journal->j_commit_request, tid);
        }
@@ -718,10 +718,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        }
        read_unlock(&journal->j_state_lock);
 
-       if (unlikely(is_journal_aborted(journal))) {
-               printk(KERN_EMERG "journal commit I/O error\n");
+       if (unlikely(is_journal_aborted(journal)))
                err = -EIO;
-       }
        return err;
 }
 
@@ -1527,13 +1525,13 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) &&
            JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                /* Can't have checksum v1 and v2 on at the same time! */
-               printk(KERN_ERR "JBD: Can't enable checksumming v1 and v2 "
+               printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 "
                       "at the same time!\n");
                goto out;
        }
 
        if (!jbd2_verify_csum_type(journal, sb)) {
-               printk(KERN_ERR "JBD: Unknown checksum type\n");
+               printk(KERN_ERR "JBD2: Unknown checksum type\n");
                goto out;
        }
 
@@ -1541,7 +1539,7 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
                if (IS_ERR(journal->j_chksum_driver)) {
-                       printk(KERN_ERR "JBD: Cannot load crc32c driver.\n");
+                       printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
                        err = PTR_ERR(journal->j_chksum_driver);
                        journal->j_chksum_driver = NULL;
                        goto out;
@@ -1550,7 +1548,7 @@ static int journal_get_superblock(journal_t *journal)
 
        /* Check superblock checksum */
        if (!jbd2_superblock_csum_verify(journal, sb)) {
-               printk(KERN_ERR "JBD: journal checksum error\n");
+               printk(KERN_ERR "JBD2: journal checksum error\n");
                goto out;
        }
 
@@ -1836,7 +1834,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
                        journal->j_chksum_driver = crypto_alloc_shash("crc32c",
                                                                      0, 0);
                        if (IS_ERR(journal->j_chksum_driver)) {
-                               printk(KERN_ERR "JBD: Cannot load crc32c "
+                               printk(KERN_ERR "JBD2: Cannot load crc32c "
                                       "driver.\n");
                                journal->j_chksum_driver = NULL;
                                return 0;
@@ -2645,7 +2643,7 @@ static void __exit journal_exit(void)
 #ifdef CONFIG_JBD2_DEBUG
        int n = atomic_read(&nr_journal_heads);
        if (n)
-               printk(KERN_EMERG "JBD2: leaked %d journal_heads!\n", n);
+               printk(KERN_ERR "JBD2: leaked %d journal_heads!\n", n);
 #endif
        jbd2_remove_jbd_stats_proc_entry();
        jbd2_journal_destroy_caches();
index 3929c50428b1a289d4024fcbe673276f63ff97c0..3b6bb19d60b17abceadec4c38df5d3570c0fcba9 100644 (file)
@@ -594,7 +594,7 @@ static int do_one_pass(journal_t *journal,
                                                be32_to_cpu(tmp->h_sequence))) {
                                                brelse(obh);
                                                success = -EIO;
-                                               printk(KERN_ERR "JBD: Invalid "
+                                               printk(KERN_ERR "JBD2: Invalid "
                                                       "checksum recovering "
                                                       "block %llu in log\n",
                                                       blocknr);
index 7aa9a32573bba885d166e484c367bffc06bcd9e2..8360674c85bcb98af88d6aaff3ee4c46fe6f31bf 100644 (file)
@@ -932,7 +932,7 @@ repeat:
                                        jbd2_alloc(jh2bh(jh)->b_size,
                                                         GFP_NOFS);
                                if (!frozen_buffer) {
-                                       printk(KERN_EMERG
+                                       printk(KERN_ERR
                                               "%s: OOM for frozen_buffer\n",
                                               __func__);
                                        JBUFFER_TRACE(jh, "oom!");
@@ -1166,7 +1166,7 @@ repeat:
        if (!jh->b_committed_data) {
                committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
                if (!committed_data) {
-                       printk(KERN_EMERG "%s: No memory for committed data\n",
+                       printk(KERN_ERR "%s: No memory for committed data\n",
                                __func__);
                        err = -ENOMEM;
                        goto out;
@@ -1290,7 +1290,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                 * once a transaction -bzzz
                 */
                jh->b_modified = 1;
-               J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+               if (handle->h_buffer_credits <= 0) {
+                       ret = -ENOSPC;
+                       goto out_unlock_bh;
+               }
                handle->h_buffer_credits--;
        }
 
@@ -1305,7 +1308,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "fastpath");
                if (unlikely(jh->b_transaction !=
                             journal->j_running_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_running_transaction (%p, %u)",
                               journal->j_devname,
@@ -1332,7 +1335,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "already on other transaction");
                if (unlikely(jh->b_transaction !=
                             journal->j_committing_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_committing_transaction (%p, %u)",
                               journal->j_devname,
@@ -1345,7 +1348,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                        ret = -EINVAL;
                }
                if (unlikely(jh->b_next_transaction != transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_next_transaction (%llu, %p, %u) != "
                               "transaction (%p, %u)",
                               journal->j_devname,
@@ -1373,7 +1376,6 @@ out_unlock_bh:
        jbd2_journal_put_journal_head(jh);
 out:
        JBUFFER_TRACE(jh, "exit");
-       WARN_ON(ret);   /* All errors are bugs, so dump the stack */
        return ret;
 }
 
index ac2ce8a766e1a9c6250cdac616f9a951dddee45e..be32ebccdeb166a0c4eb85c4459d68a3d2555fab 100644 (file)
@@ -2886,7 +2886,7 @@ bool fs_fully_visible(struct file_system_type *type)
                        struct inode *inode = child->mnt_mountpoint->d_inode;
                        if (!S_ISDIR(inode->i_mode))
                                goto next;
-                       if (inode->i_nlink != 2)
+                       if (inode->i_nlink > 2)
                                goto next;
                }
                visible = true;
index 9f6b486b6c01a0e6711ca5930e78474d0739e35e..a1a191634abc1729f94a443ab4eac4cdddaaf54c 100644 (file)
@@ -1440,17 +1440,19 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
 
                nilfs_clear_logs(&sci->sc_segbufs);
 
-               err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
-               if (unlikely(err))
-                       return err;
-
                if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
                        err = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
                                                        sci->sc_freesegs,
                                                        sci->sc_nfreesegs,
                                                        NULL);
                        WARN_ON(err); /* do not happen */
+                       sci->sc_stage.flags &= ~NILFS_CF_SUFREED;
                }
+
+               err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
+               if (unlikely(err))
+                       return err;
+
                nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA);
                sci->sc_stage = prev_stage;
        }
index b8e93a40a5d3342767a26959858d24f2a24274c0..78c3c2097787a1be2ea2bd1757a6c6e5554df72c 100644 (file)
@@ -443,8 +443,11 @@ int pstore_register(struct pstore_info *psi)
                pstore_get_records(0);
 
        kmsg_dump_register(&pstore_dumper);
-       pstore_register_console();
-       pstore_register_ftrace();
+
+       if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
+               pstore_register_console();
+               pstore_register_ftrace();
+       }
 
        if (pstore_update_ms >= 0) {
                pstore_timer.expires = jiffies +
index b94f93685093edb4f2d189238989d3024fffa246..35e7d08fe629dfcb79553bcdcdf39af03b5e4960 100644 (file)
@@ -609,7 +609,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
        struct sysfs_open_file *of;
-       bool has_read, has_write, has_mmap;
+       bool has_read, has_write;
        int error = -EACCES;
 
        /* need attr_sd for attr and ops, its parent for kobj */
@@ -621,7 +621,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 
                has_read = battr->read || battr->mmap;
                has_write = battr->write || battr->mmap;
-               has_mmap = battr->mmap;
        } else {
                const struct sysfs_ops *ops = sysfs_file_ops(attr_sd);
 
@@ -633,7 +632,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 
                has_read = ops->show;
                has_write = ops->store;
-               has_mmap = false;
        }
 
        /* check perms and supported operations */
@@ -661,9 +659,9 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
         * open file has a separate mutex, it's okay as long as those don't
         * happen on the same file.  At this point, we can't easily give
         * each file a separate locking class.  Let's differentiate on
-        * whether the file has mmap or not for now.
+        * whether the file is bin or not for now.
         */
-       if (has_mmap)
+       if (sysfs_is_bin(attr_sd))
                mutex_init(&of->mutex);
        else
                mutex_init(&of->mutex);
index 739e0a52dedadea67eb595f4b03619ce3e3383a3..5549d69ddb45a2038ece8e24085e0f9ef6ce9984 100644 (file)
@@ -110,7 +110,7 @@ xfs_attr3_rmt_verify(
        if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
                return false;
        if (be32_to_cpu(rmt->rm_offset) +
-                               be32_to_cpu(rmt->rm_bytes) >= XATTR_SIZE_MAX)
+                               be32_to_cpu(rmt->rm_bytes) > XATTR_SIZE_MAX)
                return false;
        if (rmt->rm_owner == 0)
                return false;
index 3ef11b22e7505c380feb6597113d5b150f7b1afb..3b2c14b6f0fb13efd7a3aa89abc05d0a8334a5ff 100644 (file)
@@ -1635,7 +1635,7 @@ xfs_bmap_last_extent(
  * blocks at the end of the file which do not start at the previous data block,
  * we will try to align the new blocks at stripe unit boundaries.
  *
- * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
+ * Returns 1 in bma->aeof if the file (fork) is empty as any new write will be
  * at, or past the EOF.
  */
 STATIC int
@@ -1650,9 +1650,14 @@ xfs_bmap_isaeof(
        bma->aeof = 0;
        error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
                                     &is_empty);
-       if (error || is_empty)
+       if (error)
                return error;
 
+       if (is_empty) {
+               bma->aeof = 1;
+               return 0;
+       }
+
        /*
         * Check if we are allocation or past the last extent, or at least into
         * the last delayed allocated extent.
@@ -3643,10 +3648,19 @@ xfs_bmap_btalloc(
        int             isaligned;
        int             tryagain;
        int             error;
+       int             stripe_align;
 
        ASSERT(ap->length);
 
        mp = ap->ip->i_mount;
+
+       /* stripe alignment for allocation is determined by mount parameters */
+       stripe_align = 0;
+       if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+               stripe_align = mp->m_swidth;
+       else if (mp->m_dalign)
+               stripe_align = mp->m_dalign;
+
        align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
        if (unlikely(align)) {
                error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
@@ -3655,6 +3669,8 @@ xfs_bmap_btalloc(
                ASSERT(!error);
                ASSERT(ap->length);
        }
+
+
        nullfb = *ap->firstblock == NULLFSBLOCK;
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
        if (nullfb) {
@@ -3730,7 +3746,7 @@ xfs_bmap_btalloc(
         */
        if (!ap->flist->xbf_low && ap->aeof) {
                if (!ap->offset) {
-                       args.alignment = mp->m_dalign;
+                       args.alignment = stripe_align;
                        atype = args.type;
                        isaligned = 1;
                        /*
@@ -3755,13 +3771,13 @@ xfs_bmap_btalloc(
                         * of minlen+alignment+slop doesn't go up
                         * between the calls.
                         */
-                       if (blen > mp->m_dalign && blen <= args.maxlen)
-                               nextminlen = blen - mp->m_dalign;
+                       if (blen > stripe_align && blen <= args.maxlen)
+                               nextminlen = blen - stripe_align;
                        else
                                nextminlen = args.minlen;
-                       if (nextminlen + mp->m_dalign > args.minlen + 1)
+                       if (nextminlen + stripe_align > args.minlen + 1)
                                args.minalignslop =
-                                       nextminlen + mp->m_dalign -
+                                       nextminlen + stripe_align -
                                        args.minlen - 1;
                        else
                                args.minalignslop = 0;
@@ -3783,7 +3799,7 @@ xfs_bmap_btalloc(
                 */
                args.type = atype;
                args.fsbno = ap->blkno;
-               args.alignment = mp->m_dalign;
+               args.alignment = stripe_align;
                args.minlen = nextminlen;
                args.minalignslop = 0;
                isaligned = 1;
index 5887e41c0323ae85f867cc9bc83bbdf8c1e41cd1..82e0dab46ee52cc991a7130d8f671e011eef10a3 100644 (file)
@@ -287,6 +287,7 @@ xfs_bmapi_allocate(
        INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
        queue_work(xfs_alloc_wq, &args->work);
        wait_for_completion(&done);
+       destroy_work_on_stack(&args->work);
        return args->result;
 }
 
@@ -1187,7 +1188,12 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNWRITE(bp);
                XFS_BUF_READ(bp);
                XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
-               xfsbdstrat(mp, bp);
+
+               if (XFS_FORCED_SHUTDOWN(mp)) {
+                       error = XFS_ERROR(EIO);
+                       break;
+               }
+               xfs_buf_iorequest(bp);
                error = xfs_buf_iowait(bp);
                if (error) {
                        xfs_buf_ioerror_alert(bp,
@@ -1200,7 +1206,12 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNDONE(bp);
                XFS_BUF_UNREAD(bp);
                XFS_BUF_WRITE(bp);
-               xfsbdstrat(mp, bp);
+
+               if (XFS_FORCED_SHUTDOWN(mp)) {
+                       error = XFS_ERROR(EIO);
+                       break;
+               }
+               xfs_buf_iorequest(bp);
                error = xfs_buf_iowait(bp);
                if (error) {
                        xfs_buf_ioerror_alert(bp,
index c7f0b77dcb0090046b84eda27c68d870af25d45a..afe7645e4b2b8b7746665ed35a0d55da6ce11e3b 100644 (file)
@@ -698,7 +698,11 @@ xfs_buf_read_uncached(
        bp->b_flags |= XBF_READ;
        bp->b_ops = ops;
 
-       xfsbdstrat(target->bt_mount, bp);
+       if (XFS_FORCED_SHUTDOWN(target->bt_mount)) {
+               xfs_buf_relse(bp);
+               return NULL;
+       }
+       xfs_buf_iorequest(bp);
        xfs_buf_iowait(bp);
        return bp;
 }
@@ -1089,7 +1093,7 @@ xfs_bioerror(
  * This is meant for userdata errors; metadata bufs come with
  * iodone functions attached, so that we can track down errors.
  */
-STATIC int
+int
 xfs_bioerror_relse(
        struct xfs_buf  *bp)
 {
@@ -1152,7 +1156,7 @@ xfs_bwrite(
        ASSERT(xfs_buf_islocked(bp));
 
        bp->b_flags |= XBF_WRITE;
-       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q);
+       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q | XBF_WRITE_FAIL);
 
        xfs_bdstrat_cb(bp);
 
@@ -1164,25 +1168,6 @@ xfs_bwrite(
        return error;
 }
 
-/*
- * Wrapper around bdstrat so that we can stop data from going to disk in case
- * we are shutting down the filesystem.  Typically user data goes thru this
- * path; one of the exceptions is the superblock.
- */
-void
-xfsbdstrat(
-       struct xfs_mount        *mp,
-       struct xfs_buf          *bp)
-{
-       if (XFS_FORCED_SHUTDOWN(mp)) {
-               trace_xfs_bdstrat_shut(bp, _RET_IP_);
-               xfs_bioerror_relse(bp);
-               return;
-       }
-
-       xfs_buf_iorequest(bp);
-}
-
 STATIC void
 _xfs_buf_ioend(
        xfs_buf_t               *bp,
@@ -1516,6 +1501,12 @@ xfs_wait_buftarg(
                        struct xfs_buf *bp;
                        bp = list_first_entry(&dispose, struct xfs_buf, b_lru);
                        list_del_init(&bp->b_lru);
+                       if (bp->b_flags & XBF_WRITE_FAIL) {
+                               xfs_alert(btp->bt_mount,
+"Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n"
+"Please run xfs_repair to determine the extent of the problem.",
+                                       (long long)bp->b_bn);
+                       }
                        xfs_buf_rele(bp);
                }
                if (loop++ != 0)
@@ -1799,7 +1790,7 @@ __xfs_buf_delwri_submit(
 
        blk_start_plug(&plug);
        list_for_each_entry_safe(bp, n, io_list, b_list) {
-               bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC);
+               bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL);
                bp->b_flags |= XBF_WRITE;
 
                if (!wait) {
index e65683361017745eff61e245ee72896d2e6ff8df..1cf21a4a9f221de465299bf820fa710c3b3aa40e 100644 (file)
@@ -45,6 +45,7 @@ typedef enum {
 #define XBF_ASYNC       (1 << 4) /* initiator will not wait for completion */
 #define XBF_DONE        (1 << 5) /* all pages in the buffer uptodate */
 #define XBF_STALE       (1 << 6) /* buffer has been staled, do not find it */
+#define XBF_WRITE_FAIL  (1 << 24)/* async writes have failed on this buffer */
 
 /* I/O hints for the BIO layer */
 #define XBF_SYNCIO      (1 << 10)/* treat this buffer as synchronous I/O */
@@ -70,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t;
        { XBF_ASYNC,            "ASYNC" }, \
        { XBF_DONE,             "DONE" }, \
        { XBF_STALE,            "STALE" }, \
+       { XBF_WRITE_FAIL,       "WRITE_FAIL" }, \
        { XBF_SYNCIO,           "SYNCIO" }, \
        { XBF_FUA,              "FUA" }, \
        { XBF_FLUSH,            "FLUSH" }, \
@@ -80,6 +82,7 @@ typedef unsigned int xfs_buf_flags_t;
        { _XBF_DELWRI_Q,        "DELWRI_Q" }, \
        { _XBF_COMPOUND,        "COMPOUND" }
 
+
 /*
  * Internal state flags.
  */
@@ -269,9 +272,6 @@ extern void xfs_buf_unlock(xfs_buf_t *);
 
 /* Buffer Read and Write Routines */
 extern int xfs_bwrite(struct xfs_buf *bp);
-
-extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
-
 extern void xfs_buf_ioend(xfs_buf_t *, int);
 extern void xfs_buf_ioerror(xfs_buf_t *, int);
 extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
@@ -282,6 +282,8 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
 #define xfs_buf_zero(bp, off, len) \
            xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
 
+extern int xfs_bioerror_relse(struct xfs_buf *);
+
 static inline int xfs_buf_geterror(xfs_buf_t *bp)
 {
        return bp ? bp->b_error : ENOMEM;
@@ -301,7 +303,8 @@ extern void xfs_buf_terminate(void);
 
 #define XFS_BUF_ZEROFLAGS(bp) \
        ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \
-                           XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
+                           XBF_SYNCIO|XBF_FUA|XBF_FLUSH| \
+                           XBF_WRITE_FAIL))
 
 void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_UNSTALE(bp)    ((bp)->b_flags &= ~XBF_STALE)
index a64f67ba25d3c99c748e1d4a8f84f7648e3dd651..2227b9b050bb30248d986b343dd33e42c7978529 100644 (file)
@@ -496,6 +496,14 @@ xfs_buf_item_unpin(
        }
 }
 
+/*
+ * Buffer IO error rate limiting. Limit it to no more than 10 messages per 30
+ * seconds so as to not spam logs too much on repeated detection of the same
+ * buffer being bad..
+ */
+
+DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10);
+
 STATIC uint
 xfs_buf_item_push(
        struct xfs_log_item     *lip,
@@ -524,6 +532,14 @@ xfs_buf_item_push(
 
        trace_xfs_buf_item_push(bip);
 
+       /* has a previous flush failed due to IO errors? */
+       if ((bp->b_flags & XBF_WRITE_FAIL) &&
+           ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) {
+               xfs_warn(bp->b_target->bt_mount,
+"Detected failing async write on buffer block 0x%llx. Retrying async write.\n",
+                        (long long)bp->b_bn);
+       }
+
        if (!xfs_buf_delwri_queue(bp, buffer_list))
                rval = XFS_ITEM_FLUSHING;
        xfs_buf_unlock(bp);
@@ -1096,8 +1112,9 @@ xfs_buf_iodone_callbacks(
 
                xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
 
-               if (!XFS_BUF_ISSTALE(bp)) {
-                       bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE;
+               if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL))) {
+                       bp->b_flags |= XBF_WRITE | XBF_ASYNC |
+                                      XBF_DONE | XBF_WRITE_FAIL;
                        xfs_buf_iorequest(bp);
                } else {
                        xfs_buf_relse(bp);
index 56369d4509d5603cff44adeb17902324a547f48b..48c7d18f68c3fb23a89a31a955fc9250fbd63108 100644 (file)
@@ -2067,12 +2067,12 @@ xfs_dir2_node_lookup(
  */
 int                                            /* error */
 xfs_dir2_node_removename(
-       xfs_da_args_t           *args)          /* operation arguments */
+       struct xfs_da_args      *args)          /* operation arguments */
 {
-       xfs_da_state_blk_t      *blk;           /* leaf block */
+       struct xfs_da_state_blk *blk;           /* leaf block */
        int                     error;          /* error return value */
        int                     rval;           /* operation return value */
-       xfs_da_state_t          *state;         /* btree cursor */
+       struct xfs_da_state     *state;         /* btree cursor */
 
        trace_xfs_dir2_node_removename(args);
 
@@ -2084,19 +2084,18 @@ xfs_dir2_node_removename(
        state->mp = args->dp->i_mount;
        state->blocksize = state->mp->m_dirblksize;
        state->node_ents = state->mp->m_dir_node_ents;
-       /*
-        * Look up the entry we're deleting, set up the cursor.
-        */
+
+       /* Look up the entry we're deleting, set up the cursor. */
        error = xfs_da3_node_lookup_int(state, &rval);
        if (error)
-               rval = error;
-       /*
-        * Didn't find it, upper layer screwed up.
-        */
+               goto out_free;
+
+       /* Didn't find it, upper layer screwed up. */
        if (rval != EEXIST) {
-               xfs_da_state_free(state);
-               return rval;
+               error = rval;
+               goto out_free;
        }
+
        blk = &state->path.blk[state->path.active - 1];
        ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
        ASSERT(state->extravalid);
@@ -2107,7 +2106,7 @@ xfs_dir2_node_removename(
        error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
                &state->extrablk, &rval);
        if (error)
-               return error;
+               goto out_free;
        /*
         * Fix the hash values up the btree.
         */
@@ -2122,6 +2121,7 @@ xfs_dir2_node_removename(
         */
        if (!error)
                error = xfs_dir2_node_to_leaf(state);
+out_free:
        xfs_da_state_free(state);
        return error;
 }
index 27e0e544e9635ba47281279c68670f7e568a7a58..104455b8046c4bd9ea11855c917b7b46c4573361 100644 (file)
@@ -618,7 +618,8 @@ xfs_setattr_nonsize(
                }
                if (!gid_eq(igid, gid)) {
                        if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
-                               ASSERT(!XFS_IS_PQUOTA_ON(mp));
+                               ASSERT(xfs_sb_version_has_pquotino(&mp->m_sb) ||
+                                      !XFS_IS_PQUOTA_ON(mp));
                                ASSERT(mask & ATTR_GID);
                                ASSERT(gdqp);
                                olddquot2 = xfs_qm_vop_chown(tp, ip,
index b6b669df40f3ab335e75cd3a67903601be0128a4..eae16920655b4569af25e9567682019ba301533d 100644 (file)
@@ -193,7 +193,10 @@ xlog_bread_noalign(
        bp->b_io_length = nbblks;
        bp->b_error = 0;
 
-       xfsbdstrat(log->l_mp, bp);
+       if (XFS_FORCED_SHUTDOWN(log->l_mp))
+               return XFS_ERROR(EIO);
+
+       xfs_buf_iorequest(bp);
        error = xfs_buf_iowait(bp);
        if (error)
                xfs_buf_ioerror_alert(bp, __func__);
@@ -4397,7 +4400,13 @@ xlog_do_recover(
        XFS_BUF_READ(bp);
        XFS_BUF_UNASYNC(bp);
        bp->b_ops = &xfs_sb_buf_ops;
-       xfsbdstrat(log->l_mp, bp);
+
+       if (XFS_FORCED_SHUTDOWN(log->l_mp)) {
+               xfs_buf_relse(bp);
+               return XFS_ERROR(EIO);
+       }
+
+       xfs_buf_iorequest(bp);
        error = xfs_buf_iowait(bp);
        if (error) {
                xfs_buf_ioerror_alert(bp, __func__);
index 14a4996cfec6cb4fbeaa1d3f8432548ebb57d48b..dd88f0e27bd8ce1119d2606c256117d4d2488b9c 100644 (file)
@@ -134,8 +134,6 @@ xfs_qm_dqpurge(
 {
        struct xfs_mount        *mp = dqp->q_mount;
        struct xfs_quotainfo    *qi = mp->m_quotainfo;
-       struct xfs_dquot        *gdqp = NULL;
-       struct xfs_dquot        *pdqp = NULL;
 
        xfs_dqlock(dqp);
        if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -143,21 +141,6 @@ xfs_qm_dqpurge(
                return EAGAIN;
        }
 
-       /*
-        * If this quota has a hint attached, prepare for releasing it now.
-        */
-       gdqp = dqp->q_gdquot;
-       if (gdqp) {
-               xfs_dqlock(gdqp);
-               dqp->q_gdquot = NULL;
-       }
-
-       pdqp = dqp->q_pdquot;
-       if (pdqp) {
-               xfs_dqlock(pdqp);
-               dqp->q_pdquot = NULL;
-       }
-
        dqp->dq_flags |= XFS_DQ_FREEING;
 
        xfs_dqflock(dqp);
@@ -206,11 +189,47 @@ xfs_qm_dqpurge(
        XFS_STATS_DEC(xs_qm_dquot_unused);
 
        xfs_qm_dqdestroy(dqp);
+       return 0;
+}
+
+/*
+ * Release the group or project dquot pointers the user dquots maybe carrying
+ * around as a hint, and proceed to purge the user dquot cache if requested.
+*/
+STATIC int
+xfs_qm_dqpurge_hints(
+       struct xfs_dquot        *dqp,
+       void                    *data)
+{
+       struct xfs_dquot        *gdqp = NULL;
+       struct xfs_dquot        *pdqp = NULL;
+       uint                    flags = *((uint *)data);
+
+       xfs_dqlock(dqp);
+       if (dqp->dq_flags & XFS_DQ_FREEING) {
+               xfs_dqunlock(dqp);
+               return EAGAIN;
+       }
+
+       /* If this quota has a hint attached, prepare for releasing it now */
+       gdqp = dqp->q_gdquot;
+       if (gdqp)
+               dqp->q_gdquot = NULL;
+
+       pdqp = dqp->q_pdquot;
+       if (pdqp)
+               dqp->q_pdquot = NULL;
+
+       xfs_dqunlock(dqp);
 
        if (gdqp)
-               xfs_qm_dqput(gdqp);
+               xfs_qm_dqrele(gdqp);
        if (pdqp)
-               xfs_qm_dqput(pdqp);
+               xfs_qm_dqrele(pdqp);
+
+       if (flags & XFS_QMOPT_UQUOTA)
+               return xfs_qm_dqpurge(dqp, NULL);
+
        return 0;
 }
 
@@ -222,8 +241,18 @@ xfs_qm_dqpurge_all(
        struct xfs_mount        *mp,
        uint                    flags)
 {
-       if (flags & XFS_QMOPT_UQUOTA)
-               xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge, NULL);
+       /*
+        * We have to release group/project dquot hint(s) from the user dquot
+        * at first if they are there, otherwise we would run into an infinite
+        * loop while walking through radix tree to purge other type of dquots
+        * since their refcount is not zero if the user dquot refers to them
+        * as hint.
+        *
+        * Call the special xfs_qm_dqpurge_hints() will end up go through the
+        * general xfs_qm_dqpurge() against user dquot cache if requested.
+        */
+       xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge_hints, &flags);
+
        if (flags & XFS_QMOPT_GQUOTA)
                xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL);
        if (flags & XFS_QMOPT_PQUOTA)
@@ -2082,24 +2111,21 @@ xfs_qm_vop_create_dqattach(
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
-       if (udqp) {
+       if (udqp && XFS_IS_UQUOTA_ON(mp)) {
                ASSERT(ip->i_udquot == NULL);
-               ASSERT(XFS_IS_UQUOTA_ON(mp));
                ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
 
                ip->i_udquot = xfs_qm_dqhold(udqp);
                xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (gdqp) {
+       if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
                ASSERT(ip->i_gdquot == NULL);
-               ASSERT(XFS_IS_GQUOTA_ON(mp));
                ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
                ip->i_gdquot = xfs_qm_dqhold(gdqp);
                xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (pdqp) {
+       if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
                ASSERT(ip->i_pdquot == NULL);
-               ASSERT(XFS_IS_PQUOTA_ON(mp));
                ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
 
                ip->i_pdquot = xfs_qm_dqhold(pdqp);
index c035d11b7734196c4fd689121d945e598a8d6d7a..647b6f1d8923fee484ada5eea3e2e68d47df8286 100644 (file)
@@ -314,7 +314,18 @@ xfs_trans_read_buf_map(
                        ASSERT(bp->b_iodone == NULL);
                        XFS_BUF_READ(bp);
                        bp->b_ops = ops;
-                       xfsbdstrat(tp->t_mountp, bp);
+
+                       /*
+                        * XXX(hch): clean up the error handling here to be less
+                        * of a mess..
+                        */
+                       if (XFS_FORCED_SHUTDOWN(mp)) {
+                               trace_xfs_bdstrat_shut(bp, _RET_IP_);
+                               xfs_bioerror_relse(bp);
+                       } else {
+                               xfs_buf_iorequest(bp);
+                       }
+
                        error = xfs_buf_iowait(bp);
                        if (error) {
                                xfs_buf_ioerror_alert(bp, __func__);
index c602c7718421ded2f2bbe50f1e76edc39ac2b6f2..ddabed1f51c22227df9fdc1a7d050ca3b395b470 100644 (file)
@@ -169,7 +169,8 @@ struct acpi_device_flags {
        u32 ejectable:1;
        u32 power_manageable:1;
        u32 match_driver:1;
-       u32 reserved:27;
+       u32 no_hotplug:1;
+       u32 reserved:26;
 };
 
 /* File System */
@@ -344,6 +345,7 @@ extern struct kobject *acpi_kobj;
 extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
 void acpi_bus_private_data_handler(acpi_handle, void *);
 int acpi_bus_get_private_data(acpi_handle, void **);
+void acpi_bus_no_hotplug(acpi_handle handle);
 extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
 extern int register_acpi_notifier(struct notifier_block *);
 extern int unregister_acpi_notifier(struct notifier_block *);
index f330d28e4d0eaf4d8e681bb905f52ff72465bea7..db09234589409760b91cb9e696472a3e828476f9 100644 (file)
@@ -217,7 +217,7 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #endif
 
 #ifndef pte_accessible
-# define pte_accessible(pte)           ((void)(pte),1)
+# define pte_accessible(mm, pte)       ((void)(pte), 1)
 #endif
 
 #ifndef flush_tlb_fix_spurious_fault
@@ -599,11 +599,10 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
        barrier();
 #endif
-       if (pmd_none(pmdval))
+       if (pmd_none(pmdval) || pmd_trans_huge(pmdval))
                return 1;
        if (unlikely(pmd_bad(pmdval))) {
-               if (!pmd_trans_huge(pmdval))
-                       pmd_clear_bad(pmd);
+               pmd_clear_bad(pmd);
                return 1;
        }
        return 0;
index ddf2b420ac8f81621ec9dd088e8379f8b686cd94..1cd3f5d767a81b18b8c3950701506e3f8bfcfc6c 100644 (file)
@@ -3,13 +3,11 @@
 
 #include <linux/thread_info.h>
 
-/*
- * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
- * that think a non-zero value indicates we cannot preempt.
- */
+#define PREEMPT_ENABLED        (0)
+
 static __always_inline int preempt_count(void)
 {
-       return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED;
+       return current_thread_info()->preempt_count;
 }
 
 static __always_inline int *preempt_count_ptr(void)
@@ -17,11 +15,6 @@ static __always_inline int *preempt_count_ptr(void)
        return &current_thread_info()->preempt_count;
 }
 
-/*
- * We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the
- * alternative is loosing a reschedule. Better schedule too often -- also this
- * should be a very rare operation.
- */
 static __always_inline void preempt_count_set(int pc)
 {
        *preempt_count_ptr() = pc;
@@ -41,28 +34,17 @@ static __always_inline void preempt_count_set(int pc)
        task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \
 } while (0)
 
-/*
- * We fold the NEED_RESCHED bit into the preempt count such that
- * preempt_enable() can decrement and test for needing to reschedule with a
- * single instruction.
- *
- * We invert the actual bit, so that when the decrement hits 0 we know we both
- * need to resched (the bit is cleared) and can resched (no preempt count).
- */
-
 static __always_inline void set_preempt_need_resched(void)
 {
-       *preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED;
 }
 
 static __always_inline void clear_preempt_need_resched(void)
 {
-       *preempt_count_ptr() |= PREEMPT_NEED_RESCHED;
 }
 
 static __always_inline bool test_preempt_need_resched(void)
 {
-       return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED);
+       return false;
 }
 
 /*
@@ -81,7 +63,12 @@ static __always_inline void __preempt_count_sub(int val)
 
 static __always_inline bool __preempt_count_dec_and_test(void)
 {
-       return !--*preempt_count_ptr();
+       /*
+        * Because of load-store architectures cannot do per-cpu atomic
+        * operations; we cannot use PREEMPT_NEED_RESCHED because it might get
+        * lost.
+        */
+       return !--*preempt_count_ptr() && tif_need_resched();
 }
 
 /*
@@ -89,7 +76,7 @@ static __always_inline bool __preempt_count_dec_and_test(void)
  */
 static __always_inline bool should_resched(void)
 {
-       return unlikely(!*preempt_count_ptr());
+       return unlikely(!preempt_count() && tif_need_resched());
 }
 
 #ifdef CONFIG_PREEMPT
index 1d4a920ef7ff4ffea56470ef24c2e6cf8a7b0696..04086c5be930e2941f8be91cb0a47107da73ad08 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 #if defined(__alpha__) || defined(__powerpc__)
 #include <asm/pgtable.h>       /* For pte_wrprotect */
 #endif
@@ -136,7 +137,6 @@ int drm_err(const char *func, const char *format, ...);
 
 /* driver capabilities and requirements mask */
 #define DRIVER_USE_AGP     0x1
-#define DRIVER_REQUIRE_AGP 0x2
 #define DRIVER_PCI_DMA     0x8
 #define DRIVER_SG          0x10
 #define DRIVER_HAVE_DMA    0x20
@@ -180,6 +180,22 @@ int drm_err(const char *func, const char *format, ...);
 #define DRM_ERROR(fmt, ...)                            \
        drm_err(__func__, fmt, ##__VA_ARGS__)
 
+/**
+ * Rate limited error output.  Like DRM_ERROR() but won't flood the log.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#define DRM_ERROR_RATELIMITED(fmt, ...)                                \
+({                                                                     \
+       static DEFINE_RATELIMIT_STATE(_rs,                              \
+                                     DEFAULT_RATELIMIT_INTERVAL,       \
+                                     DEFAULT_RATELIMIT_BURST);         \
+                                                                       \
+       if (__ratelimit(&_rs))                                          \
+               drm_err(__func__, fmt, ##__VA_ARGS__);                  \
+})
+
 #define DRM_INFO(fmt, ...)                             \
        printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__)
 
@@ -422,7 +438,6 @@ struct drm_file {
        struct pid *pid;
        kuid_t uid;
        drm_magic_t magic;
-       unsigned long ioctl_count;
        struct list_head lhead;
        struct drm_minor *minor;
        unsigned long lock_count;
@@ -511,7 +526,7 @@ struct drm_device_dma {
  */
 struct drm_agp_mem {
        unsigned long handle;           /**< handle */
-       DRM_AGP_MEM *memory;
+       struct agp_memory *memory;
        unsigned long bound;            /**< address */
        int pages;
        struct list_head head;
@@ -523,7 +538,7 @@ struct drm_agp_mem {
  * \sa drm_agp_init() and drm_device::agp.
  */
 struct drm_agp_head {
-       DRM_AGP_KERN agp_info;          /**< AGP device information */
+       struct agp_kern_info agp_info;          /**< AGP device information */
        struct list_head memory;
        unsigned long mode;             /**< AGP mode */
        struct agp_bridge_data *bridge;
@@ -606,13 +621,6 @@ struct drm_ati_pcigart_info {
        int table_size;
 };
 
-/**
- * GEM specific mm private for tracking GEM objects
- */
-struct drm_gem_mm {
-       struct drm_vma_offset_manager vma_manager;
-};
-
 /**
  * This structure defines the drm_mm memory object, which will be used by the
  * DRM for its buffer objects.
@@ -750,10 +758,6 @@ struct drm_bus {
        int (*set_unique)(struct drm_device *dev, struct drm_master *master,
                          struct drm_unique *unique);
        int (*irq_by_busid)(struct drm_device *dev, struct drm_irq_busid *p);
-       /* hooks that are for PCI */
-       int (*agp_init)(struct drm_device *dev);
-       void (*agp_destroy)(struct drm_device *dev);
-
 };
 
 /**
@@ -841,6 +845,7 @@ struct drm_driver {
         *
         * \param dev  DRM device.
         * \param crtc Id of the crtc to query.
+        * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
         * \param *vpos Target location for current vertical scanout position.
         * \param *hpos Target location for current horizontal scanout position.
         * \param *stime Target location for timestamp taken immediately before
@@ -863,6 +868,7 @@ struct drm_driver {
         *
         */
        int (*get_scanout_position) (struct drm_device *dev, int crtc,
+                                    unsigned int flags,
                                     int *vpos, int *hpos, ktime_t *stime,
                                     ktime_t *etime);
 
@@ -903,7 +909,7 @@ struct drm_driver {
 
        /* these have to be filled in */
 
-       irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+       irqreturn_t(*irq_handler) (int irq, void *arg);
        void (*irq_preinstall) (struct drm_device *dev);
        int (*irq_postinstall) (struct drm_device *dev);
        void (*irq_uninstall) (struct drm_device *dev);
@@ -995,8 +1001,8 @@ struct drm_driver {
        } kdriver;
        struct drm_bus *bus;
 
-       /* List of devices hanging off this driver */
-       struct list_head device_list;
+       /* List of devices hanging off this driver with stealth attach. */
+       struct list_head legacy_dev_list;
 };
 
 #define DRM_MINOR_UNASSIGNED 0
@@ -1085,7 +1091,7 @@ struct drm_vblank_crtc {
  * may contain multiple heads.
  */
 struct drm_device {
-       struct list_head driver_item;   /**< list of devices per driver */
+       struct list_head legacy_dev_list;/**< list of devices per driver for stealth attach cleanup */
        char *devname;                  /**< For /proc/interrupts */
        int if_version;                 /**< Highest interface version set */
 
@@ -1098,8 +1104,6 @@ struct drm_device {
        /** \name Usage Counters */
        /*@{ */
        int open_count;                 /**< Outstanding files open */
-       atomic_t ioctl_count;           /**< Outstanding IOCTLs pending */
-       atomic_t vma_count;             /**< Outstanding vma areas open */
        int buf_use;                    /**< Buffers in use -- cannot alloc */
        atomic_t buf_alloc;             /**< Buffer allocation in progress */
        /*@} */
@@ -1176,7 +1180,6 @@ struct drm_device {
        struct drm_sg_mem *sg;  /**< Scatter gather memory */
        unsigned int num_crtcs;                  /**< Number of CRTCs on this device */
        void *dev_private;              /**< device private data */
-       void *mm_private;
        struct address_space *dev_mapping;
        struct drm_sigdata sigdata;        /**< For block_all_signals */
        sigset_t sigmask;
@@ -1194,6 +1197,7 @@ struct drm_device {
        /*@{ */
        struct mutex object_name_lock;
        struct idr object_name_idr;
+       struct drm_vma_offset_manager *vma_offset_manager;
        /*@} */
        int switch_power_state;
 
@@ -1268,6 +1272,7 @@ extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
                                /* Memory management support (drm_memory.h) */
 #include <drm/drm_memory.h>
 
+
                                /* Misc. IOCTL support (drm_ioctl.h) */
 extern int drm_irq_by_busid(struct drm_device *dev, void *data,
                            struct drm_file *file_priv);
@@ -1398,8 +1403,10 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
                                                 int crtc, int *max_error,
                                                 struct timeval *vblank_time,
                                                 unsigned flags,
-                                                struct drm_crtc *refcrtc);
-extern void drm_calc_timestamping_constants(struct drm_crtc *crtc);
+                                                const struct drm_crtc *refcrtc,
+                                                const struct drm_display_mode *mode);
+extern void drm_calc_timestamping_constants(struct drm_crtc *crtc,
+                                           const struct drm_display_mode *mode);
 
 extern bool
 drm_mode_parse_command_line_for_connector(const char *mode_option,
@@ -1461,6 +1468,30 @@ extern int drm_debugfs_create_files(const struct drm_info_list *files,
 extern int drm_debugfs_remove_files(const struct drm_info_list *files,
                                    int count, struct drm_minor *minor);
 extern int drm_debugfs_cleanup(struct drm_minor *minor);
+#else
+static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id,
+                                  struct dentry *root)
+{
+       return 0;
+}
+
+static inline int drm_debugfs_create_files(const struct drm_info_list *files,
+                                          int count, struct dentry *root,
+                                          struct drm_minor *minor)
+{
+       return 0;
+}
+
+static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
+                                          int count, struct drm_minor *minor)
+{
+       return 0;
+}
+
+static inline int drm_debugfs_cleanup(struct drm_minor *minor)
+{
+       return 0;
+}
 #endif
 
                                /* Info file support */
@@ -1645,6 +1676,7 @@ static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
 
        return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
+void drm_pci_agp_destroy(struct drm_device *dev);
 
 extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
 extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
@@ -1660,7 +1692,6 @@ extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
 
 /* platform section */
 extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device);
-extern void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device);
 
 /* returns true if currently okay to sleep */
 static __inline__ bool drm_can_sleep(void)
index a184eeee9c96bfb4afc4a1bc8b173a0a71fa1225..86a02188074bcec037714fdb1ea293dfb4ae3ebe 100644 (file)
 
 #if __OS_HAS_AGP
 
-void drm_free_agp(DRM_AGP_MEM * handle, int pages);
-int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
-int drm_unbind_agp(DRM_AGP_MEM * handle);
-DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+void drm_free_agp(struct agp_memory * handle, int pages);
+int drm_bind_agp(struct agp_memory * handle, unsigned int start);
+int drm_unbind_agp(struct agp_memory * handle);
+struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,
                                struct page **pages,
                                unsigned long num_pages,
                                uint32_t gtt_offset,
                                uint32_t type);
 
 struct drm_agp_head *drm_agp_init(struct drm_device *dev);
-void drm_agp_destroy(struct drm_agp_head *agp);
 void drm_agp_clear(struct drm_device *dev);
 int drm_agp_acquire(struct drm_device *dev);
 int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
@@ -46,29 +45,23 @@ int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
 int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
 int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv);
-
-static inline int drm_core_has_AGP(struct drm_device *dev)
-{
-       return drm_core_check_feature(dev, DRIVER_USE_AGP);
-}
-
 #else /* __OS_HAS_AGP */
 
-static inline void drm_free_agp(DRM_AGP_MEM * handle, int pages)
+static inline void drm_free_agp(struct agp_memory * handle, int pages)
 {
 }
 
-static inline int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
+static inline int drm_bind_agp(struct agp_memory * handle, unsigned int start)
 {
        return -ENODEV;
 }
 
-static inline int drm_unbind_agp(DRM_AGP_MEM * handle)
+static inline int drm_unbind_agp(struct agp_memory * handle)
 {
        return -ENODEV;
 }
 
-static inline DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+static inline struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,
                                              struct page **pages,
                                              unsigned long num_pages,
                                              uint32_t gtt_offset,
@@ -82,10 +75,6 @@ static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev)
        return NULL;
 }
 
-static inline void drm_agp_destroy(struct drm_agp_head *agp)
-{
-}
-
 static inline void drm_agp_clear(struct drm_device *dev)
 {
 }
@@ -183,12 +172,6 @@ static inline int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
 {
        return -ENODEV;
 }
-
-static inline int drm_core_has_AGP(struct drm_device *dev)
-{
-       return 0;
-}
-
 #endif /* __OS_HAS_AGP */
 
 #endif /* _DRM_AGPSUPPORT_H_ */
index b3865a0e39f4570ebda09c3aabeaf9306d235f96..71727b6210ae57d5b064be1cab19a4dc660df6f8 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/idr.h>
 #include <linux/fb.h>
+#include <linux/hdmi.h>
 #include <drm/drm_mode.h>
 
 #include <drm/drm_fourcc.h>
@@ -181,6 +182,7 @@ struct drm_display_mode {
 
        int vrefresh;           /* in Hz */
        int hsync;              /* in kHz */
+       enum hdmi_picture_aspect picture_aspect_ratio;
 };
 
 static inline bool drm_mode_is_stereo(const struct drm_display_mode *mode)
@@ -447,7 +449,7 @@ struct drm_crtc {
        uint16_t *gamma_store;
 
        /* Constants needed for precise vblank and swap timestamping. */
-       s64 framedur_ns, linedur_ns, pixeldur_ns;
+       int framedur_ns, linedur_ns, pixeldur_ns;
 
        /* if you are using the helper */
        void *helper_private;
index ef6ad3a8e58e517f31624767fb1751f7ada463c5..b1388b5fe7acd7d597f6345f273ce26de61d7535 100644 (file)
@@ -120,8 +120,8 @@ struct drm_encoder_helper_funcs {
  */
 struct drm_connector_helper_funcs {
        int (*get_modes)(struct drm_connector *connector);
-       int (*mode_valid)(struct drm_connector *connector,
-                         struct drm_display_mode *mode);
+       enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
+                                          struct drm_display_mode *mode);
        struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
 };
 
index a92c3754e3bbffe56c286d85bd2212f753ebe2c3..1d09050a8c001749ba26087581b93cb2de1f9153 100644 (file)
  * 1.2 formally includes both eDP and DPI definitions.
  */
 
-#define AUX_NATIVE_WRITE       0x8
-#define AUX_NATIVE_READ                0x9
-#define AUX_I2C_WRITE          0x0
-#define AUX_I2C_READ           0x1
-#define AUX_I2C_STATUS         0x2
-#define AUX_I2C_MOT            0x4
-
-#define AUX_NATIVE_REPLY_ACK   (0x0 << 4)
-#define AUX_NATIVE_REPLY_NACK  (0x1 << 4)
-#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
-#define AUX_NATIVE_REPLY_MASK  (0x3 << 4)
-
-#define AUX_I2C_REPLY_ACK      (0x0 << 6)
-#define AUX_I2C_REPLY_NACK     (0x1 << 6)
-#define AUX_I2C_REPLY_DEFER    (0x2 << 6)
-#define AUX_I2C_REPLY_MASK     (0x3 << 6)
+#define DP_AUX_I2C_WRITE               0x0
+#define DP_AUX_I2C_READ                        0x1
+#define DP_AUX_I2C_STATUS              0x2
+#define DP_AUX_I2C_MOT                 0x4
+#define DP_AUX_NATIVE_WRITE            0x8
+#define DP_AUX_NATIVE_READ             0x9
+
+#define DP_AUX_NATIVE_REPLY_ACK                (0x0 << 0)
+#define DP_AUX_NATIVE_REPLY_NACK       (0x1 << 0)
+#define DP_AUX_NATIVE_REPLY_DEFER      (0x2 << 0)
+#define DP_AUX_NATIVE_REPLY_MASK       (0x3 << 0)
+
+#define DP_AUX_I2C_REPLY_ACK           (0x0 << 2)
+#define DP_AUX_I2C_REPLY_NACK          (0x1 << 2)
+#define DP_AUX_I2C_REPLY_DEFER         (0x2 << 2)
+#define DP_AUX_I2C_REPLY_MASK          (0x3 << 2)
 
 /* AUX CH addresses */
 /* DPCD */
 
 #define DP_TEST_REQUEST                            0x218
 # define DP_TEST_LINK_TRAINING             (1 << 0)
-# define DP_TEST_LINK_PATTERN              (1 << 1)
+# define DP_TEST_LINK_VIDEO_PATTERN        (1 << 1)
 # define DP_TEST_LINK_EDID_READ                    (1 << 2)
 # define DP_TEST_LINK_PHY_TEST_PATTERN     (1 << 3) /* DPCD >= 1.1 */
+# define DP_TEST_LINK_FAUX_PATTERN         (1 << 4) /* DPCD >= 1.2 */
 
 #define DP_TEST_LINK_RATE                  0x219
 # define DP_LINK_RATE_162                  (0x6)
index 815fafc6b4adb2f0acc7f4474351b6e56d30cef5..86ab99bc0ac50e560b5f31c55fd3f91231607244 100644 (file)
@@ -21,7 +21,6 @@ static inline void writeq(u64 val, void __iomem *reg)
 
 /** Current process ID */
 #define DRM_CURRENTPID                 task_pid_nr(current)
-#define DRM_SUSER(p)                   capable(CAP_SYS_ADMIN)
 #define DRM_UDELAY(d)                  udelay(d)
 /** Read a byte from a MMIO region */
 #define DRM_READ8(map, offset)         readb(((void __iomem *)(map)->handle) + (offset))
@@ -35,45 +34,12 @@ static inline void writeq(u64 val, void __iomem *reg)
 #define DRM_WRITE16(map, offset, val)   writew(val, ((void __iomem *)(map)->handle) + (offset))
 /** Write a dword into a MMIO region */
 #define DRM_WRITE32(map, offset, val)  writel(val, ((void __iomem *)(map)->handle) + (offset))
-/** Read memory barrier */
 
 /** Read a qword from a MMIO region - be careful using these unless you really understand them */
 #define DRM_READ64(map, offset)                readq(((void __iomem *)(map)->handle) + (offset))
 /** Write a qword into a MMIO region */
 #define DRM_WRITE64(map, offset, val)  writeq(val, ((void __iomem *)(map)->handle) + (offset))
 
-#define DRM_READMEMORYBARRIER()                rmb()
-/** Write memory barrier */
-#define DRM_WRITEMEMORYBARRIER()       wmb()
-/** Read/write memory barrier */
-#define DRM_MEMORYBARRIER()            mb()
-
-/** IRQ handler arguments and return type and values */
-#define DRM_IRQ_ARGS           int irq, void *arg
-
-/** AGP types */
-#if __OS_HAS_AGP
-#define DRM_AGP_MEM            struct agp_memory
-#define DRM_AGP_KERN           struct agp_kern_info
-#else
-/* define some dummy types for non AGP supporting kernels */
-struct no_agp_kern {
-       unsigned long aper_base;
-       unsigned long aper_size;
-};
-#define DRM_AGP_MEM             int
-#define DRM_AGP_KERN            struct no_agp_kern
-#endif
-
-/** Other copying of data to kernel space */
-#define DRM_COPY_FROM_USER(arg1, arg2, arg3)           \
-       copy_from_user(arg1, arg2, arg3)
-/** Other copying of data from kernel space */
-#define DRM_COPY_TO_USER(arg1, arg2, arg3)             \
-       copy_to_user(arg1, arg2, arg3)
-
-#define DRM_HZ HZ
-
 #define DRM_WAIT_ON( ret, queue, timeout, condition )          \
 do {                                                           \
        DECLARE_WAITQUEUE(entry, current);                      \
@@ -97,6 +63,3 @@ do {                                                          \
        __set_current_state(TASK_RUNNING);                      \
        remove_wait_queue(&(queue), &entry);                    \
 } while (0)
-
-#define DRM_WAKEUP( queue ) wake_up( queue )
-#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
index 87578c109e4869bbecf5cce3a7530a0c2fb80637..49376aec2fbb8a9e054b9605fd9de36e4cd39c5f 100644 (file)
        {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-       {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
+       {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
index 8639c85d61c400f4694e99ca7e1282df23f5ef66..32d34ebf0706fa8f73e793b035816fd7cfaa36a3 100644 (file)
@@ -681,6 +681,15 @@ extern int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement);
 extern int ttm_tt_swapout(struct ttm_tt *ttm,
                          struct file *persistent_swap_storage);
 
+/**
+ * ttm_tt_unpopulate - free pages from a ttm
+ *
+ * @ttm: Pointer to the ttm_tt structure
+ *
+ * Calls the driver method to free all pages from a ttm
+ */
+extern void ttm_tt_unpopulate(struct ttm_tt *ttm);
+
 /*
  * ttm_bo.c
  */
index 58b029894eb33ea32dff2ba2977546c097f2b533..0097cc03034e18b10e5ad9cdc34b9019eb821314 100644 (file)
@@ -190,13 +190,25 @@ extern int ttm_base_object_init(struct ttm_object_file *tfile,
  * @key: Hash key
  *
  * Looks up a struct ttm_base_object with the key @key.
- * Also verifies that the object is visible to the application, by
- * comparing the @tfile argument and checking the object shareable flag.
  */
 
 extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
                                                      *tfile, uint32_t key);
 
+/**
+ * ttm_base_object_lookup_for_ref
+ *
+ * @tdev: Pointer to a struct ttm_object_device.
+ * @key: Hash key
+ *
+ * Looks up a struct ttm_base_object with the key @key.
+ * This function should only be used when the struct tfile associated with the
+ * caller doesn't yet have a reference to the base object.
+ */
+
+extern struct ttm_base_object *
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key);
+
 /**
  * ttm_base_object_unref
  *
@@ -218,6 +230,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base);
  * @existed: Upon completion, indicates that an identical reference object
  * already existed, and the refcount was upped on that object instead.
  *
+ * Checks that the base object is shareable and adds a ref object to it.
+ *
  * Adding a ref object to a base object is basically like referencing the
  * base object, but a user-space application holds the reference. When the
  * file corresponding to @tfile is closed, all its reference objects are
index 669fef5c745a3fe98145a87d21a588cb64835c15..3e0fbe44176328193cf849fd039d70e91694a4ca 100644 (file)
@@ -3,6 +3,6 @@
 
 #include <uapi/linux/auxvec.h>
 
-#define AT_VECTOR_SIZE_BASE 19 /* NEW_AUX_ENT entries in auxiliary table */
+#define AT_VECTOR_SIZE_BASE 20 /* NEW_AUX_ENT entries in auxiliary table */
   /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */
 #endif /* _LINUX_AUXVEC_H */
index fe68a5a985831eca65d3880fb69094fbb91dbde0..7032518f85424bb081d9f6a713fec67d45873d77 100644 (file)
@@ -6,6 +6,8 @@
 #include <linux/proc_fs.h>
 #include <linux/elf.h>
 
+#include <asm/pgtable.h> /* for pgprot_t */
+
 #define ELFCORE_ADDR_MAX       (-1ULL)
 #define ELFCORE_ADDR_ERR       (-2ULL)
 
index 70c4836e4a9f8fb16dd578bbbcfa25ecfec0b129..fe6ac956550e4e099a04889e9b33bf0f9a917c2e 100644 (file)
@@ -613,8 +613,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(struct fb_info *fb_info);
 extern int unlink_framebuffer(struct fb_info *fb_info);
-extern void remove_conflicting_framebuffers(struct apertures_struct *a,
-                               const char *name, bool primary);
+extern int remove_conflicting_framebuffers(struct apertures_struct *a,
+                                          const char *name, bool primary);
 extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
 extern int fb_show_logo(struct fb_info *fb_info, int rotate);
 extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
index eff50e062be850189ed9e78a9b6058a5eea49b74..d9c8dbd3373f90d298ac66001ccdd13fa6f54ddf 100644 (file)
@@ -445,7 +445,7 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data)
 static inline struct i2c_adapter *
 i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
 {
-#if IS_ENABLED(I2C_MUX)
+#if IS_ENABLED(CONFIG_I2C_MUX)
        struct device *parent = adapter->dev.parent;
 
        if (parent != NULL && parent->type == &i2c_adapter_type)
index 0e23c26485f457cf2380818a18b00c1175bc02ae..9b503376738fac8e25e9fa71b286b4c341295d76 100644 (file)
@@ -418,6 +418,7 @@ enum {
        ATA_HORKAGE_DUMP_ID     = (1 << 16),    /* dump IDENTIFY data */
        ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),  /* Set max sects to 65535 */
        ATA_HORKAGE_ATAPI_DMADIR = (1 << 18),   /* device requires dmadir */
+       ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19),    /* don't use queued TRIM */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
index c8929c3832db26d00d80f96e524afbb0e75c4df1..4bfde0e99ed5169d7220204c39070faa387f57ab 100644 (file)
@@ -19,7 +19,7 @@
 
 #define USE_CMPXCHG_LOCKREF \
        (IS_ENABLED(CONFIG_ARCH_USE_CMPXCHG_LOCKREF) && \
-        IS_ENABLED(CONFIG_SMP) && !BLOATED_SPINLOCKS)
+        IS_ENABLED(CONFIG_SMP) && SPINLOCK_SIZE <= 4)
 
 struct lockref {
        union {
index 69ed5f5e9f6e4a83f8c9226cb92d6ba7eafa17bd..c45c089bfdaca9a91f32832102ff32291444884f 100644 (file)
@@ -133,4 +133,34 @@ __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
        return ret;
 }
 
+#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+       return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u32_shr */
+
+#else
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+       u32 ah, al;
+       u64 ret;
+
+       al = a;
+       ah = a >> 32;
+
+       ret = ((u64)al * mul) >> shift;
+       if (ah)
+               ret += ((u64)ah * mul) << (32 - shift);
+
+       return ret;
+}
+#endif /* mul_u64_u32_shr */
+
+#endif
+
 #endif /* _LINUX_MATH64_H */
index f5096b58b20d3ef64618e18ca37e1083b97af252..f015c059e159f1f8cad2da7b88dd26cdcbfd637d 100644 (file)
@@ -55,7 +55,8 @@ extern int migrate_huge_page_move_mapping(struct address_space *mapping,
                                  struct page *newpage, struct page *page);
 extern int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode);
+               struct buffer_head *head, enum migrate_mode mode,
+               int extra_count);
 #else
 
 static inline void putback_lru_pages(struct list_head *l) {}
@@ -90,10 +91,19 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
 #endif /* CONFIG_MIGRATION */
 
 #ifdef CONFIG_NUMA_BALANCING
+extern bool pmd_trans_migrating(pmd_t pmd);
+extern void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd);
 extern int migrate_misplaced_page(struct page *page,
                                  struct vm_area_struct *vma, int node);
 extern bool migrate_ratelimited(int node);
 #else
+static inline bool pmd_trans_migrating(pmd_t pmd)
+{
+       return false;
+}
+static inline void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd)
+{
+}
 static inline int migrate_misplaced_page(struct page *page,
                                         struct vm_area_struct *vma, int node)
 {
index 1cedd000cf293f4486575b87086b01e2ee1b26e5..35527173cf50c71baeba5f549007c5903bc8ea06 100644 (file)
@@ -1317,7 +1317,7 @@ static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long a
 #endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
 
 #if USE_SPLIT_PTE_PTLOCKS
-#if BLOATED_SPINLOCKS
+#if ALLOC_SPLIT_PTLOCKS
 extern bool ptlock_alloc(struct page *page);
 extern void ptlock_free(struct page *page);
 
@@ -1325,7 +1325,7 @@ static inline spinlock_t *ptlock_ptr(struct page *page)
 {
        return page->ptl;
 }
-#else /* BLOATED_SPINLOCKS */
+#else /* ALLOC_SPLIT_PTLOCKS */
 static inline bool ptlock_alloc(struct page *page)
 {
        return true;
@@ -1339,7 +1339,7 @@ static inline spinlock_t *ptlock_ptr(struct page *page)
 {
        return &page->ptl;
 }
-#endif /* BLOATED_SPINLOCKS */
+#endif /* ALLOC_SPLIT_PTLOCKS */
 
 static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd)
 {
index bd299418a934e21b99c303af82a7c2f427bbf915..290901a8c1de9f0193ae3e2c640c070623431081 100644 (file)
@@ -26,6 +26,7 @@ struct address_space;
 #define USE_SPLIT_PTE_PTLOCKS  (NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
 #define USE_SPLIT_PMD_PTLOCKS  (USE_SPLIT_PTE_PTLOCKS && \
                IS_ENABLED(CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK))
+#define ALLOC_SPLIT_PTLOCKS    (SPINLOCK_SIZE > BITS_PER_LONG/8)
 
 /*
  * Each physical page in the system has a struct page associated with
@@ -155,7 +156,7 @@ struct page {
                                                 * system if PG_buddy is set.
                                                 */
 #if USE_SPLIT_PTE_PTLOCKS
-#if BLOATED_SPINLOCKS
+#if ALLOC_SPLIT_PTLOCKS
                spinlock_t *ptl;
 #else
                spinlock_t ptl;
@@ -442,6 +443,14 @@ struct mm_struct {
 
        /* numa_scan_seq prevents two threads setting pte_numa */
        int numa_scan_seq;
+#endif
+#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
+       /*
+        * An operation with batched TLB flushing is going on. Anything that
+        * can move process memory needs to flush the TLB when moving a
+        * PROT_NONE or PROT_NUMA mapped page.
+        */
+       bool tlb_flush_pending;
 #endif
        struct uprobes_state uprobes_state;
 };
@@ -459,4 +468,45 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm)
        return mm->cpu_vm_mask_var;
 }
 
+#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
+/*
+ * Memory barriers to keep this state in sync are graciously provided by
+ * the page table locks, outside of which no page table modifications happen.
+ * The barriers below prevent the compiler from re-ordering the instructions
+ * around the memory barriers that are already present in the code.
+ */
+static inline bool mm_tlb_flush_pending(struct mm_struct *mm)
+{
+       barrier();
+       return mm->tlb_flush_pending;
+}
+static inline void set_tlb_flush_pending(struct mm_struct *mm)
+{
+       mm->tlb_flush_pending = true;
+
+       /*
+        * Guarantee that the tlb_flush_pending store does not leak into the
+        * critical section updating the page tables
+        */
+       smp_mb__before_spinlock();
+}
+/* Clearing is done after a TLB flush, which also provides a barrier. */
+static inline void clear_tlb_flush_pending(struct mm_struct *mm)
+{
+       barrier();
+       mm->tlb_flush_pending = false;
+}
+#else
+static inline bool mm_tlb_flush_pending(struct mm_struct *mm)
+{
+       return false;
+}
+static inline void set_tlb_flush_pending(struct mm_struct *mm)
+{
+}
+static inline void clear_tlb_flush_pending(struct mm_struct *mm)
+{
+}
+#endif
+
 #endif /* _LINUX_MM_TYPES_H */
index d9a550bf3e8e8a770c4198bf96bb2b81e34a3b6e..ce2a1f5f9a1e0226d933d28606823239e4467526 100644 (file)
@@ -769,7 +769,8 @@ struct netdev_phys_port_id {
  *        (can also return NETDEV_TX_LOCKED iff NETIF_F_LLTX)
  *     Required can not be NULL.
  *
- * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb);
+ * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
+ *                         void *accel_priv);
  *     Called to decide which queue to when device supports multiple
  *     transmit queues.
  *
@@ -990,7 +991,8 @@ struct net_device_ops {
        netdev_tx_t             (*ndo_start_xmit) (struct sk_buff *skb,
                                                   struct net_device *dev);
        u16                     (*ndo_select_queue)(struct net_device *dev,
-                                                   struct sk_buff *skb);
+                                                   struct sk_buff *skb,
+                                                   void *accel_priv);
        void                    (*ndo_change_rx_flags)(struct net_device *dev,
                                                       int flags);
        void                    (*ndo_set_rx_mode)(struct net_device *dev);
@@ -1529,7 +1531,8 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
 }
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
-                                   struct sk_buff *skb);
+                                   struct sk_buff *skb,
+                                   void *accel_priv);
 u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
 
 /*
@@ -1819,6 +1822,7 @@ int dev_close(struct net_device *dev);
 void dev_disable_lro(struct net_device *dev);
 int dev_loopback_xmit(struct sk_buff *newskb);
 int dev_queue_xmit(struct sk_buff *skb);
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv);
 int register_netdevice(struct net_device *dev);
 void unregister_netdevice_queue(struct net_device *dev, struct list_head *head);
 void unregister_netdevice_many(struct list_head *head);
@@ -1912,6 +1916,15 @@ static inline int dev_parse_header(const struct sk_buff *skb,
        return dev->header_ops->parse(skb, haddr);
 }
 
+static inline int dev_rebuild_header(struct sk_buff *skb)
+{
+       const struct net_device *dev = skb->dev;
+
+       if (!dev->header_ops || !dev->header_ops->rebuild)
+               return 0;
+       return dev->header_ops->rebuild(skb);
+}
+
 typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
 int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
 static inline int unregister_gifconf(unsigned int family)
@@ -2417,7 +2430,7 @@ int dev_change_carrier(struct net_device *, bool new_carrier);
 int dev_get_phys_port_id(struct net_device *dev,
                         struct netdev_phys_port_id *ppid);
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv);
+                       struct netdev_queue *txq);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 
 extern int             netdev_budget;
@@ -3008,6 +3021,19 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
        dev->gso_max_size = size;
 }
 
+static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
+                                       int pulled_hlen, u16 mac_offset,
+                                       int mac_len)
+{
+       skb->protocol = protocol;
+       skb->encapsulation = 1;
+       skb_push(skb, pulled_hlen);
+       skb_reset_transport_header(skb);
+       skb->mac_header = mac_offset;
+       skb->network_header = skb->mac_header + mac_len;
+       skb->mac_len = mac_len;
+}
+
 static inline bool netif_is_macvlan(struct net_device *dev)
 {
        return dev->priv_flags & IFF_MACVLAN;
index 57e890abe1f09220c777b5403c782cd6792872d6..a5fc7d01aad61049164f920f90a6f20df1cbc22d 100644 (file)
@@ -69,6 +69,7 @@
        __PCPU_DUMMY_ATTRS char __pcpu_scope_##name;                    \
        extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;            \
        __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;                   \
+       extern __PCPU_ATTRS(sec) __typeof__(type) name;                 \
        __PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak                 \
        __typeof__(type) name
 #else
index abd437d0a8a7eeac72297ad5306ca071993d8f58..ece0c6bbfcc5617f394092ec027f39ce3abc629d 100644 (file)
@@ -51,6 +51,7 @@ struct pstore_info {
        char            *buf;
        size_t          bufsize;
        struct mutex    read_mutex;     /* serialize open/read/close */
+       int             flags;
        int             (*open)(struct pstore_info *psi);
        int             (*close)(struct pstore_info *psi);
        ssize_t         (*read)(u64 *id, enum pstore_type_id *type,
@@ -70,6 +71,8 @@ struct pstore_info {
        void            *data;
 };
 
+#define        PSTORE_FLAGS_FRAGILE    1
+
 #ifdef CONFIG_PSTORE
 extern int pstore_register(struct pstore_info *);
 extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
index 8e00f9f6f96395b3e209192259b6af58f7078143..9e7db9e73cc13ffc04d05b02c9c5ea0d877be7e9 100644 (file)
@@ -43,6 +43,7 @@ extern int unregister_reboot_notifier(struct notifier_block *);
  * Architecture-specific implementations of sys_reboot commands.
  */
 
+extern void migrate_to_reboot_cpu(void);
 extern void machine_restart(char *cmd);
 extern void machine_halt(void);
 extern void machine_power_off(void);
index 939428ad25acb506297c1726faaee83d60d047c4..8e3e66ac0a5215d221042e15e631fb2fe2fb51d1 100644 (file)
@@ -24,6 +24,11 @@ extern int rtnl_trylock(void);
 extern int rtnl_is_locked(void);
 #ifdef CONFIG_PROVE_LOCKING
 extern int lockdep_rtnl_is_held(void);
+#else
+static inline int lockdep_rtnl_is_held(void)
+{
+       return 1;
+}
 #endif /* #ifdef CONFIG_PROVE_LOCKING */
 
 /**
index 768b037dfacb6273679c097a4abed0945d8f868d..53f97eb8dbc7660195f0ebc27893bf68c65cdff6 100644 (file)
@@ -440,8 +440,6 @@ struct task_cputime {
                .sum_exec_runtime = 0,                          \
        }
 
-#define PREEMPT_ENABLED                (PREEMPT_NEED_RESCHED)
-
 #ifdef CONFIG_PREEMPT_COUNT
 #define PREEMPT_DISABLED       (1 + PREEMPT_ENABLED)
 #else
@@ -932,7 +930,8 @@ struct pipe_inode_info;
 struct uts_namespace;
 
 struct load_weight {
-       unsigned long weight, inv_weight;
+       unsigned long weight;
+       u32 inv_weight;
 };
 
 struct sched_avg {
index cf87a24c0f92f1963081c93d7b0cce2356025358..535f158977b9dd4e730a62de2b9e7364a66406fc 100644 (file)
@@ -117,15 +117,15 @@ repeat:
 }
 
 /**
- * read_seqcount_begin_no_lockdep - start seq-read critical section w/o lockdep
+ * raw_read_seqcount_begin - start seq-read critical section w/o lockdep
  * @s: pointer to seqcount_t
  * Returns: count to be passed to read_seqcount_retry
  *
- * read_seqcount_begin_no_lockdep opens a read critical section of the given
+ * raw_read_seqcount_begin opens a read critical section of the given
  * seqcount, but without any lockdep checking. Validity of the critical
  * section is tested by checking read_seqcount_retry function.
  */
-static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
+static inline unsigned raw_read_seqcount_begin(const seqcount_t *s)
 {
        unsigned ret = __read_seqcount_begin(s);
        smp_rmb();
@@ -144,7 +144,7 @@ static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
 static inline unsigned read_seqcount_begin(const seqcount_t *s)
 {
        seqcount_lockdep_reader_access(s);
-       return read_seqcount_begin_no_lockdep(s);
+       return raw_read_seqcount_begin(s);
 }
 
 /**
@@ -206,14 +206,26 @@ static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
 }
 
 
+
+static inline void raw_write_seqcount_begin(seqcount_t *s)
+{
+       s->sequence++;
+       smp_wmb();
+}
+
+static inline void raw_write_seqcount_end(seqcount_t *s)
+{
+       smp_wmb();
+       s->sequence++;
+}
+
 /*
  * Sequence counter only version assumes that callers are using their
  * own mutexing.
  */
 static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
 {
-       s->sequence++;
-       smp_wmb();
+       raw_write_seqcount_begin(s);
        seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
 }
 
@@ -225,8 +237,7 @@ static inline void write_seqcount_begin(seqcount_t *s)
 static inline void write_seqcount_end(seqcount_t *s)
 {
        seqcount_release(&s->dep_map, 1, _RET_IP_);
-       smp_wmb();
-       s->sequence++;
+       raw_write_seqcount_end(s);
 }
 
 /**
index 215b5ea1cb302c43f0e8b9532fbe3ce59ff0f612..6f69b3f914fbf94c2d6d42beea62748a29a42d08 100644 (file)
@@ -1638,6 +1638,11 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
        skb->mac_header += offset;
 }
 
+static inline void skb_pop_mac_header(struct sk_buff *skb)
+{
+       skb->mac_header = skb->network_header;
+}
+
 static inline void skb_probe_transport_header(struct sk_buff *skb,
                                              const int offset_hint)
 {
@@ -2526,6 +2531,10 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
  * Ethernet MAC Drivers should call this function in their hard_xmit()
  * function immediately before giving the sk_buff to the MAC hardware.
  *
+ * Specifically, one should make absolutely sure that this function is
+ * called before TX completion of this packet can trigger.  Otherwise
+ * the packet could potentially already be freed.
+ *
  * @skb: A socket buffer.
  */
 static inline void skb_tx_timestamp(struct sk_buff *skb)
index 76d54270f2e27c175836b137f363014381e91687..65bb13035598fe141afd52a101f99ed1c9fd6838 100644 (file)
@@ -165,7 +165,6 @@ struct inet6_dev {
        struct net_device       *dev;
 
        struct list_head        addr_list;
-       int                     valid_ll_addr_cnt;
 
        struct ifmcaddr6        *mc_list;
        struct ifmcaddr6        *mc_tomb;
index 31e2de7d57c5d6c210e1b445b19551407fd31b6c..c0f0a13ed8183e58029aec1d12097aa1efb085f0 100644 (file)
 #define LLC_S_PF_IS_1(pdu)     ((pdu->ctrl_2 & LLC_S_PF_BIT_MASK) ? 1 : 0)
 
 #define PDU_SUPV_GET_Nr(pdu)   ((pdu->ctrl_2 & 0xFE) >> 1)
-#define PDU_GET_NEXT_Vr(sn)    (++sn & ~LLC_2_SEQ_NBR_MODULO)
+#define PDU_GET_NEXT_Vr(sn)    (((sn) + 1) & ~LLC_2_SEQ_NBR_MODULO)
 
 /* FRMR information field macros */
 
index 67b5d0068273e64ac94125861699e790a9d06e9d..0a248b323d875c08ca456d62ed46c028781e9432 100644 (file)
@@ -1046,9 +1046,6 @@ struct sctp_outq {
 
        /* Corked? */
        char cork;
-
-       /* Is this structure empty?  */
-       char empty;
 };
 
 void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
index 979874c627ee7f450c7aabff5c948cb2c87f84c3..61e1935c91b121d0ba6a9e5d6f05221d15060432 100644 (file)
@@ -978,7 +978,7 @@ struct ib_uobject {
 };
 
 struct ib_udata {
-       void __user *inbuf;
+       const void __user *inbuf;
        void __user *outbuf;
        size_t       inlen;
        size_t       outlen;
index 45412a6afa69d95ea82c820fb197d350c9d0575e..321301c0a643bfb32303b3f48cecae720f3fad87 100644 (file)
@@ -517,10 +517,6 @@ struct se_node_acl {
        u32                     acl_index;
 #define MAX_ACL_TAG_SIZE 64
        char                    acl_tag[MAX_ACL_TAG_SIZE];
-       u64                     num_cmds;
-       u64                     read_bytes;
-       u64                     write_bytes;
-       spinlock_t              stats_lock;
        /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
        atomic_t                acl_pr_ref_count;
        struct se_dev_entry     **device_list;
@@ -624,6 +620,7 @@ struct se_dev_attrib {
        u32             unmap_granularity;
        u32             unmap_granularity_alignment;
        u32             max_write_same_len;
+       u32             max_bytes_per_io;
        struct se_device *da_dev;
        struct config_group da_group;
 };
index 9b24d65fed72b9d06843cba89ebeeabff07fb71f..3c9a833992e872f095a4373d6cb5e33602129acc 100644 (file)
@@ -181,7 +181,6 @@ enum drm_map_type {
        _DRM_AGP = 3,             /**< AGP/GART */
        _DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
        _DRM_CONSISTENT = 5,      /**< Consistent memory for PCI DMA */
-       _DRM_GEM = 6,             /**< GEM object (obsolete) */
 };
 
 /**
index 3a4e97bd860771b6ad8e3b5d026a35200fcad4d3..126bfaa8bb6be45caf723889c077673da8c992f4 100644 (file)
@@ -222,6 +222,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_SET_CACHING       0x2f
 #define DRM_I915_GEM_GET_CACHING       0x30
 #define DRM_I915_REG_READ              0x31
+#define DRM_I915_GET_RESET_STATS       0x32
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -271,6 +272,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE      DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
 #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY     DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
 #define DRM_IOCTL_I915_REG_READ                        DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
+#define DRM_IOCTL_I915_GET_RESET_STATS         DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -719,7 +721,7 @@ struct drm_i915_gem_execbuffer2 {
  */
 #define I915_EXEC_IS_PINNED            (1<<10)
 
-/** Provide a hint to the kernel that the command stream and auxilliary
+/** Provide a hint to the kernel that the command stream and auxiliary
  * state buffers already holds the correct presumed addresses and so the
  * relocation process may be skipped if no buffers need to be moved in
  * preparation for the execbuffer.
@@ -1030,4 +1032,21 @@ struct drm_i915_reg_read {
        __u64 offset;
        __u64 val; /* Return value */
 };
+
+struct drm_i915_reset_stats {
+       __u32 ctx_id;
+       __u32 flags;
+
+       /* All resets since boot/module reload, for all contexts */
+       __u32 reset_count;
+
+       /* Number of batches lost when active in GPU, for this context */
+       __u32 batch_active;
+
+       /* Number of batches lost pending for execution, for this context */
+       __u32 batch_pending;
+
+       __u32 pad;
+};
+
 #endif /* _UAPI_I915_DRM_H_ */
index 2f3f7ea8c77b8a653b0972302ead53319f13e5fc..d9ea3a73afe2d2a4df80ebebd23316df5077c346 100644 (file)
@@ -983,6 +983,10 @@ struct drm_radeon_cs {
 #define RADEON_INFO_SI_CP_DMA_COMPUTE  0x17
 /* CIK macrotile mode array */
 #define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY   0x18
+/* query the number of render backends */
+#define RADEON_INFO_SI_BACKEND_ENABLED_MASK    0x19
+/* max engine clock - needed for OpenCL */
+#define RADEON_INFO_MAX_SCLK           0x1a
 
 
 struct drm_radeon_info {
index bcb0912afe7a4a233a171f2d1b4bb7d518c6884e..9971c560ed9aa42dc841e76b9586f05e25225d96 100644 (file)
 #ifndef __VMWGFX_DRM_H__
 #define __VMWGFX_DRM_H__
 
+#ifndef __KERNEL__
+#include <drm.h>
+#endif
+
 #define DRM_VMW_MAX_SURFACE_FACES 6
 #define DRM_VMW_MAX_MIP_LEVELS 24
 
 #define DRM_VMW_PRESENT              18
 #define DRM_VMW_PRESENT_READBACK     19
 #define DRM_VMW_UPDATE_LAYOUT        20
+#define DRM_VMW_CREATE_SHADER        21
+#define DRM_VMW_UNREF_SHADER         22
+#define DRM_VMW_GB_SURFACE_CREATE    23
+#define DRM_VMW_GB_SURFACE_REF       24
+#define DRM_VMW_SYNCCPU              25
 
 /*************************************************************************/
 /**
@@ -75,6 +84,9 @@
 #define DRM_VMW_PARAM_FIFO_CAPS        4
 #define DRM_VMW_PARAM_MAX_FB_SIZE      5
 #define DRM_VMW_PARAM_FIFO_HW_VERSION  6
+#define DRM_VMW_PARAM_MAX_SURF_MEMORY  7
+#define DRM_VMW_PARAM_3D_CAPS_SIZE     8
+#define DRM_VMW_PARAM_MAX_MOB_MEMORY   9
 
 /**
  * struct drm_vmw_getparam_arg
@@ -787,4 +799,253 @@ struct drm_vmw_update_layout_arg {
        uint64_t rects;
 };
 
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CREATE_SHADER - Create shader
+ *
+ * Creates a shader and optionally binds it to a dma buffer containing
+ * the shader byte-code.
+ */
+
+/**
+ * enum drm_vmw_shader_type - Shader types
+ */
+enum drm_vmw_shader_type {
+       drm_vmw_shader_type_vs = 0,
+       drm_vmw_shader_type_ps,
+       drm_vmw_shader_type_gs
+};
+
+
+/**
+ * struct drm_vmw_shader_create_arg
+ *
+ * @shader_type: Shader type of the shader to create.
+ * @size: Size of the byte-code in bytes.
+ * where the shader byte-code starts
+ * @buffer_handle: Buffer handle identifying the buffer containing the
+ * shader byte-code
+ * @shader_handle: On successful completion contains a handle that
+ * can be used to subsequently identify the shader.
+ * @offset: Offset in bytes into the buffer given by @buffer_handle,
+ *
+ * Input / Output argument to the DRM_VMW_CREATE_SHADER Ioctl.
+ */
+struct drm_vmw_shader_create_arg {
+       enum drm_vmw_shader_type shader_type;
+       uint32_t size;
+       uint32_t buffer_handle;
+       uint32_t shader_handle;
+       uint64_t offset;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_SHADER - Unreferences a shader
+ *
+ * Destroys a user-space reference to a shader, optionally destroying
+ * it.
+ */
+
+/**
+ * struct drm_vmw_shader_arg
+ *
+ * @handle: Handle identifying the shader to destroy.
+ *
+ * Input argument to the DRM_VMW_UNREF_SHADER ioctl.
+ */
+struct drm_vmw_shader_arg {
+       uint32_t handle;
+       uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_GB_SURFACE_CREATE - Create a host guest-backed surface.
+ *
+ * Allocates a surface handle and queues a create surface command
+ * for the host on the first use of the surface. The surface ID can
+ * be used as the surface ID in commands referencing the surface.
+ */
+
+/**
+ * enum drm_vmw_surface_flags
+ *
+ * @drm_vmw_surface_flag_shareable:     Whether the surface is shareable
+ * @drm_vmw_surface_flag_scanout:       Whether the surface is a scanout
+ *                                      surface.
+ * @drm_vmw_surface_flag_create_buffer: Create a backup buffer if none is
+ *                                      given.
+ */
+enum drm_vmw_surface_flags {
+       drm_vmw_surface_flag_shareable = (1 << 0),
+       drm_vmw_surface_flag_scanout = (1 << 1),
+       drm_vmw_surface_flag_create_buffer = (1 << 2)
+};
+
+/**
+ * struct drm_vmw_gb_surface_create_req
+ *
+ * @svga3d_flags:     SVGA3d surface flags for the device.
+ * @format:           SVGA3d format.
+ * @mip_level:        Number of mip levels for all faces.
+ * @drm_surface_flags Flags as described above.
+ * @multisample_count Future use. Set to 0.
+ * @autogen_filter    Future use. Set to 0.
+ * @buffer_handle     Buffer handle of backup buffer. SVGA3D_INVALID_ID
+ *                    if none.
+ * @base_size         Size of the base mip level for all faces.
+ *
+ * Input argument to the  DRM_VMW_GB_SURFACE_CREATE Ioctl.
+ * Part of output argument for the DRM_VMW_GB_SURFACE_REF Ioctl.
+ */
+struct drm_vmw_gb_surface_create_req {
+       uint32_t svga3d_flags;
+       uint32_t format;
+       uint32_t mip_levels;
+       enum drm_vmw_surface_flags drm_surface_flags;
+       uint32_t multisample_count;
+       uint32_t autogen_filter;
+       uint32_t buffer_handle;
+       uint32_t pad64;
+       struct drm_vmw_size base_size;
+};
+
+/**
+ * struct drm_vmw_gb_surface_create_rep
+ *
+ * @handle:            Surface handle.
+ * @backup_size:       Size of backup buffers for this surface.
+ * @buffer_handle:     Handle of backup buffer. SVGA3D_INVALID_ID if none.
+ * @buffer_size:       Actual size of the buffer identified by
+ *                     @buffer_handle
+ * @buffer_map_handle: Offset into device address space for the buffer
+ *                     identified by @buffer_handle.
+ *
+ * Part of output argument for the DRM_VMW_GB_SURFACE_REF ioctl.
+ * Output argument for the DRM_VMW_GB_SURFACE_CREATE ioctl.
+ */
+struct drm_vmw_gb_surface_create_rep {
+       uint32_t handle;
+       uint32_t backup_size;
+       uint32_t buffer_handle;
+       uint32_t buffer_size;
+       uint64_t buffer_map_handle;
+};
+
+/**
+ * union drm_vmw_gb_surface_create_arg
+ *
+ * @req: Input argument as described above.
+ * @rep: Output argument as described above.
+ *
+ * Argument to the DRM_VMW_GB_SURFACE_CREATE ioctl.
+ */
+union drm_vmw_gb_surface_create_arg {
+       struct drm_vmw_gb_surface_create_rep rep;
+       struct drm_vmw_gb_surface_create_req req;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_GB_SURFACE_REF - Reference a host surface.
+ *
+ * Puts a reference on a host surface with a given handle, as previously
+ * returned by the DRM_VMW_GB_SURFACE_CREATE ioctl.
+ * A reference will make sure the surface isn't destroyed while we hold
+ * it and will allow the calling client to use the surface handle in
+ * the command stream.
+ *
+ * On successful return, the Ioctl returns the surface information given
+ * to and returned from the DRM_VMW_GB_SURFACE_CREATE ioctl.
+ */
+
+/**
+ * struct drm_vmw_gb_surface_reference_arg
+ *
+ * @creq: The data used as input when the surface was created, as described
+ *        above at "struct drm_vmw_gb_surface_create_req"
+ * @crep: Additional data output when the surface was created, as described
+ *        above at "struct drm_vmw_gb_surface_create_rep"
+ *
+ * Output Argument to the DRM_VMW_GB_SURFACE_REF ioctl.
+ */
+struct drm_vmw_gb_surface_ref_rep {
+       struct drm_vmw_gb_surface_create_req creq;
+       struct drm_vmw_gb_surface_create_rep crep;
+};
+
+/**
+ * union drm_vmw_gb_surface_reference_arg
+ *
+ * @req: Input data as described above at "struct drm_vmw_surface_arg"
+ * @rep: Output data as described above at "struct drm_vmw_gb_surface_ref_rep"
+ *
+ * Argument to the DRM_VMW_GB_SURFACE_REF Ioctl.
+ */
+union drm_vmw_gb_surface_reference_arg {
+       struct drm_vmw_gb_surface_ref_rep rep;
+       struct drm_vmw_surface_arg req;
+};
+
+
+/*************************************************************************/
+/**
+ * DRM_VMW_SYNCCPU - Sync a DMA buffer / MOB for CPU access.
+ *
+ * Idles any previously submitted GPU operations on the buffer and
+ * by default blocks command submissions that reference the buffer.
+ * If the file descriptor used to grab a blocking CPU sync is closed, the
+ * cpu sync is released.
+ * The flags argument indicates how the grab / release operation should be
+ * performed:
+ */
+
+/**
+ * enum drm_vmw_synccpu_flags - Synccpu flags:
+ *
+ * @drm_vmw_synccpu_read: Sync for read. If sync is done for read only, it's a
+ * hint to the kernel to allow command submissions that references the buffer
+ * for read-only.
+ * @drm_vmw_synccpu_write: Sync for write. Block all command submissions
+ * referencing this buffer.
+ * @drm_vmw_synccpu_dontblock: Dont wait for GPU idle, but rather return
+ * -EBUSY should the buffer be busy.
+ * @drm_vmw_synccpu_allow_cs: Allow command submission that touches the buffer
+ * while the buffer is synced for CPU. This is similar to the GEM bo idle
+ * behavior.
+ */
+enum drm_vmw_synccpu_flags {
+       drm_vmw_synccpu_read = (1 << 0),
+       drm_vmw_synccpu_write = (1 << 1),
+       drm_vmw_synccpu_dontblock = (1 << 2),
+       drm_vmw_synccpu_allow_cs = (1 << 3)
+};
+
+/**
+ * enum drm_vmw_synccpu_op - Synccpu operations:
+ *
+ * @drm_vmw_synccpu_grab:    Grab the buffer for CPU operations
+ * @drm_vmw_synccpu_release: Release a previous grab.
+ */
+enum drm_vmw_synccpu_op {
+       drm_vmw_synccpu_grab,
+       drm_vmw_synccpu_release
+};
+
+/**
+ * struct drm_vmw_synccpu_arg
+ *
+ * @op:                             The synccpu operation as described above.
+ * @handle:                 Handle identifying the buffer object.
+ * @flags:                  Flags as described above.
+ */
+struct drm_vmw_synccpu_arg {
+       enum drm_vmw_synccpu_op op;
+       enum drm_vmw_synccpu_flags flags;
+       uint32_t handle;
+       uint32_t pad64;
+};
+
 #endif
index ecc88592ecbe94acfbacd1eda9b5907a832470da..bd24470d24a2c7a3145af21094e03f67b7ce0761 100644 (file)
@@ -464,7 +464,8 @@ struct input_keymap_entry {
 #define KEY_BRIGHTNESS_ZERO    244     /* brightness off, use ambient */
 #define KEY_DISPLAY_OFF                245     /* display device to off state */
 
-#define KEY_WIMAX              246
+#define KEY_WWAN               246     /* Wireless WAN (LTE, UMTS, GSM, etc.) */
+#define KEY_WIMAX              KEY_WWAN
 #define KEY_RFKILL             247     /* Key that controls all radios */
 
 #define KEY_MICMUTE            248     /* Mute / unmute the microphone */
index e1802d6153aec4d0c5fd81300dcde057d9bf8a59..959d454f76a185c87ce7fc223a229d37db2564f8 100644 (file)
@@ -679,6 +679,7 @@ enum perf_event_type {
         *
         *      { u64                   weight;   } && PERF_SAMPLE_WEIGHT
         *      { u64                   data_src; } && PERF_SAMPLE_DATA_SRC
+        *      { u64                   transaction; } && PERF_SAMPLE_TRANSACTION
         * };
         */
        PERF_RECORD_SAMPLE                      = 9,
index 65e12099ef89d9f3b5706858d956d8aabe427348..ae665ac59c36b6812a0470d5a7e0124c3e13a69f 100644 (file)
@@ -146,7 +146,7 @@ struct blkif_request_segment_aligned {
 struct blkif_request_rw {
        uint8_t        nr_segments;  /* number of segments                   */
        blkif_vdev_t   handle;       /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad1;        /* offsetof(blkif_request,u.rw.id) == 8 */
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
@@ -163,7 +163,7 @@ struct blkif_request_discard {
        uint8_t        flag;         /* BLKIF_DISCARD_SECURE or zero.        */
 #define BLKIF_DISCARD_SECURE (1<<0)  /* ignored if discard-secure=0          */
        blkif_vdev_t   _pad1;        /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad2;        /* offsetof(blkif_req..,u.discard.id)==8*/
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
@@ -175,7 +175,7 @@ struct blkif_request_discard {
 struct blkif_request_other {
        uint8_t      _pad1;
        blkif_vdev_t _pad2;        /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t     _pad3;        /* offsetof(blkif_req..,u.other.id)==8*/
 #endif
        uint64_t     id;           /* private guest value, echoed in resp  */
@@ -184,7 +184,7 @@ struct blkif_request_other {
 struct blkif_request_indirect {
        uint8_t        indirect_op;
        uint16_t       nr_segments;
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad1;        /* offsetof(blkif_...,u.indirect.id) == 8 */
 #endif
        uint64_t       id;
@@ -192,7 +192,7 @@ struct blkif_request_indirect {
        blkif_vdev_t   handle;
        uint16_t       _pad2;
        grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t      _pad3;         /* make it 64 byte aligned */
 #else
        uint64_t      _pad3;         /* make it 64 byte aligned */
index 79383d3aa5dc5f7fe64abdcaf7d511144ca016e5..4e5d96ab2034c25e2c1bb38d4ab9e619f8e04e86 100644 (file)
@@ -809,6 +809,12 @@ config GENERIC_SCHED_CLOCK
 config ARCH_SUPPORTS_NUMA_BALANCING
        bool
 
+#
+# For architectures that know their GCC __int128 support is sound
+#
+config ARCH_SUPPORTS_INT128
+       bool
+
 # For architectures that (ab)use NUMA to represent different memory regions
 # all cpu-local but of different latencies, such as SuperH.
 #
index bbaf7d59c1bb14f166441e6532b55585790e4b52..bc010ee272b6cfec39892e6cb04b98cc06995e1a 100644 (file)
@@ -137,9 +137,10 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
 ###############################################################################
 ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
 X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
-X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
-X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
+X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += $(objtree)/signing_key.x509
+X509_CERTIFICATES-raw := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
                                $(or $(realpath $(CERT)),$(CERT))))
+X509_CERTIFICATES := $(subst $(realpath $(objtree))/,,$(X509_CERTIFICATES-raw))
 
 ifeq ($(X509_CERTIFICATES),)
 $(warning *** No X.509 certificates found ***)
@@ -164,9 +165,9 @@ $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
 targets += $(obj)/.x509.list
 $(obj)/.x509.list:
        @echo $(X509_CERTIFICATES) >$@
+endif
 
 clean-files := x509_certificate_list .x509.list
-endif
 
 ifeq ($(CONFIG_MODULE_SIG),y)
 ###############################################################################
index 5253204afdcace55e89cda669aaf2896eba23aaa..9fd4246b04b8298ec608dbba4d9ee9997e105fbc 100644 (file)
@@ -22,6 +22,6 @@ void foo(void)
 #ifdef CONFIG_SMP
        DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS));
 #endif
-       DEFINE(BLOATED_SPINLOCKS, sizeof(spinlock_t) > sizeof(int));
+       DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
        /* End of constants */
 }
index 8b729c278b649c7c016786f6dac9886290ce794f..bc1dcabe92176636baf79c7ef52e597422aeaf75 100644 (file)
@@ -890,6 +890,16 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
                struct cgroup *cgrp = dentry->d_fsdata;
 
                BUG_ON(!(cgroup_is_dead(cgrp)));
+
+               /*
+                * XXX: cgrp->id is only used to look up css's.  As cgroup
+                * and css's lifetimes will be decoupled, it should be made
+                * per-subsystem and moved to css->id so that lookups are
+                * successful until the target css is released.
+                */
+               idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+               cgrp->id = -1;
+
                call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
        } else {
                struct cfent *cfe = __d_cfe(dentry);
@@ -4268,6 +4278,7 @@ static void css_release(struct percpu_ref *ref)
        struct cgroup_subsys_state *css =
                container_of(ref, struct cgroup_subsys_state, refcnt);
 
+       rcu_assign_pointer(css->cgroup->subsys[css->ss->subsys_id], NULL);
        call_rcu(&css->rcu_head, css_free_rcu_fn);
 }
 
@@ -4426,14 +4437,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
        root->number_of_cgroups++;
 
-       /* each css holds a ref to the cgroup's dentry and the parent css */
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
-
-               dget(dentry);
-               css_get(css->parent);
-       }
-
        /* hold a ref to the parent's dentry */
        dget(parent->dentry);
 
@@ -4445,6 +4448,13 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                if (err)
                        goto err_destroy;
 
+               /* each css holds a ref to the cgroup's dentry and parent css */
+               dget(dentry);
+               css_get(css->parent);
+
+               /* mark it consumed for error path */
+               css_ar[ss->subsys_id] = NULL;
+
                if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
                    parent->parent) {
                        pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
@@ -4491,6 +4501,14 @@ err_free_cgrp:
        return err;
 
 err_destroy:
+       for_each_root_subsys(root, ss) {
+               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
+
+               if (css) {
+                       percpu_ref_cancel_init(&css->refcnt);
+                       ss->css_free(css);
+               }
+       }
        cgroup_destroy_locked(cgrp);
        mutex_unlock(&cgroup_mutex);
        mutex_unlock(&dentry->d_inode->i_mutex);
@@ -4652,8 +4670,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
         * will be invoked to perform the rest of destruction once the
         * percpu refs of all css's are confirmed to be killed.
         */
-       for_each_root_subsys(cgrp->root, ss)
-               kill_css(cgroup_css(cgrp, ss));
+       for_each_root_subsys(cgrp->root, ss) {
+               struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
+
+               if (css)
+                       kill_css(css);
+       }
 
        /*
         * Mark @cgrp dead.  This prevents further task migration and child
@@ -4722,14 +4744,6 @@ static void cgroup_destroy_css_killed(struct cgroup *cgrp)
        /* delete this cgroup from parent->children */
        list_del_rcu(&cgrp->sibling);
 
-       /*
-        * We should remove the cgroup object from idr before its grace
-        * period starts, so we won't be looking up a cgroup while the
-        * cgroup is being freed.
-        */
-       idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
-       cgrp->id = -1;
-
        dput(d);
 
        set_bit(CGRP_RELEASABLE, &parent->flags);
index 72348dc192c11e7a85560b67bc792415d969e22f..f5744010a8d2f980f1902279de41a866ceb00a37 100644 (file)
@@ -1396,6 +1396,8 @@ event_sched_out(struct perf_event *event,
        if (event->state != PERF_EVENT_STATE_ACTIVE)
                return;
 
+       perf_pmu_disable(event->pmu);
+
        event->state = PERF_EVENT_STATE_INACTIVE;
        if (event->pending_disable) {
                event->pending_disable = 0;
@@ -1412,6 +1414,8 @@ event_sched_out(struct perf_event *event,
                ctx->nr_freq--;
        if (event->attr.exclusive || !cpuctx->active_oncpu)
                cpuctx->exclusive = 0;
+
+       perf_pmu_enable(event->pmu);
 }
 
 static void
@@ -1652,6 +1656,7 @@ event_sched_in(struct perf_event *event,
                 struct perf_event_context *ctx)
 {
        u64 tstamp = perf_event_time(event);
+       int ret = 0;
 
        if (event->state <= PERF_EVENT_STATE_OFF)
                return 0;
@@ -1674,10 +1679,13 @@ event_sched_in(struct perf_event *event,
         */
        smp_wmb();
 
+       perf_pmu_disable(event->pmu);
+
        if (event->pmu->add(event, PERF_EF_START)) {
                event->state = PERF_EVENT_STATE_INACTIVE;
                event->oncpu = -1;
-               return -EAGAIN;
+               ret = -EAGAIN;
+               goto out;
        }
 
        event->tstamp_running += tstamp - event->tstamp_stopped;
@@ -1693,7 +1701,10 @@ event_sched_in(struct perf_event *event,
        if (event->attr.exclusive)
                cpuctx->exclusive = 1;
 
-       return 0;
+out:
+       perf_pmu_enable(event->pmu);
+
+       return ret;
 }
 
 static int
@@ -2743,6 +2754,8 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                if (!event_filter_match(event))
                        continue;
 
+               perf_pmu_disable(event->pmu);
+
                hwc = &event->hw;
 
                if (hwc->interrupts == MAX_INTERRUPTS) {
@@ -2752,7 +2765,7 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                }
 
                if (!event->attr.freq || !event->attr.sample_freq)
-                       continue;
+                       goto next;
 
                /*
                 * stop the event and update event->count
@@ -2774,6 +2787,8 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                        perf_adjust_period(event, period, delta, false);
 
                event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
+       next:
+               perf_pmu_enable(event->pmu);
        }
 
        perf_pmu_enable(ctx->pmu);
index 728d5be9548ce61913c85e14303248363eae0a31..dfa736c98d17b4a8a6c353b4ee2bb2199dfd6a2e 100644 (file)
@@ -537,6 +537,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
        spin_lock_init(&mm->page_table_lock);
        mm_init_aio(mm);
        mm_init_owner(mm, p);
+       clear_tlb_flush_pending(mm);
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
@@ -1171,7 +1172,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         * do not allow it to share a thread group or signal handlers or
         * parent with the forking task.
         */
-       if (clone_flags & (CLONE_SIGHAND | CLONE_PARENT)) {
+       if (clone_flags & CLONE_SIGHAND) {
                if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
                    (task_active_pid_ns(current) !=
                                current->nsproxy->pid_ns_for_children))
index b462fa197517b6176701fa860cdb966bc44a69ba..aa6a8aadb911fb323b4662a4652c95ff4319f0c5 100644 (file)
@@ -19,6 +19,12 @@ EXPORT_SYMBOL(system_freezing_cnt);
 bool pm_freezing;
 bool pm_nosig_freezing;
 
+/*
+ * Temporary export for the deadlock workaround in ata_scsi_hotplug().
+ * Remove once the hack becomes unnecessary.
+ */
+EXPORT_SYMBOL_GPL(pm_freezing);
+
 /* protects freezing and frozen transitions */
 static DEFINE_SPINLOCK(freezer_lock);
 
index d0d8fca54065d72a248b0f8b76346bb72c6e2441..9c970167e4025f01be6bd696499eec2504c72ef7 100644 (file)
@@ -1680,6 +1680,7 @@ int kernel_kexec(void)
        {
                kexec_in_progress = true;
                kernel_restart_prepare(NULL);
+               migrate_to_reboot_cpu();
                printk(KERN_EMERG "Starting new kernel\n");
                machine_shutdown();
        }
index 463aa6736751a0a12d949ddeb93330b6067f053b..eacb8bd8cab4e1205230ecfdde12483be9846cf7 100644 (file)
@@ -81,6 +81,7 @@ void pm_vt_switch_unregister(struct device *dev)
        list_for_each_entry(tmp, &pm_vt_switch_list, head) {
                if (tmp->dev == dev) {
                        list_del(&tmp->head);
+                       kfree(tmp);
                        break;
                }
        }
index f813b3474646c5b320a19d9a8997349bdd14d68e..662c83fc16b77ed79b9474c681848858666055e0 100644 (file)
@@ -104,7 +104,7 @@ int unregister_reboot_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_reboot_notifier);
 
-static void migrate_to_reboot_cpu(void)
+void migrate_to_reboot_cpu(void)
 {
        /* The boot cpu is always logical cpu 0 */
        int cpu = reboot_cpu;
index e85cda20ab2b8ed6694d1cfa4a617b1bf231569d..a88f4a485c5e5f92190dd5bf784600d79d5f8f18 100644 (file)
@@ -4902,6 +4902,7 @@ DEFINE_PER_CPU(struct sched_domain *, sd_asym);
 static void update_top_cache_domain(int cpu)
 {
        struct sched_domain *sd;
+       struct sched_domain *busy_sd = NULL;
        int id = cpu;
        int size = 1;
 
@@ -4909,9 +4910,9 @@ static void update_top_cache_domain(int cpu)
        if (sd) {
                id = cpumask_first(sched_domain_span(sd));
                size = cpumask_weight(sched_domain_span(sd));
-               sd = sd->parent; /* sd_busy */
+               busy_sd = sd->parent; /* sd_busy */
        }
-       rcu_assign_pointer(per_cpu(sd_busy, cpu), sd);
+       rcu_assign_pointer(per_cpu(sd_busy, cpu), busy_sd);
 
        rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
        per_cpu(sd_llc_size, cpu) = size;
@@ -5112,6 +5113,7 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu)
                 * die on a /0 trap.
                 */
                sg->sgp->power = SCHED_POWER_SCALE * cpumask_weight(sg_span);
+               sg->sgp->power_orig = sg->sgp->power;
 
                /*
                 * Make sure the first group of this domain contains the
index fd773ade1a3141cd4b152cb8fce905866a7c223a..e64b0794060e6d89a7d3e216efe8189fffdbb8d7 100644 (file)
@@ -178,59 +178,61 @@ void sched_init_granularity(void)
        update_sysctl();
 }
 
-#if BITS_PER_LONG == 32
-# define WMULT_CONST   (~0UL)
-#else
-# define WMULT_CONST   (1UL << 32)
-#endif
-
+#define WMULT_CONST    (~0U)
 #define WMULT_SHIFT    32
 
-/*
- * Shift right and round:
- */
-#define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))
+static void __update_inv_weight(struct load_weight *lw)
+{
+       unsigned long w;
+
+       if (likely(lw->inv_weight))
+               return;
+
+       w = scale_load_down(lw->weight);
+
+       if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
+               lw->inv_weight = 1;
+       else if (unlikely(!w))
+               lw->inv_weight = WMULT_CONST;
+       else
+               lw->inv_weight = WMULT_CONST / w;
+}
 
 /*
- * delta *= weight / lw
+ * delta_exec * weight / lw.weight
+ *   OR
+ * (delta_exec * (weight * lw->inv_weight)) >> WMULT_SHIFT
+ *
+ * Either weight := NICE_0_LOAD and lw \e prio_to_wmult[], in which case
+ * we're guaranteed shift stays positive because inv_weight is guaranteed to
+ * fit 32 bits, and NICE_0_LOAD gives another 10 bits; therefore shift >= 22.
+ *
+ * Or, weight =< lw.weight (because lw.weight is the runqueue weight), thus
+ * weight/lw.weight <= 1, and therefore our shift will also be positive.
  */
-static unsigned long
-calc_delta_mine(unsigned long delta_exec, unsigned long weight,
-               struct load_weight *lw)
+static u64 __calc_delta(u64 delta_exec, unsigned long weight, struct load_weight *lw)
 {
-       u64 tmp;
-
-       /*
-        * weight can be less than 2^SCHED_LOAD_RESOLUTION for task group sched
-        * entities since MIN_SHARES = 2. Treat weight as 1 if less than
-        * 2^SCHED_LOAD_RESOLUTION.
-        */
-       if (likely(weight > (1UL << SCHED_LOAD_RESOLUTION)))
-               tmp = (u64)delta_exec * scale_load_down(weight);
-       else
-               tmp = (u64)delta_exec;
+       u64 fact = scale_load_down(weight);
+       int shift = WMULT_SHIFT;
 
-       if (!lw->inv_weight) {
-               unsigned long w = scale_load_down(lw->weight);
+       __update_inv_weight(lw);
 
-               if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
-                       lw->inv_weight = 1;
-               else if (unlikely(!w))
-                       lw->inv_weight = WMULT_CONST;
-               else
-                       lw->inv_weight = WMULT_CONST / w;
+       if (unlikely(fact >> 32)) {
+               while (fact >> 32) {
+                       fact >>= 1;
+                       shift--;
+               }
        }
 
-       /*
-        * Check whether we'd overflow the 64-bit multiplication:
-        */
-       if (unlikely(tmp > WMULT_CONST))
-               tmp = SRR(SRR(tmp, WMULT_SHIFT/2) * lw->inv_weight,
-                       WMULT_SHIFT/2);
-       else
-               tmp = SRR(tmp * lw->inv_weight, WMULT_SHIFT);
+       /* hint to use a 32x32->64 mul */
+       fact = (u64)(u32)fact * lw->inv_weight;
+
+       while (fact >> 32) {
+               fact >>= 1;
+               shift--;
+       }
 
-       return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX);
+       return mul_u64_u32_shr(delta_exec, fact, shift);
 }
 
 
@@ -443,7 +445,7 @@ find_matching_se(struct sched_entity **se, struct sched_entity **pse)
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
 static __always_inline
-void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec);
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec);
 
 /**************************************************************
  * Scheduling class tree data structure manipulation methods:
@@ -612,11 +614,10 @@ int sched_proc_update_handler(struct ctl_table *table, int write,
 /*
  * delta /= w
  */
-static inline unsigned long
-calc_delta_fair(unsigned long delta, struct sched_entity *se)
+static inline u64 calc_delta_fair(u64 delta, struct sched_entity *se)
 {
        if (unlikely(se->load.weight != NICE_0_LOAD))
-               delta = calc_delta_mine(delta, NICE_0_LOAD, &se->load);
+               delta = __calc_delta(delta, NICE_0_LOAD, &se->load);
 
        return delta;
 }
@@ -665,7 +666,7 @@ static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se)
                        update_load_add(&lw, se->load.weight);
                        load = &lw;
                }
-               slice = calc_delta_mine(slice, se->load.weight, load);
+               slice = __calc_delta(slice, se->load.weight, load);
        }
        return slice;
 }
@@ -703,47 +704,32 @@ void init_task_runnable_average(struct task_struct *p)
 #endif
 
 /*
- * Update the current task's runtime statistics. Skip current tasks that
- * are not in our scheduling class.
+ * Update the current task's runtime statistics.
  */
-static inline void
-__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
-             unsigned long delta_exec)
-{
-       unsigned long delta_exec_weighted;
-
-       schedstat_set(curr->statistics.exec_max,
-                     max((u64)delta_exec, curr->statistics.exec_max));
-
-       curr->sum_exec_runtime += delta_exec;
-       schedstat_add(cfs_rq, exec_clock, delta_exec);
-       delta_exec_weighted = calc_delta_fair(delta_exec, curr);
-
-       curr->vruntime += delta_exec_weighted;
-       update_min_vruntime(cfs_rq);
-}
-
 static void update_curr(struct cfs_rq *cfs_rq)
 {
        struct sched_entity *curr = cfs_rq->curr;
        u64 now = rq_clock_task(rq_of(cfs_rq));
-       unsigned long delta_exec;
+       u64 delta_exec;
 
        if (unlikely(!curr))
                return;
 
-       /*
-        * Get the amount of time the current task was running
-        * since the last time we changed load (this cannot
-        * overflow on 32 bits):
-        */
-       delta_exec = (unsigned long)(now - curr->exec_start);
-       if (!delta_exec)
+       delta_exec = now - curr->exec_start;
+       if (unlikely((s64)delta_exec <= 0))
                return;
 
-       __update_curr(cfs_rq, curr, delta_exec);
        curr->exec_start = now;
 
+       schedstat_set(curr->statistics.exec_max,
+                     max(delta_exec, curr->statistics.exec_max));
+
+       curr->sum_exec_runtime += delta_exec;
+       schedstat_add(cfs_rq, exec_clock, delta_exec);
+
+       curr->vruntime += calc_delta_fair(delta_exec, curr);
+       update_min_vruntime(cfs_rq);
+
        if (entity_is_task(curr)) {
                struct task_struct *curtask = task_of(curr);
 
@@ -1752,6 +1738,13 @@ void task_numa_work(struct callback_head *work)
                    (vma->vm_file && (vma->vm_flags & (VM_READ|VM_WRITE)) == (VM_READ)))
                        continue;
 
+               /*
+                * Skip inaccessible VMAs to avoid any confusion between
+                * PROT_NONE and NUMA hinting ptes
+                */
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+                       continue;
+
                do {
                        start = max(start, vma->vm_start);
                        end = ALIGN(start + (pages << PAGE_SHIFT), HPAGE_SIZE);
@@ -3015,8 +3008,7 @@ static void expire_cfs_rq_runtime(struct cfs_rq *cfs_rq)
        }
 }
 
-static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                    unsigned long delta_exec)
+static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
 {
        /* dock delta_exec before expiring quota (as it could span periods) */
        cfs_rq->runtime_remaining -= delta_exec;
@@ -3034,7 +3026,7 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
 }
 
 static __always_inline
-void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec)
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
 {
        if (!cfs_bandwidth_used() || !cfs_rq->runtime_enabled)
                return;
@@ -3574,8 +3566,7 @@ static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
        return rq_clock_task(rq_of(cfs_rq));
 }
 
-static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                    unsigned long delta_exec) {}
+static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec) {}
 static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 static void check_enqueue_throttle(struct cfs_rq *cfs_rq) {}
 static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
@@ -3932,7 +3923,7 @@ static long effective_load(struct task_group *tg, int cpu, long wl, long wg)
 {
        struct sched_entity *se = tg->se[cpu];
 
-       if (!tg->parent || !wl) /* the trivial, non-cgroup case */
+       if (!tg->parent)        /* the trivial, non-cgroup case */
                return wl;
 
        for_each_sched_entity(se) {
index 7d57275fc396d1c56475c707888f1f95fd84142b..1c4065575fa2c44d91250455db38638d728788e8 100644 (file)
@@ -901,6 +901,13 @@ inc_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio)
 {
        struct rq *rq = rq_of_rt_rq(rt_rq);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * Change rq's cpupri only if rt_rq is the top queue.
+        */
+       if (&rq->rt != rt_rq)
+               return;
+#endif
        if (rq->online && prio < prev_prio)
                cpupri_set(&rq->rd->cpupri, rq->cpu, prio);
 }
@@ -910,6 +917,13 @@ dec_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio)
 {
        struct rq *rq = rq_of_rt_rq(rt_rq);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * Change rq's cpupri only if rt_rq is the top queue.
+        */
+       if (&rq->rt != rt_rq)
+               return;
+#endif
        if (rq->online && rt_rq->highest_prio.curr != prev_prio)
                cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio.curr);
 }
index 68b79937598106918748832a396848f7fd22f870..0abb364642818e4ef842ab2f3631d15cb80400f2 100644 (file)
@@ -74,7 +74,7 @@ unsigned long long notrace sched_clock(void)
                return cd.epoch_ns;
 
        do {
-               seq = read_seqcount_begin(&cd.seq);
+               seq = raw_read_seqcount_begin(&cd.seq);
                epoch_cyc = cd.epoch_cyc;
                epoch_ns = cd.epoch_ns;
        } while (read_seqcount_retry(&cd.seq, seq));
@@ -99,10 +99,10 @@ static void notrace update_sched_clock(void)
                          cd.mult, cd.shift);
 
        raw_local_irq_save(flags);
-       write_seqcount_begin(&cd.seq);
+       raw_write_seqcount_begin(&cd.seq);
        cd.epoch_ns = ns;
        cd.epoch_cyc = cyc;
-       write_seqcount_end(&cd.seq);
+       raw_write_seqcount_end(&cd.seq);
        raw_local_irq_restore(flags);
 }
 
index 0e9f9eaade2f6a2dd0e729cd2d3bb38b4f6f8ec0..72a0f81dc5a801e62ef5bb400c068705851b32f6 100644 (file)
@@ -775,7 +775,7 @@ static int ftrace_profile_init(void)
        int cpu;
        int ret = 0;
 
-       for_each_online_cpu(cpu) {
+       for_each_possible_cpu(cpu) {
                ret = ftrace_profile_init_cpu(cpu);
                if (ret)
                        break;
index a3a0dbfda32957616f143ae2722541a5846c0a62..c006131beb77c5151f92cacb9e11e6a3b1defe1b 100644 (file)
@@ -51,9 +51,9 @@ struct user_namespace init_user_ns = {
        .owner = GLOBAL_ROOT_UID,
        .group = GLOBAL_ROOT_GID,
        .proc_inum = PROC_USER_INIT_INO,
-#ifdef CONFIG_KEYS_KERBEROS_CACHE
-       .krb_cache_register_sem =
-       __RWSEM_INITIALIZER(init_user_ns.krb_cache_register_sem),
+#ifdef CONFIG_PERSISTENT_KEYRINGS
+       .persistent_keyring_register_sem =
+       __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
 #endif
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
index 7473ee3b4ee712b0759e264b79f350457888be1e..8280a5dd172780371711743d297fcd0fd4e4360a 100644 (file)
@@ -82,10 +82,10 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
                unsigned long flags;
                raw_spin_lock_irqsave(&fbc->lock, flags);
                fbc->count += count;
+               __this_cpu_sub(*fbc->counters, count - amount);
                raw_spin_unlock_irqrestore(&fbc->lock, flags);
-               __this_cpu_write(*fbc->counters, 0);
        } else {
-               __this_cpu_write(*fbc->counters, count);
+               this_cpu_add(*fbc->counters, amount);
        }
        preempt_enable();
 }
index eb69f352401de910552fb7f28959b38f4746a878..723bbe04a0b0511976d3778a4df94cb2974eb9c8 100644 (file)
@@ -543,7 +543,7 @@ config ZSWAP
 
 config MEM_SOFT_DIRTY
        bool "Track memory changes"
-       depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY
+       depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY && PROC_FS
        select PROC_PAGE_MONITOR
        help
          This option enables memory changes tracking by introducing a
index 805165bcd3dd0ab8f27bbff2c9105927ed803c15..f58bcd016f432dd094d6f6378aa53f9799d30811 100644 (file)
@@ -134,6 +134,10 @@ static void update_pageblock_skip(struct compact_control *cc,
                        bool migrate_scanner)
 {
        struct zone *zone = cc->zone;
+
+       if (cc->ignore_skip_hint)
+               return;
+
        if (!page)
                return;
 
index 5bff0814776870e2974e6e436ad99f99f264e05a..bbc4d660221ac4e514e24d49ce140b25ad5364d2 100644 (file)
@@ -208,9 +208,10 @@ get_write_lock:
                if (mapping_cap_account_dirty(mapping)) {
                        unsigned long addr;
                        struct file *file = get_file(vma->vm_file);
+                       /* mmap_region may free vma; grab the info now */
+                       vm_flags = vma->vm_flags;
 
-                       addr = mmap_region(file, start, size,
-                                       vma->vm_flags, pgoff);
+                       addr = mmap_region(file, start, size, vm_flags, pgoff);
                        fput(file);
                        if (IS_ERR_VALUE(addr)) {
                                err = addr;
@@ -218,7 +219,7 @@ get_write_lock:
                                BUG_ON(addr != start);
                                err = 0;
                        }
-                       goto out;
+                       goto out_freed;
                }
                mutex_lock(&mapping->i_mmap_mutex);
                flush_dcache_mmap_lock(mapping);
@@ -253,6 +254,7 @@ get_write_lock:
 out:
        if (vma)
                vm_flags = vma->vm_flags;
+out_freed:
        if (likely(!has_write_lock))
                up_read(&mm->mmap_sem);
        else
index 33a5dc492810d59eae0c7069e60dd3bdd9c8a374..95d1acb0f3d237f55f5f1d6405de5774f0f9fc6a 100644 (file)
@@ -882,6 +882,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                ret = 0;
                goto out_unlock;
        }
+
        if (unlikely(pmd_trans_splitting(pmd))) {
                /* split huge page running from under us */
                spin_unlock(src_ptl);
@@ -1153,7 +1154,7 @@ alloc:
                new_page = NULL;
 
        if (unlikely(!new_page)) {
-               if (is_huge_zero_pmd(orig_pmd)) {
+               if (!page) {
                        ret = do_huge_pmd_wp_zero_page_fallback(mm, vma,
                                        address, pmd, orig_pmd, haddr);
                } else {
@@ -1180,7 +1181,7 @@ alloc:
 
        count_vm_event(THP_FAULT_ALLOC);
 
-       if (is_huge_zero_pmd(orig_pmd))
+       if (!page)
                clear_huge_page(new_page, haddr, HPAGE_PMD_NR);
        else
                copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR);
@@ -1206,7 +1207,7 @@ alloc:
                page_add_new_anon_rmap(new_page, vma, haddr);
                set_pmd_at(mm, haddr, pmd, entry);
                update_mmu_cache_pmd(vma, address, pmd);
-               if (is_huge_zero_pmd(orig_pmd)) {
+               if (!page) {
                        add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR);
                        put_huge_zero_page();
                } else {
@@ -1243,6 +1244,10 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
        if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
                return ERR_PTR(-EFAULT);
 
+       /* Full NUMA hinting faults to serialise migration in fault paths */
+       if ((flags & FOLL_NUMA) && pmd_numa(*pmd))
+               goto out;
+
        page = pmd_page(*pmd);
        VM_BUG_ON(!PageHead(page));
        if (flags & FOLL_TOUCH) {
@@ -1295,6 +1300,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(!pmd_same(pmd, *pmdp)))
                goto out_unlock;
 
+       /*
+        * If there are potential migrations, wait for completion and retry
+        * without disrupting NUMA hinting information. Do not relock and
+        * check_same as the page may no longer be mapped.
+        */
+       if (unlikely(pmd_trans_migrating(*pmdp))) {
+               spin_unlock(ptl);
+               wait_migrate_huge_page(vma->anon_vma, pmdp);
+               goto out;
+       }
+
        page = pmd_page(pmd);
        BUG_ON(is_huge_zero_page(page));
        page_nid = page_to_nid(page);
@@ -1323,23 +1339,22 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                /* If the page was locked, there are no parallel migrations */
                if (page_locked)
                        goto clear_pmdnuma;
+       }
 
-               /*
-                * Otherwise wait for potential migrations and retry. We do
-                * relock and check_same as the page may no longer be mapped.
-                * As the fault is being retried, do not account for it.
-                */
+       /* Migration could have started since the pmd_trans_migrating check */
+       if (!page_locked) {
                spin_unlock(ptl);
                wait_on_page_locked(page);
                page_nid = -1;
                goto out;
        }
 
-       /* Page is misplaced, serialise migrations and parallel THP splits */
+       /*
+        * Page is misplaced. Page lock serialises migrations. Acquire anon_vma
+        * to serialises splits
+        */
        get_page(page);
        spin_unlock(ptl);
-       if (!page_locked)
-               lock_page(page);
        anon_vma = page_lock_anon_vma_read(page);
 
        /* Confirm the PMD did not change while page_table_lock was released */
@@ -1351,6 +1366,13 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                goto out_unlock;
        }
 
+       /* Bail if we fail to protect against THP splits for any reason */
+       if (unlikely(!anon_vma)) {
+               put_page(page);
+               page_nid = -1;
+               goto clear_pmdnuma;
+       }
+
        /*
         * Migrate the THP to the requested node, returns with page unlocked
         * and pmd_numa cleared.
@@ -1517,6 +1539,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                ret = 1;
                if (!prot_numa) {
                        entry = pmdp_get_and_clear(mm, addr, pmd);
+                       if (pmd_numa(entry))
+                               entry = pmd_mknonnuma(entry);
                        entry = pmd_modify(entry, newprot);
                        ret = HPAGE_PMD_NR;
                        BUG_ON(pmd_write(entry));
@@ -1531,7 +1555,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                         */
                        if (!is_huge_zero_page(page) &&
                            !pmd_numa(*pmd)) {
-                               entry = pmdp_get_and_clear(mm, addr, pmd);
+                               entry = *pmd;
                                entry = pmd_mknuma(entry);
                                ret = HPAGE_PMD_NR;
                        }
index bf5e8945714944f896e2dc79b33b75a491da4794..7f1a356153c013349ce520c7763002838c02fb76 100644 (file)
@@ -338,7 +338,7 @@ struct mem_cgroup {
 static size_t memcg_size(void)
 {
        return sizeof(struct mem_cgroup) +
-               nr_node_ids * sizeof(struct mem_cgroup_per_node);
+               nr_node_ids * sizeof(struct mem_cgroup_per_node *);
 }
 
 /* internal only representation about the status of kmem accounting. */
index b7c171602ba1ebb8697f0c523f1a62f51c3a2fa4..fabe55046c1d7b9638172aa8e26ecb4f3d6ed4b9 100644 (file)
@@ -938,6 +938,16 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
                                BUG_ON(!PageHWPoison(p));
                                return SWAP_FAIL;
                        }
+                       /*
+                        * We pinned the head page for hwpoison handling,
+                        * now we split the thp and we are interested in
+                        * the hwpoisoned raw page, so move the refcount
+                        * to it.
+                        */
+                       if (hpage != p) {
+                               put_page(hpage);
+                               get_page(p);
+                       }
                        /* THP is split, so ppage should be the real poisoned page. */
                        ppage = p;
                }
@@ -1505,10 +1515,16 @@ static int soft_offline_huge_page(struct page *page, int flags)
                if (ret > 0)
                        ret = -EIO;
        } else {
-               set_page_hwpoison_huge_page(hpage);
-               dequeue_hwpoisoned_huge_page(hpage);
-               atomic_long_add(1 << compound_order(hpage),
-                               &num_poisoned_pages);
+               /* overcommit hugetlb page will be freed to buddy */
+               if (PageHuge(page)) {
+                       set_page_hwpoison_huge_page(hpage);
+                       dequeue_hwpoisoned_huge_page(hpage);
+                       atomic_long_add(1 << compound_order(hpage),
+                                       &num_poisoned_pages);
+               } else {
+                       SetPageHWPoison(page);
+                       atomic_long_inc(&num_poisoned_pages);
+               }
        }
        return ret;
 }
index 5d9025f3b3e1cd65bd97655ee95d6cd2f390ce5b..6768ce9e57d29b6d8076b11c62c2097662f334d5 100644 (file)
@@ -4271,7 +4271,7 @@ void copy_user_huge_page(struct page *dst, struct page *src,
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
 
-#if USE_SPLIT_PTE_PTLOCKS && BLOATED_SPINLOCKS
+#if USE_SPLIT_PTE_PTLOCKS && ALLOC_SPLIT_PTLOCKS
 bool ptlock_alloc(struct page *page)
 {
        spinlock_t *ptl;
index eca4a3129129751208b41cfe808e9e31e5dc7b5f..0cd2c4d4e2703f88f56b957b6f442a531fbd2e1f 100644 (file)
@@ -1197,14 +1197,16 @@ static struct page *new_vma_page(struct page *page, unsigned long private, int *
                        break;
                vma = vma->vm_next;
        }
+
+       if (PageHuge(page)) {
+               if (vma)
+                       return alloc_huge_page_noerr(vma, address, 1);
+               else
+                       return NULL;
+       }
        /*
-        * queue_pages_range() confirms that @page belongs to some vma,
-        * so vma shouldn't be NULL.
+        * if !vma, alloc_page_vma() will use task or system default policy
         */
-       BUG_ON(!vma);
-
-       if (PageHuge(page))
-               return alloc_huge_page_noerr(vma, address, 1);
        return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
 }
 #else
@@ -1318,7 +1320,7 @@ static long do_mbind(unsigned long start, unsigned long len,
                if (nr_failed && (flags & MPOL_MF_STRICT))
                        err = -EIO;
        } else
-               putback_lru_pages(&pagelist);
+               putback_movable_pages(&pagelist);
 
        up_write(&mm->mmap_sem);
  mpol_out:
index bb940045fe8595842ed58f2e32f87b83d40485e1..9194375b230729fead356e8dd3c8f6bb951415ab 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/hugetlb_cgroup.h>
 #include <linux/gfp.h>
 #include <linux/balloon_compaction.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/tlbflush.h>
 
@@ -316,14 +317,15 @@ static inline bool buffer_migrate_lock_buffers(struct buffer_head *head,
  */
 int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode)
+               struct buffer_head *head, enum migrate_mode mode,
+               int extra_count)
 {
-       int expected_count = 0;
+       int expected_count = 1 + extra_count;
        void **pslot;
 
        if (!mapping) {
                /* Anonymous page without mapping */
-               if (page_count(page) != 1)
+               if (page_count(page) != expected_count)
                        return -EAGAIN;
                return MIGRATEPAGE_SUCCESS;
        }
@@ -333,7 +335,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
        pslot = radix_tree_lookup_slot(&mapping->page_tree,
                                        page_index(page));
 
-       expected_count = 2 + page_has_private(page);
+       expected_count += 1 + page_has_private(page);
        if (page_count(page) != expected_count ||
                radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) {
                spin_unlock_irq(&mapping->tree_lock);
@@ -583,7 +585,7 @@ int migrate_page(struct address_space *mapping,
 
        BUG_ON(PageWriteback(page));    /* Writeback must be complete */
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode);
+       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -610,7 +612,7 @@ int buffer_migrate_page(struct address_space *mapping,
 
        head = page_buffers(page);
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode);
+       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -1654,6 +1656,18 @@ int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
        return 1;
 }
 
+bool pmd_trans_migrating(pmd_t pmd)
+{
+       struct page *page = pmd_page(pmd);
+       return PageLocked(page);
+}
+
+void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd)
+{
+       struct page *page = pmd_page(*pmd);
+       wait_on_page_locked(page);
+}
+
 /*
  * Attempt to migrate a misplaced page to the specified destination
  * node. Caller is expected to have an elevated reference count on
@@ -1716,12 +1730,14 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                                struct page *page, int node)
 {
        spinlock_t *ptl;
-       unsigned long haddr = address & HPAGE_PMD_MASK;
        pg_data_t *pgdat = NODE_DATA(node);
        int isolated = 0;
        struct page *new_page = NULL;
        struct mem_cgroup *memcg = NULL;
        int page_lru = page_is_file_cache(page);
+       unsigned long mmun_start = address & HPAGE_PMD_MASK;
+       unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE;
+       pmd_t orig_entry;
 
        /*
         * Rate-limit the amount of data that is being migrated to a node.
@@ -1744,6 +1760,9 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                goto out_fail;
        }
 
+       if (mm_tlb_flush_pending(mm))
+               flush_tlb_range(vma, mmun_start, mmun_end);
+
        /* Prepare a page as a migration target */
        __set_page_locked(new_page);
        SetPageSwapBacked(new_page);
@@ -1755,9 +1774,12 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
        WARN_ON(PageLRU(new_page));
 
        /* Recheck the target PMD */
+       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
        ptl = pmd_lock(mm, pmd);
-       if (unlikely(!pmd_same(*pmd, entry))) {
+       if (unlikely(!pmd_same(*pmd, entry) || page_count(page) != 2)) {
+fail_putback:
                spin_unlock(ptl);
+               mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
                /* Reverse changes made by migrate_page_copy() */
                if (TestClearPageActive(new_page))
@@ -1774,7 +1796,8 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                putback_lru_page(page);
                mod_zone_page_state(page_zone(page),
                         NR_ISOLATED_ANON + page_lru, -HPAGE_PMD_NR);
-               goto out_fail;
+
+               goto out_unlock;
        }
 
        /*
@@ -1786,16 +1809,35 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
         */
        mem_cgroup_prepare_migration(page, new_page, &memcg);
 
+       orig_entry = *pmd;
        entry = mk_pmd(new_page, vma->vm_page_prot);
-       entry = pmd_mknonnuma(entry);
-       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
        entry = pmd_mkhuge(entry);
+       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
 
-       pmdp_clear_flush(vma, haddr, pmd);
-       set_pmd_at(mm, haddr, pmd, entry);
-       page_add_new_anon_rmap(new_page, vma, haddr);
+       /*
+        * Clear the old entry under pagetable lock and establish the new PTE.
+        * Any parallel GUP will either observe the old page blocking on the
+        * page lock, block on the page table lock or observe the new page.
+        * The SetPageUptodate on the new page and page_add_new_anon_rmap
+        * guarantee the copy is visible before the pagetable update.
+        */
+       flush_cache_range(vma, mmun_start, mmun_end);
+       page_add_new_anon_rmap(new_page, vma, mmun_start);
+       pmdp_clear_flush(vma, mmun_start, pmd);
+       set_pmd_at(mm, mmun_start, pmd, entry);
+       flush_tlb_range(vma, mmun_start, mmun_end);
        update_mmu_cache_pmd(vma, address, &entry);
+
+       if (page_count(page) != 2) {
+               set_pmd_at(mm, mmun_start, pmd, orig_entry);
+               flush_tlb_range(vma, mmun_start, mmun_end);
+               update_mmu_cache_pmd(vma, address, &entry);
+               page_remove_rmap(new_page);
+               goto fail_putback;
+       }
+
        page_remove_rmap(page);
+
        /*
         * Finish the charge transaction under the page table lock to
         * prevent split_huge_page() from dividing up the charge
@@ -1803,6 +1845,7 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
         */
        mem_cgroup_end_migration(memcg, page, new_page, true);
        spin_unlock(ptl);
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
        unlock_page(new_page);
        unlock_page(page);
@@ -1820,10 +1863,15 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
 out_fail:
        count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
 out_dropref:
-       entry = pmd_mknonnuma(entry);
-       set_pmd_at(mm, haddr, pmd, entry);
-       update_mmu_cache_pmd(vma, address, &entry);
+       ptl = pmd_lock(mm, pmd);
+       if (pmd_same(*pmd, entry)) {
+               entry = pmd_mknonnuma(entry);
+               set_pmd_at(mm, mmun_start, pmd, entry);
+               update_mmu_cache_pmd(vma, address, &entry);
+       }
+       spin_unlock(ptl);
 
+out_unlock:
        unlock_page(page);
        put_page(page);
        return 0;
index d480cd6fc475854259bdd51021d5125dbdfbe479..192e6eebe4f240e4a8ece7cc0e10e902ff29f308 100644 (file)
@@ -133,7 +133,10 @@ static void __munlock_isolation_failed(struct page *page)
 
 /**
  * munlock_vma_page - munlock a vma page
- * @page - page to be unlocked
+ * @page - page to be unlocked, either a normal page or THP page head
+ *
+ * returns the size of the page as a page mask (0 for normal page,
+ *         HPAGE_PMD_NR - 1 for THP head page)
  *
  * called from munlock()/munmap() path with page supposedly on the LRU.
  * When we munlock a page, because the vma where we found the page is being
@@ -148,21 +151,30 @@ static void __munlock_isolation_failed(struct page *page)
  */
 unsigned int munlock_vma_page(struct page *page)
 {
-       unsigned int page_mask = 0;
+       unsigned int nr_pages;
 
        BUG_ON(!PageLocked(page));
 
        if (TestClearPageMlocked(page)) {
-               unsigned int nr_pages = hpage_nr_pages(page);
+               nr_pages = hpage_nr_pages(page);
                mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages);
-               page_mask = nr_pages - 1;
                if (!isolate_lru_page(page))
                        __munlock_isolated_page(page);
                else
                        __munlock_isolation_failed(page);
+       } else {
+               nr_pages = hpage_nr_pages(page);
        }
 
-       return page_mask;
+       /*
+        * Regardless of the original PageMlocked flag, we determine nr_pages
+        * after touching the flag. This leaves a possible race with a THP page
+        * split, such that a whole THP page was munlocked, but nr_pages == 1.
+        * Returning a smaller mask due to that is OK, the worst that can
+        * happen is subsequent useless scanning of the former tail pages.
+        * The NR_MLOCK accounting can however become broken.
+        */
+       return nr_pages - 1;
 }
 
 /**
@@ -286,10 +298,12 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
 {
        int i;
        int nr = pagevec_count(pvec);
-       int delta_munlocked = -nr;
+       int delta_munlocked;
        struct pagevec pvec_putback;
        int pgrescued = 0;
 
+       pagevec_init(&pvec_putback, 0);
+
        /* Phase 1: page isolation */
        spin_lock_irq(&zone->lru_lock);
        for (i = 0; i < nr; i++) {
@@ -318,18 +332,21 @@ skip_munlock:
                        /*
                         * We won't be munlocking this page in the next phase
                         * but we still need to release the follow_page_mask()
-                        * pin.
+                        * pin. We cannot do it under lru_lock however. If it's
+                        * the last pin, __page_cache_release would deadlock.
                         */
+                       pagevec_add(&pvec_putback, pvec->pages[i]);
                        pvec->pages[i] = NULL;
-                       put_page(page);
-                       delta_munlocked++;
                }
        }
+       delta_munlocked = -nr + pagevec_count(&pvec_putback);
        __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
        spin_unlock_irq(&zone->lru_lock);
 
+       /* Now we can release pins of pages that we are not munlocking */
+       pagevec_release(&pvec_putback);
+
        /* Phase 2: page munlock */
-       pagevec_init(&pvec_putback, 0);
        for (i = 0; i < nr; i++) {
                struct page *page = pvec->pages[i];
 
@@ -440,7 +457,8 @@ void munlock_vma_pages_range(struct vm_area_struct *vma,
 
        while (start < end) {
                struct page *page = NULL;
-               unsigned int page_mask, page_increm;
+               unsigned int page_mask;
+               unsigned long page_increm;
                struct pagevec pvec;
                struct zone *zone;
                int zoneid;
@@ -490,7 +508,9 @@ void munlock_vma_pages_range(struct vm_area_struct *vma,
                                goto next;
                        }
                }
-               page_increm = 1 + (~(start >> PAGE_SHIFT) & page_mask);
+               /* It's a bug to munlock in the middle of a THP page */
+               VM_BUG_ON((start >> PAGE_SHIFT) & page_mask);
+               page_increm = 1 + page_mask;
                start += page_increm * PAGE_SIZE;
 next:
                cond_resched();
index 26667971c824b08ca3dae7188a965e1e4efe0b79..bb53a6591aea1373d6bc74d5bb3e847650af8d24 100644 (file)
@@ -52,17 +52,21 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                        pte_t ptent;
                        bool updated = false;
 
-                       ptent = ptep_modify_prot_start(mm, addr, pte);
                        if (!prot_numa) {
+                               ptent = ptep_modify_prot_start(mm, addr, pte);
+                               if (pte_numa(ptent))
+                                       ptent = pte_mknonnuma(ptent);
                                ptent = pte_modify(ptent, newprot);
                                updated = true;
                        } else {
                                struct page *page;
 
+                               ptent = *pte;
                                page = vm_normal_page(vma, addr, oldpte);
                                if (page) {
                                        if (!pte_numa(oldpte)) {
                                                ptent = pte_mknuma(ptent);
+                                               set_pte_at(mm, addr, pte, ptent);
                                                updated = true;
                                        }
                                }
@@ -79,7 +83,10 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 
                        if (updated)
                                pages++;
-                       ptep_modify_prot_commit(mm, addr, pte, ptent);
+
+                       /* Only !prot_numa always clears the pte */
+                       if (!prot_numa)
+                               ptep_modify_prot_commit(mm, addr, pte, ptent);
                } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) {
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
 
@@ -181,6 +188,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
        BUG_ON(addr >= end);
        pgd = pgd_offset(mm, addr);
        flush_cache_range(vma, addr, end);
+       set_tlb_flush_pending(mm);
        do {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
@@ -192,6 +200,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
        /* Only flush the TLB if we actually modified any entries: */
        if (pages)
                flush_tlb_range(vma, start, end);
+       clear_tlb_flush_pending(mm);
 
        return pages;
 }
index 580a5f075ed0ab6e3047351a8271b1f053e35774..5248fe070aa4e9f94b4be087aa8957e16cf16c1f 100644 (file)
@@ -1816,7 +1816,7 @@ static void zlc_clear_zones_full(struct zonelist *zonelist)
 
 static bool zone_local(struct zone *local_zone, struct zone *zone)
 {
-       return node_distance(local_zone->node, zone->node) == LOCAL_DISTANCE;
+       return local_zone->node == zone->node;
 }
 
 static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
@@ -1913,18 +1913,17 @@ zonelist_scan:
                 * page was allocated in should have no effect on the
                 * time the page has in memory before being reclaimed.
                 *
-                * When zone_reclaim_mode is enabled, try to stay in
-                * local zones in the fastpath.  If that fails, the
-                * slowpath is entered, which will do another pass
-                * starting with the local zones, but ultimately fall
-                * back to remote zones that do not partake in the
-                * fairness round-robin cycle of this zonelist.
+                * Try to stay in local zones in the fastpath.  If
+                * that fails, the slowpath is entered, which will do
+                * another pass starting with the local zones, but
+                * ultimately fall back to remote zones that do not
+                * partake in the fairness round-robin cycle of this
+                * zonelist.
                 */
                if (alloc_flags & ALLOC_WMARK_LOW) {
                        if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0)
                                continue;
-                       if (zone_reclaim_mode &&
-                           !zone_local(preferred_zone, zone))
+                       if (!zone_local(preferred_zone, zone))
                                continue;
                }
                /*
@@ -2390,7 +2389,7 @@ static void prepare_slowpath(gfp_t gfp_mask, unsigned int order,
                 * thrash fairness information for zones that are not
                 * actually part of this zonelist's round-robin cycle.
                 */
-               if (zone_reclaim_mode && !zone_local(preferred_zone, zone))
+               if (!zone_local(preferred_zone, zone))
                        continue;
                mod_zone_page_state(zone, NR_ALLOC_BATCH,
                                    high_wmark_pages(zone) -
index cbb38545d9d6ab8d96ebcdb001ed9e19db772f59..a8b9199259342df9cafb84be53010eb2206ebece 100644 (file)
@@ -110,9 +110,10 @@ int pmdp_clear_flush_young(struct vm_area_struct *vma,
 pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
                       pte_t *ptep)
 {
+       struct mm_struct *mm = (vma)->vm_mm;
        pte_t pte;
-       pte = ptep_get_and_clear((vma)->vm_mm, address, ptep);
-       if (pte_accessible(pte))
+       pte = ptep_get_and_clear(mm, address, ptep);
+       if (pte_accessible(mm, pte))
                flush_tlb_page(vma, address);
        return pte;
 }
@@ -191,6 +192,9 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                     pmd_t *pmdp)
 {
+       pmd_t entry = *pmdp;
+       if (pmd_numa(entry))
+               entry = pmd_mknonnuma(entry);
        set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(*pmdp));
        flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
 }
index 55c8b8dc9ffb0c349eb63ad20a8d7bbcc2e9b25d..068522d8502a58e9465a963e68c37ce4ccf635d7 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -600,7 +600,11 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
        spinlock_t *ptl;
 
        if (unlikely(PageHuge(page))) {
+               /* when pud is not present, pte will be NULL */
                pte = huge_pte_offset(mm, address);
+               if (!pte)
+                       return NULL;
+
                ptl = huge_pte_lockptr(page_hstate(page), mm, pte);
                goto check;
        }
index f7bc2096071cb925bc0e46d83d8156d38179dd0f..808f375648e77b6c1057aeee2c6d19ea26af981e 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -390,7 +390,10 @@ struct address_space *page_mapping(struct page *page)
 {
        struct address_space *mapping = page->mapping;
 
-       VM_BUG_ON(PageSlab(page));
+       /* This happens if someone calls flush_dcache_page on slab page */
+       if (unlikely(PageSlab(page)))
+               return NULL;
+
        if (unlikely(PageSwapCache(page))) {
                swp_entry_t entry;
 
index 762896ebfcf505348a659c83d8720b48e8b58c86..47c908f1f626a4d4a2de96b9f4a648ad386d4357 100644 (file)
@@ -530,6 +530,23 @@ static const struct header_ops vlan_header_ops = {
        .parse   = eth_header_parse,
 };
 
+static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev,
+                                    unsigned short type,
+                                    const void *daddr, const void *saddr,
+                                    unsigned int len)
+{
+       struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+       struct net_device *real_dev = vlan->real_dev;
+
+       return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
+}
+
+static const struct header_ops vlan_passthru_header_ops = {
+       .create  = vlan_passthru_hard_header,
+       .rebuild = dev_rebuild_header,
+       .parse   = eth_header_parse,
+};
+
 static struct device_type vlan_type = {
        .name   = "vlan",
 };
@@ -573,7 +590,7 @@ static int vlan_dev_init(struct net_device *dev)
 
        dev->needed_headroom = real_dev->needed_headroom;
        if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
-               dev->header_ops      = real_dev->header_ops;
+               dev->header_ops      = &vlan_passthru_header_ops;
                dev->hard_header_len = real_dev->hard_header_len;
        } else {
                dev->header_ops      = &vlan_header_ops;
index a2b480a908723a37d47d14bd76e63628518e6561..b9c8a6eedf4537e4216f09e65f71ef72a55d4ed3 100644 (file)
@@ -307,9 +307,9 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        hard_iface->bat_iv.ogm_buff = ogm_buff;
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
-       batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
-       batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
-       batadv_ogm_packet->header.ttl = 2;
+       batadv_ogm_packet->packet_type = BATADV_IV_OGM;
+       batadv_ogm_packet->version = BATADV_COMPAT_VERSION;
+       batadv_ogm_packet->ttl = 2;
        batadv_ogm_packet->flags = BATADV_NO_FLAGS;
        batadv_ogm_packet->reserved = 0;
        batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
@@ -346,7 +346,7 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
        batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
-       batadv_ogm_packet->header.ttl = BATADV_TTL;
+       batadv_ogm_packet->ttl = BATADV_TTL;
 }
 
 /* when do we schedule our own ogm to be sent */
@@ -435,7 +435,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
                           fwd_str, (packet_num > 0 ? "aggregated " : ""),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->tq, batadv_ogm_packet->ttl,
                           (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
                            "on" : "off"),
                           hard_iface->net_dev->name,
@@ -491,7 +491,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
        /* multihomed peer assumed
         * non-primary OGMs are only broadcasted on their interface
         */
-       if ((directlink && (batadv_ogm_packet->header.ttl == 1)) ||
+       if ((directlink && (batadv_ogm_packet->ttl == 1)) ||
            (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
                /* FIXME: what about aggregated packets ? */
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -499,7 +499,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
                           (forw_packet->own ? "Sending own" : "Forwarding"),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->ttl,
                           forw_packet->if_incoming->net_dev->name,
                           forw_packet->if_incoming->net_dev->dev_addr);
 
@@ -572,7 +572,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 */
                if ((!directlink) &&
                    (!(batadv_ogm_packet->flags & BATADV_DIRECTLINK)) &&
-                   (batadv_ogm_packet->header.ttl != 1) &&
+                   (batadv_ogm_packet->ttl != 1) &&
 
                    /* own packets originating non-primary
                     * interfaces leave only that interface
@@ -587,7 +587,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 * interface only - we still can aggregate
                 */
                if ((directlink) &&
-                   (new_bat_ogm_packet->header.ttl == 1) &&
+                   (new_bat_ogm_packet->ttl == 1) &&
                    (forw_packet->if_incoming == if_incoming) &&
 
                    /* packets from direct neighbors or
@@ -778,7 +778,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
        uint16_t tvlv_len;
 
-       if (batadv_ogm_packet->header.ttl <= 1) {
+       if (batadv_ogm_packet->ttl <= 1) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
                return;
        }
@@ -798,7 +798,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
 
-       batadv_ogm_packet->header.ttl--;
+       batadv_ogm_packet->ttl--;
        memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
 
        /* apply hop penalty */
@@ -807,7 +807,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                   "Forwarding packet: tq: %i, ttl: %i\n",
-                  batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl);
+                  batadv_ogm_packet->tq, batadv_ogm_packet->ttl);
 
        /* switch of primaries first hop flag when forwarding */
        batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP;
@@ -972,8 +972,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
        spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock);
 
        if (dup_status == BATADV_NO_DUP) {
-               orig_node->last_ttl = batadv_ogm_packet->header.ttl;
-               neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
+               orig_node->last_ttl = batadv_ogm_packet->ttl;
+               neigh_node->last_ttl = batadv_ogm_packet->ttl;
        }
 
        batadv_bonding_candidate_add(bat_priv, orig_node, neigh_node);
@@ -1247,7 +1247,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
         * packet in an aggregation.  Here we expect that the padding
         * is always zero (or not 0x01)
         */
-       if (batadv_ogm_packet->header.packet_type != BATADV_IV_OGM)
+       if (batadv_ogm_packet->packet_type != BATADV_IV_OGM)
                return;
 
        /* could be changed by schedule_own_packet() */
@@ -1267,8 +1267,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                   if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
                   batadv_ogm_packet->prev_sender,
                   ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
-                  batadv_ogm_packet->header.ttl,
-                  batadv_ogm_packet->header.version, has_directlink_flag);
+                  batadv_ogm_packet->ttl,
+                  batadv_ogm_packet->version, has_directlink_flag);
 
        rcu_read_lock();
        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
@@ -1433,7 +1433,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
         * seqno and similar ttl as the non-duplicate
         */
        sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
-       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
+       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->ttl;
        if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
                            (sameseq && similar_ttl)))
                batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
index 6c8c3934bd7b44bac8643683683c494e003f1ed2..b316a4cb6f147dbbafadb51cdccf687cef500373 100644 (file)
@@ -349,7 +349,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       switch (unicast_4addr_packet->u.header.packet_type) {
+       switch (unicast_4addr_packet->u.packet_type) {
        case BATADV_UNICAST:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within a UNICAST packet\n");
@@ -374,7 +374,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
                        break;
                default:
                        batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
-                                  unicast_4addr_packet->u.header.packet_type);
+                                  unicast_4addr_packet->u.packet_type);
                }
                break;
        case BATADV_BCAST:
@@ -387,7 +387,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
        default:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within an unknown packet type (0x%x)\n",
-                          unicast_4addr_packet->u.header.packet_type);
+                          unicast_4addr_packet->u.packet_type);
        }
 }
 
index 271d321b3a04063b4f9dfe476c7c07d9e2e50048..6ddb6145ffb564be9397728e83a4040f071c4a96 100644 (file)
@@ -355,7 +355,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
                batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
                                   skb->len + ETH_HLEN);
 
-               packet->header.ttl--;
+               packet->ttl--;
                batadv_send_skb_packet(skb, neigh_node->if_incoming,
                                       neigh_node->addr);
                ret = true;
@@ -444,9 +444,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
                goto out_err;
 
        /* Create one header to be copied to all fragments */
-       frag_header.header.packet_type = BATADV_UNICAST_FRAG;
-       frag_header.header.version = BATADV_COMPAT_VERSION;
-       frag_header.header.ttl = BATADV_TTL;
+       frag_header.packet_type = BATADV_UNICAST_FRAG;
+       frag_header.version = BATADV_COMPAT_VERSION;
+       frag_header.ttl = BATADV_TTL;
        frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
        frag_header.reserved = 0;
        frag_header.no = 0;
index 29ae4efe3543e4bfc6ff013b9c97628b9e395209..130cc3217e2b0fb091dccfad6a4f41d4b0c9dbc9 100644 (file)
@@ -194,7 +194,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
                goto free_skb;
        }
 
-       if (icmp_header->header.packet_type != BATADV_ICMP) {
+       if (icmp_header->packet_type != BATADV_ICMP) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
                len = -EINVAL;
@@ -243,9 +243,9 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
 
        icmp_header->uid = socket_client->index;
 
-       if (icmp_header->header.version != BATADV_COMPAT_VERSION) {
+       if (icmp_header->version != BATADV_COMPAT_VERSION) {
                icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
-               icmp_header->header.version = BATADV_COMPAT_VERSION;
+               icmp_header->version = BATADV_COMPAT_VERSION;
                batadv_socket_add_packet(socket_client, icmp_header,
                                         packet_len);
                goto free_skb;
index c51a5e568f0a80c08beb4ded5b34b1aff8d5cfdf..faba0f61ad535da90f8cd874ce5f901f771d4fb3 100644 (file)
@@ -277,7 +277,7 @@ int batadv_max_header_len(void)
                           sizeof(struct batadv_coded_packet));
 #endif
 
-       return header_len;
+       return header_len + ETH_HLEN;
 }
 
 /**
@@ -383,17 +383,17 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data;
 
-       if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
+       if (batadv_ogm_packet->version != BATADV_COMPAT_VERSION) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: incompatible batman version (%i)\n",
-                          batadv_ogm_packet->header.version);
+                          batadv_ogm_packet->version);
                goto err_free;
        }
 
        /* all receive handlers return whether they received or reused
         * the supplied skb. if not, we have to free the skb.
         */
-       idx = batadv_ogm_packet->header.packet_type;
+       idx = batadv_ogm_packet->packet_type;
        ret = (*batadv_rx_handler[idx])(skb, hard_iface);
 
        if (ret == NET_RX_DROP)
@@ -426,8 +426,8 @@ static void batadv_recv_handler_init(void)
        BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
        BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
        BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, icmph.dst) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, icmph.dst) != 4);
+       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
+       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
 
        /* broadcast packet */
        batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
@@ -1119,9 +1119,9 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
        skb_reserve(skb, ETH_HLEN);
        tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
        unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
-       unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV;
-       unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_tvlv_packet->header.ttl = BATADV_TTL;
+       unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
+       unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
+       unicast_tvlv_packet->ttl = BATADV_TTL;
        unicast_tvlv_packet->reserved = 0;
        unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
        unicast_tvlv_packet->align = 0;
index 351e199bc0afff37aa9c1a4b3f40201956dfde91..511d7e1eea38b6d6e13247df0f8d4399deea8382 100644 (file)
@@ -722,7 +722,7 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
 {
        if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
                return false;
-       if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
+       if (orig_node->last_ttl != ogm_packet->ttl + 1)
                return false;
        if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
                return false;
@@ -1082,9 +1082,9 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        coded_packet = (struct batadv_coded_packet *)skb_dest->data;
        skb_reset_mac_header(skb_dest);
 
-       coded_packet->header.packet_type = BATADV_CODED;
-       coded_packet->header.version = BATADV_COMPAT_VERSION;
-       coded_packet->header.ttl = packet1->header.ttl;
+       coded_packet->packet_type = BATADV_CODED;
+       coded_packet->version = BATADV_COMPAT_VERSION;
+       coded_packet->ttl = packet1->ttl;
 
        /* Info about first unicast packet */
        memcpy(coded_packet->first_source, first_source, ETH_ALEN);
@@ -1097,7 +1097,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        memcpy(coded_packet->second_source, second_source, ETH_ALEN);
        memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
        coded_packet->second_crc = packet_id2;
-       coded_packet->second_ttl = packet2->header.ttl;
+       coded_packet->second_ttl = packet2->ttl;
        coded_packet->second_ttvn = packet2->ttvn;
        coded_packet->coded_len = htons(coding_len);
 
@@ -1452,7 +1452,7 @@ bool batadv_nc_skb_forward(struct sk_buff *skb,
        /* We only handle unicast packets */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Try to find a coding opportunity and send the skb if one is found */
@@ -1505,7 +1505,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
        /* Check for supported packet type */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Find existing nc_path or create a new */
@@ -1623,7 +1623,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
                ttvn = coded_packet_tmp.second_ttvn;
        } else {
                orig_dest = coded_packet_tmp.first_orig_dest;
-               ttl = coded_packet_tmp.header.ttl;
+               ttl = coded_packet_tmp.ttl;
                ttvn = coded_packet_tmp.first_ttvn;
        }
 
@@ -1648,9 +1648,9 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        /* Create decoded unicast packet */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.packet_type = BATADV_UNICAST;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_packet->header.ttl = ttl;
+       unicast_packet->packet_type = BATADV_UNICAST;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
+       unicast_packet->ttl = ttl;
        memcpy(unicast_packet->dest, orig_dest, ETH_ALEN);
        unicast_packet->ttvn = ttvn;
 
index 207459b62966d0975bca70894fcf5ce266a5da29..2dd8f2422550c3157112eb4ce5a27362e6caf8fb 100644 (file)
@@ -155,6 +155,7 @@ enum batadv_tvlv_type {
        BATADV_TVLV_ROAM        = 0x05,
 };
 
+#pragma pack(2)
 /* the destination hardware field in the ARP frame is used to
  * transport the claim type and the group id
  */
@@ -163,24 +164,20 @@ struct batadv_bla_claim_dst {
        uint8_t type;           /* bla_claimframe */
        __be16 group;           /* group id */
 };
-
-struct batadv_header {
-       uint8_t  packet_type;
-       uint8_t  version;  /* batman version field */
-       uint8_t  ttl;
-       /* the parent struct has to add a byte after the header to make
-        * everything 4 bytes aligned again
-        */
-};
+#pragma pack()
 
 /**
  * struct batadv_ogm_packet - ogm (routing protocol) packet
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @flags: contains routing relevant flags - see enum batadv_iv_flags
  * @tvlv_len: length of tvlv data following the ogm header
  */
 struct batadv_ogm_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  flags;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -196,29 +193,51 @@ struct batadv_ogm_packet {
 #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
 
 /**
- * batadv_icmp_header - common ICMP header
- * @header: common batman header
+ * batadv_icmp_header - common members among all the ICMP packets
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @msg_type: ICMP packet type
  * @dst: address of the destination node
  * @orig: address of the source node
  * @uid: local ICMP socket identifier
+ * @align: not used - useful for alignment purposes only
+ *
+ * This structure is used for ICMP packets parsing only and it is never sent
+ * over the wire. The alignment field at the end is there to ensure that
+ * members are padded the same way as they are in real packets.
  */
 struct batadv_icmp_header {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  msg_type; /* see ICMP message types above */
        uint8_t  dst[ETH_ALEN];
        uint8_t  orig[ETH_ALEN];
        uint8_t  uid;
+       uint8_t  align[3];
 };
 
 /**
  * batadv_icmp_packet - ICMP packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @reserved: not used - useful for alignment
  * @seqno: ICMP sequence number
  */
 struct batadv_icmp_packet {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  reserved;
        __be16   seqno;
 };
@@ -227,13 +246,25 @@ struct batadv_icmp_packet {
 
 /**
  * batadv_icmp_packet_rr - ICMP RouteRecord packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @rr_cur: number of entries the rr array
  * @seqno: ICMP sequence number
  * @rr: route record array
  */
 struct batadv_icmp_packet_rr {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  rr_cur;
        __be16   seqno;
        uint8_t  rr[BATADV_RR_LEN][ETH_ALEN];
@@ -253,8 +284,18 @@ struct batadv_icmp_packet_rr {
  */
 #pragma pack(2)
 
+/**
+ * struct batadv_unicast_packet - unicast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @ttvn: translation table version number
+ * @dest: originator destination of the unicast packet
+ */
 struct batadv_unicast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  ttvn; /* destination translation table version number */
        uint8_t  dest[ETH_ALEN];
        /* "4 bytes boundary + 2 bytes" long to make the payload after the
@@ -280,7 +321,9 @@ struct batadv_unicast_4addr_packet {
 
 /**
  * struct batadv_frag_packet - fragmented packet
- * @header: common batman packet header with type, compatversion, and ttl
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @dest: final destination used when routing fragments
  * @orig: originator of the fragment used when merging the packet
  * @no: fragment number within this sequence
@@ -289,7 +332,9 @@ struct batadv_unicast_4addr_packet {
  * @total_size: size of the merged packet
  */
 struct batadv_frag_packet {
-       struct  batadv_header header;
+       uint8_t packet_type;
+       uint8_t version;  /* batman version field */
+       uint8_t ttl;
 #if defined(__BIG_ENDIAN_BITFIELD)
        uint8_t no:4;
        uint8_t reserved:4;
@@ -305,8 +350,19 @@ struct batadv_frag_packet {
        __be16  total_size;
 };
 
+/**
+ * struct batadv_bcast_packet - broadcast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @reserved: reserved byte for alignment
+ * @seqno: sequence identification
+ * @orig: originator of the broadcast packet
+ */
 struct batadv_bcast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -315,11 +371,11 @@ struct batadv_bcast_packet {
         */
 };
 
-#pragma pack()
-
 /**
  * struct batadv_coded_packet - network coded packet
- * @header: common batman packet header and ttl of first included packet
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: Align following fields to 2-byte boundaries
  * @first_source: original source of first included packet
  * @first_orig_dest: original destinal of first included packet
@@ -334,7 +390,9 @@ struct batadv_bcast_packet {
  * @coded_len: length of network coded part of the payload
  */
 struct batadv_coded_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  first_ttvn;
        /* uint8_t  first_dest[ETH_ALEN]; - saved in mac header destination */
        uint8_t  first_source[ETH_ALEN];
@@ -349,9 +407,13 @@ struct batadv_coded_packet {
        __be16   coded_len;
 };
 
+#pragma pack()
+
 /**
  * struct batadv_unicast_tvlv - generic unicast packet with tvlv payload
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: reserved field (for packet alignment)
  * @src: address of the source
  * @dst: address of the destination
@@ -359,7 +421,9 @@ struct batadv_coded_packet {
  * @align: 2 bytes to align the header to a 4 byte boundry
  */
 struct batadv_unicast_tvlv_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        uint8_t  dst[ETH_ALEN];
        uint8_t  src[ETH_ALEN];
@@ -420,13 +484,13 @@ struct batadv_tvlv_tt_vlan_data {
  * struct batadv_tvlv_tt_change - translation table diff data
  * @flags: status indicators concerning the non-mesh client (see
  *  batadv_tt_client_flags)
- * @reserved: reserved field
+ * @reserved: reserved field - useful for alignment purposes only
  * @addr: mac address of non-mesh client that triggered this tt change
  * @vid: VLAN identifier
  */
 struct batadv_tvlv_tt_change {
        uint8_t flags;
-       uint8_t reserved;
+       uint8_t reserved[3];
        uint8_t addr[ETH_ALEN];
        __be16 vid;
 };
index d4114d775ad61f659b59437c67aa7054d9a88f92..46278bfb8fdb9469e12f8fbdc8922e49f81f8014 100644 (file)
@@ -308,7 +308,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
                memcpy(icmph->dst, icmph->orig, ETH_ALEN);
                memcpy(icmph->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
                icmph->msg_type = BATADV_ECHO_REPLY;
-               icmph->header.ttl = BATADV_TTL;
+               icmph->ttl = BATADV_TTL;
 
                res = batadv_send_skb_to_orig(skb, orig_node, NULL);
                if (res != NET_XMIT_DROP)
@@ -338,9 +338,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
        /* send TTL exceeded if packet is an echo request (traceroute) */
-       if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
+       if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
                pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
-                        icmp_packet->icmph.orig, icmp_packet->icmph.dst);
+                        icmp_packet->orig, icmp_packet->dst);
                goto out;
        }
 
@@ -349,7 +349,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
                goto out;
 
        /* get routing information */
-       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
+       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig);
        if (!orig_node)
                goto out;
 
@@ -359,11 +359,11 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
-       memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
-       memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
+       memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+       memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr,
               ETH_ALEN);
-       icmp_packet->icmph.msg_type = BATADV_TTL_EXCEEDED;
-       icmp_packet->icmph.header.ttl = BATADV_TTL;
+       icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
+       icmp_packet->ttl = BATADV_TTL;
 
        if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = NET_RX_SUCCESS;
@@ -434,7 +434,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
                return batadv_recv_my_icmp_packet(bat_priv, skb);
 
        /* TTL exceeded */
-       if (icmph->header.ttl < 2)
+       if (icmph->ttl < 2)
                return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
 
        /* get routing information */
@@ -449,7 +449,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        icmph = (struct batadv_icmp_header *)skb->data;
 
        /* decrement ttl */
-       icmph->header.ttl--;
+       icmph->ttl--;
 
        /* route it */
        if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
@@ -709,7 +709,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
        /* TTL exceeded */
-       if (unicast_packet->header.ttl < 2) {
+       if (unicast_packet->ttl < 2) {
                pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
                         ethhdr->h_source, unicast_packet->dest);
                goto out;
@@ -727,9 +727,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
 
        /* decrement ttl */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.ttl--;
+       unicast_packet->ttl--;
 
-       switch (unicast_packet->header.packet_type) {
+       switch (unicast_packet->packet_type) {
        case BATADV_UNICAST_4ADDR:
                hdr_len = sizeof(struct batadv_unicast_4addr_packet);
                break;
@@ -970,7 +970,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR;
+       is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR;
        /* the caller function should have already pulled 2 bytes */
        if (is4addr)
                hdr_size = sizeof(*unicast_4addr_packet);
@@ -1160,7 +1160,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
                goto out;
 
-       if (bcast_packet->header.ttl < 2)
+       if (bcast_packet->ttl < 2)
                goto out;
 
        orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig);
index c83be5ebaa285dffe64d051850e87f2fca02624b..fba4dcfcfac21b6e9c6686c30fc6ca8a1a08f3fa 100644 (file)
@@ -161,11 +161,11 @@ batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
                return false;
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
        /* batman packet type: unicast */
-       unicast_packet->header.packet_type = BATADV_UNICAST;
+       unicast_packet->packet_type = BATADV_UNICAST;
        /* set unicast ttl */
-       unicast_packet->header.ttl = BATADV_TTL;
+       unicast_packet->ttl = BATADV_TTL;
        /* copy the destination for faster routing */
        memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
        /* set the destination tt version number */
@@ -221,7 +221,7 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
                goto out;
 
        uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
-       uc_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+       uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR;
        memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
        uc_4addr_packet->subtype = packet_subtype;
        uc_4addr_packet->reserved = 0;
@@ -436,7 +436,7 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
 
        /* as we have a copy now, it is safe to decrease the TTL */
        bcast_packet = (struct batadv_bcast_packet *)newskb->data;
-       bcast_packet->header.ttl--;
+       bcast_packet->ttl--;
 
        skb_reset_mac_header(newskb);
 
index 36f050876f8260245a008de079cf0974fa97b76e..a8f99d1486c0441e9aa192e81d7522ad451f4bd7 100644 (file)
@@ -264,11 +264,11 @@ static int batadv_interface_tx(struct sk_buff *skb,
                        goto dropped;
 
                bcast_packet = (struct batadv_bcast_packet *)skb->data;
-               bcast_packet->header.version = BATADV_COMPAT_VERSION;
-               bcast_packet->header.ttl = BATADV_TTL;
+               bcast_packet->version = BATADV_COMPAT_VERSION;
+               bcast_packet->ttl = BATADV_TTL;
 
                /* batman packet type: broadcast */
-               bcast_packet->header.packet_type = BATADV_BCAST;
+               bcast_packet->packet_type = BATADV_BCAST;
                bcast_packet->reserved = 0;
 
                /* hw address of first interface is the orig mac because only
@@ -328,7 +328,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
                         struct sk_buff *skb, struct batadv_hard_iface *recv_if,
                         int hdr_size, struct batadv_orig_node *orig_node)
 {
-       struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
+       struct batadv_bcast_packet *batadv_bcast_packet;
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
        __be16 ethertype = htons(ETH_P_BATMAN);
        struct vlan_ethhdr *vhdr;
@@ -336,7 +336,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
        unsigned short vid;
        bool is_bcast;
 
-       is_bcast = (batadv_header->packet_type == BATADV_BCAST);
+       batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
+       is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST);
 
        /* check if enough space is available for pulling, and pull */
        if (!pskb_may_pull(skb, hdr_size))
@@ -345,7 +346,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
        skb_pull_rcsum(skb, hdr_size);
        skb_reset_mac_header(skb);
 
-       vid = batadv_get_vid(skb, hdr_size);
+       /* clean the netfilter state now that the batman-adv header has been
+        * removed
+        */
+       nf_reset(skb);
+
+       vid = batadv_get_vid(skb, 0);
        ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
index 4add57d4857f11e5ea9edfa13aae1f46dab3e4f9..ff625fedbc5eeb08a7569c01973f5eb1ddc71eb1 100644 (file)
@@ -333,7 +333,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
                return;
 
        tt_change_node->change.flags = flags;
-       tt_change_node->change.reserved = 0;
+       memset(tt_change_node->change.reserved, 0,
+              sizeof(tt_change_node->change.reserved));
        memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
        tt_change_node->change.vid = htons(common->vid);
 
@@ -2221,7 +2222,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
                               ETH_ALEN);
                        tt_change->flags = tt_common_entry->flags;
                        tt_change->vid = htons(tt_common_entry->vid);
-                       tt_change->reserved = 0;
+                       memset(tt_change->reserved, 0,
+                              sizeof(tt_change->reserved));
 
                        tt_num_entries++;
                        tt_change++;
index 6a6c8bb4fd72d4f2d4294b9f7fed772d81e57b93..7552f9e3089ce790040268f1ce0a067d6ef728cb 100644 (file)
@@ -940,8 +940,22 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
        skb_pull(skb, 1);
 
-       if (hci_pi(sk)->channel == HCI_CHANNEL_RAW &&
-           bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
+       if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
+               /* No permission check is needed for user channel
+                * since that gets enforced when binding the socket.
+                *
+                * However check that the packet type is valid.
+                */
+               if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
+                       err = -EINVAL;
+                       goto drop;
+               }
+
+               skb_queue_tail(&hdev->raw_q, skb);
+               queue_work(hdev->workqueue, &hdev->tx_work);
+       } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
                u16 opcode = get_unaligned_le16(skb->data);
                u16 ogf = hci_opcode_ogf(opcode);
                u16 ocf = hci_opcode_ocf(opcode);
@@ -972,14 +986,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                        goto drop;
                }
 
-               if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
-                   bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
-                       err = -EINVAL;
-                       goto drop;
-               }
-
                skb_queue_tail(&hdev->raw_q, skb);
                queue_work(hdev->workqueue, &hdev->tx_work);
        }
index 4c214b2b88efa01d81be93a8b8d77e57229c1fa4..ef66365b7354da9f2fe2c4d87d2056d9a781f3c8 100644 (file)
@@ -1998,7 +1998,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
        u32 old;
        struct net_bridge_mdb_htable *mdb;
 
-       spin_lock(&br->multicast_lock);
+       spin_lock_bh(&br->multicast_lock);
        if (!netif_running(br->dev))
                goto unlock;
 
@@ -2030,7 +2030,7 @@ rollback:
        }
 
 unlock:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock_bh(&br->multicast_lock);
 
        return err;
 }
index ba3b7ea5ebb3139cca38e82ac6f5f5e346f4a4e0..0ce469e5ec8057c674901b404db13061fe8b7392 100644 (file)
@@ -2539,7 +2539,7 @@ static inline int skb_needs_linearize(struct sk_buff *skb,
 }
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv)
+                       struct netdev_queue *txq)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
        int rc = NETDEV_TX_OK;
@@ -2605,13 +2605,10 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        dev_queue_xmit_nit(skb, dev);
 
                skb_len = skb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(skb, dev, accel_priv);
-               else
                        rc = ops->ndo_start_xmit(skb, dev);
 
                trace_net_dev_xmit(skb, rc, dev, skb_len);
-               if (rc == NETDEV_TX_OK && txq)
+               if (rc == NETDEV_TX_OK)
                        txq_trans_update(txq);
                return rc;
        }
@@ -2627,10 +2624,7 @@ gso:
                        dev_queue_xmit_nit(nskb, dev);
 
                skb_len = nskb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(nskb, dev, accel_priv);
-               else
-                       rc = ops->ndo_start_xmit(nskb, dev);
+               rc = ops->ndo_start_xmit(nskb, dev);
                trace_net_dev_xmit(nskb, rc, dev, skb_len);
                if (unlikely(rc != NETDEV_TX_OK)) {
                        if (rc & ~NETDEV_TX_MASK)
@@ -2811,7 +2805,7 @@ EXPORT_SYMBOL(dev_loopback_xmit);
  *      the BH enable code must have IRQs enabled so that it will not deadlock.
  *          --BLG
  */
-int dev_queue_xmit(struct sk_buff *skb)
+int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
 {
        struct net_device *dev = skb->dev;
        struct netdev_queue *txq;
@@ -2827,7 +2821,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
        skb_update_prio(skb);
 
-       txq = netdev_pick_tx(dev, skb);
+       txq = netdev_pick_tx(dev, skb, accel_priv);
        q = rcu_dereference_bh(txq->qdisc);
 
 #ifdef CONFIG_NET_CLS_ACT
@@ -2863,7 +2857,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
                        if (!netif_xmit_stopped(txq)) {
                                __this_cpu_inc(xmit_recursion);
-                               rc = dev_hard_start_xmit(skb, dev, txq, NULL);
+                               rc = dev_hard_start_xmit(skb, dev, txq);
                                __this_cpu_dec(xmit_recursion);
                                if (dev_xmit_complete(rc)) {
                                        HARD_TX_UNLOCK(dev, txq);
@@ -2892,8 +2886,19 @@ out:
        rcu_read_unlock_bh();
        return rc;
 }
+
+int dev_queue_xmit(struct sk_buff *skb)
+{
+       return __dev_queue_xmit(skb, NULL);
+}
 EXPORT_SYMBOL(dev_queue_xmit);
 
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv)
+{
+       return __dev_queue_xmit(skb, accel_priv);
+}
+EXPORT_SYMBOL(dev_queue_xmit_accel);
+
 
 /*=======================================================================
                        Receiver routines
@@ -4500,7 +4505,7 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 {
        struct netdev_adjacent *upper;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
 
        upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
 
index 01b780856db29e5a2a7ebbc36aa7062340b28bb8..ad30d626a5bd3f5cbd585d0641ab79aa29c3c446 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <linux/filter.h>
-#include <linux/reciprocal_div.h>
 #include <linux/ratelimit.h>
 #include <linux/seccomp.h>
 #include <linux/if_vlan.h>
@@ -166,7 +165,7 @@ unsigned int sk_run_filter(const struct sk_buff *skb,
                        A /= X;
                        continue;
                case BPF_S_ALU_DIV_K:
-                       A = reciprocal_divide(A, K);
+                       A /= K;
                        continue;
                case BPF_S_ALU_MOD_X:
                        if (X == 0)
@@ -553,11 +552,6 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
                /* Some instructions need special checks */
                switch (code) {
                case BPF_S_ALU_DIV_K:
-                       /* check for division by zero */
-                       if (ftest->k == 0)
-                               return -EINVAL;
-                       ftest->k = reciprocal_value(ftest->k);
-                       break;
                case BPF_S_ALU_MOD_K:
                        /* check for division by zero */
                        if (ftest->k == 0)
@@ -853,27 +847,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
        to->code = decodes[code];
        to->jt = filt->jt;
        to->jf = filt->jf;
-
-       if (code == BPF_S_ALU_DIV_K) {
-               /*
-                * When loaded this rule user gave us X, which was
-                * translated into R = r(X). Now we calculate the
-                * RR = r(R) and report it back. If next time this
-                * value is loaded and RRR = r(RR) is calculated
-                * then the R == RRR will be true.
-                *
-                * One exception. X == 1 translates into R == 0 and
-                * we can't calculate RR out of it with r().
-                */
-
-               if (filt->k == 0)
-                       to->k = 1;
-               else
-                       to->k = reciprocal_value(filt->k);
-
-               BUG_ON(reciprocal_value(to->k) != filt->k);
-       } else
-               to->k = filt->k;
+       to->k = filt->k;
 }
 
 int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len)
index d6ef173225008ec1946ed232f781cc63754b9575..2fc5beaf578349cd543621a460bf2bb4eaa9d221 100644 (file)
@@ -395,17 +395,21 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 EXPORT_SYMBOL(__netdev_pick_tx);
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
-                                   struct sk_buff *skb)
+                                   struct sk_buff *skb,
+                                   void *accel_priv)
 {
        int queue_index = 0;
 
        if (dev->real_num_tx_queues != 1) {
                const struct net_device_ops *ops = dev->netdev_ops;
                if (ops->ndo_select_queue)
-                       queue_index = ops->ndo_select_queue(dev, skb);
+                       queue_index = ops->ndo_select_queue(dev, skb,
+                                                           accel_priv);
                else
                        queue_index = __netdev_pick_tx(dev, skb);
-               queue_index = dev_cap_txqueue(dev, queue_index);
+
+               if (!accel_priv)
+                       queue_index = dev_cap_txqueue(dev, queue_index);
        }
 
        skb_set_queue_mapping(skb, queue_index);
index ca15f32821fb8d536586354108488050b7cc6a0e..932c6d7cf6668e073a90432281037b51cf7dfecc 100644 (file)
@@ -1161,6 +1161,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                                                 neigh->parms->reachable_time :
                                                 0)));
                neigh->nud_state = new;
+               notify = 1;
        }
 
        if (lladdr != neigh->ha) {
@@ -1274,7 +1275,7 @@ int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
 
        if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
                            skb->len) < 0 &&
-           dev->header_ops->rebuild(skb))
+           dev_rebuild_header(skb))
                return 0;
 
        return dev_queue_xmit(skb);
index 8f971990677cd48026f651b2dba01d01190bfff6..19fe9c717cedb56051ff6cb5effca0274fd946d8 100644 (file)
@@ -375,7 +375,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
        if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) {
                struct netdev_queue *txq;
 
-               txq = netdev_pick_tx(dev, skb);
+               txq = netdev_pick_tx(dev, skb, NULL);
 
                /* try until next clock tick */
                for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
@@ -386,8 +386,14 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                            !vlan_hw_offload_capable(netif_skb_features(skb),
                                                                     skb->vlan_proto)) {
                                                skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb));
-                                               if (unlikely(!skb))
-                                                       break;
+                                               if (unlikely(!skb)) {
+                                                       /* This is actually a packet drop, but we
+                                                        * don't want the code at the end of this
+                                                        * function to try and re-queue a NULL skb.
+                                                        */
+                                                       status = NETDEV_TX_OK;
+                                                       goto unlock_txq;
+                                               }
                                                skb->vlan_tci = 0;
                                        }
 
@@ -395,6 +401,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                        if (status == NETDEV_TX_OK)
                                                txq_trans_update(txq);
                                }
+                       unlock_txq:
                                __netif_tx_unlock(txq);
 
                                if (status == NETDEV_TX_OK)
index 4c6bdf97a6577d190332b85654769a92ce553111..595ddf0459db79c724b8eab2c8b0f6a0a7d1df97 100644 (file)
@@ -152,17 +152,6 @@ static const struct file_operations dccpprobe_fops = {
        .llseek  = noop_llseek,
 };
 
-static __init int setup_jprobe(void)
-{
-       int ret = register_jprobe(&dccp_send_probe);
-
-       if (ret) {
-               request_module("dccp");
-               ret = register_jprobe(&dccp_send_probe);
-       }
-       return ret;
-}
-
 static __init int dccpprobe_init(void)
 {
        int ret = -ENOMEM;
@@ -174,7 +163,13 @@ static __init int dccpprobe_init(void)
        if (!proc_create(procname, S_IRUSR, init_net.proc_net, &dccpprobe_fops))
                goto err0;
 
-       ret = setup_jprobe();
+       ret = register_jprobe(&dccp_send_probe);
+       if (ret) {
+               ret = request_module("dccp");
+               if (!ret)
+                       ret = register_jprobe(&dccp_send_probe);
+       }
+
        if (ret)
                goto err1;
 
index 459e200c08a40e4e737798582524cd973064b143..a2d2456a557a7621059a5b0bbe033168492f8fe7 100644 (file)
@@ -547,7 +547,7 @@ static int lowpan_header_create(struct sk_buff *skb,
                        hc06_ptr += 3;
                } else {
                        /* compress nothing */
-                       memcpy(hc06_ptr, &hdr, 4);
+                       memcpy(hc06_ptr, hdr, 4);
                        /* replace the top byte with new ECN | DSCP format */
                        *hc06_ptr = tmp;
                        hc06_ptr += 4;
index d08c7a43dcd1c72f1512b01e8a00dd2b9e6b1869..89b265aea151eaf7f301c28f391d064b7d22edfc 100644 (file)
@@ -221,8 +221,10 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info)
 
        if (info->attrs[IEEE802154_ATTR_DEV_TYPE]) {
                type = nla_get_u8(info->attrs[IEEE802154_ATTR_DEV_TYPE]);
-               if (type >= __IEEE802154_DEV_MAX)
-                       return -EINVAL;
+               if (type >= __IEEE802154_DEV_MAX) {
+                       rc = -EINVAL;
+                       goto nla_put_failure;
+               }
        }
 
        dev = phy->add_iface(phy, devname, type);
index e5d436188464eba55eca773f4fb88fd0f0634e97..2cd02f32f99f568c8275389aefd754700a77efa6 100644 (file)
@@ -28,6 +28,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        netdev_features_t enc_features;
        int ghl = GRE_HEADER_SECTION;
        struct gre_base_hdr *greh;
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        __be16 protocol = skb->protocol;
        int tnl_hlen;
@@ -58,13 +59,13 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        } else
                csum = false;
 
+       if (unlikely(!pskb_may_pull(skb, ghl)))
+               goto out;
+
        /* setup inner skb. */
        skb->protocol = greh->protocol;
        skb->encapsulation = 0;
 
-       if (unlikely(!pskb_may_pull(skb, ghl)))
-               goto out;
-
        __skb_pull(skb, ghl);
        skb_reset_mac_header(skb);
        skb_set_network_header(skb, skb_inner_network_offset(skb));
@@ -73,8 +74,10 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len);
                goto out;
+       }
 
        skb = segs;
        tnl_hlen = skb_tnl_header_len(skb);
index 56a964a553d2c739a03b880acd7158a4c9714b66..e34dccbc4d70bd26f7cec88c031dcea31124314a 100644 (file)
@@ -106,6 +106,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = inet->inet_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = inet->inet_rcv_saddr;
        r->id.idiag_dst[0] = inet->inet_daddr;
 
@@ -240,12 +244,19 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 
        r->idiag_family       = tw->tw_family;
        r->idiag_retrans      = 0;
+
        r->id.idiag_if        = tw->tw_bound_dev_if;
        sock_diag_save_cookie(tw, r->id.idiag_cookie);
+
        r->id.idiag_sport     = tw->tw_sport;
        r->id.idiag_dport     = tw->tw_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0]    = tw->tw_rcv_saddr;
        r->id.idiag_dst[0]    = tw->tw_daddr;
+
        r->idiag_state        = tw->tw_substate;
        r->idiag_timer        = 3;
        r->idiag_expires      = jiffies_to_msecs(tmo);
@@ -726,8 +737,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = ireq->ir_rmt_port;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = ireq->ir_loc_addr;
        r->id.idiag_dst[0] = ireq->ir_rmt_addr;
+
        r->idiag_expires = jiffies_to_msecs(tmo);
        r->idiag_rqueue = 0;
        r->idiag_wqueue = 0;
@@ -914,12 +930,15 @@ skip_listen_ht:
                spin_lock_bh(lock);
                sk_nulls_for_each(sk, node, &head->chain) {
                        int res;
+                       int state;
 
                        if (!net_eq(sock_net(sk), net))
                                continue;
                        if (num < s_num)
                                goto next_normal;
-                       if (!(r->idiag_states & (1 << sk->sk_state)))
+                       state = (sk->sk_state == TCP_TIME_WAIT) ?
+                               inet_twsk(sk)->tw_substate : sk->sk_state;
+                       if (!(r->idiag_states & (1 << state)))
                                goto next_normal;
                        if (r->sdiag_family != AF_UNSPEC &&
                            sk->sk_family != r->sdiag_family)
index d7aea4c5b9400efec37d15db3c5a896769d0da68..e560ef34cf4bd2efe9f1f7a64424441117a4502a 100644 (file)
@@ -217,6 +217,7 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
                                  iph->saddr, iph->daddr, tpi->key);
 
        if (tunnel) {
+               skb_pop_mac_header(skb);
                ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error);
                return PACKET_RCVD;
        }
index 912402752f2ffce701d697de1bb7a32b05c3b482..df184616493f707ea8a0ea353a33d3a5aa981fc7 100644 (file)
@@ -828,7 +828,7 @@ static int __ip_append_data(struct sock *sk,
 
        if (cork->length + length > maxnonfragsize - fragheaderlen) {
                ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
-                              mtu-exthdrlen);
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
@@ -1151,7 +1151,8 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
                         mtu : 0xFFFF;
 
        if (cork->length + size > maxnonfragsize - fragheaderlen) {
-               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu);
+               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
index 62212c772a4b95961dafe1efce3fd06f146ccbb6..1672409f5ba5a10ea05eb20d0f472a46dee3c504 100644 (file)
@@ -157,9 +157,12 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
 static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
                           struct mr_table **mrt)
 {
-       struct ipmr_result res;
-       struct fib_lookup_arg arg = { .result = &res, };
        int err;
+       struct ipmr_result res;
+       struct fib_lookup_arg arg = {
+               .result = &res,
+               .flags = FIB_LOOKUP_NOREF,
+       };
 
        err = fib_rules_lookup(net->ipv4.mr_rules_ops,
                               flowi4_to_flowi(flp4), 0, &arg);
index f13bd91d9a56774f58dcf14de892b2bedd855cc5..a313c3fbeb469e0594b2f7bccd788d687184bc61 100644 (file)
@@ -423,6 +423,7 @@ static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par)
 static struct xt_target synproxy_tg4_reg __read_mostly = {
        .name           = "SYNPROXY",
        .family         = NFPROTO_IPV4,
+       .hooks          = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
        .target         = synproxy_tg4,
        .targetsize     = sizeof(struct xt_synproxy_info),
        .checkentry     = synproxy_tg4_check,
index fff5ba1a33b76321f70d1365d072f7330d524ea9..4a5e94ac314a8cfdae20d8e393724ea2d01bd588 100644 (file)
@@ -72,7 +72,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
        const struct nft_reject *priv = nft_expr_priv(expr);
 
-       if (nla_put_be32(skb, NFTA_REJECT_TYPE, priv->type))
+       if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
                goto nla_put_failure;
 
        switch (priv->type) {
index 06493736fbc826842876180a24510d9e348cb7f3..098b3a29f6f3a082af32af35d703bf884922ec77 100644 (file)
@@ -22,6 +22,9 @@
 
 int sysctl_tcp_nometrics_save __read_mostly;
 
+static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr,
+                                                  struct net *net, unsigned int hash);
+
 struct tcp_fastopen_metrics {
        u16     mss;
        u16     syn_loss:10;            /* Recurring Fast Open SYN losses */
@@ -130,16 +133,41 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst,
        }
 }
 
+#define TCP_METRICS_TIMEOUT            (60 * 60 * HZ)
+
+static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
+{
+       if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
+               tcpm_suck_dst(tm, dst, false);
+}
+
+#define TCP_METRICS_RECLAIM_DEPTH      5
+#define TCP_METRICS_RECLAIM_PTR                (struct tcp_metrics_block *) 0x1UL
+
 static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
                                          struct inetpeer_addr *addr,
-                                         unsigned int hash,
-                                         bool reclaim)
+                                         unsigned int hash)
 {
        struct tcp_metrics_block *tm;
        struct net *net;
+       bool reclaim = false;
 
        spin_lock_bh(&tcp_metrics_lock);
        net = dev_net(dst->dev);
+
+       /* While waiting for the spin-lock the cache might have been populated
+        * with this entry and so we have to check again.
+        */
+       tm = __tcp_get_metrics(addr, net, hash);
+       if (tm == TCP_METRICS_RECLAIM_PTR) {
+               reclaim = true;
+               tm = NULL;
+       }
+       if (tm) {
+               tcpm_check_stamp(tm, dst);
+               goto out_unlock;
+       }
+
        if (unlikely(reclaim)) {
                struct tcp_metrics_block *oldest;
 
@@ -169,17 +197,6 @@ out_unlock:
        return tm;
 }
 
-#define TCP_METRICS_TIMEOUT            (60 * 60 * HZ)
-
-static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
-{
-       if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
-               tcpm_suck_dst(tm, dst, false);
-}
-
-#define TCP_METRICS_RECLAIM_DEPTH      5
-#define TCP_METRICS_RECLAIM_PTR                (struct tcp_metrics_block *) 0x1UL
-
 static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, int depth)
 {
        if (tm)
@@ -282,7 +299,6 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
        struct inetpeer_addr addr;
        unsigned int hash;
        struct net *net;
-       bool reclaim;
 
        addr.family = sk->sk_family;
        switch (addr.family) {
@@ -304,13 +320,10 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
        hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
 
        tm = __tcp_get_metrics(&addr, net, hash);
-       reclaim = false;
-       if (tm == TCP_METRICS_RECLAIM_PTR) {
-               reclaim = true;
+       if (tm == TCP_METRICS_RECLAIM_PTR)
                tm = NULL;
-       }
        if (!tm && create)
-               tm = tcpm_new(dst, &addr, hash, reclaim);
+               tm = tcpm_new(dst, &addr, hash);
        else
                tcpm_check_stamp(tm, dst);
 
index 62c19fdd102d9bb1f3d8757c6de1debd6533ed50..a7e4729e974b3206f57e3b3da4026a77432768e1 100644 (file)
@@ -1600,20 +1600,15 @@ static void flush_stack(struct sock **stack, unsigned int count,
 }
 
 /* For TCP sockets, sk_rx_dst is protected by socket lock
- * For UDP, we use sk_dst_lock to guard against concurrent changes.
+ * For UDP, we use xchg() to guard against concurrent changes.
  */
 static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
 {
        struct dst_entry *old;
 
-       spin_lock(&sk->sk_dst_lock);
-       old = sk->sk_rx_dst;
-       if (likely(old != dst)) {
-               dst_hold(dst);
-               sk->sk_rx_dst = dst;
-               dst_release(old);
-       }
-       spin_unlock(&sk->sk_dst_lock);
+       dst_hold(dst);
+       old = xchg(&sk->sk_rx_dst, dst);
+       dst_release(old);
 }
 
 /*
@@ -2483,6 +2478,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
                                       netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
        __be16 protocol = skb->protocol;
@@ -2502,8 +2498,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
+                                    mac_len);
                goto out;
+       }
 
        outer_hlen = skb_tnl_header_len(skb);
        skb = segs;
index 83206de2bc7679dc20e4fdcf34f8b1f5cd7831ef..79c62bdcd3c549b7dc07c74449d30b77296134eb 100644 (file)
@@ -41,6 +41,14 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        unsigned int mss;
+       int offset;
+       __wsum csum;
+
+       if (skb->encapsulation &&
+           skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) {
+               segs = skb_udp_tunnel_segment(skb, features);
+               goto out;
+       }
 
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@ -63,27 +71,20 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
                goto out;
        }
 
+       /* Do software UFO. Complete and fill in the UDP checksum as
+        * HW cannot do checksum of UDP packets sent as multiple
+        * IP fragments.
+        */
+       offset = skb_checksum_start_offset(skb);
+       csum = skb_checksum(skb, offset, skb->len - offset, 0);
+       offset += skb->csum_offset;
+       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+       skb->ip_summed = CHECKSUM_NONE;
+
        /* Fragment the skb. IP headers of the fragments are updated in
         * inet_gso_segment()
         */
-       if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
-               segs = skb_udp_tunnel_segment(skb, features);
-       else {
-               int offset;
-               __wsum csum;
-
-               /* Do software UFO. Complete and fill in the UDP checksum as
-                * HW cannot do checksum of UDP packets sent as multiple
-                * IP fragments.
-                */
-               offset = skb_checksum_start_offset(skb);
-               csum = skb_checksum(skb, offset, skb->len - offset, 0);
-               offset += skb->csum_offset;
-               *(__sum16 *)(skb->data + offset) = csum_fold(csum);
-               skb->ip_summed = CHECKSUM_NONE;
-
-               segs = skb_segment(skb, features);
-       }
+       segs = skb_segment(skb, features);
 out:
        return segs;
 }
index d5fa5b8c443ecbbcb0ed09a10db19b06730b7d8b..4b6b720971b9294910280c6ebd9d46a34ea07e35 100644 (file)
@@ -1671,7 +1671,7 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -1682,7 +1682,7 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -2509,7 +2509,8 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        struct inet6_ifaddr *ifp;
 
        ifp = ipv6_add_addr(idev, addr, NULL, plen,
-                           scope, IFA_F_PERMANENT, 0, 0);
+                           scope, IFA_F_PERMANENT,
+                           INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        if (!IS_ERR(ifp)) {
                spin_lock_bh(&ifp->lock);
                ifp->flags &= ~IFA_F_TENTATIVE;
@@ -2637,7 +2638,8 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr
 #endif
 
 
-       ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, 0, 0);
+       ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
+                           INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        if (!IS_ERR(ifp)) {
                addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
                addrconf_dad_start(ifp);
@@ -3187,6 +3189,22 @@ out:
        in6_ifa_put(ifp);
 }
 
+/* ifp->idev must be at least read locked */
+static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp)
+{
+       struct inet6_ifaddr *ifpiter;
+       struct inet6_dev *idev = ifp->idev;
+
+       list_for_each_entry(ifpiter, &idev->addr_list, if_list) {
+               if (ifp != ifpiter && ifpiter->scope == IFA_LINK &&
+                   (ifpiter->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|
+                                      IFA_F_OPTIMISTIC|IFA_F_DADFAILED)) ==
+                   IFA_F_PERMANENT)
+                       return false;
+       }
+       return true;
+}
+
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 {
        struct net_device *dev = ifp->idev->dev;
@@ -3206,14 +3224,11 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
         */
 
        read_lock_bh(&ifp->idev->lock);
-       spin_lock(&ifp->lock);
-       send_mld = ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL &&
-                  ifp->idev->valid_ll_addr_cnt == 1;
+       send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
        send_rs = send_mld &&
                  ipv6_accept_ra(ifp->idev) &&
                  ifp->idev->cnf.rtr_solicits > 0 &&
                  (dev->flags&IFF_LOOPBACK) == 0;
-       spin_unlock(&ifp->lock);
        read_unlock_bh(&ifp->idev->lock);
 
        /* While dad is in progress mld report's source address is in6_addrany.
@@ -3456,7 +3471,12 @@ restart:
                                         &inet6_addr_lst[i], addr_lst) {
                        unsigned long age;
 
-                       if (ifp->flags & IFA_F_PERMANENT)
+                       /* When setting preferred_lft to a value not zero or
+                        * infinity, while valid_lft is infinity
+                        * IFA_F_PERMANENT has a non-infinity life time.
+                        */
+                       if ((ifp->flags & IFA_F_PERMANENT) &&
+                           (ifp->prefered_lft == INFINITY_LIFE_TIME))
                                continue;
 
                        spin_lock(&ifp->lock);
@@ -3481,7 +3501,8 @@ restart:
                                        ifp->flags |= IFA_F_DEPRECATED;
                                }
 
-                               if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
+                               if ((ifp->valid_lft != INFINITY_LIFE_TIME) &&
+                                   (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)))
                                        next = ifp->tstamp + ifp->valid_lft * HZ;
 
                                spin_unlock(&ifp->lock);
@@ -3761,7 +3782,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
        put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
                      ifa->idev->dev->ifindex);
 
-       if (!(ifa->flags&IFA_F_PERMANENT)) {
+       if (!((ifa->flags&IFA_F_PERMANENT) &&
+             (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
                preferred = ifa->prefered_lft;
                valid = ifa->valid_lft;
                if (preferred != INFINITY_LIFE_TIME) {
@@ -4503,19 +4525,6 @@ errout:
                rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
 }
 
-static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count)
-{
-       write_lock_bh(&ifp->idev->lock);
-       spin_lock(&ifp->lock);
-       if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|
-                           IFA_F_DADFAILED)) == IFA_F_PERMANENT) &&
-           (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL))
-               ifp->idev->valid_ll_addr_cnt += count;
-       WARN_ON(ifp->idev->valid_ll_addr_cnt < 0);
-       spin_unlock(&ifp->lock);
-       write_unlock_bh(&ifp->idev->lock);
-}
-
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 {
        struct net *net = dev_net(ifp->idev->dev);
@@ -4524,8 +4533,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
        switch (event) {
        case RTM_NEWADDR:
-               update_valid_ll_addr_cnt(ifp, 1);
-
                /*
                 * If the address was optimistic
                 * we inserted the route at the start of
@@ -4541,8 +4548,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
                                              ifp->idev->dev, 0, 0);
                break;
        case RTM_DELADDR:
-               update_valid_ll_addr_cnt(ifp, -1);
-
                if (ifp->idev->cnf.forwarding)
                        addrconf_leave_anycast(ifp);
                addrconf_leave_solict(ifp->idev, &ifp->addr);
index 4acdb63495dbe2484de9d278b810401e6d26fc6a..e6f931997996ef46efa1272b16e261bf8f6609a7 100644 (file)
@@ -1193,11 +1193,35 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 
        fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
                        (opt ? opt->opt_nflen : 0);
-       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
+       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen -
+                    sizeof(struct frag_hdr);
 
        if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
-               if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
-                       ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen);
+               unsigned int maxnonfragsize, headersize;
+
+               headersize = sizeof(struct ipv6hdr) +
+                            (opt ? opt->tot_len : 0) +
+                            (dst_allfrag(&rt->dst) ?
+                             sizeof(struct frag_hdr) : 0) +
+                            rt->rt6i_nfheader_len;
+
+               maxnonfragsize = (np->pmtudisc >= IPV6_PMTUDISC_DO) ?
+                                mtu : sizeof(struct ipv6hdr) + IPV6_MAXPLEN;
+
+               /* dontfrag active */
+               if ((cork->length + length > mtu - headersize) && dontfrag &&
+                   (sk->sk_protocol == IPPROTO_UDP ||
+                    sk->sk_protocol == IPPROTO_RAW)) {
+                       ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
+                                                  sizeof(struct ipv6hdr));
+                       goto emsgsize;
+               }
+
+               if (cork->length + length > maxnonfragsize - headersize) {
+emsgsize:
+                       ipv6_local_error(sk, EMSGSIZE, fl6,
+                                        mtu - headersize +
+                                        sizeof(struct ipv6hdr));
                        return -EMSGSIZE;
                }
        }
@@ -1222,12 +1246,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
         * --yoshfuji
         */
 
-       if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
-                                          sk->sk_protocol == IPPROTO_RAW)) {
-               ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
-               return -EMSGSIZE;
-       }
-
        skb = skb_peek_tail(&sk->sk_write_queue);
        cork->length += length;
        if (((length > mtu) ||
index d6062325db08411207fd63b435ec1e5e4e0f2001..7881965a824840a763a7e1183efcf21153f87b47 100644 (file)
@@ -103,16 +103,25 @@ struct ip6_tnl_net {
 
 static struct net_device_stats *ip6_get_stats(struct net_device *dev)
 {
-       struct pcpu_tstats sum = { 0 };
+       struct pcpu_tstats tmp, sum = { 0 };
        int i;
 
        for_each_possible_cpu(i) {
+               unsigned int start;
                const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
 
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
+               do {
+                       start = u64_stats_fetch_begin_bh(&tstats->syncp);
+                       tmp.rx_packets = tstats->rx_packets;
+                       tmp.rx_bytes = tstats->rx_bytes;
+                       tmp.tx_packets = tstats->tx_packets;
+                       tmp.tx_bytes =  tstats->tx_bytes;
+               } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+               sum.rx_packets += tmp.rx_packets;
+               sum.rx_bytes   += tmp.rx_bytes;
+               sum.tx_packets += tmp.tx_packets;
+               sum.tx_bytes   += tmp.tx_bytes;
        }
        dev->stats.rx_packets = sum.rx_packets;
        dev->stats.rx_bytes   = sum.rx_bytes;
@@ -824,8 +833,10 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
index ed94ba61dda0ec1c3e2b170fe74eb2334b752700..7b42d5ef868deaa193094a85a00b502aeaba0bdd 100644 (file)
@@ -75,26 +75,6 @@ struct vti6_net {
        struct ip6_tnl __rcu **tnls[2];
 };
 
-static struct net_device_stats *vti6_get_stats(struct net_device *dev)
-{
-       struct pcpu_tstats sum = { 0 };
-       int i;
-
-       for_each_possible_cpu(i) {
-               const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
-       }
-       dev->stats.rx_packets = sum.rx_packets;
-       dev->stats.rx_bytes   = sum.rx_bytes;
-       dev->stats.tx_packets = sum.tx_packets;
-       dev->stats.tx_bytes   = sum.tx_bytes;
-       return &dev->stats;
-}
-
 #define for_each_vti6_tunnel_rcu(start) \
        for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
@@ -331,8 +311,10 @@ static int vti6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                skb->mark = 0;
                secpath_reset(skb);
@@ -716,7 +698,7 @@ static const struct net_device_ops vti6_netdev_ops = {
        .ndo_start_xmit = vti6_tnl_xmit,
        .ndo_do_ioctl   = vti6_ioctl,
        .ndo_change_mtu = vti6_change_mtu,
-       .ndo_get_stats  = vti6_get_stats,
+       .ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
 /**
@@ -750,12 +732,18 @@ static void vti6_dev_setup(struct net_device *dev)
 static inline int vti6_dev_init_gen(struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
+       int i;
 
        t->dev = dev;
        t->net = dev_net(dev);
        dev->tstats = alloc_percpu(struct pcpu_tstats);
        if (!dev->tstats)
                return -ENOMEM;
+       for_each_possible_cpu(i) {
+               struct pcpu_tstats *stats;
+               stats = per_cpu_ptr(dev->tstats, i);
+               u64_stats_init(&stats->syncp);
+       }
        return 0;
 }
 
index f365310bfcca30420a9cce321c1875d7f4319c21..0eb4038a4d63434738e938113b37bfe6611e07c3 100644 (file)
@@ -141,9 +141,12 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
 static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
                            struct mr6_table **mrt)
 {
-       struct ip6mr_result res;
-       struct fib_lookup_arg arg = { .result = &res, };
        int err;
+       struct ip6mr_result res;
+       struct fib_lookup_arg arg = {
+               .result = &res,
+               .flags = FIB_LOOKUP_NOREF,
+       };
 
        err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
                               flowi6_to_flowi(flp6), 0, &arg);
index f78f41aca8e90967a026a145f938746ce317cf10..a0d17270117c37793be3cb61c4d767cd57f70611 100644 (file)
@@ -446,6 +446,7 @@ static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)
 static struct xt_target synproxy_tg6_reg __read_mostly = {
        .name           = "SYNPROXY",
        .family         = NFPROTO_IPV6,
+       .hooks          = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
        .target         = synproxy_tg6,
        .targetsize     = sizeof(struct xt_synproxy_info),
        .checkentry     = synproxy_tg6_check,
index a0a48ac3403f3a9284786aa5b8f00dc03696e2e0..4b4944c3e4c4473c8b1ca4fbce8700a8af988604 100644 (file)
@@ -1905,9 +1905,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                else
                        rt->rt6i_gateway = *dest;
                rt->rt6i_flags = ort->rt6i_flags;
-               if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
-                   (RTF_DEFAULT | RTF_ADDRCONF))
-                       rt6_set_from(rt, ort);
+               rt6_set_from(rt, ort);
                rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES
index 366fbba3359ab790e1b22917931acdbdb1daebf3..d3005b34476a82f8172cfe8807507d561d307938 100644 (file)
@@ -702,8 +702,10 @@ static int ipip6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(tunnel->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
@@ -924,7 +926,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                if (tunnel->parms.iph.daddr && skb_dst(skb))
                        skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
 
-               if (skb->len > mtu) {
+               if (skb->len > mtu && !skb_is_gso(skb)) {
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                        ip_rt_put(rt);
                        goto tx_error;
@@ -966,8 +968,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
 
        skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT);
-       if (IS_ERR(skb))
+       if (IS_ERR(skb)) {
+               ip_rt_put(rt);
                goto out;
+       }
 
        err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos,
                            ttl, df, !net_eq(tunnel->net, dev_net(dev)));
index 7b01b9f5846c845bcf4f04b21cfbcb5786c19421..c71b699eb555165e124ec21109e37212587c7741 100644 (file)
@@ -715,7 +715,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
        unsigned long cpu_flags;
        size_t copied = 0;
        u32 peek_seq = 0;
-       u32 *seq;
+       u32 *seq, skb_len;
        unsigned long used;
        int target;     /* Read at least this many bytes */
        long timeo;
@@ -812,6 +812,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
                continue;
        found_ok_skb:
+               skb_len = skb->len;
                /* Ok so how much can we use? */
                used = skb->len - offset;
                if (len < used)
@@ -844,7 +845,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                /* Partial read */
-               if (used + offset < skb->len)
+               if (used + offset < skb_len)
                        continue;
        } while (len > 0);
 
index 36c3a4cbcabf66b2a0864414b3c23ea2896b7c4e..a0757913046eab8eee0c99104d8900db4e338c3e 100644 (file)
@@ -1061,7 +1061,8 @@ static void ieee80211_uninit(struct net_device *dev)
 }
 
 static u16 ieee80211_netdev_select_queue(struct net_device *dev,
-                                        struct sk_buff *skb)
+                                        struct sk_buff *skb,
+                                        void *accel_priv)
 {
        return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
 }
@@ -1078,7 +1079,8 @@ static const struct net_device_ops ieee80211_dataif_ops = {
 };
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
-                                         struct sk_buff *skb)
+                                         struct sk_buff *skb,
+                                         void *accel_priv)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
index c558b246ef0036c38e6c8a00b338b43c46913f78..ca7fa7f0613dba22cdc0e82d8a96e1de9ff011dc 100644 (file)
@@ -463,7 +463,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 {
        struct sta_info *sta = tx->sta;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_local *local = tx->local;
 
        if (unlikely(!sta))
@@ -474,15 +473,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
                int ac = skb_get_queue_mapping(tx->skb);
 
-               /* only deauth, disassoc and action are bufferable MMPDUs */
-               if (ieee80211_is_mgmt(hdr->frame_control) &&
-                   !ieee80211_is_deauth(hdr->frame_control) &&
-                   !ieee80211_is_disassoc(hdr->frame_control) &&
-                   !ieee80211_is_action(hdr->frame_control)) {
-                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
-                       return TX_CONTINUE;
-               }
-
                ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
                       sta->sta.addr, sta->sta.aid, ac);
                if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@@ -525,9 +515,22 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
 {
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
        if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
                return TX_CONTINUE;
 
+       /* only deauth, disassoc and action are bufferable MMPDUs */
+       if (ieee80211_is_mgmt(hdr->frame_control) &&
+           !ieee80211_is_deauth(hdr->frame_control) &&
+           !ieee80211_is_disassoc(hdr->frame_control) &&
+           !ieee80211_is_action(hdr->frame_control)) {
+               if (tx->flags & IEEE80211_TX_UNICAST)
+                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
+               return TX_CONTINUE;
+       }
+
        if (tx->flags & IEEE80211_TX_UNICAST)
                return ieee80211_tx_h_unicast_ps_buf(tx);
        else
index c8beafd401aa283f0befa0494e02649359bab83f..5a355a46d1dc4a70e82fadcd509ddd4fae34c3e1 100644 (file)
@@ -63,6 +63,7 @@
 #include <net/ip_vs.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 
@@ -97,6 +98,11 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
        if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
                return;
 
+       /* Applications may adjust TCP seqs */
+       if (cp->app && nf_ct_protonum(ct) == IPPROTO_TCP &&
+           !nfct_seqadj(ct) && !nfct_seqadj_ext_add(ct))
+               return;
+
        /*
         * The connection is not yet in the hashtable, so we update it.
         * CIP->VIP will remain the same, so leave the tuple in
index 17c1bcb182c6b58a782744e23bfe671de160bf92..f6e2ae91a80badd697a1f77e299dc332bc34a8d1 100644 (file)
@@ -36,6 +36,11 @@ int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
        if (off == 0)
                return 0;
 
+       if (unlikely(!seqadj)) {
+               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+               return 0;
+       }
+
        set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 
        spin_lock_bh(&ct->lock);
index 902fb0a6b38ad9baac15c3fc3f17a3e695510db8..7a394df0deb7686fa7fe4da162ff77d3c03435c5 100644 (file)
@@ -97,7 +97,6 @@ int nf_conntrack_tstamp_pernet_init(struct net *net)
 void nf_conntrack_tstamp_pernet_fini(struct net *net)
 {
        nf_conntrack_tstamp_fini_sysctl(net);
-       nf_ct_extend_unregister(&tstamp_extend);
 }
 
 int nf_conntrack_tstamp_init(void)
index f02b3605823e5616bc70f128a896e76d8f984ff2..1fb2258c35357c8c6f5072ae6593de2d53ab9f03 100644 (file)
@@ -34,10 +34,14 @@ static unsigned int help(struct sk_buff *skb,
                         struct nf_conntrack_expect *exp)
 {
        char buffer[sizeof("4294967296 65635")];
+       struct nf_conn *ct = exp->master;
+       union nf_inet_addr newaddr;
        u_int16_t port;
        unsigned int ret;
 
        /* Reply comes from server. */
+       newaddr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3;
+
        exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
        exp->dir = IP_CT_DIR_REPLY;
        exp->expectfn = nf_nat_follow_master;
@@ -57,17 +61,35 @@ static unsigned int help(struct sk_buff *skb,
        }
 
        if (port == 0) {
-               nf_ct_helper_log(skb, exp->master, "all ports in use");
+               nf_ct_helper_log(skb, ct, "all ports in use");
                return NF_DROP;
        }
 
-       ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo,
-                                      protoff, matchoff, matchlen, buffer,
-                                      strlen(buffer));
+       /* strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
+        * strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
+        * strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
+        * strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
+        * strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
+        *
+        * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
+        *                        255.255.255.255==4294967296, 10 digits)
+        * P:         bound port (min 1 d, max 5d (65635))
+        * F:         filename   (min 1 d )
+        * S:         size       (min 1 d )
+        * 0x01, \n:  terminators
+        */
+       /* AAA = "us", ie. where server normally talks to. */
+       snprintf(buffer, sizeof(buffer), "%u %u", ntohl(newaddr.ip), port);
+       pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n",
+                buffer, &newaddr.ip, port);
+
+       ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, matchoff,
+                                      matchlen, buffer, strlen(buffer));
        if (ret != NF_ACCEPT) {
-               nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
+               nf_ct_helper_log(skb, ct, "cannot mangle packet");
                nf_ct_unexpect_related(exp);
        }
+
        return ret;
 }
 
index f93b7d06f4be9525ad4ab4314a106b01e85749ba..71a9f49a768b887dec1b361b78147016cb2b9307 100644 (file)
@@ -312,6 +312,9 @@ static int nf_tables_table_enable(struct nft_table *table)
        int err, i = 0;
 
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                err = nf_register_hook(&nft_base_chain(chain)->ops);
                if (err < 0)
                        goto err;
@@ -321,6 +324,9 @@ static int nf_tables_table_enable(struct nft_table *table)
        return 0;
 err:
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                if (i-- <= 0)
                        break;
 
@@ -333,8 +339,10 @@ static int nf_tables_table_disable(struct nft_table *table)
 {
        struct nft_chain *chain;
 
-       list_for_each_entry(chain, &table->chains, list)
-               nf_unregister_hook(&nft_base_chain(chain)->ops);
+       list_for_each_entry(chain, &table->chains, list) {
+               if (chain->flags & NFT_BASE_CHAIN)
+                       nf_unregister_hook(&nft_base_chain(chain)->ops);
+       }
 
        return 0;
 }
@@ -2098,17 +2106,21 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
                                   struct netlink_callback *cb)
 {
        const struct nft_set *set;
-       unsigned int idx = 0, s_idx = cb->args[0];
+       unsigned int idx, s_idx = cb->args[0];
        struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
 
        if (cb->args[1])
                return skb->len;
 
        list_for_each_entry(table, &ctx->afi->tables, list) {
-               if (cur_table && cur_table != table)
-                       continue;
+               if (cur_table) {
+                       if (cur_table != table)
+                               continue;
 
+                       cur_table = NULL;
+               }
                ctx->table = table;
+               idx = 0;
                list_for_each_entry(set, &ctx->table->sets, list) {
                        if (idx < s_idx)
                                goto cont;
@@ -2370,7 +2382,9 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
        enum nft_registers dreg;
 
        dreg = nft_type_to_reg(set->dtype);
-       return nft_validate_data_load(ctx, dreg, &elem->data, set->dtype);
+       return nft_validate_data_load(ctx, dreg, &elem->data,
+                                     set->dtype == NFT_DATA_VERDICT ?
+                                     NFT_DATA_VERDICT : NFT_DATA_VALUE);
 }
 
 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
index 3c4b69e5fe17348b422f390bf79ab4269043fe5d..a155d19a225edcfb4b1a550ebc898f40d51c564d 100644 (file)
@@ -1053,6 +1053,7 @@ static void __net_exit nfnl_log_net_exit(struct net *net)
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
 #endif
+       nf_log_unset(net, &nfulnl_logger);
 }
 
 static struct pernet_operations nfnl_log_net_ops = {
index 8e0bb75e7c51e61092fb904dc1d93befe1e7320d..55c939f5371fabf35ad996efb51ea52a29630703 100644 (file)
@@ -31,7 +31,7 @@ static void nft_exthdr_eval(const struct nft_expr *expr,
 {
        struct nft_exthdr *priv = nft_expr_priv(expr);
        struct nft_data *dest = &data[priv->dreg];
-       unsigned int offset;
+       unsigned int offset = 0;
        int err;
 
        err = ipv6_find_hdr(pkt->skb, &offset, priv->type, NULL, NULL);
index 872529105abc7c3a2e41b9d579e934e019e8e5ff..83b9927e7d19f3b14c8db4b199385122843d6764 100644 (file)
@@ -384,7 +384,7 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
 {
        dev->dep_link_up = true;
 
-       if (!dev->active_target) {
+       if (!dev->active_target && rf_mode == NFC_RF_INITIATOR) {
                struct nfc_target *target;
 
                target = nfc_find_target(dev, target_idx);
index b4c8b0022feeebea1aec424542e37a8391d87297..ba2dffeff60876ca669993d1863dcbb6cb76a740 100644 (file)
@@ -338,7 +338,8 @@ static int rds_ib_laddr_check(__be32 addr)
        ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
        /* due to this, we will claim to support iWARP devices unless we
           check node_type. */
-       if (ret || cm_id->device->node_type != RDMA_NODE_IB_CA)
+       if (ret || !cm_id->device ||
+           cm_id->device->node_type != RDMA_NODE_IB_CA)
                ret = -EADDRNOTAVAIL;
 
        rdsdebug("addr %pI4 ret %d node type %d\n",
index 8eb9501e3d60d41d30c3af511551f039a6264958..b7ebe23cdedfb5f31cfafab415b54b3db3f0c30b 100644 (file)
@@ -421,8 +421,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
                                 struct rds_ib_refill_cache *cache)
 {
        unsigned long flags;
-       struct list_head *old;
-       struct list_head __percpu *chpfirst;
+       struct list_head *old, *chpfirst;
 
        local_irq_save(flags);
 
@@ -432,7 +431,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
        else /* put on front */
                list_add_tail(new_item, chpfirst);
 
-       __this_cpu_write(chpfirst, new_item);
+       __this_cpu_write(cache->percpu->first, new_item);
        __this_cpu_inc(cache->percpu->count);
 
        if (__this_cpu_read(cache->percpu->count) < RDS_IB_RECYCLE_BATCH_COUNT)
@@ -452,7 +451,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
        } while (old);
 
 
-       __this_cpu_write(chpfirst, NULL);
+       __this_cpu_write(cache->percpu->first, NULL);
        __this_cpu_write(cache->percpu->count, 0);
 end:
        local_irq_restore(flags);
index 33af77246bfeb90c6b31bfe6163dc2c9cfbda787..62ced6516c586f5c7b5cb779e079ad57b72b7518 100644 (file)
@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (msg->msg_name) {
                struct sockaddr_rose *srose;
+               struct full_sockaddr_rose *full_srose = msg->msg_name;
 
                memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
                srose = msg->msg_name;
@@ -1260,18 +1261,9 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
                srose->srose_addr   = rose->dest_addr;
                srose->srose_call   = rose->dest_call;
                srose->srose_ndigis = rose->dest_ndigis;
-               if (msg->msg_namelen >= sizeof(struct full_sockaddr_rose)) {
-                       struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)msg->msg_name;
-                       for (n = 0 ; n < rose->dest_ndigis ; n++)
-                               full_srose->srose_digis[n] = rose->dest_digis[n];
-                       msg->msg_namelen = sizeof(struct full_sockaddr_rose);
-               } else {
-                       if (rose->dest_ndigis >= 1) {
-                               srose->srose_ndigis = 1;
-                               srose->srose_digi = rose->dest_digis[0];
-                       }
-                       msg->msg_namelen = sizeof(struct sockaddr_rose);
-               }
+               for (n = 0 ; n < rose->dest_ndigis ; n++)
+                       full_srose->srose_digis[n] = rose->dest_digis[n];
+               msg->msg_namelen = sizeof(struct full_sockaddr_rose);
        }
 
        skb_free_datagram(sk, skb);
index 5c5edf56adbd4fc9a4d64a509a9103511f995db4..11fe1a416433f1fe2ea46c86ee753826e523b716 100644 (file)
@@ -77,16 +77,16 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
                                     &csum_idx_gen, &csum_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_csum(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_csum(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &csum_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &csum_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
+       p = to_tcf_csum(pc);
        spin_lock_bh(&p->tcf_lock);
        p->tcf_action = parm->action;
        p->update_flags = parm->update_flags;
index 5645a4d32abdd187f59d9f6301842e35d08762df..eb9ba60ebab4394527d10f25511b36b5aff84a32 100644 (file)
@@ -102,10 +102,11 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &gact_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &gact_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        gact = to_gact(pc);
index 882a89762f77c2edb8b6d10d0c8ef69cf3e39aac..dcbfe8ce04a6a30ee9ce273f8e82196a5ba4a319 100644 (file)
@@ -141,10 +141,12 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_ipt_release(to_ipt(pc), bind);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_ipt_release(to_ipt(pc), bind);
+
+               if (!ovr)
                        return -EEXIST;
-               }
        }
        ipt = to_ipt(pc);
 
index 6a15ace002411a8c11efeed6156d72324b9eb2ff..76869538d0287148e48bf43660d3e243912a6e30 100644 (file)
@@ -70,15 +70,15 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                                     &nat_idx_gen, &nat_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_nat(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_nat(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &nat_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &nat_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
+       p = to_tcf_nat(pc);
 
        spin_lock_bh(&p->tcf_lock);
        p->old_addr = parm->old_addr;
index 03b67674169c5db79eb546d93d0b4833324786d3..7aa2dcd989f842976c57d449452d2e0458a7b32c 100644 (file)
@@ -84,10 +84,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                p = to_pedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &pedit_hash_info);
+               tcf_hash_release(pc, bind, &pedit_hash_info);
+               if (bind)
+                       return 0;
+               if (!ovr)
                        return -EEXIST;
-               }
+
                if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
                        keys = kmalloc(ksize, GFP_KERNEL);
                        if (keys == NULL)
index 16a62c36928a78110923d36d5b87808936d8f90a..ef246d87e68bbdf628bc00eebb05e9cb88a3cb87 100644 (file)
@@ -177,10 +177,12 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                        if (bind) {
                                police->tcf_bindcnt += 1;
                                police->tcf_refcnt += 1;
+                               return 0;
                        }
                        if (ovr)
                                goto override;
-                       return ret;
+                       /* not replacing */
+                       return -EEXIST;
                }
        }
 
index 31157d3e729c8c29e8bb89ce03fa68c5ad8e7f39..f7b45ab85388748e9f730939b7f214952f8df84e 100644 (file)
@@ -142,10 +142,13 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_defact(pc);
-               if (!ovr) {
-                       tcf_simp_release(d, bind);
+
+               if (bind)
+                       return 0;
+               tcf_simp_release(d, bind);
+               if (!ovr)
                        return -EEXIST;
-               }
+
                reset_policy(d, defdata, parm);
        }
 
index 35ea643b4325562d74c4c05d9950a4f8a8a7ad32..8fe9d25c3008ece001d4da815cdf4f50c893fdab 100644 (file)
@@ -120,10 +120,11 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_skbedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        spin_lock_bh(&d->tcf_lock);
index 922a09406ba70573499877ac3e561c9ee7b61a5c..7fc899a943a8fa8368415bc0c6c8a939bd042963 100644 (file)
@@ -126,7 +126,7 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
 
        HARD_TX_LOCK(dev, txq, smp_processor_id());
        if (!netif_xmit_frozen_or_stopped(txq))
-               ret = dev_hard_start_xmit(skb, dev, txq, NULL);
+               ret = dev_hard_start_xmit(skb, dev, txq);
 
        HARD_TX_UNLOCK(dev, txq);
 
index f51ba985a36eaaf0b021adba700cf16d42394e6f..59268f6e2c36a0b32ac6b768dea15b7b6be0021d 100644 (file)
@@ -208,8 +208,6 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
        INIT_LIST_HEAD(&q->retransmit);
        INIT_LIST_HEAD(&q->sacked);
        INIT_LIST_HEAD(&q->abandoned);
-
-       q->empty = 1;
 }
 
 /* Free the outqueue structure and any related pending chunks.
@@ -332,7 +330,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
                                SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
                        else
                                SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS);
-                       q->empty = 0;
                        break;
                }
        } else {
@@ -654,7 +651,6 @@ redo:
                        if (chunk->fast_retransmit == SCTP_NEED_FRTX)
                                chunk->fast_retransmit = SCTP_DONT_FRTX;
 
-                       q->empty = 0;
                        q->asoc->stats.rtxchunks++;
                        break;
                }
@@ -1065,8 +1061,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 
                        sctp_transport_reset_timers(transport);
 
-                       q->empty = 0;
-
                        /* Only let one DATA chunk get bundled with a
                         * COOKIE-ECHO chunk.
                         */
@@ -1275,29 +1269,17 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
                 "advertised peer ack point:0x%x\n", __func__, asoc, ctsn,
                 asoc->adv_peer_ack_point);
 
-       /* See if all chunks are acked.
-        * Make sure the empty queue handler will get run later.
-        */
-       q->empty = (list_empty(&q->out_chunk_list) &&
-                   list_empty(&q->retransmit));
-       if (!q->empty)
-               goto finish;
-
-       list_for_each_entry(transport, transport_list, transports) {
-               q->empty = q->empty && list_empty(&transport->transmitted);
-               if (!q->empty)
-                       goto finish;
-       }
-
-       pr_debug("%s: sack queue is empty\n", __func__);
-finish:
-       return q->empty;
+       return sctp_outq_is_empty(q);
 }
 
-/* Is the outqueue empty?  */
+/* Is the outqueue empty?
+ * The queue is empty when we have not pending data, no in-flight data
+ * and nothing pending retransmissions.
+ */
 int sctp_outq_is_empty(const struct sctp_outq *q)
 {
-       return q->empty;
+       return q->out_qlen == 0 && q->outstanding_bytes == 0 &&
+              list_empty(&q->retransmit);
 }
 
 /********************************************************************
index 53c452efb40b4ab761a54acc37f8c1333fc73fd7..5e68b94ee64012571bc4d5f277a9cc594467cc3b 100644 (file)
@@ -38,6 +38,7 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
+MODULE_SOFTDEP("pre: sctp");
 MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>");
 MODULE_DESCRIPTION("SCTP snooper");
 MODULE_LICENSE("GPL");
@@ -182,6 +183,20 @@ static struct jprobe sctp_recv_probe = {
        .entry  = jsctp_sf_eat_sack,
 };
 
+static __init int sctp_setup_jprobe(void)
+{
+       int ret = register_jprobe(&sctp_recv_probe);
+
+       if (ret) {
+               if (request_module("sctp"))
+                       goto out;
+               ret = register_jprobe(&sctp_recv_probe);
+       }
+
+out:
+       return ret;
+}
+
 static __init int sctpprobe_init(void)
 {
        int ret = -ENOMEM;
@@ -202,7 +217,7 @@ static __init int sctpprobe_init(void)
                         &sctpprobe_fops))
                goto free_kfifo;
 
-       ret = register_jprobe(&sctp_recv_probe);
+       ret = sctp_setup_jprobe();
        if (ret)
                goto remove_proc;
 
index 69cd9bf3f561d64d377ddb65091b98e1017e15cf..13b9877458201fa4d5bb14a36892825272229050 100644 (file)
@@ -1498,6 +1498,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
                int type;
 
                head = head->next;
+               buf->next = NULL;
 
                /* Ensure bearer is still enabled */
                if (unlikely(!b_ptr->active))
index c081a7632302ca0798c193b039214466c3180184..d43f3182b1d4cc1628817d882c9d006006e27e1e 100644 (file)
@@ -251,18 +251,15 @@ struct tipc_port *tipc_createport(struct sock *sk,
        return p_ptr;
 }
 
-int tipc_deleteport(u32 ref)
+int tipc_deleteport(struct tipc_port *p_ptr)
 {
-       struct tipc_port *p_ptr;
        struct sk_buff *buf = NULL;
 
-       tipc_withdraw(ref, 0, NULL);
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
+       tipc_withdraw(p_ptr, 0, NULL);
 
-       tipc_ref_discard(ref);
-       tipc_port_unlock(p_ptr);
+       spin_lock_bh(p_ptr->lock);
+       tipc_ref_discard(p_ptr->ref);
+       spin_unlock_bh(p_ptr->lock);
 
        k_cancel_timer(&p_ptr->timer);
        if (p_ptr->connected) {
@@ -704,47 +701,36 @@ int tipc_set_portimportance(u32 ref, unsigned int imp)
 }
 
 
-int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
+                struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        u32 key;
-       int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
+       if (p_ptr->connected)
                return -EINVAL;
+       key = p_ptr->ref + p_ptr->pub_count + 1;
+       if (key == p_ptr->ref)
+               return -EADDRINUSE;
 
-       if (p_ptr->connected)
-               goto exit;
-       key = ref + p_ptr->pub_count + 1;
-       if (key == ref) {
-               res = -EADDRINUSE;
-               goto exit;
-       }
        publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
                                    scope, p_ptr->ref, key);
        if (publ) {
                list_add(&publ->pport_list, &p_ptr->publications);
                p_ptr->pub_count++;
                p_ptr->published = 1;
-               res = 0;
+               return 0;
        }
-exit:
-       tipc_port_unlock(p_ptr);
-       return res;
+       return -EINVAL;
 }
 
-int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
+                 struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        struct publication *tpubl;
        int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
        if (!seq) {
                list_for_each_entry_safe(publ, tpubl,
                                         &p_ptr->publications, pport_list) {
@@ -771,7 +757,6 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
        }
        if (list_empty(&p_ptr->publications))
                p_ptr->published = 0;
-       tipc_port_unlock(p_ptr);
        return res;
 }
 
index 9122535973430edff99e8ee6070a091975dea457..34f12bd4074e49ff8b4c7809bfe0bc706941ec7c 100644 (file)
@@ -116,7 +116,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err);
 
 void tipc_acknowledge(u32 port_ref, u32 ack);
 
-int tipc_deleteport(u32 portref);
+int tipc_deleteport(struct tipc_port *p_ptr);
 
 int tipc_portimportance(u32 portref, unsigned int *importance);
 int tipc_set_portimportance(u32 portref, unsigned int importance);
@@ -127,9 +127,9 @@ int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
 int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
 int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
 
-int tipc_publish(u32 portref, unsigned int scope,
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
                 struct tipc_name_seq const *name_seq);
-int tipc_withdraw(u32 portref, unsigned int scope,
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
                  struct tipc_name_seq const *name_seq);
 
 int tipc_connect(u32 portref, struct tipc_portid const *port);
index 3b61851bb9276ec733f7ab8c9d2179a5dd7fef4d..e741416d1d24d4655cd4096b07f84cd978c90cc7 100644 (file)
@@ -354,7 +354,7 @@ static int release(struct socket *sock)
         * Delete TIPC port; this ensures no more messages are queued
         * (also disconnects an active connection & sends a 'FIN-' to peer)
         */
-       res = tipc_deleteport(tport->ref);
+       res = tipc_deleteport(tport);
 
        /* Discard any remaining (connection-based) messages in receive queue */
        __skb_queue_purge(&sk->sk_receive_queue);
@@ -386,30 +386,46 @@ static int release(struct socket *sock)
  */
 static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
 {
+       struct sock *sk = sock->sk;
        struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
-       u32 portref = tipc_sk_port(sock->sk)->ref;
+       struct tipc_port *tport = tipc_sk_port(sock->sk);
+       int res = -EINVAL;
 
-       if (unlikely(!uaddr_len))
-               return tipc_withdraw(portref, 0, NULL);
+       lock_sock(sk);
+       if (unlikely(!uaddr_len)) {
+               res = tipc_withdraw(tport, 0, NULL);
+               goto exit;
+       }
 
-       if (uaddr_len < sizeof(struct sockaddr_tipc))
-               return -EINVAL;
-       if (addr->family != AF_TIPC)
-               return -EAFNOSUPPORT;
+       if (uaddr_len < sizeof(struct sockaddr_tipc)) {
+               res = -EINVAL;
+               goto exit;
+       }
+       if (addr->family != AF_TIPC) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if (addr->addrtype == TIPC_ADDR_NAME)
                addr->addr.nameseq.upper = addr->addr.nameseq.lower;
-       else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
-               return -EAFNOSUPPORT;
+       else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
            (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
-           (addr->addr.nameseq.type != TIPC_CFG_SRV))
-               return -EACCES;
+           (addr->addr.nameseq.type != TIPC_CFG_SRV)) {
+               res = -EACCES;
+               goto exit;
+       }
 
-       return (addr->scope > 0) ?
-               tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
-               tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
+       res = (addr->scope > 0) ?
+               tipc_publish(tport, addr->scope, &addr->addr.nameseq) :
+               tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq);
+exit:
+       release_sock(sk);
+       return res;
 }
 
 /**
index a0ca162e5bd56cacd524f220b0740c0123b881c8..a427623ee574e88d9926c7972a0650c5c6f9a3eb 100644 (file)
@@ -718,7 +718,9 @@ static int unix_autobind(struct socket *sock)
        int err;
        unsigned int retries = 0;
 
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               return err;
 
        err = 0;
        if (u->addr)
@@ -877,7 +879,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                goto out;
        addr_len = err;
 
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               goto out;
 
        err = -EINVAL;
        if (u->addr)
index a271c27fac774ce987c0db6f1330ffbfca6dc7f7..722da616438cd1e933fb4d5e60a2c4846f44d186 100644 (file)
@@ -124,6 +124,10 @@ int ieee80211_radiotap_iterator_init(
        /* find payload start allowing for extended bitmap(s) */
 
        if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+               if ((unsigned long)iterator->_arg -
+                   (unsigned long)iterator->_rtheader + sizeof(uint32_t) >
+                   (unsigned long)iterator->_max_length)
+                       return -EINVAL;
                while (get_unaligned_le32(iterator->_arg) &
                                        (1 << IEEE80211_RADIOTAP_EXT)) {
                        iterator->_arg += sizeof(uint32_t);
index 65f800890d70d857c9b42d379caad887f5a98c74..d3c5bd7c6b513cd376a2e37857cb8f19919b5a43 100644 (file)
@@ -632,6 +632,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
        }
 #endif
 
+       if (!bss && (status == WLAN_STATUS_SUCCESS)) {
+               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
+               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+                                      wdev->ssid, wdev->ssid_len,
+                                      WLAN_CAPABILITY_ESS,
+                                      WLAN_CAPABILITY_ESS);
+               if (bss)
+                       cfg80211_hold_bss(bss_from_pub(bss));
+       }
+
        if (wdev->current_bss) {
                cfg80211_unhold_bss(wdev->current_bss);
                cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
@@ -649,16 +659,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                return;
        }
 
-       if (!bss) {
-               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
-               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
-                                      wdev->ssid, wdev->ssid_len,
-                                      WLAN_CAPABILITY_ESS,
-                                      WLAN_CAPABILITY_ESS);
-               if (WARN_ON(!bss))
-                       return;
-               cfg80211_hold_bss(bss_from_pub(bss));
-       }
+       if (WARN_ON(!bss))
+               return;
 
        wdev->current_bss = bss_from_pub(bss);
 
index 32b10f53d0b4cbad76b13ef86d547ad864ae19c2..2dcb37736d8469a0e18e4c1ba262281e3fd8cf37 100644 (file)
@@ -82,7 +82,9 @@ kallsyms()
                kallsymopt="${kallsymopt} --all-symbols"
        fi
 
-       kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+       if [ -n "${CONFIG_ARM}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
+               kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+       fi
 
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
index 419491d8e7d20737cc2e2098882994a1fc37ca98..57b0b49f4e6e23a9c6dd974e3f9dd78664f1f59a 100644 (file)
@@ -234,6 +234,14 @@ static int inode_alloc_security(struct inode *inode)
        return 0;
 }
 
+static void inode_free_rcu(struct rcu_head *head)
+{
+       struct inode_security_struct *isec;
+
+       isec = container_of(head, struct inode_security_struct, rcu);
+       kmem_cache_free(sel_inode_cache, isec);
+}
+
 static void inode_free_security(struct inode *inode)
 {
        struct inode_security_struct *isec = inode->i_security;
@@ -244,8 +252,16 @@ static void inode_free_security(struct inode *inode)
                list_del_init(&isec->list);
        spin_unlock(&sbsec->isec_lock);
 
-       inode->i_security = NULL;
-       kmem_cache_free(sel_inode_cache, isec);
+       /*
+        * The inode may still be referenced in a path walk and
+        * a call to selinux_inode_permission() can be made
+        * after inode_free_security() is called. Ideally, the VFS
+        * wouldn't do this, but fixing that is a much harder
+        * job. For now, simply free the i_security via RCU, and
+        * leave the current inode->i_security pointer intact.
+        * The inode will be freed after the RCU grace period too.
+        */
+       call_rcu(&isec->rcu, inode_free_rcu);
 }
 
 static int file_alloc_security(struct file *file)
@@ -4334,8 +4350,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
                err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
-               if (err)
+               if (err) {
                        selinux_netlbl_err(skb, err, 0);
+                       return err;
+               }
        }
 
        if (secmark_active) {
@@ -5586,11 +5604,11 @@ static int selinux_setprocattr(struct task_struct *p,
                /* Check for ptracing, and update the task SID if ok.
                   Otherwise, leave SID unchanged and fail. */
                ptsid = 0;
-               task_lock(p);
+               rcu_read_lock();
                tracer = ptrace_parent(p);
                if (tracer)
                        ptsid = task_sid(tracer);
-               task_unlock(p);
+               rcu_read_unlock();
 
                if (tracer) {
                        error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
index b1dfe104945078ead53647c247c46aa6134fac2e..078e553f52f27a03ab83490f20bb2353782d2ef2 100644 (file)
@@ -38,7 +38,10 @@ struct task_security_struct {
 
 struct inode_security_struct {
        struct inode *inode;    /* back pointer to inode object */
-       struct list_head list;  /* list of inode_security_struct */
+       union {
+               struct list_head list;  /* list of inode_security_struct */
+               struct rcu_head rcu;    /* for freeing the inode_security_struct */
+       };
        u32 task_sid;           /* SID of creating task */
        u32 sid;                /* SID of this object */
        u16 sclass;             /* security class of this object */
index 6e03b465e44e3a05f82e93a2d25a61f030cc3cf6..a2104671f51d38df6eec99b3e0aa8ac570ea8988 100644 (file)
@@ -1937,6 +1937,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                case SNDRV_PCM_STATE_DISCONNECTED:
                        err = -EBADFD;
                        goto _endloop;
+               case SNDRV_PCM_STATE_PAUSED:
+                       continue;
                }
                if (!tout) {
                        snd_printd("%s write error (DMA or IRQ trouble?)\n",
index 27aa14007cbd400ebcb1f21e5e4036d58e778430..956871d8b3d26a9255723eb4bdfdf963c50f031b 100644 (file)
@@ -3433,6 +3433,10 @@ static void check_probe_mask(struct azx *chip, int dev)
  * white/black-list for enable_msi
  */
 static struct snd_pci_quirk msi_black_list[] = {
+       SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x21fa, "HP", 0), /* AMD Hudson */
        SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
        SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
index 34de5dc2fe9b302e115f03961ef13c6d6b070cc2..c5646941539a87df9505eece6241dd5e9230c4ff 100644 (file)
@@ -4247,12 +4247,16 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
        SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS),
+       SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
index 8697cedccd21240f76b4b5076ba6d0968a394d75..1ead3c977a51743619b0bb2084ec174b7cf867a8 100644 (file)
@@ -648,7 +648,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
 
        dma_params = ssc_p->dma_params[dir];
 
-       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
        ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
 
        pr_debug("%s enabled SSC_SR=0x%08x\n",
@@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
+                            int cmd, struct snd_soc_dai *dai)
+{
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       struct atmel_pcm_dma_params *dma_params;
+       int dir;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dir = 0;
+       else
+               dir = 1;
+
+       dma_params = ssc_p->dma_params[dir];
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+               break;
+       default:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
+               break;
+       }
+
+       return 0;
+}
 
 #ifdef CONFIG_PM
 static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
@@ -731,6 +758,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .startup        = atmel_ssc_startup,
        .shutdown       = atmel_ssc_shutdown,
        .prepare        = atmel_ssc_prepare,
+       .trigger        = atmel_ssc_trigger,
        .hw_params      = atmel_ssc_hw_params,
        .set_fmt        = atmel_ssc_set_dai_fmt,
        .set_clkdiv     = atmel_ssc_set_dai_clkdiv,
index 1b372283bd01a947c26dc4da302f9b077adfe74a..7d6a9055874b822bb440eab72a66dc5c034127ed 100644 (file)
@@ -109,7 +109,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
        dai->stream_name = "WM8731 PCM";
        dai->codec_dai_name = "wm8731-hifi";
        dai->init = sam9x5_wm8731_init;
-       dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+       dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF
                | SND_SOC_DAIFMT_CBM_CFM;
 
        ret = snd_soc_of_parse_card_name(card, "atmel,model");
index 99b359e19d35f46a3c95946d976b294300c6ea70..0ab2dc296474373e1e407abf0762afeeffead4c6 100644 (file)
@@ -1012,7 +1012,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        { "AEC Loopback", "HPOUT3L", "OUT3L" },
        { "AEC Loopback", "HPOUT3R", "OUT3R" },
        { "HPOUT3L", NULL, "OUT3L" },
-       { "HPOUT3R", NULL, "OUT3L" },
+       { "HPOUT3R", NULL, "OUT3R" },
 
        { "AEC Loopback", "SPKOUTL", "OUT4L" },
        { "SPKOUTLN", NULL, "OUT4L" },
index 3938fb1c203ed86b5452ff130071d349a6821a87..53bbfac6a83ad14ed43d2aafca2514ea3a319468 100644 (file)
@@ -1444,7 +1444,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_B:
-               aif1 |= WM8904_AIF_LRCLK_INV;
+               aif1 |= 0x3 | WM8904_AIF_LRCLK_INV;
        case SND_SOC_DAIFMT_DSP_A:
                aif1 |= 0x3;
                break;
index 543c5c2631b61827bcebca8af1926ea02b5655e9..0f17ed3e29f41dc9d7ddebb505b7fad8fc545b02 100644 (file)
@@ -2439,7 +2439,20 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8962_CLOCKING_4,
                            WM8962_SYSCLK_RATE_MASK, clocking4);
 
+       /* DSPCLK_DIV can be only generated correctly after enabling SYSCLK.
+        * So we here provisionally enable it and then disable it afterward
+        * if current bias_level hasn't reached SND_SOC_BIAS_ON.
+        */
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA);
+
        dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
+
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, 0);
+
        if (dspclk < 0) {
                dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
                return;
index 46ec0e9744d4b88b50cc922cfdc65a0b4247e567..4fbcab63e61f1c5d8b4843fdec5c6d3dbfa498ed 100644 (file)
@@ -1474,13 +1474,17 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
                return ret;
 
        /* Wait for the RAM to start, should be near instantaneous */
-       count = 0;
-       do {
+       for (count = 0; count < 10; ++count) {
                ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
                                  &val);
                if (ret != 0)
                        return ret;
-       } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+               if (val & ADSP2_RAM_RDY)
+                       break;
+
+               msleep(1);
+       }
 
        if (!(val & ADSP2_RAM_RDY)) {
                adsp_err(dsp, "Failed to start DSP RAM\n");
index 61e48852b9e8bd21b26eec98cca4fc9ba0eea145..3fd76bc391de19a2431dd320d0abfbdcd9616cf5 100644 (file)
@@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
                break;
        }
 
-       dapm->bias_level = level;
-
        return 0;
 }
 
index 0b18f654b41340908d022003485d8a88c5e0c94e..3920a5e8125f886e15caa6607fed9e84a32950cd 100644 (file)
@@ -473,17 +473,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_I2S_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_I2S_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
@@ -494,17 +494,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
index 11a90cd027faca2956172f3dfa92f6d2ee46a8fe..891b9a9bcbf885df92bad9007b3f23054ce68c18 100644 (file)
@@ -600,12 +600,13 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_codec *codec = rtd->codec;
+       bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
        /* apply codec digital mute */
-       if (!codec->active)
+       if ((playback && codec_dai->playback_active == 1) ||
+           (!playback && codec_dai->capture_active == 1))
                snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
 
        /* free any machine hw params */
index 1dc869c475e7a561240f2ea1664b140f5b916786..42c1f6bfaf2e5bb2a4f2df89269be672b26e377c 100644 (file)
@@ -74,7 +74,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
index 08bc6931c7c7fc0477703037098a8e7185d7c69d..8c7c1028e5797dbc9b23ec88b58a4cd840db1c5c 100644 (file)
@@ -67,15 +67,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = dai->dev;
        struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
        int ret, spdifclock;
 
-       mask = TEGRA20_SPDIF_CTRL_PACK |
-              TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
+       mask |= TEGRA20_SPDIF_CTRL_PACK |
+               TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
-               val = TEGRA20_SPDIF_CTRL_PACK |
-                     TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
+               val |= TEGRA20_SPDIF_CTRL_PACK |
+                      TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
                break;
        default:
                return -EINVAL;
index 362e8f728ddfe1334af25c8ff9d7b3b8ded6c706..49ad9366add86b008823f6091315d74d78f13aeb 100644 (file)
@@ -77,7 +77,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -86,10 +86,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
index dc4de37621117f7dc6fe8d47669e761063c9eed0..bcf1d2f0b791337169ee54ffce946619006015ae 100644 (file)
@@ -18,9 +18,9 @@
 #include "helpers/bitmask.h"
 
 static struct option set_opts[] = {
-       { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
-       { .name = "sched-mc",   .has_arg = optional_argument,   .flag = NULL,   .val = 'm'},
-       { .name = "sched-smt",  .has_arg = optional_argument,   .flag = NULL,   .val = 's'},
+       { .name = "perf-bias",  .has_arg = required_argument,   .flag = NULL,   .val = 'b'},
+       { .name = "sched-mc",   .has_arg = required_argument,   .flag = NULL,   .val = 'm'},
+       { .name = "sched-smt",  .has_arg = required_argument,   .flag = NULL,   .val = 's'},
        { },
 };