Merge branch 'topic/hda' into topic/hda-switcheroo
authorTakashi Iwai <tiwai@suse.de>
Sun, 13 May 2012 09:35:44 +0000 (11:35 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sun, 13 May 2012 09:35:44 +0000 (11:35 +0200)
1611 files changed:
Documentation/ABI/stable/sysfs-driver-usb-usbtmc
Documentation/ABI/testing/sysfs-block-rssd [new file with mode: 0644]
Documentation/ABI/testing/sysfs-bus-hsi [new file with mode: 0644]
Documentation/ABI/testing/sysfs-cfq-target-latency [new file with mode: 0644]
Documentation/DMA-attributes.txt
Documentation/DocBook/device-drivers.tmpl
Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
Documentation/cgroups/cpusets.txt
Documentation/cgroups/memory.txt
Documentation/cpu-hotplug.txt
Documentation/devicetree/bindings/ata/ahci-platform.txt [new file with mode: 0644]
Documentation/devicetree/bindings/ata/calxeda-sata.txt [deleted file]
Documentation/devicetree/bindings/mtd/atmel-nand.txt
Documentation/devicetree/bindings/regulator/anatop-regulator.txt [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/vfs.txt
Documentation/hwmon/k10temp
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-parameters.txt
Documentation/networking/driver.txt
Documentation/networking/ip-sysctl.txt
Documentation/networking/netdevices.txt
Documentation/power/freezing-of-tasks.txt
Documentation/security/keys.txt
Documentation/usb/URB.txt
Documentation/usb/usbmon.txt
MAINTAINERS
Makefile
arch/alpha/Kconfig
arch/alpha/include/asm/atomic.h
arch/alpha/include/asm/cmpxchg.h [new file with mode: 0644]
arch/alpha/include/asm/dma-mapping.h
arch/alpha/include/asm/rtc.h
arch/alpha/include/asm/xchg.h
arch/alpha/kernel/core_tsunami.c
arch/alpha/kernel/pci-noop.c
arch/alpha/kernel/pci_iommu.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/smp.c
arch/alpha/kernel/sys_marvel.c
arch/arm/Kconfig
arch/arm/boot/compressed/atags_to_fdt.c
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/at91sam9g20.dtsi
arch/arm/boot/dts/at91sam9g25ek.dts
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9m10g45ek.dts
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/at91sam9x5cm.dtsi
arch/arm/boot/dts/db8500.dtsi
arch/arm/boot/dts/highbank.dts
arch/arm/boot/dts/msm8660-surf.dts
arch/arm/boot/dts/usb_a9g20.dts
arch/arm/boot/dts/versatile-ab.dts
arch/arm/boot/dts/versatile-pb.dts
arch/arm/common/vic.c
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/mini2440_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/include/asm/barrier.h
arch/arm/include/asm/io.h
arch/arm/include/asm/jump_label.h
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/tls.h
arch/arm/kernel/bios32.c
arch/arm/kernel/insn.c
arch/arm/kernel/irq.c
arch/arm/kernel/kprobes.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/setup.c
arch/arm/kernel/signal.c
arch/arm/kernel/smp.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/board-rm9200ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/include/mach/at91_pmc.h
arch/arm/mach-at91/include/mach/board.h
arch/arm/mach-at91/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-at91/setup.c
arch/arm/mach-bcmring/core.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/clock-exynos4.c
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/dev-dwmci.c
arch/arm/mach-exynos/dma.c
arch/arm/mach-exynos/include/mach/debug-macro.S
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/regs-clock.h
arch/arm/mach-exynos/include/mach/uncompress.h
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-imx/clock-imx27.c
arch/arm/mach-imx/clock-imx35.c
arch/arm/mach-imx/imx27-dt.c
arch/arm/mach-imx/mach-armadillo5x0.c
arch/arm/mach-imx/mach-kzm_arm11_01.c
arch/arm/mach-imx/mach-mx31lilly.c
arch/arm/mach-imx/mach-mx31lite.c
arch/arm/mach-imx/mach-mx35_3ds.c
arch/arm/mach-imx/mach-mx53_ard.c
arch/arm/mach-imx/mm-imx5.c
arch/arm/mach-msm/board-halibut.c
arch/arm/mach-msm/board-msm8x60.c
arch/arm/mach-msm/board-trout-panel.c
arch/arm/mach-msm/board-trout.c
arch/arm/mach-msm/include/mach/uncompress.h
arch/arm/mach-msm/proc_comm.c
arch/arm/mach-msm/smd_debug.c
arch/arm/mach-omap1/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-omap1/mux.c
arch/arm/mach-omap1/timer.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3logic.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-zoom-debugboard.c
arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/gpmc-smsc911x.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/include/mach/barriers.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/opp.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm44xx.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/twl-common.h
arch/arm/mach-omap2/usb-host.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h
arch/arm/mach-pxa/mfp-pxa2xx.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-s3c24xx/Kconfig
arch/arm/mach-s3c24xx/common.h [new file with mode: 0644]
arch/arm/mach-s5pv210/dma.c
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/include/mach/collie.h
arch/arm/mach-u300/core.c
arch/arm/mach-u300/i2c.c
arch/arm/mach-u300/include/mach/irqs.h
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/mbox-db5500.c
arch/arm/mach-ux500/platsmp.c
arch/arm/mach-versatile/pci.c
arch/arm/mm/Kconfig
arch/arm/mm/abort-ev6.S
arch/arm/mm/cache-l2x0.c
arch/arm/mm/fault.c
arch/arm/mm/init.c
arch/arm/mm/mmu.c
arch/arm/mm/nommu.c
arch/arm/mm/proc-v7.S
arch/arm/plat-mxc/3ds_debugboard.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/include/plat/clock.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/sram.c
arch/arm/plat-samsung/Kconfig
arch/arm/plat-samsung/include/plat/sdhci.h
arch/arm/vfp/vfpmodule.c
arch/avr32/include/asm/barrier.h
arch/avr32/include/asm/special_insns.h [deleted file]
arch/avr32/mach-at32ap/include/mach/board.h
arch/blackfin/Kconfig
arch/blackfin/configs/BF527-EZKIT_defconfig
arch/blackfin/include/asm/cmpxchg.h
arch/blackfin/include/asm/gpio.h
arch/blackfin/mach-bf538/boards/ezkit.c
arch/c6x/include/asm/irq.h
arch/c6x/kernel/irq.c
arch/c6x/kernel/signal.c
arch/frv/mb93090-mb00/pci-dma.c
arch/hexagon/include/asm/dma-mapping.h
arch/hexagon/kernel/dma.c
arch/hexagon/kernel/process.c
arch/hexagon/kernel/ptrace.c
arch/hexagon/kernel/smp.c
arch/hexagon/kernel/time.c
arch/hexagon/kernel/vdso.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/include/asm/cmpxchg.h
arch/ia64/include/asm/dma-mapping.h
arch/ia64/include/asm/futex.h
arch/ia64/include/asm/intrinsics.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/pci-swiotlb.c
arch/ia64/kernel/perfmon.c
arch/ia64/sn/pci/pci_dma.c
arch/m68k/configs/m5275evb_defconfig
arch/m68k/include/asm/atomic.h
arch/m68k/mac/config.c
arch/m68k/platform/527x/config.c
arch/m68k/platform/68EZ328/Makefile
arch/m68k/platform/68EZ328/bootlogo.h [deleted file]
arch/m68k/platform/68VZ328/Makefile
arch/m68k/platform/68VZ328/bootlogo.h [new file with mode: 0644]
arch/m68k/platform/coldfire/device.c
arch/m68k/q40/config.c
arch/microblaze/include/asm/cmpxchg.h
arch/microblaze/include/asm/dma-mapping.h
arch/microblaze/include/asm/futex.h
arch/microblaze/include/asm/processor.h
arch/microblaze/kernel/dma.c
arch/microblaze/kernel/early_printk.c
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/unwind.c
arch/microblaze/lib/uaccess_old.S
arch/mips/ath79/dev-wmac.c
arch/mips/cavium-octeon/dma-octeon.c
arch/mips/cavium-octeon/smp.c
arch/mips/include/asm/dma-mapping.h
arch/mips/include/asm/mach-jz4740/irq.h
arch/mips/include/asm/mmu_context.h
arch/mips/kernel/mips-mt-fpaff.c
arch/mips/kernel/proc.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smp-bmips.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc.c
arch/mips/mm/c-octeon.c
arch/mips/mm/dma-default.c
arch/mips/netlogic/common/smp.c
arch/mips/pmc-sierra/yosemite/smp.c
arch/mips/sgi-ip27/ip27-smp.c
arch/mips/sibyte/bcm1480/smp.c
arch/mips/sibyte/sb1250/smp.c
arch/parisc/include/asm/atomic.h
arch/parisc/include/asm/cmpxchg.h [new file with mode: 0644]
arch/parisc/kernel/pdc_cons.c
arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
arch/powerpc/boot/dts/p1020mbg-pc.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p1020mbg-pc_32b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1020mbg-pc_36b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1020utm-pc.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p1020utm-pc_32b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1020utm-pc_36b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p2041rdb.dts
arch/powerpc/boot/dts/p3041ds.dts
arch/powerpc/boot/dts/p3060qds.dts
arch/powerpc/boot/dts/p4080ds.dts
arch/powerpc/boot/dts/p5020ds.dts
arch/powerpc/configs/corenet32_smp_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/include/asm/dma-mapping.h
arch/powerpc/include/asm/epapr_hcalls.h
arch/powerpc/include/asm/fsl_guts.h
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/mpic_msgr.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/dma-swiotlb.c
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/fadump.c
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/vio.c
arch/powerpc/kvm/book3s_emulate.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_interrupts.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/book3s_paired_singles.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/booke_interrupts.S
arch/powerpc/net/bpf_jit.h
arch/powerpc/net/bpf_jit_64.S
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/52xx/mpc52xx_pci.c
arch/powerpc/platforms/85xx/common.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/mpc85xx_rdb.c
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/platforms/cell/axon_msi.c
arch/powerpc/platforms/cell/beat_interrupt.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/qpace_setup.c
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/powermac/low_i2c.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/ps3/interrupt.c
arch/powerpc/platforms/ps3/system-bus.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_event.c
arch/powerpc/sysdev/cpm2_pic.c
arch/powerpc/sysdev/mpc8xx_pic.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic_msgr.c
arch/powerpc/sysdev/qe_lib/qe.c
arch/powerpc/sysdev/scom.c
arch/powerpc/sysdev/xics/xics-common.c
arch/s390/Kconfig
arch/s390/defconfig
arch/s390/include/asm/facility.h
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/swab.h
arch/s390/include/asm/tlb.h
arch/s390/kernel/head.S
arch/s390/kernel/irq.c
arch/s390/kernel/perf_cpum_cf.c
arch/s390/mm/maccess.c
arch/s390/mm/pgtable.c
arch/sh/Kconfig.debug
arch/sh/boards/board-sh7785lcr.c
arch/sh/boards/mach-hp6xx/pm.c
arch/sh/drivers/dma/dma-sysfs.c
arch/sh/include/asm/atomic.h
arch/sh/include/asm/dma-mapping.h
arch/sh/kernel/cpu/fpu.c
arch/sh/kernel/cpu/sh2a/fpu.c
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
arch/sh/kernel/cpu/shmobile/pm.c
arch/sh/kernel/dma-nommu.c
arch/sh/kernel/idle.c
arch/sh/kernel/kgdb.c
arch/sh/kernel/process_32.c
arch/sh/kernel/smp.c
arch/sh/kernel/vsyscall/vsyscall-sigreturn.S
arch/sh/kernel/vsyscall/vsyscall-trapa.S
arch/sh/mm/cache-sh4.c
arch/sh/mm/consistent.c
arch/sh/mm/fault_32.c
arch/sh/mm/flush-sh4.c
arch/sh/mm/sram.c
arch/sparc/include/asm/dma-mapping.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/kernel/ds.c
arch/sparc/kernel/iommu.c
arch/sparc/kernel/ioport.c
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/leon_pci.c
arch/sparc/kernel/leon_smp.c
arch/sparc/kernel/pci_sun4v.c
arch/sparc/kernel/rtrap_64.S
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/fault_64.c
arch/tile/Kconfig
arch/tile/Makefile
arch/tile/include/arch/spr_def.h
arch/tile/include/asm/atomic.h
arch/tile/include/asm/atomic_32.h
arch/tile/include/asm/bitops_64.h
arch/tile/include/asm/cmpxchg.h [new file with mode: 0644]
arch/tile/include/asm/irq.h
arch/tile/include/asm/pci.h
arch/tile/include/asm/spinlock_64.h
arch/tile/include/asm/stack.h
arch/tile/include/asm/traps.h
arch/tile/kernel/entry.S
arch/tile/kernel/intvec_32.S
arch/tile/kernel/intvec_64.S
arch/tile/kernel/module.c
arch/tile/kernel/pci.c
arch/tile/kernel/proc.c
arch/tile/kernel/process.c
arch/tile/kernel/setup.c
arch/tile/kernel/single_step.c
arch/tile/kernel/smp.c
arch/tile/kernel/smpboot.c
arch/tile/kernel/stack.c
arch/tile/kernel/traps.c
arch/tile/lib/Makefile
arch/tile/lib/cacheflush.c
arch/tile/lib/memcpy_user_64.c
arch/tile/lib/spinlock_common.h
arch/tile/mm/fault.c
arch/tile/mm/homecache.c
arch/tile/mm/init.c
arch/tile/mm/pgtable.c
arch/um/drivers/cow.h
arch/um/drivers/cow_user.c
arch/um/drivers/mconsole_kern.c
arch/um/include/asm/Kbuild
arch/um/kernel/Makefile
arch/um/kernel/process.c
arch/um/kernel/skas/mmu.c
arch/um/kernel/skas/process.c
arch/um/kernel/smp.c
arch/unicore32/include/asm/dma-mapping.h
arch/unicore32/mm/dma-swiotlb.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/Makefile.um
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/boot/compressed/relocs.c
arch/x86/boot/tools/build.c
arch/x86/ia32/ia32_aout.c
arch/x86/include/asm/cmpxchg.h
arch/x86/include/asm/dma-mapping.h
arch/x86/include/asm/posix_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/sigcontext.h
arch/x86/include/asm/siginfo.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/uaccess_32.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/asm/unistd.h
arch/x86/include/asm/vga.h
arch/x86/include/asm/word-at-a-time.h [new file with mode: 0644]
arch/x86/include/asm/x86_init.h
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/acpi/sleep.h
arch/x86/kernel/acpi/wakeup_32.S
arch/x86/kernel/acpi/wakeup_64.S
arch/x86/kernel/amd_gart_64.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/perf_event_p4.c
arch/x86/kernel/i387.c
arch/x86/kernel/irq.c
arch/x86/kernel/kdebugfs.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/kvm.c
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/microcode_core.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/pci-nommu.c
arch/x86/kernel/pci-swiotlb.c
arch/x86/kernel/process.c
arch/x86/kernel/vsyscall_64.c
arch/x86/kernel/x86_init.c
arch/x86/kvm/pmu.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/insn.c
arch/x86/lib/usercopy.c
arch/x86/lib/usercopy_32.c
arch/x86/lib/usercopy_64.c
arch/x86/net/bpf_jit.S
arch/x86/net/bpf_jit_comp.c
arch/x86/platform/geode/net5501.c
arch/x86/platform/mrst/mrst.c
arch/x86/power/cpu.c
arch/x86/um/asm/barrier.h [new file with mode: 0644]
arch/x86/um/asm/system.h [deleted file]
arch/x86/video/fbdev.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/pci-swiotlb-xen.c
arch/x86/xen/smp.c
arch/x86/xen/xen-asm.S
arch/xtensa/include/asm/hardirq.h
arch/xtensa/include/asm/io.h
arch/xtensa/kernel/signal.c
block/blk-core.c
block/blk-throttle.c
block/cfq-iosched.c
crypto/Kconfig
crypto/ablkcipher.c
crypto/aead.c
crypto/crypto_user.c
crypto/pcrypt.c
crypto/sha512_generic.c
drivers/Kconfig
drivers/Makefile
drivers/acpi/acpica/hwxface.c
drivers/acpi/ec_sys.c
drivers/acpi/osl.c
drivers/acpi/power.c
drivers/acpi/processor_idle.c
drivers/acpi/reboot.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/amba/bus.c
drivers/ata/ahci.c
drivers/ata/ahci_platform.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/libata-transport.c
drivers/ata/libata.h
drivers/ata/pata_arasan_cf.c
drivers/ata/sata_mv.c
drivers/base/firmware_class.c
drivers/base/power/runtime.c
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-debugfs.c
drivers/base/soc.c
drivers/bcma/Kconfig
drivers/bcma/driver_pci_host.c
drivers/bcma/sprom.c
drivers/block/cciss_scsi.c
drivers/block/floppy.c
drivers/block/mtip32xx/Kconfig
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/virtio_blk.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btmrvl_debugfs.c
drivers/bluetooth/btusb.c
drivers/bluetooth/hci_ldisc.c
drivers/char/agp/generic.c
drivers/char/agp/intel-agp.c
drivers/char/agp/intel-agp.h
drivers/char/agp/intel-gtt.c
drivers/char/agp/sgi-agp.c
drivers/char/apm-emulation.c
drivers/char/hpet.c
drivers/char/random.c
drivers/char/tile-srom.c
drivers/char/virtio_console.c
drivers/clocksource/acpi_pm.c
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/db8500-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/crypto/ixp4xx_crypto.c
drivers/crypto/talitos.c
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac.c
drivers/dma/coh901318.c
drivers/dma/dmaengine.c
drivers/dma/imx-dma.c
drivers/dma/ioat/dma.c
drivers/dma/ioat/dma.h
drivers/dma/ioat/dma_v2.c
drivers/dma/ioat/dma_v2.h
drivers/dma/ioat/dma_v3.c
drivers/dma/iop-adma.c
drivers/dma/mxs-dma.c
drivers/dma/pl330.c
drivers/dma/sa11x0-dma.c
drivers/dma/ste_dma40.c
drivers/dma/ste_dma40_ll.h
drivers/edac/mce_amd.c
drivers/edac/tile_edac.c
drivers/firmware/efivars.c
drivers/gpio/Kconfig
drivers/gpio/gpio-adp5588.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-sodaville.c
drivers/gpio/gpio-tegra.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_cache.c
drivers/gpu/drm/drm_context.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_edid_modes.h
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_prime.c [new file with mode: 0644]
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/drm_usb.c
drivers/gpu/drm/drm_vm.c
drivers/gpu/drm/exynos/exynos_drm_buf.c
drivers/gpu/drm/exynos/exynos_drm_core.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_drm_hdmi.c
drivers/gpu/drm/exynos/exynos_drm_hdmi.h
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/gma500/Makefile
drivers/gpu/drm/gma500/cdv_device.c
drivers/gpu/drm/gma500/cdv_intel_crt.c
drivers/gpu/drm/gma500/cdv_intel_display.c
drivers/gpu/drm/gma500/cdv_intel_hdmi.c
drivers/gpu/drm/gma500/cdv_intel_lvds.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/gma500/gem.c
drivers/gpu/drm/gma500/gtt.c
drivers/gpu/drm/gma500/intel_bios.c
drivers/gpu/drm/gma500/intel_bios.h
drivers/gpu/drm/gma500/intel_opregion.c [deleted file]
drivers/gpu/drm/gma500/mdfld_device.c
drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
drivers/gpu/drm/gma500/mdfld_dsi_output.h
drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
drivers/gpu/drm/gma500/mdfld_intel_display.c
drivers/gpu/drm/gma500/mid_bios.c
drivers/gpu/drm/gma500/oaktrail.h
drivers/gpu/drm/gma500/oaktrail_crtc.c
drivers/gpu/drm/gma500/oaktrail_device.c
drivers/gpu/drm/gma500/oaktrail_hdmi.c
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
drivers/gpu/drm/gma500/oaktrail_lvds.c
drivers/gpu/drm/gma500/opregion.c [new file with mode: 0644]
drivers/gpu/drm/gma500/opregion.h [new file with mode: 0644]
drivers/gpu/drm/gma500/psb_device.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/gma500/psb_intel_display.c
drivers/gpu/drm/gma500/psb_intel_drv.h
drivers/gpu/drm/gma500/psb_intel_reg.h
drivers/gpu/drm/gma500/psb_intel_sdvo.c
drivers/gpu/drm/gma500/psb_irq.c
drivers/gpu/drm/gma500/psb_lid.c
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i915/Makefile
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_debug.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 [new file with mode: 0644]
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_ioc32.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 [new file with mode: 0644]
drivers/gpu/drm/i915/i915_trace_points.c
drivers/gpu/drm/i915/intel_acpi.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_modes.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/nouveau/Kconfig
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_dma.h
drivers/gpu/drm/nouveau/nouveau_hdmi.c
drivers/gpu/drm/nouveau/nouveau_pm.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv10_gpio.c
drivers/gpu/drm/nouveau/nv50_sor.c
drivers/gpu/drm/nouveau/nvc0_fb.c
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/atom.h
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_blit_kms.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreen_reg.h
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r200.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_audio.c
drivers/gpu/drm/radeon/r600_blit_kms.c
drivers/gpu/drm/radeon/r600_cp.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/r600_reg.h
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_clocks.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_object.h
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_semaphore.c
drivers/gpu/drm/radeon/radeon_test.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs600d.h
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770d.h
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/savage/savage_state.c
drivers/gpu/drm/udl/udl_drv.c
drivers/gpu/drm/udl/udl_drv.h
drivers/gpu/drm/udl/udl_gem.c
drivers/gpu/vga/Kconfig
drivers/gpu/vga/vga_switcheroo.c
drivers/gpu/vga/vgaarb.c
drivers/hid/Kconfig
drivers/hid/hid-picolcd.c
drivers/hid/hid-tivo.c
drivers/hid/hid-wiimote-debug.c
drivers/hsi/Kconfig [new file with mode: 0644]
drivers/hsi/Makefile [new file with mode: 0644]
drivers/hsi/clients/Kconfig [new file with mode: 0644]
drivers/hsi/clients/Makefile [new file with mode: 0644]
drivers/hsi/clients/hsi_char.c [new file with mode: 0644]
drivers/hsi/hsi.c [new file with mode: 0644]
drivers/hsi/hsi_boardinfo.c [new file with mode: 0644]
drivers/hsi/hsi_core.h [new file with mode: 0644]
drivers/hwmon/Kconfig
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/ad7314.c
drivers/hwmon/adm1031.c
drivers/hwmon/ads1015.c
drivers/hwmon/coretemp.c
drivers/hwmon/f75375s.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/k10temp.c
drivers/hwmon/max6639.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/smsc47b397.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/w83627ehf.c
drivers/i2c/busses/i2c-designware-pcidrv.c
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/busses/i2c-tegra.c
drivers/idle/i7300_idle.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/sysfs.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/misc/Kconfig
drivers/input/misc/da9052_onkey.c
drivers/input/misc/twl6040-vibra.c
drivers/input/mouse/elantech.c
drivers/input/mouse/gpio_mouse.c
drivers/input/mouse/sentelic.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/trackpoint.c
drivers/input/touchscreen/tps6507x-ts.c
drivers/iommu/amd_iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/omap-iommu-debug.c
drivers/isdn/gigaset/interface.c
drivers/isdn/hardware/mISDN/avmfritz.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/isdn/hardware/mISDN/mISDNipac.c
drivers/isdn/hardware/mISDN/mISDNisar.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/isdn/hardware/mISDN/w6692.c
drivers/leds/leds-atmel-pwm.c
drivers/md/bitmap.c
drivers/md/bitmap.h
drivers/md/dm-raid.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/common/tuners/xc5000.c
drivers/media/common/tuners/xc5000.h
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-usb/it913x.c
drivers/media/dvb/frontends/drxk_hard.c
drivers/media/rc/winbond-cir.c
drivers/media/video/Kconfig
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/mt9m032.c
drivers/media/video/uvc/uvc_video.c
drivers/mfd/Kconfig
drivers/mfd/aat2870-core.c
drivers/mfd/ab3100-core.c
drivers/mfd/asic3.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/omap-usb-host.c
drivers/mfd/rc5t583.c
drivers/mfd/twl6040-core.c
drivers/misc/ibmasm/ibmasmfs.c
drivers/misc/kgdbts.c
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/bus.c
drivers/mmc/core/cd-gpio.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
drivers/mmc/core/sdio_bus.c
drivers/mmc/host/atmel-mci-regs.h
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sh_mmcif.c
drivers/mtd/mtdchar.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/ubi/debug.c
drivers/net/arcnet/arc-rimi.c
drivers/net/bonding/bond_main.c
drivers/net/caif/caif_hsi.c
drivers/net/caif/caif_spi.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/dummy.c
drivers/net/eql.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/atheros/atlx/atl1.h
drivers/net/ethernet/atheros/atlx/atlx.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_fw_defs.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
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/tg3.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/dlink/dl2k.c
drivers/net/ethernet/dlink/dl2k.h
drivers/net/ethernet/freescale/fsl_pq_mdio.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/freescale/ucc_geth.h
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/ehea/ehea_phyp.h
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/param.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/marvell/sky2.h
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/Kconfig
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/ethernet/ti/tlan.c
drivers/net/ethernet/tile/tilepro.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/xilinx/xilinx_axienet.h
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/irda/sa1100_ir.c
drivers/net/phy/icplus.c
drivers/net/ppp/ppp_generic.c
drivers/net/rionet.c
drivers/net/usb/asix.c
drivers/net/usb/cdc-phonet.c
drivers/net/usb/cdc_eem.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/rtl8150.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/usbnet.c
drivers/net/usb/zaurus.c
drivers/net/virtio_net.c
drivers/net/wan/farsync.c
drivers/net/wimax/i2400m/debugfs.c
drivers/net/wimax/i2400m/netdev.c
drivers/net/wimax/i2400m/usb.c
drivers/net/wireless/ath/ath5k/ahb.c
drivers/net/wireless/ath/ath5k/debug.c
drivers/net/wireless/ath/ath6kl/debug.c
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/calib.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/dfs_debug.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/htc_drv_debug.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/debug.c
drivers/net/wireless/b43/debugfs.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43legacy/debugfs.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlegacy/3945-mac.c
drivers/net/wireless/iwlegacy/3945-rs.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/4965-rs.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlegacy/debug.c
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-fh.h
drivers/net/wireless/iwlwifi/iwl-mac80211.c
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
drivers/net/wireless/iwmc3200wifi/debugfs.c
drivers/net/wireless/iwmc3200wifi/sdio.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/debugfs.c
drivers/net/wireless/mwifiex/debugfs.c
drivers/net/wireless/mwifiex/pcie.h
drivers/net/wireless/orinoco/main.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
drivers/net/wireless/rtlwifi/rtl8192de/phy.c
drivers/net/wireless/rtlwifi/rtl8192de/sw.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/wl1251/debugfs.c
drivers/net/wireless/wl1251/main.c
drivers/net/wireless/wl1251/sdio.c
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/xen-netfront.c
drivers/of/gpio.c
drivers/oprofile/oprofilefs.c
drivers/pci/Makefile
drivers/pci/pci-acpi.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/xen-pcifront.c
drivers/pinctrl/core.c
drivers/platform/x86/acerhdf.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_mid_powerbtn.c
drivers/regulator/anatop-regulator.c
drivers/regulator/core.c
drivers/regulator/fixed-helper.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/s5m8767.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8350-regulator.c
drivers/remoteproc/remoteproc_debugfs.c
drivers/rtc/rtc-88pm860x.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-efi.c
drivers/rtc/rtc-mpc5121.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-r9701.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-twl.c
drivers/s390/block/dasd_eckd.c
drivers/s390/char/vmur.c
drivers/s390/net/qeth_core_main.c
drivers/scsi/ipr.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/libsas/sas_event.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/libsas/sas_init.c
drivers/scsi/libsas/sas_internal.h
drivers/scsi/libsas/sas_phy.c
drivers/scsi/libsas/sas_port.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bfin-sport.c
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw.c
drivers/spi/spi-ep93xx.c
drivers/spi/spi-fsl-spi.c
drivers/spi/spi-imx.c
drivers/spi/spi-pl022.c
drivers/staging/android/Kconfig
drivers/staging/android/lowmemorykiller.c
drivers/staging/android/persistent_ram.c
drivers/staging/android/timed_gpio.c
drivers/staging/iio/inkern.c
drivers/staging/iio/magnetometer/ak8975.c
drivers/staging/iio/magnetometer/hmc5843.c
drivers/staging/media/as102/as102_fw.c
drivers/staging/octeon/ethernet-rx.c
drivers/staging/octeon/ethernet-tx.c
drivers/staging/octeon/ethernet.c
drivers/staging/omapdrm/omap_drv.c
drivers/staging/ozwpan/TODO
drivers/staging/ozwpan/ozpd.c
drivers/staging/ramster/Kconfig
drivers/staging/rts_pstor/ms.c
drivers/staging/rts_pstor/rtsx.c
drivers/staging/rts_pstor/rtsx_transport.c
drivers/staging/sep/sep_main.c
drivers/staging/tidspbridge/core/tiomap3430.c
drivers/staging/tidspbridge/core/wdt.c
drivers/staging/vme/devices/vme_pio2_core.c
drivers/staging/vt6655/key.c
drivers/staging/vt6656/ioctl.c
drivers/staging/vt6656/key.c
drivers/staging/xgifb/vb_init.c
drivers/staging/xgifb/vb_setmode.c
drivers/staging/xgifb/vb_table.h
drivers/staging/zcache/Kconfig
drivers/staging/zsmalloc/zsmalloc-main.c
drivers/target/tcm_fc/tcm_fc.h
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_conf.c
drivers/target/tcm_fc/tfc_io.c
drivers/tty/amiserial.c
drivers/tty/serial/8250/8250.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/Kconfig
drivers/tty/serial/altera_uart.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/clps711x.c
drivers/tty/serial/mfd.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/pmac_zilog.c
drivers/tty/serial/samsung.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sh-sci.h
drivers/tty/serial/sunzilog.c
drivers/tty/sysrq.c
drivers/tty/vt/keyboard.c
drivers/tty/vt/vt.c
drivers/usb/Kconfig
drivers/usb/class/cdc-wdm.c
drivers/usb/core/driver.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/inode.c
drivers/usb/core/message.c
drivers/usb/core/urb.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/ep0.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/f_phonet.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/g_ffs.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/udc-core.c
drivers/usb/gadget/uvc.h
drivers/usb/gadget/uvc_queue.c
drivers/usb/gadget/uvc_v4l2.c
drivers/usb/host/ehci-atmel.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci.h
drivers/usb/host/ohci-at91.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/uhci-hub.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-ext-caps.h
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/usbtest.c
drivers/usb/misc/yurex.c
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_host.c
drivers/usb/musb/omap2430.c
drivers/usb/otg/gpio_vbus.c
drivers/usb/serial/bus.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/metro-usb.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/sierra.c
drivers/usb/serial/usb-serial.c
drivers/usb/storage/usb.c
drivers/uwb/hwa-rc.c
drivers/uwb/neh.c
drivers/uwb/uwb-debug.c
drivers/vhost/net.c
drivers/vhost/test.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/au1100fb.c
drivers/video/au1200fb.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/da9052_bl.c [new file with mode: 0644]
drivers/video/backlight/locomolcd.c
drivers/video/bfin-lq035q1-fb.c
drivers/video/efifb.c
drivers/video/kyro/STG4000Reg.h
drivers/video/msm/mddi.c
drivers/video/uvesafb.c
drivers/virtio/virtio_balloon.c
drivers/watchdog/hpwdt.c
drivers/xen/events.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/manage.c
drivers/xen/swiotlb-xen.c
drivers/xen/xen-acpi-processor.c
drivers/xen/xen-pciback/pciback_ops.c
drivers/xen/xenbus/xenbus_probe_frontend.c
fs/aio.c
fs/autofs4/autofs_i.h
fs/autofs4/dev-ioctl.c
fs/autofs4/inode.c
fs/autofs4/waitq.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_flat.c
fs/binfmt_som.c
fs/btrfs/backref.c
fs/btrfs/compression.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
fs/btrfs/reada.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/buffer.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/netmisc.c
fs/dcache.c
fs/debugfs/file.c
fs/dlm/debug_fs.c
fs/dlm/lock.c
fs/eventpoll.c
fs/exec.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/super.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/inode.c
fs/gfs2/Kconfig
fs/gfs2/aops.c
fs/gfs2/bmap.c
fs/gfs2/dir.c
fs/gfs2/inode.c
fs/gfs2/lock_dlm.c
fs/gfs2/rgrp.c
fs/gfs2/xattr.c
fs/hfsplus/catalog.c
fs/hfsplus/dir.c
fs/hugetlbfs/inode.c
fs/jbd2/commit.c
fs/libfs.c
fs/lockd/clnt4xdr.c
fs/lockd/clntxdr.c
fs/locks.c
fs/namei.c
fs/nfs/blocklayout/blocklayout.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/idmap.c
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/objlayout/objlayout.c
fs/nfs/pnfs.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/vfs.c
fs/ocfs2/alloc.c
fs/ocfs2/refcounttree.c
fs/ocfs2/suballoc.c
fs/pipe.c
fs/proc/root.c
fs/proc/stat.c
fs/proc/task_mmu.c
fs/pstore/inode.c
fs/splice.c
fs/sysfs/dir.c
fs/sysfs/group.c
fs/xattr.c
include/acpi/actypes.h
include/asm-generic/cmpxchg.h
include/asm-generic/siginfo.h
include/asm-generic/statfs.h
include/crypto/internal/aead.h
include/crypto/internal/skcipher.h
include/drm/drm.h
include/drm/drmP.h
include/drm/drm_crtc.h
include/drm/drm_crtc_helper.h
include/drm/drm_edid.h
include/drm/drm_fixed.h
include/drm/exynos_drm.h
include/drm/i915_drm.h
include/drm/intel-gtt.h
include/drm/radeon_drm.h
include/linux/Kbuild
include/linux/amba/bus.h
include/linux/amba/pl022.h
include/linux/blkdev.h
include/linux/cpumask.h
include/linux/cryptouser.h
include/linux/dma-attrs.h
include/linux/dma-mapping.h
include/linux/dmaengine.h
include/linux/efi.h
include/linux/ethtool.h
include/linux/firewire.h
include/linux/fs.h
include/linux/fuse.h
include/linux/gpio-pxa.h
include/linux/hsi/Kbuild [new file with mode: 0644]
include/linux/hsi/hsi.h [new file with mode: 0644]
include/linux/hsi/hsi_char.h [new file with mode: 0644]
include/linux/i2c/twl.h
include/linux/if_eql.h
include/linux/irq.h
include/linux/irqdomain.h
include/linux/kconfig.h
include/linux/kgdb.h
include/linux/kmod.h
include/linux/kvm_host.h
include/linux/libata.h
include/linux/lsm_audit.h
include/linux/mfd/db5500-prcmu.h
include/linux/mfd/rc5t583.h
include/linux/mfd/twl6040.h
include/linux/mm.h
include/linux/mmc/card.h
include/linux/netdevice.h
include/linux/netfilter/xt_set.h
include/linux/netfilter_bridge.h
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/nfs_xdr.h
include/linux/nfsd/Kbuild
include/linux/pagemap.h
include/linux/pinctrl/machine.h
include/linux/pipe_fs_i.h
include/linux/platform_data/atmel.h
include/linux/pm_qos.h
include/linux/regulator/machine.h
include/linux/seqlock.h
include/linux/serial_core.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/spi/spi.h
include/linux/stddef.h
include/linux/swap.h
include/linux/types.h
include/linux/usb/hcd.h
include/linux/usb/otg.h
include/linux/usb/serial.h
include/linux/vga_switcheroo.h
include/linux/vgaarb.h
include/linux/vm_event_item.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/mgmt.h
include/net/cfg80211.h
include/net/dst.h
include/net/ip6_fib.h
include/net/ip_vs.h
include/net/mac80211.h
include/net/netfilter/xt_log.h
include/net/red.h
include/net/sock.h
include/scsi/libsas.h
include/scsi/sas_ata.h
include/scsi/scsi_cmnd.h
include/trace/events/sched.h
include/xen/swiotlb-xen.h
init/Kconfig
init/do_mounts.c
init/main.c
kernel/cpuset.c
kernel/cred.c
kernel/debug/debug_core.c
kernel/debug/kdb/kdb_io.c
kernel/events/core.c
kernel/irq/Kconfig
kernel/irq/debug.h
kernel/irq/irqdomain.c
kernel/irq_work.c
kernel/itimer.c
kernel/kmod.c
kernel/padata.c
kernel/panic.c
kernel/power/hibernate.c
kernel/power/process.c
kernel/power/qos.c
kernel/power/suspend.c
kernel/power/swap.c
kernel/power/user.c
kernel/rcutree.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/features.h
kernel/sysctl.c
kernel/time/Kconfig
kernel/time/tick-broadcast.c
kernel/time/tick-sched.c
kernel/trace/blktrace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_output.c
lib/kobject.c
lib/mpi/mpi-bit.c
mm/hugetlb.c
mm/memblock.c
mm/memcontrol.c
mm/mempolicy.c
mm/migrate.c
mm/mmap.c
mm/nobootmem.c
mm/nommu.c
mm/swap_state.c
mm/vmscan.c
mm/vmstat.c
net/802/garp.c
net/ax25/af_ax25.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bridge/br_forward.c
net/bridge/br_multicast.c
net/bridge/br_netfilter.c
net/bridge/br_private.h
net/caif/chnl_net.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/drop_monitor.c
net/core/filter.c
net/core/net_namespace.c
net/core/skbuff.c
net/ieee802154/6lowpan.c
net/ipv4/inet_diag.c
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp_diag.c
net/ipv6/addrconf.c
net/ipv6/ip6_fib.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/key/af_key.c
net/l2tp/l2tp_ip.c
net/mac80211/agg-rx.c
net/mac80211/debugfs.c
net/mac80211/debugfs.h
net/mac80211/debugfs_key.c
net/mac80211/debugfs_netdev.c
net/mac80211/debugfs_sta.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/rate.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/tx.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_ftp.c
net/netfilter/ipvs/ip_vs_lblc.c
net/netfilter/ipvs/ip_vs_lblcr.c
net/netfilter/ipvs/ip_vs_proto.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/ipvs/ip_vs_proto_tcp.c
net/netfilter/ipvs/ip_vs_proto_udp.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nfnetlink_acct.c
net/netfilter/xt_CT.c
net/netlink/af_netlink.c
net/nfc/llcp/commands.c
net/phonet/pep.c
net/phonet/pn_dev.c
net/rose/rose_dev.c
net/sched/sch_gred.c
net/sched/sch_netem.c
net/sctp/socket.c
net/socket.c
net/sunrpc/clnt.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sunrpc_syms.c
net/wireless/debugfs.c
net/wireless/nl80211.c
net/wireless/util.c
net/wireless/wext-core.c
scripts/checkpatch.pl
scripts/coccinelle/api/simple_open.cocci [new file with mode: 0644]
scripts/kconfig/confdata.c
scripts/mod/file2alias.c
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/tags.sh
scripts/xz_wrap.sh
security/apparmor/audit.c
security/apparmor/capability.c
security/apparmor/file.c
security/apparmor/include/audit.h
security/apparmor/ipc.c
security/apparmor/lib.c
security/apparmor/lsm.c
security/apparmor/policy.c
security/apparmor/policy_unpack.c
security/apparmor/resource.c
security/commoncap.c
security/lsm_audit.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/include/avc.h
security/smack/smack.h
security/smack/smack_access.c
security/smack/smack_lsm.c
security/smack/smackfs.c
sound/pci/Kconfig
sound/soc/codecs/Kconfig
sound/soc/codecs/twl6040.c
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/fsl/p1022_ds.c
sound/soc/imx/imx-audmux.c
sound/soc/omap/Kconfig
sound/soc/soc-core.c
sound/soc/soc-dapm.c
tools/perf/.gitignore
tools/perf/Makefile
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/perf-archive.sh
tools/perf/util/annotate.c
tools/perf/util/hist.c
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/parse-events.l
tools/perf/util/session.c
tools/perf/util/symbol.c
tools/perf/util/ui/browsers/hists.c
tools/testing/ktest/ktest.pl
virt/kvm/iommu.c
virt/kvm/kvm_main.c

index 2a7f9a00cb0a6a0acef8fc46bbb6f290f4d0dc67..e960cd027e1e9685a83f3275ca859da7a793e116 100644 (file)
@@ -1,5 +1,5 @@
-What:          /sys/bus/usb/drivers/usbtmc/devices/*/interface_capabilities
-What:          /sys/bus/usb/drivers/usbtmc/devices/*/device_capabilities
+What:          /sys/bus/usb/drivers/usbtmc/*/interface_capabilities
+What:          /sys/bus/usb/drivers/usbtmc/*/device_capabilities
 Date:          August 2008
 Contact:       Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 Description:
@@ -12,8 +12,8 @@ Description:
                The files are read only.
 
 
-What:          /sys/bus/usb/drivers/usbtmc/devices/*/usb488_interface_capabilities
-What:          /sys/bus/usb/drivers/usbtmc/devices/*/usb488_device_capabilities
+What:          /sys/bus/usb/drivers/usbtmc/*/usb488_interface_capabilities
+What:          /sys/bus/usb/drivers/usbtmc/*/usb488_device_capabilities
 Date:          August 2008
 Contact:       Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 Description:
@@ -27,7 +27,7 @@ Description:
                The files are read only.
 
 
-What:          /sys/bus/usb/drivers/usbtmc/devices/*/TermChar
+What:          /sys/bus/usb/drivers/usbtmc/*/TermChar
 Date:          August 2008
 Contact:       Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 Description:
@@ -40,7 +40,7 @@ Description:
                sent to the device or not.
 
 
-What:          /sys/bus/usb/drivers/usbtmc/devices/*/TermCharEnabled
+What:          /sys/bus/usb/drivers/usbtmc/*/TermCharEnabled
 Date:          August 2008
 Contact:       Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 Description:
@@ -51,7 +51,7 @@ Description:
                published by the USB-IF.
 
 
-What:          /sys/bus/usb/drivers/usbtmc/devices/*/auto_abort
+What:          /sys/bus/usb/drivers/usbtmc/*/auto_abort
 Date:          August 2008
 Contact:       Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 Description:
diff --git a/Documentation/ABI/testing/sysfs-block-rssd b/Documentation/ABI/testing/sysfs-block-rssd
new file mode 100644 (file)
index 0000000..d535757
--- /dev/null
@@ -0,0 +1,18 @@
+What:           /sys/block/rssd*/registers
+Date:           March 2012
+KernelVersion:  3.3
+Contact:        Asai Thambi S P <asamymuthupa@micron.com>
+Description:    This is a read-only file. Dumps below driver information and
+                hardware registers.
+                    - S ACTive
+                    - Command Issue
+                    - Allocated
+                    - Completed
+                    - PORT IRQ STAT
+                    - HOST IRQ STAT
+
+What:           /sys/block/rssd*/status
+Date:           April 2012
+KernelVersion:  3.4
+Contact:        Asai Thambi S P <asamymuthupa@micron.com>
+Description:   This is a read-only file. Indicates the status of the device.
diff --git a/Documentation/ABI/testing/sysfs-bus-hsi b/Documentation/ABI/testing/sysfs-bus-hsi
new file mode 100644 (file)
index 0000000..1b1b282
--- /dev/null
@@ -0,0 +1,19 @@
+What:          /sys/bus/hsi
+Date:          April 2012
+KernelVersion: 3.4
+Contact:       Carlos Chinea <carlos.chinea@nokia.com>
+Description:
+               High Speed Synchronous Serial Interface (HSI) is a
+               serial interface mainly used for connecting application
+               engines (APE) with cellular modem engines (CMT) in cellular
+               handsets.
+               The bus will be populated with devices (hsi_clients) representing
+               the protocols available in the system. Bus drivers implement
+               those protocols.
+
+What:          /sys/bus/hsi/devices/.../modalias
+Date:          April 2012
+KernelVersion: 3.4
+Contact:       Carlos Chinea <carlos.chinea@nokia.com>
+Description:   Stores the same MODALIAS value emitted by uevent
+               Format: hsi:<hsi_client device name>
diff --git a/Documentation/ABI/testing/sysfs-cfq-target-latency b/Documentation/ABI/testing/sysfs-cfq-target-latency
new file mode 100644 (file)
index 0000000..df0f782
--- /dev/null
@@ -0,0 +1,8 @@
+What:          /sys/block/<device>/iosched/target_latency
+Date:          March 2012
+contact:       Tao Ma <boyu.mt@taobao.com>
+Description:
+               The /sys/block/<device>/iosched/target_latency only exists
+               when the user sets cfq to /sys/block/<device>/scheduler.
+               It contains an estimated latency time for the cfq. cfq will
+               use it to calculate the time slice used for every task.
index b768cc0e402b8e6f1cfa8ae0b0f23c4e1c50168a..5c72eed89563083250217336c79ab1d7f350a7c5 100644 (file)
@@ -31,3 +31,21 @@ may be weakly ordered, that is that reads and writes may pass each other.
 Since it is optional for platforms to implement DMA_ATTR_WEAK_ORDERING,
 those that do not will simply ignore the attribute and exhibit default
 behavior.
+
+DMA_ATTR_WRITE_COMBINE
+----------------------
+
+DMA_ATTR_WRITE_COMBINE specifies that writes to the mapping may be
+buffered to improve performance.
+
+Since it is optional for platforms to implement DMA_ATTR_WRITE_COMBINE,
+those that do not will simply ignore the attribute and exhibit default
+behavior.
+
+DMA_ATTR_NON_CONSISTENT
+-----------------------
+
+DMA_ATTR_NON_CONSISTENT lets the platform to choose to return either
+consistent or non-consistent memory as it sees fit.  By using this API,
+you are guaranteeing to the platform that you have all the correct and
+necessary sync points for this memory in the driver.
index 9c27e5125dd26efb5ca49c4b2bc9beadb4d559d7..7514dbf0a6796c4e216a175fa79db0ed3ff470d9 100644 (file)
@@ -446,4 +446,21 @@ X!Idrivers/video/console/fonts.c
 !Edrivers/i2c/i2c-core.c
   </chapter>
 
+  <chapter id="hsi">
+     <title>High Speed Synchronous Serial Interface (HSI)</title>
+
+     <para>
+       High Speed Synchronous Serial Interface (HSI) is a
+       serial interface mainly used for connecting application
+       engines (APE) with cellular modem engines (CMT) in cellular
+       handsets.
+
+       HSI provides multiplexing for up to 16 logical channels,
+       low-latency and full duplex communication.
+     </para>
+
+!Iinclude/linux/hsi/hsi.h
+!Edrivers/hsi/hsi.c
+  </chapter>
+
 </book>
index 3fd3ce5df270563a7e9e1bfc26fa968498e9b1f4..5274c24d11e0a94ce55a05d166580f5cda50196f 100644 (file)
@@ -1,6 +1,6 @@
     <refentry id="V4L2-PIX-FMT-NV12M">
       <refmeta>
-       <refentrytitle>V4L2_PIX_FMT_NV12M ('NV12M')</refentrytitle>
+       <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12')</refentrytitle>
        &manvol;
       </refmeta>
       <refnamediv>
index 9957863daf18d4a4627a74b52fbfe3bd1141b87e..60308f1eefdfea59a33d83f30d32747c8f5c1aa4 100644 (file)
@@ -1,6 +1,6 @@
     <refentry id="V4L2-PIX-FMT-YUV420M">
       <refmeta>
-       <refentrytitle>V4L2_PIX_FMT_YUV420M ('YU12M')</refentrytitle>
+       <refentrytitle>V4L2_PIX_FMT_YUV420M ('YM12')</refentrytitle>
        &manvol;
       </refmeta>
       <refnamediv>
index 5c51ed406d1d1c8c87d5f66e02b676f8ddb2f65a..cefd3d8bbd11db69f51ffee25094e138fc5d0cbd 100644 (file)
@@ -217,7 +217,7 @@ and name space for cpusets, with a minimum of additional kernel code.
 
 The cpus and mems files in the root (top_cpuset) cpuset are
 read-only.  The cpus file automatically tracks the value of
-cpu_online_map using a CPU hotplug notifier, and the mems file
+cpu_online_mask using a CPU hotplug notifier, and the mems file
 automatically tracks the value of node_states[N_HIGH_MEMORY]--i.e.,
 nodes with memory--using the cpuset_track_online_nodes() hook.
 
index 4c95c0034a4bbbffdae12a99ff2ddbd0798ca09c..9b1067afb2245f702d962ca4a93c241af6641a02 100644 (file)
@@ -34,8 +34,7 @@ Current Status: linux-2.6.34-mmotm(development version of 2010/April)
 
 Features:
  - accounting anonymous pages, file caches, swap caches usage and limiting them.
- - private LRU and reclaim routine. (system's global LRU and private LRU
-   work independently from each other)
+ - pages are linked to per-memcg LRU exclusively, and there is no global LRU.
  - optionally, memory+swap usage can be accounted and limited.
  - hierarchical accounting
  - soft limit
@@ -154,7 +153,7 @@ updated. page_cgroup has its own LRU on cgroup.
 2.2.1 Accounting details
 
 All mapped anon pages (RSS) and cache pages (Page Cache) are accounted.
-Some pages which are never reclaimable and will not be on the global LRU
+Some pages which are never reclaimable and will not be on the LRU
 are not accounted. We just account pages under usual VM management.
 
 RSS pages are accounted at page_fault unless they've already been accounted
index a20bfd415e41cca69297760cee32de91c8d2812c..66ef8f35613d2190b4e2f5e42084a4736ff3dc69 100644 (file)
@@ -47,7 +47,7 @@ maxcpus=n    Restrict boot time cpus to n. Say if you have 4 cpus, using
              other cpus later online, read FAQ's for more info.
 
 additional_cpus=n (*)  Use this to limit hotpluggable cpus. This option sets
-                       cpu_possible_map = cpu_present_map + additional_cpus
+                       cpu_possible_mask = cpu_present_mask + additional_cpus
 
 cede_offline={"off","on"}  Use this option to disable/enable putting offlined
                            processors to an extended H_CEDE state on
@@ -64,11 +64,11 @@ should only rely on this to count the # of cpus, but *MUST* not rely
 on the apicid values in those tables for disabled apics. In the event
 BIOS doesn't mark such hot-pluggable cpus as disabled entries, one could
 use this parameter "additional_cpus=x" to represent those cpus in the
-cpu_possible_map.
+cpu_possible_mask.
 
 possible_cpus=n                [s390,x86_64] use this to set hotpluggable cpus.
                        This option sets possible_cpus bits in
-                       cpu_possible_map. Thus keeping the numbers of bits set
+                       cpu_possible_mask. Thus keeping the numbers of bits set
                        constant even if the machine gets rebooted.
 
 CPU maps and such
@@ -76,7 +76,7 @@ CPU maps and such
 [More on cpumaps and primitive to manipulate, please check
 include/linux/cpumask.h that has more descriptive text.]
 
-cpu_possible_map: Bitmap of possible CPUs that can ever be available in the
+cpu_possible_mask: Bitmap of possible CPUs that can ever be available in the
 system. This is used to allocate some boot time memory for per_cpu variables
 that aren't designed to grow/shrink as CPUs are made available or removed.
 Once set during boot time discovery phase, the map is static, i.e no bits
@@ -84,13 +84,13 @@ are added or removed anytime.  Trimming it accurately for your system needs
 upfront can save some boot time memory. See below for how we use heuristics
 in x86_64 case to keep this under check.
 
-cpu_online_map: Bitmap of all CPUs currently online. Its set in __cpu_up()
+cpu_online_mask: Bitmap of all CPUs currently online. Its set in __cpu_up()
 after a cpu is available for kernel scheduling and ready to receive
 interrupts from devices. Its cleared when a cpu is brought down using
 __cpu_disable(), before which all OS services including interrupts are
 migrated to another target CPU.
 
-cpu_present_map: Bitmap of CPUs currently present in the system. Not all
+cpu_present_mask: Bitmap of CPUs currently present in the system. Not all
 of them may be online. When physical hotplug is processed by the relevant
 subsystem (e.g ACPI) can change and new bit either be added or removed
 from the map depending on the event is hot-add/hot-remove. There are currently
@@ -99,22 +99,22 @@ at which time hotplug is disabled.
 
 You really dont need to manipulate any of the system cpu maps. They should
 be read-only for most use. When setting up per-cpu resources almost always use
-cpu_possible_map/for_each_possible_cpu() to iterate.
+cpu_possible_mask/for_each_possible_cpu() to iterate.
 
 Never use anything other than cpumask_t to represent bitmap of CPUs.
 
        #include <linux/cpumask.h>
 
-       for_each_possible_cpu     - Iterate over cpu_possible_map
-       for_each_online_cpu       - Iterate over cpu_online_map
-       for_each_present_cpu      - Iterate over cpu_present_map
+       for_each_possible_cpu     - Iterate over cpu_possible_mask
+       for_each_online_cpu       - Iterate over cpu_online_mask
+       for_each_present_cpu      - Iterate over cpu_present_mask
        for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
 
        #include <linux/cpu.h>
        get_online_cpus() and put_online_cpus():
 
 The above calls are used to inhibit cpu hotplug operations. While the
-cpu_hotplug.refcount is non zero, the cpu_online_map will not change.
+cpu_hotplug.refcount is non zero, the cpu_online_mask will not change.
 If you merely need to avoid cpus going away, you could also use
 preempt_disable() and preempt_enable() for those sections.
 Just remember the critical section cannot call any
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
new file mode 100644 (file)
index 0000000..8bb8a76
--- /dev/null
@@ -0,0 +1,16 @@
+* AHCI SATA Controller
+
+SATA nodes are defined to describe on-chip Serial ATA controllers.
+Each SATA controller should have its own node.
+
+Required properties:
+- compatible        : compatible list, contains "calxeda,hb-ahci" or "snps,spear-ahci"
+- interrupts        : <interrupt mapping for SATA IRQ>
+- reg               : <registers mapping>
+
+Example:
+        sata@ffe08000 {
+               compatible = "calxeda,hb-ahci";
+                reg = <0xffe08000 0x1000>;
+                interrupts = <115>;
+        };
diff --git a/Documentation/devicetree/bindings/ata/calxeda-sata.txt b/Documentation/devicetree/bindings/ata/calxeda-sata.txt
deleted file mode 100644 (file)
index 79caa56..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-* Calxeda SATA Controller
-
-SATA nodes are defined to describe on-chip Serial ATA controllers.
-Each SATA controller should have its own node.
-
-Required properties:
-- compatible        : compatible list, contains "calxeda,hb-ahci"
-- interrupts        : <interrupt mapping for SATA IRQ>
-- reg               : <registers mapping>
-
-Example:
-        sata@ffe08000 {
-               compatible = "calxeda,hb-ahci";
-                reg = <0xffe08000 0x1000>;
-                interrupts = <115>;
-        };
-
index 5903ecf6e8952398d61710cb578b5fbc71c53675..a20069502f5aaeeb85c45978bcf13c67f598e962 100644 (file)
@@ -27,13 +27,13 @@ nand0: nand@40000000,0 {
        reg = <0x40000000 0x10000000
               0xffffe800 0x200
              >;
-       atmel,nand-addr-offset = <21>;
-       atmel,nand-cmd-offset = <22>;
+       atmel,nand-addr-offset = <21>;  /* ale */
+       atmel,nand-cmd-offset = <22>;   /* cle */
        nand-on-flash-bbt;
        nand-ecc-mode = "soft";
-       gpios = <&pioC 13 0
-                &pioC 14 0
-                0
+       gpios = <&pioC 13 0     /* rdy */
+                &pioC 14 0     /* nce */
+                0              /* cd */
                >;
        partition@0 {
                ...
diff --git a/Documentation/devicetree/bindings/regulator/anatop-regulator.txt b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
new file mode 100644 (file)
index 0000000..357758c
--- /dev/null
@@ -0,0 +1,29 @@
+Anatop Voltage regulators
+
+Required properties:
+- compatible: Must be "fsl,anatop-regulator"
+- anatop-reg-offset: Anatop MFD register offset
+- anatop-vol-bit-shift: Bit shift for the register
+- anatop-vol-bit-width: Number of bits used in the register
+- anatop-min-bit-val: Minimum value of this register
+- anatop-min-voltage: Minimum voltage of this regulator
+- anatop-max-voltage: Maximum voltage of this regulator
+
+Any property defined as part of the core regulator
+binding, defined in regulator.txt, can also be used.
+
+Example:
+
+       regulator-vddpu {
+               compatible = "fsl,anatop-regulator";
+               regulator-name = "vddpu";
+               regulator-min-microvolt = <725000>;
+               regulator-max-microvolt = <1300000>;
+               regulator-always-on;
+               anatop-reg-offset = <0x140>;
+               anatop-vol-bit-shift = <9>;
+               anatop-vol-bit-width = <5>;
+               anatop-min-bit-val = <1>;
+               anatop-min-voltage = <725000>;
+               anatop-max-voltage = <1300000>;
+       };
index c1be8066ea5914c33e9a7aacbfee66f8455741b2..03ca210406edfcbe90fc58cd006ef0e7d313b42f 100644 (file)
@@ -6,14 +6,6 @@ be removed from this file.
 
 ---------------------------
 
-What:  x86 floppy disable_hlt
-When:  2012
-Why:   ancient workaround of dubious utility clutters the
-       code used by everybody else.
-Who:   Len Brown <len.brown@intel.com>
-
----------------------------
-
 What:  CONFIG_APM_CPU_IDLE, and its ability to call APM BIOS in idle
 When:  2012
 Why:   This optional sub-feature of APM is of dubious reliability,
@@ -539,3 +531,11 @@ Why:       There appear to be no production users of the get_robust_list syscall,
        of ASLR. It was only ever intended for debugging, so it should be
        removed.
 Who:   Kees Cook <keescook@chromium.org>
+
+----------------------------
+
+What:  setitimer accepts user NULL pointer (value)
+When:  3.6
+Why:   setitimer is not returning -EFAULT if user pointer is NULL. This
+       violates the spec.
+Who:   Sasikantha Babu <sasikanth.v19@gmail.com>
index e916e3d36488d982b4cc1a8580ea5f0529af79d2..0d0492028082c0ecda1a0931cc5100765624a80a 100644 (file)
@@ -114,7 +114,7 @@ members are defined:
 struct file_system_type {
        const char *name;
        int fs_flags;
-        struct dentry (*mount) (struct file_system_type *, int,
+        struct dentry *(*mount) (struct file_system_type *, int,
                        const char *, void *);
         void (*kill_sb) (struct super_block *);
         struct module *owner;
index a10f73624ad3d8f65dd365ba1ca225dcf64c9b01..90956b6180254915e9ff17bb968729c20e043369 100644 (file)
@@ -11,7 +11,7 @@ Supported chips:
   Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
 * AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series)
 * AMD Family 14h processors: "Brazos" (C/E/G/Z-Series)
-* AMD Family 15h processors: "Bulldozer"
+* AMD Family 15h processors: "Bulldozer" (FX-Series), "Trinity"
 
   Prefix: 'k10temp'
   Addresses scanned: PCI space
index 3b7488fc33730c3098a62cea18f6d0b0de3ef584..e34b531dc3161a18cc55fc591bd1db0e7c6991dd 100644 (file)
@@ -225,6 +225,7 @@ Code  Seq#(hex)     Include File            Comments
 'j'    00-3F   linux/joystick.h
 'k'    00-0F   linux/spi/spidev.h      conflict!
 'k'    00-05   video/kyro.h            conflict!
+'k'    10-17   linux/hsi/hsi_char.h    HSI character device
 'l'    00-3F   linux/tcfs_fs.h         transparent cryptographic file system
                                        <http://web.archive.org/web/*/http://mikonos.dia.unisa.it/tcfs>
 'l'    40-7F   linux/udf_fs_i.h        in development:
index c1601e5a8b71e81ae57f7d1d5a70be5449501443..41e398c568893f2b49555b4cbdb18a1621c26c63 100644 (file)
@@ -982,6 +982,20 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        i8k.restricted  [HW] Allow controlling fans only if SYS_ADMIN
                        capability is set.
 
+       i915.invert_brightness=
+                       [DRM] Invert the sense of the variable that is used to
+                       set the brightness of the panel backlight. Normally a
+                       brightness value of 0 indicates backlight switched off,
+                       and the maximum of the brightness value sets the backlight
+                       to maximum brightness. If this parameter is set to 0
+                       (default) and the machine requires it, or this parameter
+                       is set to 1, a brightness value of 0 sets the backlight
+                       to maximum brightness, and the maximum of the brightness
+                       value switches the backlight off.
+                       -1 -- never invert brightness
+                        0 -- machine default
+                        1 -- force brightness inversion
+
        icn=            [HW,ISDN]
                        Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
 
index 03283daa64fef72360667fb979a256aa10a3bb91..da59e2884130cbfc8b128b5be6b222ca10da82b8 100644 (file)
@@ -2,16 +2,16 @@ Document about softnet driver issues
 
 Transmit path guidelines:
 
-1) The hard_start_xmit method must never return '1' under any
-   normal circumstances.  It is considered a hard error unless
+1) The ndo_start_xmit method must not return NETDEV_TX_BUSY under
+   any normal circumstances.  It is considered a hard error unless
    there is no way your device can tell ahead of time when it's
    transmit function will become busy.
 
    Instead it must maintain the queue properly.  For example,
    for a driver implementing scatter-gather this means:
 
-       static int drv_hard_start_xmit(struct sk_buff *skb,
-                                      struct net_device *dev)
+       static netdev_tx_t drv_hard_start_xmit(struct sk_buff *skb,
+                                              struct net_device *dev)
        {
                struct drv *dp = netdev_priv(dev);
 
@@ -23,7 +23,7 @@ Transmit path guidelines:
                        unlock_tx(dp);
                        printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
                               dev->name);
-                       return 1;
+                       return NETDEV_TX_BUSY;
                }
 
                ... queue packet to card ...
@@ -35,6 +35,7 @@ Transmit path guidelines:
                ...
                unlock_tx(dp);
                ...
+               return NETDEV_TX_OK;
        }
 
    And then at the end of your TX reclamation event handling:
@@ -58,15 +59,12 @@ Transmit path guidelines:
             TX_BUFFS_AVAIL(dp) > 0)
                netif_wake_queue(dp->dev);
 
-2) Do not forget to update netdev->trans_start to jiffies after
-   each new tx packet is given to the hardware.
-
-3) A hard_start_xmit method must not modify the shared parts of a
+2) An ndo_start_xmit method must not modify the shared parts of a
    cloned SKB.
 
-4) Do not forget that once you return 0 from your hard_start_xmit
-   method, it is your driver's responsibility to free up the SKB
-   and in some finite amount of time.
+3) Do not forget that once you return NETDEV_TX_OK from your
+   ndo_start_xmit method, it is your driver's responsibility to free
+   up the SKB and in some finite amount of time.
 
    For example, this means that it is not allowed for your TX
    mitigation scheme to let TX packets "hang out" in the TX
@@ -74,8 +72,9 @@ Transmit path guidelines:
    This error can deadlock sockets waiting for send buffer room
    to be freed up.
 
-   If you return 1 from the hard_start_xmit method, you must not keep
-   any reference to that SKB and you must not attempt to free it up.
+   If you return NETDEV_TX_BUSY from the ndo_start_xmit method, you
+   must not keep any reference to that SKB and you must not attempt
+   to free it up.
 
 Probing guidelines:
 
@@ -85,10 +84,10 @@ Probing guidelines:
 
 Close/stop guidelines:
 
-1) After the dev->stop routine has been called, the hardware must
+1) After the ndo_stop routine has been called, the hardware must
    not receive or transmit any data.  All in flight packets must
    be aborted. If necessary, poll or wait for completion of 
    any reset commands.
 
-2) The dev->stop routine will be called by unregister_netdevice
+2) The ndo_stop routine will be called by unregister_netdevice
    if device is still UP.
index ad3e80e17b4f49a287c1d97d39e38cd8b092aa86..1619a8c8087341477621388701fec82ca832b70b 100644 (file)
@@ -147,7 +147,7 @@ tcp_adv_win_scale - INTEGER
        (if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
        if it is <= 0.
        Possible values are [-31, 31], inclusive.
-       Default: 2
+       Default: 1
 
 tcp_allowed_congestion_control - STRING
        Show/set the congestion control choices available to non-privileged
@@ -410,7 +410,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
        net.core.rmem_max.  Calling setsockopt() with SO_RCVBUF disables
        automatic tuning of that socket's receive buffer size, in which
        case this value is ignored.
-       Default: between 87380B and 4MB, depending on RAM size.
+       Default: between 87380B and 6MB, depending on RAM size.
 
 tcp_sack - BOOLEAN
        Enable select acknowledgments (SACKS).
@@ -604,15 +604,8 @@ IP Variables:
 ip_local_port_range - 2 INTEGERS
        Defines the local port range that is used by TCP and UDP to
        choose the local port. The first number is the first, the
-       second the last local port number. Default value depends on
-       amount of memory available on the system:
-       > 128Mb 32768-61000
-       < 128Mb 1024-4999 or even less.
-       This number defines number of active connections, which this
-       system can issue simultaneously to systems not supporting
-       TCP extensions (timestamps). With tcp_tw_recycle enabled
-       (i.e. by default) range 1024-4999 is enough to issue up to
-       2000 connections per second to systems supporting timestamps.
+       second the last local port number. The default values are
+       32768 and 61000 respectively.
 
 ip_local_reserved_ports - list of comma separated ranges
        Specify the ports which are reserved for known third-party
index 89358341682a1290879d26b854c1527991b54768..c7ecc7080494da43fc469eac5b62b06905c13559 100644 (file)
@@ -47,26 +47,25 @@ packets is preferred.
 
 struct net_device synchronization rules
 =======================================
-dev->open:
+ndo_open:
        Synchronization: rtnl_lock() semaphore.
        Context: process
 
-dev->stop:
+ndo_stop:
        Synchronization: rtnl_lock() semaphore.
        Context: process
-       Note1: netif_running() is guaranteed false
-       Note2: dev->poll() is guaranteed to be stopped
+       Note: netif_running() is guaranteed false
 
-dev->do_ioctl:
+ndo_do_ioctl:
        Synchronization: rtnl_lock() semaphore.
        Context: process
 
-dev->get_stats:
+ndo_get_stats:
        Synchronization: dev_base_lock rwlock.
        Context: nominally process, but don't sleep inside an rwlock
 
-dev->hard_start_xmit:
-       Synchronization: netif_tx_lock spinlock.
+ndo_start_xmit:
+       Synchronization: __netif_tx_lock spinlock.
 
        When the driver sets NETIF_F_LLTX in dev->features this will be
        called without holding netif_tx_lock. In this case the driver
@@ -87,20 +86,20 @@ dev->hard_start_xmit:
        o NETDEV_TX_LOCKED Locking failed, please retry quickly.
          Only valid when NETIF_F_LLTX is set.
 
-dev->tx_timeout:
-       Synchronization: netif_tx_lock spinlock.
+ndo_tx_timeout:
+       Synchronization: netif_tx_lock spinlock; all TX queues frozen.
        Context: BHs disabled
        Notes: netif_queue_stopped() is guaranteed true
 
-dev->set_rx_mode:
-       Synchronization: netif_tx_lock spinlock.
+ndo_set_rx_mode:
+       Synchronization: netif_addr_lock spinlock.
        Context: BHs disabled
 
 struct napi_struct synchronization rules
 ========================================
 napi->poll:
        Synchronization: NAPI_STATE_SCHED bit in napi->state.  Device
-               driver's dev->close method will invoke napi_disable() on
+               driver's ndo_stop method will invoke napi_disable() on
                all NAPI instances which will do a sleeping poll on the
                NAPI_STATE_SCHED napi->state bit, waiting for all pending
                NAPI activity to cease.
index ec715cd78fbb7028bde53c0664a513701b162858..6ec291ea1c78c64e4e1ec35ad614336859ab4c31 100644 (file)
@@ -9,7 +9,7 @@ architectures).
 
 II. How does it work?
 
-There are four per-task flags used for that, PF_NOFREEZE, PF_FROZEN, TIF_FREEZE
+There are three per-task flags used for that, PF_NOFREEZE, PF_FROZEN
 and PF_FREEZER_SKIP (the last one is auxiliary).  The tasks that have
 PF_NOFREEZE unset (all user space processes and some kernel threads) are
 regarded as 'freezable' and treated in a special way before the system enters a
@@ -17,30 +17,31 @@ suspend state as well as before a hibernation image is created (in what follows
 we only consider hibernation, but the description also applies to suspend).
 
 Namely, as the first step of the hibernation procedure the function
-freeze_processes() (defined in kernel/power/process.c) is called.  It executes
-try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
-either wakes them up, if they are kernel threads, or sends fake signals to them,
-if they are user space processes.  A task that has TIF_FREEZE set, should react
-to it by calling the function called __refrigerator() (defined in
-kernel/freezer.c), which sets the task's PF_FROZEN flag, changes its state
-to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it.
-Then, we say that the task is 'frozen' and therefore the set of functions
-handling this mechanism is referred to as 'the freezer' (these functions are
-defined in kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h).
-User space processes are generally frozen before kernel threads.
+freeze_processes() (defined in kernel/power/process.c) is called.  A system-wide
+variable system_freezing_cnt (as opposed to a per-task flag) is used to indicate
+whether the system is to undergo a freezing operation. And freeze_processes()
+sets this variable.  After this, it executes try_to_freeze_tasks() that sends a
+fake signal to all user space processes, and wakes up all the kernel threads.
+All freezable tasks must react to that by calling try_to_freeze(), which
+results in a call to __refrigerator() (defined in kernel/freezer.c), which sets
+the task's PF_FROZEN flag, changes its state to TASK_UNINTERRUPTIBLE and makes
+it loop until PF_FROZEN is cleared for it. Then, we say that the task is
+'frozen' and therefore the set of functions handling this mechanism is referred
+to as 'the freezer' (these functions are defined in kernel/power/process.c,
+kernel/freezer.c & include/linux/freezer.h). User space processes are generally
+frozen before kernel threads.
 
 __refrigerator() must not be called directly.  Instead, use the
 try_to_freeze() function (defined in include/linux/freezer.h), that checks
-the task's TIF_FREEZE flag and makes the task enter __refrigerator() if the
-flag is set.
+if the task is to be frozen and makes the task enter __refrigerator().
 
 For user space processes try_to_freeze() is called automatically from the
 signal-handling code, but the freezable kernel threads need to call it
 explicitly in suitable places or use the wait_event_freezable() or
 wait_event_freezable_timeout() macros (defined in include/linux/freezer.h)
-that combine interruptible sleep with checking if TIF_FREEZE is set and calling
-try_to_freeze().  The main loop of a freezable kernel thread may look like the
-following one:
+that combine interruptible sleep with checking if the task is to be frozen and
+calling try_to_freeze().  The main loop of a freezable kernel thread may look
+like the following one:
 
        set_freezable();
        do {
@@ -53,7 +54,7 @@ following one:
 (from drivers/usb/core/hub.c::hub_thread()).
 
 If a freezable kernel thread fails to call try_to_freeze() after the freezer has
-set TIF_FREEZE for it, the freezing of tasks will fail and the entire
+initiated a freezing operation, the freezing of tasks will fail and the entire
 hibernation operation will be cancelled.  For this reason, freezable kernel
 threads must call try_to_freeze() somewhere or use one of the
 wait_event_freezable() and wait_event_freezable_timeout() macros.
index 787717091421d54ec330f51bdaed0f2520749da8..d389acd31e19405410ca87acbe689739e0d35771 100644 (file)
@@ -123,7 +123,7 @@ KEY SERVICE OVERVIEW
 
 The key service provides a number of features besides keys:
 
- (*) The key service defines two special key types:
+ (*) The key service defines three special key types:
 
      (+) "keyring"
 
@@ -137,6 +137,18 @@ The key service provides a number of features besides keys:
         blobs of data. These can be created, updated and read by userspace,
         and aren't intended for use by kernel services.
 
+     (+) "logon"
+
+        Like a "user" key, a "logon" key has a payload that is an arbitrary
+        blob of data. It is intended as a place to store secrets which are
+        accessible to the kernel but not to userspace programs.
+
+        The description can be arbitrary, but must be prefixed with a non-zero
+        length string that describes the key "subclass". The subclass is
+        separated from the rest of the description by a ':'. "logon" keys can
+        be created and updated from userspace, but the payload is only
+        readable from kernel space.
+
  (*) Each process subscribes to three keyrings: a thread-specific keyring, a
      process-specific keyring, and a session-specific keyring.
 
index 8ffce746d496fc41de3cfadf7ad02af5f7fa6637..00d2c644068e9ae5d0e0044150289f0976a0ae9d 100644 (file)
@@ -168,6 +168,28 @@ that if the completion handler or anyone else tries to resubmit it
 they will get a -EPERM error.  Thus you can be sure that when
 usb_kill_urb() returns, the URB is totally idle.
 
+There is a lifetime issue to consider.  An URB may complete at any
+time, and the completion handler may free the URB.  If this happens
+while usb_unlink_urb or usb_kill_urb is running, it will cause a
+memory-access violation.  The driver is responsible for avoiding this,
+which often means some sort of lock will be needed to prevent the URB
+from being deallocated while it is still in use.
+
+On the other hand, since usb_unlink_urb may end up calling the
+completion handler, the handler must not take any lock that is held
+when usb_unlink_urb is invoked.  The general solution to this problem
+is to increment the URB's reference count while holding the lock, then
+drop the lock and call usb_unlink_urb or usb_kill_urb, and then
+decrement the URB's reference count.  You increment the reference
+count by calling
+
+       struct urb *usb_get_urb(struct urb *urb)
+
+(ignore the return value; it is the same as the argument) and
+decrement the reference count by calling usb_free_urb.  Of course,
+none of this is necessary if there's no danger of the URB being freed
+by the completion handler.
+
 
 1.7. What about the completion handler?
 
index 5335fa8b06eb4f2b632126bd9fd95878b6efdce0..c42bb9cd3b43749837f1c784a2571cb6d42bf03f 100644 (file)
@@ -183,10 +183,10 @@ An input control transfer to get a port status.
 d5ea89a0 3575914555 S Ci:1:001:0 s a3 00 0000 0003 0004 4 <
 d5ea89a0 3575914560 C Ci:1:001:0 0 4 = 01050000
 
-An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
-to a storage device at address 5:
+An output bulk transfer to send a SCSI command 0x28 (READ_10) in a 31-byte
+Bulk wrapper to a storage device at address 5:
 
-dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
+dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 ad000000 00800000 80010a28 20000000 20000040 00000000 000000
 dd65f0e8 4128379808 C Bo:1:005:2 0 31 >
 
 * Raw binary format and API
index 5190cf25fd8da03ca9d9bc834064f1e76e001bc3..707163365a9308845de03708d43fcbdde8c5452c 100644 (file)
@@ -228,7 +228,7 @@ M:  Len Brown <lenb@kernel.org>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 Q:     http://patchwork.kernel.org/project/linux-acpi/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
 S:     Supported
 F:     drivers/acpi/
 F:     drivers/pnp/pnpacpi/
@@ -1251,7 +1251,6 @@ ATHEROS ATH5K WIRELESS DRIVER
 M:     Jiri Slaby <jirislaby@gmail.com>
 M:     Nick Kossifidis <mickflemm@gmail.com>
 M:     "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
-M:     Bob Copeland <me@bobcopeland.com>
 L:     linux-wireless@vger.kernel.org
 L:     ath5k-devel@lists.ath5k.org
 W:     http://wireless.kernel.org/en/users/Drivers/ath5k
@@ -1522,8 +1521,8 @@ M:        Gustavo Padovan <gustavo@padovan.org>
 M:     Johan Hedberg <johan.hedberg@gmail.com>
 L:     linux-bluetooth@vger.kernel.org
 W:     http://www.bluez.org/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
 S:     Maintained
 F:     drivers/bluetooth/
 
@@ -1533,8 +1532,8 @@ M:        Gustavo Padovan <gustavo@padovan.org>
 M:     Johan Hedberg <johan.hedberg@gmail.com>
 L:     linux-bluetooth@vger.kernel.org
 W:     http://www.bluez.org/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
 S:     Maintained
 F:     net/bluetooth/
 F:     include/net/bluetooth/
@@ -1969,10 +1968,7 @@ S:       Maintained
 F:     drivers/net/ethernet/ti/cpmac.c
 
 CPU FREQUENCY DRIVERS
-M:     Dave Jones <davej@redhat.com>
 L:     cpufreq@vger.kernel.org
-W:     http://www.codemonkey.org.uk/projects/cpufreq/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git
 S:     Maintained
 F:     drivers/cpufreq/
 F:     include/linux/cpufreq.h
@@ -2322,9 +2318,9 @@ S:        Supported
 F:     drivers/acpi/dock.c
 
 DOCUMENTATION
-M:     Randy Dunlap <rdunlap@xenotime.net>
+M:     Rob Landley <rob@landley.net>
 L:     linux-doc@vger.kernel.org
-T:     quilt http://xenotime.net/kernel-doc-patches/current/
+T:     TBD
 S:     Maintained
 F:     Documentation/
 
@@ -2451,17 +2447,17 @@ F:      fs/ecryptfs/
 
 EDAC-CORE
 M:     Doug Thompson <dougthompson@xmission.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Supported
 F:     Documentation/edac.txt
-F:     drivers/edac/edac_*
+F:     drivers/edac/
 F:     include/linux/edac.h
 
 EDAC-AMD64
 M:     Doug Thompson <dougthompson@xmission.com>
 M:     Borislav Petkov <borislav.petkov@amd.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Supported
 F:     drivers/edac/amd64_edac*
@@ -2469,35 +2465,35 @@ F:      drivers/edac/amd64_edac*
 EDAC-E752X
 M:     Mark Gross <mark.gross@intel.com>
 M:     Doug Thompson <dougthompson@xmission.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/e752x_edac.c
 
 EDAC-E7XXX
 M:     Doug Thompson <dougthompson@xmission.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/e7xxx_edac.c
 
 EDAC-I82443BXGX
 M:     Tim Small <tim@buttersideup.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i82443bxgx_edac.c
 
 EDAC-I3000
 M:     Jason Uhlenkott <juhlenko@akamai.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i3000_edac.c
 
 EDAC-I5000
 M:     Doug Thompson <dougthompson@xmission.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i5000_edac.c
@@ -2526,21 +2522,21 @@ F:      drivers/edac/i7core_edac.c
 EDAC-I82975X
 M:     Ranganathan Desikan <ravi@jetztechnologies.com>
 M:     "Arvind R." <arvino55@gmail.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i82975x_edac.c
 
 EDAC-PASEMI
 M:     Egor Martovetsky <egor@pasemi.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/pasemi_edac.c
 
 EDAC-R82600
 M:     Tim Small <tim@buttersideup.com>
-L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/r82600_edac.c
@@ -3557,17 +3553,13 @@ L:      linux-pm@vger.kernel.org
 S:     Supported
 F:     arch/x86/platform/mrst/pmu.*
 
-INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
+INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
+M:     Stanislav Yakovlev <stas.yakovlev@gmail.com>
 L:     linux-wireless@vger.kernel.org
-S:     Orphan
+S:     Maintained
 F:     Documentation/networking/README.ipw2100
-F:     drivers/net/wireless/ipw2x00/ipw2100.*
-
-INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
-L:     linux-wireless@vger.kernel.org
-S:     Orphan
 F:     Documentation/networking/README.ipw2200
-F:     drivers/net/wireless/ipw2x00/ipw2200.*
+F:     drivers/net/wireless/ipw2x00/
 
 INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
 M:     Joseph Cihula <joseph.cihula@intel.com>
@@ -3597,6 +3589,7 @@ S:        Supported
 F:     drivers/net/wireless/iwlegacy/
 
 INTEL WIRELESS WIFI LINK (iwlwifi)
+M:     Johannes Berg <johannes.berg@intel.com>
 M:     Wey-Yi Guy <wey-yi.w.guy@intel.com>
 M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
@@ -4314,6 +4307,13 @@ W:       http://www.kernel.org/doc/man-pages
 L:     linux-man@vger.kernel.org
 S:     Maintained
 
+MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
+M:     Mirko Lindner <mlindner@marvell.com>
+M:     Stephen Hemminger <shemminger@vyatta.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/ethernet/marvell/sk*
+
 MARVELL LIBERTAS WIRELESS DRIVER
 M:     Dan Williams <dcbw@redhat.com>
 L:     libertas-dev@lists.infradead.org
@@ -4344,12 +4344,6 @@ M:       Nicolas Pitre <nico@fluxnic.net>
 S:     Odd Fixes
 F:     drivers/mmc/host/mvsdio.*
 
-MARVELL YUKON / SYSKONNECT DRIVER
-M:     Mirko Lindner <mlindner@syskonnect.de>
-M:     Ralph Roesler <rroesler@syskonnect.de>
-W:     http://www.syskonnect.com
-S:     Supported
-
 MATROX FRAMEBUFFER DRIVER
 L:     linux-fbdev@vger.kernel.org
 S:     Orphan
@@ -4537,8 +4531,7 @@ S:        Supported
 F:     drivers/net/ethernet/myricom/myri10ge/
 
 NATSEMI ETHERNET DRIVER (DP8381x)
-M:     Tim Hockin <thockin@hockin.org>
-S:     Maintained
+S:     Orphan
 F:     drivers/net/ethernet/natsemi/natsemi.c
 
 NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
@@ -5122,6 +5115,11 @@ F:       drivers/i2c/busses/i2c-pca-*
 F:     include/linux/i2c-algo-pca.h
 F:     include/linux/i2c-pca-platform.h
 
+PCDP - PRIMARY CONSOLE AND DEBUG PORT
+M:     Khalid Aziz <khalid.aziz@hp.com>
+S:     Maintained
+F:     drivers/firmware/pcdp.*
+
 PCI ERROR RECOVERY
 M:     Linas Vepstas <linasvepstas@gmail.com>
 L:     linux-pci@vger.kernel.org
@@ -5643,7 +5641,7 @@ M:        Ohad Ben-Cohen <ohad@wizery.com>
 S:     Maintained
 F:     drivers/remoteproc/
 F:     Documentation/remoteproc.txt
-F:     include/linux/remoteproc.txt
+F:     include/linux/remoteproc.h
 
 RFKILL
 M:     Johannes Berg <johannes@sipsolutions.net>
@@ -5891,11 +5889,11 @@ F:      Documentation/scsi/st.txt
 F:     drivers/scsi/st*
 
 SCTP PROTOCOL
-M:     Vlad Yasevich <vladislav.yasevich@hp.com>
+M:     Vlad Yasevich <vyasevich@gmail.com>
 M:     Sridhar Samudrala <sri@us.ibm.com>
 L:     linux-sctp@vger.kernel.org
 W:     http://lksctp.sourceforge.net
-S:     Supported
+S:     Maintained
 F:     Documentation/networking/sctp.txt
 F:     include/linux/sctp.h
 F:     include/net/sctp/
@@ -6122,12 +6120,6 @@ W:       http://www.winischhofer.at/linuxsisusbvga.shtml
 S:     Maintained
 F:     drivers/usb/misc/sisusbvga/
 
-SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
-M:     Stephen Hemminger <shemminger@vyatta.com>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/ethernet/marvell/sk*
-
 SLAB ALLOCATOR
 M:     Christoph Lameter <cl@linux-foundation.org>
 M:     Pekka Enberg <penberg@kernel.org>
@@ -6293,6 +6285,15 @@ F:       drivers/tty/serial/sunsu.c
 F:     drivers/tty/serial/sunzilog.c
 F:     drivers/tty/serial/sunzilog.h
 
+SPARSE CHECKER
+M:     "Christopher Li" <sparse@chrisli.org>
+L:     linux-sparse@vger.kernel.org
+W:     https://sparse.wiki.kernel.org/
+T:     git git://git.kernel.org/pub/scm/devel/sparse/sparse.git
+T:     git git://git.kernel.org/pub/scm/devel/sparse/chrisl/sparse.git
+S:     Maintained
+F:     include/linux/compiler.h
+
 SPEAR PLATFORM SUPPORT
 M:     Viresh Kumar <viresh.kumar@st.com>
 L:     spear-devel@list.st.com
@@ -6468,6 +6469,7 @@ S:        Odd Fixes
 F:     drivers/staging/olpc_dcon/
 
 STAGING - OZMO DEVICES USB OVER WIFI DRIVER
+M:     Rupesh Gujare <rgujare@ozmodevices.com>
 M:     Chris Kelly <ckelly@ozmodevices.com>
 S:     Maintained
 F:     drivers/staging/ozwpan/
@@ -7574,8 +7576,8 @@ F:        Documentation/filesystems/xfs.txt
 F:     fs/xfs/
 
 XILINX AXI ETHERNET DRIVER
-M:     Ariane Keller <ariane.keller@tik.ee.ethz.ch>
-M:     Daniel Borkmann <daniel.borkmann@tik.ee.ethz.ch>
+M:     Anirudha Sarangi <anirudh@xilinx.com>
+M:     John Linn <John.Linn@xilinx.com>
 S:     Maintained
 F:     drivers/net/ethernet/xilinx/xilinx_axienet*
 
index 5e637c23974e6e1d57721c4051cc3b253a43d579..9e384ae6c403cb92d3ed633b3e033bf3a6c3c3de 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc6
 NAME = Saber-toothed Squirrel
 
 # *DOCUMENTATION*
index 56a4df952fb0f2e68889229133e38b2b34de4716..22e58a99f38b0fd19232ec8fec64249ca429846f 100644 (file)
@@ -477,7 +477,7 @@ config ALPHA_BROKEN_IRQ_MASK
 
 config VGA_HOSE
        bool
-       depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL || ALPHA_TSUNAMI
+       depends on VGA_CONSOLE && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL || ALPHA_TSUNAMI)
        default y
        help
          Support VGA on an arbitrary hose; needed for several platforms
index f62251e82ffac39579e26c0ee6f77f58c1bd9ac5..3bb7ffeae3bc610010bb54a3eaba698c513c0c7d 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <asm/barrier.h>
+#include <asm/cmpxchg.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -168,73 +169,6 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
        return result;
 }
 
-/*
- * Atomic exchange routines.
- */
-
-#define __ASM__MB
-#define ____xchg(type, args...)                __xchg ## type ## _local(args)
-#define ____cmpxchg(type, args...)     __cmpxchg ## type ## _local(args)
-#include <asm/xchg.h>
-
-#define xchg_local(ptr,x)                                              \
-  ({                                                                   \
-     __typeof__(*(ptr)) _x_ = (x);                                     \
-     (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_,      \
-                                      sizeof(*(ptr)));                 \
-  })
-
-#define cmpxchg_local(ptr, o, n)                                       \
-  ({                                                                   \
-     __typeof__(*(ptr)) _o_ = (o);                                     \
-     __typeof__(*(ptr)) _n_ = (n);                                     \
-     (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_,   \
-                                         (unsigned long)_n_,           \
-                                         sizeof(*(ptr)));              \
-  })
-
-#define cmpxchg64_local(ptr, o, n)                                     \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg_local((ptr), (o), (n));                                 \
-  })
-
-#ifdef CONFIG_SMP
-#undef __ASM__MB
-#define __ASM__MB      "\tmb\n"
-#endif
-#undef ____xchg
-#undef ____cmpxchg
-#define ____xchg(type, args...)                __xchg ##type(args)
-#define ____cmpxchg(type, args...)     __cmpxchg ##type(args)
-#include <asm/xchg.h>
-
-#define xchg(ptr,x)                                                    \
-  ({                                                                   \
-     __typeof__(*(ptr)) _x_ = (x);                                     \
-     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_,            \
-                                sizeof(*(ptr)));                       \
-  })
-
-#define cmpxchg(ptr, o, n)                                             \
-  ({                                                                   \
-     __typeof__(*(ptr)) _o_ = (o);                                     \
-     __typeof__(*(ptr)) _n_ = (n);                                     \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,         \
-                                   (unsigned long)_n_, sizeof(*(ptr)));\
-  })
-
-#define cmpxchg64(ptr, o, n)                                           \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg((ptr), (o), (n));                                       \
-  })
-
-#undef __ASM__MB
-#undef ____cmpxchg
-
-#define __HAVE_ARCH_CMPXCHG 1
-
 #define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 
diff --git a/arch/alpha/include/asm/cmpxchg.h b/arch/alpha/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..429e8cd
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef _ALPHA_CMPXCHG_H
+#define _ALPHA_CMPXCHG_H
+
+/*
+ * Atomic exchange routines.
+ */
+
+#define __ASM__MB
+#define ____xchg(type, args...)                __xchg ## type ## _local(args)
+#define ____cmpxchg(type, args...)     __cmpxchg ## type ## _local(args)
+#include <asm/xchg.h>
+
+#define xchg_local(ptr, x)                                             \
+({                                                                     \
+       __typeof__(*(ptr)) _x_ = (x);                                   \
+       (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_,    \
+                                      sizeof(*(ptr)));                 \
+})
+
+#define cmpxchg_local(ptr, o, n)                                       \
+({                                                                     \
+       __typeof__(*(ptr)) _o_ = (o);                                   \
+       __typeof__(*(ptr)) _n_ = (n);                                   \
+       (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \
+                                         (unsigned long)_n_,           \
+                                         sizeof(*(ptr)));              \
+})
+
+#define cmpxchg64_local(ptr, o, n)                                     \
+({                                                                     \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_local((ptr), (o), (n));                                 \
+})
+
+#ifdef CONFIG_SMP
+#undef __ASM__MB
+#define __ASM__MB      "\tmb\n"
+#endif
+#undef ____xchg
+#undef ____cmpxchg
+#define ____xchg(type, args...)                __xchg ##type(args)
+#define ____cmpxchg(type, args...)     __cmpxchg ##type(args)
+#include <asm/xchg.h>
+
+#define xchg(ptr, x)                                                   \
+({                                                                     \
+       __typeof__(*(ptr)) _x_ = (x);                                   \
+       (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_,          \
+                                sizeof(*(ptr)));                       \
+})
+
+#define cmpxchg(ptr, o, n)                                             \
+({                                                                     \
+       __typeof__(*(ptr)) _o_ = (o);                                   \
+       __typeof__(*(ptr)) _n_ = (n);                                   \
+       (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,       \
+                                   (unsigned long)_n_, sizeof(*(ptr)));\
+})
+
+#define cmpxchg64(ptr, o, n)                                           \
+({                                                                     \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg((ptr), (o), (n));                                       \
+})
+
+#undef __ASM__MB
+#undef ____cmpxchg
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+#endif /* _ALPHA_CMPXCHG_H */
index 4567aca6fdd6ef32e3730c60fa725b98f299d8aa..dfa32f0613201a92c5c6e5bf81443302deff46ac 100644 (file)
@@ -12,16 +12,22 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 
 #include <asm-generic/dma-mapping-common.h>
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t gfp)
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t gfp,
+                                   struct dma_attrs *attrs)
 {
-       return get_dma_ops(dev)->alloc_coherent(dev, size, dma_handle, gfp);
+       return get_dma_ops(dev)->alloc(dev, size, dma_handle, gfp, attrs);
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *vaddr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *vaddr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
-       get_dma_ops(dev)->free_coherent(dev, size, vaddr, dma_handle);
+       get_dma_ops(dev)->free(dev, size, vaddr, dma_handle, attrs);
 }
 
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
index 1f7fba671ae68a25f204cf819e3e04bde362810e..d70408d36677c86d0fbd8ce90530724e54d15a57 100644 (file)
@@ -1,14 +1,10 @@
 #ifndef _ALPHA_RTC_H
 #define _ALPHA_RTC_H
 
-#if defined(CONFIG_ALPHA_GENERIC)
+#if defined(CONFIG_ALPHA_MARVEL) && defined(CONFIG_SMP) \
+ || defined(CONFIG_ALPHA_GENERIC)
 # define get_rtc_time          alpha_mv.rtc_get_time
 # define set_rtc_time          alpha_mv.rtc_set_time
-#else
-# if defined(CONFIG_ALPHA_MARVEL) && defined(CONFIG_SMP)
-#  define get_rtc_time         marvel_get_rtc_time
-#  define set_rtc_time         marvel_set_rtc_time
-# endif
 #endif
 
 #include <asm-generic/rtc.h>
index 1d1b436fbff252bc867c8e577c7b8759bc55cc20..0ca9724597c1603024ff26d366013bc2da92387b 100644 (file)
@@ -1,10 +1,10 @@
-#ifndef _ALPHA_ATOMIC_H
+#ifndef _ALPHA_CMPXCHG_H
 #error Do not include xchg.h directly!
 #else
 /*
  * xchg/xchg_local and cmpxchg/cmpxchg_local share the same code
  * except that local version do not have the expensive memory barrier.
- * So this file is included twice from asm/system.h.
+ * So this file is included twice from asm/cmpxchg.h.
  */
 
 /*
index 5e7c28f92f19f29dde28d0e636ceb696f1750457..61893d7bdda552ac50e9fadadf957c6b6badb668 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/core_tsunami.h>
 #undef __EXTERN_INLINE
 
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/sched.h>
index 04eea4894ef33bc84c60335fc1e79e31553bd328..df24b76f92461a5df780059eea1488e3b50945e7 100644 (file)
@@ -108,7 +108,8 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
 }
 
 static void *alpha_noop_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t gfp)
+                                      dma_addr_t *dma_handle, gfp_t gfp,
+                                      struct dma_attrs *attrs)
 {
        void *ret;
 
@@ -123,7 +124,8 @@ static void *alpha_noop_alloc_coherent(struct device *dev, size_t size,
 }
 
 static void alpha_noop_free_coherent(struct device *dev, size_t size,
-                                    void *cpu_addr, dma_addr_t dma_addr)
+                                    void *cpu_addr, dma_addr_t dma_addr,
+                                    struct dma_attrs *attrs)
 {
        free_pages((unsigned long)cpu_addr, get_order(size));
 }
@@ -174,8 +176,8 @@ static int alpha_noop_set_mask(struct device *dev, u64 mask)
 }
 
 struct dma_map_ops alpha_noop_ops = {
-       .alloc_coherent         = alpha_noop_alloc_coherent,
-       .free_coherent          = alpha_noop_free_coherent,
+       .alloc                  = alpha_noop_alloc_coherent,
+       .free                   = alpha_noop_free_coherent,
        .map_page               = alpha_noop_map_page,
        .map_sg                 = alpha_noop_map_sg,
        .mapping_error          = alpha_noop_mapping_error,
index 43610804987dd454556307627753e79cbc457a94..cd634795aa9cda898c4f129b46e94e7d1475c785 100644 (file)
@@ -434,7 +434,8 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
    else DMA_ADDRP is undefined.  */
 
 static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
-                                     dma_addr_t *dma_addrp, gfp_t gfp)
+                                     dma_addr_t *dma_addrp, gfp_t gfp,
+                                     struct dma_attrs *attrs)
 {
        struct pci_dev *pdev = alpha_gendev_to_pci(dev);
        void *cpu_addr;
@@ -478,7 +479,8 @@ try_again:
    DMA_ADDR past this call are illegal.  */
 
 static void alpha_pci_free_coherent(struct device *dev, size_t size,
-                                   void *cpu_addr, dma_addr_t dma_addr)
+                                   void *cpu_addr, dma_addr_t dma_addr,
+                                   struct dma_attrs *attrs)
 {
        struct pci_dev *pdev = alpha_gendev_to_pci(dev);
        pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
@@ -952,8 +954,8 @@ static int alpha_pci_set_mask(struct device *dev, u64 mask)
 }
 
 struct dma_map_ops alpha_pci_ops = {
-       .alloc_coherent         = alpha_pci_alloc_coherent,
-       .free_coherent          = alpha_pci_free_coherent,
+       .alloc                  = alpha_pci_alloc_coherent,
+       .free                   = alpha_pci_free_coherent,
        .map_page               = alpha_pci_map_page,
        .unmap_page             = alpha_pci_unmap_page,
        .map_sg                 = alpha_pci_map_sg,
index 6f7feb5db27193f33e24e962e4d1be257d8464ef..35f2ef44de12629cfa166cef50f23b5e72b365cb 100644 (file)
@@ -120,12 +120,13 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
  */
 SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
+       sigset_t blocked;
+
        current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+
+       mask &= _BLOCKABLE;
+       siginitset(&blocked, mask);
+       set_current_blocked(&blocked);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -238,10 +239,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
                goto give_sigsegv;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(sc, regs, sw))
                goto give_sigsegv;
@@ -276,10 +274,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
                goto give_sigsegv;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
                goto give_sigsegv;
@@ -501,14 +496,8 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
        else
                ret = setup_frame(sig, ka, oldset, regs, sw);
 
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER)) 
-                       sigaddset(&current->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       if (ret == 0)
+               block_sigmask(ka, sig);
 
        return ret;
 }
index 4087a569b43b15f7f135241c88092395651a4a7a..50d438db1f6ba3d8fc7131c30d340bb7d293d414 100644 (file)
@@ -450,7 +450,7 @@ setup_smp(void)
                smp_num_probed = 1;
        }
 
-       printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_map = %lx\n",
+       printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
               smp_num_probed, cpumask_bits(cpu_present_mask)[0]);
 }
 
index 14a4b6a7cf59d3fa94b121714c7e3c67792618e8..407accc808777bc4a6f36fa6b912b92686d09a0b 100644 (file)
@@ -317,7 +317,7 @@ marvel_init_irq(void)
 }
 
 static int 
-marvel_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+marvel_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
        struct pci_controller *hose = dev->sysdata;
        struct io7_port *io7_port = hose->sysdata;
index 93180845ae164dbeeca41a27dfce6fda553bcb3d..36586dba6fa6e0af6260dce3827cfe1495c7f592 100644 (file)
@@ -338,6 +338,7 @@ config ARCH_AT91
        select HAVE_CLK
        select CLKDEV_LOOKUP
        select IRQ_DOMAIN
+       select NEED_MACH_IO_H if PCCARD
        help
          This enables support for systems based on the Atmel AT91RM9200,
          AT91SAM9 processors.
@@ -1185,6 +1186,15 @@ if !MMU
 source "arch/arm/Kconfig-nommu"
 endif
 
+config ARM_ERRATA_326103
+       bool "ARM errata: FSR write bit incorrect on a SWP to read-only memory"
+       depends on CPU_V6
+       help
+         Executing a SWP instruction to read-only memory does not set bit 11
+         of the FSR on the ARM 1136 prior to r1p0. This causes the kernel to
+         treat the access as a read, preventing a COW from occurring and
+         causing the faulting task to livelock.
+
 config ARM_ERRATA_411920
        bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
        depends on CPU_V6 || CPU_V6K
index 6ce11c4811786389b830d497814c5338983cc723..797f04bedb47e4175ed8cdc707efe12a71ec0693 100644 (file)
@@ -77,6 +77,8 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space)
                } else if (atag->hdr.tag == ATAG_MEM) {
                        if (memcount >= sizeof(mem_reg_property)/4)
                                continue;
+                       if (!atag->u.mem.size)
+                               continue;
                        mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
                        mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
                } else if (atag->hdr.tag == ATAG_INITRD2) {
index 5f6045f1766cc758a94c14d2de2d01164179637a..dc7e8ce8e6bed9ad10a696de4c8bbecdb909fdad 100644 (file)
@@ -273,7 +273,7 @@ restart:    adr     r0, LC0
                add     r0, r0, #0x100
                mov     r1, r6
                sub     r2, sp, r6
-               blne    atags_to_fdt
+               bleq    atags_to_fdt
 
                ldmfd   sp!, {r0-r3, ip, lr}
                sub     sp, sp, #0x10000
index 92f36627e7f8a3414ba87f020b051b5c283b69eb..773ef484037a91fd5613d26b2029a7c89f083eed 100644 (file)
@@ -35,7 +35,7 @@
                };
        };
 
-       memory@20000000 {
+       memory {
                reg = <0x20000000 0x08000000>;
        };
 
@@ -55,7 +55,6 @@
                                #interrupt-cells = <2>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
-                               interrupt-parent;
                                reg = <0xfffff000 0x200>;
                        };
 
index ac0dc0031dda310caac9ff77f54c56131c0281b6..7829a4d0cb22e2b4c010def2ca689e46c7682044 100644 (file)
@@ -37,8 +37,8 @@
                usb0: ohci@00600000 {
                        status = "okay";
                        num-ports = <2>;
-                       atmel,vbus-gpio = <&pioD 19 0
-                                          &pioD 20 0
+                       atmel,vbus-gpio = <&pioD 19 1
+                                          &pioD 20 1
                                          >;
                };
 
index 3d0c32fb218f4682a1400b38fc00e51195f85752..c8042147eaa2d39cc7470dd3525063a0e45563a0 100644 (file)
@@ -36,7 +36,7 @@
                };
        };
 
-       memory@70000000 {
+       memory {
                reg = <0x70000000 0x10000000>;
        };
 
@@ -56,7 +56,6 @@
                                #interrupt-cells = <2>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
-                               interrupt-parent;
                                reg = <0xfffff000 0x200>;
                        };
 
index c4c8ae4123d522d4f342f2ebc8ddff1e69126a05..a3633bd1311145168f36278afbed6dfe9e6bce76 100644 (file)
@@ -17,7 +17,7 @@
                bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
        };
 
-       memory@70000000 {
+       memory {
                reg = <0x70000000 0x4000000>;
        };
 
@@ -73,8 +73,8 @@
                usb0: ohci@00700000 {
                        status = "okay";
                        num-ports = <2>;
-                       atmel,vbus-gpio = <&pioD 1 0
-                                          &pioD 3 0>;
+                       atmel,vbus-gpio = <&pioD 1 1
+                                          &pioD 3 1>;
                };
 
                usb1: ehci@00800000 {
index c111001f254ea1d414a510f6258c3c94831cf79a..dd4ed748469a2e576a84562fd212328b4716623e 100644 (file)
@@ -34,7 +34,7 @@
                };
        };
 
-       memory@20000000 {
+       memory {
                reg = <0x20000000 0x10000000>;
        };
 
@@ -54,7 +54,6 @@
                                #interrupt-cells = <2>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
-                               interrupt-parent;
                                reg = <0xfffff000 0x200>;
                        };
 
                              >;
                        atmel,nand-addr-offset = <21>;
                        atmel,nand-cmd-offset = <22>;
-                       gpios = <&pioC 8 0
-                                &pioC 14 0
+                       gpios = <&pioD 5 0
+                                &pio4 0
                                 0
                                >;
                        status = "disabled";
index 67936f83c69450703528888710e9aaea1936c99d..31e7be23703d258a49b58a2afb05bb16e780fcff 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 / {
-       memory@20000000 {
+       memory {
                reg = <0x20000000 0x8000000>;
        };
 
index d73dce6456679de2281c121225b677930ba85a83..14bc307050999d278cda3684b98da6577e6d6371 100644 (file)
@@ -24,7 +24,6 @@
                        #interrupt-cells = <3>;
                        #address-cells = <1>;
                        interrupt-controller;
-                       interrupt-parent;
                        reg = <0xa0411000 0x1000>,
                              <0xa0410100 0x100>;
                };
index 37c0ff9c8b90cb03f0ebb7fb2e1ce961ee4c141c..83e72294aefb1211c1bc3cdecab273750baa3294 100644 (file)
@@ -89,7 +89,6 @@
                        #size-cells = <0>;
                        #address-cells = <1>;
                        interrupt-controller;
-                       interrupt-parent;
                        reg = <0xfff11000 0x1000>,
                              <0xfff10100 0x100>;
                };
index 15ded0deaa79aec744760a00b8f80e9f81fe4228..45bc4bb04e5745969184b9baa3e78e4d4c5402f3 100644 (file)
@@ -10,7 +10,7 @@
        intc: interrupt-controller@02080000 {
                compatible = "qcom,msm-8660-qgic";
                interrupt-controller;
-               #interrupt-cells = <1>;
+               #interrupt-cells = <3>;
                reg = < 0x02080000 0x1000 >,
                      < 0x02081000 0x1000 >;
        };
@@ -19,6 +19,6 @@
                compatible = "qcom,msm-hsuart", "qcom,msm-uart";
                reg = <0x19c40000 0x1000>,
                      <0x19c00000 0x1000>;
-               interrupts = <195>;
+               interrupts = <0 195 0x0>;
        };
 };
index 3b3c4e0fa79f8429df9efafc2a97942e997e3331..7c2399c532e52990b17f98c6ce48908f0e3b11c3 100644 (file)
@@ -16,7 +16,7 @@
                bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
        };
 
-       memory@20000000 {
+       memory {
                reg = <0x20000000 0x4000000>;
        };
 
index 0b32925f21474fcb983716aed17205bd50ee10a3..e2fe3195c0d109c6a31853455171627724c2e2d8 100644 (file)
                        mmc@5000 {
                                compatible = "arm,primecell";
                                reg = < 0x5000 0x1000>;
-                               interrupts = <22>;
+                               interrupts = <22 34>;
                        };
                        kmi@6000 {
                                compatible = "arm,pl050", "arm,primecell";
index 166461073b7893ec6dc49a60957bf8ef1d3e106f..7e8175269064d6f5dbf0a0b3bca1b933aa5efd9f 100644 (file)
@@ -41,7 +41,7 @@
                        mmc@b000 {
                                compatible = "arm,primecell";
                                reg = <0xb000 0x1000>;
-                               interrupts = <23>;
+                               interrupts = <23 34>;
                        };
                };
        };
index 7a66311f306666bf7c7ff07ffcbe4e501c93f236..7e288f96cedf01fa782b3326788d40305c551e0d 100644 (file)
@@ -427,19 +427,18 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
 
 /*
  * Handle each interrupt in a single VIC.  Returns non-zero if we've
- * handled at least one interrupt.  This does a single read of the
- * status register and handles all interrupts in order from LSB first.
+ * handled at least one interrupt.  This reads the status register
+ * before handling each interrupt, which is necessary given that
+ * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
  */
 static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
 {
        u32 stat, irq;
        int handled = 0;
 
-       stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
-       while (stat) {
+       while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
                irq = ffs(stat) - 1;
                handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
-               stat &= ~(1 << irq);
                handled = 1;
        }
 
index b5ac644e12af9121985b0eadeecfdefaaf85c33b..6b31cb60daabd516579d55f1cb2b5a7198cb3776 100644 (file)
@@ -112,6 +112,7 @@ CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
 CONFIG_MFD_MC13XXX=y
 CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_FB=y
index 42da9183acc85509342b00bc14a458a6d5d6a267..082175c54e7cc7343a15c7d0f15f3ddbf5631c8a 100644 (file)
@@ -14,6 +14,8 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_ARCH_S3C24XX=y
+# CONFIG_CPU_S3C2410 is not set
+CONFIG_CPU_S3C2440=y
 CONFIG_S3C_ADC=y
 CONFIG_S3C24XX_PWM=y
 CONFIG_MACH_MINI2440=y
index 889d73ac1ae11e6870a7a345fb402b8e54ce8070..7e84f453e8a6f07e76c182badb2ee055eda1bde6 100644 (file)
@@ -8,8 +8,6 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_ARCH_U8500=y
-CONFIG_UX500_SOC_DB5500=y
-CONFIG_UX500_SOC_DB8500=y
 CONFIG_MACH_HREFV60=y
 CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_U5500=y
@@ -39,7 +37,6 @@ CONFIG_CAIF=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
-CONFIG_MISC_DEVICES=y
 CONFIG_AB8500_PWM=y
 CONFIG_SENSORS_BH1780=y
 CONFIG_NETDEVICES=y
@@ -65,16 +62,18 @@ CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_NOMADIK=y
-CONFIG_I2C=y
-CONFIG_I2C_NOMADIK=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_TC3589X=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_AB8500_BM=y
+CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
 CONFIG_AB5500_CORE=y
 CONFIG_AB8500_CORE=y
+CONFIG_REGULATOR=y
 CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB_GADGET=y
index 44f4a09ff37b6d095c61c9f264c43ba5ff53db84..05112380dc5398dd47cbd9fb6adf564f96a4c94c 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_BARRIER_H
 
 #ifndef __ASSEMBLY__
+#include <asm/outercache.h>
 
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
@@ -39,7 +40,6 @@
 #ifdef CONFIG_ARCH_HAS_BARRIERS
 #include <mach/barriers.h>
 #elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
-#include <asm/outercache.h>
 #define mb()           do { dsb(); outer_sync(); } while (0)
 #define rmb()          dsb()
 #define wmb()          mb()
index df0ac0bb39aae43d6ebf92a7271c4ba7e536f151..9af5563dd3ebbc6be0f53448e107a05249cca859 100644 (file)
@@ -119,7 +119,7 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
 #ifdef CONFIG_NEED_MACH_IO_H
 #include <mach/io.h>
 #else
-#define __io(a)                ({ (void)(a); __typesafe_io(0); })
+#define __io(a)                __typesafe_io((a) & IO_SPACE_LIMIT)
 #endif
 
 /*
index 5c5ca2ea62b04753c49b6d64eb8d9ca9214049a5..bfc198c759130109d44b73b4506ea853d01fba28 100644 (file)
@@ -14,7 +14,7 @@
 #define JUMP_LABEL_NOP "nop"
 #endif
 
-static __always_inline bool arch_static_branch(struct jump_label_key *key)
+static __always_inline bool arch_static_branch(struct static_key *key)
 {
        asm goto("1:\n\t"
                 JUMP_LABEL_NOP "\n\t"
index d4c24d412a8ddbdaba9f11a6217cd6a8b592c22c..0f04d84582e1d81ef5448ee180d23b42c80a2eee 100644 (file)
@@ -118,6 +118,13 @@ extern void iwmmxt_task_switch(struct thread_info *);
 extern void vfp_sync_hwstate(struct thread_info *);
 extern void vfp_flush_hwstate(struct thread_info *);
 
+struct user_vfp;
+struct user_vfp_exc;
+
+extern int vfp_preserve_user_clear_hwstate(struct user_vfp __user *,
+                                          struct user_vfp_exc __user *);
+extern int vfp_restore_user_hwstate(struct user_vfp __user *,
+                                   struct user_vfp_exc __user *);
 #endif
 
 /*
index 60843eb0f61c3f9f9536d3ebaebc05b3cdfd2189..73409e6c0251001b5b03f27ae811a523cc605f62 100644 (file)
@@ -7,6 +7,8 @@
 
        .macro set_tls_v6k, tp, tmp1, tmp2
        mcr     p15, 0, \tp, c13, c0, 3         @ set TLS register
+       mov     \tmp1, #0
+       mcr     p15, 0, \tmp1, c13, c0, 2       @ clear user r/w TLS register
        .endm
 
        .macro set_tls_v6, tp, tmp1, tmp2
@@ -15,6 +17,8 @@
        mov     \tmp2, #0xffff0fff
        tst     \tmp1, #HWCAP_TLS               @ hardware TLS available?
        mcrne   p15, 0, \tp, c13, c0, 3         @ yes, set TLS register
+       movne   \tmp1, #0
+       mcrne   p15, 0, \tmp1, c13, c0, 2       @ clear user r/w TLS register
        streq   \tp, [\tmp2, #-15]              @ set TLS value at 0xffff0ff0
        .endm
 
index 632df9a66f8c1e989a3d369457579b5613c65aab..ede5f7741c42246984333a4398020015575ebaaa 100644 (file)
@@ -299,7 +299,6 @@ static inline int pdev_bad_for_parity(struct pci_dev *dev)
  */
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       struct pci_sys_data *root = bus->sysdata;
        struct pci_dev *dev;
        u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
 
index ab312e516546ac8fc0d25b7d0a352c18e613dfcd..b760340b70146123bd05dbc32e47d042f8d243d1 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/bug.h>
 #include <linux/kernel.h>
 #include <asm/opcodes.h>
 
index 71ccdbfed66276f2c76db1b683da17cab392f0ad..8349d4e97e2b8b9b7bb5672b2cf974c2cdb74fd0 100644 (file)
@@ -155,10 +155,10 @@ static bool migrate_one_irq(struct irq_desc *desc)
        }
 
        c = irq_data_get_irq_chip(d);
-       if (c->irq_set_affinity)
-               c->irq_set_affinity(d, affinity, true);
-       else
+       if (!c->irq_set_affinity)
                pr_debug("IRQ%u: unable to set affinity\n", d->irq);
+       else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
+               cpumask_copy(d->affinity, affinity);
 
        return ret;
 }
index ab1869dac97a96a6399964e088f1dc58ff6191e2..4dd41fc9e23572793ec384b28b77fb9d5ada63d8 100644 (file)
@@ -152,7 +152,7 @@ int __kprobes __arch_disarm_kprobe(void *p)
 
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
-       stop_machine(__arch_disarm_kprobe, p, &cpu_online_map);
+       stop_machine(__arch_disarm_kprobe, p, cpu_online_mask);
 }
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
index 45956c9d0ef0d383dc60a41ba20be10256d029e8..80abafb9bf3374d5f6d86b67ee0f1b1260b7e9fc 100644 (file)
@@ -256,7 +256,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
 {
        unsigned long tmp;
 
-       if (off & 3 || off >= sizeof(struct user))
+       if (off & 3)
                return -EIO;
 
        tmp = 0;
@@ -268,6 +268,8 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
                tmp = tsk->mm->end_code;
        else if (off < sizeof(struct pt_regs))
                tmp = get_user_reg(tsk, off >> 2);
+       else if (off >= sizeof(struct user))
+               return -EIO;
 
        return put_user(tmp, ret);
 }
index b91411371ae19b1ae75c2184b4b26ec6c9b06193..ebfac782593f048c9cf81a5619f0b3d24900ca8c 100644 (file)
@@ -523,7 +523,21 @@ int __init arm_add_memory(phys_addr_t start, unsigned long size)
         */
        size -= start & ~PAGE_MASK;
        bank->start = PAGE_ALIGN(start);
-       bank->size  = size & PAGE_MASK;
+
+#ifndef CONFIG_LPAE
+       if (bank->start + size < bank->start) {
+               printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in "
+                       "32-bit physical address space\n", (long long)start);
+               /*
+                * To ensure bank->start + bank->size is representable in
+                * 32 bits, we use ULONG_MAX as the upper limit rather than 4GB.
+                * This means we lose a page after masking.
+                */
+               size = ULONG_MAX - bank->start;
+       }
+#endif
+
+       bank->size = size & PAGE_MASK;
 
        /*
         * Check whether this memory region has non-zero size or
index 7cb532fc8aa4e3a9dc1e9d63d4cb887a08b1fad1..d68d1b6946809831458d03d8a020ea32f571c62f 100644 (file)
@@ -180,44 +180,23 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
 
 static int preserve_vfp_context(struct vfp_sigframe __user *frame)
 {
-       struct thread_info *thread = current_thread_info();
-       struct vfp_hard_struct *h = &thread->vfpstate.hard;
        const unsigned long magic = VFP_MAGIC;
        const unsigned long size = VFP_STORAGE_SIZE;
        int err = 0;
 
-       vfp_sync_hwstate(thread);
        __put_user_error(magic, &frame->magic, err);
        __put_user_error(size, &frame->size, err);
 
-       /*
-        * Copy the floating point registers. There can be unused
-        * registers see asm/hwcap.h for details.
-        */
-       err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs,
-                             sizeof(h->fpregs));
-       /*
-        * Copy the status and control register.
-        */
-       __put_user_error(h->fpscr, &frame->ufp.fpscr, err);
-
-       /*
-        * Copy the exception registers.
-        */
-       __put_user_error(h->fpexc, &frame->ufp_exc.fpexc, err);
-       __put_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
-       __put_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
+       if (err)
+               return -EFAULT;
 
-       return err ? -EFAULT : 0;
+       return vfp_preserve_user_clear_hwstate(&frame->ufp, &frame->ufp_exc);
 }
 
 static int restore_vfp_context(struct vfp_sigframe __user *frame)
 {
-       struct thread_info *thread = current_thread_info();
-       struct vfp_hard_struct *h = &thread->vfpstate.hard;
        unsigned long magic;
        unsigned long size;
-       unsigned long fpexc;
        int err = 0;
 
        __get_user_error(magic, &frame->magic, err);
@@ -228,33 +207,7 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
        if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
                return -EINVAL;
 
-       vfp_flush_hwstate(thread);
-
-       /*
-        * Copy the floating point registers. There can be unused
-        * registers see asm/hwcap.h for details.
-        */
-       err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs,
-                               sizeof(h->fpregs));
-       /*
-        * Copy the status and control register.
-        */
-       __get_user_error(h->fpscr, &frame->ufp.fpscr, err);
-
-       /*
-        * Sanitise and restore the exception registers.
-        */
-       __get_user_error(fpexc, &frame->ufp_exc.fpexc, err);
-       /* Ensure the VFP is enabled. */
-       fpexc |= FPEXC_EN;
-       /* Ensure FPINST2 is invalid and the exception flag is cleared. */
-       fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
-       h->fpexc = fpexc;
-
-       __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
-       __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
-
-       return err ? -EFAULT : 0;
+       return vfp_restore_user_hwstate(&frame->ufp, &frame->ufp_exc);
 }
 
 #endif
index 2cee7d1eb958bc39b19b31f18447fe4c6119419a..f6a4d32b0421a9dd35fa1ca2884e8980374a76a3 100644 (file)
@@ -349,7 +349,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                 * re-initialize the map in platform_smp_prepare_cpus() if
                 * present != possible (e.g. physical hotplug).
                 */
-               init_cpu_present(&cpu_possible_map);
+               init_cpu_present(cpu_possible_mask);
 
                /*
                 * Initialise the SCU if there are more than one CPU
@@ -510,10 +510,6 @@ static void ipi_cpu_stop(unsigned int cpu)
        local_fiq_disable();
        local_irq_disable();
 
-#ifdef CONFIG_HOTPLUG_CPU
-       platform_cpu_kill(cpu);
-#endif
-
        while (1)
                cpu_relax();
 }
@@ -576,16 +572,25 @@ void smp_send_reschedule(int cpu)
        smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static void smp_kill_cpus(cpumask_t *mask)
+{
+       unsigned int cpu;
+       for_each_cpu(cpu, mask)
+               platform_cpu_kill(cpu);
+}
+#else
+static void smp_kill_cpus(cpumask_t *mask) { }
+#endif
+
 void smp_send_stop(void)
 {
        unsigned long timeout;
+       struct cpumask mask;
 
-       if (num_online_cpus() > 1) {
-               cpumask_t mask = cpu_online_map;
-               cpu_clear(smp_processor_id(), mask);
-
-               smp_cross_call(&mask, IPI_CPU_STOP);
-       }
+       cpumask_copy(&mask, cpu_online_mask);
+       cpumask_clear_cpu(smp_processor_id(), &mask);
+       smp_cross_call(&mask, IPI_CPU_STOP);
 
        /* Wait up to one second for other CPUs to stop */
        timeout = USEC_PER_SEC;
@@ -594,6 +599,8 @@ void smp_send_stop(void)
 
        if (num_online_cpus() > 1)
                pr_warning("SMP: failed to stop secondary CPUs\n");
+
+       smp_kill_cpus(&mask);
 }
 
 /*
index 99ce5c955e39d94d24f50005b875459739ef6ce5..05774e5b1cbaf32488a142b4060a1adc452c8177 100644 (file)
@@ -1173,7 +1173,6 @@ void __init at91_add_device_serial(void)
                printk(KERN_INFO "AT91: No default serial console defined.\n");
 }
 #else
-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
 void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
 void __init at91_set_serial_console(unsigned portnr) {}
 void __init at91_add_device_serial(void) {}
index dd7f782b0b91731202c3d8e10f02597b7d89518c..104ca40d8d18908cb463e7ae1cd56790c926d971 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/clockchips.h>
+#include <linux/export.h>
 
 #include <asm/mach/time.h>
 
@@ -176,6 +177,7 @@ static struct clock_event_device clkevt = {
 };
 
 void __iomem *at91_st_base;
+EXPORT_SYMBOL_GPL(at91_st_base);
 
 void __init at91rm9200_ioremap_st(u32 addr)
 {
index 7e5651ee9f859f9689b76f07ca5bc834d3aa871a..5652dde4bbe291fd5723481ab9a978eb66bd5ec9 100644 (file)
@@ -598,6 +598,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
                else
                        cs_pin = spi1_standard_cs[devices[i].chip_select];
 
+               if (!gpio_is_valid(cs_pin))
+                       continue;
+
                if (devices[i].bus_num == 0)
                        enable_spi0 = 1;
                else
index 096da87dc00d41359fa793f6dd25f541516dd86c..4db961a93085566e80973e241f910223484ccd96 100644 (file)
@@ -415,6 +415,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
                else
                        cs_pin = spi1_standard_cs[devices[i].chip_select];
 
+               if (!gpio_is_valid(cs_pin))
+                       continue;
+
                if (devices[i].bus_num == 0)
                        enable_spi0 = 1;
                else
index 53688c46f95652f02fced22b9d1979cd6799df1b..fe99206de8802b549dc099b65f3daa62a53f5768 100644 (file)
@@ -72,7 +72,8 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
        /* Enable VBus control for UHP ports */
        for (i = 0; i < data->ports; i++) {
                if (gpio_is_valid(data->vbus_pin[i]))
-                       at91_set_gpio_output(data->vbus_pin[i], 0);
+                       at91_set_gpio_output(data->vbus_pin[i],
+                                            data->vbus_pin_active_low[i]);
        }
 
        /* Enable overcurrent notification */
@@ -671,6 +672,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
                else
                        cs_pin = spi1_standard_cs[devices[i].chip_select];
 
+               if (!gpio_is_valid(cs_pin))
+                       continue;
+
                if (devices[i].bus_num == 0)
                        enable_spi0 = 1;
                else
index 698479f1e197cf5725139bf135eb0c89f0d5d715..6b008aee1dffad648874e6318e397d7d640e2d31 100644 (file)
@@ -127,12 +127,13 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
        /* Enable VBus control for UHP ports */
        for (i = 0; i < data->ports; i++) {
                if (gpio_is_valid(data->vbus_pin[i]))
-                       at91_set_gpio_output(data->vbus_pin[i], 0);
+                       at91_set_gpio_output(data->vbus_pin[i],
+                                            data->vbus_pin_active_low[i]);
        }
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -188,7 +189,8 @@ void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data)
        /* Enable VBus control for UHP ports */
        for (i = 0; i < data->ports; i++) {
                if (gpio_is_valid(data->vbus_pin[i]))
-                       at91_set_gpio_output(data->vbus_pin[i], 0);
+                       at91_set_gpio_output(data->vbus_pin[i],
+                                            data->vbus_pin_active_low[i]);
        }
 
        usbh_ehci_data = *data;
@@ -785,6 +787,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
                else
                        cs_pin = spi1_standard_cs[devices[i].chip_select];
 
+               if (!gpio_is_valid(cs_pin))
+                       continue;
+
                if (devices[i].bus_num == 0)
                        enable_spi0 = 1;
                else
index eda72e83037dc7dd176c859e7f4ad874a9506a75..fe4ae22e8561bc9084b9d64870d063cfca88ed9a 100644 (file)
@@ -419,6 +419,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
                else
                        cs_pin = spi_standard_cs[devices[i].chip_select];
 
+               if (!gpio_is_valid(cs_pin))
+                       continue;
+
                /* enable chip-select pin */
                at91_set_gpio_output(cs_pin, 1);
 
index b6831eeb7b767c92d8abcc1343ef6b8b47656ca9..13c8cae6046253c0a24fcafaedef1b2797cbc122 100644 (file)
@@ -223,6 +223,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
+       CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
+       CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
        CLKDEV_CON_ID("pioA", &pioAB_clk),
        CLKDEV_CON_ID("pioB", &pioAB_clk),
        CLKDEV_CON_ID("pioC", &pioCD_clk),
index 11cbaa8946fe0e269877104aac08da9fe03818e9..b2e4fe21f346cf6217dfb78b5e8b3f6553e76fe6 100644 (file)
@@ -117,7 +117,7 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
 };
 
 #define EK_FLASH_BASE  AT91_CHIPSELECT_0
-#define EK_FLASH_SIZE  SZ_2M
+#define EK_FLASH_SIZE  SZ_8M
 
 static struct physmap_flash_data ek_flash_data = {
        .width          = 2,
index c3f9944628642050c34c0a5f31388854511921e4..065fed342424902bbe15aa67101fd524397eaa7b 100644 (file)
@@ -85,8 +85,6 @@ static struct resource dm9000_resource[] = {
                .flags  = IORESOURCE_MEM
        },
        [2] = {
-               .start  = AT91_PIN_PC11,
-               .end    = AT91_PIN_PC11,
                .flags  = IORESOURCE_IRQ
                        | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE,
        }
@@ -130,6 +128,8 @@ static struct sam9_smc_config __initdata dm9000_smc_config = {
 
 static void __init ek_add_device_dm9000(void)
 {
+       struct resource *r = &dm9000_resource[2];
+
        /* Configure chip-select 2 (DM9000) */
        sam9_smc_configure(0, 2, &dm9000_smc_config);
 
@@ -139,6 +139,7 @@ static void __init ek_add_device_dm9000(void)
        /* Configure Interrupt pin as input, no pull-up */
        at91_set_gpio_input(AT91_PIN_PC11, 0);
 
+       r->start = r->end = gpio_to_irq(AT91_PIN_PC11);
        platform_device_register(&dm9000_device);
 }
 #else
index 66f0ddf4b2ae416102626e02514a660576164d22..2ffe50f3a9e9e056a48879dd4c6a755cfa65f622 100644 (file)
@@ -74,6 +74,7 @@ static void __init ek_init_early(void)
 static struct at91_usbh_data __initdata ek_usbh_data = {
        .ports          = 2,
        .vbus_pin       = { AT91_PIN_PA24, AT91_PIN_PA21 },
+       .vbus_pin_active_low = {1, 1},
        .overcurrent_pin= {-EINVAL, -EINVAL},
 };
 
index e1bea73e6b30bb3e0c3c9f192a42c9eeb0b0da0c..c88e908ddd82e9de014b360448a194c568f27154 100644 (file)
@@ -71,6 +71,7 @@ static void __init ek_init_early(void)
 static struct at91_usbh_data __initdata ek_usbh_hs_data = {
        .ports          = 2,
        .vbus_pin       = {AT91_PIN_PD1, AT91_PIN_PD3},
+       .vbus_pin_active_low = {1, 1},
        .overcurrent_pin= {-EINVAL, -EINVAL},
 };
 
index a0f4d7424cdcf4cfbebbc0c81185fb615862e9b5..6b692824c9885555fffe031ead3bafcdf71d141d 100644 (file)
@@ -35,6 +35,7 @@
 #include "generic.h"
 
 void __iomem *at91_pmc_base;
+EXPORT_SYMBOL_GPL(at91_pmc_base);
 
 /*
  * There's a lot more which can be done with clocks, including cpufreq
index 36604782a78f0e52d4bed0d6af21c787dacf418f..ea2c57a86ca6ebf389aaa406bffeb5441e65a067 100644 (file)
@@ -25,7 +25,7 @@ extern void __iomem *at91_pmc_base;
 #define at91_pmc_write(field, value) \
        __raw_writel(value, at91_pmc_base + field)
 #else
-.extern at91_aic_base
+.extern at91_pmc_base
 #endif
 
 #define        AT91_PMC_SCER           0x00                    /* System Clock Enable Register */
index 544a5d5ce4165e9117f8a7ab1cdcbaea79b2df22..49a821192c652c959321b834953d7f3ce2073452 100644 (file)
@@ -86,14 +86,15 @@ extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *d
 extern void __init at91_add_device_eth(struct macb_platform_data *data);
 
  /* USB Host */
+#define AT91_MAX_USBH_PORTS    3
 struct at91_usbh_data {
-       u8              ports;          /* number of ports on root hub */
-       int             vbus_pin[2];    /* port power-control pin */
-       u8              vbus_pin_active_low[2];
+       int             vbus_pin[AT91_MAX_USBH_PORTS];  /* port power-control pin */
+       int             overcurrent_pin[AT91_MAX_USBH_PORTS];
+       u8              ports;                          /* number of ports on root hub */
        u8              overcurrent_supported;
-       int             overcurrent_pin[2];
-       u8              overcurrent_status[2];
-       u8              overcurrent_changed[2];
+       u8              vbus_pin_active_low[AT91_MAX_USBH_PORTS];
+       u8              overcurrent_status[AT91_MAX_USBH_PORTS];
+       u8              overcurrent_changed[AT91_MAX_USBH_PORTS];
 };
 extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
diff --git a/arch/arm/mach-at91/include/mach/io.h b/arch/arm/mach-at91/include/mach/io.h
new file mode 100644 (file)
index 0000000..2d9ca04
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-at91/include/mach/io.h
+ *
+ *  Copyright (C) 2003 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT         0xFFFFFFFF
+#define __io(a)                        __typesafe_io(a)
+
+#endif
index 97cc04dc807302d635e9fe56176d34e0d9210c4f..f44a2e7272e33f8e8568c4bc597db0bc0b38f5b5 100644 (file)
@@ -54,6 +54,7 @@ void __init at91_init_interrupts(unsigned int *priority)
 }
 
 void __iomem *at91_ramc_base[2];
+EXPORT_SYMBOL_GPL(at91_ramc_base);
 
 void __init at91_ioremap_ramc(int id, u32 addr, u32 size)
 {
@@ -292,6 +293,7 @@ void __init at91_ioremap_rstc(u32 base_addr)
 }
 
 void __iomem *at91_matrix_base;
+EXPORT_SYMBOL_GPL(at91_matrix_base);
 
 void __init at91_ioremap_matrix(u32 base_addr)
 {
index 22e4e0a28ad1eae0e549f43e47e548b9a36945dd..adbfb1994582ee1352a511501279f5b58c378bfc 100644 (file)
@@ -52,8 +52,8 @@
 #include <mach/csp/chipcHw_inline.h>
 #include <mach/csp/tmrHw_reg.h>
 
-static AMBA_APB_DEVICE(uartA, "uarta", MM_ADDR_IO_UARTA, { IRQ_UARTA }, NULL);
-static AMBA_APB_DEVICE(uartB, "uartb", MM_ADDR_IO_UARTB, { IRQ_UARTB }, NULL);
+static AMBA_APB_DEVICE(uartA, "uartA", 0, MM_ADDR_IO_UARTA, {IRQ_UARTA}, NULL);
+static AMBA_APB_DEVICE(uartB, "uartB", 0, MM_ADDR_IO_UARTB, {IRQ_UARTB}, NULL);
 
 static struct clk pll1_clk = {
        .name = "PLL1",
index 0491ceef1cda8a77bbaf60409416d906fc701620..e81c35f936b595e5d332e9cdcdd1229d2ac21670 100644 (file)
@@ -368,6 +368,7 @@ comment "Flattened Device Tree based board for EXYNOS SoCs"
 
 config MACH_EXYNOS4_DT
        bool "Samsung Exynos4 Machine using device tree"
+       depends on ARCH_EXYNOS4
        select CPU_EXYNOS4210
        select USE_OF
        select ARM_AMBA
@@ -380,6 +381,7 @@ config MACH_EXYNOS4_DT
 
 config MACH_EXYNOS5_DT
        bool "SAMSUNG EXYNOS5 Machine using device tree"
+       depends on ARCH_EXYNOS5
        select SOC_EXYNOS5250
        select USE_OF
        select ARM_AMBA
index df54c2a922252826b6b2f837134da025ca2a6994..6efd1e5919fdebcd389e61cf48e25b1967a75bb1 100644 (file)
@@ -497,25 +497,25 @@ static struct clk exynos4_init_clocks_off[] = {
                .ctrlbit        = (1 << 3),
        }, {
                .name           = "hsmmc",
-               .devname        = "s3c-sdhci.0",
+               .devname        = "exynos4-sdhci.0",
                .parent         = &exynos4_clk_aclk_133.clk,
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 5),
        }, {
                .name           = "hsmmc",
-               .devname        = "s3c-sdhci.1",
+               .devname        = "exynos4-sdhci.1",
                .parent         = &exynos4_clk_aclk_133.clk,
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 6),
        }, {
                .name           = "hsmmc",
-               .devname        = "s3c-sdhci.2",
+               .devname        = "exynos4-sdhci.2",
                .parent         = &exynos4_clk_aclk_133.clk,
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 7),
        }, {
                .name           = "hsmmc",
-               .devname        = "s3c-sdhci.3",
+               .devname        = "exynos4-sdhci.3",
                .parent         = &exynos4_clk_aclk_133.clk,
                .enable         = exynos4_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 8),
@@ -1202,7 +1202,7 @@ static struct clksrc_clk exynos4_clk_sclk_uart3 = {
 static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
        .clk    = {
                .name           = "sclk_mmc",
-               .devname        = "s3c-sdhci.0",
+               .devname        = "exynos4-sdhci.0",
                .parent         = &exynos4_clk_dout_mmc0.clk,
                .enable         = exynos4_clksrc_mask_fsys_ctrl,
                .ctrlbit        = (1 << 0),
@@ -1213,7 +1213,7 @@ static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
 static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
        .clk    = {
                .name           = "sclk_mmc",
-               .devname        = "s3c-sdhci.1",
+               .devname        = "exynos4-sdhci.1",
                .parent         = &exynos4_clk_dout_mmc1.clk,
                .enable         = exynos4_clksrc_mask_fsys_ctrl,
                .ctrlbit        = (1 << 4),
@@ -1224,7 +1224,7 @@ static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
 static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
        .clk    = {
                .name           = "sclk_mmc",
-               .devname        = "s3c-sdhci.2",
+               .devname        = "exynos4-sdhci.2",
                .parent         = &exynos4_clk_dout_mmc2.clk,
                .enable         = exynos4_clksrc_mask_fsys_ctrl,
                .ctrlbit        = (1 << 8),
@@ -1235,7 +1235,7 @@ static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
 static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
        .clk    = {
                .name           = "sclk_mmc",
-               .devname        = "s3c-sdhci.3",
+               .devname        = "exynos4-sdhci.3",
                .parent         = &exynos4_clk_dout_mmc3.clk,
                .enable         = exynos4_clksrc_mask_fsys_ctrl,
                .ctrlbit        = (1 << 12),
@@ -1340,10 +1340,10 @@ static struct clk_lookup exynos4_clk_lookup[] = {
        CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos4_clk_sclk_uart1.clk),
        CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos4_clk_sclk_uart2.clk),
        CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos4_clk_sclk_uart3.clk),
-       CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
-       CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
-       CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
-       CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
+       CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
+       CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
+       CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
+       CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
        CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
        CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
        CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
index d013982d0f8e1bc9e49a80824069c7214dec36be..5cd7a8b8868ce0fbb7e48a1a393e020d17cdcd88 100644 (file)
@@ -455,25 +455,25 @@ static struct clk exynos5_init_clocks_off[] = {
                .ctrlbit        = (1 << 20),
        }, {
                .name           = "hsmmc",
-               .devname        = "s3c-sdhci.0",
+               .devname        = "exynos4-sdhci.0",
                .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 12),
        }, {
                .name           = "hsmmc",
-               .devname        = "s3c-sdhci.1",
+               .devname        = "exynos4-sdhci.1",
                .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 13),
        }, {
                .name           = "hsmmc",
-               .devname        = "s3c-sdhci.2",
+               .devname        = "exynos4-sdhci.2",
                .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 14),
        }, {
                .name           = "hsmmc",
-               .devname        = "s3c-sdhci.3",
+               .devname        = "exynos4-sdhci.3",
                .parent         = &exynos5_clk_aclk_200.clk,
                .enable         = exynos5_clk_ip_fsys_ctrl,
                .ctrlbit        = (1 << 15),
@@ -813,7 +813,7 @@ static struct clksrc_clk exynos5_clk_sclk_uart3 = {
 static struct clksrc_clk exynos5_clk_sclk_mmc0 = {
        .clk    = {
                .name           = "sclk_mmc",
-               .devname        = "s3c-sdhci.0",
+               .devname        = "exynos4-sdhci.0",
                .parent         = &exynos5_clk_dout_mmc0.clk,
                .enable         = exynos5_clksrc_mask_fsys_ctrl,
                .ctrlbit        = (1 << 0),
@@ -824,7 +824,7 @@ static struct clksrc_clk exynos5_clk_sclk_mmc0 = {
 static struct clksrc_clk exynos5_clk_sclk_mmc1 = {
        .clk    = {
                .name           = "sclk_mmc",
-               .devname        = "s3c-sdhci.1",
+               .devname        = "exynos4-sdhci.1",
                .parent         = &exynos5_clk_dout_mmc1.clk,
                .enable         = exynos5_clksrc_mask_fsys_ctrl,
                .ctrlbit        = (1 << 4),
@@ -835,7 +835,7 @@ static struct clksrc_clk exynos5_clk_sclk_mmc1 = {
 static struct clksrc_clk exynos5_clk_sclk_mmc2 = {
        .clk    = {
                .name           = "sclk_mmc",
-               .devname        = "s3c-sdhci.2",
+               .devname        = "exynos4-sdhci.2",
                .parent         = &exynos5_clk_dout_mmc2.clk,
                .enable         = exynos5_clksrc_mask_fsys_ctrl,
                .ctrlbit        = (1 << 8),
@@ -846,7 +846,7 @@ static struct clksrc_clk exynos5_clk_sclk_mmc2 = {
 static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
        .clk    = {
                .name           = "sclk_mmc",
-               .devname        = "s3c-sdhci.3",
+               .devname        = "exynos4-sdhci.3",
                .parent         = &exynos5_clk_dout_mmc3.clk,
                .enable         = exynos5_clksrc_mask_fsys_ctrl,
                .ctrlbit        = (1 << 12),
@@ -990,10 +990,10 @@ static struct clk_lookup exynos5_clk_lookup[] = {
        CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos5_clk_sclk_uart1.clk),
        CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos5_clk_sclk_uart2.clk),
        CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos5_clk_sclk_uart3.clk),
-       CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk),
-       CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
-       CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
-       CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
+       CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk),
+       CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
+       CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
+       CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
        CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
        CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
        CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
index e6cc50e94a58f86cff1e5d60cc1fc9fd5d1eebeb..5ccd6e80a607fec8750409d6d5731dfa92f2a73e 100644 (file)
@@ -326,6 +326,11 @@ static void __init exynos4_map_io(void)
        s3c_fimc_setname(2, "exynos4-fimc");
        s3c_fimc_setname(3, "exynos4-fimc");
 
+       s3c_sdhci_setname(0, "exynos4-sdhci");
+       s3c_sdhci_setname(1, "exynos4-sdhci");
+       s3c_sdhci_setname(2, "exynos4-sdhci");
+       s3c_sdhci_setname(3, "exynos4-sdhci");
+
        /* The I2C bus controllers are directly compatible with s3c2440 */
        s3c_i2c0_setname("s3c2440-i2c");
        s3c_i2c1_setname("s3c2440-i2c");
@@ -344,6 +349,11 @@ static void __init exynos5_map_io(void)
        s3c_device_i2c0.resource[1].start = EXYNOS5_IRQ_IIC;
        s3c_device_i2c0.resource[1].end   = EXYNOS5_IRQ_IIC;
 
+       s3c_sdhci_setname(0, "exynos4-sdhci");
+       s3c_sdhci_setname(1, "exynos4-sdhci");
+       s3c_sdhci_setname(2, "exynos4-sdhci");
+       s3c_sdhci_setname(3, "exynos4-sdhci");
+
        /* The I2C bus controllers are directly compatible with s3c2440 */
        s3c_i2c0_setname("s3c2440-i2c");
        s3c_i2c1_setname("s3c2440-i2c");
@@ -537,7 +547,9 @@ void __init exynos5_init_irq(void)
 {
        int irq;
 
-       gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+#ifdef CONFIG_OF
+       of_irq_init(exynos4_dt_irq_match);
+#endif
 
        for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) {
                combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
@@ -583,10 +595,11 @@ core_initcall(exynos_core_init);
 #ifdef CONFIG_CACHE_L2X0
 static int __init exynos4_l2x0_cache_init(void)
 {
+       int ret;
+
        if (soc_is_exynos5250())
                return 0;
 
-       int ret;
        ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
        if (!ret) {
                l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
index b025db4bf602380e465402381a270668ece4b41f..79035018fb746da2a5c0a284bbc2b229d3cebbe9 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/mmc/dw_mmc.h>
 
 #include <plat/devs.h>
@@ -33,16 +34,8 @@ static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data)
 }
 
 static struct resource exynos4_dwmci_resource[] = {
-       [0] = {
-               .start  = EXYNOS4_PA_DWMCI,
-               .end    = EXYNOS4_PA_DWMCI + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_DWMCI,
-               .end    = IRQ_DWMCI,
-               .flags  = IORESOURCE_IRQ,
-       }
+       [0] = DEFINE_RES_MEM(EXYNOS4_PA_DWMCI, SZ_4K),
+       [1] = DEFINE_RES_IRQ(EXYNOS4_IRQ_DWMCI),
 };
 
 static struct dw_mci_board exynos4_dwci_pdata = {
index 3983abee4264fb629b0dc16c083307703e71085b..69aaa45032057d8409e890b90ff6a6c1bd0b106c 100644 (file)
@@ -35,8 +35,6 @@
 #include <mach/irqs.h>
 #include <mach/dma.h>
 
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
 static u8 exynos4210_pdma0_peri[] = {
        DMACH_PCM0_RX,
        DMACH_PCM0_TX,
index 6c857ff0b5d84670f65287230801a7bf2cf5d974..e0c86ea475e7bccd6f1e7b598fe6da69b78abc0f 100644 (file)
         */
 
        .macro addruart, rp, rv, tmp
-               mov     \rp, #0x10000000
-               ldr     \rp, [\rp, #0x0]
-               and     \rp, \rp, #0xf00000
-               teq     \rp, #0x500000          @@ EXYNOS5
+               mrc     p15, 0, \tmp, c0, c0, 0
+               and     \tmp, \tmp, #0xf0
+               teq     \tmp, #0xf0             @@ A15
                ldreq   \rp, =EXYNOS5_PA_UART
                movne   \rp, #EXYNOS4_PA_UART   @@ EXYNOS4
                ldr     \rv, =S3C_VA_UART
index 9bee8535d9e0aa994960de244002b198975a8709..591e78521a9f11f6de5114c8f717933efe4c9fd7 100644 (file)
 #define IRQ_MFC                                EXYNOS4_IRQ_MFC
 #define IRQ_SDO                                EXYNOS4_IRQ_SDO
 
+#define IRQ_I2S0                       EXYNOS4_IRQ_I2S0
+
 #define IRQ_ADC                                EXYNOS4_IRQ_ADC0
 #define IRQ_TC                         EXYNOS4_IRQ_PEN0
 
index 024d38ff17183fed96447aebcbeb27f1cc04fb62..6e6d11ff352a30b131db307b8d2910c9c0c6282b 100644 (file)
 #define EXYNOS4_PA_MDMA1               0x12840000
 #define EXYNOS4_PA_PDMA0               0x12680000
 #define EXYNOS4_PA_PDMA1               0x12690000
+#define EXYNOS5_PA_MDMA0               0x10800000
+#define EXYNOS5_PA_MDMA1               0x11C10000
+#define EXYNOS5_PA_PDMA0               0x121A0000
+#define EXYNOS5_PA_PDMA1               0x121B0000
 
 #define EXYNOS4_PA_SYSMMU_MDMA         0x10A40000
 #define EXYNOS4_PA_SYSMMU_SSS          0x10A50000
index e141c1fd68d84ce00a4dcca450c2e904867709f7..d9578a58ae7f573b35d7065609ae4d090884acbf 100644 (file)
 
 /* For EXYNOS5250 */
 
+#define EXYNOS5_APLL_LOCK                      EXYNOS_CLKREG(0x00000)
 #define EXYNOS5_APLL_CON0                      EXYNOS_CLKREG(0x00100)
 #define EXYNOS5_CLKSRC_CPU                     EXYNOS_CLKREG(0x00200)
+#define EXYNOS5_CLKMUX_STATCPU                 EXYNOS_CLKREG(0x00400)
 #define EXYNOS5_CLKDIV_CPU0                    EXYNOS_CLKREG(0x00500)
+#define EXYNOS5_CLKDIV_CPU1                    EXYNOS_CLKREG(0x00504)
+#define EXYNOS5_CLKDIV_STATCPU0                        EXYNOS_CLKREG(0x00600)
+#define EXYNOS5_CLKDIV_STATCPU1                        EXYNOS_CLKREG(0x00604)
+
 #define EXYNOS5_MPLL_CON0                      EXYNOS_CLKREG(0x04100)
 #define EXYNOS5_CLKSRC_CORE1                   EXYNOS_CLKREG(0x04204)
 
index 493f4f365ddfe65a8ceab62908bc2ff6725a1ef1..2979995d5a6ad8ba92cf7e142a10e69676a28a8c 100644 (file)
@@ -20,9 +20,24 @@ volatile u8 *uart_base;
 
 #include <plat/uncompress.h>
 
+static unsigned int __raw_readl(unsigned int ptr)
+{
+       return *((volatile unsigned int *)ptr);
+}
+
 static void arch_detect_cpu(void)
 {
-       if (machine_is_smdk5250())
+       u32 chip_id = __raw_readl(EXYNOS_PA_CHIPID);
+
+       /*
+        * product_id is bits 31:12
+        *    bits 23:20 describe the exynosX family
+        *
+        */
+       chip_id >>= 20;
+       chip_id &= 0xf;
+
+       if (chip_id == 0x5)
                uart_base = (volatile u8 *)EXYNOS5_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT);
        else
                uart_base = (volatile u8 *)EXYNOS4_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT);
index 0d26f50081ad9e44e0d5cd3a9e962c391b3382f4..4711c8920e37830d7bda8cb32ee03ed1ae70730a 100644 (file)
@@ -45,7 +45,7 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
                                "exynos4210-uart.3", NULL),
        OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
        OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
-       OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.2", NULL),
+       OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
        {},
 };
 
index b3982c867c9c5e9243c505d41b9914b69c130b30..ed90aef404c3175259e4a4ba576e60a6bb018a3f 100644 (file)
@@ -112,6 +112,7 @@ static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
        .host_caps              = (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
                                MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                                MMC_CAP_ERASE),
+       .host_caps2             = MMC_CAP2_BROKEN_VOLTAGE,
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
        .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
@@ -307,49 +308,7 @@ static struct i2c_board_info i2c1_devs[] __initdata = {
 };
 
 /* TSP */
-static u8 mxt_init_vals[] = {
-       /* MXT_GEN_COMMAND(6) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* MXT_GEN_POWER(7) */
-       0x20, 0xff, 0x32,
-       /* MXT_GEN_ACQUIRE(8) */
-       0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-       /* MXT_TOUCH_MULTI(9) */
-       0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
-       0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00,
-       /* MXT_TOUCH_KEYARRAY(15) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-       0x00,
-       /* MXT_SPT_GPIOPWM(19) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* MXT_PROCI_GRIPFACE(20) */
-       0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-       0x0f, 0x0a,
-       /* MXT_PROCG_NOISE(22) */
-       0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-       0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-       /* MXT_TOUCH_PROXIMITY(23) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00,
-       /* MXT_PROCI_ONETOUCH(24) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* MXT_SPT_SELFTEST(25) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       /* MXT_PROCI_TWOTOUCH(27) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       /* MXT_SPT_CTECONFIG(28) */
-       0x00, 0x00, 0x02, 0x08, 0x10, 0x00,
-};
-
 static struct mxt_platform_data mxt_platform_data = {
-       .config                 = mxt_init_vals,
-       .config_length          = ARRAY_SIZE(mxt_init_vals),
-
        .x_line                 = 18,
        .y_line                 = 11,
        .x_size                 = 1024,
@@ -571,7 +530,7 @@ static struct regulator_init_data __initdata max8997_ldo7_data = {
 
 static struct regulator_init_data __initdata max8997_ldo8_data = {
        .constraints    = {
-               .name           = "VUSB/VDAC_3.3V_C210",
+               .name           = "VUSB+VDAC_3.3V_C210",
                .min_uV         = 3300000,
                .max_uV         = 3300000,
                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -1347,6 +1306,7 @@ static struct platform_device *nuri_devices[] __initdata = {
 
 static void __init nuri_map_io(void)
 {
+       clk_xusbxti.rate = 24000000;
        exynos_init_io(NULL, 0);
        s3c24xx_init_clocks(24000000);
        s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
@@ -1379,7 +1339,6 @@ static void __init nuri_machine_init(void)
        nuri_camera_init();
 
        nuri_ehci_init();
-       clk_xusbxti.rate = 24000000;
 
        /* Last */
        platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
index 6bb9dbdd73fdde842bcad0cb75f4713316c4a760..cb2b027f09a603800477a31bfeb765b27f829942 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
+#include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/iic.h>
@@ -746,6 +747,7 @@ static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
        .max_width              = 8,
        .host_caps              = (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
                                MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+       .host_caps2             = MMC_CAP2_BROKEN_VOLTAGE,
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
        .clk_type               = S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
@@ -1057,6 +1059,7 @@ static struct platform_device *universal_devices[] __initdata = {
 
 static void __init universal_map_io(void)
 {
+       clk_xusbxti.rate = 24000000;
        exynos_init_io(NULL, 0);
        s3c24xx_init_clocks(24000000);
        s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
index b9a95ed75553a73e4fcea686bf8f38a1e3216081..98e04f5a87ddd2320c9a1392a96ab05347a114f4 100644 (file)
@@ -662,6 +662,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK(NULL, "dma", dma_clk)
        _REGISTER_CLOCK(NULL, "rtic", rtic_clk)
        _REGISTER_CLOCK(NULL, "brom", brom_clk)
+       _REGISTER_CLOCK(NULL, "emma", emma_clk)
        _REGISTER_CLOCK("m2m-emmaprp.0", NULL, emma_clk)
        _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
        _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
index 1e279af656ad034dc46abf13c836077f0c754eca..e56c1a83eee3eafa38fdf1fbd02434484d5124de 100644 (file)
@@ -483,7 +483,7 @@ static struct clk_lookup lookups[] = {
        _REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
        _REGISTER_CLOCK(NULL, "max", max_clk)
        _REGISTER_CLOCK(NULL, "audmux", audmux_clk)
-       _REGISTER_CLOCK(NULL, "csi", csi_clk)
+       _REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
        _REGISTER_CLOCK(NULL, "iim", iim_clk)
        _REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk)
        _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
index 861ceb8232d60ca468cb361a749e34574bdb7961..ed38d03c61f22296acb782e7e4cc9c8dfde20344 100644 (file)
@@ -35,7 +35,7 @@ static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = {
 static int __init imx27_avic_add_irq_domain(struct device_node *np,
                                struct device_node *interrupt_parent)
 {
-       irq_domain_add_simple(np, 0);
+       irq_domain_add_legacy(np, 64, 0, 0, &irq_domain_simple_ops, NULL);
        return 0;
 }
 
@@ -44,7 +44,9 @@ static int __init imx27_gpio_add_irq_domain(struct device_node *np,
 {
        static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
 
-       irq_domain_add_simple(np, gpio_irq_base);
+       gpio_irq_base -= 32;
+       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops,
+                               NULL);
 
        return 0;
 }
index 27bc27e6ea4124a7163f34600c6bf8dacfbbd2c6..c650145d1646e6dbdfbe65ec4c96c7c56d611cd5 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -479,6 +481,11 @@ static struct platform_device *devices[] __initdata = {
        &armadillo5x0_smc911x_device,
 };
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+       REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
 /*
  * Perform board specific initializations
  */
@@ -489,6 +496,8 @@ static void __init armadillo5x0_init(void)
        mxc_iomux_setup_multiple_pins(armadillo5x0_pins,
                        ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0");
 
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
        platform_add_devices(devices, ARRAY_SIZE(devices));
        imx_add_gpio_keys(&armadillo5x0_button_data);
        imx31_add_imx_i2c1(NULL);
index fc78e8071cd178de28ada44104b9faf182b5bdf9..15a26e90826032d987775a16223e5e49e023b864 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/serial_8250.h>
 #include <linux/smsc911x.h>
 #include <linux/types.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
@@ -166,6 +168,11 @@ static struct platform_device kzm_smsc9118_device = {
                          },
 };
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+       REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
 static int __init kzm_init_smsc9118(void)
 {
        /*
@@ -175,6 +182,8 @@ static int __init kzm_init_smsc9118(void)
        gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2), "smsc9118-int");
        gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2));
 
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
        return platform_device_register(&kzm_smsc9118_device);
 }
 #else
index 02401bbd6d53e7ef014507f2029212fb74f34b1d..83714b0cc290a25202e1e5122f3490ea426339c7 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/mfd/mc13783.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -242,6 +244,11 @@ static struct platform_device *devices[] __initdata = {
 static int mx31lilly_baseboard;
 core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+       REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
 static void __init mx31lilly_board_init(void)
 {
        imx31_soc_init();
@@ -280,6 +287,8 @@ static void __init mx31lilly_board_init(void)
        imx31_add_spi_imx1(&spi1_pdata);
        spi_register_board_info(&mc13783_dev, 1);
 
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        /* USB */
index ef80751712e70ca0165c7fa817f41f1f92c39589..0abef5f13df5089798401a91c1d4b3d0b8696844 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/usb/ulpi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -226,6 +228,11 @@ void __init mx31lite_map_io(void)
 static int mx31lite_baseboard;
 core_param(mx31lite_baseboard, mx31lite_baseboard, int, 0444);
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+       REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
 static void __init mx31lite_init(void)
 {
        int ret;
@@ -259,6 +266,8 @@ static void __init mx31lite_init(void)
        if (usbh2_pdata.otg)
                imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
        /* SMSC9117 IRQ pin */
        ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq");
        if (ret)
index e14291d89e4fda86ec6c885a902e467ad53ad401..6ae51c6b95b7c02992d27d6f053b9fb289a92b36 100644 (file)
@@ -97,7 +97,7 @@ static struct i2c_board_info __initdata i2c_devices_3ds[] = {
 static int lcd_power_gpio = -ENXIO;
 
 static int mc9s08dz60_gpiochip_match(struct gpio_chip *chip,
-                                                    void *data)
+                                                    const void *data)
 {
        return !strcmp(chip->label, data);
 }
index 753f4fc9ec04ae1ddf908a7ba9b124d7f27b4379..05641980dc5e7c86ede296ef01129be70fea653b 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/smsc911x.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -214,6 +216,11 @@ static int weim_cs_config(void)
        return 0;
 }
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+       REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
 void __init imx53_ard_common_init(void)
 {
        mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
@@ -232,6 +239,7 @@ static void __init mx53_ard_board_init(void)
 
        imx53_ard_common_init();
        mx53_ard_io_init();
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
index 05250aed61fbbc7f73f9e7b1c5b4bca00000f6fd..e10f3914fcfe6b1d2c59f9296d373805b4740901 100644 (file)
@@ -35,7 +35,7 @@ static void imx5_idle(void)
        }
        clk_enable(gpc_dvfs_clk);
        mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-       if (tzic_enable_wake() != 0)
+       if (!tzic_enable_wake())
                cpu_do_idle();
        clk_disable(gpc_dvfs_clk);
 }
index 3698a370d6360051f00cb02bbfc62cb861568e6d..26aac363a06405f865e76ea8c0db6324af8d85aa 100644 (file)
@@ -86,9 +86,6 @@ static void __init halibut_init(void)
 static void __init halibut_fixup(struct tag *tags, char **cmdline,
                                 struct meminfo *mi)
 {
-       mi->nr_banks=1;
-       mi->bank[0].start = PHYS_OFFSET;
-       mi->bank[0].size = (101*1024*1024);
 }
 
 static void __init halibut_map_io(void)
index 962e71169750a0243225b52c1ddda062779eb5e0..fb3496a52ef4c08921de04e75e4682ad00e796a2 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
 
@@ -49,10 +50,22 @@ static void __init msm8x60_map_io(void)
        msm_map_msm8x60_io();
 }
 
+#ifdef CONFIG_OF
+static struct of_device_id msm_dt_gic_match[] __initdata = {
+       { .compatible = "qcom,msm-8660-qgic", .data = gic_of_init },
+       {}
+};
+#endif
+
 static void __init msm8x60_init_irq(void)
 {
-       gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
-                (void *)MSM_QGIC_CPU_BASE);
+       if (!of_have_populated_dt())
+               gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+                        (void *)MSM_QGIC_CPU_BASE);
+#ifdef CONFIG_OF
+       else
+               of_irq_init(msm_dt_gic_match);
+#endif
 
        /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
        writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
@@ -73,16 +86,8 @@ static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = {
        {}
 };
 
-static struct of_device_id msm_dt_gic_match[] __initdata = {
-       { .compatible = "qcom,msm-8660-qgic", },
-       {}
-};
-
 static void __init msm8x60_dt_init(void)
 {
-       irq_domain_generate_simple(msm_dt_gic_match, MSM8X60_QGIC_DIST_PHYS,
-                               GIC_SPI_START);
-
        if (of_machine_is_compatible("qcom,msm8660-surf")) {
                printk(KERN_INFO "Init surf UART registers\n");
                msm8x60_init_uart12dm();
index 25105c1027fe44c1862b94605ca8d6fd520ff3c1..89bf6b426699863d8230d9fcdf2b9d66bfa3cdc3 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/io.h>
 #include <asm/mach-types.h>
+#include <asm/system_info.h>
 
 #include <mach/msm_fb.h>
 #include <mach/vreg.h>
index 5414f76ec0a948578b6c2c28c2058acbb2ccf133..d4060a37e23d39776456974e97b361ac6522b1e5 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/clkdev.h>
 
+#include <asm/system_info.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 169a8400745659171efcfcefa6a4e55b9dbef060..c14011fe832d2fa8f014c0c5a7805204e5949387 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef __ASM_ARCH_MSM_UNCOMPRESS_H
 #define __ASM_ARCH_MSM_UNCOMPRESS_H
 
+#include <asm/barrier.h>
 #include <asm/processor.h>
 #include <mach/msm_iomap.h>
 
index 67e701c7f183746c923d722163ec3c9dfc94cecf..9980dc736e7bb690c31f93560efcdd2925d74ffe 100644 (file)
@@ -121,7 +121,7 @@ int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)
  * and unknown state. This function should be called early to
  * wait on the ARM9.
  */
-void __init proc_comm_boot_wait(void)
+void __devinit proc_comm_boot_wait(void)
 {
        void __iomem *base = MSM_SHARED_RAM_BASE;
  
index 0c56a5aaf588f18c9b2e311620752137c2e83481..c56df9e932aec303aca92252040fe2d9344b5391 100644 (file)
@@ -203,15 +203,9 @@ static ssize_t debug_read(struct file *file, char __user *buf,
        return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
 }
 
-static int debug_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static const struct file_operations debug_ops = {
        .read = debug_read,
-       .open = debug_open,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
diff --git a/arch/arm/mach-omap1/include/mach/io.h b/arch/arm/mach-omap1/include/mach/io.h
new file mode 100644 (file)
index 0000000..ce4f800
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * arch/arm/mach-omap1/include/mach/io.h
+ *
+ * IO definitions for TI OMAP processors and boards
+ *
+ * Copied from arch/arm/mach-sa1100/include/mach/io.h
+ * Copyright (C) 1997-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Modifications:
+ *  06-12-1997 RMK     Created.
+ *  07-04-1999 RMK     Major cleanup
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a)                __typesafe_io(a)
+
+#endif
index 087dba0df47e305fd059b97885c68f696d4c8ea5..e9cc52d4cb2869964b933b8a4a74ee844bb003d8 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/io.h>
 #include <linux/spinlock.h>
 
+#include <mach/hardware.h>
 
 #include <plat/mux.h>
 
index 6e90665a7c47f6d4ed929b57dd6a79d9c7ed4f2a..fb202af01d0dc2fbb1f9622d220b90335e939de8 100644 (file)
@@ -47,9 +47,9 @@ static int omap1_dm_timer_set_src(struct platform_device *pdev,
        int n = (pdev->id - 1) << 1;
        u32 l;
 
-       l = __raw_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+       l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
        l |= source << n;
-       __raw_writel(l, MOD_CONF_CTRL_1);
+       omap_writel(l, MOD_CONF_CTRL_1);
 
        return 0;
 }
index a39fc4bbd2b8ffb9cb8bb06c1c91f1c40e120333..130ab00c09a2b00751f7c3e90dfa2ffb8eac7882 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/otg.h>
 #include <linux/spi/spi.h>
 #include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
 #include <linux/gpio_keys.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -560,7 +561,7 @@ static struct regulator_init_data sdp4430_vusim = {
        },
 };
 
-static struct twl4030_codec_data twl6040_codec = {
+static struct twl6040_codec_data twl6040_codec = {
        /* single-step ramp for headset and handsfree */
        .hs_left_step   = 0x0f,
        .hs_right_step  = 0x0f,
@@ -568,7 +569,7 @@ static struct twl4030_codec_data twl6040_codec = {
        .hf_right_step  = 0x1d,
 };
 
-static struct twl4030_vibra_data twl6040_vibra = {
+static struct twl6040_vibra_data twl6040_vibra = {
        .vibldrv_res = 8,
        .vibrdrv_res = 3,
        .viblmotor_res = 10,
@@ -577,16 +578,14 @@ static struct twl4030_vibra_data twl6040_vibra = {
        .vddvibr_uV = 0,        /* fixed volt supply - VBAT */
 };
 
-static struct twl4030_audio_data twl6040_audio = {
+static struct twl6040_platform_data twl6040_data = {
        .codec          = &twl6040_codec,
        .vibra          = &twl6040_vibra,
        .audpwron_gpio  = 127,
-       .naudint_irq    = OMAP44XX_IRQ_SYS_2N,
        .irq_base       = TWL6040_CODEC_IRQ_BASE,
 };
 
 static struct twl4030_platform_data sdp4430_twldata = {
-       .audio          = &twl6040_audio,
        /* Regulators */
        .vusim          = &sdp4430_vusim,
        .vaux1          = &sdp4430_vaux1,
@@ -617,7 +616,8 @@ static int __init omap4_i2c_init(void)
                        TWL_COMMON_REGULATOR_VCXIO |
                        TWL_COMMON_REGULATOR_VUSB |
                        TWL_COMMON_REGULATOR_CLK32KG);
-       omap4_pmic_init("twl6030", &sdp4430_twldata);
+       omap4_pmic_init("twl6030", &sdp4430_twldata,
+                       &twl6040_data, OMAP44XX_IRQ_SYS_2N);
        omap_register_i2c_bus(2, 400, NULL, 0);
        omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
                                ARRAY_SIZE(sdp4430_i2c_3_boardinfo));
index 41b0a2fe0b04b2de9d2953e3d938426068bbb0c5..909a8b91b564278d5d481845d8ad5ba249f69d0e 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/i2c/at24.h>
 #include <linux/i2c/twl.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
 
@@ -81,8 +82,23 @@ static struct omap_smsc911x_platform_data sb_t35_smsc911x_cfg = {
        .flags          = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
 };
 
+static struct regulator_consumer_supply cm_t35_smsc911x_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
+static struct regulator_consumer_supply sb_t35_smsc911x_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.1"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.1"),
+};
+
 static void __init cm_t35_init_ethernet(void)
 {
+       regulator_register_fixed(0, cm_t35_smsc911x_supplies,
+                                ARRAY_SIZE(cm_t35_smsc911x_supplies));
+       regulator_register_fixed(1, sb_t35_smsc911x_supplies,
+                                ARRAY_SIZE(sb_t35_smsc911x_supplies));
+
        gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
        gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
 }
index 74e1687b51706317672694d80ac79aa92f0c416f..098d183a008655c6dd66895346033d76da74ecbe 100644 (file)
@@ -137,7 +137,7 @@ static struct twl4030_platform_data sdp4430_twldata = {
 
 static void __init omap4_i2c_init(void)
 {
-       omap4_pmic_init("twl6030", &sdp4430_twldata);
+       omap4_pmic_init("twl6030", &sdp4430_twldata, NULL, 0);
 }
 
 static void __init omap4_init(void)
index e558800adfdf58bdd69b55398ed8a7f3c4b332b0..930c0d3804359ee6543a0b0c59323432af6e7847 100644 (file)
@@ -634,8 +634,14 @@ static void __init igep_wlan_bt_init(void)
 static inline void __init igep_wlan_bt_init(void) { }
 #endif
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
 static void __init igep_init(void)
 {
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 
        /* Get IGEP2 hardware revision */
index d50a562adfa0b08c4eed8318711384833385571f..1b6049567ab49621d59061d80b34d6cb84a94cf0 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/spi/spi.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
 #include <linux/io.h>
@@ -410,8 +411,14 @@ static struct mtd_partition ldp_nand_partitions[] = {
 
 };
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
 static void __init omap_ldp_init(void)
 {
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
        ldp_init_smsc911x();
        omap_i2c_init();
index 4c90f078abe16fe7a7aba37c31800ae364ca611b..49df12735b41916db3a9d222880ddb4dcd89015d 100644 (file)
@@ -114,15 +114,6 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init omap3evm_init_smsc911x(void)
 {
-       struct clk *l3ck;
-       unsigned int rate;
-
-       l3ck = clk_get(NULL, "l3_ck");
-       if (IS_ERR(l3ck))
-               rate = 100000000;
-       else
-               rate = clk_get_rate(l3ck);
-
        /* Configure ethernet controller reset gpio */
        if (cpu_is_omap3430()) {
                if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1)
@@ -632,9 +623,15 @@ static void __init omap3_evm_wl12xx_init(void)
 #endif
 }
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
 static void __init omap3_evm_init(void)
 {
        omap3_evm_get_revision();
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
        if (cpu_is_omap3630())
                omap3_mux_init(omap36x_board_mux, OMAP_PACKAGE_CBB);
index 4a7d8c8a75da5298e2647e30aed3c4b87d8c5fef..9b3c141ff51bc575d65f157daf702df4ba6eab89 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 
 #include <linux/i2c/twl.h>
@@ -188,8 +189,14 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
 static void __init omap3logic_init(void)
 {
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
        omap3torpedo_fix_pbias_voltage();
        omap3logic_i2c_init();
index 641004380795f458c9432bf1056dd63187a5a33e..4dffc95bddd25836f85f06cc50dc3909fbc83abb 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
@@ -72,15 +73,6 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init omap3stalker_init_eth(void)
 {
-       struct clk *l3ck;
-       unsigned int rate;
-
-       l3ck = clk_get(NULL, "l3_ck");
-       if (IS_ERR(l3ck))
-               rate = 100000000;
-       else
-               rate = clk_get_rate(l3ck);
-
        omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP);
        gpmc_smsc911x_init(&smsc911x_cfg);
 }
@@ -419,8 +411,14 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
 static void __init omap3_stalker_init(void)
 {
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
        omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
        omap_board_config = omap3_stalker_config;
        omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
index d8c0e89f0126a2b4a7ba2a87d49641d1cf05c57c..1b782ba534336f6f3d3236e10316733f0f1b2abc 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/wl12xx.h>
@@ -284,7 +285,7 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
        return 0;
 }
 
-static struct twl4030_codec_data twl6040_codec = {
+static struct twl6040_codec_data twl6040_codec = {
        /* single-step ramp for headset and handsfree */
        .hs_left_step   = 0x0f,
        .hs_right_step  = 0x0f,
@@ -292,17 +293,14 @@ static struct twl4030_codec_data twl6040_codec = {
        .hf_right_step  = 0x1d,
 };
 
-static struct twl4030_audio_data twl6040_audio = {
+static struct twl6040_platform_data twl6040_data = {
        .codec          = &twl6040_codec,
        .audpwron_gpio  = 127,
-       .naudint_irq    = OMAP44XX_IRQ_SYS_2N,
        .irq_base       = TWL6040_CODEC_IRQ_BASE,
 };
 
 /* Panda board uses the common PMIC configuration */
-static struct twl4030_platform_data omap4_panda_twldata = {
-       .audio          = &twl6040_audio,
-};
+static struct twl4030_platform_data omap4_panda_twldata;
 
 /*
  * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
@@ -326,7 +324,8 @@ static int __init omap4_panda_i2c_init(void)
                        TWL_COMMON_REGULATOR_VCXIO |
                        TWL_COMMON_REGULATOR_VUSB |
                        TWL_COMMON_REGULATOR_CLK32KG);
-       omap4_pmic_init("twl6030", &omap4_panda_twldata);
+       omap4_pmic_init("twl6030", &omap4_panda_twldata,
+                       &twl6040_data, OMAP44XX_IRQ_SYS_2N);
        omap_register_i2c_bus(2, 400, NULL, 0);
        /*
         * Bus 3 is attached to the DVI port where devices like the pico DLP
index 668533e2a3791442e3582696d365e964179124e8..33aa3910b09e0deb1d209e35c2aefdfd9ca4fc71 100644 (file)
@@ -498,10 +498,18 @@ static struct gpio overo_bt_gpios[] __initdata = {
        { OVERO_GPIO_BT_NRESET, GPIOF_OUT_INIT_HIGH,    "lcd bl enable" },
 };
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+       REGULATOR_SUPPLY("vddvario", "smsc911x.1"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.1"),
+};
+
 static void __init overo_init(void)
 {
        int ret;
 
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
        omap_hsmmc_init(mmc);
        overo_i2c_init();
index 1e8540eabde98188ced71d321d7b531a685b463a..f64f441730612adc5c095cfab972bbc8064837da 100644 (file)
@@ -14,6 +14,9 @@
 #include <linux/smsc911x.h>
 #include <linux/interrupt.h>
 
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+
 #include <plat/gpmc.h>
 #include <plat/gpmc-smsc911x.h>
 
@@ -117,11 +120,17 @@ static struct platform_device *zoom_devices[] __initdata = {
        &zoom_debugboard_serial_device,
 };
 
+static struct regulator_consumer_supply dummy_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
 int __init zoom_debugboard_init(void)
 {
        if (!omap_zoom_debugboard_detect())
                return 0;
 
+       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
        zoom_init_smsc911x();
        zoom_init_quaduart();
        return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
index 7072e0d651b12356ec889158dde5102c5e7d6100..3d9d746b221ae0669fc01b1020ce0716c4f73a97 100644 (file)
@@ -165,83 +165,3 @@ int omap2_select_table_rate(struct clk *clk, unsigned long rate)
 
        return 0;
 }
-
-#ifdef CONFIG_CPU_FREQ
-/*
- * Walk PRCM rate table and fillout cpufreq freq_table
- * XXX This should be replaced by an OPP layer in the near future
- */
-static struct cpufreq_frequency_table *freq_table;
-
-void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
-{
-       const struct prcm_config *prcm;
-       int i = 0;
-       int tbl_sz = 0;
-
-       if (!cpu_is_omap24xx())
-               return;
-
-       for (prcm = rate_table; prcm->mpu_speed; prcm++) {
-               if (!(prcm->flags & cpu_mask))
-                       continue;
-               if (prcm->xtal_speed != sclk->rate)
-                       continue;
-
-               /* don't put bypass rates in table */
-               if (prcm->dpll_speed == prcm->xtal_speed)
-                       continue;
-
-               tbl_sz++;
-       }
-
-       /*
-        * XXX Ensure that we're doing what CPUFreq expects for this error
-        * case and the following one
-        */
-       if (tbl_sz == 0) {
-               pr_warning("%s: no matching entries in rate_table\n",
-                          __func__);
-               return;
-       }
-
-       /* Include the CPUFREQ_TABLE_END terminator entry */
-       tbl_sz++;
-
-       freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * tbl_sz,
-                            GFP_ATOMIC);
-       if (!freq_table) {
-               pr_err("%s: could not kzalloc frequency table\n", __func__);
-               return;
-       }
-
-       for (prcm = rate_table; prcm->mpu_speed; prcm++) {
-               if (!(prcm->flags & cpu_mask))
-                       continue;
-               if (prcm->xtal_speed != sclk->rate)
-                       continue;
-
-               /* don't put bypass rates in table */
-               if (prcm->dpll_speed == prcm->xtal_speed)
-                       continue;
-
-               freq_table[i].index = i;
-               freq_table[i].frequency = prcm->mpu_speed / 1000;
-               i++;
-       }
-
-       freq_table[i].index = i;
-       freq_table[i].frequency = CPUFREQ_TABLE_END;
-
-       *table = &freq_table[0];
-}
-
-void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
-{
-       if (!cpu_is_omap24xx())
-               return;
-
-       kfree(freq_table);
-}
-
-#endif
index f57ed5baeccf78f93c6b7f0a012a7b0da083c193..d9f4931513f97b4ba9020853ccbad621615d430f 100644 (file)
@@ -536,10 +536,5 @@ struct clk_functions omap2_clk_functions = {
        .clk_set_rate           = omap2_clk_set_rate,
        .clk_set_parent         = omap2_clk_set_parent,
        .clk_disable_unused     = omap2_clk_disable_unused,
-#ifdef CONFIG_CPU_FREQ
-       /* These will be removed when the OPP code is integrated */
-       .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
-       .clk_exit_cpufreq_table = omap2_clk_exit_cpufreq_table,
-#endif
 };
 
index b8c2a686481ca313298253246e789e1ce844feea..a1bb23a23351262600d242873d71536c9e4de134 100644 (file)
@@ -146,14 +146,6 @@ extern const struct clksel_rate gpt_sys_rates[];
 extern const struct clksel_rate gfx_l3_rates[];
 extern const struct clksel_rate dsp_ick_rates[];
 
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
-extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
-extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
-#else
-#define omap2_clk_init_cpufreq_table   0
-#define omap2_clk_exit_cpufreq_table   0
-#endif
-
 extern const struct clkops clkops_omap2_iclk_dflt_wait;
 extern const struct clkops clkops_omap2_iclk_dflt;
 extern const struct clkops clkops_omap2_iclk_idle_only;
index 480fb8f09aeda407a1578e521483768e48c9784c..f4a626f7c79e9670d65edf05e9d5813883b42da8 100644 (file)
@@ -747,7 +747,7 @@ static struct clk dpll4_m3_ck = {
        .parent         = &dpll4_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
-       .clksel_mask    = OMAP3430_CLKSEL_TV_MASK,
+       .clksel_mask    = OMAP3630_CLKSEL_TV_MASK,
        .clksel         = dpll4_clksel,
        .clkdm_name     = "dpll4_clkdm",
        .recalc         = &omap2_clksel_recalc,
@@ -832,7 +832,7 @@ static struct clk dpll4_m4_ck = {
        .parent         = &dpll4_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
-       .clksel_mask    = OMAP3430_CLKSEL_DSS1_MASK,
+       .clksel_mask    = OMAP3630_CLKSEL_DSS1_MASK,
        .clksel         = dpll4_clksel,
        .clkdm_name     = "dpll4_clkdm",
        .recalc         = &omap2_clksel_recalc,
@@ -859,7 +859,7 @@ static struct clk dpll4_m5_ck = {
        .parent         = &dpll4_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
-       .clksel_mask    = OMAP3430_CLKSEL_CAM_MASK,
+       .clksel_mask    = OMAP3630_CLKSEL_CAM_MASK,
        .clksel         = dpll4_clksel,
        .clkdm_name     = "dpll4_clkdm",
        .set_rate       = &omap2_clksel_set_rate,
@@ -886,7 +886,7 @@ static struct clk dpll4_m6_ck = {
        .parent         = &dpll4_ck,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
-       .clksel_mask    = OMAP3430_DIV_DPLL4_MASK,
+       .clksel_mask    = OMAP3630_DIV_DPLL4_MASK,
        .clksel         = dpll4_clksel,
        .clkdm_name     = "dpll4_clkdm",
        .recalc         = &omap2_clksel_recalc,
@@ -1394,6 +1394,7 @@ static struct clk cpefuse_fck = {
        .name           = "cpefuse_fck",
        .ops            = &clkops_omap2_dflt,
        .parent         = &sys_ck,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
        .enable_bit     = OMAP3430ES2_EN_CPEFUSE_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1403,6 +1404,7 @@ static struct clk ts_fck = {
        .name           = "ts_fck",
        .ops            = &clkops_omap2_dflt,
        .parent         = &omap_32k_fck,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
        .enable_bit     = OMAP3430ES2_EN_TS_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1412,6 +1414,7 @@ static struct clk usbtll_fck = {
        .name           = "usbtll_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &dpll5_m2_ck,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
        .enable_bit     = OMAP3430ES2_EN_USBTLL_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1617,6 +1620,7 @@ static struct clk fshostusb_fck = {
        .name           = "fshostusb_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &core_48m_fck,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2043,6 +2047,7 @@ static struct clk omapctrl_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_OMAPCTRL_SHIFT,
        .flags          = ENABLE_ON_INIT,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2094,6 +2099,7 @@ static struct clk usb_l4_ick = {
        .clksel_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
        .clksel_mask    = OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
        .clksel         = usb_l4_clksel,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -3467,8 +3473,8 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "ipss_ick",     &ipss_ick,      CK_AM35XX),
        CLK(NULL,       "rmii_ck",      &rmii_ck,       CK_AM35XX),
        CLK(NULL,       "pclk_ck",      &pclk_ck,       CK_AM35XX),
-       CLK("davinci_emac",     "emac_clk",     &emac_ick,      CK_AM35XX),
-       CLK("davinci_emac",     "phy_clk",      &emac_fck,      CK_AM35XX),
+       CLK("davinci_emac",     NULL,   &emac_ick,      CK_AM35XX),
+       CLK("davinci_mdio.0",   NULL,   &emac_fck,      CK_AM35XX),
        CLK("vpfe-capture",     "master",       &vpfe_ick,      CK_AM35XX),
        CLK("vpfe-capture",     "slave",        &vpfe_fck,      CK_AM35XX),
        CLK("musb-am35x",       "ick",          &hsotgusb_ick_am35xx,   CK_AM35XX),
index c03c1108468e1a59f5f203de7d092928e06bae79..fa6ea65ad44b0c87874cd54347eb74d48a24ae81 100644 (file)
@@ -957,8 +957,8 @@ static struct dpll_data dpll_usb_dd = {
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_USB,
        .idlest_reg     = OMAP4430_CM_IDLEST_DPLL_USB,
-       .mult_mask      = OMAP4430_DPLL_MULT_MASK,
-       .div1_mask      = OMAP4430_DPLL_DIV_MASK,
+       .mult_mask      = OMAP4430_DPLL_MULT_USB_MASK,
+       .div1_mask      = OMAP4430_DPLL_DIV_0_7_MASK,
        .enable_mask    = OMAP4430_DPLL_EN_MASK,
        .autoidle_mask  = OMAP4430_AUTO_DPLL_MODE_MASK,
        .idlest_mask    = OMAP4430_ST_DPLL_CLK_MASK,
@@ -978,6 +978,7 @@ static struct clk dpll_usb_ck = {
        .recalc         = &omap3_dpll_recalc,
        .round_rate     = &omap2_dpll_round_rate,
        .set_rate       = &omap3_noncore_dpll_set_rate,
+       .clkdm_name     = "l3_init_clkdm",
 };
 
 static struct clk dpll_usb_clkdcoldo_ck = {
index 9299ac291d28165b74f23bcb5e7ed73741c6a31b..bd7ed13515cc75c78662ef8adb323b693407247f 100644 (file)
@@ -390,7 +390,7 @@ static struct clockdomain emu_sys_44xx_clkdm = {
        .prcm_partition   = OMAP4430_PRM_PARTITION,
        .cm_inst          = OMAP4430_PRM_EMU_CM_INST,
        .clkdm_offs       = OMAP4430_PRM_EMU_CM_EMU_CDOFFS,
-       .flags            = CLKDM_CAN_HWSUP,
+       .flags            = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_FORCE_WAKEUP,
 };
 
 static struct clockdomain l3_dma_44xx_clkdm = {
index 5e5880d6d099e9a17e29436f7515f27ad2f94093..b6c77be3e8f762a144fd993553d88aa4ebe7f101 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/smsc911x.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
 
 #include <plat/board.h>
 #include <plat/gpmc.h>
 #include <plat/gpmc-smsc911x.h>
 
-static struct omap_smsc911x_platform_data *gpmc_cfg;
-
 static struct resource gpmc_smsc911x_resources[] = {
        [0] = {
                .flags          = IORESOURCE_MEM,
@@ -41,51 +37,6 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = {
        .phy_interface  = PHY_INTERFACE_MODE_MII,
        .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
        .irq_type       = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
-       .flags          = SMSC911X_USE_16BIT,
-};
-
-static struct regulator_consumer_supply gpmc_smsc911x_supply[] = {
-       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
-       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
-};
-
-/* Generic regulator definition to satisfy smsc911x */
-static struct regulator_init_data gpmc_smsc911x_reg_init_data = {
-       .constraints = {
-               .min_uV                 = 3300000,
-               .max_uV                 = 3300000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(gpmc_smsc911x_supply),
-       .consumer_supplies      = gpmc_smsc911x_supply,
-};
-
-static struct fixed_voltage_config gpmc_smsc911x_fixed_reg_data = {
-       .supply_name            = "gpmc_smsc911x",
-       .microvolts             = 3300000,
-       .gpio                   = -EINVAL,
-       .startup_delay          = 0,
-       .enable_high            = 0,
-       .enabled_at_boot        = 1,
-       .init_data              = &gpmc_smsc911x_reg_init_data,
-};
-
-/*
- * Platform device id of 42 is a temporary fix to avoid conflicts
- * with other reg-fixed-voltage devices. The real fix should
- * involve the driver core providing a way of dynamically
- * assigning a unique id on registration for platform devices
- * in the same name space.
- */
-static struct platform_device gpmc_smsc911x_regulator = {
-       .name           = "reg-fixed-voltage",
-       .id             = 42,
-       .dev = {
-               .platform_data  = &gpmc_smsc911x_fixed_reg_data,
-       },
 };
 
 /*
@@ -93,23 +44,12 @@ static struct platform_device gpmc_smsc911x_regulator = {
  * assume that pin multiplexing is done in the board-*.c file,
  * or in the bootloader.
  */
-void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data)
+void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 {
        struct platform_device *pdev;
        unsigned long cs_mem_base;
        int ret;
 
-       gpmc_cfg = board_data;
-
-       if (!gpmc_cfg->id) {
-               ret = platform_device_register(&gpmc_smsc911x_regulator);
-               if (ret < 0) {
-                       pr_err("Unable to register smsc911x regulators: %d\n",
-                              ret);
-                       return;
-               }
-       }
-
        if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
                pr_err("Failed to request GPMC mem region\n");
                return;
@@ -139,8 +79,7 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data)
                gpio_set_value(gpmc_cfg->gpio_reset, 1);
        }
 
-       if (gpmc_cfg->flags)
-               gpmc_smsc911x_config.flags = gpmc_cfg->flags;
+       gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT;
 
        pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id,
                 gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources),
index 100db6217f39984428ba49df988df65c2307f936..b0268eaffe1353dcba99f46eaf76971ccb94c178 100644 (file)
@@ -506,6 +506,13 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
        if (oh->dev_attr != NULL) {
                mmc_dev_attr = oh->dev_attr;
                mmc_data->controller_flags = mmc_dev_attr->flags;
+               /*
+                * erratum 2.1.1.128 doesn't apply if board has
+                * a transceiver is attached
+                */
+               if (hsmmcinfo->transceiver)
+                       mmc_data->controller_flags &=
+                               ~OMAP_HSMMC_BROKEN_MULTIBLOCK_READ;
        }
 
        pdev = platform_device_alloc(name, ctrl_nr - 1);
index 4fa72c7cc7cdee537c65dbc13b553ce60dd667b6..1c582a8592b936be6184dcf84c2272960c1e662e 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef __MACH_BARRIERS_H
 #define __MACH_BARRIERS_H
 
+#include <asm/outercache.h>
+
 extern void omap_bus_sync(void);
 
 #define rmb()          dsb()
index eba6cd3816f5e917d09aa5d8367c84f27a6e51dc..7144ae651d3defcb6e74f9f59ce7f38207691bf4 100644 (file)
@@ -1395,7 +1395,7 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
  */
 static int _ocp_softreset(struct omap_hwmod *oh)
 {
-       u32 v;
+       u32 v, softrst_mask;
        int c = 0;
        int ret = 0;
 
@@ -1422,16 +1422,21 @@ static int _ocp_softreset(struct omap_hwmod *oh)
                goto dis_opt_clks;
        _write_sysconfig(v, oh);
 
+       if (oh->class->sysc->srst_udelay)
+               udelay(oh->class->sysc->srst_udelay);
+
        if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
                omap_test_timeout((omap_hwmod_read(oh,
                                                    oh->class->sysc->syss_offs)
                                   & SYSS_RESETDONE_MASK),
                                  MAX_MODULE_SOFTRESET_WAIT, c);
-       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS)
+       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
+               softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
                omap_test_timeout(!(omap_hwmod_read(oh,
                                                     oh->class->sysc->sysc_offs)
-                                  & SYSC_TYPE2_SOFTRESET_MASK),
+                                  & softrst_mask),
                                  MAX_MODULE_SOFTRESET_WAIT, c);
+       }
 
        if (c == MAX_MODULE_SOFTRESET_WAIT)
                pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
@@ -1477,6 +1482,11 @@ static int _reset(struct omap_hwmod *oh)
 
        ret = (oh->class->reset) ? oh->class->reset(oh) : _ocp_softreset(oh);
 
+       if (oh->class->sysc) {
+               _update_sysc_cache(oh);
+               _enable_sysc(oh);
+       }
+
        return ret;
 }
 
@@ -1786,20 +1796,9 @@ static int _setup(struct omap_hwmod *oh, void *data)
                return 0;
        }
 
-       if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
+       if (!(oh->flags & HWMOD_INIT_NO_RESET))
                _reset(oh);
 
-               /*
-                * OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
-                * The _enable() function should be split to
-                * avoid the rewrite of the OCP_SYSCONFIG register.
-                */
-               if (oh->class->sysc) {
-                       _update_sysc_cache(oh);
-                       _enable_sysc(oh);
-               }
-       }
-
        postsetup_state = oh->_postsetup_state;
        if (postsetup_state == _HWMOD_STATE_UNKNOWN)
                postsetup_state = _HWMOD_STATE_ENABLED;
@@ -2463,26 +2462,28 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
  * @oh: struct omap_hwmod *
  *
  * Sets the module OCP socket ENAWAKEUP bit to allow the module to
- * send wakeups to the PRCM.  Eventually this should sets PRCM wakeup
- * registers to cause the PRCM to receive wakeup events from the
- * module.  Does not set any wakeup routing registers beyond this
- * point - if the module is to wake up any other module or subsystem,
- * that must be set separately.  Called by omap_device code.  Returns
- * -EINVAL on error or 0 upon success.
+ * send wakeups to the PRCM, and enable I/O ring wakeup events for
+ * this IP block if it has dynamic mux entries.  Eventually this
+ * should set PRCM wakeup registers to cause the PRCM to receive
+ * wakeup events from the module.  Does not set any wakeup routing
+ * registers beyond this point - if the module is to wake up any other
+ * module or subsystem, that must be set separately.  Called by
+ * omap_device code.  Returns -EINVAL on error or 0 upon success.
  */
 int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 {
        unsigned long flags;
        u32 v;
 
-       if (!oh->class->sysc ||
-           !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
-               return -EINVAL;
-
        spin_lock_irqsave(&oh->_lock, flags);
-       v = oh->_sysc_cache;
-       _enable_wakeup(oh, &v);
-       _write_sysconfig(v, oh);
+
+       if (oh->class->sysc &&
+           (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) {
+               v = oh->_sysc_cache;
+               _enable_wakeup(oh, &v);
+               _write_sysconfig(v, oh);
+       }
+
        _set_idle_ioring_wakeup(oh, true);
        spin_unlock_irqrestore(&oh->_lock, flags);
 
@@ -2494,26 +2495,28 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
  * @oh: struct omap_hwmod *
  *
  * Clears the module OCP socket ENAWAKEUP bit to prevent the module
- * from sending wakeups to the PRCM.  Eventually this should clear
- * PRCM wakeup registers to cause the PRCM to ignore wakeup events
- * from the module.  Does not set any wakeup routing registers beyond
- * this point - if the module is to wake up any other module or
- * subsystem, that must be set separately.  Called by omap_device
- * code.  Returns -EINVAL on error or 0 upon success.
+ * from sending wakeups to the PRCM, and disable I/O ring wakeup
+ * events for this IP block if it has dynamic mux entries.  Eventually
+ * this should clear PRCM wakeup registers to cause the PRCM to ignore
+ * wakeup events from the module.  Does not set any wakeup routing
+ * registers beyond this point - if the module is to wake up any other
+ * module or subsystem, that must be set separately.  Called by
+ * omap_device code.  Returns -EINVAL on error or 0 upon success.
  */
 int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 {
        unsigned long flags;
        u32 v;
 
-       if (!oh->class->sysc ||
-           !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
-               return -EINVAL;
-
        spin_lock_irqsave(&oh->_lock, flags);
-       v = oh->_sysc_cache;
-       _disable_wakeup(oh, &v);
-       _write_sysconfig(v, oh);
+
+       if (oh->class->sysc &&
+           (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) {
+               v = oh->_sysc_cache;
+               _disable_wakeup(oh, &v);
+               _write_sysconfig(v, oh);
+       }
+
        _set_idle_ioring_wakeup(oh, false);
        spin_unlock_irqrestore(&oh->_lock, flags);
 
index a5409ce3f3233eaac531ed070fc1f9cf74e8398f..a6bde34e443a7719fcefcbf447779ea16c9202b0 100644 (file)
@@ -1000,7 +1000,6 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
                        .flags  = OMAP_FIREWALL_L4,
                }
        },
-       .flags          = OCPIF_SWSUP_IDLE,
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
index c4f56cb60d7d676ddda36e232c8b385a58fef6ba..04a3885f4475f6e6ff865c4624a19d58b061a7f4 100644 (file)
@@ -1049,7 +1049,6 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
        .slave          = &omap2430_dss_venc_hwmod,
        .clk            = "dss_ick",
        .addr           = omap2_dss_venc_addrs,
-       .flags          = OCPIF_SWSUP_IDLE,
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
index 34b9766d1d231845356b2c71626fa234a731bee6..db86ce90c69fbc769fd1c63005a5ad188e43f33b 100644 (file)
@@ -1676,7 +1676,6 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
                        .flags  = OMAP_FIREWALL_L4,
                }
        },
-       .flags          = OCPIF_SWSUP_IDLE,
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
index 08daa5e0eb5fdbd1fa3a20c5c1ba4dd1112b3d90..6abc75753e42b2048ab7e7a4e4d158064efcce8b 100644 (file)
@@ -2594,6 +2594,15 @@ static struct omap_hwmod omap44xx_ipu_hwmod = {
 static struct omap_hwmod_class_sysconfig omap44xx_iss_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
+       /*
+        * ISS needs 100 OCP clk cycles delay after a softreset before
+        * accessing sysconfig again.
+        * The lowest frequency at the moment for L3 bus is 100 MHz, so
+        * 1usec delay is needed. Add an x2 margin to be safe (2 usecs).
+        *
+        * TODO: Indicate errata when available.
+        */
+       .srst_udelay    = 2,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
                           SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -2996,6 +3005,11 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp1_slaves[] = {
        &omap44xx_l4_abe__mcbsp1_dma,
 };
 
+static struct omap_hwmod_opt_clk mcbsp1_opt_clks[] = {
+       { .role = "pad_fck", .clk = "pad_clks_ck" },
+       { .role = "prcm_clk", .clk = "mcbsp1_sync_mux_ck" },
+};
+
 static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
        .name           = "mcbsp1",
        .class          = &omap44xx_mcbsp_hwmod_class,
@@ -3012,6 +3026,8 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
        },
        .slaves         = omap44xx_mcbsp1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_mcbsp1_slaves),
+       .opt_clks       = mcbsp1_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp1_opt_clks),
 };
 
 /* mcbsp2 */
@@ -3071,6 +3087,11 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp2_slaves[] = {
        &omap44xx_l4_abe__mcbsp2_dma,
 };
 
+static struct omap_hwmod_opt_clk mcbsp2_opt_clks[] = {
+       { .role = "pad_fck", .clk = "pad_clks_ck" },
+       { .role = "prcm_clk", .clk = "mcbsp2_sync_mux_ck" },
+};
+
 static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
        .name           = "mcbsp2",
        .class          = &omap44xx_mcbsp_hwmod_class,
@@ -3087,6 +3108,8 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
        },
        .slaves         = omap44xx_mcbsp2_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_mcbsp2_slaves),
+       .opt_clks       = mcbsp2_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp2_opt_clks),
 };
 
 /* mcbsp3 */
@@ -3146,6 +3169,11 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp3_slaves[] = {
        &omap44xx_l4_abe__mcbsp3_dma,
 };
 
+static struct omap_hwmod_opt_clk mcbsp3_opt_clks[] = {
+       { .role = "pad_fck", .clk = "pad_clks_ck" },
+       { .role = "prcm_clk", .clk = "mcbsp3_sync_mux_ck" },
+};
+
 static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
        .name           = "mcbsp3",
        .class          = &omap44xx_mcbsp_hwmod_class,
@@ -3162,6 +3190,8 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
        },
        .slaves         = omap44xx_mcbsp3_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_mcbsp3_slaves),
+       .opt_clks       = mcbsp3_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp3_opt_clks),
 };
 
 /* mcbsp4 */
@@ -3200,6 +3230,11 @@ static struct omap_hwmod_ocp_if *omap44xx_mcbsp4_slaves[] = {
        &omap44xx_l4_per__mcbsp4,
 };
 
+static struct omap_hwmod_opt_clk mcbsp4_opt_clks[] = {
+       { .role = "pad_fck", .clk = "pad_clks_ck" },
+       { .role = "prcm_clk", .clk = "mcbsp4_sync_mux_ck" },
+};
+
 static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
        .name           = "mcbsp4",
        .class          = &omap44xx_mcbsp_hwmod_class,
@@ -3216,6 +3251,8 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
        },
        .slaves         = omap44xx_mcbsp4_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_mcbsp4_slaves),
+       .opt_clks       = mcbsp4_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp4_opt_clks),
 };
 
 /*
index 9262a6b47702582d30a2a75d21cb3637c2252a24..de6d46451746eaa19f2ba2a28c6385531acddce3 100644 (file)
@@ -64,10 +64,10 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
                }
                oh = omap_hwmod_lookup(opp_def->hwmod_name);
                if (!oh || !oh->od) {
-                       pr_warn("%s: no hwmod or odev for %s, [%d] "
+                       pr_debug("%s: no hwmod or odev for %s, [%d] "
                                "cannot add OPPs.\n", __func__,
                                opp_def->hwmod_name, i);
-                       return -EINVAL;
+                       continue;
                }
                dev = &oh->od->pdev->dev;
 
index 238defc6f6df26a185794510f8f031d0848afda8..703bd10992591ce2a05635052c9cb685dd5c9c83 100644 (file)
@@ -153,8 +153,7 @@ static void omap3_save_secure_ram_context(void)
                pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
                /* Following is for error tracking, it should not happen */
                if (ret) {
-                       printk(KERN_ERR "save_secure_sram() returns %08x\n",
-                               ret);
+                       pr_err("save_secure_sram() returns %08x\n", ret);
                        while (1)
                                ;
                }
@@ -289,7 +288,7 @@ void omap_sram_idle(void)
                break;
        default:
                /* Invalid state */
-               printk(KERN_ERR "Invalid mpu state in sram_idle\n");
+               pr_err("Invalid mpu state in sram_idle\n");
                return;
        }
 
@@ -439,18 +438,17 @@ restore:
        list_for_each_entry(pwrst, &pwrst_list, node) {
                state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
                if (state > pwrst->next_state) {
-                       printk(KERN_INFO "Powerdomain (%s) didn't enter "
-                              "target state %d\n",
+                       pr_info("Powerdomain (%s) didn't enter "
+                               "target state %d\n",
                               pwrst->pwrdm->name, pwrst->next_state);
                        ret = -1;
                }
                omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
        }
        if (ret)
-               printk(KERN_ERR "Could not enter target state in pm_suspend\n");
+               pr_err("Could not enter target state in pm_suspend\n");
        else
-               printk(KERN_INFO "Successfully put all powerdomains "
-                      "to target state\n");
+               pr_info("Successfully put all powerdomains to target state\n");
 
        return ret;
 }
@@ -734,21 +732,22 @@ static int __init omap3_pm_init(void)
 
        if (ret) {
                pr_err("pm: Failed to request pm_io irq\n");
-               goto err1;
+               goto err2;
        }
 
        ret = pwrdm_for_each(pwrdms_setup, NULL);
        if (ret) {
-               printk(KERN_ERR "Failed to setup powerdomains\n");
-               goto err2;
+               pr_err("Failed to setup powerdomains\n");
+               goto err3;
        }
 
        (void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
 
        mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
        if (mpu_pwrdm == NULL) {
-               printk(KERN_ERR "Failed to get mpu_pwrdm\n");
-               goto err2;
+               pr_err("Failed to get mpu_pwrdm\n");
+               ret = -EINVAL;
+               goto err3;
        }
 
        neon_pwrdm = pwrdm_lookup("neon_pwrdm");
@@ -781,8 +780,8 @@ static int __init omap3_pm_init(void)
                omap3_secure_ram_storage =
                        kmalloc(0x803F, GFP_KERNEL);
                if (!omap3_secure_ram_storage)
-                       printk(KERN_ERR "Memory allocation failed when"
-                                       "allocating for secure sram context\n");
+                       pr_err("Memory allocation failed when "
+                              "allocating for secure sram context\n");
 
                local_irq_disable();
                local_fiq_disable();
@@ -796,14 +795,17 @@ static int __init omap3_pm_init(void)
        }
 
        omap3_save_scratchpad_contents();
-err1:
        return ret;
-err2:
-       free_irq(INT_34XX_PRCM_MPU_IRQ, NULL);
+
+err3:
        list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) {
                list_del(&pwrst->node);
                kfree(pwrst);
        }
+       free_irq(omap_prcm_event_to_irq("io"), omap3_pm_init);
+err2:
+       free_irq(omap_prcm_event_to_irq("wkup"), NULL);
+err1:
        return ret;
 }
 
index 9ccaadc2cf071011c39713548bf557ced9b789f7..8856253524292dcfb9ebffca53bcc3f83cf3151d 100644 (file)
@@ -144,7 +144,7 @@ static void omap_default_idle(void)
 static int __init omap4_pm_init(void)
 {
        int ret;
-       struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm;
+       struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm, *l4wkup;
        struct clockdomain *ducati_clkdm, *l3_2_clkdm, *l4_per_clkdm;
 
        if (!cpu_is_omap44xx())
@@ -168,14 +168,19 @@ static int __init omap4_pm_init(void)
         * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as
         * expected. The hardware recommendation is to enable static
         * dependencies for these to avoid system lock ups or random crashes.
+        * The L4 wakeup depedency is added to workaround the OCP sync hardware
+        * BUG with 32K synctimer which lead to incorrect timer value read
+        * from the 32K counter. The BUG applies for GPTIMER1 and WDT2 which
+        * are part of L4 wakeup clockdomain.
         */
        mpuss_clkdm = clkdm_lookup("mpuss_clkdm");
        emif_clkdm = clkdm_lookup("l3_emif_clkdm");
        l3_1_clkdm = clkdm_lookup("l3_1_clkdm");
        l3_2_clkdm = clkdm_lookup("l3_2_clkdm");
        l4_per_clkdm = clkdm_lookup("l4_per_clkdm");
+       l4wkup = clkdm_lookup("l4_wkup_clkdm");
        ducati_clkdm = clkdm_lookup("ducati_clkdm");
-       if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) ||
+       if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) || (!l4wkup) ||
                (!l3_2_clkdm) || (!ducati_clkdm) || (!l4_per_clkdm))
                goto err2;
 
@@ -183,6 +188,7 @@ static int __init omap4_pm_init(void)
        ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm);
        ret |= clkdm_add_wkdep(mpuss_clkdm, l3_2_clkdm);
        ret |= clkdm_add_wkdep(mpuss_clkdm, l4_per_clkdm);
+       ret |= clkdm_add_wkdep(mpuss_clkdm, l4wkup);
        ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm);
        ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
        if (ret) {
index 8a18d1bd61c80af893e3cc549daaaa2e10b90db3..96ad3dbeac3433b877028800e6b3a621b7e67666 100644 (file)
@@ -972,7 +972,13 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
 
 int pwrdm_state_switch(struct powerdomain *pwrdm)
 {
-       return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
+       int ret;
+
+       ret = pwrdm_wait_transition(pwrdm);
+       if (!ret)
+               ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
+
+       return ret;
 }
 
 int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
index eac623c7c3d86c58869c4804f63ad576631c129a..f106d21ff581a3af4894fd45f58fe53aaebc6dd2 100644 (file)
@@ -147,8 +147,9 @@ static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs)
        u32 mask, st;
 
        /* XXX read mask from RAM? */
-       mask = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, irqen_offs);
-       st = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, irqst_offs);
+       mask = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+                                      irqen_offs);
+       st = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, irqst_offs);
 
        return mask & st;
 }
@@ -180,7 +181,7 @@ void omap44xx_prm_read_pending_irqs(unsigned long *events)
  */
 void omap44xx_prm_ocp_barrier(void)
 {
-       omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+       omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
                                OMAP4_REVISION_PRM_OFFSET);
 }
 
@@ -198,19 +199,19 @@ void omap44xx_prm_ocp_barrier(void)
 void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
 {
        saved_mask[0] =
-               omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+               omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
                                        OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
        saved_mask[1] =
-               omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+               omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
                                        OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET);
 
-       omap4_prm_write_inst_reg(0, OMAP4430_PRM_DEVICE_INST,
+       omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
                                 OMAP4_PRM_IRQENABLE_MPU_OFFSET);
-       omap4_prm_write_inst_reg(0, OMAP4430_PRM_DEVICE_INST,
+       omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
                                 OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
 
        /* OCP barrier */
-       omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+       omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
                                OMAP4_REVISION_PRM_OFFSET);
 }
 
@@ -226,9 +227,9 @@ void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
  */
 void omap44xx_prm_restore_irqen(u32 *saved_mask)
 {
-       omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_DEVICE_INST,
+       omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_OCP_SOCKET_INST,
                                 OMAP4_PRM_IRQENABLE_MPU_OFFSET);
-       omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_DEVICE_INST,
+       omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_OCP_SOCKET_INST,
                                 OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
 }
 
index 873b51d494eace09418ad9da30e35d15642b6ef8..d28f848897d62083e339d493263032249a2760bd 100644 (file)
@@ -290,7 +290,7 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
                goto err;
        }
 
-       for (i = 0; i <= irq_setup->nr_regs; i++) {
+       for (i = 0; i < irq_setup->nr_regs; i++) {
                gc = irq_alloc_generic_chip("PRCM", 1,
                        irq_setup->base_irq + i * 32, prm_base,
                        handle_level_irq);
index 0cdd359a128ee855e357daee257ec38231a05658..9fc2f44188cbb5fa0657f45ee5b5f3e14662569b 100644 (file)
@@ -108,8 +108,14 @@ static void omap_uart_set_noidle(struct platform_device *pdev)
 static void omap_uart_set_smartidle(struct platform_device *pdev)
 {
        struct omap_device *od = to_omap_device(pdev);
+       u8 idlemode;
 
-       omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
+       if (od->hwmods[0]->class->sysc->idlemodes & SIDLE_SMART_WKUP)
+               idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+       else
+               idlemode = HWMOD_IDLEMODE_SMART;
+
+       omap_hwmod_set_slave_idlemode(od->hwmods[0], idlemode);
 }
 
 #else
@@ -120,124 +126,8 @@ static void omap_uart_set_smartidle(struct platform_device *pdev) {}
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_OMAP_MUX
-static struct omap_device_pad default_uart1_pads[] __initdata = {
-       {
-               .name   = "uart1_cts.uart1_cts",
-               .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart1_rts.uart1_rts",
-               .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart1_tx.uart1_tx",
-               .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart1_rx.uart1_rx",
-               .flags  = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
-               .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
-               .idle   = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
-       },
-};
-
-static struct omap_device_pad default_uart2_pads[] __initdata = {
-       {
-               .name   = "uart2_cts.uart2_cts",
-               .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart2_rts.uart2_rts",
-               .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart2_tx.uart2_tx",
-               .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart2_rx.uart2_rx",
-               .flags  = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
-               .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
-               .idle   = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
-       },
-};
-
-static struct omap_device_pad default_uart3_pads[] __initdata = {
-       {
-               .name   = "uart3_cts_rctx.uart3_cts_rctx",
-               .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart3_rts_sd.uart3_rts_sd",
-               .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart3_tx_irtx.uart3_tx_irtx",
-               .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart3_rx_irrx.uart3_rx_irrx",
-               .flags  = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
-               .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
-               .idle   = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
-       },
-};
-
-static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = {
-       {
-               .name   = "gpmc_wait2.uart4_tx",
-               .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "gpmc_wait3.uart4_rx",
-               .flags  = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
-               .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
-               .idle   = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
-       },
-};
-
-static struct omap_device_pad default_omap4_uart4_pads[] __initdata = {
-       {
-               .name   = "uart4_tx.uart4_tx",
-               .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
-       },
-       {
-               .name   = "uart4_rx.uart4_rx",
-               .flags  = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
-               .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
-               .idle   = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
-       },
-};
-
 static void omap_serial_fill_default_pads(struct omap_board_data *bdata)
 {
-       switch (bdata->id) {
-       case 0:
-               bdata->pads = default_uart1_pads;
-               bdata->pads_cnt = ARRAY_SIZE(default_uart1_pads);
-               break;
-       case 1:
-               bdata->pads = default_uart2_pads;
-               bdata->pads_cnt = ARRAY_SIZE(default_uart2_pads);
-               break;
-       case 2:
-               bdata->pads = default_uart3_pads;
-               bdata->pads_cnt = ARRAY_SIZE(default_uart3_pads);
-               break;
-       case 3:
-               if (cpu_is_omap44xx()) {
-                       bdata->pads = default_omap4_uart4_pads;
-                       bdata->pads_cnt =
-                               ARRAY_SIZE(default_omap4_uart4_pads);
-               } else if (cpu_is_omap3630()) {
-                       bdata->pads = default_omap36xx_uart4_pads;
-                       bdata->pads_cnt =
-                               ARRAY_SIZE(default_omap36xx_uart4_pads);
-               }
-               break;
-       default:
-               break;
-       }
 }
 #else
 static void omap_serial_fill_default_pads(struct omap_board_data *bdata) {}
index 4b57757bf9d1200cf4e47e099734ec424cad47d2..7a7b89304c48eeb2e1af9f9b87f77d9d5dd5a6f1 100644 (file)
@@ -37,6 +37,16 @@ static struct i2c_board_info __initdata pmic_i2c_board_info = {
        .flags          = I2C_CLIENT_WAKE,
 };
 
+static struct i2c_board_info __initdata omap4_i2c1_board_info[] = {
+       {
+               .addr           = 0x48,
+               .flags          = I2C_CLIENT_WAKE,
+       },
+       {
+               I2C_BOARD_INFO("twl6040", 0x4b),
+       },
+};
+
 void __init omap_pmic_init(int bus, u32 clkrate,
                           const char *pmic_type, int pmic_irq,
                           struct twl4030_platform_data *pmic_data)
@@ -49,14 +59,31 @@ void __init omap_pmic_init(int bus, u32 clkrate,
        omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
 }
 
+void __init omap4_pmic_init(const char *pmic_type,
+                   struct twl4030_platform_data *pmic_data,
+                   struct twl6040_platform_data *twl6040_data, int twl6040_irq)
+{
+       /* PMIC part*/
+       strncpy(omap4_i2c1_board_info[0].type, pmic_type,
+               sizeof(omap4_i2c1_board_info[0].type));
+       omap4_i2c1_board_info[0].irq = OMAP44XX_IRQ_SYS_1N;
+       omap4_i2c1_board_info[0].platform_data = pmic_data;
+
+       /* TWL6040 audio IC part */
+       omap4_i2c1_board_info[1].irq = twl6040_irq;
+       omap4_i2c1_board_info[1].platform_data = twl6040_data;
+
+       omap_register_i2c_bus(1, 400, omap4_i2c1_board_info, 2);
+
+}
+
 void __init omap_pmic_late_init(void)
 {
        /* Init the OMAP TWL parameters (if PMIC has been registerd) */
-       if (!pmic_i2c_board_info.irq)
-               return;
-
-       omap3_twl_init();
-       omap4_twl_init();
+       if (pmic_i2c_board_info.irq)
+               omap3_twl_init();
+       if (omap4_i2c1_board_info[0].irq)
+               omap4_twl_init();
 }
 
 #if defined(CONFIG_ARCH_OMAP3)
index 275dde8cb27aa789ce4d9bfa89c8ed92fb122711..09627483a57f917a3a1c74c39b232b951de1594f 100644 (file)
@@ -29,6 +29,7 @@
 
 
 struct twl4030_platform_data;
+struct twl6040_platform_data;
 
 void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
                    struct twl4030_platform_data *pmic_data);
@@ -46,12 +47,9 @@ static inline void omap3_pmic_init(const char *pmic_type,
        omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
 }
 
-static inline void omap4_pmic_init(const char *pmic_type,
-                                  struct twl4030_platform_data *pmic_data)
-{
-       /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */
-       omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data);
-}
+void omap4_pmic_init(const char *pmic_type,
+                   struct twl4030_platform_data *pmic_data,
+                   struct twl6040_platform_data *audio_data, int twl6040_irq);
 
 void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
                           u32 pdata_flags, u32 regulators_flags);
index f51348dafafdfb8ec85f48af6740fef8629f42b4..dde8a11f47d5ab9621dd3f6f0e87d1920351c9a2 100644 (file)
@@ -54,7 +54,7 @@ static struct omap_device_pm_latency omap_uhhtll_latency[] = {
 /*
  * setup_ehci_io_mux - initialize IO pad mux for USBHOST
  */
-static void setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static void __init setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
 {
        switch (port_mode[0]) {
        case OMAP_EHCI_PORT_MODE_PHY:
@@ -197,7 +197,8 @@ static void setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
        return;
 }
 
-static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static
+void __init setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
 {
        switch (port_mode[0]) {
        case OMAP_EHCI_PORT_MODE_PHY:
@@ -315,7 +316,7 @@ static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
        }
 }
 
-static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static void __init setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
 {
        switch (port_mode[0]) {
        case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
@@ -412,7 +413,8 @@ static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
        }
 }
 
-static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static
+void __init setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
 {
        switch (port_mode[0]) {
        case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
index 109ccd2a8885842dab6327e18ae4c4b49f0b35a0..fe2d1f80ef50ff340d63542e045e49295716cec9 100644 (file)
@@ -113,6 +113,7 @@ config MACH_ARMCORE
        select IWMMXT
        select PXA25x
        select MIGHT_HAVE_PCI
+       select NEED_MACH_IO_H if PCI
 
 config MACH_EM_X270
        bool "CompuLab EM-x270 platform"
diff --git a/arch/arm/mach-pxa/include/mach/io.h b/arch/arm/mach-pxa/include/mach/io.h
new file mode 100644 (file)
index 0000000..cd78b7f
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-pxa/include/mach/io.h
+ *
+ * Copied from asm/arch/sa1100/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a)                __typesafe_io(a)
+
+#endif
index c54cef25895cdbbbe03c3922490f69be83409868..cbf51ae81855bc5bc255a4aa3abb606cf93bce68 100644 (file)
@@ -17,6 +17,7 @@
  *
  * bit     23 - Input/Output (PXA2xx specific)
  * bit     24 - Wakeup Enable(PXA2xx specific)
+ * bit     25 - Keep Output  (PXA2xx specific)
  */
 
 #define MFP_DIR_IN             (0x0 << 23)
 #define MFP_DIR(x)             (((x) >> 23) & 0x1)
 
 #define MFP_LPM_CAN_WAKEUP     (0x1 << 24)
+
+/*
+ * MFP_LPM_KEEP_OUTPUT must be specified for pins that need to
+ * retain their last output level (low or high).
+ * Note: MFP_LPM_KEEP_OUTPUT has no effect on pins configured for input.
+ */
 #define MFP_LPM_KEEP_OUTPUT    (0x1 << 25)
 
 #define WAKEUP_ON_EDGE_RISE    (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE)
index b0a842887780f9acbe32e4223b4fe769f49b88f1..ef0426a159d4d4e04c681f7097fb8732d7096156 100644 (file)
@@ -33,6 +33,8 @@
 #define BANK_OFF(n)    (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
 #define GPLR(x)                __REG2(0x40E00000, BANK_OFF((x) >> 5))
 #define GPDR(x)                __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x0c)
+#define GPSR(x)                __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x18)
+#define GPCR(x)                __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x24)
 
 #define PWER_WE35      (1 << 24)
 
@@ -348,6 +350,7 @@ static inline void pxa27x_mfp_init(void) {}
 #ifdef CONFIG_PM
 static unsigned long saved_gafr[2][4];
 static unsigned long saved_gpdr[4];
+static unsigned long saved_gplr[4];
 static unsigned long saved_pgsr[4];
 
 static int pxa2xx_mfp_suspend(void)
@@ -366,14 +369,26 @@ static int pxa2xx_mfp_suspend(void)
        }
 
        for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) {
-
                saved_gafr[0][i] = GAFR_L(i);
                saved_gafr[1][i] = GAFR_U(i);
                saved_gpdr[i] = GPDR(i * 32);
+               saved_gplr[i] = GPLR(i * 32);
                saved_pgsr[i] = PGSR(i);
 
-               GPDR(i * 32) = gpdr_lpm[i];
+               GPSR(i * 32) = PGSR(i);
+               GPCR(i * 32) = ~PGSR(i);
+       }
+
+       /* set GPDR bits taking into account MFP_LPM_KEEP_OUTPUT */
+       for (i = 0; i < pxa_last_gpio; i++) {
+               if ((gpdr_lpm[gpio_to_bank(i)] & GPIO_bit(i)) ||
+                   ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) &&
+                    (saved_gpdr[gpio_to_bank(i)] & GPIO_bit(i))))
+                       GPDR(i) |= GPIO_bit(i);
+               else
+                       GPDR(i) &= ~GPIO_bit(i);
        }
+
        return 0;
 }
 
@@ -384,6 +399,8 @@ static void pxa2xx_mfp_resume(void)
        for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) {
                GAFR_L(i) = saved_gafr[0][i];
                GAFR_U(i) = saved_gafr[1][i];
+               GPSR(i * 32) = saved_gplr[i];
+               GPCR(i * 32) = ~saved_gplr[i];
                GPDR(i * 32) = saved_gpdr[i];
                PGSR(i) = saved_pgsr[i];
        }
index 6bce78edce7a3c070b197b57f1fcb16197c3ba7f..4726c246dcdc930bd5db27feb301221c2edced42 100644 (file)
@@ -421,8 +421,11 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info)
        pxa_register_device(&pxa27x_device_i2c_power, info);
 }
 
+static struct pxa_gpio_platform_data pxa27x_gpio_info __initdata = {
+       .gpio_set_wake = gpio_set_wake,
+};
+
 static struct platform_device *devices[] __initdata = {
-       &pxa_device_gpio,
        &pxa27x_device_udc,
        &pxa_device_pmu,
        &pxa_device_i2s,
@@ -458,6 +461,7 @@ static int __init pxa27x_init(void)
                register_syscore_ops(&pxa2xx_mfp_syscore_ops);
                register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
+               pxa_register_device(&pxa_device_gpio, &pxa27x_gpio_info);
                ret = platform_add_devices(devices, ARRAY_SIZE(devices));
        }
 
index 0f3a327ebcaa380c823d251f65eb819bac9033a0..b34287ab5afd93502e9b5779918085c3b8eb68ec 100644 (file)
@@ -111,10 +111,6 @@ config S3C24XX_SETUP_TS
        help
          Compile in platform device definition for Samsung TouchScreen.
 
-# cpu-specific sections
-
-if CPU_S3C2410
-
 config S3C2410_DMA
        bool
        depends on S3C24XX_DMA && (CPU_S3C2410 || CPU_S3C2442)
@@ -127,6 +123,10 @@ config S3C2410_PM
        help
          Power Management code common to S3C2410 and better
 
+# cpu-specific sections
+
+if CPU_S3C2410
+
 config S3C24XX_SIMTEC_NOR
        bool
        help
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
new file mode 100644 (file)
index 0000000..c2f596e
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Common Header for S3C24XX SoCs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_S3C24XX_COMMON_H
+#define __ARCH_ARM_MACH_S3C24XX_COMMON_H __FILE__
+
+void s3c2410_restart(char mode, const char *cmd);
+void s3c244x_restart(char mode, const char *cmd);
+
+#endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */
index 86ce62f66190fe5a67c2c5dad4f092db67b4818e..b8337e248b0985587806fa9dab8b3759dd5c1ce3 100644 (file)
@@ -33,8 +33,6 @@
 #include <mach/irqs.h>
 #include <mach/dma.h>
 
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
 static u8 pdma0_peri[] = {
        DMACH_UART0_RX,
        DMACH_UART0_TX,
index a9ea64e0da0d2758e7775a8590d431fc5725d563..48d018f2332bc020239ca49f7d42986dd30134f8 100644 (file)
@@ -484,8 +484,8 @@ static struct wm8994_pdata wm8994_platform_data = {
        .gpio_defaults[8] = 0x0100,
        .gpio_defaults[9] = 0x0100,
        .gpio_defaults[10] = 0x0100,
-       .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
-       .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
+       .ldo[0] = { S5PV210_MP03(6), &wm8994_ldo1_data },       /* XM0FRNB_2 */
+       .ldo[1] = { 0, &wm8994_ldo2_data },
 };
 
 /* GPIO I2C PMIC */
index 2cf5ed75f3906ed21f6e5c028b7faaeb9f0c7bef..32395664e87917f640cdc70b74f287304a939b6a 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/mmc/host.h>
 #include <linux/interrupt.h>
 
 #include <asm/hardware/vic.h>
@@ -674,8 +675,8 @@ static struct wm8994_pdata wm8994_platform_data = {
        .gpio_defaults[8] = 0x0100,
        .gpio_defaults[9] = 0x0100,
        .gpio_defaults[10] = 0x0100,
-       .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
-       .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
+       .ldo[0] = { S5PV210_MP03(6), &wm8994_ldo1_data },       /* XM0FRNB_2 */
+       .ldo[1] = { 0, &wm8994_ldo2_data },
 };
 
 /* GPIO I2C PMIC */
@@ -765,6 +766,7 @@ static void __init goni_pmic_init(void)
 /* MoviNAND */
 static struct s3c_sdhci_platdata goni_hsmmc0_data __initdata = {
        .max_width              = 4,
+       .host_caps2             = MMC_CAP2_BROKEN_VOLTAGE,
        .cd_type                = S3C_SDHCI_CD_PERMANENT,
 };
 
index 48885b7efd6b895e470d616b5e8f895483747a7b..c7f418b0cde9bde3ba23c8d1ea73533fa775b700 100644 (file)
@@ -313,6 +313,10 @@ static struct sa1100fb_mach_info collie_lcd_info = {
 
        .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
        .lccr3          = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+
+#ifdef CONFIG_BACKLIGHT_LOCOMO
+       .lcd_power      = locomolcd_power
+#endif
 };
 
 static void __init collie_init(void)
index 7c524b4e415d7ec7843dcbd7987c663d2f447bd9..16be4c56abe3ff37a153807b93d066c49c0d94ab 100644 (file)
@@ -306,7 +306,7 @@ void sa11x0_register_irda(struct irda_platform_data *irda)
 }
 
 static struct resource sa1100_rtc_resources[] = {
-       DEFINE_RES_MEM(0x90010000, 0x9001003f),
+       DEFINE_RES_MEM(0x90010000, 0x40),
        DEFINE_RES_IRQ_NAMED(IRQ_RTC1Hz, "rtc 1Hz"),
        DEFINE_RES_IRQ_NAMED(IRQ_RTCAlrm, "rtc alarm"),
 };
index 52acda7061b7f85ccbc9b1d6966b5ffe57671e86..f33679d2d3ee0a218d280972c5f409f0b561d41b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-sa1100/include/mach/collie.h
  *
- * This file contains the hardware specific definitions for Assabet
+ * This file contains the hardware specific definitions for Collie
  * Only include this file from SA1100-specific files.
  *
  * ChangeLog:
@@ -13,6 +13,7 @@
 #ifndef __ASM_ARCH_COLLIE_H
 #define __ASM_ARCH_COLLIE_H
 
+extern void locomolcd_power(int on);
 
 #define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1)
 #define COLLIE_GPIO_CHARGE_ON  (COLLIE_SCOOP_GPIO_BASE + 0)
index 1621ad07d284fea97626fea99a3e5535844c8417..33339745d432bdf185f23d46a59f4dd1bb9f8eca 100644 (file)
@@ -1667,8 +1667,10 @@ void __init u300_init_irq(void)
 
        for (i = 0; i < U300_VIC_IRQS_END; i++)
                set_bit(i, (unsigned long *) &mask[0]);
-       vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);
-       vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
+       vic_init((void __iomem *) U300_INTCON0_VBASE, IRQ_U300_INTCON0_START,
+                mask[0], mask[0]);
+       vic_init((void __iomem *) U300_INTCON1_VBASE, IRQ_U300_INTCON1_START,
+                mask[1], mask[1]);
 }
 
 
index a38f80238ea97f08a69a9e42fb80a430404ff4a5..cb04bd6ab3e7f07248f57372015cec729e030798 100644 (file)
@@ -146,9 +146,6 @@ static struct ab3100_platform_data ab3100_plf_data = {
                                .min_uV = 1800000,
                                .max_uV = 1800000,
                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
-                               .valid_ops_mask =
-                               REGULATOR_CHANGE_VOLTAGE |
-                               REGULATOR_CHANGE_STATUS,
                                .always_on = 1,
                                .boot_on = 1,
                        },
@@ -160,9 +157,6 @@ static struct ab3100_platform_data ab3100_plf_data = {
                                .min_uV = 2500000,
                                .max_uV = 2500000,
                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
-                               .valid_ops_mask =
-                               REGULATOR_CHANGE_VOLTAGE |
-                               REGULATOR_CHANGE_STATUS,
                                .always_on = 1,
                                .boot_on = 1,
                        },
@@ -230,8 +224,7 @@ static struct ab3100_platform_data ab3100_plf_data = {
                                .max_uV = 1800000,
                                .valid_modes_mask = REGULATOR_MODE_NORMAL,
                                .valid_ops_mask =
-                               REGULATOR_CHANGE_VOLTAGE |
-                               REGULATOR_CHANGE_STATUS,
+                               REGULATOR_CHANGE_VOLTAGE,
                                .always_on = 1,
                                .boot_on = 1,
                        },
index ee78a26707ebe595f00265ccbc3c09a52ea4c1d3..ec09c1e07b1a8f6655e1887c353031f6471bc7f9 100644 (file)
 #ifndef __MACH_IRQS_H
 #define __MACH_IRQS_H
 
-#define IRQ_U300_INTCON0_START         0
-#define IRQ_U300_INTCON1_START         32
+#define IRQ_U300_INTCON0_START         1
+#define IRQ_U300_INTCON1_START         33
 /* These are on INTCON0 - 30 lines */
-#define IRQ_U300_IRQ0_EXT              0
-#define IRQ_U300_IRQ1_EXT              1
-#define IRQ_U300_DMA                   2
-#define IRQ_U300_VIDEO_ENC_0           3
-#define IRQ_U300_VIDEO_ENC_1           4
-#define IRQ_U300_AAIF_RX               5
-#define IRQ_U300_AAIF_TX               6
-#define IRQ_U300_AAIF_VGPIO            7
-#define IRQ_U300_AAIF_WAKEUP           8
-#define IRQ_U300_PCM_I2S0_FRAME                9
-#define IRQ_U300_PCM_I2S0_FIFO         10
-#define IRQ_U300_PCM_I2S1_FRAME                11
-#define IRQ_U300_PCM_I2S1_FIFO         12
-#define IRQ_U300_XGAM_GAMCON           13
-#define IRQ_U300_XGAM_CDI              14
-#define IRQ_U300_XGAM_CDICON           15
+#define IRQ_U300_IRQ0_EXT              1
+#define IRQ_U300_IRQ1_EXT              2
+#define IRQ_U300_DMA                   3
+#define IRQ_U300_VIDEO_ENC_0           4
+#define IRQ_U300_VIDEO_ENC_1           5
+#define IRQ_U300_AAIF_RX               6
+#define IRQ_U300_AAIF_TX               7
+#define IRQ_U300_AAIF_VGPIO            8
+#define IRQ_U300_AAIF_WAKEUP           9
+#define IRQ_U300_PCM_I2S0_FRAME                10
+#define IRQ_U300_PCM_I2S0_FIFO         11
+#define IRQ_U300_PCM_I2S1_FRAME                12
+#define IRQ_U300_PCM_I2S1_FIFO         13
+#define IRQ_U300_XGAM_GAMCON           14
+#define IRQ_U300_XGAM_CDI              15
+#define IRQ_U300_XGAM_CDICON           16
 #if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
 /* MMIACC not used on the DB3210 or DB3350 chips */
-#define IRQ_U300_XGAM_MMIACC           16
+#define IRQ_U300_XGAM_MMIACC           17
 #endif
-#define IRQ_U300_XGAM_PDI              17
-#define IRQ_U300_XGAM_PDICON           18
-#define IRQ_U300_XGAM_GAMEACC          19
-#define IRQ_U300_XGAM_MCIDCT           20
-#define IRQ_U300_APEX                  21
-#define IRQ_U300_UART0                 22
-#define IRQ_U300_SPI                   23
-#define IRQ_U300_TIMER_APP_OS          24
-#define IRQ_U300_TIMER_APP_DD          25
-#define IRQ_U300_TIMER_APP_GP1         26
-#define IRQ_U300_TIMER_APP_GP2         27
-#define IRQ_U300_TIMER_OS              28
-#define IRQ_U300_TIMER_MS              29
-#define IRQ_U300_KEYPAD_KEYBF          30
-#define IRQ_U300_KEYPAD_KEYBR          31
+#define IRQ_U300_XGAM_PDI              18
+#define IRQ_U300_XGAM_PDICON           19
+#define IRQ_U300_XGAM_GAMEACC          20
+#define IRQ_U300_XGAM_MCIDCT           21
+#define IRQ_U300_APEX                  22
+#define IRQ_U300_UART0                 23
+#define IRQ_U300_SPI                   24
+#define IRQ_U300_TIMER_APP_OS          25
+#define IRQ_U300_TIMER_APP_DD          26
+#define IRQ_U300_TIMER_APP_GP1         27
+#define IRQ_U300_TIMER_APP_GP2         28
+#define IRQ_U300_TIMER_OS              29
+#define IRQ_U300_TIMER_MS              30
+#define IRQ_U300_KEYPAD_KEYBF          31
+#define IRQ_U300_KEYPAD_KEYBR          32
 /* These are on INTCON1 - 32 lines */
-#define IRQ_U300_GPIO_PORT0            32
-#define IRQ_U300_GPIO_PORT1            33
-#define IRQ_U300_GPIO_PORT2            34
+#define IRQ_U300_GPIO_PORT0            33
+#define IRQ_U300_GPIO_PORT1            34
+#define IRQ_U300_GPIO_PORT2            35
 
 #if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) || \
     defined(CONFIG_MACH_U300_BS335)
 /* These are for DB3150, DB3200 and DB3350 */
-#define IRQ_U300_WDOG                  35
-#define IRQ_U300_EVHIST                        36
-#define IRQ_U300_MSPRO                 37
-#define IRQ_U300_MMCSD_MCIINTR0                38
-#define IRQ_U300_MMCSD_MCIINTR1                39
-#define IRQ_U300_I2C0                  40
-#define IRQ_U300_I2C1                  41
-#define IRQ_U300_RTC                   42
-#define IRQ_U300_NFIF                  43
-#define IRQ_U300_NFIF2                 44
+#define IRQ_U300_WDOG                  36
+#define IRQ_U300_EVHIST                        37
+#define IRQ_U300_MSPRO                 38
+#define IRQ_U300_MMCSD_MCIINTR0                39
+#define IRQ_U300_MMCSD_MCIINTR1                40
+#define IRQ_U300_I2C0                  41
+#define IRQ_U300_I2C1                  42
+#define IRQ_U300_RTC                   43
+#define IRQ_U300_NFIF                  44
+#define IRQ_U300_NFIF2                 45
 #endif
 
 /* DB3150 and DB3200 have only 45 IRQs */
 #if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_VIC_IRQS_END              45
+#define U300_VIC_IRQS_END              46
 #endif
 
 /* The DB3350-specific interrupt lines */
 #ifdef CONFIG_MACH_U300_BS335
-#define IRQ_U300_ISP_F0                        45
-#define IRQ_U300_ISP_F1                        46
-#define IRQ_U300_ISP_F2                        47
-#define IRQ_U300_ISP_F3                        48
-#define IRQ_U300_ISP_F4                        49
-#define IRQ_U300_GPIO_PORT3            50
-#define IRQ_U300_SYSCON_PLL_LOCK       51
-#define IRQ_U300_UART1                 52
-#define IRQ_U300_GPIO_PORT4            53
-#define IRQ_U300_GPIO_PORT5            54
-#define IRQ_U300_GPIO_PORT6            55
-#define U300_VIC_IRQS_END              56
+#define IRQ_U300_ISP_F0                        46
+#define IRQ_U300_ISP_F1                        47
+#define IRQ_U300_ISP_F2                        48
+#define IRQ_U300_ISP_F3                        49
+#define IRQ_U300_ISP_F4                        50
+#define IRQ_U300_GPIO_PORT3            51
+#define IRQ_U300_SYSCON_PLL_LOCK       52
+#define IRQ_U300_UART1                 53
+#define IRQ_U300_GPIO_PORT4            54
+#define IRQ_U300_GPIO_PORT5            55
+#define IRQ_U300_GPIO_PORT6            56
+#define U300_VIC_IRQS_END              57
 #endif
 
 /* The DB3210-specific interrupt lines */
 #ifdef CONFIG_MACH_U300_BS365
-#define IRQ_U300_GPIO_PORT3            35
-#define IRQ_U300_GPIO_PORT4            36
-#define IRQ_U300_WDOG                  37
-#define IRQ_U300_EVHIST                        38
-#define IRQ_U300_MSPRO                 39
-#define IRQ_U300_MMCSD_MCIINTR0                40
-#define IRQ_U300_MMCSD_MCIINTR1                41
-#define IRQ_U300_I2C0                  42
-#define IRQ_U300_I2C1                  43
-#define IRQ_U300_RTC                   44
-#define IRQ_U300_NFIF                  45
-#define IRQ_U300_NFIF2                 46
-#define IRQ_U300_SYSCON_PLL_LOCK       47
-#define U300_VIC_IRQS_END              48
+#define IRQ_U300_GPIO_PORT3            36
+#define IRQ_U300_GPIO_PORT4            37
+#define IRQ_U300_WDOG                  38
+#define IRQ_U300_EVHIST                        39
+#define IRQ_U300_MSPRO                 40
+#define IRQ_U300_MMCSD_MCIINTR0                41
+#define IRQ_U300_MMCSD_MCIINTR1                42
+#define IRQ_U300_I2C0                  43
+#define IRQ_U300_I2C1                  44
+#define IRQ_U300_RTC                   45
+#define IRQ_U300_NFIF                  46
+#define IRQ_U300_NFIF2                 47
+#define IRQ_U300_SYSCON_PLL_LOCK       48
+#define U300_VIC_IRQS_END              49
 #endif
 
 /* Maximum 8*7 GPIO lines */
 #define IRQ_U300_GPIO_END              (U300_VIC_IRQS_END)
 #endif
 
-#define NR_IRQS                                (IRQ_U300_GPIO_END)
+#define NR_IRQS                                (IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
 
 #endif
index 880d02ec89d4e598afb2ef6014ab7f03e9b0a56f..ef7099eea0f29a6a593106c482154b37a2d1a4e5 100644 (file)
@@ -17,6 +17,7 @@ config UX500_SOC_DB5500
 config UX500_SOC_DB8500
        bool
        select MFD_DB8500_PRCMU
+       select REGULATOR
        select REGULATOR_DB8500_PRCMU
        select CPU_FREQ_TABLE if CPU_FREQ
 
index 2b2d51caf9d8b9f4db2e62c1eaa7a596b3313546..0127490218cdfc4bc00b107be2816a84703d6a4f 100644 (file)
@@ -168,7 +168,7 @@ static ssize_t mbox_read_fifo(struct device *dev,
        return sprintf(buf, "0x%X\n", mbox_value);
 }
 
-static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
+static DEVICE_ATTR(fifo, S_IWUSR | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
 
 static int mbox_show(struct seq_file *s, void *data)
 {
index d2058ef8345fd4518874d2ab409ae3daa376d5df..eff5842f6232a8f7d0af9e29a87477508ce9f455 100644 (file)
@@ -99,7 +99,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         */
        write_pen_release(cpu_logical_map(cpu));
 
-       gic_raise_softirq(cpumask_of(cpu), 1);
+       smp_send_reschedule(cpu);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
index a6e23f4645289675cf3be0501e90650772064b62..d2268be8c34ca5762945e1954d832655da11d591 100644 (file)
@@ -190,7 +190,7 @@ static struct resource pre_mem = {
        .flags  = IORESOURCE_MEM | IORESOURCE_PREFETCH,
 };
 
-static int __init pci_versatile_setup_resources(struct list_head *resources)
+static int __init pci_versatile_setup_resources(struct pci_sys_data *sys)
 {
        int ret = 0;
 
@@ -218,9 +218,9 @@ static int __init pci_versatile_setup_resources(struct list_head *resources)
         * the mem resource for this bus
         * the prefetch mem resource for this bus
         */
-       pci_add_resource_offset(resources, &io_mem, sys->io_offset);
-       pci_add_resource_offset(resources, &non_mem, sys->mem_offset);
-       pci_add_resource_offset(resources, &pre_mem, sys->mem_offset);
+       pci_add_resource_offset(&sys->resources, &io_mem, sys->io_offset);
+       pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset);
+       pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset);
 
        goto out;
 
@@ -249,7 +249,7 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
 
        if (nr == 0) {
                sys->mem_offset = 0;
-               ret = pci_versatile_setup_resources(&sys->resources);
+               ret = pci_versatile_setup_resources(sys);
                if (ret < 0) {
                        printk("pci_versatile_setup: resources... oops?\n");
                        goto out;
index 7edef9121632ed94c8e477d64385625040da92a7..7c8a7d8467bf0b40fff40eb01a6533a83e10a18f 100644 (file)
@@ -723,7 +723,7 @@ config CPU_HIGH_VECTOR
        bool "Select the High exception vector"
        help
          Say Y here to select high exception vector(0xFFFF0000~).
-         The exception vector can be vary depending on the platform
+         The exception vector can vary depending on the platform
          design in nommu mode. If your platform needs to select
          high exception vector, say Y.
          Otherwise or if you are unsure, say N, and the low exception
index ff1f7cc11f87bdee1509757c7cd0c3cf7c105754..80741992a9fcff0b98d963ec3465bf407c51c5f6 100644 (file)
@@ -26,18 +26,23 @@ ENTRY(v6_early_abort)
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
 /*
- * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR (erratum 326103).
- * The test below covers all the write situations, including Java bytecodes
+ * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR.
  */
-       bic     r1, r1, #1 << 11                @ clear bit 11 of FSR
+#ifdef CONFIG_ARM_ERRATA_326103
+       ldr     ip, =0x4107b36
+       mrc     p15, 0, r3, c0, c0, 0           @ get processor id
+       teq     ip, r3, lsr #4                  @ r0 ARM1136?
+       bne     do_DataAbort
        tst     r5, #PSR_J_BIT                  @ Java?
+       tsteq   r5, #PSR_T_BIT                  @ Thumb?
        bne     do_DataAbort
-       do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
-       ldreq   r3, [r4]                        @ read aborted ARM instruction
+       bic     r1, r1, #1 << 11                @ clear bit 11 of FSR
+       ldr     r3, [r4]                        @ read aborted ARM instruction
 #ifdef CONFIG_CPU_ENDIAN_BE8
-       reveq   r3, r3
+       rev     r3, r3
 #endif
        do_ldrd_abort tmp=ip, insn=r3
        tst     r3, #1 << 20                    @ L = 0 -> write
        orreq   r1, r1, #1 << 11                @ yes.
+#endif
        b       do_DataAbort
index a53fd2aaa2f4b59397bfa01847b22cd991bcdd8b..2a8e380501e81a2c0bcaf08c8d018f0c9f20050c 100644 (file)
@@ -32,6 +32,7 @@ static void __iomem *l2x0_base;
 static DEFINE_RAW_SPINLOCK(l2x0_lock);
 static u32 l2x0_way_mask;      /* Bitmask of active ways */
 static u32 l2x0_size;
+static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
 
 struct l2x0_regs l2x0_saved_regs;
 
@@ -61,12 +62,7 @@ static inline void cache_sync(void)
 {
        void __iomem *base = l2x0_base;
 
-#ifdef CONFIG_PL310_ERRATA_753970
-       /* write to an unmmapped register */
-       writel_relaxed(0, base + L2X0_DUMMY_REG);
-#else
-       writel_relaxed(0, base + L2X0_CACHE_SYNC);
-#endif
+       writel_relaxed(0, base + sync_reg_offset);
        cache_wait(base + L2X0_CACHE_SYNC, 1);
 }
 
@@ -85,10 +81,13 @@ static inline void l2x0_inv_line(unsigned long addr)
 }
 
 #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
+static inline void debug_writel(unsigned long val)
+{
+       if (outer_cache.set_debug)
+               outer_cache.set_debug(val);
+}
 
-#define debug_writel(val)      outer_cache.set_debug(val)
-
-static void l2x0_set_debug(unsigned long val)
+static void pl310_set_debug(unsigned long val)
 {
        writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
 }
@@ -98,7 +97,7 @@ static inline void debug_writel(unsigned long val)
 {
 }
 
-#define l2x0_set_debug NULL
+#define pl310_set_debug        NULL
 #endif
 
 #ifdef CONFIG_PL310_ERRATA_588369
@@ -331,6 +330,11 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
                else
                        ways = 8;
                type = "L310";
+#ifdef CONFIG_PL310_ERRATA_753970
+               /* Unmapped register. */
+               sync_reg_offset = L2X0_DUMMY_REG;
+#endif
+               outer_cache.set_debug = pl310_set_debug;
                break;
        case L2X0_CACHE_ID_PART_L210:
                ways = (aux >> 13) & 0xf;
@@ -379,7 +383,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
        outer_cache.flush_all = l2x0_flush_all;
        outer_cache.inv_all = l2x0_inv_all;
        outer_cache.disable = l2x0_disable;
-       outer_cache.set_debug = l2x0_set_debug;
 
        printk(KERN_INFO "%s cache controller enabled\n", type);
        printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
index 9055b5a84ec5614914ab19dc5ed54004a821370f..f0746753336546448a3512e297444fe3137f1c07 100644 (file)
@@ -320,7 +320,7 @@ retry:
         */
 
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr);
-       if (flags & FAULT_FLAG_ALLOW_RETRY) {
+       if (!(fault & VM_FAULT_ERROR) && flags & FAULT_FLAG_ALLOW_RETRY) {
                if (fault & VM_FAULT_MAJOR) {
                        tsk->maj_flt++;
                        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
index 595079fa9d1d2eb342afae05f3b29a4395b87331..8f5813bbffb560b15b44974ff3543f0b5457e026 100644 (file)
@@ -293,11 +293,11 @@ EXPORT_SYMBOL(pfn_valid);
 #endif
 
 #ifndef CONFIG_SPARSEMEM
-static void arm_memory_present(void)
+static void __init arm_memory_present(void)
 {
 }
 #else
-static void arm_memory_present(void)
+static void __init arm_memory_present(void)
 {
        struct memblock_region *reg;
 
index b86f8933ff918908e107afe40553388e0e207988..2c7cf2f9c837263504b139e44137ac027724bd0e 100644 (file)
@@ -618,8 +618,8 @@ static void __init alloc_init_section(pud_t *pud, unsigned long addr,
        }
 }
 
-static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
-       unsigned long phys, const struct mem_type *type)
+static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
+       unsigned long end, unsigned long phys, const struct mem_type *type)
 {
        pud_t *pud = pud_offset(pgd, addr);
        unsigned long next;
index 6486d2f253cdd9dba5758d4402b11746dc0bda0a..d51225f90ae2d5d3af909ec87d29910bea4f23d5 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/sections.h>
 #include <asm/page.h>
 #include <asm/setup.h>
+#include <asm/traps.h>
 #include <asm/mach/arch.h>
 
 #include "mm.h"
@@ -39,6 +40,7 @@ void __init sanity_check_meminfo(void)
  */
 void __init paging_init(struct machine_desc *mdesc)
 {
+       early_trap_init((void *)CONFIG_VECTORS_BASE);
        bootmem_init();
 }
 
index f1c8486f750169b0ffe8974b35e1b5555e53ad32..c2e2b66f72b5cd08648085c28ffc5d8c2ee8359a 100644 (file)
@@ -254,6 +254,18 @@ __v7_setup:
        ldr     r6, =NMRR                       @ NMRR
        mcr     p15, 0, r5, c10, c2, 0          @ write PRRR
        mcr     p15, 0, r6, c10, c2, 1          @ write NMRR
+#endif
+#ifndef CONFIG_ARM_THUMBEE
+       mrc     p15, 0, r0, c0, c1, 0           @ read ID_PFR0 for ThumbEE
+       and     r0, r0, #(0xf << 12)            @ ThumbEE enabled field
+       teq     r0, #(1 << 12)                  @ check if ThumbEE is present
+       bne     1f
+       mov     r5, #0
+       mcr     p14, 6, r5, c1, c0, 0           @ Initialize TEEHBR to 0
+       mrc     p14, 6, r0, c0, c0, 0           @ load TEECR
+       orr     r0, r0, #1                      @ set the 1st bit in order to
+       mcr     p14, 6, r0, c0, c0, 0           @ stop userspace TEEHBR access
+1:
 #endif
        adr     r5, v7_crval
        ldmia   r5, {r5, r6}
index d1e31fa1b0c3435a40a2039e592de72a6ee023af..5cac2c540f4f86b6d73ecd5b24617e4ee9b27705 100644 (file)
@@ -80,7 +80,7 @@ static struct smsc911x_platform_config smsc911x_config = {
 
 static struct platform_device smsc_lan9217_device = {
        .name = "smsc911x",
-       .id = 0,
+       .id = -1,
        .dev = {
                .platform_data = &smsc911x_config,
        },
index ce1e9b96ba1a34903f79eed02c65122c98454a0b..ad95c7a5d00926f933864cb9a9285e95ae1f7f10 100644 (file)
@@ -17,6 +17,7 @@ config ARCH_OMAP1
        select IRQ_DOMAIN
        select HAVE_IDE
        select NEED_MACH_MEMORY_H
+       select NEED_MACH_IO_H if PCCARD
        help
          "Systems based on omap7xx, omap15xx or omap16xx"
 
index 56b6f8b7053e3f842ce8a67bdea2d3cb8663b11b..62ec5c452792706407922b5ea0173009f6247622 100644 (file)
@@ -398,32 +398,6 @@ struct clk dummy_ck = {
        .ops    = &clkops_null,
 };
 
-#ifdef CONFIG_CPU_FREQ
-void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
-{
-       unsigned long flags;
-
-       if (!arch_clock || !arch_clock->clk_init_cpufreq_table)
-               return;
-
-       spin_lock_irqsave(&clockfw_lock, flags);
-       arch_clock->clk_init_cpufreq_table(table);
-       spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-
-void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
-{
-       unsigned long flags;
-
-       if (!arch_clock || !arch_clock->clk_exit_cpufreq_table)
-               return;
-
-       spin_lock_irqsave(&clockfw_lock, flags);
-       arch_clock->clk_exit_cpufreq_table(table);
-       spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-#endif
-
 /*
  *
  */
@@ -441,6 +415,8 @@ static int __init clk_disable_unused(void)
                return 0;
 
        pr_info("clock: disabling unused clocks to save power\n");
+
+       spin_lock_irqsave(&clockfw_lock, flags);
        list_for_each_entry(ck, &clocks, node) {
                if (ck->ops == &clkops_null)
                        continue;
@@ -448,10 +424,9 @@ static int __init clk_disable_unused(void)
                if (ck->usecount > 0 || !ck->enable_reg)
                        continue;
 
-               spin_lock_irqsave(&clockfw_lock, flags);
                arch_clock->clk_disable_unused(ck);
-               spin_unlock_irqrestore(&clockfw_lock, flags);
        }
+       spin_unlock_irqrestore(&clockfw_lock, flags);
 
        return 0;
 }
index ecdb3da0dea93704086df1f83dff342813c3afd3..c58d896cd5c39dba0ab5950d4fb69a657e0a5d0a 100644 (file)
@@ -916,6 +916,13 @@ void omap_start_dma(int lch)
                        l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
        l |= OMAP_DMA_CCR_EN;
 
+       /*
+        * As dma_write() uses IO accessors which are weakly ordered, there
+        * is no guarantee that data in coherent DMA memory will be visible
+        * to the DMA device.  Add a memory barrier here to ensure that any
+        * such data is visible prior to enabling DMA.
+        */
+       mb();
        p->dma_write(l, CCR, lch);
 
        dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
@@ -965,6 +972,13 @@ void omap_stop_dma(int lch)
                p->dma_write(l, CCR, lch);
        }
 
+       /*
+        * Ensure that data transferred by DMA is visible to any access
+        * after DMA has been disabled.  This is important for coherent
+        * DMA regions.
+        */
+       mb();
+
        if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
                int next_lch, cur_lch = lch;
                char dma_chan_link_map[dma_lch_count];
index 240a7b9fd946ed95de93fd8b1685e4207acada20..d0ef57c1d71b8d674fd649342f3241eed5d0ba53 100644 (file)
@@ -272,8 +272,6 @@ struct clk {
 #endif
 };
 
-struct cpufreq_frequency_table;
-
 struct clk_functions {
        int             (*clk_enable)(struct clk *clk);
        void            (*clk_disable)(struct clk *clk);
@@ -283,10 +281,6 @@ struct clk_functions {
        void            (*clk_allow_idle)(struct clk *clk);
        void            (*clk_deny_idle)(struct clk *clk);
        void            (*clk_disable_unused)(struct clk *clk);
-#ifdef CONFIG_CPU_FREQ
-       void            (*clk_init_cpufreq_table)(struct cpufreq_frequency_table **);
-       void            (*clk_exit_cpufreq_table)(struct cpufreq_frequency_table **);
-#endif
 };
 
 extern int mpurate;
@@ -301,10 +295,6 @@ extern void recalculate_root_clocks(void);
 extern unsigned long followparent_recalc(struct clk *clk);
 extern void clk_enable_init_clocks(void);
 unsigned long omap_fixed_divisor_recalc(struct clk *clk);
-#ifdef CONFIG_CPU_FREQ
-extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
-extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
-#endif
 extern struct clk *omap_clk_get_by_name(const char *name);
 extern int omap_clk_enable_autoidle_all(void);
 extern int omap_clk_disable_autoidle_all(void);
index 9e8e63d52aab9515a67882c534c7b563e29bbe9a..3f26db4ee8e671531bb4239acc60852cb0448295 100644 (file)
@@ -47,17 +47,17 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
  * with the original PRCM protocol defined for OMAP2420
  */
 #define SYSC_TYPE1_MIDLEMODE_SHIFT     12
-#define SYSC_TYPE1_MIDLEMODE_MASK      (0x3 << SYSC_MIDLEMODE_SHIFT)
+#define SYSC_TYPE1_MIDLEMODE_MASK      (0x3 << SYSC_TYPE1_MIDLEMODE_SHIFT)
 #define SYSC_TYPE1_CLOCKACTIVITY_SHIFT 8
-#define SYSC_TYPE1_CLOCKACTIVITY_MASK  (0x3 << SYSC_CLOCKACTIVITY_SHIFT)
+#define SYSC_TYPE1_CLOCKACTIVITY_MASK  (0x3 << SYSC_TYPE1_CLOCKACTIVITY_SHIFT)
 #define SYSC_TYPE1_SIDLEMODE_SHIFT     3
-#define SYSC_TYPE1_SIDLEMODE_MASK      (0x3 << SYSC_SIDLEMODE_SHIFT)
+#define SYSC_TYPE1_SIDLEMODE_MASK      (0x3 << SYSC_TYPE1_SIDLEMODE_SHIFT)
 #define SYSC_TYPE1_ENAWAKEUP_SHIFT     2
-#define SYSC_TYPE1_ENAWAKEUP_MASK      (1 << SYSC_ENAWAKEUP_SHIFT)
+#define SYSC_TYPE1_ENAWAKEUP_MASK      (1 << SYSC_TYPE1_ENAWAKEUP_SHIFT)
 #define SYSC_TYPE1_SOFTRESET_SHIFT     1
-#define SYSC_TYPE1_SOFTRESET_MASK      (1 << SYSC_SOFTRESET_SHIFT)
+#define SYSC_TYPE1_SOFTRESET_MASK      (1 << SYSC_TYPE1_SOFTRESET_SHIFT)
 #define SYSC_TYPE1_AUTOIDLE_SHIFT      0
-#define SYSC_TYPE1_AUTOIDLE_MASK       (1 << SYSC_AUTOIDLE_SHIFT)
+#define SYSC_TYPE1_AUTOIDLE_MASK       (1 << SYSC_TYPE1_AUTOIDLE_SHIFT)
 
 /*
  * OCP SYSCONFIG bit shifts/masks TYPE2. These are for IPs compliant
@@ -305,6 +305,7 @@ struct omap_hwmod_sysc_fields {
  * @rev_offs: IP block revision register offset (from module base addr)
  * @sysc_offs: OCP_SYSCONFIG register offset (from module base addr)
  * @syss_offs: OCP_SYSSTATUS register offset (from module base addr)
+ * @srst_udelay: Delay needed after doing a softreset in usecs
  * @idlemodes: One or more of {SIDLE,MSTANDBY}_{OFF,FORCE,SMART}
  * @sysc_flags: SYS{C,S}_HAS* flags indicating SYSCONFIG bits supported
  * @clockact: the default value of the module CLOCKACTIVITY bits
@@ -330,9 +331,10 @@ struct omap_hwmod_class_sysconfig {
        u16 sysc_offs;
        u16 syss_offs;
        u16 sysc_flags;
+       struct omap_hwmod_sysc_fields *sysc_fields;
+       u8 srst_udelay;
        u8 idlemodes;
        u8 clockact;
-       struct omap_hwmod_sysc_fields *sysc_fields;
 };
 
 /**
index eec98afa0f8328b2023f855879fa8a2ff34890ac..f9a8c5341ee93e41138f2adb5a6a6f4ce09d48d5 100644 (file)
@@ -348,7 +348,6 @@ u32 omap3_configure_core_dpll(u32 m2, u32 unlock_dll, u32 f, u32 inc,
                        sdrc_actim_ctrl_b_1, sdrc_mr_1);
 }
 
-#ifdef CONFIG_PM
 void omap3_sram_restore_context(void)
 {
        omap_sram_ceil = omap_sram_base + omap_sram_size;
@@ -358,17 +357,18 @@ void omap3_sram_restore_context(void)
                               omap3_sram_configure_core_dpll_sz);
        omap_push_sram_idle();
 }
-#endif /* CONFIG_PM */
-
-#endif /* CONFIG_ARCH_OMAP3 */
 
 static inline int omap34xx_sram_init(void)
 {
-#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
        omap3_sram_restore_context();
-#endif
        return 0;
 }
+#else
+static inline int omap34xx_sram_init(void)
+{
+       return 0;
+}
+#endif /* CONFIG_ARCH_OMAP3 */
 
 static inline int am33xx_sram_init(void)
 {
index 71553f410016057315a51b27c28bca46d8bfd93e..a0ffc77da8091a3ab962b8570a7592e9d254bfb5 100644 (file)
@@ -302,6 +302,7 @@ comment "Power management"
 config SAMSUNG_PM_DEBUG
        bool "S3C2410 PM Suspend debug"
        depends on PM
+       select DEBUG_LL
        help
          Say Y here if you want verbose debugging from the PM Suspend and
          Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
index 317e246ffc5604e1c0712054b90c5da23654a6da..e834c5ef437c3c857cfe02d55f84df3307fa35e8 100644 (file)
@@ -18,6 +18,8 @@
 #ifndef __PLAT_S3C_SDHCI_H
 #define __PLAT_S3C_SDHCI_H __FILE__
 
+#include <plat/devs.h>
+
 struct platform_device;
 struct mmc_host;
 struct mmc_card;
@@ -356,4 +358,30 @@ static inline void exynos4_default_sdhci3(void) { }
 
 #endif /* CONFIG_EXYNOS4_SETUP_SDHCI */
 
+static inline void s3c_sdhci_setname(int id, char *name)
+{
+       switch (id) {
+#ifdef CONFIG_S3C_DEV_HSMMC
+       case 0:
+               s3c_device_hsmmc0.name = name;
+               break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC1
+       case 1:
+               s3c_device_hsmmc1.name = name;
+               break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC2
+       case 2:
+               s3c_device_hsmmc2.name = name;
+               break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC3
+       case 3:
+               s3c_device_hsmmc3.name = name;
+               break;
+#endif
+       }
+}
+
 #endif /* __PLAT_S3C_SDHCI_H */
index 858748eaa144f91c7f9b4c88fbc8bb83a8d419d7..bc683b8219b5bf3715345742b0d41d4746e4746b 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/user.h>
 
 #include <asm/cp15.h>
 #include <asm/cputype.h>
@@ -528,6 +530,103 @@ void vfp_flush_hwstate(struct thread_info *thread)
        put_cpu();
 }
 
+/*
+ * Save the current VFP state into the provided structures and prepare
+ * for entry into a new function (signal handler).
+ */
+int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
+                                   struct user_vfp_exc __user *ufp_exc)
+{
+       struct thread_info *thread = current_thread_info();
+       struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
+       int err = 0;
+
+       /* Ensure that the saved hwstate is up-to-date. */
+       vfp_sync_hwstate(thread);
+
+       /*
+        * Copy the floating point registers. There can be unused
+        * registers see asm/hwcap.h for details.
+        */
+       err |= __copy_to_user(&ufp->fpregs, &hwstate->fpregs,
+                             sizeof(hwstate->fpregs));
+       /*
+        * Copy the status and control register.
+        */
+       __put_user_error(hwstate->fpscr, &ufp->fpscr, err);
+
+       /*
+        * Copy the exception registers.
+        */
+       __put_user_error(hwstate->fpexc, &ufp_exc->fpexc, err);
+       __put_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
+       __put_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err);
+
+       if (err)
+               return -EFAULT;
+
+       /* Ensure that VFP is disabled. */
+       vfp_flush_hwstate(thread);
+
+       /*
+        * As per the PCS, clear the length and stride bits for function
+        * entry.
+        */
+       hwstate->fpscr &= ~(FPSCR_LENGTH_MASK | FPSCR_STRIDE_MASK);
+
+       /*
+        * Disable VFP in the hwstate so that we can detect if it gets
+        * used.
+        */
+       hwstate->fpexc &= ~FPEXC_EN;
+       return 0;
+}
+
+/* Sanitise and restore the current VFP state from the provided structures. */
+int vfp_restore_user_hwstate(struct user_vfp __user *ufp,
+                            struct user_vfp_exc __user *ufp_exc)
+{
+       struct thread_info *thread = current_thread_info();
+       struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
+       unsigned long fpexc;
+       int err = 0;
+
+       /*
+        * If VFP has been used, then disable it to avoid corrupting
+        * the new thread state.
+        */
+       if (hwstate->fpexc & FPEXC_EN)
+               vfp_flush_hwstate(thread);
+
+       /*
+        * Copy the floating point registers. There can be unused
+        * registers see asm/hwcap.h for details.
+        */
+       err |= __copy_from_user(&hwstate->fpregs, &ufp->fpregs,
+                               sizeof(hwstate->fpregs));
+       /*
+        * Copy the status and control register.
+        */
+       __get_user_error(hwstate->fpscr, &ufp->fpscr, err);
+
+       /*
+        * Sanitise and restore the exception registers.
+        */
+       __get_user_error(fpexc, &ufp_exc->fpexc, err);
+
+       /* Ensure the VFP is enabled. */
+       fpexc |= FPEXC_EN;
+
+       /* Ensure FPINST2 is invalid and the exception flag is cleared. */
+       fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
+       hwstate->fpexc = fpexc;
+
+       __get_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
+       __get_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err);
+
+       return err ? -EFAULT : 0;
+}
+
 /*
  * VFP hardware can lose all context when a CPU goes offline.
  * As we will be running in SMP mode with CPU hotplug, we will save the
index 808001c9cf8c65f14651e72ad2ed23135c7aec53..0961275373dbb6afb355edccbcbeaa24c611ec5a 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __ASM_AVR32_BARRIER_H
 #define __ASM_AVR32_BARRIER_H
 
+#define nop()                  asm volatile("nop")
+
 #define mb()                   asm volatile("" : : : "memory")
 #define rmb()                  mb()
 #define wmb()                  asm volatile("sync 0" : : : "memory")
diff --git a/arch/avr32/include/asm/special_insns.h b/arch/avr32/include/asm/special_insns.h
deleted file mode 100644 (file)
index f922218..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2004-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_AVR32_SPECIAL_INSNS_H
-#define __ASM_AVR32_SPECIAL_INSNS_H
-
-#define nop() asm volatile("nop")
-
-#endif /* __ASM_AVR32_SPECIAL_INSNS_H */
index 71733866cb4f21c308d5e926b59d261576666741..70742ec997f86eb7ec06304da5715d3acd03569b 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/types.h>
 #include <linux/serial.h>
 #include <linux/platform_data/macb.h>
-#include <linux/platform_data/atmel_nand.h>
+#include <linux/platform_data/atmel.h>
 
 #define GPIO_PIN_NONE  (-1)
 
index c1269a1085e16fa12b7e5377500b7ef4da829a47..373a6902d8fa6c7955732b1d1cb2d5911c24a431 100644 (file)
@@ -823,7 +823,7 @@ config CACHELINE_ALIGNED_L1
        bool "Locate cacheline_aligned data to L1 Data Memory"
        default y if !BF54x
        default n if BF54x
-       depends on !SMP && !BF531
+       depends on !SMP && !BF531 && !CRC32
        help
          If enabled, cacheline_aligned data is linked
          into L1 data memory. (less latency)
index 9ccc18a6b4dfaaee66db8da9ed864f2f890243ec..90b1753236446fcef1ce1225abc0decd92dd092d 100644 (file)
@@ -147,6 +147,7 @@ CONFIG_USB_OTG_BLACKLIST_HUB=y
 CONFIG_USB_MON=y
 CONFIG_USB_MUSB_HDRC=y
 CONFIG_USB_MUSB_BLACKFIN=y
+CONFIG_MUSB_PIO_ONLY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_RTC_CLASS=y
index ba2484f4cb2a07e33f62d76666b04538dd80a8cf..c05868cc61c1aacc290ecfacfebb048cf032bc6f 100644 (file)
@@ -122,7 +122,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
                        (unsigned long)(n), sizeof(*(ptr))))
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 
-#include <asm-generic/cmpxchg.h>
+#define cmpxchg(ptr, o, n)     cmpxchg_local((ptr), (o), (n))
+#define cmpxchg64(ptr, o, n)   cmpxchg64_local((ptr), (o), (n))
 
 #endif /* !CONFIG_SMP */
 
index 5a25856381fff3257fbeba2e52aa85a0e4e21b1a..12d3571b523232db7a230b853c87deb802a24062 100644 (file)
@@ -244,16 +244,26 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
        return -EINVAL;
 }
 
-static inline int gpio_get_value(unsigned gpio)
+static inline int __gpio_get_value(unsigned gpio)
 {
        return bfin_gpio_get_value(gpio);
 }
 
-static inline void gpio_set_value(unsigned gpio, int value)
+static inline void __gpio_set_value(unsigned gpio, int value)
 {
        return bfin_gpio_set_value(gpio, value);
 }
 
+static inline int gpio_get_value(unsigned gpio)
+{
+       return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       return __gpio_set_value(gpio, value);
+}
+
 static inline int gpio_to_irq(unsigned gpio)
 {
        if (likely(gpio < MAX_BLACKFIN_GPIOS))
index 1633a6f306c0e1390fedf5dd12dd805c5ac9c704..85038f54354dc78ac514655972d021e4a0cb63e6 100644 (file)
@@ -38,7 +38,7 @@ static struct platform_device rtc_device = {
        .name = "rtc-bfin",
        .id   = -1,
 };
-#endif
+#endif /* CONFIG_RTC_DRV_BFIN */
 
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 #ifdef CONFIG_SERIAL_BFIN_UART0
@@ -100,7 +100,7 @@ static struct platform_device bfin_uart0_device = {
                .platform_data = &bfin_uart0_peripherals, /* Passed to driver */
        },
 };
-#endif
+#endif /* CONFIG_SERIAL_BFIN_UART0 */
 #ifdef CONFIG_SERIAL_BFIN_UART1
 static struct resource bfin_uart1_resources[] = {
        {
@@ -148,7 +148,7 @@ static struct platform_device bfin_uart1_device = {
                .platform_data = &bfin_uart1_peripherals, /* Passed to driver */
        },
 };
-#endif
+#endif /* CONFIG_SERIAL_BFIN_UART1 */
 #ifdef CONFIG_SERIAL_BFIN_UART2
 static struct resource bfin_uart2_resources[] = {
        {
@@ -196,8 +196,8 @@ static struct platform_device bfin_uart2_device = {
                .platform_data = &bfin_uart2_peripherals, /* Passed to driver */
        },
 };
-#endif
-#endif
+#endif /* CONFIG_SERIAL_BFIN_UART2 */
+#endif /* CONFIG_SERIAL_BFIN */
 
 #if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
 #ifdef CONFIG_BFIN_SIR0
@@ -224,7 +224,7 @@ static struct platform_device bfin_sir0_device = {
        .num_resources = ARRAY_SIZE(bfin_sir0_resources),
        .resource = bfin_sir0_resources,
 };
-#endif
+#endif /* CONFIG_BFIN_SIR0 */
 #ifdef CONFIG_BFIN_SIR1
 static struct resource bfin_sir1_resources[] = {
        {
@@ -249,7 +249,7 @@ static struct platform_device bfin_sir1_device = {
        .num_resources = ARRAY_SIZE(bfin_sir1_resources),
        .resource = bfin_sir1_resources,
 };
-#endif
+#endif /* CONFIG_BFIN_SIR1 */
 #ifdef CONFIG_BFIN_SIR2
 static struct resource bfin_sir2_resources[] = {
        {
@@ -274,8 +274,8 @@ static struct platform_device bfin_sir2_device = {
        .num_resources = ARRAY_SIZE(bfin_sir2_resources),
        .resource = bfin_sir2_resources,
 };
-#endif
-#endif
+#endif /* CONFIG_BFIN_SIR2 */
+#endif /* CONFIG_BFIN_SIR */
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
 #ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
@@ -311,7 +311,7 @@ static struct platform_device bfin_sport0_uart_device = {
                .platform_data = &bfin_sport0_peripherals, /* Passed to driver */
        },
 };
-#endif
+#endif /* CONFIG_SERIAL_BFIN_SPORT0_UART */
 #ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
 static struct resource bfin_sport1_uart_resources[] = {
        {
@@ -345,7 +345,7 @@ static struct platform_device bfin_sport1_uart_device = {
                .platform_data = &bfin_sport1_peripherals, /* Passed to driver */
        },
 };
-#endif
+#endif /* CONFIG_SERIAL_BFIN_SPORT1_UART */
 #ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
 static struct resource bfin_sport2_uart_resources[] = {
        {
@@ -379,7 +379,7 @@ static struct platform_device bfin_sport2_uart_device = {
                .platform_data = &bfin_sport2_peripherals, /* Passed to driver */
        },
 };
-#endif
+#endif /* CONFIG_SERIAL_BFIN_SPORT2_UART */
 #ifdef CONFIG_SERIAL_BFIN_SPORT3_UART
 static struct resource bfin_sport3_uart_resources[] = {
        {
@@ -413,8 +413,8 @@ static struct platform_device bfin_sport3_uart_device = {
                .platform_data = &bfin_sport3_peripherals, /* Passed to driver */
        },
 };
-#endif
-#endif
+#endif /* CONFIG_SERIAL_BFIN_SPORT3_UART */
+#endif /* CONFIG_SERIAL_BFIN_SPORT */
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
 static unsigned short bfin_can_peripherals[] = {
@@ -452,7 +452,7 @@ static struct platform_device bfin_can_device = {
                .platform_data = &bfin_can_peripherals, /* Passed to driver */
        },
 };
-#endif
+#endif /* CONFIG_CAN_BFIN */
 
 /*
  *  USB-LAN EzExtender board
@@ -488,7 +488,7 @@ static struct platform_device smc91x_device = {
                .platform_data  = &smc91x_info,
        },
 };
-#endif
+#endif /* CONFIG_SMC91X */
 
 #if defined(CONFIG_SPI_BFIN5XX) || defined(CONFIG_SPI_BFIN5XX_MODULE)
 /* all SPI peripherals info goes here */
@@ -518,7 +518,8 @@ static struct flash_platform_data bfin_spi_flash_data = {
 static struct bfin5xx_spi_chip spi_flash_chip_info = {
        .enable_dma = 0,         /* use dma transfer with this chip*/
 };
-#endif
+#endif /* CONFIG_MTD_M25P80 */
+#endif /* CONFIG_SPI_BFIN5XX */
 
 #if defined(CONFIG_TOUCHSCREEN_AD7879) || defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
 #include <linux/spi/ad7879.h>
@@ -535,7 +536,7 @@ static const struct ad7879_platform_data bfin_ad7879_ts_info = {
        .gpio_export            = 1,    /* Export GPIO to gpiolib */
        .gpio_base              = -1,   /* Dynamic allocation */
 };
-#endif
+#endif /* CONFIG_TOUCHSCREEN_AD7879 */
 
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
 #include <asm/bfin-lq035q1.h>
@@ -564,7 +565,7 @@ static struct platform_device bfin_lq035q1_device = {
                .platform_data = &bfin_lq035q1_data,
        },
 };
-#endif
+#endif /* CONFIG_FB_BFIN_LQ035Q1 */
 
 static struct spi_board_info bf538_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
@@ -579,7 +580,7 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
                .controller_data = &spi_flash_chip_info,
                .mode = SPI_MODE_3,
        },
-#endif
+#endif /* CONFIG_MTD_M25P80 */
 #if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
        {
                .modalias = "ad7879",
@@ -590,7 +591,7 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
                .chip_select = 1,
                .mode = SPI_CPHA | SPI_CPOL,
        },
-#endif
+#endif /* CONFIG_TOUCHSCREEN_AD7879_SPI */
 #if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
        {
                .modalias = "bfin-lq035q1-spi",
@@ -599,7 +600,7 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
                .chip_select = 2,
                .mode = SPI_CPHA | SPI_CPOL,
        },
-#endif
+#endif /* CONFIG_FB_BFIN_LQ035Q1 */
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
        {
                .modalias = "spidev",
@@ -607,7 +608,7 @@ static struct spi_board_info bf538_spi_board_info[] __initdata = {
                .bus_num = 0,
                .chip_select = 1,
        },
-#endif
+#endif /* CONFIG_SPI_SPIDEV */
 };
 
 /* SPI (0) */
@@ -716,8 +717,6 @@ static struct platform_device bf538_spi_master2 = {
                },
 };
 
-#endif  /* spi master and devices */
-
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
 static struct resource bfin_twi0_resource[] = {
        [0] = {
@@ -759,8 +758,8 @@ static struct platform_device i2c_bfin_twi1_device = {
        .num_resources = ARRAY_SIZE(bfin_twi1_resource),
        .resource = bfin_twi1_resource,
 };
-#endif
-#endif
+#endif /* CONFIG_BF542 */
+#endif /* CONFIG_I2C_BLACKFIN_TWI */
 
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 #include <linux/gpio_keys.h>
index f13b78d5e1ca2c8f170357dd39c35d124f445daf..ab4577f93d96c97f347936a33a75dce2825df0c4 100644 (file)
 /* This number is used when no interrupt has been assigned */
 #define NO_IRQ         0
 
-struct irq_data;
-extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
-extern irq_hw_number_t virq_to_hw(unsigned int virq);
-
 extern void __init init_pic_c64xplus(void);
 
 extern void init_IRQ(void);
index 65b8ddf54b446ca904780dbc02a2e181fde037b1..c90fb5e82ad7b829fb9be3a9d562118374eff901 100644 (file)
@@ -130,16 +130,3 @@ int arch_show_interrupts(struct seq_file *p, int prec)
        seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
        return 0;
 }
-
-irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
-{
-       return d->hwirq;
-}
-EXPORT_SYMBOL_GPL(irqd_to_hwirq);
-
-irq_hw_number_t virq_to_hw(unsigned int virq)
-{
-       struct irq_data *irq_data = irq_get_irq_data(virq);
-       return WARN_ON(!irq_data) ? 0 : irq_data->hwirq;
-}
-EXPORT_SYMBOL_GPL(virq_to_hw);
index 304f675826e93a249595ec65d5c81bb5629a9d85..3b5a0509998994549a80d72ef440b71c1934f2cf 100644 (file)
@@ -85,10 +85,7 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
@@ -279,15 +276,8 @@ static int handle_signal(int sig,
 
        /* Set up the stack frame */
        ret = setup_rt_frame(sig, ka, info, oldset, regs);
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked,
-                         &ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       if (ret == 0)
+               block_sigmask(ka, sig);
 
        return ret;
 }
index 41098a3803a22db4fa787d4ab5129dfe1da8456d..4f8d8bcdc7de53a2d4b7cbf89989a27243e59dea 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/export.h>
 #include <linux/highmem.h>
 #include <linux/scatterlist.h>
 #include <asm/io.h>
index 448b224ba4efd569455b5dfe41dec2a319bfb817..233ed3d2d25e61ede6d63ccff367f860c969f421 100644 (file)
@@ -71,29 +71,35 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
        return (dma_addr == bad_dma_address);
 }
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
 {
        void *ret;
        struct dma_map_ops *ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
 
-       ret = ops->alloc_coherent(dev, size, dma_handle, flag);
+       ret = ops->alloc(dev, size, dma_handle, flag, attrs);
 
        debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
 
        return ret;
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
 
-       dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+       dma_ops->free(dev, size, cpu_addr, dma_handle, attrs);
 
        debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
 }
index e711ace62fdf9b60eb93d97cf0de193d936cce35..0f2367cc549311a3c8ba1911b0707699435716b2 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/bootmem.h>
 #include <linux/genalloc.h>
 #include <asm/dma-mapping.h>
+#include <linux/module.h>
 
 struct dma_map_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
@@ -54,7 +55,8 @@ static struct gen_pool *coherent_pool;
 /* Allocates from a pool of uncached memory that was reserved at boot time */
 
 void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
-                                dma_addr_t *dma_addr, gfp_t flag)
+                                dma_addr_t *dma_addr, gfp_t flag,
+                                struct dma_attrs *attrs)
 {
        void *ret;
 
@@ -81,7 +83,7 @@ void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
 }
 
 static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
-                                 dma_addr_t dma_addr)
+                                 dma_addr_t dma_addr, struct dma_attrs *attrs)
 {
        gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
 }
@@ -202,8 +204,8 @@ static void hexagon_sync_single_for_device(struct device *dev,
 }
 
 struct dma_map_ops hexagon_dma_ops = {
-       .alloc_coherent = hexagon_dma_alloc_coherent,
-       .free_coherent  = hexagon_free_coherent,
+       .alloc          = hexagon_dma_alloc_coherent,
+       .free           = hexagon_free_coherent,
        .map_sg         = hexagon_map_sg,
        .map_page       = hexagon_map_page,
        .sync_single_for_cpu = hexagon_sync_single_for_cpu,
index 18c4f0b0f4baeb27adb741e7b88138aad100148a..ff02821bfb7ede3372d76d4f1657a1c3e08d1aea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Process creation support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -88,7 +88,7 @@ void (*idle_sleep)(void) = default_idle;
 void cpu_idle(void)
 {
        while (1) {
-               tick_nohz_stop_sched_tick(1);
+               tick_nohz_idle_enter();
                local_irq_disable();
                while (!need_resched()) {
                        idle_sleep();
@@ -97,7 +97,7 @@ void cpu_idle(void)
                        local_irq_disable();
                }
                local_irq_enable();
-               tick_nohz_restart_sched_tick();
+               tick_nohz_idle_exit();
                schedule();
        }
 }
index 32342de1a79c7ae6951fe819c56de0d53a3b999d..96c3b2c4dbaded2a24bb0c62a13a5f669637c90d 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/user.h>
+#include <linux/elf.h>
 
 #include <asm/user.h>
 
index 15d1fd22bbc54fba10da9b9caf9598619e7cd7ec..1298141874a3b4890d1dfab3c82529b49ecd5a78 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SMP support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
+#include <linux/cpu.h>
 
 #include <asm/time.h>    /*  timer_interrupt  */
 #include <asm/hexagon_vm.h>
@@ -35,7 +36,7 @@
 #define BASE_IPI_IRQ 26
 
 /*
- * cpu_possible_map needs to be filled out prior to setup_per_cpu_areas
+ * cpu_possible_mask needs to be filled out prior to setup_per_cpu_areas
  * (which is prior to any of our smp_prepare_cpu crap), in order to set
  * up the...  per_cpu areas.
  */
@@ -177,7 +178,12 @@ void __cpuinit start_secondary(void)
 
        printk(KERN_INFO "%s cpu %d\n", __func__, current_thread_info()->cpu);
 
+       notify_cpu_starting(cpu);
+
+       ipi_call_lock();
        set_cpu_online(cpu, true);
+       ipi_call_unlock();
+
        local_irq_enable();
 
        cpu_idle();
@@ -208,7 +214,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
        stack_start =  ((void *) thread) + THREAD_SIZE;
        __vmstart(start_secondary, stack_start);
 
-       while (!cpu_isset(cpu, cpu_online_map))
+       while (!cpu_online(cpu))
                barrier();
 
        return 0;
@@ -229,7 +235,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 
        /*  Right now, let's just fake it. */
        for (i = 0; i < max_cpus; i++)
-               cpu_set(i, cpu_present_map);
+               set_cpu_present(i, true);
 
        /*  Also need to register the interrupts for IPI  */
        if (max_cpus > 1)
@@ -269,5 +275,5 @@ void smp_start_cpus(void)
        int i;
 
        for (i = 0; i < NR_CPUS; i++)
-               cpu_set(i, cpu_possible_map);
+               set_cpu_possible(i, true);
 }
index 6bee15c9c113d7854991597fa0d2f0b7af4f9b91..5d9b33b67935529a38c437be63c55f4556a7f0c3 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/module.h>
 
 #include <asm/timer-regs.h>
 #include <asm/hexagon_vm.h>
index f212a453b527d09accbd09c16dbfa5ae506745e1..5d39f42f7085bb1fec3c44a101dceb3615c0cc2d 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/err.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/binfmts.h>
 
 #include <asm/vdso.h>
 
index f6ea3a3b4a842e8e0099d967f07a647786fff7d0..bcda5b2d121a624ee784f81843a13c155b7865a8 100644 (file)
@@ -1129,7 +1129,8 @@ void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
  * See Documentation/DMA-API-HOWTO.txt
  */
 static void *
-sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
+sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+                  gfp_t flags, struct dma_attrs *attrs)
 {
        struct ioc *ioc;
        void *addr;
@@ -1191,8 +1192,8 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp
  *
  * See Documentation/DMA-API-HOWTO.txt
  */
-static void sba_free_coherent (struct device *dev, size_t size, void *vaddr,
-                              dma_addr_t dma_handle)
+static void sba_free_coherent(struct device *dev, size_t size, void *vaddr,
+                             dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
        sba_unmap_single_attrs(dev, dma_handle, size, 0, NULL);
        free_pages((unsigned long) vaddr, get_order(size));
@@ -2212,8 +2213,8 @@ sba_page_override(char *str)
 __setup("sbapagesize=",sba_page_override);
 
 struct dma_map_ops sba_dma_ops = {
-       .alloc_coherent         = sba_alloc_coherent,
-       .free_coherent          = sba_free_coherent,
+       .alloc                  = sba_alloc_coherent,
+       .free                   = sba_free_coherent,
        .map_page               = sba_map_page,
        .unmap_page             = sba_unmap_page,
        .map_sg                 = sba_map_sg_attrs,
index 4c96187e204908bb3a9ba7e37a198df61159ff28..4f37dbbb864081cac07e473270f8dd5ec42cf083 100644 (file)
@@ -1 +1,147 @@
-#include <asm/intrinsics.h>
+#ifndef _ASM_IA64_CMPXCHG_H
+#define _ASM_IA64_CMPXCHG_H
+
+/*
+ * Compare/Exchange, forked from asm/intrinsics.h
+ * which was:
+ *
+ *     Copyright (C) 2002-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+/* include compiler specific intrinsics */
+#include <asm/ia64regs.h>
+#ifdef __INTEL_COMPILER
+# include <asm/intel_intrin.h>
+#else
+# include <asm/gcc_intrin.h>
+#endif
+
+/*
+ * This function doesn't exist, so you'll get a linker error if
+ * something tries to do an invalid xchg().
+ */
+extern void ia64_xchg_called_with_bad_pointer(void);
+
+#define __xchg(x, ptr, size)                                           \
+({                                                                     \
+       unsigned long __xchg_result;                                    \
+                                                                       \
+       switch (size) {                                                 \
+       case 1:                                                         \
+               __xchg_result = ia64_xchg1((__u8 *)ptr, x);             \
+               break;                                                  \
+                                                                       \
+       case 2:                                                         \
+               __xchg_result = ia64_xchg2((__u16 *)ptr, x);            \
+               break;                                                  \
+                                                                       \
+       case 4:                                                         \
+               __xchg_result = ia64_xchg4((__u32 *)ptr, x);            \
+               break;                                                  \
+                                                                       \
+       case 8:                                                         \
+               __xchg_result = ia64_xchg8((__u64 *)ptr, x);            \
+               break;                                                  \
+       default:                                                        \
+               ia64_xchg_called_with_bad_pointer();                    \
+       }                                                               \
+       __xchg_result;                                                  \
+})
+
+#define xchg(ptr, x)                                                   \
+((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg().
+ */
+extern long ia64_cmpxchg_called_with_bad_pointer(void);
+
+#define ia64_cmpxchg(sem, ptr, old, new, size)                         \
+({                                                                     \
+       __u64 _o_, _r_;                                                 \
+                                                                       \
+       switch (size) {                                                 \
+       case 1:                                                         \
+               _o_ = (__u8) (long) (old);                              \
+               break;                                                  \
+       case 2:                                                         \
+               _o_ = (__u16) (long) (old);                             \
+               break;                                                  \
+       case 4:                                                         \
+               _o_ = (__u32) (long) (old);                             \
+               break;                                                  \
+       case 8:                                                         \
+               _o_ = (__u64) (long) (old);                             \
+               break;                                                  \
+       default:                                                        \
+               break;                                                  \
+       }                                                               \
+       switch (size) {                                                 \
+       case 1:                                                         \
+               _r_ = ia64_cmpxchg1_##sem((__u8 *) ptr, new, _o_);      \
+               break;                                                  \
+                                                                       \
+       case 2:                                                         \
+               _r_ = ia64_cmpxchg2_##sem((__u16 *) ptr, new, _o_);     \
+               break;                                                  \
+                                                                       \
+       case 4:                                                         \
+               _r_ = ia64_cmpxchg4_##sem((__u32 *) ptr, new, _o_);     \
+               break;                                                  \
+                                                                       \
+       case 8:                                                         \
+               _r_ = ia64_cmpxchg8_##sem((__u64 *) ptr, new, _o_);     \
+               break;                                                  \
+                                                                       \
+       default:                                                        \
+               _r_ = ia64_cmpxchg_called_with_bad_pointer();           \
+               break;                                                  \
+       }                                                               \
+       (__typeof__(old)) _r_;                                          \
+})
+
+#define cmpxchg_acq(ptr, o, n) \
+       ia64_cmpxchg(acq, (ptr), (o), (n), sizeof(*(ptr)))
+#define cmpxchg_rel(ptr, o, n) \
+       ia64_cmpxchg(rel, (ptr), (o), (n), sizeof(*(ptr)))
+
+/* for compatibility with other platforms: */
+#define cmpxchg(ptr, o, n)     cmpxchg_acq((ptr), (o), (n))
+#define cmpxchg64(ptr, o, n)   cmpxchg_acq((ptr), (o), (n))
+
+#define cmpxchg_local          cmpxchg
+#define cmpxchg64_local                cmpxchg64
+
+#ifdef CONFIG_IA64_DEBUG_CMPXCHG
+# define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128;
+# define CMPXCHG_BUGCHECK(v)                                           \
+do {                                                                   \
+       if (_cmpxchg_bugcheck_count-- <= 0) {                           \
+               void *ip;                                               \
+               extern int printk(const char *fmt, ...);                \
+               ip = (void *) ia64_getreg(_IA64_REG_IP);                \
+               printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
+               break;                                                  \
+       }                                                               \
+} while (0)
+#else /* !CONFIG_IA64_DEBUG_CMPXCHG */
+# define CMPXCHG_BUGCHECK_DECL
+# define CMPXCHG_BUGCHECK(v)
+#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_IA64_CMPXCHG_H */
index 4336d080b2410a5b4a43589684974b2a6fa8cb03..4f5e8148440d25b2d89d8824e9387878e33e4802 100644 (file)
@@ -23,23 +23,29 @@ extern void machvec_dma_sync_single(struct device *, dma_addr_t, size_t,
 extern void machvec_dma_sync_sg(struct device *, struct scatterlist *, int,
                                enum dma_data_direction);
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *daddr, gfp_t gfp)
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *daddr, gfp_t gfp,
+                                   struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = platform_dma_get_ops(dev);
        void *caddr;
 
-       caddr = ops->alloc_coherent(dev, size, daddr, gfp);
+       caddr = ops->alloc(dev, size, daddr, gfp, attrs);
        debug_dma_alloc_coherent(dev, size, *daddr, caddr);
        return caddr;
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *caddr, dma_addr_t daddr)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *caddr, dma_addr_t daddr,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = platform_dma_get_ops(dev);
        debug_dma_free_coherent(dev, size, caddr, daddr);
-       ops->free_coherent(dev, size, caddr, daddr);
+       ops->free(dev, size, caddr, daddr, attrs);
 }
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
index 0ab82cc2dc8fe990f79d7db76f166b94e75b11d9..d2bf1fd5e44f5970caf455acdddc671fc0dee192 100644 (file)
@@ -106,15 +106,16 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                return -EFAULT;
 
        {
-               register unsigned long r8 __asm ("r8") = 0;
+               register unsigned long r8 __asm ("r8");
                unsigned long prev;
                __asm__ __volatile__(
                        "       mf;;                                    \n"
-                       "       mov ar.ccv=%3;;                         \n"
-                       "[1:]   cmpxchg4.acq %0=[%1],%2,ar.ccv          \n"
+                       "       mov %0=r0                               \n"
+                       "       mov ar.ccv=%4;;                         \n"
+                       "[1:]   cmpxchg4.acq %1=[%2],%3,ar.ccv          \n"
                        "       .xdata4 \"__ex_table\", 1b-., 2f-.      \n"
                        "[2:]"
-                       : "=r" (prev)
+                       : "=r" (r8), "=r" (prev)
                        : "r" (uaddr), "r" (newval),
                          "rO" ((long) (unsigned) oldval)
                        : "memory");
index e4076b511829572ad590d36e362f463f93e813d6..d129e367e76448036c4dad8c347cc6a33977f710 100644 (file)
@@ -18,6 +18,7 @@
 #else
 # include <asm/gcc_intrin.h>
 #endif
+#include <asm/cmpxchg.h>
 
 #define ia64_native_get_psr_i()        (ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I)
 
@@ -81,119 +82,6 @@ extern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
 
 #define ia64_fetch_and_add(i,v)        (ia64_fetchadd(i, v, rel) + (i)) /* return new value */
 
-/*
- * This function doesn't exist, so you'll get a linker error if
- * something tries to do an invalid xchg().
- */
-extern void ia64_xchg_called_with_bad_pointer (void);
-
-#define __xchg(x,ptr,size)                                             \
-({                                                                     \
-       unsigned long __xchg_result;                                    \
-                                                                       \
-       switch (size) {                                                 \
-             case 1:                                                   \
-               __xchg_result = ia64_xchg1((__u8 *)ptr, x);             \
-               break;                                                  \
-                                                                       \
-             case 2:                                                   \
-               __xchg_result = ia64_xchg2((__u16 *)ptr, x);            \
-               break;                                                  \
-                                                                       \
-             case 4:                                                   \
-               __xchg_result = ia64_xchg4((__u32 *)ptr, x);            \
-               break;                                                  \
-                                                                       \
-             case 8:                                                   \
-               __xchg_result = ia64_xchg8((__u64 *)ptr, x);            \
-               break;                                                  \
-             default:                                                  \
-               ia64_xchg_called_with_bad_pointer();                    \
-       }                                                               \
-       __xchg_result;                                                  \
-})
-
-#define xchg(ptr,x)                                                         \
-  ((__typeof__(*(ptr))) __xchg ((unsigned long) (x), (ptr), sizeof(*(ptr))))
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-/*
- * This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid cmpxchg().
- */
-extern long ia64_cmpxchg_called_with_bad_pointer (void);
-
-#define ia64_cmpxchg(sem,ptr,old,new,size)                                             \
-({                                                                                     \
-       __u64 _o_, _r_;                                                                 \
-                                                                                       \
-       switch (size) {                                                                 \
-             case 1: _o_ = (__u8 ) (long) (old); break;                                \
-             case 2: _o_ = (__u16) (long) (old); break;                                \
-             case 4: _o_ = (__u32) (long) (old); break;                                \
-             case 8: _o_ = (__u64) (long) (old); break;                                \
-             default: break;                                                           \
-       }                                                                               \
-       switch (size) {                                                                 \
-             case 1:                                                                   \
-               _r_ = ia64_cmpxchg1_##sem((__u8 *) ptr, new, _o_);                      \
-               break;                                                                  \
-                                                                                       \
-             case 2:                                                                   \
-              _r_ = ia64_cmpxchg2_##sem((__u16 *) ptr, new, _o_);                      \
-               break;                                                                  \
-                                                                                       \
-             case 4:                                                                   \
-               _r_ = ia64_cmpxchg4_##sem((__u32 *) ptr, new, _o_);                     \
-               break;                                                                  \
-                                                                                       \
-             case 8:                                                                   \
-               _r_ = ia64_cmpxchg8_##sem((__u64 *) ptr, new, _o_);                     \
-               break;                                                                  \
-                                                                                       \
-             default:                                                                  \
-               _r_ = ia64_cmpxchg_called_with_bad_pointer();                           \
-               break;                                                                  \
-       }                                                                               \
-       (__typeof__(old)) _r_;                                                          \
-})
-
-#define cmpxchg_acq(ptr, o, n) \
-       ia64_cmpxchg(acq, (ptr), (o), (n), sizeof(*(ptr)))
-#define cmpxchg_rel(ptr, o, n) \
-       ia64_cmpxchg(rel, (ptr), (o), (n), sizeof(*(ptr)))
-
-/* for compatibility with other platforms: */
-#define cmpxchg(ptr, o, n)     cmpxchg_acq((ptr), (o), (n))
-#define cmpxchg64(ptr, o, n)   cmpxchg_acq((ptr), (o), (n))
-
-#define cmpxchg_local          cmpxchg
-#define cmpxchg64_local                cmpxchg64
-
-#ifdef CONFIG_IA64_DEBUG_CMPXCHG
-# define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128;
-# define CMPXCHG_BUGCHECK(v)                                                   \
-  do {                                                                         \
-       if (_cmpxchg_bugcheck_count-- <= 0) {                                   \
-               void *ip;                                                       \
-               extern int printk(const char *fmt, ...);                        \
-               ip = (void *) ia64_getreg(_IA64_REG_IP);                        \
-               printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));  \
-               break;                                                          \
-       }                                                                       \
-  } while (0)
-#else /* !CONFIG_IA64_DEBUG_CMPXCHG */
-# define CMPXCHG_BUGCHECK_DECL
-# define CMPXCHG_BUGCHECK(v)
-#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
-
 #endif
 
 #ifdef __KERNEL__
index ac795d311f4411cef9cd8c76b1e91cc6b7d5988c..6f38b6120d96bc841f4563c1fe3202ae7a78b7f3 100644 (file)
@@ -839,7 +839,7 @@ static __init int setup_additional_cpus(char *s)
 early_param("additional_cpus", setup_additional_cpus);
 
 /*
- * cpu_possible_map should be static, it cannot change as CPUs
+ * cpu_possible_mask should be static, it cannot change as CPUs
  * are onlined, or offlined. The reason is per-cpu data-structures
  * are allocated by some modules at init time, and dont expect to
  * do this dynamically on cpu arrival/departure.
index d9485d952ed0a8c26fe8677b09e5ba249a5f9c25..939260aeac98a6013d8e8ba0ab4a88763fec8e22 100644 (file)
@@ -15,16 +15,24 @@ int swiotlb __read_mostly;
 EXPORT_SYMBOL(swiotlb);
 
 static void *ia64_swiotlb_alloc_coherent(struct device *dev, size_t size,
-                                        dma_addr_t *dma_handle, gfp_t gfp)
+                                        dma_addr_t *dma_handle, gfp_t gfp,
+                                        struct dma_attrs *attrs)
 {
        if (dev->coherent_dma_mask != DMA_BIT_MASK(64))
                gfp |= GFP_DMA;
        return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
 }
 
+static void ia64_swiotlb_free_coherent(struct device *dev, size_t size,
+                                      void *vaddr, dma_addr_t dma_addr,
+                                      struct dma_attrs *attrs)
+{
+       swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+}
+
 struct dma_map_ops swiotlb_dma_ops = {
-       .alloc_coherent = ia64_swiotlb_alloc_coherent,
-       .free_coherent = swiotlb_free_coherent,
+       .alloc = ia64_swiotlb_alloc_coherent,
+       .free = ia64_swiotlb_free_coherent,
        .map_page = swiotlb_map_page,
        .unmap_page = swiotlb_unmap_page,
        .map_sg = swiotlb_map_sg_attrs,
index 9d0fd7d5bb82c03d65820a01b1af673c7b0c7c7e..f00ba025375d5696d0070bfe640b6f26f554eebd 100644 (file)
@@ -604,12 +604,6 @@ pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f)
        spin_unlock(&(x)->ctx_lock);
 }
 
-static inline unsigned int
-pfm_do_munmap(struct mm_struct *mm, unsigned long addr, size_t len, int acct)
-{
-       return do_munmap(mm, addr, len);
-}
-
 static inline unsigned long 
 pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, unsigned long exec)
 {
@@ -1458,8 +1452,9 @@ pfm_unreserve_session(pfm_context_t *ctx, int is_syswide, unsigned int cpu)
  * a PROTECT_CTX() section.
  */
 static int
-pfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long size)
+pfm_remove_smpl_mapping(void *vaddr, unsigned long size)
 {
+       struct task_struct *task = current;
        int r;
 
        /* sanity checks */
@@ -1473,13 +1468,8 @@ pfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long siz
        /*
         * does the actual unmapping
         */
-       down_write(&task->mm->mmap_sem);
+       r = vm_munmap((unsigned long)vaddr, size);
 
-       DPRINT(("down_write done smpl_vaddr=%p size=%lu\n", vaddr, size));
-
-       r = pfm_do_munmap(task->mm, (unsigned long)vaddr, size, 0);
-
-       up_write(&task->mm->mmap_sem);
        if (r !=0) {
                printk(KERN_ERR "perfmon: [%d] unable to unmap sampling buffer @%p size=%lu\n", task_pid_nr(task), vaddr, size);
        }
@@ -1945,7 +1935,7 @@ pfm_flush(struct file *filp, fl_owner_t id)
         * because some VM function reenables interrupts.
         *
         */
-       if (smpl_buf_vaddr) pfm_remove_smpl_mapping(current, smpl_buf_vaddr, smpl_buf_size);
+       if (smpl_buf_vaddr) pfm_remove_smpl_mapping(smpl_buf_vaddr, smpl_buf_size);
 
        return 0;
 }
index a9d310de57da650ac7c3549774729c990ceac583..3290d6e00c3164674e2d2d018c9b992dbc5fc152 100644 (file)
@@ -76,7 +76,8 @@ EXPORT_SYMBOL(sn_dma_set_mask);
  * more information.
  */
 static void *sn_dma_alloc_coherent(struct device *dev, size_t size,
-                                  dma_addr_t * dma_handle, gfp_t flags)
+                                  dma_addr_t * dma_handle, gfp_t flags,
+                                  struct dma_attrs *attrs)
 {
        void *cpuaddr;
        unsigned long phys_addr;
@@ -137,7 +138,7 @@ static void *sn_dma_alloc_coherent(struct device *dev, size_t size,
  * any associated IOMMU mappings.
  */
 static void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
-                                dma_addr_t dma_handle)
+                                dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
@@ -466,8 +467,8 @@ int sn_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
 }
 
 static struct dma_map_ops sn_dma_ops = {
-       .alloc_coherent         = sn_dma_alloc_coherent,
-       .free_coherent          = sn_dma_free_coherent,
+       .alloc                  = sn_dma_alloc_coherent,
+       .free                   = sn_dma_free_coherent,
        .map_page               = sn_dma_map_page,
        .unmap_page             = sn_dma_unmap_page,
        .map_sg                 = sn_dma_map_sg,
index 33c32aeca12beb418955260a4f83a127ef900960..a1230e82bb1e5226c3d61968b1c625bbf40c6a17 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_FEC=y
-CONFIG_FEC2=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_PPP=y
index 336e6173794f3a2c2b720d4b3ce87e8ddca7d67a..f4e32de263a7cefe98f3c9a5f7b2dc4071c12d00 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <linux/irqflags.h>
+#include <asm/cmpxchg.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
index 96fa6ed7e7995b5bbee00f1d3d6f513ccba288ad..d9f62e0f46c0b8861aff1509549be510c0b2a514 100644 (file)
@@ -980,6 +980,9 @@ int __init mac_platform_init(void)
 {
        u8 *swim_base;
 
+       if (!MACH_IS_MAC)
+               return -ENODEV;
+
        /*
         * Serial devices
         */
index 7ed848c3b848784cf4d0067e35889ce4c857a0fd..f91a53294c357eebe80364a9a696a5993ab782f7 100644 (file)
@@ -74,9 +74,7 @@ static void __init m527x_fec_init(void)
        writew(par | 0xf00, MCF_IPSBAR + 0x100082);
        v = readb(MCF_IPSBAR + 0x100078);
        writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
-#endif
 
-#ifdef CONFIG_FEC2
        /* Set multi-function pins to ethernet mode for fec1 */
        par = readw(MCF_IPSBAR + 0x100082);
        writew(par | 0xa0, MCF_IPSBAR + 0x100082);
index ee97735a242c5575c208c8391559b2e2fab98dce..b44d799b111500d9e4406227fd50ff85ac812830 100644 (file)
@@ -3,9 +3,3 @@
 #
 
 obj-y := config.o
-
-extra-y := bootlogo.rh
-
-$(obj)/bootlogo.rh: $(src)/bootlogo.h
-       perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \
-               > $(obj)/bootlogo.rh
diff --git a/arch/m68k/platform/68EZ328/bootlogo.h b/arch/m68k/platform/68EZ328/bootlogo.h
deleted file mode 100644 (file)
index e842bda..0000000
+++ /dev/null
@@ -1,3204 +0,0 @@
-#define splash_width 640
-#define splash_height 480
-static unsigned char splash_bits[] = {
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfe, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x7c, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0xe0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3e, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
-  0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0xfe, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
-  0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xe0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0x07, 0xfe, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
-  0x00, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0xe0, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03,
-  0x3f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0x00, 0x00, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f,
-  0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0xff, 0xff, 0x3f, 0xf0, 0x01, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xc0, 0xff,
-  0xc1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xfc, 0x07, 0x07, 0x00, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f,
-  0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x07, 0x00, 0x00, 0xe0, 0x07, 0x0e, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
-  0x3f, 0x1c, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x38, 0x00, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f,
-  0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
-  0x00, 0x00, 0x00, 0x00, 0x78, 0x70, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xe0, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc3, 0x01, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f,
-  0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0xc7, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x87, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x07, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f,
-  0x00, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0e, 0x00, 0xf0, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xf0, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x30, 0x0c, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1c, 0x00,
-  0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x07, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x80, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00,
-  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0xe0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe2, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
-  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01,
-  0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03,
-  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
-  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xfe, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07,
-  0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07,
-  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0xf0, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x9f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
-  0xf8, 0xff, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0xff, 0xff, 0x00,
-  0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x0f, 0x20, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0xf8, 0xff, 0xff, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
-  0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xfc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
-  0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf0, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0xf8, 0xff, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0x01,
-  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xfc, 0x01, 0xff, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0xe0, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30, 0x30, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0xf8,
-  0x41, 0xc6, 0x84, 0x0c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0xf8, 0x41, 0xc6, 0x84, 0x0c,
-  0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x0f, 0x00, 0x00, 0x18, 0x0c, 0x08, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xe4,
-  0xb1, 0xc1, 0x98, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0xe4, 0xb1, 0xc1, 0x98, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-  0x08, 0x00, 0x00, 0x1c, 0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0xff, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c,
-  0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xc0, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x10, 0x80,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00,
-  0x36, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x09, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x9c,
-  0x01, 0x08, 0x83, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40,
-  0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40, 0x30, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0x03, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x9b,
-  0x01, 0xc0, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x40,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0x9b, 0x01, 0xc0, 0x00, 0x00,
-  0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-  0x00, 0x00, 0x00, 0x07, 0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf0, 0xc1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x07,
-  0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x10, 0xe0,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x7b, 0x00, 0x30, 0x03, 0x0c,
-  0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x07, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x09, 0x00, 0xc0, 0x84, 0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xfd, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xc0, 0x84,
-  0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x03, 0xf0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40,
-  0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xfc, 0x01, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40, 0x08, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x07, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-  0xf8, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x64,
-  0x42, 0x06, 0x1b, 0x03, 0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0xc0, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x10, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x64, 0x42, 0x06, 0x1b, 0x03,
-  0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x0f, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x3f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x1b,
-  0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xc3, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xe0, 0x84, 0x31, 0x30, 0x04, 0x80,
-  0xc1, 0x18, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x09, 0x00, 0xc0, 0x63, 0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-  0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0xc0, 0x63,
-  0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c,
-  0x06, 0x81, 0x80, 0xfd, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c, 0x06, 0x81, 0x80, 0xfd,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x00, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x20, 0x63,
-  0x0c, 0x08, 0x80, 0x00, 0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x30, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x20, 0x63, 0x0c, 0x08, 0x80, 0x00,
-  0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x0f, 0x00, 0xd8, 0x84, 0x01, 0xc0, 0x00, 0x00, 0x06, 0x00, 0x80, 0xf1,
-  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf8, 0x1b,
-  0x40, 0x08, 0x84, 0x0c, 0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xe0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xf8, 0x1b, 0x40, 0x08, 0x84, 0x0c,
-  0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0xe4, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x09, 0x00, 0x38, 0x80, 0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-  0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x07, 0x00, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x38, 0x80,
-  0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x10, 0x84,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00,
-  0x00, 0x00, 0x03, 0xf2, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x08, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00, 0x00, 0x00, 0x03, 0xf2,
-  0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
-  0x08, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x3e, 0x00,
-  0x82, 0x01, 0x03, 0x40, 0x30, 0x98, 0x10, 0xf0, 0xe7, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x10, 0xe4,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c,
-  0x00, 0x00, 0x00, 0xfc, 0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x30, 0x7c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0xfc,
-  0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
-  0x08, 0x00, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64,
-  0x30, 0xc6, 0x80, 0x80, 0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf8, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0e, 0x00, 0xc0, 0x3c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64, 0x30, 0xc6, 0x80, 0x80,
-  0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc3, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0e, 0x00, 0x39, 0x03, 0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x39, 0x03,
-  0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3e, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0xe7, 0x04, 0x42, 0xc6, 0x00, 0x00,
-  0x00, 0x00, 0xec, 0xcf, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x0f, 0xc0, 0x1f, 0x80, 0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01,
-  0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x01, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x1f, 0x80,
-  0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01, 0x00, 0xe0, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3f, 0x08, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00,
-  0xc0, 0x60, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x1f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
-  0x00, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00, 0xc0, 0x60, 0x7c, 0x00,
-  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xc0, 0x19, 0x60,
-  0x40, 0x00, 0x63, 0x30, 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0xf3, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x09, 0xc0, 0x19, 0x60, 0x40, 0x00, 0x63, 0x30,
-  0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xf3, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x78, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0f, 0xc0, 0x27, 0x03, 0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0xcf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xc0, 0x27, 0x03,
-  0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x0f, 0xc0, 0xde, 0x04, 0x0c, 0x06, 0x03, 0x80,
-  0xc1, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0f, 0x03, 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x0f, 0xc0, 0x19, 0x00, 0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f,
-  0x07, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x19, 0x00,
-  0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x07, 0x00, 0x18, 0x40,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03,
-  0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
-  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x1f, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
-  0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03, 0xf0, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
-  0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31,
-  0x04, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0xd9, 0x04,
-  0x00, 0x08, 0x00, 0x80, 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x60, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0xd9, 0x04, 0x00, 0x08, 0x00, 0x80,
-  0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x78, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0f, 0xc0, 0x27, 0x00, 0x30, 0xc0, 0x60, 0xb0, 0xff, 0x7f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-  0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
-  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b,
-  0x8d, 0x01, 0x04, 0xc3, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x80, 0xf1, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x03, 0x00, 0xf0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b, 0x8d, 0x01, 0x04, 0xc3,
-  0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf1, 0xff,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0x39, 0x04, 0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x39, 0x04,
-  0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-  0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xff, 0x07,
-  0xb0, 0x09, 0xe4, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x30, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0xf8,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x08,
-  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07,
-  0xb0, 0xc9, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07, 0xb0, 0xc9, 0xf8, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
-  0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x0f, 0x00, 0xe7, 0xfb, 0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0xe7, 0xfb,
-  0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xe0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xfe, 0x1c, 0xb2, 0x0f, 0xe0, 0xff,
-  0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0xf8, 0xe7, 0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0,
-  0xb1, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xf8, 0xe7,
-  0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0, 0xb1, 0x3f, 0x00, 0x00,
-  0xf8, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff,
-  0x01, 0x00, 0xe0, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x98, 0x4f, 0x0e, 0x18, 0x00, 0xf8, 0xff, 0xff, 0xff,
-  0x07, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff, 0x01, 0x00, 0xe0, 0x03,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
-  0x4f, 0x0e, 0xf8, 0x1f, 0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xf8, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x1f,
-  0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0xe0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
-  0x00, 0xce, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0xe3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xe0, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xce, 0xff, 0x7f,
-  0x00, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x20, 0x1b, 0xb2, 0x31, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0xe0, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c,
-  0x00, 0xc0, 0xff, 0x73, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
-  0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c, 0x00, 0xc0, 0x7f, 0x1c,
-  0x30, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x78, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x38, 0x87, 0x31, 0x06, 0x7c, 0x1c, 0x30, 0xff, 0xff, 0xff,
-  0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x87,
-  0x31, 0x06, 0xfc, 0x0f, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x38,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-  0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0xe3, 0x0f,
-  0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xe0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0x03, 0x00, 0xf0, 0xff, 0xff, 0xff,
-  0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x07, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b,
-  0x4c, 0x00, 0x04, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0xc0, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x18, 0x80,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x78, 0xf3, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x08, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04,
-  0x02, 0x30, 0x60, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc0, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04, 0x02, 0x30, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc6, 0x04, 0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x04,
-  0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x67, 0x00, 0x06, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x06, 0x04, 0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-  0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04,
-  0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08,
-  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08, 0x60, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x1c, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x02, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c,
-  0x0c, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38,
-  0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xe0,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c, 0x0c, 0x06, 0xfb, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x68, 0x7c, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf8, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x18, 0xfe, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b,
-  0x81, 0x01, 0x60, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x80,
-  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b, 0x81, 0x01, 0x00, 0x00,
-  0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x38, 0x78, 0x0c, 0x30, 0x04, 0x00, 0xf6, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x78,
-  0x0c, 0x30, 0x04, 0x00, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8,
-  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0x1c, 0x00,
-  0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8, 0x58, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0,
-  0x01, 0x36, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0x36, 0xfc, 0x1f,
-  0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc6, 0x87, 0x0f, 0x00, 0xff, 0x1f, 0x30, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xcf, 0x03, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-  0x40, 0xc0, 0xff, 0x7f, 0xc0, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xcf, 0x03, 0x00, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0xc0, 0xff, 0x7f,
-  0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x7f,
-  0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x07, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-  0x4c, 0x00, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x1f,
-  0x00, 0xff, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x0f, 0x00, 0xff, 0xff, 0x03,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
-  0x41, 0x00, 0xe0, 0x0f, 0x00, 0xff, 0xff, 0x03, 0xff, 0x03, 0x00, 0x38,
-  0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x41, 0x00, 0x00, 0x80,
-  0xc9, 0xf9, 0xff, 0x3d, 0xff, 0x03, 0x00, 0x78, 0xc0, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x60, 0x32, 0x08, 0x00, 0x80, 0xc9, 0xf9, 0xff, 0x3d,
-  0xff, 0x03, 0x00, 0xf8, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x02, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-  0x32, 0x08, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0xf8,
-  0x81, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xff,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0xf8, 0x00, 0x00,
-  0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0x38, 0x03, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0x38, 0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38,
-  0x1e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0xfc,
-  0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38, 0xfc, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x1f, 0x00, 0x00, 0x38, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-  0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x78,
-  0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0xc1, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x60, 0xf8, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
-  0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff,
-  0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x67,
-  0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x13, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0xff,
-  0xff, 0xff, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x67, 0xfe, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
-  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x0f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x98,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xf8, 0xff,
-  0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x00, 0xc0, 0xff, 0x67, 0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf8,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0xff, 0x67,
-  0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c,
-  0x37, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
-  0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-  0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c, 0x37, 0x80, 0x0c, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xfc,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0xc0, 0xfe, 0x03,
-  0x8c, 0x09, 0xe3, 0x73, 0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xfe, 0x03, 0x8c, 0x09, 0xe3, 0x73,
-  0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0xc0, 0x27, 0xe7, 0x31, 0x36, 0x04, 0x8c, 0x01, 0x60, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18,
-  0x42, 0xc0, 0x98, 0x30, 0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18, 0x42, 0xc0, 0x98, 0x30,
-  0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0xc0, 0x27, 0x63, 0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x27, 0x63,
-  0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0,
-  0x31, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff,
-  0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0, 0x31, 0x19, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0xc0, 0x1e, 0x63,
-  0x00, 0x30, 0x04, 0x03, 0xc8, 0x60, 0x00, 0x0e, 0x00, 0x00, 0xfc, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x0e, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0,
-  0x01, 0xe7, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x0f, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0, 0x01, 0xe7, 0xf3, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x0f, 0xc0, 0x1e, 0x03,
-  0x02, 0x08, 0x04, 0x00, 0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xd8, 0x0f, 0xc0, 0x1e, 0x03, 0x02, 0x08, 0x04, 0x00,
-  0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xc0, 0x0f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x0b, 0x00, 0x21, 0x64, 0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xfb, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x21, 0x64,
-  0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xfb, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0xfb, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfd, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00,
-  0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xf9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf,
-  0x01, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00, 0x0e, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf0, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x0b, 0xc0, 0xc0, 0x84,
-  0x31, 0xc0, 0x00, 0x4c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x1e, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0f, 0x0e, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80,
-  0x09, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xc3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x0c, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80, 0x09, 0xff, 0xff, 0x3f,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
-  0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0xc0, 0xc1, 0x03,
-  0x4c, 0x00, 0x00, 0x30, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x90, 0x13, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x08, 0xc0, 0xc1, 0x03, 0x4c, 0x00, 0x00, 0x30,
-  0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0xc0, 0x3f, 0x98, 0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-  0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x98,
-  0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xc6, 0x03, 0x40, 0x00, 0x00, 0x80,
-  0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xef, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-  0x00, 0x00, 0x3f, 0x18, 0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xef, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x18,
-  0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xc7, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30,
-  0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x83, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
-  0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30, 0x30, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x04,
-  0x02, 0x00, 0x00, 0x83, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x38, 0x04, 0x02, 0x00, 0x00, 0x83,
-  0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x03, 0x00, 0xe0, 0x1b, 0x0c, 0x08, 0x18, 0x40, 0x30, 0xfe, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84,
-  0x81, 0x01, 0x03, 0x0c, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84, 0x81, 0x01, 0x03, 0x0c,
-  0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x0e, 0x00, 0x00, 0x1b, 0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-  0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x1b,
-  0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40,
-  0x00, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40, 0x00, 0xe1, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-  0x30, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x9c,
-  0x01, 0x08, 0x60, 0x0c, 0x06, 0x86, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbf, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x07, 0x0e, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00,
-  0xc0, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x9f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x07, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00, 0xc0, 0x00, 0xfc, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x1f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0xe0,
-  0x01, 0x06, 0x00, 0x30, 0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x06, 0x00, 0x30,
-  0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-  0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00,
-  0x00, 0x06, 0x83, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00, 0x00, 0x06, 0x83, 0xff,
-  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0x00, 0x8c, 0xc9, 0x60, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-  0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x0c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0f, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xc6,
-  0x03, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xef, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xd8, 0xef, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x1c, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf3,
-  0x0f, 0x00, 0x00, 0x00, 0x80, 0x09, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x88, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x13,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00,
-  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x88, 0xf3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe3,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe1, 0x1f, 0x00, 0x00, 0x00,
-  0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xf0, 0xc1, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc0, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  };
index 447ffa0fd7c7a15759e06403a4c7eafe9fabbfb6..a49d75e654899a1adb229fb275290943ad0b3b94 100644 (file)
@@ -3,14 +3,9 @@
 #
 
 obj-y          := config.o
-logo-$(UCDIMM) := bootlogo.rh
-logo-$(DRAGEN2)        := screen.h
-extra-y                := $(logo-y)
-
-$(obj)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h
-       perl $(src)/bootlogo.pl < $(src)/../68328/bootlogo.h > $(obj)/bootlogo.rh
+extra-$(DRAGEN2):= screen.h
 
 $(obj)/screen.h: $(src)/screen.xbm $(src)/xbm2lcd.pl
        perl $(src)/xbm2lcd.pl < $(src)/screen.xbm > $(obj)/screen.h
 
-clean-files := $(obj)/screen.h $(obj)/bootlogo.rh
+clean-files := $(obj)/screen.h
diff --git a/arch/m68k/platform/68VZ328/bootlogo.h b/arch/m68k/platform/68VZ328/bootlogo.h
new file mode 100644 (file)
index 0000000..b38e2b2
--- /dev/null
@@ -0,0 +1,3204 @@
+#define splash_width 640
+#define splash_height 480
+unsigned char __attribute__ ((aligned(16))) bootlogo_bits[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfe, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x7c, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0xe0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3e, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
+  0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0xfe, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xe0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0x07, 0xfe, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+  0x00, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0xe0, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03,
+  0x3f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0x00, 0x00, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f,
+  0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0xff, 0xff, 0x3f, 0xf0, 0x01, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xc0, 0xff,
+  0xc1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xfc, 0x07, 0x07, 0x00, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f,
+  0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x07, 0x00, 0x00, 0xe0, 0x07, 0x0e, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
+  0x3f, 0x1c, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x38, 0x00, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f,
+  0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
+  0x00, 0x00, 0x00, 0x00, 0x78, 0x70, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xe0, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc3, 0x01, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f,
+  0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0xc7, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x87, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x07, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f,
+  0x00, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0e, 0x00, 0xf0, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xf0, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0x0c, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1c, 0x00,
+  0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x07, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00,
+  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0xe0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe2, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
+  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01,
+  0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03,
+  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
+  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xfe, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0xf0, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x9f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+  0xf8, 0xff, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0xff, 0xff, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x0f, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0xf8, 0xff, 0xff, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xfc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+  0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf0, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0xf8, 0xff, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0x01,
+  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xfc, 0x01, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0xe0, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0xf8,
+  0x41, 0xc6, 0x84, 0x0c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0xf8, 0x41, 0xc6, 0x84, 0x0c,
+  0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x0f, 0x00, 0x00, 0x18, 0x0c, 0x08, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xe4,
+  0xb1, 0xc1, 0x98, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0xe4, 0xb1, 0xc1, 0x98, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x08, 0x00, 0x00, 0x1c, 0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0xff, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c,
+  0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xc0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x10, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00,
+  0x36, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x09, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x9c,
+  0x01, 0x08, 0x83, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40,
+  0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40, 0x30, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0x03, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x9b,
+  0x01, 0xc0, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0x9b, 0x01, 0xc0, 0x00, 0x00,
+  0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x00, 0x00, 0x00, 0x07, 0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf0, 0xc1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x07,
+  0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x10, 0xe0,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x7b, 0x00, 0x30, 0x03, 0x0c,
+  0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x07, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x09, 0x00, 0xc0, 0x84, 0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xfd, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xc0, 0x84,
+  0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x03, 0xf0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40,
+  0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xfc, 0x01, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40, 0x08, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x07, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0xf8, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x64,
+  0x42, 0x06, 0x1b, 0x03, 0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0xc0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x10, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x64, 0x42, 0x06, 0x1b, 0x03,
+  0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x0f, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x3f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x1b,
+  0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xc3, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xe0, 0x84, 0x31, 0x30, 0x04, 0x80,
+  0xc1, 0x18, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x09, 0x00, 0xc0, 0x63, 0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+  0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0xc0, 0x63,
+  0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c,
+  0x06, 0x81, 0x80, 0xfd, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c, 0x06, 0x81, 0x80, 0xfd,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x00, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x20, 0x63,
+  0x0c, 0x08, 0x80, 0x00, 0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x30, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x20, 0x63, 0x0c, 0x08, 0x80, 0x00,
+  0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x0f, 0x00, 0xd8, 0x84, 0x01, 0xc0, 0x00, 0x00, 0x06, 0x00, 0x80, 0xf1,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf8, 0x1b,
+  0x40, 0x08, 0x84, 0x0c, 0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xe0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xf8, 0x1b, 0x40, 0x08, 0x84, 0x0c,
+  0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0xe4, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x09, 0x00, 0x38, 0x80, 0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+  0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x07, 0x00, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x38, 0x80,
+  0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x10, 0x84,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00,
+  0x00, 0x00, 0x03, 0xf2, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x08, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00, 0x00, 0x00, 0x03, 0xf2,
+  0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  0x08, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x3e, 0x00,
+  0x82, 0x01, 0x03, 0x40, 0x30, 0x98, 0x10, 0xf0, 0xe7, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x10, 0xe4,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c,
+  0x00, 0x00, 0x00, 0xfc, 0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x30, 0x7c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0xfc,
+  0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+  0x08, 0x00, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64,
+  0x30, 0xc6, 0x80, 0x80, 0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf8, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0e, 0x00, 0xc0, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64, 0x30, 0xc6, 0x80, 0x80,
+  0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc3, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x39, 0x03, 0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x39, 0x03,
+  0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0xe7, 0x04, 0x42, 0xc6, 0x00, 0x00,
+  0x00, 0x00, 0xec, 0xcf, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x0f, 0xc0, 0x1f, 0x80, 0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01,
+  0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x01, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x1f, 0x80,
+  0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01, 0x00, 0xe0, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3f, 0x08, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00,
+  0xc0, 0x60, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x1f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+  0x00, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00, 0xc0, 0x60, 0x7c, 0x00,
+  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xc0, 0x19, 0x60,
+  0x40, 0x00, 0x63, 0x30, 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0xf3, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x09, 0xc0, 0x19, 0x60, 0x40, 0x00, 0x63, 0x30,
+  0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xf3, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x78, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0xc0, 0x27, 0x03, 0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0xcf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xc0, 0x27, 0x03,
+  0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x0f, 0xc0, 0xde, 0x04, 0x0c, 0x06, 0x03, 0x80,
+  0xc1, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0f, 0x03, 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x0f, 0xc0, 0x19, 0x00, 0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f,
+  0x07, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x19, 0x00,
+  0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x07, 0x00, 0x18, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03,
+  0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x1f, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+  0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03, 0xf0, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+  0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31,
+  0x04, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0xd9, 0x04,
+  0x00, 0x08, 0x00, 0x80, 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x60, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0xd9, 0x04, 0x00, 0x08, 0x00, 0x80,
+  0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x78, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0xc0, 0x27, 0x00, 0x30, 0xc0, 0x60, 0xb0, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+  0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b,
+  0x8d, 0x01, 0x04, 0xc3, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0xf1, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x03, 0x00, 0xf0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b, 0x8d, 0x01, 0x04, 0xc3,
+  0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf1, 0xff,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0x39, 0x04, 0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x39, 0x04,
+  0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+  0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xff, 0x07,
+  0xb0, 0x09, 0xe4, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x30, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x08,
+  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07,
+  0xb0, 0xc9, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07, 0xb0, 0xc9, 0xf8, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x0f, 0x00, 0xe7, 0xfb, 0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0xe7, 0xfb,
+  0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xe0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xfe, 0x1c, 0xb2, 0x0f, 0xe0, 0xff,
+  0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0xf8, 0xe7, 0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0,
+  0xb1, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xf8, 0xe7,
+  0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0, 0xb1, 0x3f, 0x00, 0x00,
+  0xf8, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff,
+  0x01, 0x00, 0xe0, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x98, 0x4f, 0x0e, 0x18, 0x00, 0xf8, 0xff, 0xff, 0xff,
+  0x07, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff, 0x01, 0x00, 0xe0, 0x03,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
+  0x4f, 0x0e, 0xf8, 0x1f, 0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xf8, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x1f,
+  0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0xe0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
+  0x00, 0xce, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0xe3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xe0, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xce, 0xff, 0x7f,
+  0x00, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x1b, 0xb2, 0x31, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0xe0, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c,
+  0x00, 0xc0, 0xff, 0x73, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
+  0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c, 0x00, 0xc0, 0x7f, 0x1c,
+  0x30, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x78, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x38, 0x87, 0x31, 0x06, 0x7c, 0x1c, 0x30, 0xff, 0xff, 0xff,
+  0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x87,
+  0x31, 0x06, 0xfc, 0x0f, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x38,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+  0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0xe3, 0x0f,
+  0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xe0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0x03, 0x00, 0xf0, 0xff, 0xff, 0xff,
+  0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x07, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b,
+  0x4c, 0x00, 0x04, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0xc0, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x18, 0x80,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x78, 0xf3, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x08, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04,
+  0x02, 0x30, 0x60, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc0, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04, 0x02, 0x30, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc6, 0x04, 0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x04,
+  0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x67, 0x00, 0x06, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x04, 0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04,
+  0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08,
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08, 0x60, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x1c, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x02, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c,
+  0x0c, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38,
+  0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xe0,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c, 0x0c, 0x06, 0xfb, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x68, 0x7c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf8, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x18, 0xfe, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b,
+  0x81, 0x01, 0x60, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x80,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b, 0x81, 0x01, 0x00, 0x00,
+  0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x38, 0x78, 0x0c, 0x30, 0x04, 0x00, 0xf6, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x78,
+  0x0c, 0x30, 0x04, 0x00, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8,
+  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0x1c, 0x00,
+  0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8, 0x58, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0,
+  0x01, 0x36, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0x36, 0xfc, 0x1f,
+  0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc6, 0x87, 0x0f, 0x00, 0xff, 0x1f, 0x30, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xcf, 0x03, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+  0x40, 0xc0, 0xff, 0x7f, 0xc0, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xcf, 0x03, 0x00, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0xc0, 0xff, 0x7f,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x7f,
+  0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x07, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0x4c, 0x00, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x1f,
+  0x00, 0xff, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x0f, 0x00, 0xff, 0xff, 0x03,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
+  0x41, 0x00, 0xe0, 0x0f, 0x00, 0xff, 0xff, 0x03, 0xff, 0x03, 0x00, 0x38,
+  0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x41, 0x00, 0x00, 0x80,
+  0xc9, 0xf9, 0xff, 0x3d, 0xff, 0x03, 0x00, 0x78, 0xc0, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x60, 0x32, 0x08, 0x00, 0x80, 0xc9, 0xf9, 0xff, 0x3d,
+  0xff, 0x03, 0x00, 0xf8, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x02, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0x32, 0x08, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0xf8,
+  0x81, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xff,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0xf8, 0x00, 0x00,
+  0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0x38, 0x03, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0x38, 0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38,
+  0x1e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0xfc,
+  0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38, 0xfc, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x1f, 0x00, 0x00, 0x38, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+  0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x78,
+  0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0xc1, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x60, 0xf8, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff,
+  0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x67,
+  0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x13, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0xff,
+  0xff, 0xff, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x67, 0xfe, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x0f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x98,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xf8, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x00, 0xc0, 0xff, 0x67, 0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0xff, 0x67,
+  0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c,
+  0x37, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+  0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c, 0x37, 0x80, 0x0c, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xfc,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0xc0, 0xfe, 0x03,
+  0x8c, 0x09, 0xe3, 0x73, 0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xfe, 0x03, 0x8c, 0x09, 0xe3, 0x73,
+  0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0xc0, 0x27, 0xe7, 0x31, 0x36, 0x04, 0x8c, 0x01, 0x60, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18,
+  0x42, 0xc0, 0x98, 0x30, 0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18, 0x42, 0xc0, 0x98, 0x30,
+  0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0xc0, 0x27, 0x63, 0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x27, 0x63,
+  0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0,
+  0x31, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0, 0x31, 0x19, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0xc0, 0x1e, 0x63,
+  0x00, 0x30, 0x04, 0x03, 0xc8, 0x60, 0x00, 0x0e, 0x00, 0x00, 0xfc, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x0e, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0,
+  0x01, 0xe7, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x0f, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0, 0x01, 0xe7, 0xf3, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x0f, 0xc0, 0x1e, 0x03,
+  0x02, 0x08, 0x04, 0x00, 0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xd8, 0x0f, 0xc0, 0x1e, 0x03, 0x02, 0x08, 0x04, 0x00,
+  0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc0, 0x0f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x0b, 0x00, 0x21, 0x64, 0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xfb, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x21, 0x64,
+  0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xfb, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0xfb, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfd, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00,
+  0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xf9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf,
+  0x01, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00, 0x0e, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf0, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x0b, 0xc0, 0xc0, 0x84,
+  0x31, 0xc0, 0x00, 0x4c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x1e, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0f, 0x0e, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80,
+  0x09, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xc3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x0c, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80, 0x09, 0xff, 0xff, 0x3f,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
+  0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0xc0, 0xc1, 0x03,
+  0x4c, 0x00, 0x00, 0x30, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x90, 0x13, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0xc0, 0xc1, 0x03, 0x4c, 0x00, 0x00, 0x30,
+  0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0xc0, 0x3f, 0x98, 0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+  0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x98,
+  0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xc6, 0x03, 0x40, 0x00, 0x00, 0x80,
+  0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xef, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+  0x00, 0x00, 0x3f, 0x18, 0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xef, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x18,
+  0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xc7, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30,
+  0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x83, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
+  0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30, 0x30, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x04,
+  0x02, 0x00, 0x00, 0x83, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x38, 0x04, 0x02, 0x00, 0x00, 0x83,
+  0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x03, 0x00, 0xe0, 0x1b, 0x0c, 0x08, 0x18, 0x40, 0x30, 0xfe, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84,
+  0x81, 0x01, 0x03, 0x0c, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84, 0x81, 0x01, 0x03, 0x0c,
+  0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x0e, 0x00, 0x00, 0x1b, 0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+  0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x1b,
+  0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40,
+  0x00, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40, 0x00, 0xe1, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+  0x30, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x9c,
+  0x01, 0x08, 0x60, 0x0c, 0x06, 0x86, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbf, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x07, 0x0e, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00,
+  0xc0, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x9f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x07, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00, 0xc0, 0x00, 0xfc, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x1f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0xe0,
+  0x01, 0x06, 0x00, 0x30, 0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x06, 0x00, 0x30,
+  0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00,
+  0x00, 0x06, 0x83, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00, 0x00, 0x06, 0x83, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0x00, 0x8c, 0xc9, 0x60, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x0c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xc6,
+  0x03, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xef, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xd8, 0xef, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1c, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf3,
+  0x0f, 0x00, 0x00, 0x00, 0x80, 0x09, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x88, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x13,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x88, 0xf3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe3,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe1, 0x1f, 0x00, 0x00, 0x00,
+  0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xf0, 0xc1, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc0, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  };
index fa50c48292ffafc7597afb073079dd79c3b6bb98..7af97362b95c3bb067ee939f35d50bcd0991ac4f 100644 (file)
@@ -114,7 +114,7 @@ static struct resource mcf_fec1_resources[] = {
 
 static struct platform_device mcf_fec1 = {
        .name                   = "fec",
-       .id                     = 0,
+       .id                     = 1,
        .num_resources          = ARRAY_SIZE(mcf_fec1_resources),
        .resource               = mcf_fec1_resources,
 };
index 512adb64f7dd574bbe11613ddc21fc75e80bfcf1..8a1ce327c963da94dffa388f2fff533260467679 100644 (file)
@@ -334,6 +334,9 @@ static __init int q40_add_kbd_device(void)
 {
        struct platform_device *pdev;
 
+       if (!MACH_IS_Q40)
+               return -ENODEV;
+
        pdev = platform_device_register_simple("q40kbd", -1, NULL, 0);
        if (IS_ERR(pdev))
                return PTR_ERR(pdev);
index 0094859abd9b3c7cab1cb9a3a037b2a589b8d6c8..538afc0ab9f3d60f15d70c1a9ec53394c429475c 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_MICROBLAZE_CMPXCHG_H
 #define _ASM_MICROBLAZE_CMPXCHG_H
 
+#include <linux/irqflags.h>
+
 void __bad_xchg(volatile void *ptr, int size);
 
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
index 3a3e5b8868544718c7b9b9c0af796f2aed4a6625..01d228286cb0414c157707aa0535bf5f44787ec8 100644 (file)
@@ -123,28 +123,34 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                       dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
        void *memory;
 
        BUG_ON(!ops);
 
-       memory = ops->alloc_coherent(dev, size, dma_handle, flag);
+       memory = ops->alloc(dev, size, dma_handle, flag, attrs);
 
        debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
        return memory;
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d, s, c, h, NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
 
        BUG_ON(!ops);
        debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
-       ops->free_coherent(dev, size, cpu_addr, dma_handle);
+       ops->free(dev, size, cpu_addr, dma_handle, attrs);
 }
 
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
index b0526d2716fa7defea7c036c750284f5a7496443..ff8cde159d9a4809abac1994537b5425c71c9cb4 100644 (file)
@@ -24,7 +24,7 @@
                        .word   1b,4b,2b,4b;                            \
                        .previous;"                                     \
        : "=&r" (oldval), "=&r" (ret)                                   \
-       : "b" (uaddr), "i" (-EFAULT), "r" (oparg)                       \
+       : "r" (uaddr), "i" (-EFAULT), "r" (oparg)                       \
        );                                                              \
 })
 
index 510a8e1c16ba604f5200987fb779da24f45b48ea..bffb545272997b54c2a0090b398618f83320662a 100644 (file)
@@ -31,6 +31,8 @@ extern const struct seq_operations cpuinfo_op;
 /* Do necessary setup to start up a newly executed thread. */
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp);
 
+extern void ret_from_fork(void);
+
 # endif /* __ASSEMBLY__ */
 
 # ifndef CONFIG_MMU
@@ -143,8 +145,6 @@ static inline void exit_thread(void)
 
 unsigned long get_wchan(struct task_struct *p);
 
-extern void ret_from_fork(void);
-
 /* The size allocated for kernel stacks. This _must_ be a power of two! */
 # define KERNEL_STACK_SIZE     0x2000
 
index 65a4af4cbbbe864bb10eb75ff7fd1426c8021950..a2bfa2ca5730657cb729e6b507827c22708348ca 100644 (file)
@@ -33,7 +33,8 @@ static unsigned long get_dma_direct_offset(struct device *dev)
 #define NOT_COHERENT_CACHE
 
 static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
-                               dma_addr_t *dma_handle, gfp_t flag)
+                                      dma_addr_t *dma_handle, gfp_t flag,
+                                      struct dma_attrs *attrs)
 {
 #ifdef NOT_COHERENT_CACHE
        return consistent_alloc(flag, size, dma_handle);
@@ -57,7 +58,8 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 }
 
 static void dma_direct_free_coherent(struct device *dev, size_t size,
-                             void *vaddr, dma_addr_t dma_handle)
+                                    void *vaddr, dma_addr_t dma_handle,
+                                    struct dma_attrs *attrs)
 {
 #ifdef NOT_COHERENT_CACHE
        consistent_free(size, vaddr);
@@ -176,8 +178,8 @@ dma_direct_sync_sg_for_device(struct device *dev,
 }
 
 struct dma_map_ops dma_direct_ops = {
-       .alloc_coherent = dma_direct_alloc_coherent,
-       .free_coherent  = dma_direct_free_coherent,
+       .alloc          = dma_direct_alloc_coherent,
+       .free           = dma_direct_free_coherent,
        .map_sg         = dma_direct_map_sg,
        .unmap_sg       = dma_direct_unmap_sg,
        .dma_supported  = dma_direct_dma_supported,
index ec485876d0d0ec3ca14b005325320fd5c154eb59..aba1f9a97d5d38aa64f31f4965be988ab1d597f7 100644 (file)
@@ -176,6 +176,7 @@ void __init remap_early_printk(void)
        base_addr = (u32) ioremap(base_addr, PAGE_SIZE);
        printk(KERN_CONT "0x%x\n", base_addr);
 
+#ifdef CONFIG_MMU
        /*
         * Early console is on the top of skipped TLB entries
         * decrease tlb_skip size ensure that hardcoded TLB entry will be
@@ -189,6 +190,7 @@ void __init remap_early_printk(void)
         *  cmp rX, orig_base_addr
         */
        tlb_skip -= 1;
+#endif
 }
 
 void __init disable_early_printk(void)
index 71af974aa24acfb82403968c23cb0cbccb7bb55a..16d8dfd9094b1a0df25eaa48799576449a8b234b 100644 (file)
@@ -206,6 +206,7 @@ static int microblaze_debugfs_init(void)
 }
 arch_initcall(microblaze_debugfs_init);
 
+# ifdef CONFIG_MMU
 static int __init debugfs_tlb(void)
 {
        struct dentry *d;
@@ -218,6 +219,7 @@ static int __init debugfs_tlb(void)
                return -ENOMEM;
 }
 device_initcall(debugfs_tlb);
+# endif
 #endif
 
 static int dflt_bus_notify(struct notifier_block *nb,
index 9781a528cfc9179c3c50c2f457fc62db54131b8b..6be4ae3c335140a0173dc0db06bab4dcf86f896d 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/sections.h>
 #include <asm/exceptions.h>
 #include <asm/unwind.h>
+#include <asm/switch_to.h>
 
 struct stack_trace;
 
index f037266cdaf3e358676c0428e83393c16dd410cb..f085995ee8482da474be869148b581543cbf786f 100644 (file)
@@ -122,22 +122,22 @@ __strnlen_user:
 15:    swi     r24, r5, 0x0018 + offset;       \
 16:    swi     r25, r5, 0x001C + offset;       \
        .section __ex_table,"a";                \
-       .word   1b, 0f;                         \
-       .word   2b, 0f;                         \
-       .word   3b, 0f;                         \
-       .word   4b, 0f;                         \
-       .word   5b, 0f;                         \
-       .word   6b, 0f;                         \
-       .word   7b, 0f;                         \
-       .word   8b, 0f;                         \
-       .word   9b, 0f;                         \
-       .word   10b, 0f;                        \
-       .word   11b, 0f;                        \
-       .word   12b, 0f;                        \
-       .word   13b, 0f;                        \
-       .word   14b, 0f;                        \
-       .word   15b, 0f;                        \
-       .word   16b, 0f;                        \
+       .word   1b, 33f;                        \
+       .word   2b, 33f;                        \
+       .word   3b, 33f;                        \
+       .word   4b, 33f;                        \
+       .word   5b, 33f;                        \
+       .word   6b, 33f;                        \
+       .word   7b, 33f;                        \
+       .word   8b, 33f;                        \
+       .word   9b, 33f;                        \
+       .word   10b, 33f;                       \
+       .word   11b, 33f;                       \
+       .word   12b, 33f;                       \
+       .word   13b, 33f;                       \
+       .word   14b, 33f;                       \
+       .word   15b, 33f;                       \
+       .word   16b, 33f;                       \
        .text
 
 #define COPY_80(offset)        \
@@ -190,14 +190,17 @@ w2:       sw      r4, r5, r3
 
 .align 4 /* Alignment is important to keep icache happy */
 page:  /* Create room on stack and save registers for storign values */
-       addik   r1, r1, -32
-       swi     r19, r1, 4
-       swi     r20, r1, 8
-       swi     r21, r1, 12
-       swi     r22, r1, 16
-       swi     r23, r1, 20
-       swi     r24, r1, 24
-       swi     r25, r1, 28
+       addik   r1, r1, -40
+       swi     r5, r1, 0
+       swi     r6, r1, 4
+       swi     r7, r1, 8
+       swi     r19, r1, 12
+       swi     r20, r1, 16
+       swi     r21, r1, 20
+       swi     r22, r1, 24
+       swi     r23, r1, 28
+       swi     r24, r1, 32
+       swi     r25, r1, 36
 loop:  /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
        /* Loop unrolling to get performance boost */
        COPY_80(0x000);
@@ -205,21 +208,44 @@ loop:     /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
        COPY_80(0x100);
        COPY_80(0x180);
        /* copy loop */
-       addik   r6, r6, 0x200
-       addik   r7, r7, -0x200
-       bneid   r7, loop
-       addik   r5, r5, 0x200
+       addik   r6, r6, 0x200
+       addik   r7, r7, -0x200
+       bneid   r7, loop
+       addik   r5, r5, 0x200
+
        /* Restore register content */
-       lwi     r19, r1, 4
-       lwi     r20, r1, 8
-       lwi     r21, r1, 12
-       lwi     r22, r1, 16
-       lwi     r23, r1, 20
-       lwi     r24, r1, 24
-       lwi     r25, r1, 28
-       addik   r1, r1, 32
+       lwi     r5, r1, 0
+       lwi     r6, r1, 4
+       lwi     r7, r1, 8
+       lwi     r19, r1, 12
+       lwi     r20, r1, 16
+       lwi     r21, r1, 20
+       lwi     r22, r1, 24
+       lwi     r23, r1, 28
+       lwi     r24, r1, 32
+       lwi     r25, r1, 36
+       addik   r1, r1, 40
        /* return back */
+       addik   r3, r0, 0
+       rtsd    r15, 8
+       nop
+
+/* Fault case - return temp count */
+33:
        addik   r3, r7, 0
+       /* Restore register content */
+       lwi     r5, r1, 0
+       lwi     r6, r1, 4
+       lwi     r7, r1, 8
+       lwi     r19, r1, 12
+       lwi     r20, r1, 16
+       lwi     r21, r1, 20
+       lwi     r22, r1, 24
+       lwi     r23, r1, 28
+       lwi     r24, r1, 32
+       lwi     r25, r1, 36
+       addik   r1, r1, 40
+       /* return back */
        rtsd    r15, 8
        nop
 
index e21507052066fbfe5aaec7185286376f2eaf4d02..9c717bf98ffe629f9f9c4061bd49b9114a9a99f5 100644 (file)
@@ -58,8 +58,8 @@ static void __init ar913x_wmac_setup(void)
 
 static int ar933x_wmac_reset(void)
 {
-       ath79_device_reset_clear(AR933X_RESET_WMAC);
        ath79_device_reset_set(AR933X_RESET_WMAC);
+       ath79_device_reset_clear(AR933X_RESET_WMAC);
 
        return 0;
 }
index b6bb92c16a47e94981f6e49672554b82c228491f..41dd008849757f2cbeec99f00cdf7193e80ac874 100644 (file)
@@ -157,7 +157,7 @@ static void octeon_dma_sync_sg_for_device(struct device *dev,
 }
 
 static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t *dma_handle, gfp_t gfp)
+       dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
 {
        void *ret;
 
@@ -192,7 +192,7 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
 }
 
 static void octeon_dma_free_coherent(struct device *dev, size_t size,
-       void *vaddr, dma_addr_t dma_handle)
+       void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
        int order = get_order(size);
 
@@ -240,8 +240,8 @@ EXPORT_SYMBOL(dma_to_phys);
 
 static struct octeon_dma_map_ops octeon_linear_dma_map_ops = {
        .dma_map_ops = {
-               .alloc_coherent = octeon_dma_alloc_coherent,
-               .free_coherent = octeon_dma_free_coherent,
+               .alloc = octeon_dma_alloc_coherent,
+               .free = octeon_dma_free_coherent,
                .map_page = octeon_dma_map_page,
                .unmap_page = swiotlb_unmap_page,
                .map_sg = octeon_dma_map_sg,
@@ -325,8 +325,8 @@ void __init plat_swiotlb_setup(void)
 #ifdef CONFIG_PCI
 static struct octeon_dma_map_ops _octeon_pci_dma_map_ops = {
        .dma_map_ops = {
-               .alloc_coherent = octeon_dma_alloc_coherent,
-               .free_coherent = octeon_dma_free_coherent,
+               .alloc = octeon_dma_alloc_coherent,
+               .free = octeon_dma_free_coherent,
                .map_page = octeon_dma_map_page,
                .unmap_page = swiotlb_unmap_page,
                .map_sg = octeon_dma_map_sg,
index c3e2b85c3b0294ef75315e683100c730ace5820a..97e7ce9b50ed4066d276ed98e47937bfd5236d42 100644 (file)
@@ -78,7 +78,7 @@ static inline void octeon_send_ipi_mask(const struct cpumask *mask,
 }
 
 /**
- * Detect available CPUs, populate cpu_possible_map
+ * Detect available CPUs, populate cpu_possible_mask
  */
 static void octeon_smp_hotplug_setup(void)
 {
@@ -268,7 +268,7 @@ static int octeon_cpu_disable(void)
 
        spin_lock(&smp_reserve_lock);
 
-       cpu_clear(cpu, cpu_online_map);
+       set_cpu_online(cpu, false);
        cpu_clear(cpu, cpu_callin_map);
        local_irq_disable();
        fixup_irqs();
index 7aa37ddfca4ba59b25603183a1d5bca23099fa9c..be39a12901c6c33563b2abedf3a7698caf76ed4c 100644 (file)
@@ -57,25 +57,31 @@ dma_set_mask(struct device *dev, u64 mask)
 extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
               enum dma_data_direction direction);
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t gfp)
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t gfp,
+                                   struct dma_attrs *attrs)
 {
        void *ret;
        struct dma_map_ops *ops = get_dma_ops(dev);
 
-       ret = ops->alloc_coherent(dev, size, dma_handle, gfp);
+       ret = ops->alloc(dev, size, dma_handle, gfp, attrs);
 
        debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
 
        return ret;
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *vaddr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *vaddr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
 
-       ops->free_coherent(dev, size, vaddr, dma_handle);
+       ops->free(dev, size, vaddr, dma_handle, attrs);
 
        debug_dma_free_coherent(dev, size, vaddr, dma_handle);
 }
index a865c983c70affffc26ce5c00ab8742df7a442e8..5ad1a9c113c624136c6f2bfd584906c72f62d7a5 100644 (file)
@@ -45,7 +45,7 @@
 #define JZ4740_IRQ_LCD         JZ4740_IRQ(30)
 
 /* 2nd-level interrupts */
-#define JZ4740_IRQ_DMA(x)      (JZ4740_IRQ(32) + (X))
+#define JZ4740_IRQ_DMA(x)      (JZ4740_IRQ(32) + (x))
 
 #define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x))
 #define JZ4740_IRQ_GPIO(x)     (JZ4740_IRQ(48) + (x))
index 73c0d45798dec6cf00fc99021fc4bc00664ccaad..9b02cfba7449ff7ceb2a1b56d4f8876efef38ca5 100644 (file)
@@ -37,12 +37,6 @@ extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
                write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
        } while (0)
 
-
-static inline unsigned long get_current_pgd(void)
-{
-       return PHYS_TO_XKSEG_CACHED((read_c0_context() >> 11) & ~0xfffUL);
-}
-
 #else /* CONFIG_MIPS_PGD_C0_CONTEXT: using  pgd_current*/
 
 /*
index 802e6160f37e987802ac60b2e1cec193b4c832af..33f63bab478a7478ad34733eaa861f3aba01e78b 100644 (file)
@@ -173,7 +173,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
        if (retval)
                goto out_unlock;
 
-       cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+       cpumask_and(&mask, &p->thread.user_cpus_allowed, cpu_possible_mask);
 
 out_unlock:
        read_unlock(&tasklist_lock);
index e309665b6c81962a82cb247b76f7b0312b0ba172..f8b2c592514de3293e219d92bb59939ec51e8ace 100644 (file)
@@ -25,7 +25,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        int i;
 
 #ifdef CONFIG_SMP
-       if (!cpu_isset(n, cpu_online_map))
+       if (!cpu_online(n))
                return 0;
 #endif
 
index 185ca00c4c84d53be39e2d7e98031f37b6a0d5bf..d5a338a1739c9027fcc3db50c30a59f15f6c2e62 100644 (file)
@@ -257,11 +257,8 @@ asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
                return -EFAULT;
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
-       spin_lock_irq(&current->sighand->siglock);
        current->saved_sigmask = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&newset);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -286,11 +283,8 @@ asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
                return -EFAULT;
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
-       spin_lock_irq(&current->sighand->siglock);
        current->saved_sigmask = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&newset);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -362,10 +356,7 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs)
                goto badframe;
 
        sigdelsetmask(&blocked, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = blocked;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&blocked);
 
        sig = restore_sigcontext(&regs, &frame->sf_sc);
        if (sig < 0)
@@ -401,10 +392,7 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
        if (sig < 0)
@@ -580,12 +568,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
        if (ret)
                return ret;
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked, sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       block_sigmask(ka, sig);
 
        return ret;
 }
index 06b5da392e243ec652ba0a2e1dd25128ac005305..ac3b8d89aae51a4a75f14249ddc5a4f894046087 100644 (file)
@@ -290,11 +290,8 @@ asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
                return -EFAULT;
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
-       spin_lock_irq(&current->sighand->siglock);
        current->saved_sigmask = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&newset);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -318,11 +315,8 @@ asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
                return -EFAULT;
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
-       spin_lock_irq(&current->sighand->siglock);
        current->saved_sigmask = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&newset);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -488,10 +482,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
                goto badframe;
 
        sigdelsetmask(&blocked, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = blocked;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&blocked);
 
        sig = restore_sigcontext32(&regs, &frame->sf_sc);
        if (sig < 0)
@@ -529,10 +520,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
        if (sig < 0)
index ae29e894ab8d0f0cf099d28dbcc1f6cf0751e546..86eb4b04631c43924527231da81e3e23a5b01d0e 100644 (file)
@@ -93,11 +93,8 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
        sigset_from_compat(&newset, &uset);
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
-       spin_lock_irq(&current->sighand->siglock);
        current->saved_sigmask = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&newset);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -121,10 +118,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
        if (sig < 0)
index ca673569fd2421d390fbdd33029b98110727acae..3046e2986006b448c884bbb7355a676cc63e6ad9 100644 (file)
@@ -317,7 +317,7 @@ static int bmips_cpu_disable(void)
 
        pr_info("SMP: CPU%d is offline\n", cpu);
 
-       cpu_clear(cpu, cpu_online_map);
+       set_cpu_online(cpu, false);
        cpu_clear(cpu, cpu_callin_map);
 
        local_flush_tlb_all();
index 9c1cce9de35fdf9ff28168a87f344b84ffc3370f..ba9376bf52a1e80bdaaef76201b50d973c932d0c 100644 (file)
@@ -148,7 +148,7 @@ static void stop_this_cpu(void *dummy)
        /*
         * Remove this CPU:
         */
-       cpu_clear(smp_processor_id(), cpu_online_map);
+       set_cpu_online(smp_processor_id(), false);
        for (;;) {
                if (cpu_wait)
                        (*cpu_wait)();          /* Wait if available. */
@@ -174,7 +174,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        mp_ops->prepare_cpus(max_cpus);
        set_cpu_sibling_map(0);
 #ifndef CONFIG_HOTPLUG_CPU
-       init_cpu_present(&cpu_possible_map);
+       init_cpu_present(cpu_possible_mask);
 #endif
 }
 
@@ -248,7 +248,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
        while (!cpu_isset(cpu, cpu_callin_map))
                udelay(100);
 
-       cpu_set(cpu, cpu_online_map);
+       set_cpu_online(cpu, true);
 
        return 0;
 }
@@ -320,13 +320,12 @@ void flush_tlb_mm(struct mm_struct *mm)
        if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
                smp_on_other_tlbs(flush_tlb_mm_ipi, mm);
        } else {
-               cpumask_t mask = cpu_online_map;
                unsigned int cpu;
 
-               cpu_clear(smp_processor_id(), mask);
-               for_each_cpu_mask(cpu, mask)
-                       if (cpu_context(cpu, mm))
+               for_each_online_cpu(cpu) {
+                       if (cpu != smp_processor_id() && cpu_context(cpu, mm))
                                cpu_context(cpu, mm) = 0;
+               }
        }
        local_flush_tlb_mm(mm);
 
@@ -360,13 +359,12 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned l
 
                smp_on_other_tlbs(flush_tlb_range_ipi, &fd);
        } else {
-               cpumask_t mask = cpu_online_map;
                unsigned int cpu;
 
-               cpu_clear(smp_processor_id(), mask);
-               for_each_cpu_mask(cpu, mask)
-                       if (cpu_context(cpu, mm))
+               for_each_online_cpu(cpu) {
+                       if (cpu != smp_processor_id() && cpu_context(cpu, mm))
                                cpu_context(cpu, mm) = 0;
+               }
        }
        local_flush_tlb_range(vma, start, end);
        preempt_enable();
@@ -407,13 +405,12 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 
                smp_on_other_tlbs(flush_tlb_page_ipi, &fd);
        } else {
-               cpumask_t mask = cpu_online_map;
                unsigned int cpu;
 
-               cpu_clear(smp_processor_id(), mask);
-               for_each_cpu_mask(cpu, mask)
-                       if (cpu_context(cpu, vma->vm_mm))
+               for_each_online_cpu(cpu) {
+                       if (cpu != smp_processor_id() && cpu_context(cpu, vma->vm_mm))
                                cpu_context(cpu, vma->vm_mm) = 0;
+               }
        }
        local_flush_tlb_page(vma, page);
        preempt_enable();
index c4f75bbc0bd6160deedbb7ec127feb6e2c3bdc7f..f5dd38f1d0152b49b13c971c59fde0cd218cb93e 100644 (file)
@@ -291,7 +291,7 @@ static void smtc_configure_tlb(void)
  * possibly leave some TCs/VPEs as "slave" processors.
  *
  * Use c0_MVPConf0 to find out how many TCs are available, setting up
- * cpu_possible_map and the logical/physical mappings.
+ * cpu_possible_mask and the logical/physical mappings.
  */
 
 int __init smtc_build_cpu_map(int start_cpu_slot)
index 1f9ca07f53c8f33335cb316e11d6d61733e748cf..47037ec5589b88bca92df21c81a3a890f937bd36 100644 (file)
@@ -80,9 +80,9 @@ static void octeon_flush_icache_all_cores(struct vm_area_struct *vma)
        if (vma)
                mask = *mm_cpumask(vma->vm_mm);
        else
-               mask = cpu_online_map;
-       cpu_clear(cpu, mask);
-       for_each_cpu_mask(cpu, mask)
+               mask = *cpu_online_mask;
+       cpumask_clear_cpu(cpu, &mask);
+       for_each_cpu(cpu, &mask)
                octeon_send_ipi_single(cpu, SMP_ICACHE_FLUSH);
 
        preempt_enable();
index 46084912e58880ffe2eb13e6ac4a2c9a0993b893..3fab2046c8a430d762ca800b905672fadc5e4572 100644 (file)
@@ -98,7 +98,7 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
 EXPORT_SYMBOL(dma_alloc_noncoherent);
 
 static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t * dma_handle, gfp_t gfp)
+       dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
 {
        void *ret;
 
@@ -132,7 +132,7 @@ void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
 EXPORT_SYMBOL(dma_free_noncoherent);
 
 static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle)
+       dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
        unsigned long addr = (unsigned long) vaddr;
        int order = get_order(size);
@@ -323,8 +323,8 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 EXPORT_SYMBOL(dma_cache_sync);
 
 static struct dma_map_ops mips_default_dma_map_ops = {
-       .alloc_coherent = mips_dma_alloc_coherent,
-       .free_coherent = mips_dma_free_coherent,
+       .alloc = mips_dma_alloc_coherent,
+       .free = mips_dma_free_coherent,
        .map_page = mips_dma_map_page,
        .unmap_page = mips_dma_unmap_page,
        .map_sg = mips_dma_map_sg,
index db17f49886c26681b5fe1d61555e7c7b5f8602b9..fab316de57e96718a38abcd1c8434ca54b7ab363 100644 (file)
@@ -165,7 +165,7 @@ void __init nlm_smp_setup(void)
        cpu_set(boot_cpu, phys_cpu_present_map);
        __cpu_number_map[boot_cpu] = 0;
        __cpu_logical_map[0] = boot_cpu;
-       cpu_set(0, cpu_possible_map);
+       set_cpu_possible(0, true);
 
        num_cpus = 1;
        for (i = 0; i < NR_CPUS; i++) {
@@ -177,14 +177,14 @@ void __init nlm_smp_setup(void)
                        cpu_set(i, phys_cpu_present_map);
                        __cpu_number_map[i] = num_cpus;
                        __cpu_logical_map[num_cpus] = i;
-                       cpu_set(num_cpus, cpu_possible_map);
+                       set_cpu_possible(num_cpus, true);
                        ++num_cpus;
                }
        }
 
        pr_info("Phys CPU present map: %lx, possible map %lx\n",
                (unsigned long)phys_cpu_present_map.bits[0],
-               (unsigned long)cpu_possible_map.bits[0]);
+               (unsigned long)cpumask_bits(cpu_possible_mask)[0]);
 
        pr_info("Detected %i Slave CPU(s)\n", num_cpus);
        nlm_set_nmi_handler(nlm_boot_secondary_cpus);
index 2608752898c0823671b51773178edcd6e945398c..b71fae231049dfa86d25f3e5fef2216d968faa17 100644 (file)
@@ -146,7 +146,7 @@ static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle)
 }
 
 /*
- * Detect available CPUs, populate cpu_possible_map before smp_init
+ * Detect available CPUs, populate cpu_possible_mask before smp_init
  *
  * We don't want to start the secondary CPU yet nor do we have a nice probing
  * feature in PMON so we just assume presence of the secondary core.
@@ -155,10 +155,10 @@ static void __init yos_smp_setup(void)
 {
        int i;
 
-       cpus_clear(cpu_possible_map);
+       init_cpu_possible(cpu_none_mask);
 
        for (i = 0; i < 2; i++) {
-               cpu_set(i, cpu_possible_map);
+               set_cpu_possible(i, true);
                __cpu_number_map[i]     = i;
                __cpu_logical_map[i]    = i;
        }
@@ -169,7 +169,7 @@ static void __init yos_prepare_cpus(unsigned int max_cpus)
        /*
         * Be paranoid.  Enable the IPI only if we're really about to go SMP.
         */
-       if (cpus_weight(cpu_possible_map))
+       if (num_possible_cpus())
                set_c0_status(STATUSF_IP5);
 }
 
index c6851df9ab741a4979ca373bc32b32862bfb5038..735b43bf8f82eebc8eec907c925b800cf49c544e 100644 (file)
@@ -76,7 +76,7 @@ static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest)
                        /* Only let it join in if it's marked enabled */
                        if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
                            (tot_cpus_found != NR_CPUS)) {
-                               cpu_set(cpuid, cpu_possible_map);
+                               set_cpu_possible(cpuid, true);
                                alloc_cpupda(cpuid, tot_cpus_found);
                                cpus_found++;
                                tot_cpus_found++;
index d667875be564ef97dbd55cc6ffced70e207ff202..de88e22694a05940b4dae2fd123688f7849fcdf8 100644 (file)
@@ -138,7 +138,7 @@ static void __cpuinit bcm1480_boot_secondary(int cpu, struct task_struct *idle)
 
 /*
  * Use CFE to find out how many CPUs are available, setting up
- * cpu_possible_map and the logical/physical mappings.
+ * cpu_possible_mask and the logical/physical mappings.
  * XXXKW will the boot CPU ever not be physical 0?
  *
  * Common setup before any secondaries are started
@@ -147,14 +147,13 @@ static void __init bcm1480_smp_setup(void)
 {
        int i, num;
 
-       cpus_clear(cpu_possible_map);
-       cpu_set(0, cpu_possible_map);
+       init_cpu_possible(cpumask_of(0));
        __cpu_number_map[0] = 0;
        __cpu_logical_map[0] = 0;
 
        for (i = 1, num = 0; i < NR_CPUS; i++) {
                if (cfe_cpu_stop(i) == 0) {
-                       cpu_set(i, cpu_possible_map);
+                       set_cpu_possible(i, true);
                        __cpu_number_map[i] = ++num;
                        __cpu_logical_map[num] = i;
                }
index 38e7f6bd7922edd6c25e2169515cdccacfc81ea7..285cfef4ebc083cc24a554c3bb4a534a9092f48c 100644 (file)
@@ -126,7 +126,7 @@ static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle)
 
 /*
  * Use CFE to find out how many CPUs are available, setting up
- * cpu_possible_map and the logical/physical mappings.
+ * cpu_possible_mask and the logical/physical mappings.
  * XXXKW will the boot CPU ever not be physical 0?
  *
  * Common setup before any secondaries are started
@@ -135,14 +135,13 @@ static void __init sb1250_smp_setup(void)
 {
        int i, num;
 
-       cpus_clear(cpu_possible_map);
-       cpu_set(0, cpu_possible_map);
+       init_cpu_possible(cpumask_of(0));
        __cpu_number_map[0] = 0;
        __cpu_logical_map[0] = 0;
 
        for (i = 1, num = 0; i < NR_CPUS; i++) {
                if (cfe_cpu_stop(i) == 0) {
-                       cpu_set(i, cpu_possible_map);
+                       set_cpu_possible(i, true);
                        __cpu_number_map[i] = ++num;
                        __cpu_logical_map[num] = i;
                }
index 3ae56073cc3d717a8ab82b78be379d6fe52fb4e3..6c6defc24619fbab673b6296387c1dead503158b 100644 (file)
@@ -6,6 +6,7 @@
 #define _ASM_PARISC_ATOMIC_H_
 
 #include <linux/types.h>
+#include <asm/cmpxchg.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -48,112 +49,6 @@ extern arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
 #  define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0)
 #endif
 
-/* This should get optimized out since it's never called.
-** Or get a link error if xchg is used "wrong".
-*/
-extern void __xchg_called_with_bad_pointer(void);
-
-
-/* __xchg32/64 defined in arch/parisc/lib/bitops.c */
-extern unsigned long __xchg8(char, char *);
-extern unsigned long __xchg32(int, int *);
-#ifdef CONFIG_64BIT
-extern unsigned long __xchg64(unsigned long, unsigned long *);
-#endif
-
-/* optimizer better get rid of switch since size is a constant */
-static __inline__ unsigned long
-__xchg(unsigned long x, __volatile__ void * ptr, int size)
-{
-       switch(size) {
-#ifdef CONFIG_64BIT
-       case 8: return __xchg64(x,(unsigned long *) ptr);
-#endif
-       case 4: return __xchg32((int) x, (int *) ptr);
-       case 1: return __xchg8((char) x, (char *) ptr);
-       }
-       __xchg_called_with_bad_pointer();
-       return x;
-}
-
-
-/*
-** REVISIT - Abandoned use of LDCW in xchg() for now:
-** o need to test sizeof(*ptr) to avoid clearing adjacent bytes
-** o and while we are at it, could CONFIG_64BIT code use LDCD too?
-**
-**     if (__builtin_constant_p(x) && (x == NULL))
-**             if (((unsigned long)p & 0xf) == 0)
-**                     return __ldcw(p);
-*/
-#define xchg(ptr,x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-
-#define __HAVE_ARCH_CMPXCHG    1
-
-/* bug catcher for when unsupported size is used - won't link */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-/* __cmpxchg_u32/u64 defined in arch/parisc/lib/bitops.c */
-extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old, unsigned int new_);
-extern unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new_);
-
-/* don't worry...optimizer will get rid of most of this */
-static __inline__ unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
-{
-       switch(size) {
-#ifdef CONFIG_64BIT
-       case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
-#endif
-       case 4: return __cmpxchg_u32((unsigned int *)ptr, (unsigned int) old, (unsigned int) new_);
-       }
-       __cmpxchg_called_with_bad_pointer();
-       return old;
-}
-
-#define cmpxchg(ptr,o,n)                                                \
-  ({                                                                    \
-     __typeof__(*(ptr)) _o_ = (o);                                      \
-     __typeof__(*(ptr)) _n_ = (n);                                      \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
-                                   (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-                                     unsigned long old,
-                                     unsigned long new_, int size)
-{
-       switch (size) {
-#ifdef CONFIG_64BIT
-       case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
-#endif
-       case 4: return __cmpxchg_u32(ptr, old, new_);
-       default:
-               return __cmpxchg_local_generic(ptr, old, new_, size);
-       }
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                       \
-       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
-                       (unsigned long)(n), sizeof(*(ptr))))
-#ifdef CONFIG_64BIT
-#define cmpxchg64_local(ptr, o, n)                                     \
-  ({                                                                   \
-       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
-       cmpxchg_local((ptr), (o), (n));                                 \
-  })
-#else
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-#endif
-
 /*
  * Note that we need not lock read accesses - aligned word writes/reads
  * are atomic, so a reader never sees inconsistent values.
diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..dbd1335
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * forked from parisc asm/atomic.h which was:
+ *     Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *     Copyright (C) 2006 Kyle McMartin <kyle@parisc-linux.org>
+ */
+
+#ifndef _ASM_PARISC_CMPXCHG_H_
+#define _ASM_PARISC_CMPXCHG_H_
+
+/* This should get optimized out since it's never called.
+** Or get a link error if xchg is used "wrong".
+*/
+extern void __xchg_called_with_bad_pointer(void);
+
+/* __xchg32/64 defined in arch/parisc/lib/bitops.c */
+extern unsigned long __xchg8(char, char *);
+extern unsigned long __xchg32(int, int *);
+#ifdef CONFIG_64BIT
+extern unsigned long __xchg64(unsigned long, unsigned long *);
+#endif
+
+/* optimizer better get rid of switch since size is a constant */
+static inline unsigned long
+__xchg(unsigned long x, __volatile__ void *ptr, int size)
+{
+       switch (size) {
+#ifdef CONFIG_64BIT
+       case 8: return __xchg64(x, (unsigned long *) ptr);
+#endif
+       case 4: return __xchg32((int) x, (int *) ptr);
+       case 1: return __xchg8((char) x, (char *) ptr);
+       }
+       __xchg_called_with_bad_pointer();
+       return x;
+}
+
+/*
+** REVISIT - Abandoned use of LDCW in xchg() for now:
+** o need to test sizeof(*ptr) to avoid clearing adjacent bytes
+** o and while we are at it, could CONFIG_64BIT code use LDCD too?
+**
+**     if (__builtin_constant_p(x) && (x == NULL))
+**             if (((unsigned long)p & 0xf) == 0)
+**                     return __ldcw(p);
+*/
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+#define __HAVE_ARCH_CMPXCHG    1
+
+/* bug catcher for when unsupported size is used - won't link */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+/* __cmpxchg_u32/u64 defined in arch/parisc/lib/bitops.c */
+extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old,
+                                  unsigned int new_);
+extern unsigned long __cmpxchg_u64(volatile unsigned long *ptr,
+                                  unsigned long old, unsigned long new_);
+
+/* don't worry...optimizer will get rid of most of this */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
+{
+       switch (size) {
+#ifdef CONFIG_64BIT
+       case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
+#endif
+       case 4: return __cmpxchg_u32((unsigned int *)ptr,
+                                    (unsigned int)old, (unsigned int)new_);
+       }
+       __cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define cmpxchg(ptr, o, n)                                              \
+({                                                                      \
+       __typeof__(*(ptr)) _o_ = (o);                                    \
+       __typeof__(*(ptr)) _n_ = (n);                                    \
+       (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,        \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+})
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+                                     unsigned long old,
+                                     unsigned long new_, int size)
+{
+       switch (size) {
+#ifdef CONFIG_64BIT
+       case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
+#endif
+       case 4: return __cmpxchg_u32(ptr, old, new_);
+       default:
+               return __cmpxchg_local_generic(ptr, old, new_, size);
+       }
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                       \
+       ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+                       (unsigned long)(n), sizeof(*(ptr))))
+#ifdef CONFIG_64BIT
+#define cmpxchg64_local(ptr, o, n)                                     \
+({                                                                     \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_local((ptr), (o), (n));                                 \
+})
+#else
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+#endif
+
+#endif /* _ASM_PARISC_CMPXCHG_H_ */
index 4f004596a6e7ad920674fb14780c668fe015b965..0b3393381a81261209d8b0fac80d20b6db7654c2 100644 (file)
@@ -104,7 +104,7 @@ static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp)
 
 static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp)
 {
-       if (!tty->count) {
+       if (tty->count == 1) {
                del_timer_sync(&pdc_console_timer);
                tty_port_tty_set(&tty_port, NULL);
        }
diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi
new file mode 100644 (file)
index 0000000..1cf0b77
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * PQ3 MPIC Message (Group B) device tree stub [ controller @ offset 0x42400 ]
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+message@42400 {
+       compatible = "fsl,mpic-v3.1-msgr";
+       reg = <0x42400 0x200>;
+       interrupts = <
+               0xb4 2 0 0
+               0xb5 2 0 0
+               0xb6 2 0 0
+               0xb7 2 0 0>;
+};
index fdedf7b1fe0f2e25d47729470e1665be9615a3d8..71c30eb10056962c439d6e7900415d9c27c829fc 100644 (file)
@@ -53,6 +53,16 @@ timer@41100 {
                      3 0 3 0>;
 };
 
+message@41400 {
+       compatible = "fsl,mpic-v3.1-msgr";
+       reg = <0x41400 0x200>;
+       interrupts = <
+               0xb0 2 0 0
+               0xb1 2 0 0
+               0xb2 2 0 0
+               0xb3 2 0 0>;
+};
+
 msi@41600 {
        compatible = "fsl,mpic-msi";
        reg = <0x41600 0x80>;
diff --git a/arch/powerpc/boot/dts/p1020mbg-pc.dtsi b/arch/powerpc/boot/dts/p1020mbg-pc.dtsi
new file mode 100644 (file)
index 0000000..a24699c
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * P1020 MBG-PC Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&lbc {
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x4000000>;
+               bank-width = <2>;
+               device-width = <1>;
+
+               partition@0 {
+                       /* 128KB for DTB Image */
+                       reg = <0x0 0x00020000>;
+                       label = "NOR DTB Image";
+               };
+
+               partition@20000 {
+                       /* 3.875 MB for Linux Kernel Image */
+                       reg = <0x00020000 0x003e0000>;
+                       label = "NOR Linux Kernel Image";
+               };
+
+               partition@400000 {
+                       /* 58MB for Root file System */
+                       reg = <0x00400000 0x03a00000>;
+                       label = "NOR Root File System";
+               };
+
+               partition@3e00000 {
+                       /* This location must not be altered  */
+                       /* 1M for Vitesse 7385 Switch firmware */
+                       reg = <0x3e00000 0x00100000>;
+                       label = "NOR Vitesse-7385 Firmware";
+                       read-only;
+               };
+
+               partition@3f00000 {
+                       /* This location must not be altered  */
+                       /* 512KB for u-boot Bootloader Image */
+                       /* 512KB for u-boot Environment Variables */
+                       reg = <0x03f00000 0x00100000>;
+                       label = "NOR U-Boot Image";
+                       read-only;
+               };
+       };
+
+       L2switch@2,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "vitesse-7385";
+               reg = <0x2 0x0 0x20000>;
+       };
+};
+
+&soc {
+       i2c@3000 {
+               rtc@68 {
+                       compatible = "dallas,ds1339";
+                       reg = <0x68>;
+               };
+       };
+
+       mdio@24000 {
+               phy0: ethernet-phy@0 {
+                       interrupts = <3 1 0 0>;
+                       reg = <0x0>;
+               };
+               phy1: ethernet-phy@1 {
+                       interrupts = <2 1 0 0>;
+                       reg = <0x1>;
+               };
+       };
+
+       mdio@25000 {
+               tbi1: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       mdio@26000 {
+               tbi2: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       enet0: ethernet@b0000 {
+               fixed-link = <1 1 1000 0 0>;
+               phy-connection-type = "rgmii-id";
+       };
+
+       enet1: ethernet@b1000 {
+               phy-handle = <&phy0>;
+               tbi-handle = <&tbi1>;
+               phy-connection-type = "sgmii";
+       };
+
+       enet2: ethernet@b2000 {
+               phy-handle = <&phy1>;
+               phy-connection-type = "rgmii-id";
+       };
+
+       usb@22000 {
+               phy_type = "ulpi";
+       };
+
+       /* USB2 is shared with localbus, so it must be disabled
+          by default. We can't put 'status = "disabled";' here
+          since U-Boot doesn't clear the status property when
+          it enables USB2. OTOH, U-Boot does create a new node
+          when there isn't any. So, just comment it out.
+       */
+       usb@23000 {
+               status = "disabled";
+               phy_type = "ulpi";
+       };
+};
diff --git a/arch/powerpc/boot/dts/p1020mbg-pc_32b.dts b/arch/powerpc/boot/dts/p1020mbg-pc_32b.dts
new file mode 100644 (file)
index 0000000..ab8f076
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * P1020 MBG-PC Device Tree Source (32-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+       model = "fsl,P1020MBG-PC";
+       compatible = "fsl,P1020MBG-PC";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@ffe05000 {
+               reg = <0x0 0xffe05000 0x0 0x1000>;
+
+               /* NOR and L2 switch */
+               ranges = <0x0 0x0 0x0 0xec000000 0x04000000
+                         0x1 0x0 0x0 0xffa00000 0x00040000
+                         0x2 0x0 0x0 0xffb00000 0x00020000>;
+       };
+
+       soc: soc@ffe00000 {
+               ranges = <0x0 0x0 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@ffe09000 {
+               reg = <0x0 0xffe09000 0x0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0x0 0xa0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0x0 0xffc10000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@ffe0a000 {
+               reg = <0x0 0xffe0a000 0x0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0x0 0x80000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0x0 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
+
+/include/ "p1020mbg-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020mbg-pc_36b.dts b/arch/powerpc/boot/dts/p1020mbg-pc_36b.dts
new file mode 100644 (file)
index 0000000..9e9f401
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * P1020 MBG-PC Device Tree Source (36-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+       model = "fsl,P1020MBG-PC";
+       compatible = "fsl,P1020MBG-PC";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@fffe05000 {
+               reg = <0xf 0xffe05000 0x0 0x1000>;
+
+               /* NOR and L2 switch */
+               ranges = <0x0 0x0 0xf 0xec000000 0x04000000
+                         0x1 0x0 0xf 0xffa00000 0x00040000
+                         0x2 0x0 0xf 0xffb00000 0x00020000>;
+       };
+
+       soc: soc@fffe00000 {
+               ranges = <0x0 0xf 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@fffe09000 {
+               reg = <0xf 0xffe09000 0x0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@fffe0a000 {
+               reg = <0xf 0xffe0a000 0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
+
+/include/ "p1020mbg-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020utm-pc.dtsi b/arch/powerpc/boot/dts/p1020utm-pc.dtsi
new file mode 100644 (file)
index 0000000..7ea85ea
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * P1020 UTM-PC Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&lbc {
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x2000000>;
+               bank-width = <2>;
+               device-width = <1>;
+
+               partition@0 {
+                       /* 256KB for DTB Image */
+                       reg = <0x0 0x00040000>;
+                       label = "NOR DTB Image";
+               };
+
+               partition@40000 {
+                       /* 3.75 MB for Linux Kernel Image */
+                       reg = <0x00040000 0x003c0000>;
+                       label = "NOR Linux Kernel Image";
+               };
+
+               partition@400000 {
+                       /* 27MB for Root file System */
+                       reg = <0x00400000 0x01b00000>;
+                       label = "NOR Root File System";
+               };
+
+               partition@1f00000 {
+                       /* This location must not be altered  */
+                       /* 512KB for u-boot Bootloader Image */
+                       /* 512KB for u-boot Environment Variables */
+                       reg = <0x01f00000 0x00100000>;
+                       label = "NOR U-Boot Image";
+                       read-only;
+               };
+       };
+};
+
+&soc {
+       i2c@3000 {
+               rtc@68 {
+                       compatible = "dallas,ds1339";
+                       reg = <0x68>;
+               };
+       };
+
+       mdio@24000 {
+               phy0: ethernet-phy@0 {
+                       interrupts = <3 1 0 0>;
+                       reg = <0x0>;
+               };
+               phy1: ethernet-phy@1 {
+                       interrupts = <2 1 0 0>;
+                       reg = <0x1>;
+               };
+               phy2: ethernet-phy@2 {
+                       interrupts = <1 1 0 0>;
+                       reg = <0x2>;
+               };
+       };
+
+       mdio@25000 {
+               tbi1: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       mdio@26000 {
+               tbi2: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       enet0: ethernet@b0000 {
+               phy-handle = <&phy2>;
+               phy-connection-type = "rgmii-id";
+       };
+
+       enet1: ethernet@b1000 {
+               phy-handle = <&phy0>;
+               tbi-handle = <&tbi1>;
+               phy-connection-type = "sgmii";
+       };
+
+       enet2: ethernet@b2000 {
+               phy-handle = <&phy1>;
+               phy-connection-type = "rgmii-id";
+       };
+
+       usb@22000 {
+               phy_type = "ulpi";
+       };
+
+       /* USB2 is shared with localbus, so it must be disabled
+          by default. We can't put 'status = "disabled";' here
+          since U-Boot doesn't clear the status property when
+          it enables USB2. OTOH, U-Boot does create a new node
+          when there isn't any. So, just comment it out.
+       */
+       usb@23000 {
+               status = "disabled";
+               phy_type = "ulpi";
+       };
+};
diff --git a/arch/powerpc/boot/dts/p1020utm-pc_32b.dts b/arch/powerpc/boot/dts/p1020utm-pc_32b.dts
new file mode 100644 (file)
index 0000000..4bfdd89
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * P1020 UTM-PC Device Tree Source (32-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+       model = "fsl,P1020UTM-PC";
+       compatible = "fsl,P1020UTM-PC";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@ffe05000 {
+               reg = <0x0 0xffe05000 0x0 0x1000>;
+
+               /* NOR */
+               ranges = <0x0 0x0 0x0 0xec000000 0x02000000
+                         0x1 0x0 0x0 0xffa00000 0x00040000
+                         0x2 0x0 0x0 0xffb00000 0x00020000>;
+       };
+
+       soc: soc@ffe00000 {
+               ranges = <0x0 0x0 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@ffe09000 {
+               reg = <0x0 0xffe09000 0x0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0x0 0xa0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0x0 0xffc10000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@ffe0a000 {
+               reg = <0x0 0xffe0a000 0x0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0x0 0x80000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0x0 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
+
+/include/ "p1020utm-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020utm-pc_36b.dts b/arch/powerpc/boot/dts/p1020utm-pc_36b.dts
new file mode 100644 (file)
index 0000000..abec535
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * P1020 UTM-PC Device Tree Source (36-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+       model = "fsl,P1020UTM-PC";
+       compatible = "fsl,P1020UTM-PC";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@fffe05000 {
+               reg = <0xf 0xffe05000 0x0 0x1000>;
+
+               /* NOR */
+               ranges = <0x0 0x0 0xf 0xec000000 0x02000000
+                         0x1 0x0 0xf 0xffa00000 0x00040000
+                         0x2 0x0 0xf 0xffb00000 0x00020000>;
+       };
+
+       soc: soc@fffe00000 {
+               ranges = <0x0 0xf 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@fffe09000 {
+               reg = <0xf 0xffe09000 0x0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@fffe0a000 {
+               reg = <0xf 0xffe0a000 0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
+
+/include/ "p1020utm-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
index 4f957db01230906e23b8cdd854a2f4ac00813491..285213976a7f18811e5a90e5f00af2858c9a1cdd 100644 (file)
                reg = <0xf 0xfe200000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-               fsl,msi = <&msi0>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe201000 0 0x1000>;
                ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
                          0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-               fsl,msi = <&msi1>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe202000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
-               fsl,msi = <&msi2>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
index f469145abaeb420e8dc31b44a87672273c14ab4d..22a215e94162362be8525740d0836a14efca4cb9 100644 (file)
                reg = <0xf 0xfe200000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-               fsl,msi = <&msi0>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe201000 0 0x1000>;
                ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
                          0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-               fsl,msi = <&msi1>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe202000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
-               fsl,msi = <&msi2>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe203000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
-               fsl,msi = <&msi2>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
index 529042e4b9a22427577bc99211b9582a1f260aae..9ae875c8a2117f70ae664da9918b7baa9044b2a0 100644 (file)
                reg = <0xf 0xfe200000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-               fsl,msi = <&msi0>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe201000 0 0x1000>;
                ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
                          0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-               fsl,msi = <&msi1>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
index 6d60e54e50a09a6fbbec45d686f85ba7b5c00fa3..3e204609d02e51905183ca21478ab6ae69e99459 100644 (file)
                reg = <0xf 0xfe200000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-               fsl,msi = <&msi0>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe201000 0 0x1000>;
                ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
                          0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-               fsl,msi = <&msi1>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe202000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
-               fsl,msi = <&msi2>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
index 1c250684c9028cfa70e17c675292d72247a69da1..27c07ed6adc1490921bceabcd6be5dac1cdb58b2 100644 (file)
                reg = <0xf 0xfe200000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-               fsl,msi = <&msi0>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe201000 0 0x1000>;
                ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
                          0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-               fsl,msi = <&msi1>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe202000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
-               fsl,msi = <&msi2>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
                reg = <0xf 0xfe203000 0 0x1000>;
                ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
                          0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
-               fsl,msi = <&msi2>;
                pcie@0 {
                        ranges = <0x02000000 0 0xe0000000
                                  0x02000000 0 0xe0000000
index f8aef205d222234564b46fd7b35dede4ee865fd3..91db656294e85a642f40182b4245231293aaa22b 100644 (file)
@@ -116,6 +116,7 @@ CONFIG_SERIAL_8250_RSA=y
 CONFIG_HW_RANDOM=y
 CONFIG_NVRAM=y
 CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
 CONFIG_SPI=y
 CONFIG_SPI_GPIO=y
index 82b13bfcf3c0bc1cb5fc57f2caf1237aa4445580..6798343580f0bfcd9bc03eaab6baab9e675eb257 100644 (file)
@@ -71,6 +71,8 @@ CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
 CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MPC=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 # CONFIG_HID_SUPPORT is not set
index cc87a8441566d663071aa6b2fff7d105fc796a60..d6b6df5e874355c7c67624f6bdc7dc2a83cbfd82 100644 (file)
@@ -117,6 +117,7 @@ CONFIG_SERIAL_8250_RSA=y
 CONFIG_SERIAL_QE=m
 CONFIG_NVRAM=y
 CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
 CONFIG_SPI=y
index 48d6682f2434bfcc3ea0cbe70eb847e62de92d45..5b0e2926becd0ffdc6142c65a4f1d7fe3bf10969 100644 (file)
@@ -119,6 +119,7 @@ CONFIG_SERIAL_8250_RSA=y
 CONFIG_SERIAL_QE=m
 CONFIG_NVRAM=y
 CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
 CONFIG_SPI=y
index dd70fac57ec896253990fc1761fd3ad96fa6098a..62678e365ca0768e0566329eb957f0058a04897d 100644 (file)
 
 /* Some dma direct funcs must be visible for use in other dma_ops */
 extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t flag);
+                                      dma_addr_t *dma_handle, gfp_t flag,
+                                      struct dma_attrs *attrs);
 extern void dma_direct_free_coherent(struct device *dev, size_t size,
-                                    void *vaddr, dma_addr_t dma_handle);
+                                    void *vaddr, dma_addr_t dma_handle,
+                                    struct dma_attrs *attrs);
 
 
 #ifdef CONFIG_NOT_COHERENT_CACHE
@@ -130,23 +132,29 @@ static inline int dma_supported(struct device *dev, u64 mask)
 
 extern int dma_set_mask(struct device *dev, u64 dma_mask);
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
 {
        struct dma_map_ops *dma_ops = get_dma_ops(dev);
        void *cpu_addr;
 
        BUG_ON(!dma_ops);
 
-       cpu_addr = dma_ops->alloc_coherent(dev, size, dma_handle, flag);
+       cpu_addr = dma_ops->alloc(dev, size, dma_handle, flag, attrs);
 
        debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
 
        return cpu_addr;
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
@@ -154,7 +162,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
 
        debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
 
-       dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+       dma_ops->free(dev, size, cpu_addr, dma_handle, attrs);
 }
 
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
index f3b0c2cc9fea0ce611d07eb7fde72541d62860fa..976835d8f22e2a378f6166ff3ef20b37f7e1e6f9 100644 (file)
  * whether they will be clobbered.
  *
  * Note that r11 can be used as an output parameter.
+ *
+ * The "memory" clobber is only necessary for hcalls where the Hypervisor
+ * will read or write guest memory. However, we add it to all hcalls because
+ * the impact is minimal, and we want to ensure that it's present for the
+ * hcalls that need it.
 */
 
 /* List of common clobbered registers.  Do not use this macro. */
-#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc"
+#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc", "memory"
 
 #define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS
 #define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10"
index ce04530d20003a42e045a634790691c99d715d53..aa4c488589ce51b7bbdf1089db7282e69bfaccad 100644 (file)
 #define __ASM_POWERPC_FSL_GUTS_H__
 #ifdef __KERNEL__
 
-/*
- * These #ifdefs are safe because it's not possible to build a kernel that
- * runs on e500 and e600 cores.
- */
-
-#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx)
-#error Only 85xx and 86xx SOCs are supported
-#endif
-
 /**
  * Global Utility Registers.
  *
  * different names.  In these cases, one name is chosen to avoid extraneous
  * #ifdefs.
  */
-#ifdef CONFIG_PPC_85xx
-struct ccsr_guts_85xx {
-#else
-struct ccsr_guts_86xx {
-#endif
+struct ccsr_guts {
        __be32  porpllsr;       /* 0x.0000 - POR PLL Ratio Status Register */
        __be32  porbmsr;        /* 0x.0004 - POR Boot Mode Status Register */
        __be32  porimpscr;      /* 0x.0008 - POR I/O Impedance Status and Control Register */
@@ -77,11 +64,8 @@ struct ccsr_guts_86xx {
        u8      res0a8[0xb0 - 0xa8];
        __be32  rstcr;          /* 0x.00b0 - Reset Control Register */
        u8      res0b4[0xc0 - 0xb4];
-#ifdef CONFIG_PPC_85xx
-       __be32  iovselsr;       /* 0x.00c0 - I/O voltage select status register */
-#else
-       __be32  elbcvselcr;     /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */
-#endif
+       __be32  iovselsr;       /* 0x.00c0 - I/O voltage select status register
+                                            Called 'elbcvselcr' on 86xx SOCs */
        u8      res0c4[0x224 - 0xc4];
        __be32  iodelay1;       /* 0x.0224 - IO delay control register 1 */
        __be32  iodelay2;       /* 0x.0228 - IO delay control register 2 */
@@ -136,7 +120,7 @@ struct ccsr_guts_86xx {
  * ch: The channel on the DMA controller (0, 1, 2, or 3)
  * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
  */
-static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts,
+static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
        unsigned int co, unsigned int ch, unsigned int device)
 {
        unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
@@ -172,7 +156,7 @@ static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts,
  * ch: The channel on the DMA controller (0, 1, 2, or 3)
  * value: the new value for the bit (0 or 1)
  */
-static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts,
+static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
        unsigned int co, unsigned int ch, unsigned int value)
 {
        if ((ch == 0) || (ch == 3)) {
index cf417e51073627ff6184f15ddd3a78f7948419c7..0e40843a1c6ed58273c1a0e2eb22841e9007e977 100644 (file)
 #include <linux/atomic.h>
 
 
-/* Define a way to iterate across irqs. */
-#define for_each_irq(i) \
-       for ((i) = 0; (i) < NR_IRQS; ++(i))
-
 extern atomic_t ppc_n_lost_interrupts;
 
 /* This number is used when no interrupt has been assigned */
@@ -33,8 +29,6 @@ extern atomic_t ppc_n_lost_interrupts;
 /* Same thing, used by the generic IRQ code */
 #define NR_IRQS_LEGACY         NUM_ISA_INTERRUPTS
 
-struct irq_data;
-extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
 extern irq_hw_number_t virq_to_hw(unsigned int virq);
 
 /**
index c65b9294376ee8e2e1745cf73b014dc1f49d372e..c9f698a994be246860ee6cfdd6895d27d68cea7b 100644 (file)
@@ -275,9 +275,6 @@ struct mpic
        unsigned int            isu_mask;
        /* Number of sources */
        unsigned int            num_sources;
-       /* default senses array */
-       unsigned char           *senses;
-       unsigned int            senses_count;
 
        /* vector numbers used for internal sources (ipi/timers) */
        unsigned int            ipi_vecs[4];
@@ -415,21 +412,6 @@ extern struct mpic *mpic_alloc(struct device_node *node,
 extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
                            phys_addr_t phys_addr);
 
-/* Set default sense codes
- *
- * @mpic:      controller
- * @senses:    array of sense codes
- * @count:     size of above array
- *
- * Optionally provide an array (indexed on hardware interrupt numbers
- * for this MPIC) of default sense codes for the chip. Those are linux
- * sense codes IRQ_TYPE_*
- *
- * The driver gets ownership of the pointer, don't dispose of it or
- * anything like that. __init only.
- */
-extern void mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count);
-
 
 /* Initialize the controller. After this has been called, none of the above
  * should be called again for this mpic
index 3ec37dc9003e2575ee7170c4786904ab0ac6ee95..326d33ca55cdc33e8b3cb112f0fefb8117bab3af 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <asm/smp.h>
 
 struct mpic_msgr {
        u32 __iomem *base;
index b86faa9107da24338d661d7acf7ba455da413974..8a97aa7289d36b155a1e01df4211a261a7a110e8 100644 (file)
 #ifndef __ASM_POWERPC_REG_BOOKE_H__
 #define __ASM_POWERPC_REG_BOOKE_H__
 
-#ifdef CONFIG_BOOKE_WDT
-extern u32 booke_wdt_enabled;
-extern u32 booke_wdt_period;
-#endif /* CONFIG_BOOKE_WDT */
-
 /* Machine State Register (MSR) Fields */
 #define MSR_GS         (1<<28) /* Guest state */
 #define MSR_UCLE       (1<<26) /* User-mode cache lock enable */
index 3f6464b4d970e48cce597657ca6d77e84967666d..bcfdcd22c766f43ebb29dbe495641892215b1cda 100644 (file)
@@ -17,7 +17,8 @@
  * to the dma address (mapping) of the first page.
  */
 static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
-                                     dma_addr_t *dma_handle, gfp_t flag)
+                                     dma_addr_t *dma_handle, gfp_t flag,
+                                     struct dma_attrs *attrs)
 {
        return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size,
                                    dma_handle, dev->coherent_dma_mask, flag,
@@ -25,7 +26,8 @@ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
 }
 
 static void dma_iommu_free_coherent(struct device *dev, size_t size,
-                                   void *vaddr, dma_addr_t dma_handle)
+                                   void *vaddr, dma_addr_t dma_handle,
+                                   struct dma_attrs *attrs)
 {
        iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle);
 }
@@ -105,8 +107,8 @@ static u64 dma_iommu_get_required_mask(struct device *dev)
 }
 
 struct dma_map_ops dma_iommu_ops = {
-       .alloc_coherent         = dma_iommu_alloc_coherent,
-       .free_coherent          = dma_iommu_free_coherent,
+       .alloc                  = dma_iommu_alloc_coherent,
+       .free                   = dma_iommu_free_coherent,
        .map_sg                 = dma_iommu_map_sg,
        .unmap_sg               = dma_iommu_unmap_sg,
        .dma_supported          = dma_iommu_dma_supported,
index 1ebc9189aada9ff21d9268b71e486589010a20a8..4ab88dafb235c8b29955bf1a70a3e04aa255db5a 100644 (file)
@@ -47,8 +47,8 @@ static u64 swiotlb_powerpc_get_required(struct device *dev)
  * for everything else.
  */
 struct dma_map_ops swiotlb_dma_ops = {
-       .alloc_coherent = dma_direct_alloc_coherent,
-       .free_coherent = dma_direct_free_coherent,
+       .alloc = dma_direct_alloc_coherent,
+       .free = dma_direct_free_coherent,
        .map_sg = swiotlb_map_sg_attrs,
        .unmap_sg = swiotlb_unmap_sg_attrs,
        .dma_supported = swiotlb_dma_supported,
index 7d0233c12ee3febac282f37083648ce703cbd349..b1ec983dcec8954ada2bf1cd9937c9d52706b333 100644 (file)
@@ -26,7 +26,8 @@
 
 
 void *dma_direct_alloc_coherent(struct device *dev, size_t size,
-                               dma_addr_t *dma_handle, gfp_t flag)
+                               dma_addr_t *dma_handle, gfp_t flag,
+                               struct dma_attrs *attrs)
 {
        void *ret;
 #ifdef CONFIG_NOT_COHERENT_CACHE
@@ -54,7 +55,8 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 }
 
 void dma_direct_free_coherent(struct device *dev, size_t size,
-                             void *vaddr, dma_addr_t dma_handle)
+                             void *vaddr, dma_addr_t dma_handle,
+                             struct dma_attrs *attrs)
 {
 #ifdef CONFIG_NOT_COHERENT_CACHE
        __dma_free_coherent(size, vaddr);
@@ -150,8 +152,8 @@ static inline void dma_direct_sync_single(struct device *dev,
 #endif
 
 struct dma_map_ops dma_direct_ops = {
-       .alloc_coherent                 = dma_direct_alloc_coherent,
-       .free_coherent                  = dma_direct_free_coherent,
+       .alloc                          = dma_direct_alloc_coherent,
+       .free                           = dma_direct_free_coherent,
        .map_sg                         = dma_direct_map_sg,
        .unmap_sg                       = dma_direct_unmap_sg,
        .dma_supported                  = dma_direct_dma_supported,
index 3e57a00b8cba784633d1b0465fd3b47f1b85baf0..ba3aeb4bc06a81453105c6294bd74b81b340ed77 100644 (file)
@@ -206,40 +206,43 @@ reenable_mmu:                             /* re-enable mmu so we can */
        andi.   r10,r10,MSR_EE          /* Did EE change? */
        beq     1f
 
-       /* Save handler and return address into the 2 unused words
-        * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything
-        * else can be recovered from the pt_regs except r3 which for
-        * normal interrupts has been set to pt_regs and for syscalls
-        * is an argument, so we temporarily use ORIG_GPR3 to save it
-        */
-       stw     r9,8(r1)
-       stw     r11,12(r1)
-       stw     r3,ORIG_GPR3(r1)
        /*
         * The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1.
         * If from user mode there is only one stack frame on the stack, and
         * accessing CALLER_ADDR1 will cause oops. So we need create a dummy
         * stack frame to make trace_hardirqs_off happy.
+        *
+        * This is handy because we also need to save a bunch of GPRs,
+        * r3 can be different from GPR3(r1) at this point, r9 and r11
+        * contains the old MSR and handler address respectively,
+        * r4 & r5 can contain page fault arguments that need to be passed
+        * along as well. r12, CCR, CTR, XER etc... are left clobbered as
+        * they aren't useful past this point (aren't syscall arguments),
+        * the rest is restored from the exception frame.
         */
+       stwu    r1,-32(r1)
+       stw     r9,8(r1)
+       stw     r11,12(r1)
+       stw     r3,16(r1)
+       stw     r4,20(r1)
+       stw     r5,24(r1)
        andi.   r12,r12,MSR_PR
-       beq     11f
-       stwu    r1,-16(r1)
+       b       11f
        bl      trace_hardirqs_off
-       addi    r1,r1,16
        b       12f
-
 11:
        bl      trace_hardirqs_off
 12:
+       lwz     r5,24(r1)
+       lwz     r4,20(r1)
+       lwz     r3,16(r1)
+       lwz     r11,12(r1)
+       lwz     r9,8(r1)
+       addi    r1,r1,32
        lwz     r0,GPR0(r1)
-       lwz     r3,ORIG_GPR3(r1)
-       lwz     r4,GPR4(r1)
-       lwz     r5,GPR5(r1)
        lwz     r6,GPR6(r1)
        lwz     r7,GPR7(r1)
        lwz     r8,GPR8(r1)
-       lwz     r9,8(r1)
-       lwz     r11,12(r1)
 1:     mtctr   r11
        mtlr    r9
        bctr                            /* jump to handler */
index cfe7a38708c3724d6fc88cc6b110d2917d85b3e9..18bdf74fa164042e0e3b07a7dd0867faf8d6069c 100644 (file)
@@ -40,6 +40,8 @@
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/fadump.h>
+#include <asm/debug.h>
+#include <asm/setup.h>
 
 static struct fw_dump fw_dump;
 static struct fadump_mem_struct fdm;
index 79bb282e650161d8478887fde87cb9d99e00c97f..b01d14eeca8da2633711d2b114a860a257eea427 100644 (file)
@@ -65,7 +65,8 @@ static struct of_device_id __initdata ibmebus_matches[] = {
 static void *ibmebus_alloc_coherent(struct device *dev,
                                    size_t size,
                                    dma_addr_t *dma_handle,
-                                   gfp_t flag)
+                                   gfp_t flag,
+                                   struct dma_attrs *attrs)
 {
        void *mem;
 
@@ -77,7 +78,8 @@ static void *ibmebus_alloc_coherent(struct device *dev,
 
 static void ibmebus_free_coherent(struct device *dev,
                                  size_t size, void *vaddr,
-                                 dma_addr_t dma_handle)
+                                 dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        kfree(vaddr);
 }
@@ -136,8 +138,8 @@ static u64 ibmebus_dma_get_required_mask(struct device *dev)
 }
 
 static struct dma_map_ops ibmebus_dma_ops = {
-       .alloc_coherent     = ibmebus_alloc_coherent,
-       .free_coherent      = ibmebus_free_coherent,
+       .alloc              = ibmebus_alloc_coherent,
+       .free               = ibmebus_free_coherent,
        .map_sg             = ibmebus_map_sg,
        .unmap_sg           = ibmebus_unmap_sg,
        .dma_supported      = ibmebus_dma_supported,
index 243dbabfe74dff0ebbe55fab216a335574c1dc12..43eb74fcedde2806da8dd0c5193f3df4c91433dc 100644 (file)
@@ -330,14 +330,10 @@ void migrate_irqs(void)
 
        alloc_cpumask_var(&mask, GFP_KERNEL);
 
-       for_each_irq(irq) {
+       for_each_irq_desc(irq, desc) {
                struct irq_data *data;
                struct irq_chip *chip;
 
-               desc = irq_to_desc(irq);
-               if (!desc)
-                       continue;
-
                data = irq_desc_get_irq_data(desc);
                if (irqd_is_per_cpu(data))
                        continue;
@@ -560,12 +556,6 @@ void do_softirq(void)
        local_irq_restore(flags);
 }
 
-irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
-{
-       return d->hwirq;
-}
-EXPORT_SYMBOL_GPL(irqd_to_hwirq);
-
 irq_hw_number_t virq_to_hw(unsigned int virq)
 {
        struct irq_data *irq_data = irq_get_irq_data(virq);
index 76a6e40a6f7c8e797882d2462a0533a4c1391901..782bd0a3c2f0f95496b1b144ebb3ec6e6218e0f8 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/current.h>
 #include <asm/processor.h>
 #include <asm/machdep.h>
+#include <asm/debug.h>
 
 /*
  * This table contains the mapping between PowerPC hardware trap types, and
index c957b1202bdca6162479f395c063979b73613ba8..5df777794403d49a3820add9ba6409701b295da4 100644 (file)
 
 void machine_kexec_mask_interrupts(void) {
        unsigned int i;
+       struct irq_desc *desc;
 
-       for_each_irq(i) {
-               struct irq_desc *desc = irq_to_desc(i);
+       for_each_irq_desc(i, desc) {
                struct irq_chip *chip;
 
-               if (!desc)
-                       continue;
-
                chip = irq_desc_get_chip(desc);
                if (!chip)
                        continue;
index f88698c0f332d2a0c87957d10f1ca32ddd3d5eb0..4937c9690090d0e9bf3809b7ae923ae24d181d93 100644 (file)
@@ -1235,7 +1235,7 @@ void __ppc64_runlatch_on(void)
        ctrl |= CTRL_RUNLATCH;
        mtspr(SPRN_CTRLT, ctrl);
 
-       ti->local_flags |= TLF_RUNLATCH;
+       ti->local_flags |= _TLF_RUNLATCH;
 }
 
 /* Called with hard IRQs off */
@@ -1244,7 +1244,7 @@ void __ppc64_runlatch_off(void)
        struct thread_info *ti = current_thread_info();
        unsigned long ctrl;
 
-       ti->local_flags &= ~TLF_RUNLATCH;
+       ti->local_flags &= ~_TLF_RUNLATCH;
 
        ctrl = mfspr(SPRN_CTRLF);
        ctrl &= ~CTRL_RUNLATCH;
index 9825f29d1fafbcfd381aec51286137efa51830e9..ec8a53fa9e8f6a07f82b640426ef50f38e224d53 100644 (file)
@@ -150,6 +150,9 @@ notrace void __init machine_init(u64 dt_ptr)
 }
 
 #ifdef CONFIG_BOOKE_WDT
+extern u32 booke_wdt_enabled;
+extern u32 booke_wdt_period;
+
 /* Checks wdt=x and wdt_period=xx command-line option */
 notrace int __init early_parse_wdt(char *p)
 {
index b2f7c8480bf6e853704ba20cb4787db7cb519a91..a3a99901c8ecf4a1929815329a72a54146017603 100644 (file)
@@ -482,7 +482,8 @@ static void vio_cmo_balance(struct work_struct *work)
 }
 
 static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
-                                          dma_addr_t *dma_handle, gfp_t flag)
+                                         dma_addr_t *dma_handle, gfp_t flag,
+                                         struct dma_attrs *attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
        void *ret;
@@ -492,7 +493,7 @@ static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
                return NULL;
        }
 
-       ret = dma_iommu_ops.alloc_coherent(dev, size, dma_handle, flag);
+       ret = dma_iommu_ops.alloc(dev, size, dma_handle, flag, attrs);
        if (unlikely(ret == NULL)) {
                vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
                atomic_inc(&viodev->cmo.allocs_failed);
@@ -502,11 +503,12 @@ static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
 }
 
 static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
-                                        void *vaddr, dma_addr_t dma_handle)
+                                       void *vaddr, dma_addr_t dma_handle,
+                                       struct dma_attrs *attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
 
-       dma_iommu_ops.free_coherent(dev, size, vaddr, dma_handle);
+       dma_iommu_ops.free(dev, size, vaddr, dma_handle, attrs);
 
        vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
 }
@@ -607,8 +609,8 @@ static u64 vio_dma_get_required_mask(struct device *dev)
 }
 
 struct dma_map_ops vio_dma_mapping_ops = {
-       .alloc_coherent    = vio_dma_iommu_alloc_coherent,
-       .free_coherent     = vio_dma_iommu_free_coherent,
+       .alloc             = vio_dma_iommu_alloc_coherent,
+       .free              = vio_dma_iommu_free_coherent,
        .map_sg            = vio_dma_iommu_map_sg,
        .unmap_sg          = vio_dma_iommu_unmap_sg,
        .map_page          = vio_dma_iommu_map_page,
index f1950d1318273ae3b8dd2455ee493d436a7aaef8..135663a3e4fc945d4eaf9ef7706fa388feccfe07 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/disassemble.h>
 #include <asm/kvm_book3s.h>
 #include <asm/reg.h>
+#include <asm/switch_to.h>
 
 #define OP_19_XOP_RFID         18
 #define OP_19_XOP_RFI          50
index bed1279aa6a8788a8308b8966ef4c970f8aafd36..e1b60f56f2a1eb73bdd00ebc36faa44e5e3a0aa2 100644 (file)
@@ -173,9 +173,9 @@ static void __init kvm_linear_init_one(ulong size, int count, int type)
 
 static struct kvmppc_linear_info *kvm_alloc_linear(int type)
 {
-       struct kvmppc_linear_info *ri;
+       struct kvmppc_linear_info *ri, *ret;
 
-       ri = NULL;
+       ret = NULL;
        spin_lock(&linear_lock);
        list_for_each_entry(ri, &free_linears, list) {
                if (ri->type != type)
@@ -183,11 +183,12 @@ static struct kvmppc_linear_info *kvm_alloc_linear(int type)
 
                list_del(&ri->list);
                atomic_inc(&ri->use_count);
+               memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT);
+               ret = ri;
                break;
        }
        spin_unlock(&linear_lock);
-       memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT);
-       return ri;
+       return ret;
 }
 
 static void kvm_release_linear(struct kvmppc_linear_info *ri)
index 3f7b674dd4bf4843ab37e649527149fd6143cf23..d3fb4df02c419f48dfd8d3205c042cc04ff94426 100644 (file)
@@ -46,8 +46,10 @@ _GLOBAL(__kvmppc_vcore_entry)
        /* Save host state to the stack */
        stdu    r1, -SWITCH_FRAME_SIZE(r1)
 
-       /* Save non-volatile registers (r14 - r31) */
+       /* Save non-volatile registers (r14 - r31) and CR */
        SAVE_NVGPRS(r1)
+       mfcr    r3
+       std     r3, _CCR(r1)
 
        /* Save host DSCR */
 BEGIN_FTR_SECTION
@@ -157,8 +159,10 @@ kvmppc_handler_highmem:
         * R13      = PACA
         */
 
-       /* Restore non-volatile host registers (r14 - r31) */
+       /* Restore non-volatile host registers (r14 - r31) and CR */
        REST_NVGPRS(r1)
+       ld      r4, _CCR(r1)
+       mtcr    r4
 
        addi    r1, r1, SWITCH_FRAME_SIZE
        ld      r0, PPC_LR_STKOFF(r1)
index 0a8515a5c0422db7dc27890d4651267a62a6531c..3e35383bdb2186e81bb78dfbae2ebe8818c223ac 100644 (file)
@@ -84,6 +84,10 @@ kvm_start_entry:
        /* Save non-volatile registers (r14 - r31) */
        SAVE_NVGPRS(r1)
 
+       /* Save CR */
+       mfcr    r14
+       stw     r14, _CCR(r1)
+
        /* Save LR */
        PPC_STL r0, _LINK(r1)
 
@@ -165,6 +169,9 @@ kvm_exit_loop:
        PPC_LL  r4, _LINK(r1)
        mtlr    r4
 
+       lwz     r14, _CCR(r1)
+       mtcr    r14
+
        /* Restore non-volatile host registers (r14 - r31) */
        REST_NVGPRS(r1)
 
index e70ef2d86431bd7eef8c93adf219a88009ea6828..a59a25a1321843ff5fe72caf385b80aba0302f95 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/kvm_fpu.h>
 #include <asm/reg.h>
 #include <asm/cacheflush.h>
+#include <asm/switch_to.h>
 #include <linux/vmalloc.h>
 
 /* #define DEBUG */
index 7340e1090b770302cdb055728b0c7740241c0ca6..7759053d391b87298a4888c1cbbb7463ee6e8431 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
 #include <asm/mmu_context.h>
+#include <asm/switch_to.h>
 #include <linux/gfp.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
@@ -776,6 +777,7 @@ program_interrupt:
        }
        }
 
+       preempt_disable();
        if (!(r & RESUME_HOST)) {
                /* To avoid clobbering exit_reason, only check for signals if
                 * we aren't already exiting to userspace for some other
@@ -797,8 +799,6 @@ program_interrupt:
                        run->exit_reason = KVM_EXIT_INTR;
                        r = -EINTR;
                } else {
-                       preempt_disable();
-
                        /* In case an interrupt came in that was triggered
                         * from userspace (like DEC), we need to check what
                         * to inject now! */
@@ -880,7 +880,8 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 
        switch (reg->id) {
        case KVM_REG_PPC_HIOR:
-               r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+               r = copy_to_user((u64 __user *)(long)reg->addr,
+                               &to_book3s(vcpu)->hior, sizeof(u64));
                break;
        default:
                break;
@@ -895,7 +896,8 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 
        switch (reg->id) {
        case KVM_REG_PPC_HIOR:
-               r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+               r = copy_from_user(&to_book3s(vcpu)->hior,
+                                  (u64 __user *)(long)reg->addr, sizeof(u64));
                if (!r)
                        to_book3s(vcpu)->hior_explicit = true;
                break;
index 10d8ef602e5c9303795c7b78268d5691be79eeec..c8c4b878795a71542876308d68e34d7ff6e26163 100644 (file)
@@ -34,7 +34,8 @@
 /* r2 is special: it holds 'current', and it made nonvolatile in the
  * kernel with the -ffixed-r2 gcc option. */
 #define HOST_R2         12
-#define HOST_NV_GPRS    16
+#define HOST_CR         16
+#define HOST_NV_GPRS    20
 #define HOST_NV_GPR(n)  (HOST_NV_GPRS + ((n - 14) * 4))
 #define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + 4)
 #define HOST_STACK_SIZE (((HOST_MIN_STACK_SIZE + 15) / 16) * 16) /* Align. */
@@ -296,8 +297,10 @@ heavyweight_exit:
 
        /* Return to kvm_vcpu_run(). */
        lwz     r4, HOST_STACK_LR(r1)
+       lwz     r5, HOST_CR(r1)
        addi    r1, r1, HOST_STACK_SIZE
        mtlr    r4
+       mtcr    r5
        /* r3 still contains the return code from kvmppc_handle_exit(). */
        blr
 
@@ -314,6 +317,8 @@ _GLOBAL(__kvmppc_vcpu_run)
        stw     r3, HOST_RUN(r1)
        mflr    r3
        stw     r3, HOST_STACK_LR(r1)
+       mfcr    r5
+       stw     r5, HOST_CR(r1)
 
        /* Save host non-volatile register state to stack. */
        stw     r14, HOST_NV_GPR(r14)(r1)
index af1ab5e9a691e6b3c70b8d08415992f8c2205049..5c3cf2d04e41ccaa6e8b7aa94eb7ca27ba4baad9 100644 (file)
 /*
  * Assembly helpers from arch/powerpc/net/bpf_jit.S:
  */
-extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
+#define DECLARE_LOAD_FUNC(func)        \
+       extern u8 func[], func##_negative_offset[], func##_positive_offset[]
+
+DECLARE_LOAD_FUNC(sk_load_word);
+DECLARE_LOAD_FUNC(sk_load_half);
+DECLARE_LOAD_FUNC(sk_load_byte);
+DECLARE_LOAD_FUNC(sk_load_byte_msh);
 
 #define FUNCTION_DESCR_SIZE    24
 
index ff4506e85cce80bc2fdb7003078cec3f5c0d9962..55ba3855a97f58093ec06f343cde1df2dffbb17b 100644 (file)
  * then branch directly to slow_path_XXX if required.  (In fact, could
  * load a spare GPR with the address of slow_path_generic and pass size
  * as an argument, making the call site a mtlr, li and bllr.)
- *
- * Technically, the "is addr < 0" check is unnecessary & slowing down
- * the ABS path, as it's statically checked on generation.
  */
        .globl  sk_load_word
 sk_load_word:
        cmpdi   r_addr, 0
-       blt     bpf_error
+       blt     bpf_slow_path_word_neg
+       .globl  sk_load_word_positive_offset
+sk_load_word_positive_offset:
        /* Are we accessing past headlen? */
        subi    r_scratch1, r_HL, 4
        cmpd    r_scratch1, r_addr
@@ -51,7 +50,9 @@ sk_load_word:
        .globl  sk_load_half
 sk_load_half:
        cmpdi   r_addr, 0
-       blt     bpf_error
+       blt     bpf_slow_path_half_neg
+       .globl  sk_load_half_positive_offset
+sk_load_half_positive_offset:
        subi    r_scratch1, r_HL, 2
        cmpd    r_scratch1, r_addr
        blt     bpf_slow_path_half
@@ -61,7 +62,9 @@ sk_load_half:
        .globl  sk_load_byte
 sk_load_byte:
        cmpdi   r_addr, 0
-       blt     bpf_error
+       blt     bpf_slow_path_byte_neg
+       .globl  sk_load_byte_positive_offset
+sk_load_byte_positive_offset:
        cmpd    r_HL, r_addr
        ble     bpf_slow_path_byte
        lbzx    r_A, r_D, r_addr
@@ -69,22 +72,20 @@ sk_load_byte:
 
 /*
  * BPF_S_LDX_B_MSH: ldxb  4*([offset]&0xf)
- * r_addr is the offset value, already known positive
+ * r_addr is the offset value
  */
        .globl sk_load_byte_msh
 sk_load_byte_msh:
+       cmpdi   r_addr, 0
+       blt     bpf_slow_path_byte_msh_neg
+       .globl sk_load_byte_msh_positive_offset
+sk_load_byte_msh_positive_offset:
        cmpd    r_HL, r_addr
        ble     bpf_slow_path_byte_msh
        lbzx    r_X, r_D, r_addr
        rlwinm  r_X, r_X, 2, 32-4-2, 31-2
        blr
 
-bpf_error:
-       /* Entered with cr0 = lt */
-       li      r3, 0
-       /* Generated code will 'blt epilogue', returning 0. */
-       blr
-
 /* Call out to skb_copy_bits:
  * We'll need to back up our volatile regs first; we have
  * local variable space at r1+(BPF_PPC_STACK_BASIC).
@@ -136,3 +137,84 @@ bpf_slow_path_byte_msh:
        lbz     r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
        rlwinm  r_X, r_X, 2, 32-4-2, 31-2
        blr
+
+/* Call out to bpf_internal_load_pointer_neg_helper:
+ * We'll need to back up our volatile regs first; we have
+ * local variable space at r1+(BPF_PPC_STACK_BASIC).
+ * Allocate a new stack frame here to remain ABI-compliant in
+ * stashing LR.
+ */
+#define sk_negative_common(SIZE)                               \
+       mflr    r0;                                             \
+       std     r0, 16(r1);                                     \
+       /* R3 goes in parameter space of caller's frame */      \
+       std     r_skb, (BPF_PPC_STACKFRAME+48)(r1);             \
+       std     r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1);           \
+       std     r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1);           \
+       stdu    r1, -BPF_PPC_SLOWPATH_FRAME(r1);                \
+       /* R3 = r_skb, as passed */                             \
+       mr      r4, r_addr;                                     \
+       li      r5, SIZE;                                       \
+       bl      bpf_internal_load_pointer_neg_helper;           \
+       /* R3 != 0 on success */                                \
+       addi    r1, r1, BPF_PPC_SLOWPATH_FRAME;                 \
+       ld      r0, 16(r1);                                     \
+       ld      r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1);           \
+       ld      r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1);           \
+       mtlr    r0;                                             \
+       cmpldi  r3, 0;                                          \
+       beq     bpf_error_slow; /* cr0 = EQ */                  \
+       mr      r_addr, r3;                                     \
+       ld      r_skb, (BPF_PPC_STACKFRAME+48)(r1);             \
+       /* Great success! */
+
+bpf_slow_path_word_neg:
+       lis     r_scratch1,-32  /* SKF_LL_OFF */
+       cmpd    r_addr, r_scratch1      /* addr < SKF_* */
+       blt     bpf_error       /* cr0 = LT */
+       .globl  sk_load_word_negative_offset
+sk_load_word_negative_offset:
+       sk_negative_common(4)
+       lwz     r_A, 0(r_addr)
+       blr
+
+bpf_slow_path_half_neg:
+       lis     r_scratch1,-32  /* SKF_LL_OFF */
+       cmpd    r_addr, r_scratch1      /* addr < SKF_* */
+       blt     bpf_error       /* cr0 = LT */
+       .globl  sk_load_half_negative_offset
+sk_load_half_negative_offset:
+       sk_negative_common(2)
+       lhz     r_A, 0(r_addr)
+       blr
+
+bpf_slow_path_byte_neg:
+       lis     r_scratch1,-32  /* SKF_LL_OFF */
+       cmpd    r_addr, r_scratch1      /* addr < SKF_* */
+       blt     bpf_error       /* cr0 = LT */
+       .globl  sk_load_byte_negative_offset
+sk_load_byte_negative_offset:
+       sk_negative_common(1)
+       lbz     r_A, 0(r_addr)
+       blr
+
+bpf_slow_path_byte_msh_neg:
+       lis     r_scratch1,-32  /* SKF_LL_OFF */
+       cmpd    r_addr, r_scratch1      /* addr < SKF_* */
+       blt     bpf_error       /* cr0 = LT */
+       .globl  sk_load_byte_msh_negative_offset
+sk_load_byte_msh_negative_offset:
+       sk_negative_common(1)
+       lbz     r_X, 0(r_addr)
+       rlwinm  r_X, r_X, 2, 32-4-2, 31-2
+       blr
+
+bpf_error_slow:
+       /* fabricate a cr0 = lt */
+       li      r_scratch1, -1
+       cmpdi   r_scratch1, 0
+bpf_error:
+       /* Entered with cr0 = lt */
+       li      r3, 0
+       /* Generated code will 'blt epilogue', returning 0. */
+       blr
index 73619d3aeb6ceebaa9d54e652b5025234f31660c..2dc8b14848455122918d13cf1d2985984f8a248b 100644 (file)
@@ -127,6 +127,9 @@ static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
        PPC_BLR();
 }
 
+#define CHOOSE_LOAD_FUNC(K, func) \
+       ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
+
 /* Assemble the body code between the prologue & epilogue. */
 static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
                              struct codegen_context *ctx,
@@ -391,21 +394,16 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
 
                        /*** Absolute loads from packet header/data ***/
                case BPF_S_LD_W_ABS:
-                       func = sk_load_word;
+                       func = CHOOSE_LOAD_FUNC(K, sk_load_word);
                        goto common_load;
                case BPF_S_LD_H_ABS:
-                       func = sk_load_half;
+                       func = CHOOSE_LOAD_FUNC(K, sk_load_half);
                        goto common_load;
                case BPF_S_LD_B_ABS:
-                       func = sk_load_byte;
+                       func = CHOOSE_LOAD_FUNC(K, sk_load_byte);
                common_load:
-                       /*
-                        * Load from [K].  Reference with the (negative)
-                        * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported.
-                        */
+                       /* Load from [K]. */
                        ctx->seen |= SEEN_DATAREF;
-                       if ((int)K < 0)
-                               return -ENOTSUPP;
                        PPC_LI64(r_scratch1, func);
                        PPC_MTLR(r_scratch1);
                        PPC_LI32(r_addr, K);
@@ -429,7 +427,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
                common_load_ind:
                        /*
                         * Load from [X + K].  Negative offsets are tested for
-                        * in the helper functions, and result in a 'ret 0'.
+                        * in the helper functions.
                         */
                        ctx->seen |= SEEN_DATAREF | SEEN_XREG;
                        PPC_LI64(r_scratch1, func);
@@ -443,13 +441,7 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
                        break;
 
                case BPF_S_LDX_B_MSH:
-                       /*
-                        * x86 version drops packet (RET 0) when K<0, whereas
-                        * interpreter does allow K<0 (__load_pointer, special
-                        * ancillary data).  common_load returns ENOTSUPP if K<0,
-                        * so we fall back to interpreter & filter works.
-                        */
-                       func = sk_load_byte_msh;
+                       func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh);
                        goto common_load;
                        break;
 
index bfb11e01133e23b3e33fdb2423e41c81f567fd86..e2d401ad8fbbed71bf6594f840dc63ab2dc367e0 100644 (file)
@@ -93,7 +93,7 @@ struct mpc52xx_pci {
 };
 
 /* MPC5200 device tree match tables */
-const struct of_device_id mpc52xx_pci_ids[] __initdata = {
+const struct of_device_id mpc52xx_pci_ids[] __initconst = {
        { .type = "pci", .compatible = "fsl,mpc5200-pci", },
        { .type = "pci", .compatible = "mpc5200-pci", },
        {}
index 9fef5302adc127468d821f8335c0ef007e416270..67dac22b4363c07f5add4b0c56c06af0d3225ba9 100644 (file)
@@ -21,6 +21,12 @@ static struct of_device_id __initdata mpc85xx_common_ids[] = {
        { .compatible = "fsl,qe", },
        { .compatible = "fsl,cpm2", },
        { .compatible = "fsl,srio", },
+       /* So that the DMA channel nodes can be probed individually: */
+       { .compatible = "fsl,eloplus-dma", },
+       /* For the PMC driver */
+       { .compatible = "fsl,mpc8548-guts", },
+       /* Probably unnecessary? */
+       { .compatible = "gpio-leds", },
        {},
 };
 
index 3754ddc00af709fe8290a8234a2c20b1b53d28ee..d208ebccb91cc5f5db92bee1cf47e82e0e0c4b31 100644 (file)
@@ -270,7 +270,7 @@ static void __init mpc85xx_mds_qe_init(void)
 
        if (machine_is(p1021_mds)) {
 
-               struct ccsr_guts_85xx __iomem *guts;
+               struct ccsr_guts __iomem *guts;
 
                np = of_find_node_by_name(NULL, "global-utilities");
                if (np) {
@@ -399,12 +399,6 @@ static int __init board_fixups(void)
 machine_arch_initcall(mpc8568_mds, board_fixups);
 machine_arch_initcall(mpc8569_mds, board_fixups);
 
-static struct of_device_id mpc85xx_ids[] = {
-       { .compatible = "fsl,mpc8548-guts", },
-       { .compatible = "gpio-leds", },
-       {},
-};
-
 static int __init mpc85xx_publish_devices(void)
 {
        if (machine_is(mpc8568_mds))
@@ -412,10 +406,7 @@ static int __init mpc85xx_publish_devices(void)
        if (machine_is(mpc8569_mds))
                simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
 
-       mpc85xx_common_publish_devices();
-       of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
-
-       return 0;
+       return mpc85xx_common_publish_devices();
 }
 
 machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
index 9848f9e39853fc9a06b497dae73c394c597c699c..313fce4f55747eb9d0fe8639a145ef7489c2e52e 100644 (file)
@@ -127,7 +127,7 @@ static void __init mpc85xx_rdb_setup_arch(void)
 #if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
        if (machine_is(p1025_rdb)) {
 
-               struct ccsr_guts_85xx __iomem *guts;
+               struct ccsr_guts __iomem *guts;
 
                np = of_find_node_by_name(NULL, "global-utilities");
                if (np) {
index 0fe88e39945ecd5e4b13dee9ec03e362e0ebdfe8..f700c81a1321ca2de222b6f1561408e454094204 100644 (file)
@@ -150,7 +150,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 {
        struct device_node *guts_node;
        struct device_node *indirect_node = NULL;
-       struct ccsr_guts_85xx __iomem *guts;
+       struct ccsr_guts __iomem *guts;
        u8 __iomem *lbc_lcs0_ba = NULL;
        u8 __iomem *lbc_lcs1_ba = NULL;
        u8 b;
@@ -269,7 +269,7 @@ exit:
 void p1022ds_set_pixel_clock(unsigned int pixclock)
 {
        struct device_node *guts_np = NULL;
-       struct ccsr_guts_85xx __iomem *guts;
+       struct ccsr_guts __iomem *guts;
        unsigned long freq;
        u64 temp;
        u32 pxclk;
@@ -460,18 +460,7 @@ static void __init p1022_ds_setup_arch(void)
        pr_info("Freescale P1022 DS reference board\n");
 }
 
-static struct of_device_id __initdata p1022_ds_ids[] = {
-       /* So that the DMA channel nodes can be probed individually: */
-       { .compatible = "fsl,eloplus-dma", },
-       {},
-};
-
-static int __init p1022_ds_publish_devices(void)
-{
-       mpc85xx_common_publish_devices();
-       return of_platform_bus_probe(NULL, p1022_ds_ids, NULL);
-}
-machine_device_initcall(p1022_ds, p1022_ds_publish_devices);
+machine_device_initcall(p1022_ds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
 
index bbc615206c6774d430889a76a0eb558551081437..62cd3c555bfbcf80a57dc29f1450786b5aa41ae4 100644 (file)
@@ -225,7 +225,7 @@ void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
 void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
 {
        struct device_node *guts_np = NULL;
-       struct ccsr_guts_86xx __iomem *guts;
+       struct ccsr_guts __iomem *guts;
        unsigned long freq;
        u64 temp;
        u32 pxclk;
index db360fc4cf0e616a9f463c37f197ee04ba4d657d..85825b5401e51d936b81c99b8342b2f2a08cf6c1 100644 (file)
@@ -114,7 +114,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
                pr_devel("axon_msi: woff %x roff %x msi %x\n",
                          write_offset, msic->read_offset, msi);
 
-               if (msi < NR_IRQS && irq_get_chip_data(msi) == msic) {
+               if (msi < nr_irqs && irq_get_chip_data(msi) == msic) {
                        generic_handle_irq(msi);
                        msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
                } else {
@@ -276,9 +276,6 @@ static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        if (rc)
                return rc;
 
-       /* We rely on being able to stash a virq in a u16 */
-       BUILD_BUG_ON(NR_IRQS > 65536);
-
        list_for_each_entry(entry, &dev->msi_list, list) {
                virq = irq_create_direct_mapping(msic->irq_domain);
                if (virq == NO_IRQ) {
@@ -392,7 +389,8 @@ static int axon_msi_probe(struct platform_device *device)
        }
        memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES);
 
-       msic->irq_domain = irq_domain_add_nomap(dn, &msic_host_ops, msic);
+       /* We rely on being able to stash a virq in a u16, so limit irqs to < 65536 */
+       msic->irq_domain = irq_domain_add_nomap(dn, 65536, &msic_host_ops, msic);
        if (!msic->irq_domain) {
                printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %s\n",
                       dn->full_name);
index e5c3a2c6090d186b5ddeb5941514bda73d165065..8c6dc42ecf65440f0a488e84483b43cdbfa4816f 100644 (file)
@@ -239,7 +239,7 @@ void __init beatic_init_IRQ(void)
        ppc_md.get_irq = beatic_get_irq;
 
        /* Allocate an irq host */
-       beatic_host = irq_domain_add_nomap(NULL, &beatic_pic_host_ops, NULL);
+       beatic_host = irq_domain_add_nomap(NULL, 0, &beatic_pic_host_ops, NULL);
        BUG_ON(beatic_host == NULL);
        irq_set_default_host(beatic_host);
 }
@@ -248,6 +248,6 @@ void beatic_deinit_IRQ(void)
 {
        int     i;
 
-       for (i = 1; i < NR_IRQS; i++)
+       for (i = 1; i < nr_irqs; i++)
                beat_destruct_irq_plug(i);
 }
index ae9fc7bc17d6da2781c01e32249b27f107ff3ba5..b9f509a34c012b672e3b368f8121d9446b52d2ee 100644 (file)
@@ -564,7 +564,8 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
 /* A coherent allocation implies strong ordering */
 
 static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
-                                     dma_addr_t *dma_handle, gfp_t flag)
+                                     dma_addr_t *dma_handle, gfp_t flag,
+                                     struct dma_attrs *attrs)
 {
        if (iommu_fixed_is_weak)
                return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
@@ -572,18 +573,19 @@ static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
                                            device_to_mask(dev), flag,
                                            dev_to_node(dev));
        else
-               return dma_direct_ops.alloc_coherent(dev, size, dma_handle,
-                                                    flag);
+               return dma_direct_ops.alloc(dev, size, dma_handle, flag,
+                                           attrs);
 }
 
 static void dma_fixed_free_coherent(struct device *dev, size_t size,
-                                   void *vaddr, dma_addr_t dma_handle)
+                                   void *vaddr, dma_addr_t dma_handle,
+                                   struct dma_attrs *attrs)
 {
        if (iommu_fixed_is_weak)
                iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
                                    dma_handle);
        else
-               dma_direct_ops.free_coherent(dev, size, vaddr, dma_handle);
+               dma_direct_ops.free(dev, size, vaddr, dma_handle, attrs);
 }
 
 static dma_addr_t dma_fixed_map_page(struct device *dev, struct page *page,
@@ -642,8 +644,8 @@ static int dma_fixed_dma_supported(struct device *dev, u64 mask)
 static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
 
 struct dma_map_ops dma_iommu_fixed_ops = {
-       .alloc_coherent = dma_fixed_alloc_coherent,
-       .free_coherent  = dma_fixed_free_coherent,
+       .alloc          = dma_fixed_alloc_coherent,
+       .free           = dma_fixed_free_coherent,
        .map_sg         = dma_fixed_map_sg,
        .unmap_sg       = dma_fixed_unmap_sg,
        .dma_supported  = dma_fixed_dma_supported,
index 7f9b6742f8b65889e5d90db2a0cb2f752eac301e..6e3409d590ac6eb55e19e43b3c0d8719262760cb 100644 (file)
@@ -61,7 +61,7 @@ static void qpace_progress(char *s, unsigned short hex)
        printk("*** %04x : %s\n", hex, s ? s : "");
 }
 
-static const struct of_device_id qpace_bus_ids[] __initdata = {
+static const struct of_device_id qpace_bus_ids[] __initconst = {
        { .type = "soc", },
        { .compatible = "soc", },
        { .type = "spider", },
index fa3e294fd34305c17fb9932a45d5439c1e006042..4ab08767118534c780b1136adf909024c7893414 100644 (file)
@@ -140,7 +140,7 @@ static int __devinit cell_setup_phb(struct pci_controller *phb)
        return 0;
 }
 
-static const struct of_device_id cell_bus_ids[] __initdata = {
+static const struct of_device_id cell_bus_ids[] __initconst = {
        { .type = "soc", },
        { .compatible = "soc", },
        { .type = "spider", },
index 996c5ff7824b7b3342e1bce1ce46d44db06e8491..03685a329d7dadde0c52643ddd85a4ee23211747 100644 (file)
@@ -366,11 +366,20 @@ static void kw_i2c_timeout(unsigned long data)
        unsigned long flags;
 
        spin_lock_irqsave(&host->lock, flags);
+
+       /*
+        * If the timer is pending, that means we raced with the
+        * irq, in which case we just return
+        */
+       if (timer_pending(&host->timeout_timer))
+               goto skip;
+
        kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr));
        if (host->state != state_idle) {
                host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
                add_timer(&host->timeout_timer);
        }
+ skip:
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
index 66ad93de1d5571f80b5431dd72b69b88b304f6fc..c4e630576ff283666f74c37ee985cf4f1b22b105 100644 (file)
@@ -57,9 +57,9 @@ static int max_real_irqs;
 
 static DEFINE_RAW_SPINLOCK(pmac_pic_lock);
 
-#define NR_MASK_WORDS  ((NR_IRQS + 31) / 32)
-static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
-static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+/* The max irq number this driver deals with is 128; see max_irqs */
+static DECLARE_BITMAP(ppc_lost_interrupts, 128);
+static DECLARE_BITMAP(ppc_cached_irq_mask, 128);
 static int pmac_irq_cascade = -1;
 static struct irq_domain *pmac_pic_host;
 
index a81e5a88fbdf1c49c70cba6ef2699b86ed95d7b5..b4ddaa3fbb298eccc37044f61222d38a688c9f8c 100644 (file)
@@ -192,7 +192,7 @@ static int psurge_secondary_ipi_init(void)
 {
        int rc = -ENOMEM;
 
-       psurge_host = irq_domain_add_nomap(NULL, &psurge_host_ops, NULL);
+       psurge_host = irq_domain_add_nomap(NULL, 0, &psurge_host_ops, NULL);
 
        if (psurge_host)
                psurge_secondary_virq = irq_create_direct_mapping(psurge_host);
index 2a4ff86cc21f72c5c0af0082e4c12c64de5db6cd..5f3b23220b8ee395e0d9e05821a43b98fd8592f1 100644 (file)
@@ -753,9 +753,8 @@ void __init ps3_init_IRQ(void)
        unsigned cpu;
        struct irq_domain *host;
 
-       host = irq_domain_add_nomap(NULL, &ps3_host_ops, NULL);
+       host = irq_domain_add_nomap(NULL, PS3_PLUG_MAX + 1, &ps3_host_ops, NULL);
        irq_set_default_host(host);
-       irq_set_virq_count(PS3_PLUG_MAX + 1);
 
        for_each_possible_cpu(cpu) {
                struct ps3_private *pd = &per_cpu(ps3_private, cpu);
index 880eb9ce22c52784f8c8993e291dfb5f7a7c3cc3..5606fe36faf231760c1bd5d8a0f4b331934144c0 100644 (file)
@@ -515,7 +515,8 @@ core_initcall(ps3_system_bus_init);
  * to the dma address (mapping) of the first page.
  */
 static void * ps3_alloc_coherent(struct device *_dev, size_t size,
-                                     dma_addr_t *dma_handle, gfp_t flag)
+                                dma_addr_t *dma_handle, gfp_t flag,
+                                struct dma_attrs *attrs)
 {
        int result;
        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
@@ -552,7 +553,7 @@ clean_none:
 }
 
 static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
-       dma_addr_t dma_handle)
+                             dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
@@ -701,8 +702,8 @@ static u64 ps3_dma_get_required_mask(struct device *_dev)
 }
 
 static struct dma_map_ops ps3_sb_dma_ops = {
-       .alloc_coherent = ps3_alloc_coherent,
-       .free_coherent = ps3_free_coherent,
+       .alloc = ps3_alloc_coherent,
+       .free = ps3_free_coherent,
        .map_sg = ps3_sb_map_sg,
        .unmap_sg = ps3_sb_unmap_sg,
        .dma_supported = ps3_dma_supported,
@@ -712,8 +713,8 @@ static struct dma_map_ops ps3_sb_dma_ops = {
 };
 
 static struct dma_map_ops ps3_ioc0_dma_ops = {
-       .alloc_coherent = ps3_alloc_coherent,
-       .free_coherent = ps3_free_coherent,
+       .alloc = ps3_alloc_coherent,
+       .free = ps3_free_coherent,
        .map_sg = ps3_ioc0_map_sg,
        .unmap_sg = ps3_ioc0_unmap_sg,
        .dma_supported = ps3_dma_supported,
index aadbe4f6d5373d03bef6fd8de146a02c43a04ceb..178a5f300bc973afeb8c4a21799992cbfbdc74e1 100644 (file)
@@ -30,9 +30,9 @@ config PPC_SPLPAR
          two or more partitions.
 
 config EEH
-       bool "PCI Extended Error Handling (EEH)" if EXPERT
+       bool
        depends on PPC_PSERIES && PCI
-       default y if !EXPERT
+       default y
 
 config PSERIES_MSI
        bool
index 309d38ef732209ce68ec99380ef09b97d5bfc41f..a75e37dc41aa7d94dc762c9f9c7afb23acab1841 100644 (file)
@@ -1076,7 +1076,7 @@ static void eeh_add_device_late(struct pci_dev *dev)
        pr_debug("EEH: Adding device %s\n", pci_name(dev));
 
        dn = pci_device_to_OF_node(dev);
-       edev = pci_dev_to_eeh_dev(dev);
+       edev = of_node_to_eeh_dev(dn);
        if (edev->pdev == dev) {
                pr_debug("EEH: Already referenced !\n");
                return;
index 4a475256585606889b791ce25a4f6683b21a315c..4cb375c0f8d173ff545c665971d8054d61fdfc17 100644 (file)
@@ -59,8 +59,7 @@ static int eeh_event_handler(void * dummy)
        struct eeh_event *event;
        struct eeh_dev *edev;
 
-       daemonize("eehd");
-       set_current_state(TASK_INTERRUPTIBLE);
+       set_task_comm(current, "eehd");
 
        spin_lock_irqsave(&eeh_eventlist_lock, flags);
        event = NULL;
@@ -83,6 +82,7 @@ static int eeh_event_handler(void * dummy)
        printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
               eeh_pci_name(edev->pdev));
 
+       set_current_state(TASK_INTERRUPTIBLE);  /* Don't add to load average */
        edev = handle_eeh_events(event);
 
        eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
index d3be961e2ae73d3fd9a3cebe0481a2f0f5e652ad..10386b676d8758b7f52bb8348f7cf321cc8db89a 100644 (file)
@@ -51,8 +51,7 @@
 static intctl_cpm2_t __iomem *cpm2_intctl;
 
 static struct irq_domain *cpm2_pic_host;
-#define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)
-static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+static unsigned long ppc_cached_irq_mask[2]; /* 2 32-bit registers */
 
 static const u_char irq_to_siureg[] = {
        1, 1, 1, 1, 1, 1, 1, 1,
index d5f5416be310b0fc5f78f7466cc5755b34a6f1cd..b724622c3a0b74ab5eddfa3b0cfc10dc6eab2c34 100644 (file)
 extern int cpm_get_irq(struct pt_regs *regs);
 
 static struct irq_domain *mpc8xx_pic_host;
-#define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)
-static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+static unsigned long mpc8xx_cached_irq_mask;
 static sysconf8xx_t __iomem *siu_reg;
 
-int cpm_get_irq(struct pt_regs *regs);
+static inline unsigned long mpc8xx_irqd_to_bit(struct irq_data *d)
+{
+       return 0x80000000 >> irqd_to_hwirq(d);
+}
 
 static void mpc8xx_unmask_irq(struct irq_data *d)
 {
-       int     bit, word;
-       unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
-
-       bit = irq_nr & 0x1f;
-       word = irq_nr >> 5;
-
-       ppc_cached_irq_mask[word] |= (1 << (31-bit));
-       out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+       mpc8xx_cached_irq_mask |= mpc8xx_irqd_to_bit(d);
+       out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
 }
 
 static void mpc8xx_mask_irq(struct irq_data *d)
 {
-       int     bit, word;
-       unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
-
-       bit = irq_nr & 0x1f;
-       word = irq_nr >> 5;
-
-       ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
-       out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+       mpc8xx_cached_irq_mask &= ~mpc8xx_irqd_to_bit(d);
+       out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
 }
 
 static void mpc8xx_ack(struct irq_data *d)
 {
-       int     bit;
-       unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
-
-       bit = irq_nr & 0x1f;
-       out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
+       out_be32(&siu_reg->sc_sipend, mpc8xx_irqd_to_bit(d));
 }
 
 static void mpc8xx_end_irq(struct irq_data *d)
 {
-       int bit, word;
-       unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
-
-       bit = irq_nr & 0x1f;
-       word = irq_nr >> 5;
-
-       ppc_cached_irq_mask[word] |= (1 << (31-bit));
-       out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+       mpc8xx_cached_irq_mask |= mpc8xx_irqd_to_bit(d);
+       out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
 }
 
 static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-       if (flow_type & IRQ_TYPE_EDGE_FALLING) {
-               irq_hw_number_t hw = (unsigned int)irqd_to_hwirq(d);
+       /* only external IRQ senses are programmable */
+       if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !(irqd_to_hwirq(d) & 1)) {
                unsigned int siel = in_be32(&siu_reg->sc_siel);
-
-               /* only external IRQ senses are programmable */
-               if ((hw & 1) == 0) {
-                       siel |= (0x80000000 >> hw);
-                       out_be32(&siu_reg->sc_siel, siel);
-                       __irq_set_handler_locked(d->irq, handle_edge_irq);
-               }
+               siel |= mpc8xx_irqd_to_bit(d);
+               out_be32(&siu_reg->sc_siel, siel);
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
        }
        return 0;
 }
@@ -132,6 +108,9 @@ static int mpc8xx_pic_host_xlate(struct irq_domain *h, struct device_node *ct,
                IRQ_TYPE_EDGE_FALLING,
        };
 
+       if (intspec[0] > 0x1f)
+               return 0;
+
        *out_hwirq = intspec[0];
        if (intsize > 1 && intspec[1] < 4)
                *out_flags = map_pic_senses[intspec[1]];
index 9ac71ebd2c408b47869f5f152ff577e84c958064..395af1347749104aeef3c832fb48dd26e6385ace 100644 (file)
@@ -604,18 +604,14 @@ static struct mpic *mpic_find(unsigned int irq)
 }
 
 /* Determine if the linux irq is an IPI */
-static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq)
+static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int src)
 {
-       unsigned int src = virq_to_hw(irq);
-
        return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]);
 }
 
 /* Determine if the linux irq is a timer */
-static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int irq)
+static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int src)
 {
-       unsigned int src = virq_to_hw(irq);
-
        return (src >= mpic->timer_vecs[0] && src <= mpic->timer_vecs[7]);
 }
 
@@ -876,21 +872,45 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
        if (src >= mpic->num_sources)
                return -EINVAL;
 
+       vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
+
+       /* We don't support "none" type */
        if (flow_type == IRQ_TYPE_NONE)
-               if (mpic->senses && src < mpic->senses_count)
-                       flow_type = mpic->senses[src];
-       if (flow_type == IRQ_TYPE_NONE)
-               flow_type = IRQ_TYPE_LEVEL_LOW;
+               flow_type = IRQ_TYPE_DEFAULT;
+
+       /* Default: read HW settings */
+       if (flow_type == IRQ_TYPE_DEFAULT) {
+               switch(vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
+                              MPIC_INFO(VECPRI_SENSE_MASK))) {
+                       case MPIC_INFO(VECPRI_SENSE_EDGE) |
+                            MPIC_INFO(VECPRI_POLARITY_POSITIVE):
+                               flow_type = IRQ_TYPE_EDGE_RISING;
+                               break;
+                       case MPIC_INFO(VECPRI_SENSE_EDGE) |
+                            MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
+                               flow_type = IRQ_TYPE_EDGE_FALLING;
+                               break;
+                       case MPIC_INFO(VECPRI_SENSE_LEVEL) |
+                            MPIC_INFO(VECPRI_POLARITY_POSITIVE):
+                               flow_type = IRQ_TYPE_LEVEL_HIGH;
+                               break;
+                       case MPIC_INFO(VECPRI_SENSE_LEVEL) |
+                            MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
+                               flow_type = IRQ_TYPE_LEVEL_LOW;
+                               break;
+               }
+       }
 
+       /* Apply to irq desc */
        irqd_set_trigger_type(d, flow_type);
 
+       /* Apply to HW */
        if (mpic_is_ht_interrupt(mpic, src))
                vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
                        MPIC_VECPRI_SENSE_EDGE;
        else
                vecpri = mpic_type_to_vecpri(mpic, flow_type);
 
-       vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
        vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
                        MPIC_INFO(VECPRI_SENSE_MASK));
        vnew |= vecpri;
@@ -1026,7 +1046,7 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
        irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
 
        /* Set default irq type */
-       irq_set_irq_type(virq, IRQ_TYPE_NONE);
+       irq_set_irq_type(virq, IRQ_TYPE_DEFAULT);
 
        /* If the MPIC was reset, then all vectors have already been
         * initialized.  Otherwise, a per source lazy initialization
@@ -1417,12 +1437,6 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
                mpic->num_sources = isu_first + mpic->isu_size;
 }
 
-void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
-{
-       mpic->senses = senses;
-       mpic->senses_count = count;
-}
-
 void __init mpic_init(struct mpic *mpic)
 {
        int i, cpu;
@@ -1555,12 +1569,12 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
                return;
 
        raw_spin_lock_irqsave(&mpic_lock, flags);
-       if (mpic_is_ipi(mpic, irq)) {
+       if (mpic_is_ipi(mpic, src)) {
                reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) &
                        ~MPIC_VECPRI_PRIORITY_MASK;
                mpic_ipi_write(src - mpic->ipi_vecs[0],
                               reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
-       } else if (mpic_is_tm(mpic, irq)) {
+       } else if (mpic_is_tm(mpic, src)) {
                reg = mpic_tm_read(src - mpic->timer_vecs[0]) &
                        ~MPIC_VECPRI_PRIORITY_MASK;
                mpic_tm_write(src - mpic->timer_vecs[0],
index 6e7fa386e76a75c36de9f38cf376d178ef6ea83f..483d8fa72e8ba3bc6bca736faf2f007399282e13 100644 (file)
@@ -27,6 +27,7 @@
 
 static struct mpic_msgr **mpic_msgrs;
 static unsigned int mpic_msgr_count;
+static DEFINE_RAW_SPINLOCK(msgrs_lock);
 
 static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value)
 {
@@ -56,12 +57,11 @@ struct mpic_msgr *mpic_msgr_get(unsigned int reg_num)
        if (reg_num >= mpic_msgr_count)
                return ERR_PTR(-ENODEV);
 
-       raw_spin_lock_irqsave(&msgr->lock, flags);
-       if (mpic_msgrs[reg_num]->in_use == MSGR_FREE) {
-               msgr = mpic_msgrs[reg_num];
+       raw_spin_lock_irqsave(&msgrs_lock, flags);
+       msgr = mpic_msgrs[reg_num];
+       if (msgr->in_use == MSGR_FREE)
                msgr->in_use = MSGR_INUSE;
-       }
-       raw_spin_unlock_irqrestore(&msgr->lock, flags);
+       raw_spin_unlock_irqrestore(&msgrs_lock, flags);
 
        return msgr;
 }
@@ -228,7 +228,7 @@ static __devinit int mpic_msgr_probe(struct platform_device *dev)
 
                reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i;
                msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE;
-               msgr->mer = msgr->base + MPIC_MSGR_MER_OFFSET;
+               msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET);
                msgr->in_use = MSGR_FREE;
                msgr->num = i;
                raw_spin_lock_init(&msgr->lock);
index ceb09cbd2329e782fe00a5c3e1326d217ab3e92b..818e763f826509b78efdcd2ca216e395b8a52c43 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006-2010 Freescale Semicondutor, Inc. All rights reserved.
  *
  * Authors:    Shlomi Gridish <gridish@freescale.com>
  *             Li Yang <leoli@freescale.com>
@@ -266,7 +266,19 @@ EXPORT_SYMBOL(qe_clock_source);
 static void qe_snums_init(void)
 {
        int i;
-       static const u8 snum_init[] = {
+       static const u8 snum_init_76[] = {
+               0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
+               0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
+               0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
+               0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D,
+               0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D,
+               0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D,
+               0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD,
+               0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD,
+               0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED,
+               0xF4, 0xF5, 0xFC, 0xFD,
+       };
+       static const u8 snum_init_46[] = {
                0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
                0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
                0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
@@ -274,9 +286,15 @@ static void qe_snums_init(void)
                0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
                0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
        };
+       static const u8 *snum_init;
 
        qe_num_of_snum = qe_get_num_of_snums();
 
+       if (qe_num_of_snum == 76)
+               snum_init = snum_init_76;
+       else
+               snum_init = snum_init_46;
+
        for (i = 0; i < qe_num_of_snum; i++) {
                snums[i].num = snum_init[i];
                snums[i].state = QE_SNUM_STATE_FREE;
index 49a3ece1c6b3589971872bf4d440cab1e609d764..702256a1ca1184c3044c2ae981cbcaeacb571b88 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <asm/debug.h>
 #include <asm/prom.h>
 #include <asm/scom.h>
 
index ea5e204e345093cedfc320d06f23a804d3c8589e..cd1d18db92c6afdc5e35c7980b4e038b8a6057a4 100644 (file)
@@ -188,6 +188,7 @@ void xics_migrate_irqs_away(void)
 {
        int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
        unsigned int irq, virq;
+       struct irq_desc *desc;
 
        /* If we used to be the default server, move to the new "boot_cpuid" */
        if (hw_cpu == xics_default_server)
@@ -202,8 +203,7 @@ void xics_migrate_irqs_away(void)
        /* Allow IPIs again... */
        icp_ops->set_priority(DEFAULT_PRIORITY);
 
-       for_each_irq(virq) {
-               struct irq_desc *desc;
+       for_each_irq_desc(virq, desc) {
                struct irq_chip *chip;
                long server;
                unsigned long flags;
@@ -212,9 +212,8 @@ void xics_migrate_irqs_away(void)
                /* We can't set affinity on ISA interrupts */
                if (virq < NUM_ISA_INTERRUPTS)
                        continue;
-               desc = irq_to_desc(virq);
                /* We only need to migrate enabled IRQS */
-               if (!desc || !desc->action)
+               if (!desc->action)
                        continue;
                if (desc->irq_data.domain != xics_host)
                        continue;
index 2b7c0fbe578e3341a8d52e98f9cfced0a82023df..9015060919a0430cd5b8233081f2e12f4c3e2547 100644 (file)
@@ -90,7 +90,6 @@ config S390
        select HAVE_KERNEL_XZ
        select HAVE_ARCH_MUTEX_CPU_RELAX
        select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
-       select HAVE_RCU_TABLE_FREE if SMP
        select ARCH_SAVE_PAGE_KEYS if HIBERNATION
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
index 6cf8e26b313780a4addc668018f3a658880be257..1957a9dd256d655400deca01f69e7530de33869d 100644 (file)
@@ -1,8 +1,12 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_AUDIT=y
-CONFIG_RCU_TRACE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
@@ -14,16 +18,22 @@ CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_EXPERT=y
 # CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IBM_PARTITION=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -34,18 +44,15 @@ CONFIG_KSM=y
 CONFIG_BINFMT_MISC=m
 CONFIG_CMM=m
 CONFIG_HZ_100=y
-CONFIG_KEXEC=y
-CONFIG_PM=y
+CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_NET_KEY=y
-CONFIG_AFIUCV=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
-CONFIG_NET_SCTPPROBE=m
 CONFIG_L2TP=m
 CONFIG_L2TP_DEBUGFS=m
 CONFIG_VLAN_8021Q=y
@@ -84,15 +91,14 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_ZFCP=y
-CONFIG_ZFCP_DIF=y
 CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
 CONFIG_BONDING=m
+CONFIG_DUMMY=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
-CONFIG_NET_ETHERNET=y
 CONFIG_VIRTIO_NET=y
 CONFIG_RAW_DRIVER=m
+CONFIG_VIRTIO_BALLOON=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
@@ -103,27 +109,21 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_IBM_PARTITION=y
-CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_TIMER_STATS=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_PROVE_RCU=y
 CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_LOCKDEP=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_LIST=y
 CONFIG_DEBUG_NOTIFIERS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_RCU_TRACE=y
 CONFIG_KPROBES_SANITY_TEST=y
 CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
 CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
 CONFIG_LATENCYTOP=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_DEBUG_PAGEALLOC=y
-# CONFIG_FTRACE is not set
+CONFIG_BLK_DEV_IO_TRACE=y
 # CONFIG_STRICT_DEVMEM is not set
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
@@ -173,4 +173,3 @@ CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRC7=m
-CONFIG_VIRTIO_BALLOON=y
index 1e5b27edc0c92e72e656485539391b579db8086a..2ee66a65f2d4740572791c46b9cf42a9c4e65d51 100644 (file)
@@ -38,12 +38,11 @@ static inline void stfle(u64 *stfle_fac_list, int size)
        unsigned long nr;
 
        preempt_disable();
-       S390_lowcore.stfl_fac_list = 0;
        asm volatile(
                "       .insn s,0xb2b10000,0(0)\n" /* stfl */
                "0:\n"
                EX_TABLE(0b, 0b)
-               : "=m" (S390_lowcore.stfl_fac_list));
+               : "+m" (S390_lowcore.stfl_fac_list));
        nr = 4; /* bytes stored by stfl */
        memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
        if (S390_lowcore.stfl_fac_list & 0x01000000) {
index 8eef9b5b3cf440c35744ed5338240e39f777067a..78e3041919dedd11556ed359c40c1b2d875a197c 100644 (file)
@@ -22,10 +22,7 @@ void crst_table_free(struct mm_struct *, unsigned long *);
 
 unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
 void page_table_free(struct mm_struct *, unsigned long *);
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
 void page_table_free_rcu(struct mmu_gather *, unsigned long *);
-void __tlb_remove_table(void *_table);
-#endif
 
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 {
index 6bdee21c077e0755ab0e0bc2084e118bdcb5e83f..a3e4ebb32090dc10ab0692f320c3ae3137f0f7dc 100644 (file)
@@ -77,7 +77,7 @@ static inline __u16 __arch_swab16p(const __u16 *x)
        
        asm volatile(
 #ifndef __s390x__
-               "       icm     %0,2,%O+1(%R1)\n"
+               "       icm     %0,2,%O1+1(%R1)\n"
                "       ic      %0,%1\n"
                : "=&d" (result) : "Q" (*x) : "cc");
 #else /* __s390x__ */
index c687a2c834626adb1f01cc24ae4f62713d83adaa..775a5eea8f9eb9896e9d38e809dc74d51823d99f 100644 (file)
 
 struct mmu_gather {
        struct mm_struct *mm;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
        struct mmu_table_batch *batch;
-#endif
        unsigned int fullmm;
-       unsigned int need_flush;
 };
 
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
 struct mmu_table_batch {
        struct rcu_head         rcu;
        unsigned int            nr;
@@ -49,7 +45,6 @@ struct mmu_table_batch {
 
 extern void tlb_table_flush(struct mmu_gather *tlb);
 extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
-#endif
 
 static inline void tlb_gather_mmu(struct mmu_gather *tlb,
                                  struct mm_struct *mm,
@@ -57,29 +52,20 @@ static inline void tlb_gather_mmu(struct mmu_gather *tlb,
 {
        tlb->mm = mm;
        tlb->fullmm = full_mm_flush;
-       tlb->need_flush = 0;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
        tlb->batch = NULL;
-#endif
        if (tlb->fullmm)
                __tlb_flush_mm(mm);
 }
 
 static inline void tlb_flush_mmu(struct mmu_gather *tlb)
 {
-       if (!tlb->need_flush)
-               return;
-       tlb->need_flush = 0;
-       __tlb_flush_mm(tlb->mm);
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
        tlb_table_flush(tlb);
-#endif
 }
 
 static inline void tlb_finish_mmu(struct mmu_gather *tlb,
                                  unsigned long start, unsigned long end)
 {
-       tlb_flush_mmu(tlb);
+       tlb_table_flush(tlb);
 }
 
 /*
@@ -105,10 +91,8 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
                                unsigned long address)
 {
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
        if (!tlb->fullmm)
                return page_table_free_rcu(tlb, (unsigned long *) pte);
-#endif
        page_table_free(tlb->mm, (unsigned long *) pte);
 }
 
@@ -125,10 +109,8 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
 #ifdef __s390x__
        if (tlb->mm->context.asce_limit <= (1UL << 31))
                return;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
        if (!tlb->fullmm)
                return tlb_remove_table(tlb, pmd);
-#endif
        crst_table_free(tlb->mm, (unsigned long *) pmd);
 #endif
 }
@@ -146,10 +128,8 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
 #ifdef __s390x__
        if (tlb->mm->context.asce_limit <= (1UL << 42))
                return;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
        if (!tlb->fullmm)
                return tlb_remove_table(tlb, pud);
-#endif
        crst_table_free(tlb->mm, (unsigned long *) pud);
 #endif
 }
index c27a0727f9304cecf518aa310c70c33260fc3245..adccd908ebc773d51c8850897098c04af91b601d 100644 (file)
@@ -474,9 +474,9 @@ ENTRY(startup_kdump)
        stck    __LC_LAST_UPDATE_CLOCK
        spt     5f-.LPG0(%r13)
        mvc     __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
+       xc      __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
 #ifndef CONFIG_MARCH_G5
        # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
-       xc      __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
        .insn   s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list
        tm      __LC_STFL_FAC_LIST,0x01 # stfle available ?
        jz      0f
index 1c2cdd59ccd0504469a1d31a45ba2aaf6442368b..8a22c27219dd0748f380a0aef0d63128b01ec21a 100644 (file)
@@ -118,9 +118,10 @@ asmlinkage void do_softirq(void)
                                         "a" (__do_softirq)
                                     : "0", "1", "2", "3", "4", "5", "14",
                                       "cc", "memory" );
-               } else
+               } else {
                        /* We are already on the async stack. */
                        __do_softirq();
+               }
        }
 
        local_irq_restore(flags);
@@ -192,11 +193,12 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler)
        int index = ext_hash(code);
 
        spin_lock_irqsave(&ext_int_hash_lock, flags);
-       list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
+       list_for_each_entry_rcu(p, &ext_int_hash[index], entry) {
                if (p->code == code && p->handler == handler) {
                        list_del_rcu(&p->entry);
                        kfree_rcu(p, rcu);
                }
+       }
        spin_unlock_irqrestore(&ext_int_hash_lock, flags);
        return 0;
 }
@@ -211,9 +213,10 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code,
 
        old_regs = set_irq_regs(regs);
        irq_enter();
-       if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
+       if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) {
                /* Serve timer interrupts first. */
                clock_comparator_work();
+       }
        kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
        if (ext_code.code != 0x1004)
                __get_cpu_var(s390_idle).nohz_delay = 1;
index 46405086479c246f6439151c879ab7430d59e5f2..cb019f429e88ba22745a14bf38c714743c2383ad 100644 (file)
@@ -178,7 +178,7 @@ static void cpumf_pmu_enable(struct pmu *pmu)
        err = lcctl(cpuhw->state);
        if (err) {
                pr_err("Enabling the performance measuring unit "
-                      "failed with rc=%lx\n", err);
+                      "failed with rc=%x\n", err);
                return;
        }
 
@@ -203,7 +203,7 @@ static void cpumf_pmu_disable(struct pmu *pmu)
        err = lcctl(inactive);
        if (err) {
                pr_err("Disabling the performance measuring unit "
-                      "failed with rc=%lx\n", err);
+                      "failed with rc=%x\n", err);
                return;
        }
 
index 7bb15fcca75ea572362d02a6b2626836868be9ed..e1335dc2b1b76fffea016ef83e7d1b229086bf20 100644 (file)
@@ -61,21 +61,14 @@ long probe_kernel_write(void *dst, const void *src, size_t size)
        return copied < 0 ? -EFAULT : 0;
 }
 
-/*
- * Copy memory in real mode (kernel to kernel)
- */
-int memcpy_real(void *dest, void *src, size_t count)
+static int __memcpy_real(void *dest, void *src, size_t count)
 {
        register unsigned long _dest asm("2") = (unsigned long) dest;
        register unsigned long _len1 asm("3") = (unsigned long) count;
        register unsigned long _src  asm("4") = (unsigned long) src;
        register unsigned long _len2 asm("5") = (unsigned long) count;
-       unsigned long flags;
        int rc = -EFAULT;
 
-       if (!count)
-               return 0;
-       flags = __arch_local_irq_stnsm(0xf8UL);
        asm volatile (
                "0:     mvcle   %1,%2,0x0\n"
                "1:     jo      0b\n"
@@ -86,7 +79,23 @@ int memcpy_real(void *dest, void *src, size_t count)
                  "+d" (_len2), "=m" (*((long *) dest))
                : "m" (*((long *) src))
                : "cc", "memory");
-       arch_local_irq_restore(flags);
+       return rc;
+}
+
+/*
+ * Copy memory in real mode (kernel to kernel)
+ */
+int memcpy_real(void *dest, void *src, size_t count)
+{
+       unsigned long flags;
+       int rc;
+
+       if (!count)
+               return 0;
+       local_irq_save(flags);
+       __arch_local_irq_stnsm(0xfbUL);
+       rc = __memcpy_real(dest, src, count);
+       local_irq_restore(flags);
        return rc;
 }
 
index 373adf69b01c48ceebfa2808131326ba5c7188dc..6e765bf00670c2d062632baa317c2b8ef0ea7235 100644 (file)
@@ -678,8 +678,6 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
        }
 }
 
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
-
 static void __page_table_free_rcu(void *table, unsigned bit)
 {
        struct page *page;
@@ -733,7 +731,66 @@ void __tlb_remove_table(void *_table)
                free_pages((unsigned long) table, ALLOC_ORDER);
 }
 
-#endif
+static void tlb_remove_table_smp_sync(void *arg)
+{
+       /* Simply deliver the interrupt */
+}
+
+static void tlb_remove_table_one(void *table)
+{
+       /*
+        * This isn't an RCU grace period and hence the page-tables cannot be
+        * assumed to be actually RCU-freed.
+        *
+        * It is however sufficient for software page-table walkers that rely
+        * on IRQ disabling. See the comment near struct mmu_table_batch.
+        */
+       smp_call_function(tlb_remove_table_smp_sync, NULL, 1);
+       __tlb_remove_table(table);
+}
+
+static void tlb_remove_table_rcu(struct rcu_head *head)
+{
+       struct mmu_table_batch *batch;
+       int i;
+
+       batch = container_of(head, struct mmu_table_batch, rcu);
+
+       for (i = 0; i < batch->nr; i++)
+               __tlb_remove_table(batch->tables[i]);
+
+       free_page((unsigned long)batch);
+}
+
+void tlb_table_flush(struct mmu_gather *tlb)
+{
+       struct mmu_table_batch **batch = &tlb->batch;
+
+       if (*batch) {
+               __tlb_flush_mm(tlb->mm);
+               call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu);
+               *batch = NULL;
+       }
+}
+
+void tlb_remove_table(struct mmu_gather *tlb, void *table)
+{
+       struct mmu_table_batch **batch = &tlb->batch;
+
+       if (*batch == NULL) {
+               *batch = (struct mmu_table_batch *)
+                       __get_free_page(GFP_NOWAIT | __GFP_NOWARN);
+               if (*batch == NULL) {
+                       __tlb_flush_mm(tlb->mm);
+                       tlb_remove_table_one(table);
+                       return;
+               }
+               (*batch)->nr = 0;
+       }
+       (*batch)->tables[(*batch)->nr++] = table;
+       if ((*batch)->nr == MAX_TABLE_BATCH)
+               tlb_table_flush(tlb);
+}
 
 /*
  * switch on pgstes for its userspace process (for kvm)
index c1d5a820b1aa3f64e72475203515b6a4303c1c0f..5f2bb4242c0f78465cbaea70cbb43d5c7f66d91c 100644 (file)
@@ -61,6 +61,7 @@ config DUMP_CODE
 config DWARF_UNWINDER
        bool "Enable the DWARF unwinder for stacktraces"
        select FRAME_POINTER
+       depends on SUPERH32
        default n
        help
          Enabling this option will make stacktraces more accurate, at
index d879848f3cdd49ac533502064b7025c39cf53ecb..d0d6221d7c2eaef908b4804848c442923c970b21 100644 (file)
@@ -28,6 +28,7 @@
 #include <cpu/sh7785.h>
 #include <asm/heartbeat.h>
 #include <asm/clock.h>
+#include <asm/bl_bit.h>
 
 /*
  * NOTE: This board has 2 physical memory maps.
index adc9b4bba8281fd1875332d2672222a7c2294115..8b50cf763c065010666d9598bed8c1a3f59043f0 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/gfp.h>
 #include <asm/io.h>
 #include <asm/hd64461.h>
+#include <asm/bl_bit.h>
 #include <mach/hp6xx.h>
 #include <cpu/dac.h>
 #include <asm/freq.h>
index b1cb2715ad6e8de77c9d7ee555c6e078e17834da..67ee956038138b2ca039512a48995085271e36dd 100644 (file)
@@ -54,7 +54,7 @@ static int __init dma_subsys_init(void)
        if (unlikely(ret))
                return ret;
 
-       return device_create_file(dma_subsys.dev_root, &dev_attr_devices.attr);
+       return device_create_file(dma_subsys.dev_root, &dev_attr_devices);
 }
 postcore_initcall(dma_subsys_init);
 
index 37f2f4a55231f9c09854708b9f0b07c4f4ad2016..f4c1c20bcdf63289dfb0d94a3c2ed990482c337a 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/types.h>
 #include <asm/cmpxchg.h>
 
-#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
+#define ATOMIC_INIT(i) { (i) }
 
 #define atomic_read(v)         (*(volatile int *)&(v)->counter)
 #define atomic_set(v,i)                ((v)->counter = (i))
index 1a73c3e759a79d2a6b5c443bd225309d786e0b06..8bd965e00a159c2ae6f45af71b8804da23f84c98 100644 (file)
@@ -52,25 +52,31 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
        return dma_addr == 0;
 }
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t gfp)
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t gfp,
+                                   struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
        void *memory;
 
        if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
                return memory;
-       if (!ops->alloc_coherent)
+       if (!ops->alloc)
                return NULL;
 
-       memory = ops->alloc_coherent(dev, size, dma_handle, gfp);
+       memory = ops->alloc(dev, size, dma_handle, gfp, attrs);
        debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
 
        return memory;
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *vaddr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *vaddr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
 
@@ -78,14 +84,16 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
                return;
 
        debug_dma_free_coherent(dev, size, vaddr, dma_handle);
-       if (ops->free_coherent)
-               ops->free_coherent(dev, size, vaddr, dma_handle);
+       if (ops->free)
+               ops->free(dev, size, vaddr, dma_handle, attrs);
 }
 
 /* arch/sh/mm/consistent.c */
 extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
-                                       dma_addr_t *dma_addr, gfp_t flag);
+                                       dma_addr_t *dma_addr, gfp_t flag,
+                                       struct dma_attrs *attrs);
 extern void dma_generic_free_coherent(struct device *dev, size_t size,
-                                     void *vaddr, dma_addr_t dma_handle);
+                                     void *vaddr, dma_addr_t dma_handle,
+                                     struct dma_attrs *attrs);
 
 #endif /* __ASM_SH_DMA_MAPPING_H */
index 7f1b70cace35d74be094e5078df32fe63c7eb680..f8f7af51c12892e6fc513a5a38aa8786789c163b 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/slab.h>
 #include <asm/processor.h>
 #include <asm/fpu.h>
+#include <asm/traps.h>
 
 int init_fpu(struct task_struct *tsk)
 {
index 488d24e0cdf0b1aa59988a17afc7a9edd9a7e898..98bbaa447c93400363b9ed1e5b3739473598bfec 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/fpu.h>
+#include <asm/traps.h>
 
 /* The PR (precision) bit in the FP Status Register must be clear when
  * an frchg instruction is executed, otherwise the instruction is undefined.
index e74cd6c0f10de9c5b94078de2ada8ddd5afa47d9..69ab4d3c8d4149be3bfd90dbb6d97090c12aceed 100644 (file)
@@ -16,6 +16,7 @@
 #include <cpu/fpu.h>
 #include <asm/processor.h>
 #include <asm/fpu.h>
+#include <asm/traps.h>
 
 /* The PR (precision) bit in the FP Status Register must be clear when
  * an frchg instruction is executed, otherwise the instruction is undefined.
index 5853989586ed6a2d4687937d38c80381106eea0e..04ab5aeaf9206527d0eae807a317ecd342a233fd 100644 (file)
@@ -113,7 +113,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
        /* MSTP32 clocks */
-       CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
+       CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP004]),
        CLKDEV_CON_ID("riic0", &mstp_clks[MSTP000]),
        CLKDEV_CON_ID("riic1", &mstp_clks[MSTP000]),
        CLKDEV_CON_ID("riic2", &mstp_clks[MSTP000]),
index a6f95ae4aae705269db86f8e133f3114d93646a1..08d27fac8d080736110008282b03188d8917cae8 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/suspend.h>
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
+#include <asm/bl_bit.h>
 
 /*
  * Notifier lists for pre/post sleep notification
index 3c55b87f8b63195480f365cb34882b95dbee4b2b..5b0bfcda6d0b7dc07bd72ffc2fd1c758a88b161d 100644 (file)
@@ -63,8 +63,8 @@ static void nommu_sync_sg(struct device *dev, struct scatterlist *sg,
 #endif
 
 struct dma_map_ops nommu_dma_ops = {
-       .alloc_coherent         = dma_generic_alloc_coherent,
-       .free_coherent          = dma_generic_free_coherent,
+       .alloc                  = dma_generic_alloc_coherent,
+       .free                   = dma_generic_free_coherent,
        .map_page               = nommu_map_page,
        .map_sg                 = nommu_map_sg,
 #ifdef CONFIG_DMA_NONCOHERENT
index 64852ecc6881ecab8646ad6ff59a1e2643941e69..ee226e20c20cf49e874efb87fd11bba4681e73fd 100644 (file)
@@ -17,8 +17,8 @@
 #include <linux/irqflags.h>
 #include <linux/smp.h>
 #include <linux/cpuidle.h>
-#include <asm/pgalloc.h>
 #include <linux/atomic.h>
+#include <asm/pgalloc.h>
 #include <asm/smp.h>
 #include <asm/bl_bit.h>
 
index efb6d398dec3b9f2a1beacc8c279b8bfd1c5c6d6..b117781bfea2914efef3579cbe696cd29f399f00 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/cacheflush.h>
+#include <asm/traps.h>
 
 /* Macros for single step instruction identification */
 #define OPCODE_BT(op)          (((op) & 0xff00) == 0x8900)
index f72e3a951588297fe59ed0f310574f75cd2be17b..94273aaf78c1605da62d82ea61dc14a746ec5dff 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/mmu_context.h>
 #include <asm/fpu.h>
 #include <asm/syscalls.h>
+#include <asm/switch_to.h>
 
 void show_regs(struct pt_regs * regs)
 {
index a17a14d32340fb1c537955b3b1266d20cfe3576d..eaebdf6a5c77506f5b80bb2af9f9693d17894838 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/smp.h>
 #include <asm/cacheflush.h>
 #include <asm/sections.h>
+#include <asm/setup.h>
 
 int __cpu_number_map[NR_CPUS];         /* Map physical to logical */
 int __cpu_logical_map[NR_CPUS];                /* Map logical to physical */
index 555a64f124ca0cf9200e10c615662bb492c54db2..23af17584054e4601ae6277046eafd1145841a99 100644 (file)
@@ -34,6 +34,41 @@ __kernel_rt_sigreturn:
 1:     .short  __NR_rt_sigreturn
 .LEND_rt_sigreturn:
        .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
+       .previous
 
        .section .eh_frame,"a",@progbits
+.LCIE1:
+       .ualong .LCIE1_end - .LCIE1_start
+.LCIE1_start:
+       .ualong 0               /* CIE ID */
+       .byte   0x1             /* Version number */
+       .string "zRS"           /* NUL-terminated augmentation string */
+       .uleb128 0x1            /* Code alignment factor */
+       .sleb128 -4             /* Data alignment factor */
+       .byte   0x11            /* Return address register column */
+       .uleb128 0x1            /* Augmentation length and data */
+       .byte 0x1b              /* DW_EH_PE_pcrel | DW_EH_PE_sdata4. */
+       .byte   0xc, 0xf, 0x0   /* DW_CFA_def_cfa: r15 ofs 0 */
+
+       .align 2
+.LCIE1_end:
+
+       .ualong .LFDE0_end-.LFDE0_start /* Length FDE0 */
+.LFDE0_start:
+       .ualong .LFDE0_start-.LCIE1     /* CIE pointer */
+       .ualong .LSTART_sigreturn-.     /* PC-relative start address */
+       .ualong .LEND_sigreturn-.LSTART_sigreturn
+       .uleb128 0                      /* Augmentation */
+       .align 2
+.LFDE0_end:
+
+       .ualong .LFDE1_end-.LFDE1_start /* Length FDE1 */
+.LFDE1_start:
+       .ualong .LFDE1_start-.LCIE1     /* CIE pointer */
+       .ualong .LSTART_rt_sigreturn-.  /* PC-relative start address */
+       .ualong .LEND_rt_sigreturn-.LSTART_rt_sigreturn
+       .uleb128 0                      /* Augmentation */
+       .align 2
+.LFDE1_end:
+
        .previous
index 3e70f851cdc6c1b674af7dec81bb8f19e290d4ad..0eb74d00690a18d4c725fb95c9bd697c7a04e7f6 100644 (file)
@@ -3,37 +3,34 @@
        .type __kernel_vsyscall,@function
 __kernel_vsyscall:
 .LSTART_vsyscall:
-       /* XXX: We'll have to do something here once we opt to use the vDSO
-        * page for something other than the signal trampoline.. as well as
-        * fill out .eh_frame -- PFM. */
+       trapa   #0x10
+        nop
 .LEND_vsyscall:
        .size __kernel_vsyscall,.-.LSTART_vsyscall
+       .previous
 
        .section .eh_frame,"a",@progbits
-       .previous
 .LCIE:
        .ualong .LCIE_end - .LCIE_start
 .LCIE_start:
        .ualong 0               /* CIE ID */
        .byte   0x1             /* Version number */
-       .string "zRS"           /* NUL-terminated augmentation string */
+       .string "zR           /* NUL-terminated augmentation string */
        .uleb128 0x1            /* Code alignment factor */
        .sleb128 -4             /* Data alignment factor */
        .byte   0x11            /* Return address register column */
-                               /* Augmentation length and data (none) */
-       .byte   0xc             /* DW_CFA_def_cfa */
-       .uleb128 0xf            /* r15 */
-       .uleb128 0x0            /* offset 0 */
-
+       .uleb128 0x1            /* Augmentation length and data */
+       .byte 0x1b              /* DW_EH_PE_pcrel | DW_EH_PE_sdata4. */
+       .byte   0xc,0xf,0x0     /* DW_CFA_def_cfa: r15 ofs 0 */
        .align 2
 .LCIE_end:
 
        .ualong .LFDE_end-.LFDE_start   /* Length FDE */
 .LFDE_start:
-       .ualong .LCIE                   /* CIE pointer */
-       .ualong .LSTART_vsyscall-.      /* start address */
+       .ualong .LFDE_start-.LCIE       /* CIE pointer */
+       .ualong .LSTART_vsyscall-.      /* PC-relative start address */
        .ualong .LEND_vsyscall-.LSTART_vsyscall
-       .uleb128 0
+       .uleb128 0                      /* Augmentation */
        .align 2
 .LFDE_end:
        .previous
index 112fea12522afab24166a879bc496e5fbda8e893..0e529285b28d42c688fb0901349ba70218385d51 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/highmem.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
+#include <asm/cache_insns.h>
 #include <asm/cacheflush.h>
 
 /*
index f251b5f27652f3aa278c3789d198e88c841c3938..b81d9dbf9fef195291e3d9454b59f3ed6a1315c6 100644 (file)
@@ -33,7 +33,8 @@ static int __init dma_init(void)
 fs_initcall(dma_init);
 
 void *dma_generic_alloc_coherent(struct device *dev, size_t size,
-                                dma_addr_t *dma_handle, gfp_t gfp)
+                                dma_addr_t *dma_handle, gfp_t gfp,
+                                struct dma_attrs *attrs)
 {
        void *ret, *ret_nocache;
        int order = get_order(size);
@@ -64,7 +65,8 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
 }
 
 void dma_generic_free_coherent(struct device *dev, size_t size,
-                              void *vaddr, dma_addr_t dma_handle)
+                              void *vaddr, dma_addr_t dma_handle,
+                              struct dma_attrs *attrs)
 {
        int order = get_order(size);
        unsigned long pfn = dma_handle >> PAGE_SHIFT;
index 324eef93c90068ae91d202aebe986339aa8bf192..e99b104d967a3464d555459b024a19e09263815f 100644 (file)
@@ -86,7 +86,7 @@ static noinline int vmalloc_fault(unsigned long address)
        pte_t *pte_k;
 
        /* Make sure we are in vmalloc/module/P3 area: */
-       if (!(address >= VMALLOC_START && address < P3_ADDR_MAX))
+       if (!(address >= P3SEG && address < P3_ADDR_MAX))
                return -1;
 
        /*
index 75a17f5bfa1478f906d1b4c9dbcffc5b82b7badf..0b85dd9dd3a7df0ae97e37da5228328bf0c4a5ac 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
+#include <asm/cache_insns.h>
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
 
index bc156ec4545e07941bce9f5a1cb4fcafd35b449d..2d8fa718d55e7416eeffc12e932717953c951d2e 100644 (file)
@@ -9,6 +9,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
 #include <asm/sram.h>
 
 /*
index 8c0e4f7bb20484a674f663f30bf34789be6877d9..48a7c65731d2e0cf08ab2e974adcf922f2dddc58 100644 (file)
@@ -26,24 +26,30 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 
 #include <asm-generic/dma-mapping-common.h>
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
        void *cpu_addr;
 
-       cpu_addr = ops->alloc_coherent(dev, size, dma_handle, flag);
+       cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
        debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
        return cpu_addr;
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
 
        debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
-       ops->free_coherent(dev, size, cpu_addr, dma_handle);
+       ops->free(dev, size, cpu_addr, dma_handle, attrs);
 }
 
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
index 6fa2f7980e6bc09fee78bb0dd34ecb0009ea68c1..76e4a52aa85e2db6588cb261b82bd94bbf697dd9 100644 (file)
@@ -12,8 +12,6 @@
  * the SpitFire page tables.
  */
 
-#include <asm-generic/pgtable-nopud.h>
-
 #include <linux/compiler.h>
 #include <linux/const.h>
 #include <asm/types.h>
@@ -22,6 +20,8 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 
+#include <asm-generic/pgtable-nopud.h>
+
 /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB).
  * The page copy blockops can use 0x6000000 to 0x8000000.
  * The TSB is mapped in the 0x8000000 to 0xa000000 range.
index fea13c7b1aeeddcf206217c935a1b044ae96e215..b93c2c9ccb1d17c250d4a945e0fea06fff38baf6 100644 (file)
@@ -1264,4 +1264,4 @@ static int __init ds_init(void)
        return vio_register_driver(&ds_driver);
 }
 
-subsys_initcall(ds_init);
+fs_initcall(ds_init);
index 4643d68713fa48d415d2aff92e1c86315ff91f6f..070ed141aac79728da15f406289219a9c385fe27 100644 (file)
@@ -280,7 +280,8 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
 }
 
 static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
-                                  dma_addr_t *dma_addrp, gfp_t gfp)
+                                  dma_addr_t *dma_addrp, gfp_t gfp,
+                                  struct dma_attrs *attrs)
 {
        unsigned long flags, order, first_page;
        struct iommu *iommu;
@@ -330,7 +331,8 @@ static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
 }
 
 static void dma_4u_free_coherent(struct device *dev, size_t size,
-                                void *cpu, dma_addr_t dvma)
+                                void *cpu, dma_addr_t dvma,
+                                struct dma_attrs *attrs)
 {
        struct iommu *iommu;
        unsigned long flags, order, npages;
@@ -825,8 +827,8 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev,
 }
 
 static struct dma_map_ops sun4u_dma_ops = {
-       .alloc_coherent         = dma_4u_alloc_coherent,
-       .free_coherent          = dma_4u_free_coherent,
+       .alloc                  = dma_4u_alloc_coherent,
+       .free                   = dma_4u_free_coherent,
        .map_page               = dma_4u_map_page,
        .unmap_page             = dma_4u_unmap_page,
        .map_sg                 = dma_4u_map_sg,
index d0479e2163faa8615b4a3cc6d75c1c87bb33d660..21bd73943f7f8c7b4421b5f1bd8f106433b8377a 100644 (file)
@@ -261,7 +261,8 @@ EXPORT_SYMBOL(sbus_set_sbus64);
  * CPU may access them without any explicit flushing.
  */
 static void *sbus_alloc_coherent(struct device *dev, size_t len,
-                                dma_addr_t *dma_addrp, gfp_t gfp)
+                                dma_addr_t *dma_addrp, gfp_t gfp,
+                                struct dma_attrs *attrs)
 {
        struct platform_device *op = to_platform_device(dev);
        unsigned long len_total = PAGE_ALIGN(len);
@@ -315,7 +316,7 @@ err_nopages:
 }
 
 static void sbus_free_coherent(struct device *dev, size_t n, void *p,
-                              dma_addr_t ba)
+                              dma_addr_t ba, struct dma_attrs *attrs)
 {
        struct resource *res;
        struct page *pgv;
@@ -407,8 +408,8 @@ static void sbus_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 }
 
 struct dma_map_ops sbus_dma_ops = {
-       .alloc_coherent         = sbus_alloc_coherent,
-       .free_coherent          = sbus_free_coherent,
+       .alloc                  = sbus_alloc_coherent,
+       .free                   = sbus_free_coherent,
        .map_page               = sbus_map_page,
        .unmap_page             = sbus_unmap_page,
        .map_sg                 = sbus_map_sg,
@@ -436,7 +437,8 @@ arch_initcall(sparc_register_ioport);
  * hwdev should be valid struct pci_dev pointer for PCI devices.
  */
 static void *pci32_alloc_coherent(struct device *dev, size_t len,
-                                 dma_addr_t *pba, gfp_t gfp)
+                                 dma_addr_t *pba, gfp_t gfp,
+                                 struct dma_attrs *attrs)
 {
        unsigned long len_total = PAGE_ALIGN(len);
        void *va;
@@ -489,7 +491,7 @@ err_nopages:
  * past this call are illegal.
  */
 static void pci32_free_coherent(struct device *dev, size_t n, void *p,
-                               dma_addr_t ba)
+                               dma_addr_t ba, struct dma_attrs *attrs)
 {
        struct resource *res;
 
@@ -645,8 +647,8 @@ static void pci32_sync_sg_for_device(struct device *device, struct scatterlist *
 }
 
 struct dma_map_ops pci32_dma_ops = {
-       .alloc_coherent         = pci32_alloc_coherent,
-       .free_coherent          = pci32_free_coherent,
+       .alloc                  = pci32_alloc_coherent,
+       .free                   = pci32_free_coherent,
        .map_page               = pci32_map_page,
        .unmap_page             = pci32_unmap_page,
        .map_sg                 = pci32_map_sg,
index a19c8a063683205c35792991efad03fe961f8140..35e43673c45344afd3a58c382fb78a7bc419284d 100644 (file)
@@ -104,11 +104,11 @@ static int irq_choose_cpu(const struct cpumask *affinity)
 {
        cpumask_t mask;
 
-       cpus_and(mask, cpu_online_map, *affinity);
-       if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask))
+       cpumask_and(&mask, cpu_online_mask, affinity);
+       if (cpumask_equal(&mask, cpu_online_mask) || cpumask_empty(&mask))
                return boot_cpu_id;
        else
-               return first_cpu(mask);
+               return cpumask_first(&mask);
 }
 #else
 #define irq_choose_cpu(affinity) boot_cpu_id
index aba6b958b2a5da25a49adbe76783eca1e5570dc9..19f56058742be945d1a29be0137a683523aa49cd 100644 (file)
@@ -45,7 +45,6 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
 
 void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
 {
-       struct leon_pci_info *info = pbus->sysdata;
        struct pci_dev *dev;
        int i, has_io, has_mem;
        u16 cmd;
@@ -111,18 +110,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        return pci_enable_resources(dev, mask);
 }
 
-struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
-       /*
-        * Currently the OpenBoot nodes are not connected with the PCI device,
-        * this is because the LEON PROM does not create PCI nodes. Eventually
-        * this will change and the same approach as pcic.c can be used to
-        * match PROM nodes with pci devices.
-        */
-       return NULL;
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
 void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
 {
 #ifdef CONFIG_PCI_DEBUG
index 1210fde187406c2a5c149151ab46205c00c3358d..160cac9c403654043269e0a63123ecf3ee3bd0a6 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/pm.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
+#include <linux/cpu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
@@ -78,6 +79,8 @@ void __cpuinit leon_callin(void)
        local_flush_tlb_all();
        leon_configure_cache_smp();
 
+       notify_cpu_starting(cpuid);
+
        /* Get our local ticker going. */
        smp_setup_percpu_timer();
 
index af5755d20fbe91eb43b682e99aa8f836bfafa6ad..7661e84a05a06c23e34ef49fb5c63bfb69934761 100644 (file)
@@ -128,7 +128,8 @@ static inline long iommu_batch_end(void)
 }
 
 static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
-                                  dma_addr_t *dma_addrp, gfp_t gfp)
+                                  dma_addr_t *dma_addrp, gfp_t gfp,
+                                  struct dma_attrs *attrs)
 {
        unsigned long flags, order, first_page, npages, n;
        struct iommu *iommu;
@@ -198,7 +199,7 @@ range_alloc_fail:
 }
 
 static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
-                                dma_addr_t dvma)
+                                dma_addr_t dvma, struct dma_attrs *attrs)
 {
        struct pci_pbm_info *pbm;
        struct iommu *iommu;
@@ -527,8 +528,8 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
 }
 
 static struct dma_map_ops sun4v_dma_ops = {
-       .alloc_coherent                 = dma_4v_alloc_coherent,
-       .free_coherent                  = dma_4v_free_coherent,
+       .alloc                          = dma_4v_alloc_coherent,
+       .free                           = dma_4v_free_coherent,
        .map_page                       = dma_4v_map_page,
        .unmap_page                     = dma_4v_unmap_page,
        .map_sg                         = dma_4v_map_sg,
index 77f1b95e0806bb92dc19fd421acd6f159e7dfab0..9171fc238def230e6e14e92852f2ee2d9b33a8f2 100644 (file)
 
                .text
                .align                  32
-__handle_softirq:
-               call                    do_softirq
-                nop
-               ba,a,pt                 %xcc, __handle_softirq_continue
-                nop
 __handle_preemption:
                call                    schedule
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
@@ -89,9 +84,7 @@ rtrap:
                cmp                     %l1, 0
 
                /* mm/ultra.S:xcall_report_regs KNOWS about this load. */
-               bne,pn                  %icc, __handle_softirq
                 ldx                    [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
-__handle_softirq_continue:
 rtrap_xcall:
                sethi                   %hi(0xf << 20), %l4
                and                     %l1, %l4, %l4
index 232df9949530f3d95c3c95385a62d45402c6d042..3ee51f189a55297b0babeb1f54d0b40af97de6f8 100644 (file)
@@ -566,15 +566,10 @@ out:
 
 SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len)
 {
-       long ret;
-
        if (invalid_64bit_range(addr, len))
                return -EINVAL;
 
-       down_write(&current->mm->mmap_sem);
-       ret = do_munmap(current->mm, addr, len);
-       up_write(&current->mm->mmap_sem);
-       return ret;
+       return vm_munmap(addr, len);
 }
 
 extern unsigned long do_mremap(unsigned long addr,
index 7705c6731e2843697286e3d045279811d5691ed1..df3155a179918e0ad5e9741eceab601ae93d8abb 100644 (file)
@@ -225,6 +225,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
        unsigned long g2;
        int from_user = !(regs->psr & PSR_PS);
        int fault, code;
+       unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+                             (write ? FAULT_FLAG_WRITE : 0));
 
        if(text_fault)
                address = regs->pc;
@@ -251,6 +253,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
 
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
+retry:
        down_read(&mm->mmap_sem);
 
        /*
@@ -289,7 +292,11 @@ good_area:
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+       fault = handle_mm_fault(mm, vma, address, flags);
+
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+               return;
+
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
@@ -297,13 +304,29 @@ good_area:
                        goto do_sigbus;
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR) {
-               current->maj_flt++;
-               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
-       } else {
-               current->min_flt++;
-               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
+
+       if (flags & FAULT_FLAG_ALLOW_RETRY) {
+               if (fault & VM_FAULT_MAJOR) {
+                       current->maj_flt++;
+                       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
+                                     1, regs, address);
+               } else {
+                       current->min_flt++;
+                       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
+                                     1, regs, address);
+               }
+               if (fault & VM_FAULT_RETRY) {
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+                       /* No need to up_read(&mm->mmap_sem) as we would
+                        * have already released it in __lock_page_or_retry
+                        * in mm/filemap.c.
+                        */
+
+                       goto retry;
+               }
        }
+
        up_read(&mm->mmap_sem);
        return;
 
index 504c0622f7296c42bb09cae18bc487630e6344a4..1fe0429b6314257faa40d80b07f7d4e3b77538c6 100644 (file)
@@ -279,6 +279,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
        unsigned int insn = 0;
        int si_code, fault_code, fault;
        unsigned long address, mm_rss;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
        fault_code = get_thread_fault_code();
 
@@ -333,6 +334,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
                        insn = get_fault_insn(regs, insn);
                        goto handle_kernel_fault;
                }
+
+retry:
                down_read(&mm->mmap_sem);
        }
 
@@ -423,7 +426,12 @@ good_area:
                        goto bad_area;
        }
 
-       fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0);
+       flags |= ((fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0);
+       fault = handle_mm_fault(mm, vma, address, flags);
+
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+               return;
+
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
@@ -431,12 +439,27 @@ good_area:
                        goto do_sigbus;
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR) {
-               current->maj_flt++;
-               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
-       } else {
-               current->min_flt++;
-               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
+
+       if (flags & FAULT_FLAG_ALLOW_RETRY) {
+               if (fault & VM_FAULT_MAJOR) {
+                       current->maj_flt++;
+                       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
+                                     1, regs, address);
+               } else {
+                       current->min_flt++;
+                       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
+                                     1, regs, address);
+               }
+               if (fault & VM_FAULT_RETRY) {
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+                       /* No need to up_read(&mm->mmap_sem) as we would
+                        * have already released it in __lock_page_or_retry
+                        * in mm/filemap.c.
+                        */
+
+                       goto retry;
+               }
        }
        up_read(&mm->mmap_sem);
 
index 11270ca22c0a7b880718cd832a3e890f0b69c28f..96033e2d6845cc84a442541fb73f095f8d272f91 100644 (file)
@@ -12,7 +12,7 @@ config TILE
        select GENERIC_PENDING_IRQ if SMP
        select GENERIC_IRQ_SHOW
        select SYS_HYPERVISOR
-       select ARCH_HAVE_NMI_SAFE_CMPXCHG if !M386
+       select ARCH_HAVE_NMI_SAFE_CMPXCHG
 
 # FIXME: investigate whether we need/want these options.
 #      select HAVE_IOREMAP_PROT
@@ -69,6 +69,9 @@ config ARCH_PHYS_ADDR_T_64BIT
 config ARCH_DMA_ADDR_T_64BIT
        def_bool y
 
+config NEED_DMA_MAP_STATE
+       def_bool y
+
 config LOCKDEP_SUPPORT
        def_bool y
 
@@ -118,7 +121,7 @@ config 64BIT
 
 config ARCH_DEFCONFIG
        string
-       default "arch/tile/configs/tile_defconfig" if !TILEGX
+       default "arch/tile/configs/tilepro_defconfig" if !TILEGX
        default "arch/tile/configs/tilegx_defconfig" if TILEGX
 
 source "init/Kconfig"
@@ -240,6 +243,7 @@ endchoice
 
 config PAGE_OFFSET
        hex
+       depends on !64BIT
        default 0xF0000000 if VMSPLIT_3_75G
        default 0xE0000000 if VMSPLIT_3_5G
        default 0xB0000000 if VMSPLIT_2_75G
index 17acce70569b01aaf7de554a66c0f7e6e8a47157..9520bc5a4b7f65f9904882185267d797885ab7f5 100644 (file)
@@ -30,7 +30,8 @@ ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
 KBUILD_CFLAGS   += $(CONFIG_DEBUG_EXTRA_FLAGS)
 endif
 
-LIBGCC_PATH     := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+LIBGCC_PATH     := \
+  $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
 
 # Provide the path to use for "make defconfig".
 KBUILD_DEFCONFIG := $(ARCH)_defconfig
@@ -53,8 +54,6 @@ libs-y                += $(LIBGCC_PATH)
 # See arch/tile/Kbuild for content of core part of the kernel
 core-y         += arch/tile/
 
-core-$(CONFIG_KVM) += arch/tile/kvm/
-
 ifdef TILERA_ROOT
 INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot
 endif
index f548efeb2de3f7fc005f90854a80d1b4941e3a98..d6ba449b5363f3318d094ece0f1bf455853da755 100644 (file)
@@ -60,8 +60,8 @@
        _concat4(SPR_IPI_EVENT_, CONFIG_KERNEL_PL,,)
 #define SPR_IPI_EVENT_RESET_K \
        _concat4(SPR_IPI_EVENT_RESET_, CONFIG_KERNEL_PL,,)
-#define SPR_IPI_MASK_SET_K \
-       _concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_EVENT_SET_K \
+       _concat4(SPR_IPI_EVENT_SET_, CONFIG_KERNEL_PL,,)
 #define INT_IPI_K \
        _concat4(INT_IPI_, CONFIG_KERNEL_PL,,)
 
index bb696da5d7cdbdbd4b20d98dedc9d12d53ced994..f2461429a4a4004b474e5024447b4a11200d4fa3 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef _ASM_TILE_ATOMIC_H
 #define _ASM_TILE_ATOMIC_H
 
+#include <asm/cmpxchg.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/compiler.h>
@@ -121,54 +123,6 @@ static inline int atomic_read(const atomic_t *v)
  */
 #define atomic_add_negative(i, v)      (atomic_add_return((i), (v)) < 0)
 
-/* Nonexistent functions intended to cause link errors. */
-extern unsigned long __xchg_called_with_bad_pointer(void);
-extern unsigned long __cmpxchg_called_with_bad_pointer(void);
-
-#define xchg(ptr, x)                                                   \
-       ({                                                              \
-               typeof(*(ptr)) __x;                                     \
-               switch (sizeof(*(ptr))) {                               \
-               case 4:                                                 \
-                       __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \
-                               (atomic_t *)(ptr),                      \
-                               (u32)(typeof((x)-(x)))(x));             \
-                       break;                                          \
-               case 8:                                                 \
-                       __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \
-                               (atomic64_t *)(ptr),                    \
-                               (u64)(typeof((x)-(x)))(x));             \
-                       break;                                          \
-               default:                                                \
-                       __xchg_called_with_bad_pointer();               \
-               }                                                       \
-               __x;                                                    \
-       })
-
-#define cmpxchg(ptr, o, n)                                             \
-       ({                                                              \
-               typeof(*(ptr)) __x;                                     \
-               switch (sizeof(*(ptr))) {                               \
-               case 4:                                                 \
-                       __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \
-                               (atomic_t *)(ptr),                      \
-                               (u32)(typeof((o)-(o)))(o),              \
-                               (u32)(typeof((n)-(n)))(n));             \
-                       break;                                          \
-               case 8:                                                 \
-                       __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \
-                               (atomic64_t *)(ptr),                    \
-                               (u64)(typeof((o)-(o)))(o),              \
-                               (u64)(typeof((n)-(n)))(n));             \
-                       break;                                          \
-               default:                                                \
-                       __cmpxchg_called_with_bad_pointer();            \
-               }                                                       \
-               __x;                                                    \
-       })
-
-#define tas(ptr) (xchg((ptr), 1))
-
 #endif /* __ASSEMBLY__ */
 
 #ifndef __tilegx__
index 466dc4a39a4faf004d7d7dcabd683d6d41044f40..54d1da826f93dfbf167aaa3c219f143783d91902 100644 (file)
@@ -200,7 +200,7 @@ static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as @v was not already @u.
- * Returns the old value of @v.
+ * Returns non-zero if @v was not @u, and zero otherwise.
  */
 static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
 {
index 58d021a9834f0b12d2b8bc2f091d32a22ca17baf..60b87ee54fb8863eb2387467b76d95117405fb6c 100644 (file)
@@ -38,10 +38,10 @@ static inline void clear_bit(unsigned nr, volatile unsigned long *addr)
 
 static inline void change_bit(unsigned nr, volatile unsigned long *addr)
 {
-       unsigned long old, mask = (1UL << (nr % BITS_PER_LONG));
-       long guess, oldval;
+       unsigned long mask = (1UL << (nr % BITS_PER_LONG));
+       unsigned long guess, oldval;
        addr += nr / BITS_PER_LONG;
-       old = *addr;
+       oldval = *addr;
        do {
                guess = oldval;
                oldval = atomic64_cmpxchg((atomic64_t *)addr,
@@ -85,7 +85,7 @@ static inline int test_and_change_bit(unsigned nr,
                                      volatile unsigned long *addr)
 {
        unsigned long mask = (1UL << (nr % BITS_PER_LONG));
-       long guess, oldval = *addr;
+       unsigned long guess, oldval;
        addr += nr / BITS_PER_LONG;
        oldval = *addr;
        do {
diff --git a/arch/tile/include/asm/cmpxchg.h b/arch/tile/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..276f067
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * cmpxchg.h -- forked from asm/atomic.h with this copyright:
+ *
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ */
+
+#ifndef _ASM_TILE_CMPXCHG_H
+#define _ASM_TILE_CMPXCHG_H
+
+#ifndef __ASSEMBLY__
+
+/* Nonexistent functions intended to cause link errors. */
+extern unsigned long __xchg_called_with_bad_pointer(void);
+extern unsigned long __cmpxchg_called_with_bad_pointer(void);
+
+#define xchg(ptr, x)                                                   \
+       ({                                                              \
+               typeof(*(ptr)) __x;                                     \
+               switch (sizeof(*(ptr))) {                               \
+               case 4:                                                 \
+                       __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \
+                               (atomic_t *)(ptr),                      \
+                               (u32)(typeof((x)-(x)))(x));             \
+                       break;                                          \
+               case 8:                                                 \
+                       __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \
+                               (atomic64_t *)(ptr),                    \
+                               (u64)(typeof((x)-(x)))(x));             \
+                       break;                                          \
+               default:                                                \
+                       __xchg_called_with_bad_pointer();               \
+               }                                                       \
+               __x;                                                    \
+       })
+
+#define cmpxchg(ptr, o, n)                                             \
+       ({                                                              \
+               typeof(*(ptr)) __x;                                     \
+               switch (sizeof(*(ptr))) {                               \
+               case 4:                                                 \
+                       __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \
+                               (atomic_t *)(ptr),                      \
+                               (u32)(typeof((o)-(o)))(o),              \
+                               (u32)(typeof((n)-(n)))(n));             \
+                       break;                                          \
+               case 8:                                                 \
+                       __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \
+                               (atomic64_t *)(ptr),                    \
+                               (u64)(typeof((o)-(o)))(o),              \
+                               (u64)(typeof((n)-(n)))(n));             \
+                       break;                                          \
+               default:                                                \
+                       __cmpxchg_called_with_bad_pointer();            \
+               }                                                       \
+               __x;                                                    \
+       })
+
+#define tas(ptr) (xchg((ptr), 1))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_TILE_CMPXCHG_H */
index f80f8ceabc67abd6ef57fce76cb1a224f53204c8..33cff9a3058b02ebb2104ab04bcc85741ec83e0d 100644 (file)
@@ -21,7 +21,7 @@
 #define NR_IRQS 32
 
 /* IRQ numbers used for linux IPIs. */
-#define IRQ_RESCHEDULE 1
+#define IRQ_RESCHEDULE 0
 
 #define irq_canonicalize(irq)   (irq)
 
index 5d5a635530bd5ed527eb6387ce3a0170d605e0b0..32e6cbe8dff3350d1d7e236691fced9a47bd2c8d 100644 (file)
@@ -47,8 +47,8 @@ struct pci_controller {
  */
 #define PCI_DMA_BUS_IS_PHYS     1
 
-int __devinit tile_pci_init(void);
-int __devinit pcibios_init(void);
+int __init tile_pci_init(void);
+int __init pcibios_init(void);
 
 static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
 
index 72be5904e020e7df9b4923edb92bf25fbf8670a5..5f8b6a095fd84a0748ea645c96a4b3908ba6d6fb 100644 (file)
@@ -137,7 +137,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 static inline void arch_write_unlock(arch_rwlock_t *rw)
 {
        __insn_mf();
-       rw->lock = 0;
+       __insn_exch4(&rw->lock, 0);  /* Avoid waiting in the write buffer. */
 }
 
 static inline int arch_read_trylock(arch_rwlock_t *rw)
index 4d97a2db932e90784d37eb4f53ff7da3f80eb4e2..0e9d382a2d451482ff2d5f686cdecaa8b7f56a05 100644 (file)
@@ -25,7 +25,6 @@
 struct KBacktraceIterator {
        BacktraceIterator it;
        struct task_struct *task;     /* task we are backtracing */
-       pte_t *pgtable;               /* page table for user space access */
        int end;                      /* iteration complete. */
        int new_context;              /* new context is starting */
        int profile;                  /* profiling, so stop on async intrpt */
index 5f20f920f932b6c38e0a8971d1cedfb012dd729c..e28c3df4176a918c09fc56dfa702c17e0f48e401 100644 (file)
@@ -64,7 +64,11 @@ void do_breakpoint(struct pt_regs *, int fault_num);
 
 
 #ifdef __tilegx__
+/* kernel/single_step.c */
 void gx_singlestep_handle(struct pt_regs *, int fault_num);
+
+/* kernel/intvec_64.S */
+void fill_ra_stack(void);
 #endif
 
-#endif /* _ASM_TILE_SYSCALLS_H */
+#endif /* _ASM_TILE_TRAPS_H */
index 431e9ae60488c73f29c35761170150e7f65a7a92..ec91568df880ef0d41f99f7ab86cc0fdb2330551 100644 (file)
@@ -85,6 +85,7 @@ STD_ENTRY(cpu_idle_on_new_stack)
 /* Loop forever on a nap during SMP boot. */
 STD_ENTRY(smp_nap)
        nap
+       nop       /* avoid provoking the icache prefetch with a jump */
        j smp_nap /* we are not architecturally guaranteed not to exit nap */
        jrp lr    /* clue in the backtracer */
        STD_ENDPROC(smp_nap)
@@ -105,5 +106,6 @@ STD_ENTRY(_cpu_idle)
        .global _cpu_idle_nap
 _cpu_idle_nap:
        nap
+       nop       /* avoid provoking the icache prefetch with a jump */
        jrp lr
        STD_ENDPROC(_cpu_idle)
index aecc8ed5f39bd71d48cb150fe30301425b2179b7..5d56a1ef5ba5212e6cffe97e0fe14223bc0d116b 100644 (file)
@@ -799,6 +799,10 @@ handle_interrupt:
  * This routine takes a boolean in r30 indicating if this is an NMI.
  * If so, we also expect a boolean in r31 indicating whether to
  * re-enable the oprofile interrupts.
+ *
+ * Note that .Lresume_userspace is jumped to directly in several
+ * places, and we need to make sure r30 is set correctly in those
+ * callers as well.
  */
 STD_ENTRY(interrupt_return)
        /* If we're resuming to kernel space, don't check thread flags. */
@@ -1237,7 +1241,10 @@ handle_syscall:
        bzt     r30, 1f
        jal     do_syscall_trace
        FEEDBACK_REENTER(handle_syscall)
-1:     j       .Lresume_userspace   /* jump into middle of interrupt_return */
+1:     {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
 
 .Linvalid_syscall:
        /* Report an invalid syscall back to the user program */
@@ -1246,7 +1253,10 @@ handle_syscall:
         movei  r28, -ENOSYS
        }
        sw      r29, r28
-       j       .Lresume_userspace   /* jump into middle of interrupt_return */
+       {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
        STD_ENDPROC(handle_syscall)
 
        /* Return the address for oprofile to suppress in backtraces. */
@@ -1262,7 +1272,10 @@ STD_ENTRY(ret_from_fork)
        jal     sim_notify_fork
        jal     schedule_tail
        FEEDBACK_REENTER(ret_from_fork)
-       j       .Lresume_userspace   /* jump into middle of interrupt_return */
+       {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
        STD_ENDPROC(ret_from_fork)
 
        /*
@@ -1376,7 +1389,10 @@ handle_ill:
 
        jal     send_sigtrap    /* issue a SIGTRAP */
        FEEDBACK_REENTER(handle_ill)
-       j       .Lresume_userspace   /* jump into middle of interrupt_return */
+       {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
 
 .Ldispatch_normal_ill:
        {
index 79c93e10ba27b1a11c939e216233ec5956b6b11a..49d9d66216822a463a4e905f3425e8eb2a4f77e8 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/irqflags.h>
 #include <asm/asm-offsets.h>
 #include <asm/types.h>
+#include <asm/signal.h>
 #include <hv/hypervisor.h>
 #include <arch/abi.h>
 #include <arch/interrupts.h>
@@ -605,6 +606,10 @@ handle_interrupt:
  * This routine takes a boolean in r30 indicating if this is an NMI.
  * If so, we also expect a boolean in r31 indicating whether to
  * re-enable the oprofile interrupts.
+ *
+ * Note that .Lresume_userspace is jumped to directly in several
+ * places, and we need to make sure r30 is set correctly in those
+ * callers as well.
  */
 STD_ENTRY(interrupt_return)
        /* If we're resuming to kernel space, don't check thread flags. */
@@ -1039,11 +1044,28 @@ handle_syscall:
 
        /* Do syscall trace again, if requested. */
        ld      r30, r31
-       andi    r30, r30, _TIF_SYSCALL_TRACE
-       beqzt   r30, 1f
+       andi    r0, r30, _TIF_SYSCALL_TRACE
+       {
+        andi    r0, r30, _TIF_SINGLESTEP
+        beqzt   r0, 1f
+       }
        jal     do_syscall_trace
        FEEDBACK_REENTER(handle_syscall)
-1:     j       .Lresume_userspace   /* jump into middle of interrupt_return */
+       andi    r0, r30, _TIF_SINGLESTEP
+
+1:     beqzt   r0, 2f
+
+       /* Single stepping -- notify ptrace. */
+       {
+        movei   r0, SIGTRAP
+        jal     ptrace_notify
+       }
+       FEEDBACK_REENTER(handle_syscall)
+
+2:     {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
 
 .Lcompat_syscall:
        /*
@@ -1077,7 +1099,10 @@ handle_syscall:
         movei  r28, -ENOSYS
        }
        st      r29, r28
-       j       .Lresume_userspace   /* jump into middle of interrupt_return */
+       {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
        STD_ENDPROC(handle_syscall)
 
        /* Return the address for oprofile to suppress in backtraces. */
@@ -1093,7 +1118,10 @@ STD_ENTRY(ret_from_fork)
        jal     sim_notify_fork
        jal     schedule_tail
        FEEDBACK_REENTER(ret_from_fork)
-       j       .Lresume_userspace
+       {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
        STD_ENDPROC(ret_from_fork)
 
 /* Various stub interrupt handlers and syscall handlers */
@@ -1156,6 +1184,18 @@ int_unalign:
        push_extra_callee_saves r0
        j       do_trap
 
+/* Fill the return address stack with nonzero entries. */
+STD_ENTRY(fill_ra_stack)
+       {
+        move   r0, lr
+        jal    1f
+       }
+1:     jal     2f
+2:     jal     3f
+3:     jal     4f
+4:     jrp     r0
+       STD_ENDPROC(fill_ra_stack)
+
 /* Include .intrpt1 array of interrupt vectors */
        .section ".intrpt1", "ax"
 
@@ -1166,7 +1206,7 @@ int_unalign:
 #define do_hardwall_trap bad_intr
 #endif
 
-       int_hand     INT_MEM_ERROR, MEM_ERROR, bad_intr
+       int_hand     INT_MEM_ERROR, MEM_ERROR, do_trap
        int_hand     INT_SINGLE_STEP_3, SINGLE_STEP_3, bad_intr
 #if CONFIG_KERNEL_PL == 2
        int_hand     INT_SINGLE_STEP_2, SINGLE_STEP_2, gx_singlestep_handle
index b90ab9925674339f1389abd511fc56d7c6881330..98d476920106084d847b54fd9bf9cc19c9e21983 100644 (file)
@@ -67,6 +67,8 @@ void *module_alloc(unsigned long size)
        area = __get_vm_area(size, VM_ALLOC, MEM_MODULE_START, MEM_MODULE_END);
        if (!area)
                goto error;
+       area->nr_pages = npages;
+       area->pages = pages;
 
        if (map_vm_area(area, prot_rwx, &pages)) {
                vunmap(area->addr);
index a1bb59eecc1850bcd7aedf6f1ec538498e0d1573..b56d12bf5900c8f266132bc9b50dadfb092af10a 100644 (file)
@@ -141,7 +141,7 @@ static int __devinit tile_init_irqs(int controller_id,
  *
  * Returns the number of controllers discovered.
  */
-int __devinit tile_pci_init(void)
+int __init tile_pci_init(void)
 {
        int i;
 
@@ -287,7 +287,7 @@ static void __devinit fixup_read_and_payload_sizes(void)
  * The controllers have been set up by the time we get here, by a call to
  * tile_pci_init.
  */
-int __devinit pcibios_init(void)
+int __init pcibios_init(void)
 {
        int i;
 
index 7a93270464045753c76caa4032716ea6981c082c..446a7f52cc11f3a6380b7e6cfbf2181abca046a0 100644 (file)
@@ -146,7 +146,6 @@ static ctl_table unaligned_table[] = {
        },
        {}
 };
-#endif
 
 static struct ctl_path tile_path[] = {
        { .procname = "tile" },
@@ -155,10 +154,9 @@ static struct ctl_path tile_path[] = {
 
 static int __init proc_sys_tile_init(void)
 {
-#ifndef __tilegx__  /* FIXME: GX: no support for unaligned access yet */
        register_sysctl_paths(tile_path, unaligned_table);
-#endif
        return 0;
 }
 
 arch_initcall(proc_sys_tile_init);
+#endif
index 30caecac94dcae955928900c4d6841c154263810..2d5ef617bb3906cfcf1f9846af10b9d87e8d53e0 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/tracehook.h>
 #include <linux/signal.h>
 #include <asm/stack.h>
+#include <asm/switch_to.h>
 #include <asm/homecache.h>
 #include <asm/syscalls.h>
 #include <asm/traps.h>
@@ -285,7 +286,7 @@ struct task_struct *validate_current(void)
        static struct task_struct corrupt = { .comm = "<corrupt>" };
        struct task_struct *tsk = current;
        if (unlikely((unsigned long)tsk < PAGE_OFFSET ||
-                    (void *)tsk > high_memory ||
+                    (high_memory && (void *)tsk > high_memory) ||
                     ((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) {
                pr_err("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer);
                tsk = &corrupt;
index 5f85d8b34dbb0ed717484c03954a1254f4c5f0b1..bff23f4761103713ee00be2294a726fac6eeb06c 100644 (file)
@@ -103,13 +103,11 @@ unsigned long __initdata pci_reserve_end_pfn = -1U;
 
 static int __init setup_maxmem(char *str)
 {
-       long maxmem_mb;
-       if (str == NULL || strict_strtol(str, 0, &maxmem_mb) != 0 ||
-           maxmem_mb == 0)
+       unsigned long long maxmem;
+       if (str == NULL || (maxmem = memparse(str, NULL)) == 0)
                return -EINVAL;
 
-       maxmem_pfn = (maxmem_mb >> (HPAGE_SHIFT - 20)) <<
-               (HPAGE_SHIFT - PAGE_SHIFT);
+       maxmem_pfn = (maxmem >> HPAGE_SHIFT) << (HPAGE_SHIFT - PAGE_SHIFT);
        pr_info("Forcing RAM used to no more than %dMB\n",
               maxmem_pfn >> (20 - PAGE_SHIFT));
        return 0;
@@ -119,14 +117,15 @@ early_param("maxmem", setup_maxmem);
 static int __init setup_maxnodemem(char *str)
 {
        char *endp;
-       long maxnodemem_mb, node;
+       unsigned long long maxnodemem;
+       long node;
 
        node = str ? simple_strtoul(str, &endp, 0) : INT_MAX;
-       if (node >= MAX_NUMNODES || *endp != ':' ||
-           strict_strtol(endp+1, 0, &maxnodemem_mb) != 0)
+       if (node >= MAX_NUMNODES || *endp != ':')
                return -EINVAL;
 
-       maxnodemem_pfn[node] = (maxnodemem_mb >> (HPAGE_SHIFT - 20)) <<
+       maxnodemem = memparse(endp+1, NULL);
+       maxnodemem_pfn[node] = (maxnodemem >> HPAGE_SHIFT) <<
                (HPAGE_SHIFT - PAGE_SHIFT);
        pr_info("Forcing RAM used on node %ld to no more than %dMB\n",
               node, maxnodemem_pfn[node] >> (20 - PAGE_SHIFT));
@@ -913,6 +912,13 @@ void __cpuinit setup_cpu(int boot)
 
 #ifdef CONFIG_BLK_DEV_INITRD
 
+/*
+ * Note that the kernel can potentially support other compression
+ * techniques than gz, though we don't do so by default.  If we ever
+ * decide to do so we can either look for other filename extensions,
+ * or just allow a file with this name to be compressed with an
+ * arbitrary compressor (somewhat counterintuitively).
+ */
 static int __initdata set_initramfs_file;
 static char __initdata initramfs_file[128] = "initramfs.cpio.gz";
 
@@ -928,9 +934,9 @@ static int __init setup_initramfs_file(char *str)
 early_param("initramfs_file", setup_initramfs_file);
 
 /*
- * We look for an additional "initramfs.cpio.gz" file in the hvfs.
+ * We look for an "initramfs.cpio.gz" file in the hvfs.
  * If there is one, we allocate some memory for it and it will be
- * unpacked to the initramfs after any built-in initramfs_data.
+ * unpacked to the initramfs.
  */
 static void __init load_hv_initrd(void)
 {
@@ -1100,7 +1106,7 @@ EXPORT_SYMBOL(hash_for_home_map);
 
 /*
  * cpu_cacheable_map lists all the cpus whose caches the hypervisor can
- * flush on our behalf.  It is set to cpu_possible_map OR'ed with
+ * flush on our behalf.  It is set to cpu_possible_mask OR'ed with
  * hash_for_home_map, and it is what should be passed to
  * hv_flush_remote() to flush all caches.  Note that if there are
  * dedicated hypervisor driver tiles that have authorized use of their
@@ -1186,7 +1192,7 @@ static void __init setup_cpu_maps(void)
                              sizeof(cpu_lotar_map));
        if (rc < 0) {
                pr_err("warning: no HV_INQ_TILES_LOTAR; using AVAIL\n");
-               cpu_lotar_map = cpu_possible_map;
+               cpu_lotar_map = *cpu_possible_mask;
        }
 
 #if CHIP_HAS_CBOX_HOME_MAP()
@@ -1196,9 +1202,9 @@ static void __init setup_cpu_maps(void)
                              sizeof(hash_for_home_map));
        if (rc < 0)
                early_panic("hv_inquire_tiles(HFH_CACHE) failed: rc %d\n", rc);
-       cpumask_or(&cpu_cacheable_map, &cpu_possible_map, &hash_for_home_map);
+       cpumask_or(&cpu_cacheable_map, cpu_possible_mask, &hash_for_home_map);
 #else
-       cpu_cacheable_map = cpu_possible_map;
+       cpu_cacheable_map = *cpu_possible_mask;
 #endif
 }
 
index bc1eb586e24db24bf924644fe5e68b3424e7a308..89529c9f060535013bfd0505cfa3a13cfd728cd6 100644 (file)
@@ -153,6 +153,25 @@ static tile_bundle_bits rewrite_load_store_unaligned(
        if (((unsigned long)addr % size) == 0)
                return bundle;
 
+       /*
+        * Return SIGBUS with the unaligned address, if requested.
+        * Note that we return SIGBUS even for completely invalid addresses
+        * as long as they are in fact unaligned; this matches what the
+        * tilepro hardware would be doing, if it could provide us with the
+        * actual bad address in an SPR, which it doesn't.
+        */
+       if (unaligned_fixup == 0) {
+               siginfo_t info = {
+                       .si_signo = SIGBUS,
+                       .si_code = BUS_ADRALN,
+                       .si_addr = addr
+               };
+               trace_unhandled_signal("unaligned trap", regs,
+                                      (unsigned long)addr, SIGBUS);
+               force_sig_info(info.si_signo, &info, current);
+               return (tilepro_bundle_bits) 0;
+       }
+
 #ifndef __LITTLE_ENDIAN
 # error We assume little-endian representation with copy_xx_user size 2 here
 #endif
@@ -192,18 +211,6 @@ static tile_bundle_bits rewrite_load_store_unaligned(
                return (tile_bundle_bits) 0;
        }
 
-       if (unaligned_fixup == 0) {
-               siginfo_t info = {
-                       .si_signo = SIGBUS,
-                       .si_code = BUS_ADRALN,
-                       .si_addr = addr
-               };
-               trace_unhandled_signal("unaligned trap", regs,
-                                      (unsigned long)addr, SIGBUS);
-               force_sig_info(info.si_signo, &info, current);
-               return (tile_bundle_bits) 0;
-       }
-
        if (unaligned_printk || unaligned_fixup_count == 0) {
                pr_info("Process %d/%s: PC %#lx: Fixup of"
                        " unaligned %s at %#lx.\n",
@@ -339,12 +346,10 @@ void single_step_once(struct pt_regs *regs)
                }
 
                /* allocate a cache line of writable, executable memory */
-               down_write(&current->mm->mmap_sem);
-               buffer = (void __user *) do_mmap(NULL, 0, 64,
+               buffer = (void __user *) vm_mmap(NULL, 0, 64,
                                          PROT_EXEC | PROT_READ | PROT_WRITE,
                                          MAP_PRIVATE | MAP_ANONYMOUS,
                                          0);
-               up_write(&current->mm->mmap_sem);
 
                if (IS_ERR((void __force *)buffer)) {
                        kfree(state);
index a44e103c5a636670bdbd358f5143419c24d19d7a..91da0f721958da44d91ea08c526228c6c9a015e6 100644 (file)
@@ -103,7 +103,7 @@ static void smp_stop_cpu_interrupt(void)
        set_cpu_online(smp_processor_id(), 0);
        arch_local_irq_disable_all();
        for (;;)
-               asm("nap");
+               asm("nap; nop");
 }
 
 /* This function calls the 'stop' function on all other CPUs in the system. */
@@ -113,6 +113,12 @@ void smp_send_stop(void)
        send_IPI_allbutself(MSG_TAG_STOP_CPU);
 }
 
+/* On panic, just wait; we may get an smp_send_stop() later on. */
+void panic_smp_self_stop(void)
+{
+       while (1)
+               asm("nap; nop");
+}
 
 /*
  * Dispatch code called from hv_message_intr() for HV_MSG_TILE hv messages.
index b949edcec200b60018c7ecf6a9aef049771e0260..172aef7d3159b254e428ccede2a86dca05115716 100644 (file)
@@ -196,6 +196,8 @@ void __cpuinit online_secondary(void)
        /* This must be done before setting cpu_online_mask */
        wmb();
 
+       notify_cpu_starting(smp_processor_id());
+
        /*
         * We need to hold call_lock, so there is no inconsistency
         * between the time smp_call_function() determines number of
index 37ee4d037e0bae6788762e23e28fd3f518f38175..b2f44c28dda6f29c1867c59464462c63ac427e6a 100644 (file)
 #include <linux/stacktrace.h>
 #include <linux/uaccess.h>
 #include <linux/mmzone.h>
+#include <linux/dcache.h>
+#include <linux/fs.h>
 #include <asm/backtrace.h>
 #include <asm/page.h>
-#include <asm/tlbflush.h>
 #include <asm/ucontext.h>
+#include <asm/switch_to.h>
 #include <asm/sigframe.h>
 #include <asm/stack.h>
 #include <arch/abi.h>
@@ -44,72 +46,23 @@ static int in_kernel_stack(struct KBacktraceIterator *kbt, unsigned long sp)
        return sp >= kstack_base && sp < kstack_base + THREAD_SIZE;
 }
 
-/* Is address valid for reading? */
-static int valid_address(struct KBacktraceIterator *kbt, unsigned long address)
-{
-       HV_PTE *l1_pgtable = kbt->pgtable;
-       HV_PTE *l2_pgtable;
-       unsigned long pfn;
-       HV_PTE pte;
-       struct page *page;
-
-       if (l1_pgtable == NULL)
-               return 0;       /* can't read user space in other tasks */
-
-#ifdef CONFIG_64BIT
-       /* Find the real l1_pgtable by looking in the l0_pgtable. */
-       pte = l1_pgtable[HV_L0_INDEX(address)];
-       if (!hv_pte_get_present(pte))
-               return 0;
-       pfn = hv_pte_get_pfn(pte);
-       if (pte_huge(pte)) {
-               if (!pfn_valid(pfn)) {
-                       pr_err("L0 huge page has bad pfn %#lx\n", pfn);
-                       return 0;
-               }
-               return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
-       }
-       page = pfn_to_page(pfn);
-       BUG_ON(PageHighMem(page));  /* No HIGHMEM on 64-bit. */
-       l1_pgtable = (HV_PTE *)pfn_to_kaddr(pfn);
-#endif
-       pte = l1_pgtable[HV_L1_INDEX(address)];
-       if (!hv_pte_get_present(pte))
-               return 0;
-       pfn = hv_pte_get_pfn(pte);
-       if (pte_huge(pte)) {
-               if (!pfn_valid(pfn)) {
-                       pr_err("huge page has bad pfn %#lx\n", pfn);
-                       return 0;
-               }
-               return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
-       }
-
-       page = pfn_to_page(pfn);
-       if (PageHighMem(page)) {
-               pr_err("L2 page table not in LOWMEM (%#llx)\n",
-                      HV_PFN_TO_CPA(pfn));
-               return 0;
-       }
-       l2_pgtable = (HV_PTE *)pfn_to_kaddr(pfn);
-       pte = l2_pgtable[HV_L2_INDEX(address)];
-       return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
-}
-
 /* Callback for backtracer; basically a glorified memcpy */
 static bool read_memory_func(void *result, unsigned long address,
                             unsigned int size, void *vkbt)
 {
        int retval;
        struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt;
+
+       if (address == 0)
+               return 0;
        if (__kernel_text_address(address)) {
                /* OK to read kernel code. */
        } else if (address >= PAGE_OFFSET) {
                /* We only tolerate kernel-space reads of this task's stack */
                if (!in_kernel_stack(kbt, address))
                        return 0;
-       } else if (!valid_address(kbt, address)) {
-               return 0;       /* invalid user-space address */
+       } else if (!kbt->is_current) {
+               return 0;       /* can't read from other user address spaces */
        }
        pagefault_disable();
        retval = __copy_from_user_inatomic(result,
@@ -127,6 +80,8 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
        unsigned long sp = kbt->it.sp;
        struct pt_regs *p;
 
+       if (sp % sizeof(long) != 0)
+               return NULL;
        if (!in_kernel_stack(kbt, sp))
                return NULL;
        if (!in_kernel_stack(kbt, sp + C_ABI_SAVE_AREA_SIZE + PTREGS_SIZE-1))
@@ -169,27 +124,27 @@ static int is_sigreturn(unsigned long pc)
 }
 
 /* Return a pt_regs pointer for a valid signal handler frame */
-static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt)
+static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt,
+                                     struct rt_sigframe* kframe)
 {
        BacktraceIterator *b = &kbt->it;
 
-       if (b->pc == VDSO_BASE) {
-               struct rt_sigframe *frame;
-               unsigned long sigframe_top =
-                       b->sp + sizeof(struct rt_sigframe) - 1;
-               if (!valid_address(kbt, b->sp) ||
-                   !valid_address(kbt, sigframe_top)) {
-                       if (kbt->verbose)
-                               pr_err("  (odd signal: sp %#lx?)\n",
-                                      (unsigned long)(b->sp));
+       if (b->pc == VDSO_BASE && b->sp < PAGE_OFFSET &&
+           b->sp % sizeof(long) == 0) {
+               int retval;
+               pagefault_disable();
+               retval = __copy_from_user_inatomic(
+                       kframe, (void __user __force *)b->sp,
+                       sizeof(*kframe));
+               pagefault_enable();
+               if (retval != 0 ||
+                   (unsigned int)(kframe->info.si_signo) >= _NSIG)
                        return NULL;
-               }
-               frame = (struct rt_sigframe *)b->sp;
                if (kbt->verbose) {
                        pr_err("  <received signal %d>\n",
-                              frame->info.si_signo);
+                              kframe->info.si_signo);
                }
-               return (struct pt_regs *)&frame->uc.uc_mcontext;
+               return (struct pt_regs *)&kframe->uc.uc_mcontext;
        }
        return NULL;
 }
@@ -202,10 +157,11 @@ static int KBacktraceIterator_is_sigreturn(struct KBacktraceIterator *kbt)
 static int KBacktraceIterator_restart(struct KBacktraceIterator *kbt)
 {
        struct pt_regs *p;
+       struct rt_sigframe kframe;
 
        p = valid_fault_handler(kbt);
        if (p == NULL)
-               p = valid_sigframe(kbt);
+               p = valid_sigframe(kbt, &kframe);
        if (p == NULL)
                return 0;
        backtrace_init(&kbt->it, read_memory_func, kbt,
@@ -265,41 +221,19 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
 
        /*
         * Set up callback information.  We grab the kernel stack base
-        * so we will allow reads of that address range, and if we're
-        * asking about the current process we grab the page table
-        * so we can check user accesses before trying to read them.
-        * We flush the TLB to avoid any weird skew issues.
+        * so we will allow reads of that address range.
         */
-       is_current = (t == NULL);
+       is_current = (t == NULL || t == current);
        kbt->is_current = is_current;
        if (is_current)
                t = validate_current();
        kbt->task = t;
-       kbt->pgtable = NULL;
        kbt->verbose = 0;   /* override in caller if desired */
        kbt->profile = 0;   /* override in caller if desired */
        kbt->end = KBT_ONGOING;
-       kbt->new_context = 0;
-       if (is_current) {
-               HV_PhysAddr pgdir_pa = hv_inquire_context().page_table;
-               if (pgdir_pa == (unsigned long)swapper_pg_dir - PAGE_OFFSET) {
-                       /*
-                        * Not just an optimization: this also allows
-                        * this to work at all before va/pa mappings
-                        * are set up.
-                        */
-                       kbt->pgtable = swapper_pg_dir;
-               } else {
-                       struct page *page = pfn_to_page(PFN_DOWN(pgdir_pa));
-                       if (!PageHighMem(page))
-                               kbt->pgtable = __va(pgdir_pa);
-                       else
-                               pr_err("page table not in LOWMEM"
-                                      " (%#llx)\n", pgdir_pa);
-               }
-               local_flush_tlb_all();
+       kbt->new_context = 1;
+       if (is_current)
                validate_stack(regs);
-       }
 
        if (regs == NULL) {
                if (is_current || t->state == TASK_RUNNING) {
@@ -345,6 +279,78 @@ void KBacktraceIterator_next(struct KBacktraceIterator *kbt)
 }
 EXPORT_SYMBOL(KBacktraceIterator_next);
 
+static void describe_addr(struct KBacktraceIterator *kbt,
+                         unsigned long address,
+                         int have_mmap_sem, char *buf, size_t bufsize)
+{
+       struct vm_area_struct *vma;
+       size_t namelen, remaining;
+       unsigned long size, offset, adjust;
+       char *p, *modname;
+       const char *name;
+       int rc;
+
+       /*
+        * Look one byte back for every caller frame (i.e. those that
+        * aren't a new context) so we look up symbol data for the
+        * call itself, not the following instruction, which may be on
+        * a different line (or in a different function).
+        */
+       adjust = !kbt->new_context;
+       address -= adjust;
+
+       if (address >= PAGE_OFFSET) {
+               /* Handle kernel symbols. */
+               BUG_ON(bufsize < KSYM_NAME_LEN);
+               name = kallsyms_lookup(address, &size, &offset,
+                                      &modname, buf);
+               if (name == NULL) {
+                       buf[0] = '\0';
+                       return;
+               }
+               namelen = strlen(buf);
+               remaining = (bufsize - 1) - namelen;
+               p = buf + namelen;
+               rc = snprintf(p, remaining, "+%#lx/%#lx ",
+                             offset + adjust, size);
+               if (modname && rc < remaining)
+                       snprintf(p + rc, remaining - rc, "[%s] ", modname);
+               buf[bufsize-1] = '\0';
+               return;
+       }
+
+       /* If we don't have the mmap_sem, we can't show any more info. */
+       buf[0] = '\0';
+       if (!have_mmap_sem)
+               return;
+
+       /* Find vma info. */
+       vma = find_vma(kbt->task->mm, address);
+       if (vma == NULL || address < vma->vm_start) {
+               snprintf(buf, bufsize, "[unmapped address] ");
+               return;
+       }
+
+       if (vma->vm_file) {
+               char *s;
+               p = d_path(&vma->vm_file->f_path, buf, bufsize);
+               if (IS_ERR(p))
+                       p = "?";
+               s = strrchr(p, '/');
+               if (s)
+                       p = s+1;
+       } else {
+               p = "anon";
+       }
+
+       /* Generate a string description of the vma info. */
+       namelen = strlen(p);
+       remaining = (bufsize - 1) - namelen;
+       memmove(buf, p, namelen);
+       snprintf(buf + namelen, remaining, "[%lx+%lx] ",
+                vma->vm_start, vma->vm_end - vma->vm_start);
+}
+
 /*
  * This method wraps the backtracer's more generic support.
  * It is only invoked from the architecture-specific code; show_stack()
@@ -353,6 +359,7 @@ EXPORT_SYMBOL(KBacktraceIterator_next);
 void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
 {
        int i;
+       int have_mmap_sem = 0;
 
        if (headers) {
                /*
@@ -369,31 +376,16 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
        kbt->verbose = 1;
        i = 0;
        for (; !KBacktraceIterator_end(kbt); KBacktraceIterator_next(kbt)) {
-               char *modname;
-               const char *name;
-               unsigned long address = kbt->it.pc;
-               unsigned long offset, size;
                char namebuf[KSYM_NAME_LEN+100];
+               unsigned long address = kbt->it.pc;
 
-               if (address >= PAGE_OFFSET)
-                       name = kallsyms_lookup(address, &size, &offset,
-                                              &modname, namebuf);
-               else
-                       name = NULL;
-
-               if (!name)
-                       namebuf[0] = '\0';
-               else {
-                       size_t namelen = strlen(namebuf);
-                       size_t remaining = (sizeof(namebuf) - 1) - namelen;
-                       char *p = namebuf + namelen;
-                       int rc = snprintf(p, remaining, "+%#lx/%#lx ",
-                                         offset, size);
-                       if (modname && rc < remaining)
-                               snprintf(p + rc, remaining - rc,
-                                        "[%s] ", modname);
-                       namebuf[sizeof(namebuf)-1] = '\0';
-               }
+               /* Try to acquire the mmap_sem as we pass into userspace. */
+               if (address < PAGE_OFFSET && !have_mmap_sem && kbt->task->mm)
+                       have_mmap_sem =
+                               down_read_trylock(&kbt->task->mm->mmap_sem);
+
+               describe_addr(kbt, address, have_mmap_sem,
+                             namebuf, sizeof(namebuf));
 
                pr_err("  frame %d: 0x%lx %s(sp 0x%lx)\n",
                       i++, address, namebuf, (unsigned long)(kbt->it.sp));
@@ -408,6 +400,8 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
                pr_err("Stack dump stopped; next frame identical to this one\n");
        if (headers)
                pr_err("Stack dump complete\n");
+       if (have_mmap_sem)
+               up_read(&kbt->task->mm->mmap_sem);
 }
 EXPORT_SYMBOL(tile_show_stack);
 
index 2bb6602a1ee711c64146319a39c657de79f5a7b5..73cff814ac57252065ca8086185f2fc7bb87c012 100644 (file)
@@ -200,7 +200,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
 {
        siginfo_t info = { 0 };
        int signo, code;
-       unsigned long address;
+       unsigned long address = 0;
        bundle_bits instr;
 
        /* Re-enable interrupts. */
@@ -223,6 +223,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
        }
 
        switch (fault_num) {
+       case INT_MEM_ERROR:
+               signo = SIGBUS;
+               code = BUS_OBJERR;
+               break;
        case INT_ILL:
                if (copy_from_user(&instr, (void __user *)regs->pc,
                                   sizeof(instr))) {
@@ -289,7 +293,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                address = regs->pc;
                break;
 #ifdef __tilegx__
-       case INT_ILL_TRANS:
+       case INT_ILL_TRANS: {
+               /* Avoid a hardware erratum with the return address stack. */
+               fill_ra_stack();
+
                signo = SIGSEGV;
                code = SEGV_MAPERR;
                if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK)
@@ -297,6 +304,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                else
                        address = 0;  /* FIXME: GX: single-step for address */
                break;
+       }
 #endif
        default:
                panic("Unexpected do_trap interrupt number %d", fault_num);
@@ -308,7 +316,8 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
        info.si_addr = (void __user *)address;
        if (signo == SIGILL)
                info.si_trapno = fault_num;
-       trace_unhandled_signal("trap", regs, address, signo);
+       if (signo != SIGTRAP)
+               trace_unhandled_signal("trap", regs, address, signo);
        force_sig_info(signo, &info, current);
 }
 
index 0c26086ecbef01523c440b3636f8bf049bdfc8f0..985f59858234d98cf7a29df45d91edc0e6deb973 100644 (file)
@@ -7,6 +7,7 @@ lib-y = cacheflush.o checksum.o cpumask.o delay.o uaccess.o \
        strchr_$(BITS).o strlen_$(BITS).o
 
 ifeq ($(CONFIG_TILEGX),y)
+CFLAGS_REMOVE_memcpy_user_64.o = -fno-omit-frame-pointer
 lib-y += memcpy_user_64.o
 else
 lib-y += atomic_32.o atomic_asm_32.o memcpy_tile64.o
index 8928aace7a641d8a2b7be866f88deefb4f5f9a1e..db4fb89e12d89a4461b8cc19c99885469fcaf22c 100644 (file)
@@ -39,7 +39,21 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)
 {
        char *p, *base;
        size_t step_size, load_count;
+
+       /*
+        * On TILEPro the striping granularity is a fixed 8KB; on
+        * TILE-Gx it is configurable, and we rely on the fact that
+        * the hypervisor always configures maximum striping, so that
+        * bits 9 and 10 of the PA are part of the stripe function, so
+        * every 512 bytes we hit a striping boundary.
+        *
+        */
+#ifdef __tilegx__
+       const unsigned long STRIPE_WIDTH = 512;
+#else
        const unsigned long STRIPE_WIDTH = 8192;
+#endif
+
 #ifdef __tilegx__
        /*
         * On TILE-Gx, we must disable the dstream prefetcher before doing
@@ -74,7 +88,7 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)
         * memory, that one load would be sufficient, but since we may
         * be, we also need to back up to the last load issued to
         * another memory controller, which would be the point where
-        * we crossed an 8KB boundary (the granularity of striping
+        * we crossed a "striping" boundary (the granularity of striping
         * across memory controllers).  Keep backing up and doing this
         * until we are before the beginning of the buffer, or have
         * hit all the controllers.
@@ -88,12 +102,22 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)
         * every cache line on a full memory stripe on each
         * controller" that we simply do that, to simplify the logic.
         *
-        * FIXME: See bug 9535 for some issues with this code.
+        * On TILE-Gx the hash-for-home function is much more complex,
+        * with the upshot being we can't readily guarantee we have
+        * hit both entries in the 128-entry AMT that were hit by any
+        * load in the entire range, so we just re-load them all.
+        * With larger buffers, we may want to consider using a hypervisor
+        * trap to issue loads directly to each hash-for-home tile for
+        * each controller (doing it from Linux would trash the TLB).
         */
        if (hfh) {
                step_size = L2_CACHE_BYTES;
+#ifdef __tilegx__
+               load_count = (size + L2_CACHE_BYTES - 1) / L2_CACHE_BYTES;
+#else
                load_count = (STRIPE_WIDTH / L2_CACHE_BYTES) *
                              (1 << CHIP_LOG_NUM_MSHIMS());
+#endif
        } else {
                step_size = STRIPE_WIDTH;
                load_count = (1 << CHIP_LOG_NUM_MSHIMS());
@@ -109,7 +133,7 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)
 
        /* Figure out how far back we need to go. */
        base = p - (step_size * (load_count - 2));
-       if ((long)base < (long)buffer)
+       if ((unsigned long)base < (unsigned long)buffer)
                base = buffer;
 
        /*
index 4763b3aff1cc7695f340aae288e913a79a02f6ea..37440caa7370fe3d4c052086c6143bb6ab8e583c 100644 (file)
  * Do memcpy(), but trap and return "n" when a load or store faults.
  *
  * Note: this idiom only works when memcpy() compiles to a leaf function.
- * If "sp" is updated during memcpy, the "jrp lr" will be incorrect.
+ * Here leaf function not only means it does not have calls, but also
+ * requires no stack operations (sp, stack frame pointer) and no
+ * use of callee-saved registers, else "jrp lr" will be incorrect since
+ * unwinding stack frame is bypassed. Since memcpy() is not complex so
+ * these conditions are satisfied here, but we need to be careful when
+ * modifying this file. This is not a clean solution but is the best
+ * one so far.
  *
  * Also note that we are capturing "n" from the containing scope here.
  */
index c101098091327e5b52a104d2b2d4769212f80043..6ac37509faca56ab614eae690123bf9be9be9313 100644 (file)
@@ -60,5 +60,5 @@ static void delay_backoff(int iterations)
        loops += __insn_crc32_32(stack_pointer, get_cycles_low()) &
                (loops - 1);
 
-       relax(1 << exponent);
+       relax(loops);
 }
index cba30e9547b41682c8cfca0f3577637f1ff8cbbf..22e58f51ed23eedd405e9dc0b719eddb9550f502 100644 (file)
@@ -130,7 +130,7 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
 }
 
 /*
- * Handle a fault on the vmalloc or module mapping area
+ * Handle a fault on the vmalloc area.
  */
 static inline int vmalloc_fault(pgd_t *pgd, unsigned long address)
 {
@@ -203,9 +203,14 @@ static pgd_t *get_current_pgd(void)
  * interrupt or a critical region, and must do as little as possible.
  * Similarly, we can't use atomic ops here, since we may be handling a
  * fault caused by an atomic op access.
+ *
+ * If we find a migrating PTE while we're in an NMI context, and we're
+ * at a PC that has a registered exception handler, we don't wait,
+ * since this thread may (e.g.) have been interrupted while migrating
+ * its own stack, which would then cause us to self-deadlock.
  */
 static int handle_migrating_pte(pgd_t *pgd, int fault_num,
-                               unsigned long address,
+                               unsigned long address, unsigned long pc,
                                int is_kernel_mode, int write)
 {
        pud_t *pud;
@@ -227,6 +232,8 @@ static int handle_migrating_pte(pgd_t *pgd, int fault_num,
                pte_offset_kernel(pmd, address);
        pteval = *pte;
        if (pte_migrating(pteval)) {
+               if (in_nmi() && search_exception_tables(pc))
+                       return 0;
                wait_for_migration(pte);
                return 1;
        }
@@ -300,7 +307,7 @@ static int handle_page_fault(struct pt_regs *regs,
         * rather than trying to patch up the existing PTE.
         */
        pgd = get_current_pgd();
-       if (handle_migrating_pte(pgd, fault_num, address,
+       if (handle_migrating_pte(pgd, fault_num, address, regs->pc,
                                 is_kernel_mode, write))
                return 1;
 
@@ -335,9 +342,12 @@ static int handle_page_fault(struct pt_regs *regs,
        /*
         * If we're trying to touch user-space addresses, we must
         * be either at PL0, or else with interrupts enabled in the
-        * kernel, so either way we can re-enable interrupts here.
+        * kernel, so either way we can re-enable interrupts here
+        * unless we are doing atomic access to user space with
+        * interrupts disabled.
         */
-       local_irq_enable();
+       if (!(regs->flags & PT_FLAGS_DISABLE_IRQ))
+               local_irq_enable();
 
        mm = tsk->mm;
 
@@ -665,7 +675,7 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num,
         */
        if (fault_num == INT_DTLB_ACCESS)
                write = 1;
-       if (handle_migrating_pte(pgd, fault_num, address, 1, write))
+       if (handle_migrating_pte(pgd, fault_num, address, pc, 1, write))
                return state;
 
        /* Return zero so that we continue on with normal fault handling. */
index 1cc6ae477c98b59711c29deb5674e50c63c96be3..499f73770b05d09e1616e1d9a2293a20c7ae1bac 100644 (file)
@@ -394,6 +394,7 @@ int page_home(struct page *page)
                return pte_to_home(*virt_to_pte(NULL, kva));
        }
 }
+EXPORT_SYMBOL(page_home);
 
 void homecache_change_page_home(struct page *page, int order, int home)
 {
index 830c4908ea76cf4c7156777db8a8cced9fb887f9..6a9d20ddc34f416438a7d9717cf75919ea7fa34b 100644 (file)
@@ -254,11 +254,6 @@ static pgprot_t __init init_pgprot(ulong address)
                return construct_pgprot(PAGE_KERNEL_RO, PAGE_HOME_IMMUTABLE);
        }
 
-       /* As a performance optimization, keep the boot init stack here. */
-       if (address >= (ulong)&init_thread_union &&
-           address < (ulong)&init_thread_union + THREAD_SIZE)
-               return construct_pgprot(PAGE_KERNEL, smp_processor_id());
-
 #ifndef __tilegx__
 #if !ATOMIC_LOCKS_FOUND_VIA_TABLE()
        /* Force the atomic_locks[] array page to be hash-for-home. */
@@ -557,6 +552,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
 
        address = MEM_SV_INTRPT;
        pmd = get_pmd(pgtables, address);
+       pfn = 0;  /* code starts at PA 0 */
        if (ktext_small) {
                /* Allocate an L2 PTE for the kernel text */
                int cpu = 0;
@@ -579,10 +575,15 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
                }
 
                BUG_ON(address != (unsigned long)_stext);
-               pfn = 0;  /* code starts at PA 0 */
-               pte = alloc_pte();
-               for (pte_ofs = 0; address < (unsigned long)_einittext;
-                    pfn++, pte_ofs++, address += PAGE_SIZE) {
+               pte = NULL;
+               for (; address < (unsigned long)_einittext;
+                    pfn++, address += PAGE_SIZE) {
+                       pte_ofs = pte_index(address);
+                       if (pte_ofs == 0) {
+                               if (pte)
+                                       assign_pte(pmd++, pte);
+                               pte = alloc_pte();
+                       }
                        if (!ktext_local) {
                                prot = set_remote_cache_cpu(prot, cpu);
                                cpu = cpumask_next(cpu, &ktext_mask);
@@ -591,7 +592,8 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
                        }
                        pte[pte_ofs] = pfn_pte(pfn, prot);
                }
-               assign_pte(pmd, pte);
+               if (pte)
+                       assign_pte(pmd, pte);
        } else {
                pte_t pteval = pfn_pte(0, PAGE_KERNEL_EXEC);
                pteval = pte_mkhuge(pteval);
@@ -614,7 +616,9 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
                else
                        pteval = hv_pte_set_mode(pteval,
                                                 HV_PTE_MODE_CACHE_NO_L3);
-               *(pte_t *)pmd = pteval;
+               for (; address < (unsigned long)_einittext;
+                    pfn += PFN_DOWN(HPAGE_SIZE), address += HPAGE_SIZE)
+                       *(pte_t *)(pmd++) = pfn_pte(pfn, pteval);
        }
 
        /* Set swapper_pgprot here so it is flushed to memory right away. */
index 87303693a0727faa96d844d58dc9115a4dd85b10..2410aa899b3e7c9c17079d2bf78d2d4eaf1eb8b1 100644 (file)
@@ -177,14 +177,10 @@ void shatter_huge_page(unsigned long addr)
        if (!pmd_huge_page(*pmd))
                return;
 
-       /*
-        * Grab the pgd_lock, since we may need it to walk the pgd_list,
-        * and since we need some kind of lock here to avoid races.
-        */
-       spin_lock_irqsave(&pgd_lock, flags);
+       spin_lock_irqsave(&init_mm.page_table_lock, flags);
        if (!pmd_huge_page(*pmd)) {
                /* Lost the race to convert the huge page. */
-               spin_unlock_irqrestore(&pgd_lock, flags);
+               spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
                return;
        }
 
@@ -194,6 +190,7 @@ void shatter_huge_page(unsigned long addr)
 
 #ifdef __PAGETABLE_PMD_FOLDED
        /* Walk every pgd on the system and update the pmd there. */
+       spin_lock(&pgd_lock);
        list_for_each(pos, &pgd_list) {
                pmd_t *copy_pmd;
                pgd = list_to_pgd(pos) + pgd_index(addr);
@@ -201,6 +198,7 @@ void shatter_huge_page(unsigned long addr)
                copy_pmd = pmd_offset(pud, addr);
                __set_pmd(copy_pmd, *pmd);
        }
+       spin_unlock(&pgd_lock);
 #endif
 
        /* Tell every cpu to notice the change. */
@@ -208,7 +206,7 @@ void shatter_huge_page(unsigned long addr)
                     cpu_possible_mask, NULL, 0);
 
        /* Hold the lock until the TLB flush is finished to avoid races. */
-       spin_unlock_irqrestore(&pgd_lock, flags);
+       spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
 }
 
 /*
@@ -217,9 +215,13 @@ void shatter_huge_page(unsigned long addr)
  * against pageattr.c; it is the unique case in which a valid change
  * of kernel pagetables can't be lazily synchronized by vmalloc faults.
  * vmalloc faults work because attached pagetables are never freed.
- * The locking scheme was chosen on the basis of manfred's
- * recommendations and having no core impact whatsoever.
- * -- wli
+ *
+ * The lock is always taken with interrupts disabled, unlike on x86
+ * and other platforms, because we need to take the lock in
+ * shatter_huge_page(), which may be called from an interrupt context.
+ * We are not at risk from the tlbflush IPI deadlock that was seen on
+ * x86, since we use the flush_remote() API to have the hypervisor do
+ * the TLB flushes regardless of irq disabling.
  */
 DEFINE_SPINLOCK(pgd_lock);
 LIST_HEAD(pgd_list);
@@ -469,10 +471,18 @@ void __set_pte(pte_t *ptep, pte_t pte)
 
 void set_pte(pte_t *ptep, pte_t pte)
 {
-       struct page *page = pfn_to_page(pte_pfn(pte));
-
-       /* Update the home of a PTE if necessary */
-       pte = pte_set_home(pte, page_home(page));
+       if (pte_present(pte) &&
+           (!CHIP_HAS_MMIO() || hv_pte_get_mode(pte) != HV_PTE_MODE_MMIO)) {
+               /* The PTE actually references physical memory. */
+               unsigned long pfn = pte_pfn(pte);
+               if (pfn_valid(pfn)) {
+                       /* Update the home of the PTE from the struct page. */
+                       pte = pte_set_home(pte, page_home(pfn_to_page(pfn)));
+               } else if (hv_pte_get_mode(pte) == 0) {
+                       /* remap_pfn_range(), etc, must supply PTE mode. */
+                       panic("set_pte(): out-of-range PFN and mode 0\n");
+               }
+       }
 
        __set_pte(ptep, pte);
 }
index dc36b222100b9abde780f996407a758f336afce4..6673508f342603554c4fbe874511ab6df14af45f 100644 (file)
@@ -3,41 +3,6 @@
 
 #include <asm/types.h>
 
-#if defined(__KERNEL__)
-
-# include <asm/byteorder.h>
-
-# if defined(__BIG_ENDIAN)
-#      define ntohll(x) (x)
-#      define htonll(x) (x)
-# elif defined(__LITTLE_ENDIAN)
-#      define ntohll(x)  be64_to_cpu(x)
-#      define htonll(x)  cpu_to_be64(x)
-# else
-#      error "Could not determine byte order"
-# endif
-
-#else
-/* For the definition of ntohl, htonl and __BYTE_ORDER */
-#include <endian.h>
-#include <netinet/in.h>
-#if defined(__BYTE_ORDER)
-
-#  if __BYTE_ORDER == __BIG_ENDIAN
-#      define ntohll(x) (x)
-#      define htonll(x) (x)
-#  elif __BYTE_ORDER == __LITTLE_ENDIAN
-#      define ntohll(x)  bswap_64(x)
-#      define htonll(x)  bswap_64(x)
-#  else
-#      error "Could not determine byte order: __BYTE_ORDER uncorrectly defined"
-#  endif
-
-#else  /* ! defined(__BYTE_ORDER) */
-#      error "Could not determine byte order: __BYTE_ORDER not defined"
-#endif
-#endif /* ! defined(__KERNEL__) */
-
 extern int init_cow_file(int fd, char *cow_file, char *backing_file,
                         int sectorsize, int alignment, int *bitmap_offset_out,
                         unsigned long *bitmap_len_out, int *data_offset_out);
index 9cbb426c0b9183e8a5c65afe47483f47e00da0ec..0ee9cc6cc4c79dfb4d78fd8fa15072294c62568f 100644 (file)
@@ -8,11 +8,10 @@
  * that.
  */
 #include <unistd.h>
-#include <byteswap.h>
 #include <errno.h>
 #include <string.h>
 #include <arpa/inet.h>
-#include <asm/types.h>
+#include <endian.h>
 #include "cow.h"
 #include "cow_sys.h"
 
@@ -214,8 +213,8 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
                           "header\n");
                goto out;
        }
-       header->magic = htonl(COW_MAGIC);
-       header->version = htonl(COW_VERSION);
+       header->magic = htobe32(COW_MAGIC);
+       header->version = htobe32(COW_VERSION);
 
        err = -EINVAL;
        if (strlen(backing_file) > sizeof(header->backing_file) - 1) {
@@ -246,10 +245,10 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
                goto out_free;
        }
 
-       header->mtime = htonl(modtime);
-       header->size = htonll(*size);
-       header->sectorsize = htonl(sectorsize);
-       header->alignment = htonl(alignment);
+       header->mtime = htobe32(modtime);
+       header->size = htobe64(*size);
+       header->sectorsize = htobe32(sectorsize);
+       header->alignment = htobe32(alignment);
        header->cow_format = COW_BITMAP;
 
        err = cow_write_file(fd, header, sizeof(*header));
@@ -301,8 +300,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
        magic = header->v1.magic;
        if (magic == COW_MAGIC)
                version = header->v1.version;
-       else if (magic == ntohl(COW_MAGIC))
-               version = ntohl(header->v1.version);
+       else if (magic == be32toh(COW_MAGIC))
+               version = be32toh(header->v1.version);
        /* No error printed because the non-COW case comes through here */
        else goto out;
 
@@ -327,9 +326,9 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
                                   "header\n");
                        goto out;
                }
-               *mtime_out = ntohl(header->v2.mtime);
-               *size_out = ntohll(header->v2.size);
-               *sectorsize_out = ntohl(header->v2.sectorsize);
+               *mtime_out = be32toh(header->v2.mtime);
+               *size_out = be64toh(header->v2.size);
+               *sectorsize_out = be32toh(header->v2.sectorsize);
                *bitmap_offset_out = sizeof(header->v2);
                *align_out = *sectorsize_out;
                file = header->v2.backing_file;
@@ -341,10 +340,10 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
                                   "header\n");
                        goto out;
                }
-               *mtime_out = ntohl(header->v3.mtime);
-               *size_out = ntohll(header->v3.size);
-               *sectorsize_out = ntohl(header->v3.sectorsize);
-               *align_out = ntohl(header->v3.alignment);
+               *mtime_out = be32toh(header->v3.mtime);
+               *size_out = be64toh(header->v3.size);
+               *sectorsize_out = be32toh(header->v3.sectorsize);
+               *align_out = be32toh(header->v3.alignment);
                if (*align_out == 0) {
                        cow_printf("read_cow_header - invalid COW header, "
                                   "align == 0\n");
@@ -366,16 +365,16 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
                 * this was used until Dec2005 - 64bits are needed to represent
                 * 2038+. I.e. we can safely do this truncating cast.
                 *
-                * Additionally, we must use ntohl() instead of ntohll(), since
+                * Additionally, we must use be32toh() instead of be64toh(), since
                 * the program used to use the former (tested - I got mtime
                 * mismatch "0 vs whatever").
                 *
                 * Ever heard about bug-to-bug-compatibility ? ;-) */
-               *mtime_out = (time32_t) ntohl(header->v3_b.mtime);
+               *mtime_out = (time32_t) be32toh(header->v3_b.mtime);
 
-               *size_out = ntohll(header->v3_b.size);
-               *sectorsize_out = ntohl(header->v3_b.sectorsize);
-               *align_out = ntohl(header->v3_b.alignment);
+               *size_out = be64toh(header->v3_b.size);
+               *sectorsize_out = be32toh(header->v3_b.sectorsize);
+               *align_out = be32toh(header->v3_b.alignment);
                if (*align_out == 0) {
                        cow_printf("read_cow_header - invalid COW header, "
                                   "align == 0\n");
index e672bd6d43e3b2aa72b4c1c51029db9510233f52..43b39d61b538698229a23f654b7fb44a335187b3 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
+#include <asm/switch_to.h>
 
 #include "init.h"
 #include "irq_kern.h"
index 8419f5cf2ac7e3586c68677198b2b28321b95221..fff24352255df0b0b448c43f11e287d5011fb836 100644 (file)
@@ -1,3 +1,4 @@
 generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
 generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
-generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h
+generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h exec.h
+generic-y += switch_to.h
index 492bc4c1b62bf3516a996d81c24c05c494fcf8d5..65a1c3d690ea01c8af4e2d7ea2c74d95ab415ec2 100644 (file)
@@ -3,9 +3,10 @@
 # Licensed under the GPL
 #
 
-CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \
-                        -DELF_ARCH=$(LDS_ELF_ARCH)        \
-                        -DELF_FORMAT=$(LDS_ELF_FORMAT)
+CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START)           \
+                        -DELF_ARCH=$(LDS_ELF_ARCH)     \
+                        -DELF_FORMAT=$(LDS_ELF_FORMAT) \
+                       $(LDS_EXTRA)
 extra-y := vmlinux.lds
 clean-files :=
 
index f386d04a84a526df7a51a13cbc6c1636543071fe..2b73dedb44cacdda741b3e5774346c93b37b1b22 100644 (file)
@@ -88,11 +88,8 @@ static inline void set_current(struct task_struct *task)
 
 extern void arch_switch_to(struct task_struct *to);
 
-void *_switch_to(void *prev, void *next, void *last)
+void *__switch_to(struct task_struct *from, struct task_struct *to)
 {
-       struct task_struct *from = prev;
-       struct task_struct *to = next;
-
        to->thread.prev_sched = from;
        set_current(to);
 
@@ -111,7 +108,6 @@ void *_switch_to(void *prev, void *next, void *last)
        } while (current->thread.saved_task);
 
        return current->thread.prev_sched;
-
 }
 
 void interrupt_end(void)
index 4947b319f53ad7d1359631bf3ae09e0e38731b12..0a49ef0c2bf48995cb063ea425a10b91d11c8c96 100644 (file)
@@ -103,7 +103,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
 
 void uml_setup_stubs(struct mm_struct *mm)
 {
-       struct page **pages;
        int err, ret;
 
        if (!skas_needs_stub)
index 2e9852c0d487449911fc289e3520a90e6306f9b9..0a9e57e7446b277ed8cdcfdda3e29c17cc257f57 100644 (file)
@@ -41,7 +41,7 @@ static int __init start_kernel_proc(void *unused)
        cpu_tasks[0].pid = pid;
        cpu_tasks[0].task = current;
 #ifdef CONFIG_SMP
-       cpu_online_map = cpumask_of_cpu(0);
+       init_cpu_online(get_cpu_mask(0));
 #endif
        start_kernel();
        return 0;
index 155206a6690879da2e6521c7604d74ad8f9e52a0..6f588e160fb0ec1bf4e035b282d8dd10f300e8f8 100644 (file)
@@ -76,7 +76,7 @@ static int idle_proc(void *cpup)
                cpu_relax();
 
        notify_cpu_starting(cpu);
-       cpu_set(cpu, cpu_online_map);
+       set_cpu_online(cpu, true);
        default_idle();
        return 0;
 }
@@ -110,8 +110,7 @@ void smp_prepare_cpus(unsigned int maxcpus)
        for (i = 0; i < ncpus; ++i)
                set_cpu_possible(i, true);
 
-       cpu_clear(me, cpu_online_map);
-       cpu_set(me, cpu_online_map);
+       set_cpu_online(me, true);
        cpu_set(me, cpu_callin_map);
 
        err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
@@ -138,13 +137,13 @@ void smp_prepare_cpus(unsigned int maxcpus)
 
 void smp_prepare_boot_cpu(void)
 {
-       cpu_set(smp_processor_id(), cpu_online_map);
+       set_cpu_online(smp_processor_id(), true);
 }
 
 int __cpu_up(unsigned int cpu)
 {
        cpu_set(cpu, smp_commenced_mask);
-       while (!cpu_isset(cpu, cpu_online_map))
+       while (!cpu_online(cpu))
                mb();
        return 0;
 }
index 9258e592f414ff1fd08ff563ee8205959b68ecc0..366460a817965d2ed7d1d4dceb987784067e87e6 100644 (file)
@@ -82,20 +82,26 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
        return 0;
 }
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
 {
        struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
-       return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
+       return dma_ops->alloc(dev, size, dma_handle, flag, attrs);
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
-       dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+       dma_ops->free(dev, size, cpu_addr, dma_handle, attrs);
 }
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
index bfa9fbb2bbb1146c882b4cfac7da02b7b874007c..16c08b2143a77098a8501d47b4daf963624b282b 100644 (file)
 
 #include <asm/dma.h>
 
+static void *unicore_swiotlb_alloc_coherent(struct device *dev, size_t size,
+                                           dma_addr_t *dma_handle, gfp_t flags,
+                                           struct dma_attrs *attrs)
+{
+       return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
+}
+
+static void unicore_swiotlb_free_coherent(struct device *dev, size_t size,
+                                         void *vaddr, dma_addr_t dma_addr,
+                                         struct dma_attrs *attrs)
+{
+       swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+}
+
 struct dma_map_ops swiotlb_dma_map_ops = {
-       .alloc_coherent = swiotlb_alloc_coherent,
-       .free_coherent = swiotlb_free_coherent,
+       .alloc = unicore_swiotlb_alloc_coherent,
+       .free = unicore_swiotlb_free_coherent,
        .map_sg = swiotlb_map_sg_attrs,
        .unmap_sg = swiotlb_unmap_sg_attrs,
        .dma_supported = swiotlb_dma_supported,
index 1d14cc6b79ad399d1ad293030c9f2271d9e5df1d..c9866b0b77d81d678e97ebbacd48ed5d5e659a77 100644 (file)
@@ -81,7 +81,7 @@ config X86
        select CLKEVT_I8253
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_IOMAP
-       select DCACHE_WORD_ACCESS if !DEBUG_PAGEALLOC
+       select DCACHE_WORD_ACCESS
 
 config INSTRUCTION_DECODER
        def_bool (KPROBES || PERF_EVENTS)
index 968dbe24a255453bb3bb3768cd76f2f72b424bcc..41a7237606a3b3a26393b0c7844166d728a9ed0a 100644 (file)
@@ -129,6 +129,7 @@ KBUILD_CFLAGS += -Wno-sign-compare
 KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
 # prevent gcc from generating any FP code by mistake
 KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
 
 KBUILD_CFLAGS += $(mflags-y)
 KBUILD_AFLAGS += $(mflags-y)
index 4be406abeefde51f1f3dd9419a799256ae1c1e1d..36b62bc52638368c750c250a529995cd8cac80cb 100644 (file)
@@ -14,6 +14,9 @@ LINK-y                        += $(call cc-option,-m32)
 
 export LDFLAGS
 
+LDS_EXTRA              := -Ui386
+export LDS_EXTRA
+
 # First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
 include $(srctree)/arch/x86/Makefile_32.cpu
 
index a0559930a180ecb810df4b186d173d6fb11e3755..c85e3ac99bbabc597d772cb85b4efd4d4b3bc291 100644 (file)
@@ -33,6 +33,9 @@
        __HEAD
 ENTRY(startup_32)
 #ifdef CONFIG_EFI_STUB
+       jmp     preferred_addr
+
+       .balign 0x10
        /*
         * We don't need the return address, so set up the stack so
         * efi_main() can find its arugments.
@@ -41,12 +44,17 @@ ENTRY(startup_32)
 
        call    efi_main
        cmpl    $0, %eax
-       je      preferred_addr
        movl    %eax, %esi
-       call    1f
+       jne     2f
 1:
+       /* EFI init failed, so hang. */
+       hlt
+       jmp     1b
+2:
+       call    3f
+3:
        popl    %eax
-       subl    $1b, %eax
+       subl    $3b, %eax
        subl    BP_pref_address(%esi), %eax
        add     BP_code32_start(%esi), %eax
        leal    preferred_addr(%eax), %eax
index 558d76ce23bcf3518a4c9b32bced0ef717be000e..87e03a13d8e3f5d9eaad2d515679d97887833ea2 100644 (file)
@@ -200,18 +200,28 @@ ENTRY(startup_64)
         * entire text+data+bss and hopefully all of memory.
         */
 #ifdef CONFIG_EFI_STUB
-       pushq   %rsi
+       /*
+        * The entry point for the PE/COFF executable is 0x210, so only
+        * legacy boot loaders will execute this jmp.
+        */
+       jmp     preferred_addr
+
+       .org 0x210
        mov     %rcx, %rdi
        mov     %rdx, %rsi
        call    efi_main
-       popq    %rsi
-       cmpq    $0,%rax
-       je      preferred_addr
        movq    %rax,%rsi
-       call    1f
+       cmpq    $0,%rax
+       jne     2f
 1:
+       /* EFI init failed, so hang. */
+       hlt
+       jmp     1b
+2:
+       call    3f
+3:
        popq    %rax
-       subq    $1b, %rax
+       subq    $3b, %rax
        subq    BP_pref_address(%rsi), %rax
        add     BP_code32_start(%esi), %eax
        leaq    preferred_addr(%rax), %rax
index d3c0b027766656c69dfc82404b74de3849eaadaa..fb7117a4ade1e259c69d45b47d4ffc3b62196540 100644 (file)
@@ -403,13 +403,11 @@ static void print_absolute_symbols(void)
        for (i = 0; i < ehdr.e_shnum; i++) {
                struct section *sec = &secs[i];
                char *sym_strtab;
-               Elf32_Sym *sh_symtab;
                int j;
 
                if (sec->shdr.sh_type != SHT_SYMTAB) {
                        continue;
                }
-               sh_symtab = sec->symtab;
                sym_strtab = sec->link->strtab;
                for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
                        Elf32_Sym *sym;
index ed549767a231eece626dd19cd64746cb2569b6f5..24443a3320838ede8cdf995525851794e8d1052a 100644 (file)
@@ -205,8 +205,13 @@ int main(int argc, char ** argv)
        put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
 
 #ifdef CONFIG_X86_32
-       /* Address of entry point */
-       put_unaligned_le32(i, &buf[pe_header + 0x28]);
+       /*
+        * Address of entry point.
+        *
+        * The EFI stub entry point is +16 bytes from the start of
+        * the .text section.
+        */
+       put_unaligned_le32(i + 16, &buf[pe_header + 0x28]);
 
        /* .text size */
        put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]);
@@ -217,9 +222,11 @@ int main(int argc, char ** argv)
        /*
         * Address of entry point. startup_32 is at the beginning and
         * the 64-bit entry point (startup_64) is always 512 bytes
-        * after.
+        * after. The EFI stub entry point is 16 bytes after that, as
+        * the first instruction allows legacy loaders to jump over
+        * the EFI stub initialisation
         */
-       put_unaligned_le32(i + 512, &buf[pe_header + 0x28]);
+       put_unaligned_le32(i + 528, &buf[pe_header + 0x28]);
 
        /* .text size */
        put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]);
index d511d951a0527103e05abca9c1cf73b4b024b7c1..07b3a68d2d291ab4c8582a1cc5121c6443e208bb 100644 (file)
@@ -119,9 +119,7 @@ static void set_brk(unsigned long start, unsigned long end)
        end = PAGE_ALIGN(end);
        if (end <= start)
                return;
-       down_write(&current->mm->mmap_sem);
-       do_brk(start, end - start);
-       up_write(&current->mm->mmap_sem);
+       vm_brk(start, end - start);
 }
 
 #ifdef CORE_DUMP
@@ -296,8 +294,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 
        /* OK, This is the point of no return */
        set_personality(PER_LINUX);
-       set_thread_flag(TIF_IA32);
-       current->mm->context.ia32_compat = 1;
+       set_personality_ia32(false);
 
        setup_new_exec(bprm);
 
@@ -332,9 +329,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                pos = 32;
                map_size = ex.a_text+ex.a_data;
 
-               down_write(&current->mm->mmap_sem);
-               error = do_brk(text_addr & PAGE_MASK, map_size);
-               up_write(&current->mm->mmap_sem);
+               error = vm_brk(text_addr & PAGE_MASK, map_size);
 
                if (error != (text_addr & PAGE_MASK)) {
                        send_sig(SIGKILL, current, 0);
@@ -373,9 +368,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
                        loff_t pos = fd_offset;
 
-                       down_write(&current->mm->mmap_sem);
-                       do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
-                       up_write(&current->mm->mmap_sem);
+                       vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
                        bprm->file->f_op->read(bprm->file,
                                        (char __user *)N_TXTADDR(ex),
                                        ex.a_text+ex.a_data, &pos);
@@ -385,26 +378,22 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                        goto beyond_if;
                }
 
-               down_write(&current->mm->mmap_sem);
-               error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
+               error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
                                PROT_READ | PROT_EXEC,
                                MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
                                MAP_EXECUTABLE | MAP_32BIT,
                                fd_offset);
-               up_write(&current->mm->mmap_sem);
 
                if (error != N_TXTADDR(ex)) {
                        send_sig(SIGKILL, current, 0);
                        return error;
                }
 
-               down_write(&current->mm->mmap_sem);
-               error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
+               error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
                                PROT_READ | PROT_WRITE | PROT_EXEC,
                                MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
                                MAP_EXECUTABLE | MAP_32BIT,
                                fd_offset + ex.a_text);
-               up_write(&current->mm->mmap_sem);
                if (error != N_DATADDR(ex)) {
                        send_sig(SIGKILL, current, 0);
                        return error;
@@ -476,9 +465,7 @@ static int load_aout_library(struct file *file)
                        error_time = jiffies;
                }
 #endif
-               down_write(&current->mm->mmap_sem);
-               do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
-               up_write(&current->mm->mmap_sem);
+               vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
 
                file->f_op->read(file, (char __user *)start_addr,
                        ex.a_text + ex.a_data, &pos);
@@ -490,12 +477,10 @@ static int load_aout_library(struct file *file)
                goto out;
        }
        /* Now use mmap to map the library into memory. */
-       down_write(&current->mm->mmap_sem);
-       error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+       error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
                        PROT_READ | PROT_WRITE | PROT_EXEC,
                        MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
                        N_TXTOFF(ex));
-       up_write(&current->mm->mmap_sem);
        retval = error;
        if (error != start_addr)
                goto out;
@@ -503,9 +488,7 @@ static int load_aout_library(struct file *file)
        len = PAGE_ALIGN(ex.a_text + ex.a_data);
        bss = ex.a_text + ex.a_data + ex.a_bss;
        if (bss > len) {
-               down_write(&current->mm->mmap_sem);
-               error = do_brk(start_addr + len, bss - len);
-               up_write(&current->mm->mmap_sem);
+               error = vm_brk(start_addr + len, bss - len);
                retval = error;
                if (error != start_addr + len)
                        goto out;
index b3b7332629096849d11866c017c4444f8d156f9e..99480e55973d975a6082bf53c6f209591ec3d56c 100644 (file)
@@ -43,7 +43,7 @@ extern void __add_wrong_size(void)
                switch (sizeof(*(ptr))) {                               \
                case __X86_CASE_B:                                      \
                        asm volatile (lock #op "b %b0, %1\n"            \
-                                     : "+r" (__ret), "+m" (*(ptr))     \
+                                     : "+q" (__ret), "+m" (*(ptr))     \
                                      : : "memory", "cc");              \
                        break;                                          \
                case __X86_CASE_W:                                      \
@@ -173,7 +173,7 @@ extern void __add_wrong_size(void)
                switch (sizeof(*(ptr))) {                               \
                case __X86_CASE_B:                                      \
                        asm volatile (lock "addb %b1, %0\n"             \
-                                     : "+m" (*(ptr)) : "ri" (inc)      \
+                                     : "+m" (*(ptr)) : "qi" (inc)      \
                                      : "memory", "cc");                \
                        break;                                          \
                case __X86_CASE_W:                                      \
index ed3065fd63146d5ce68582a50b0c2d675ec7e3ec..4b4331d71935c7cf0d477e1c3a06b93072e4b463 100644 (file)
@@ -59,7 +59,8 @@ extern int dma_supported(struct device *hwdev, u64 mask);
 extern int dma_set_mask(struct device *dev, u64 mask);
 
 extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
-                                       dma_addr_t *dma_addr, gfp_t flag);
+                                       dma_addr_t *dma_addr, gfp_t flag,
+                                       struct dma_attrs *attrs);
 
 static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 {
@@ -111,9 +112,11 @@ static inline gfp_t dma_alloc_coherent_gfp_flags(struct device *dev, gfp_t gfp)
        return gfp;
 }
 
+#define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
+
 static inline void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-               gfp_t gfp)
+dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
+               gfp_t gfp, struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
        void *memory;
@@ -129,18 +132,21 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
        if (!is_device_dma_capable(dev))
                return NULL;
 
-       if (!ops->alloc_coherent)
+       if (!ops->alloc)
                return NULL;
 
-       memory = ops->alloc_coherent(dev, size, dma_handle,
-                                    dma_alloc_coherent_gfp_flags(dev, gfp));
+       memory = ops->alloc(dev, size, dma_handle,
+                           dma_alloc_coherent_gfp_flags(dev, gfp), attrs);
        debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
 
        return memory;
 }
 
-static inline void dma_free_coherent(struct device *dev, size_t size,
-                                    void *vaddr, dma_addr_t bus)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *vaddr, dma_addr_t bus,
+                                 struct dma_attrs *attrs)
 {
        struct dma_map_ops *ops = get_dma_ops(dev);
 
@@ -150,8 +156,8 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
                return;
 
        debug_dma_free_coherent(dev, size, vaddr, bus);
-       if (ops->free_coherent)
-               ops->free_coherent(dev, size, vaddr, bus);
+       if (ops->free)
+               ops->free(dev, size, vaddr, bus, attrs);
 }
 
 #endif
index 3427b7798dbcdfed5a93f0e5d448feedb588846c..7ef7c3020e5c5bb8e34b4f573e02434b4202f806 100644 (file)
@@ -7,9 +7,9 @@
 #else
 # ifdef __i386__
 #  include "posix_types_32.h"
-# elif defined(__LP64__)
-#  include "posix_types_64.h"
-# else
+# elif defined(__ILP32__)
 #  include "posix_types_x32.h"
+# else
+#  include "posix_types_64.h"
 # endif
 #endif
index 7284c9a6a0b531c29132a475b0429046787de742..4fa7dcceb6c084816346562bacdac4aa7098a9ee 100644 (file)
@@ -974,16 +974,6 @@ extern bool cpu_has_amd_erratum(const int *);
 #define cpu_has_amd_erratum(x) (false)
 #endif /* CONFIG_CPU_SUP_AMD */
 
-#ifdef CONFIG_X86_32
-/*
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-#endif
-
-void disable_hlt(void);
-void enable_hlt(void);
-
 void cpu_idle_wait(void);
 
 extern unsigned long arch_align_stack(unsigned long sp);
index 4a085383af27effcab8935689ef63f0ba9304842..5ca71c065eef2d9a62af1defdb2b06ac7f64cbbd 100644 (file)
@@ -257,7 +257,7 @@ struct sigcontext {
        __u64 oldmask;
        __u64 cr2;
        struct _fpstate __user *fpstate;        /* zero when no FPU context */
-#ifndef __LP64__
+#ifdef __ILP32__
        __u32 __fpstate_pad;
 #endif
        __u64 reserved1[8];
index fc1aa553564604c405569eea428d3a10398bcc55..34c47b3341c0343a7bca3f09fa35e87121df08c8 100644 (file)
@@ -2,7 +2,13 @@
 #define _ASM_X86_SIGINFO_H
 
 #ifdef __x86_64__
-# define __ARCH_SI_PREAMBLE_SIZE       (4 * sizeof(int))
+# ifdef __ILP32__ /* x32 */
+typedef long long __kernel_si_clock_t __attribute__((aligned(4)));
+#  define __ARCH_SI_CLOCK_T            __kernel_si_clock_t
+#  define __ARCH_SI_ATTRIBUTES         __attribute__((aligned(8)))
+# else /* x86-64 */
+#  define __ARCH_SI_PREAMBLE_SIZE      (4 * sizeof(int))
+# endif
 #endif
 
 #include <asm-generic/siginfo.h>
index 8be5f54d93606a374943cba5080dde65ff5e9e1d..e0544597cfe7b30a0e40d52c9d13cb65a6bf3d6c 100644 (file)
@@ -557,6 +557,8 @@ struct __large_struct { unsigned long buf[100]; };
 
 extern unsigned long
 copy_from_user_nmi(void *to, const void __user *from, unsigned long n);
+extern __must_check long
+strncpy_from_user(char *dst, const char __user *src, long count);
 
 /*
  * movsl can be slow when source and dest are not both 8-byte aligned
index 566e803cc6026a11a1391fd25051717cef3f5979..8084bc73b18cbf8164f85dc86f7e78c4e1b07c78 100644 (file)
@@ -213,11 +213,6 @@ static inline unsigned long __must_check copy_from_user(void *to,
        return n;
 }
 
-long __must_check strncpy_from_user(char *dst, const char __user *src,
-                                   long count);
-long __must_check __strncpy_from_user(char *dst,
-                                     const char __user *src, long count);
-
 /**
  * strlen_user: - Get the size of a string in user space.
  * @str: The string to measure.
index 1c66d30971adedaac940770d701e141ae464e1f4..fcd4b6f3ef02ffcabec9ae5ef815ea7b7fdf80a8 100644 (file)
@@ -208,10 +208,6 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
        }
 }
 
-__must_check long
-strncpy_from_user(char *dst, const char __user *src, long count);
-__must_check long
-__strncpy_from_user(char *dst, const char __user *src, long count);
 __must_check long strnlen_user(const char __user *str, long n);
 __must_check long __strnlen_user(const char __user *str, long n);
 __must_check long strlen_user(const char __user *str);
index 37cdc9d99bb18097c5cde1895606864510de3f5f..4437001d8e3d124853e7e12289befb09c12b2e2f 100644 (file)
 #else
 # ifdef __i386__
 #  include <asm/unistd_32.h>
-# elif defined(__LP64__)
-#  include <asm/unistd_64.h>
-# else
+# elif defined(__ILP32__)
 #  include <asm/unistd_x32.h>
+# else
+#  include <asm/unistd_64.h>
 # endif
 #endif
 
index c4b9dc2f67c5f6f7a095dd7d4a3a6bb7fd7b3975..44282fbf7bf95c9e36c1ce200810d2a7c6163bf2 100644 (file)
 #define vga_readb(x) (*(x))
 #define vga_writeb(x, y) (*(y) = (x))
 
+#ifdef CONFIG_FB_EFI
+#define __ARCH_HAS_VGA_DEFAULT_DEVICE
+extern struct pci_dev *vga_default_device(void);
+extern void vga_set_default_device(struct pci_dev *pdev);
+#endif
+
 #endif /* _ASM_X86_VGA_H */
diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h
new file mode 100644 (file)
index 0000000..e58f03b
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef _ASM_WORD_AT_A_TIME_H
+#define _ASM_WORD_AT_A_TIME_H
+
+/*
+ * This is largely generic for little-endian machines, but the
+ * optimal byte mask counting is probably going to be something
+ * that is architecture-specific. If you have a reliably fast
+ * bit count instruction, that might be better than the multiply
+ * and shift, for example.
+ */
+
+#ifdef CONFIG_64BIT
+
+/*
+ * Jan Achrenius on G+: microoptimized version of
+ * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
+ * that works for the bytemasks without having to
+ * mask them first.
+ */
+static inline long count_masked_bytes(unsigned long mask)
+{
+       return mask*0x0001020304050608ul >> 56;
+}
+
+#else  /* 32-bit case */
+
+/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
+static inline long count_masked_bytes(long mask)
+{
+       /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
+       long a = (0x0ff0001+mask) >> 23;
+       /* Fix the 1 for 00 case */
+       return a & mask;
+}
+
+#endif
+
+#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
+
+/* Return the high bit set in the first byte that is a zero */
+static inline unsigned long has_zero(unsigned long a)
+{
+       return ((a - REPEAT_BYTE(0x01)) & ~a) & REPEAT_BYTE(0x80);
+}
+
+/*
+ * Load an unaligned word from kernel space.
+ *
+ * In the (very unlikely) case of the word being a page-crosser
+ * and the next page not being mapped, take the exception and
+ * return zeroes in the non-existing part.
+ */
+static inline unsigned long load_unaligned_zeropad(const void *addr)
+{
+       unsigned long ret, dummy;
+
+       asm(
+               "1:\tmov %2,%0\n"
+               "2:\n"
+               ".section .fixup,\"ax\"\n"
+               "3:\t"
+               "lea %2,%1\n\t"
+               "and %3,%1\n\t"
+               "mov (%1),%0\n\t"
+               "leal %2,%%ecx\n\t"
+               "andl %4,%%ecx\n\t"
+               "shll $3,%%ecx\n\t"
+               "shr %%cl,%0\n\t"
+               "jmp 2b\n"
+               ".previous\n"
+               _ASM_EXTABLE(1b, 3b)
+               :"=&r" (ret),"=&c" (dummy)
+               :"m" (*(unsigned long *)addr),
+                "i" (-sizeof(unsigned long)),
+                "i" (sizeof(unsigned long)-1));
+       return ret;
+}
+
+#endif /* _ASM_WORD_AT_A_TIME_H */
index baaca8defec8032463d1a87d53137a8c88f63639..764b66a4cf896cc51cbbdc50f9455d51511b64c6 100644 (file)
@@ -195,6 +195,5 @@ extern struct x86_msi_ops x86_msi;
 
 extern void x86_init_noop(void);
 extern void x86_init_uint_noop(unsigned int unused);
-extern void x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node);
 
 #endif
index 103b6ab368d39315bc752e02a7bdc5b83ede0acf..146a49c763a49085b50d5b3b6babcda74650463b 100644 (file)
@@ -24,6 +24,10 @@ unsigned long acpi_realmode_flags;
 static char temp_stack[4096];
 #endif
 
+asmlinkage void acpi_enter_s3(void)
+{
+       acpi_enter_sleep_state(3, wake_sleep_flags);
+}
 /**
  * acpi_suspend_lowlevel - save kernel state
  *
index 416d4be13fef6d16cc96936ae3f222a91040ccf0..d68677a2a01037a758496ee31aa575ccbb2badff 100644 (file)
@@ -3,12 +3,16 @@
  */
 
 #include <asm/trampoline.h>
+#include <linux/linkage.h>
 
 extern unsigned long saved_video_mode;
 extern long saved_magic;
 
 extern int wakeup_pmode_return;
 
+extern u8 wake_sleep_flags;
+extern asmlinkage void acpi_enter_s3(void);
+
 extern unsigned long acpi_copy_wakeup_routine(unsigned long);
 extern void wakeup_long64(void);
 
index 13ab720573e3e31e317ac52f977e168401552f17..72610839f03b3d45e8fa6adb49a13fe933b477b2 100644 (file)
@@ -74,9 +74,7 @@ restore_registers:
 ENTRY(do_suspend_lowlevel)
        call    save_processor_state
        call    save_registers
-       pushl   $3
-       call    acpi_enter_sleep_state
-       addl    $4, %esp
+       call    acpi_enter_s3
 
 #      In case of S3 failure, we'll emerge here.  Jump
 #      to ret_point to recover
index 8ea5164cbd0451a27b9048699f60c2420057edb3..014d1d28c397076606be9d50f04af06892bf2f03 100644 (file)
@@ -71,9 +71,7 @@ ENTRY(do_suspend_lowlevel)
        movq    %rsi, saved_rsi
 
        addq    $8, %rsp
-       movl    $3, %edi
-       xorl    %eax, %eax
-       call    acpi_enter_sleep_state
+       call    acpi_enter_s3
        /* in case something went wrong, restore the machine status and go on */
        jmp     resume_point
 
index b1e7c7f7a0af46c788b5a5f47a476a41e035f5f9..e66311200cbd8ae78274e7f3525d9098cec43ffe 100644 (file)
@@ -477,7 +477,7 @@ error:
 /* allocate and map a coherent mapping */
 static void *
 gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr,
-                   gfp_t flag)
+                   gfp_t flag, struct dma_attrs *attrs)
 {
        dma_addr_t paddr;
        unsigned long align_mask;
@@ -500,7 +500,8 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr,
                }
                __free_pages(page, get_order(size));
        } else
-               return dma_generic_alloc_coherent(dev, size, dma_addr, flag);
+               return dma_generic_alloc_coherent(dev, size, dma_addr, flag,
+                                                 attrs);
 
        return NULL;
 }
@@ -508,7 +509,7 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr,
 /* free a coherent mapping */
 static void
 gart_free_coherent(struct device *dev, size_t size, void *vaddr,
-                  dma_addr_t dma_addr)
+                  dma_addr_t dma_addr, struct dma_attrs *attrs)
 {
        gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, NULL);
        free_pages((unsigned long)vaddr, get_order(size));
@@ -700,8 +701,8 @@ static struct dma_map_ops gart_dma_ops = {
        .unmap_sg                       = gart_unmap_sg,
        .map_page                       = gart_map_page,
        .unmap_page                     = gart_unmap_page,
-       .alloc_coherent                 = gart_alloc_coherent,
-       .free_coherent                  = gart_free_coherent,
+       .alloc                          = gart_alloc_coherent,
+       .free                           = gart_free_coherent,
        .mapping_error                  = gart_mapping_error,
 };
 
index 11544d8f1e975e30c1e3c0d9aafa58b4ba67a1da..edc24480469f10188e64855ff76f3df2dcab85c4 100644 (file)
@@ -1637,9 +1637,11 @@ static int __init apic_verify(void)
        mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
 
        /* The BIOS may have set up the APIC at some other address */
-       rdmsr(MSR_IA32_APICBASE, l, h);
-       if (l & MSR_IA32_APICBASE_ENABLE)
-               mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+       if (boot_cpu_data.x86 >= 6) {
+               rdmsr(MSR_IA32_APICBASE, l, h);
+               if (l & MSR_IA32_APICBASE_ENABLE)
+                       mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+       }
 
        pr_info("Found and enabled local APIC!\n");
        return 0;
@@ -1657,13 +1659,15 @@ int __init apic_force_enable(unsigned long addr)
         * MSR. This can only be done in software for Intel P6 or later
         * and AMD K7 (Model > 1) or later.
         */
-       rdmsr(MSR_IA32_APICBASE, l, h);
-       if (!(l & MSR_IA32_APICBASE_ENABLE)) {
-               pr_info("Local APIC disabled by BIOS -- reenabling.\n");
-               l &= ~MSR_IA32_APICBASE_BASE;
-               l |= MSR_IA32_APICBASE_ENABLE | addr;
-               wrmsr(MSR_IA32_APICBASE, l, h);
-               enabled_via_apicbase = 1;
+       if (boot_cpu_data.x86 >= 6) {
+               rdmsr(MSR_IA32_APICBASE, l, h);
+               if (!(l & MSR_IA32_APICBASE_ENABLE)) {
+                       pr_info("Local APIC disabled by BIOS -- reenabling.\n");
+                       l &= ~MSR_IA32_APICBASE_BASE;
+                       l |= MSR_IA32_APICBASE_ENABLE | addr;
+                       wrmsr(MSR_IA32_APICBASE, l, h);
+                       enabled_via_apicbase = 1;
+               }
        }
        return apic_verify();
 }
@@ -2209,10 +2213,12 @@ static void lapic_resume(void)
                 * FIXME! This will be wrong if we ever support suspend on
                 * SMP! We'll need to do this as part of the CPU restore!
                 */
-               rdmsr(MSR_IA32_APICBASE, l, h);
-               l &= ~MSR_IA32_APICBASE_BASE;
-               l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
-               wrmsr(MSR_IA32_APICBASE, l, h);
+               if (boot_cpu_data.x86 >= 6) {
+                       rdmsr(MSR_IA32_APICBASE, l, h);
+                       l &= ~MSR_IA32_APICBASE_BASE;
+                       l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
+                       wrmsr(MSR_IA32_APICBASE, l, h);
+               }
        }
 
        maxlvt = lapic_get_maxlvt();
index 899803e032142662650389d693ca4594a08ab18d..23e75422e0138aa42e58ff64a5a37322bd9f46bb 100644 (file)
@@ -207,8 +207,11 @@ static void __init map_csrs(void)
 
 static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
 {
-       c->phys_proc_id = node;
-       per_cpu(cpu_llc_id, smp_processor_id()) = node;
+
+       if (c->phys_proc_id != node) {
+               c->phys_proc_id = node;
+               per_cpu(cpu_llc_id, smp_processor_id()) = node;
+       }
 }
 
 static int __init numachip_system_init(void)
index 8a778db45e3a508ef2402596ee57884eaf639166..991e315f4227c8e69b5bac35372c15a86ab28b60 100644 (file)
@@ -24,6 +24,12 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
        if (x2apic_phys)
                return x2apic_enabled();
+       else if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) &&
+               (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL) &&
+               x2apic_enabled()) {
+               printk(KERN_DEBUG "System requires x2apic physical mode\n");
+               return 1;
+       }
        else
                return 0;
 }
index 0a44b90602b036584a6f499759b47c53028e10b2..146bb6218eec3daa3cdbe0472c04bcfac7500e8a 100644 (file)
@@ -26,7 +26,8 @@
  *     contact AMD for precise details and a CPU swap.
  *
  *     See     http://www.multimania.com/poulot/k6bug.html
- *             http://www.amd.com/K6/k6docs/revgd.html
+ *     and     section 2.6.2 of "AMD-K6 Processor Revision Guide - Model 6"
+ *             (Publication # 21266  Issue Date: August 1998)
  *
  *     The following test is erm.. interesting. AMD neglected to up
  *     the chip setting when fixing the bug but they also tweaked some
@@ -94,7 +95,6 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c)
                                "system stability may be impaired when more than 32 MB are used.\n");
                else
                        printk(KERN_CONT "probably OK (after B9730xxxx).\n");
-               printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n");
        }
 
        /* K6 with old style WHCR */
@@ -353,10 +353,11 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
                node = per_cpu(cpu_llc_id, cpu);
 
        /*
-        * If core numbers are inconsistent, it's likely a multi-fabric platform,
-        * so invoke platform-specific handler
+        * On multi-fabric platform (e.g. Numascale NumaChip) a
+        * platform-specific handler needs to be called to fixup some
+        * IDs of the CPU.
         */
-       if (c->phys_proc_id != node)
+       if (x86_cpuinit.fixup_cpu_id)
                x86_cpuinit.fixup_cpu_id(c, node);
 
        if (!node_online(node)) {
@@ -579,6 +580,24 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                }
        }
 
+       /* re-enable TopologyExtensions if switched off by BIOS */
+       if ((c->x86 == 0x15) &&
+           (c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
+           !cpu_has(c, X86_FEATURE_TOPOEXT)) {
+               u64 val;
+
+               if (!rdmsrl_amd_safe(0xc0011005, &val)) {
+                       val |= 1ULL << 54;
+                       wrmsrl_amd_safe(0xc0011005, val);
+                       rdmsrl(0xc0011005, val);
+                       if (val & (1ULL << 54)) {
+                               set_cpu_cap(c, X86_FEATURE_TOPOEXT);
+                               printk(KERN_INFO FW_INFO "CPU: Re-enabling "
+                                 "disabled Topology Extensions Support\n");
+                       }
+               }
+       }
+
        cpu_detect_cache_sizes(c);
 
        /* Multi core CPU? */
index 67e258362a3d56d7f94c675ec876705003469c3a..cf79302198a620bc1e1e60740487f33d5244edbe 100644 (file)
@@ -1162,15 +1162,6 @@ static void dbg_restore_debug_regs(void)
 #define dbg_restore_debug_regs()
 #endif /* ! CONFIG_KGDB */
 
-/*
- * Prints an error where the NUMA and configured core-number mismatch and the
- * platform didn't override this to fix it up
- */
-void __cpuinit x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node)
-{
-       pr_err("NUMA core number %d differs from configured core number %d\n", node, c->phys_proc_id);
-}
-
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
index 73d08ed98a64fc8beafb3c2e6768d19f02c09f89..b8f3653dddbc2daccf1d0da1990e74b8cab57202 100644 (file)
@@ -433,14 +433,14 @@ int amd_set_l3_disable_slot(struct amd_northbridge *nb, int cpu, unsigned slot,
        /*  check if @slot is already used or the index is already disabled */
        ret = amd_get_l3_disable_slot(nb, slot);
        if (ret >= 0)
-               return -EINVAL;
+               return -EEXIST;
 
        if (index > nb->l3_cache.indices)
                return -EINVAL;
 
        /* check whether the other slot has disabled the same index already */
        if (index == amd_get_l3_disable_slot(nb, !slot))
-               return -EINVAL;
+               return -EEXIST;
 
        amd_l3_disable_index(nb, cpu, slot, index);
 
@@ -468,8 +468,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
        err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
        if (err) {
                if (err == -EEXIST)
-                       printk(KERN_WARNING "L3 disable slot %d in use!\n",
-                                           slot);
+                       pr_warning("L3 slot %d in use/index already disabled!\n",
+                                  slot);
                return err;
        }
        return count;
index ef484d9d0a251b0128a164486096ce43c4ea8f4c..a2dfacfd7103b4b951452d5c42a3d613223f5ad5 100644 (file)
@@ -1271,6 +1271,17 @@ done:
        return num ? -EINVAL : 0;
 }
 
+PMU_FORMAT_ATTR(cccr, "config:0-31" );
+PMU_FORMAT_ATTR(escr, "config:32-62");
+PMU_FORMAT_ATTR(ht,   "config:63"   );
+
+static struct attribute *intel_p4_formats_attr[] = {
+       &format_attr_cccr.attr,
+       &format_attr_escr.attr,
+       &format_attr_ht.attr,
+       NULL,
+};
+
 static __initconst const struct x86_pmu p4_pmu = {
        .name                   = "Netburst P4/Xeon",
        .handle_irq             = p4_pmu_handle_irq,
@@ -1305,6 +1316,8 @@ static __initconst const struct x86_pmu p4_pmu = {
         * the former idea is taken from OProfile code
         */
        .perfctr_second_write   = 1,
+
+       .format_attrs           = intel_p4_formats_attr,
 };
 
 __init int p4_pmu_init(void)
index 7734bcbb5a3a3b21e11374f82747972d678e8999..2d6e6498c176cda24349b01d5d89cd57b2cfb5ac 100644 (file)
@@ -235,6 +235,7 @@ int init_fpu(struct task_struct *tsk)
        if (tsk_used_math(tsk)) {
                if (HAVE_HWFP && tsk == current)
                        unlazy_fpu(tsk);
+               tsk->thread.fpu.last_cpu = ~0;
                return 0;
        }
 
index 7943e0c21bde4daa742ed209e5121ab697f659e8..3dafc6003b7c4a5c177238f3f21d652cdb20ca30 100644 (file)
@@ -282,8 +282,13 @@ void fixup_irqs(void)
                else if (!(warned++))
                        set_affinity = 0;
 
+               /*
+                * We unmask if the irq was not marked masked by the
+                * core code. That respects the lazy irq disable
+                * behaviour.
+                */
                if (!irqd_can_move_in_process_context(data) &&
-                   !irqd_irq_disabled(data) && chip->irq_unmask)
+                   !irqd_irq_masked(data) && chip->irq_unmask)
                        chip->irq_unmask(data);
 
                raw_spin_unlock(&desc->lock);
index 90fcf62854bbac679eec40879db54df2ed6d09b5..1d5d31ea686be2aaedb2790637674cc0c0fec56b 100644 (file)
@@ -68,16 +68,9 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
        return count;
 }
 
-static int setup_data_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-
-       return 0;
-}
-
 static const struct file_operations fops_setup_data = {
        .read           = setup_data_read,
-       .open           = setup_data_open,
+       .open           = simple_open,
        .llseek         = default_llseek,
 };
 
index db6720edfdd04f6d6a5e57da090c36db7a28eb31..8bfb6146f7530634d30fa9f25d1718111a214649 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/smp.h>
 #include <linux/nmi.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/uaccess.h>
+#include <linux/memory.h>
 
 #include <asm/debugreg.h>
 #include <asm/apicdef.h>
@@ -741,6 +743,64 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
        regs->ip = ip;
 }
 
+int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
+{
+       int err;
+       char opc[BREAK_INSTR_SIZE];
+
+       bpt->type = BP_BREAKPOINT;
+       err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+                               BREAK_INSTR_SIZE);
+       if (err)
+               return err;
+       err = probe_kernel_write((char *)bpt->bpt_addr,
+                                arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+#ifdef CONFIG_DEBUG_RODATA
+       if (!err)
+               return err;
+       /*
+        * It is safe to call text_poke() because normal kernel execution
+        * is stopped on all cores, so long as the text_mutex is not locked.
+        */
+       if (mutex_is_locked(&text_mutex))
+               return -EBUSY;
+       text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr,
+                 BREAK_INSTR_SIZE);
+       err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+       if (err)
+               return err;
+       if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE))
+               return -EINVAL;
+       bpt->type = BP_POKE_BREAKPOINT;
+#endif /* CONFIG_DEBUG_RODATA */
+       return err;
+}
+
+int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
+{
+#ifdef CONFIG_DEBUG_RODATA
+       int err;
+       char opc[BREAK_INSTR_SIZE];
+
+       if (bpt->type != BP_POKE_BREAKPOINT)
+               goto knl_write;
+       /*
+        * It is safe to call text_poke() because normal kernel execution
+        * is stopped on all cores, so long as the text_mutex is not locked.
+        */
+       if (mutex_is_locked(&text_mutex))
+               goto knl_write;
+       text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE);
+       err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+       if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE))
+               goto knl_write;
+       return err;
+knl_write:
+#endif /* CONFIG_DEBUG_RODATA */
+       return probe_kernel_write((char *)bpt->bpt_addr,
+                                 (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
+}
+
 struct kgdb_arch arch_kgdb_ops = {
        /* Breakpoint instruction: */
        .gdb_bpt_instr          = { 0xcc },
index 694d801bf606736fb5b54a74b225fa229c7f5ac4..b8ba6e4a27e4102bd36a6445ec4b503be990d62d 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/traps.h>
 #include <asm/desc.h>
 #include <asm/tlbflush.h>
+#include <asm/idle.h>
 
 static int kvmapf = 1;
 
@@ -253,7 +254,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
                kvm_async_pf_task_wait((u32)read_cr2());
                break;
        case KVM_PV_REASON_PAGE_READY:
+               rcu_irq_enter();
+               exit_idle();
                kvm_async_pf_task_wake((u32)read_cr2());
+               rcu_irq_exit();
                break;
        }
 }
index 73465aab28f87c09b5313e81e79d54a31afff1f1..8a2ce8fd41c0e68bbedc6fce685fb52c95502d24 100644 (file)
@@ -82,11 +82,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
 {
        struct cpuinfo_x86 *c = &cpu_data(cpu);
 
-       if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
-               pr_warning("CPU%d: family %d not supported\n", cpu, c->x86);
-               return -1;
-       }
-
        csig->rev = c->microcode;
        pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
 
@@ -380,6 +375,13 @@ static struct microcode_ops microcode_amd_ops = {
 
 struct microcode_ops * __init init_amd_microcode(void)
 {
+       struct cpuinfo_x86 *c = &cpu_data(0);
+
+       if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
+               pr_warning("AMD CPU family 0x%x not supported\n", c->x86);
+               return NULL;
+       }
+
        patch = (void *)get_zeroed_page(GFP_KERNEL);
        if (!patch)
                return NULL;
index 87a0f868830141cc6e508341c756640ace7fc34c..c9bda6d6035c83b06b2ac5e26aebca76b9fc4f34 100644 (file)
@@ -419,10 +419,8 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif)
        if (err)
                return err;
 
-       if (microcode_init_cpu(cpu) == UCODE_ERROR) {
-               sysfs_remove_group(&dev->kobj, &mc_attr_group);
+       if (microcode_init_cpu(cpu) == UCODE_ERROR)
                return -EINVAL;
-       }
 
        return err;
 }
@@ -528,11 +526,11 @@ static int __init microcode_init(void)
                microcode_ops = init_intel_microcode();
        else if (c->x86_vendor == X86_VENDOR_AMD)
                microcode_ops = init_amd_microcode();
-
-       if (!microcode_ops) {
+       else
                pr_err("no support for this CPU vendor\n");
+
+       if (!microcode_ops)
                return -ENODEV;
-       }
 
        microcode_pdev = platform_device_register_simple("microcode", -1,
                                                         NULL, 0);
index 6ac5782f4d6bf6cfb90666bc5288aad548d0c04f..d0b2fb9ccbb16e1e9dc09afe32cb48fa38bfe81c 100644 (file)
@@ -430,7 +430,7 @@ static void calgary_unmap_page(struct device *dev, dma_addr_t dma_addr,
 }
 
 static void* calgary_alloc_coherent(struct device *dev, size_t size,
-       dma_addr_t *dma_handle, gfp_t flag)
+       dma_addr_t *dma_handle, gfp_t flag, struct dma_attrs *attrs)
 {
        void *ret = NULL;
        dma_addr_t mapping;
@@ -463,7 +463,8 @@ error:
 }
 
 static void calgary_free_coherent(struct device *dev, size_t size,
-                                 void *vaddr, dma_addr_t dma_handle)
+                                 void *vaddr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
 {
        unsigned int npages;
        struct iommu_table *tbl = find_iommu_table(dev);
@@ -476,8 +477,8 @@ static void calgary_free_coherent(struct device *dev, size_t size,
 }
 
 static struct dma_map_ops calgary_dma_ops = {
-       .alloc_coherent = calgary_alloc_coherent,
-       .free_coherent = calgary_free_coherent,
+       .alloc = calgary_alloc_coherent,
+       .free = calgary_free_coherent,
        .map_sg = calgary_map_sg,
        .unmap_sg = calgary_unmap_sg,
        .map_page = calgary_map_page,
index 28e5e06fcba484c7520c718fb3cd9d961a103988..3003250ac51dbcdc5be17a2fa37a84d9aae4a4e1 100644 (file)
@@ -96,7 +96,8 @@ void __init pci_iommu_alloc(void)
        }
 }
 void *dma_generic_alloc_coherent(struct device *dev, size_t size,
-                                dma_addr_t *dma_addr, gfp_t flag)
+                                dma_addr_t *dma_addr, gfp_t flag,
+                                struct dma_attrs *attrs)
 {
        unsigned long dma_mask;
        struct page *page;
index 3af4af810c07947d9a697444f3010bf2d5427e45..f96050685b46eb16504f3731ea02096464750829 100644 (file)
@@ -75,7 +75,7 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
 }
 
 static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr,
-                               dma_addr_t dma_addr)
+                               dma_addr_t dma_addr, struct dma_attrs *attrs)
 {
        free_pages((unsigned long)vaddr, get_order(size));
 }
@@ -96,8 +96,8 @@ static void nommu_sync_sg_for_device(struct device *dev,
 }
 
 struct dma_map_ops nommu_dma_ops = {
-       .alloc_coherent         = dma_generic_alloc_coherent,
-       .free_coherent          = nommu_free_coherent,
+       .alloc                  = dma_generic_alloc_coherent,
+       .free                   = nommu_free_coherent,
        .map_sg                 = nommu_map_sg,
        .map_page               = nommu_map_page,
        .sync_single_for_device = nommu_sync_single_for_device,
index 8f972cbddef0c390df0a386ff4d08a8c20865ea1..6c483ba98b9c614eb5fabc87d5f6f1833fabb4e4 100644 (file)
 int swiotlb __read_mostly;
 
 static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
-                                       dma_addr_t *dma_handle, gfp_t flags)
+                                       dma_addr_t *dma_handle, gfp_t flags,
+                                       struct dma_attrs *attrs)
 {
        void *vaddr;
 
-       vaddr = dma_generic_alloc_coherent(hwdev, size, dma_handle, flags);
+       vaddr = dma_generic_alloc_coherent(hwdev, size, dma_handle, flags,
+                                          attrs);
        if (vaddr)
                return vaddr;
 
        return swiotlb_alloc_coherent(hwdev, size, dma_handle, flags);
 }
 
+static void x86_swiotlb_free_coherent(struct device *dev, size_t size,
+                                     void *vaddr, dma_addr_t dma_addr,
+                                     struct dma_attrs *attrs)
+{
+       swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+}
+
 static struct dma_map_ops swiotlb_dma_ops = {
        .mapping_error = swiotlb_dma_mapping_error,
-       .alloc_coherent = x86_swiotlb_alloc_coherent,
-       .free_coherent = swiotlb_free_coherent,
+       .alloc = x86_swiotlb_alloc_coherent,
+       .free = x86_swiotlb_free_coherent,
        .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
        .sync_single_for_device = swiotlb_sync_single_for_device,
        .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
index a33afaa5ddb78e2594f706b826fee37a9dd02129..1d92a5ab6e8b939613d6bfd7221133df2496b482 100644 (file)
@@ -362,34 +362,10 @@ void (*pm_idle)(void);
 EXPORT_SYMBOL(pm_idle);
 #endif
 
-#ifdef CONFIG_X86_32
-/*
- * This halt magic was a workaround for ancient floppy DMA
- * wreckage. It should be safe to remove.
- */
-static int hlt_counter;
-void disable_hlt(void)
-{
-       hlt_counter++;
-}
-EXPORT_SYMBOL(disable_hlt);
-
-void enable_hlt(void)
-{
-       hlt_counter--;
-}
-EXPORT_SYMBOL(enable_hlt);
-
-static inline int hlt_use_halt(void)
-{
-       return (!hlt_counter && boot_cpu_data.hlt_works_ok);
-}
-#else
 static inline int hlt_use_halt(void)
 {
        return 1;
 }
-#endif
 
 #ifndef CONFIG_SMP
 static inline void play_dead(void)
index f386dc49f988d753c5b9f8167c80313d5be72178..7515cf0e1805eae308e1dd0650b1dd33a8d8564d 100644 (file)
@@ -216,9 +216,9 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
        current_thread_info()->sig_on_uaccess_error = 1;
 
        /*
-        * 0 is a valid user pointer (in the access_ok sense) on 32-bit and
+        * NULL is a valid user pointer (in the access_ok sense) on 32-bit and
         * 64-bit, so we don't need to special-case it here.  For all the
-        * vsyscalls, 0 means "don't write anything" not "write it at
+        * vsyscalls, NULL means "don't write anything" not "write it at
         * address 0".
         */
        ret = -EFAULT;
@@ -247,7 +247,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
 
                ret = sys_getcpu((unsigned __user *)regs->di,
                                 (unsigned __user *)regs->si,
-                                0);
+                                NULL);
                break;
        }
 
index e9f265fd79ae11db4d5234e7b7462134c6220619..9cf71d0b2d373598b4db57b508061c08cd44e19b 100644 (file)
@@ -93,7 +93,6 @@ struct x86_init_ops x86_init __initdata = {
 struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = {
        .early_percpu_clock_init        = x86_init_noop,
        .setup_percpu_clockev           = setup_secondary_APIC_clock,
-       .fixup_cpu_id                   = x86_default_fixup_cpu_id,
 };
 
 static void default_nmi_init(void) { };
index a73f0c1048137062417b43e59785546c38b0dcd5..2e88438ffd83186c0d7a6b136cc97ae5c943ae4a 100644 (file)
@@ -369,7 +369,7 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data)
        case MSR_CORE_PERF_FIXED_CTR_CTRL:
                if (pmu->fixed_ctr_ctrl == data)
                        return 0;
-               if (!(data & 0xfffffffffffff444)) {
+               if (!(data & 0xfffffffffffff444ull)) {
                        reprogram_fixed_counters(pmu, data);
                        return 0;
                }
@@ -459,17 +459,17 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
        pmu->available_event_types = ~entry->ebx & ((1ull << bitmap_len) - 1);
 
        if (pmu->version == 1) {
-               pmu->global_ctrl = (1 << pmu->nr_arch_gp_counters) - 1;
-               return;
+               pmu->nr_arch_fixed_counters = 0;
+       } else {
+               pmu->nr_arch_fixed_counters = min((int)(entry->edx & 0x1f),
+                               X86_PMC_MAX_FIXED);
+               pmu->counter_bitmask[KVM_PMC_FIXED] =
+                       ((u64)1 << ((entry->edx >> 5) & 0xff)) - 1;
        }
 
-       pmu->nr_arch_fixed_counters = min((int)(entry->edx & 0x1f),
-                       X86_PMC_MAX_FIXED);
-       pmu->counter_bitmask[KVM_PMC_FIXED] =
-               ((u64)1 << ((entry->edx >> 5) & 0xff)) - 1;
-       pmu->global_ctrl_mask = ~(((1 << pmu->nr_arch_gp_counters) - 1)
-                       | (((1ull << pmu->nr_arch_fixed_counters) - 1)
-                               << X86_PMC_IDX_FIXED));
+       pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
+               (((1ull << pmu->nr_arch_fixed_counters) - 1) << X86_PMC_IDX_FIXED);
+       pmu->global_ctrl_mask = ~pmu->global_ctrl;
 }
 
 void kvm_pmu_init(struct kvm_vcpu *vcpu)
index 280751c84724a087ce5a6d9bbeb9c3dba67541bc..4ff0ab9bc3c86fd26889fa4b88b23c48c84523db 100644 (file)
@@ -2210,9 +2210,12 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
                msr = find_msr_entry(vmx, msr_index);
                if (msr) {
                        msr->data = data;
-                       if (msr - vmx->guest_msrs < vmx->save_nmsrs)
+                       if (msr - vmx->guest_msrs < vmx->save_nmsrs) {
+                               preempt_disable();
                                kvm_set_shared_msr(msr->index, msr->data,
                                                   msr->mask);
+                               preempt_enable();
+                       }
                        break;
                }
                ret = kvm_set_msr_common(vcpu, msr_index, data);
@@ -3906,7 +3909,9 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
                vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
 
        vmx->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
+       vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
        vmx_set_cr0(&vmx->vcpu, kvm_read_cr0(vcpu)); /* enter rmode */
+       srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
        vmx_set_cr4(&vmx->vcpu, 0);
        vmx_set_efer(&vmx->vcpu, 0);
        vmx_fpu_activate(&vmx->vcpu);
index 4044ce0bf7c1e7741620b8fcda9a78c9cb1bc775..91a5e989abcfe86f60df7bcb2a2919e25f87df6a 100644 (file)
@@ -6336,13 +6336,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                if (npages && !old.rmap) {
                        unsigned long userspace_addr;
 
-                       down_write(&current->mm->mmap_sem);
-                       userspace_addr = do_mmap(NULL, 0,
+                       userspace_addr = vm_mmap(NULL, 0,
                                                 npages * PAGE_SIZE,
                                                 PROT_READ | PROT_WRITE,
                                                 map_flags,
                                                 0);
-                       up_write(&current->mm->mmap_sem);
 
                        if (IS_ERR((void *)userspace_addr))
                                return PTR_ERR((void *)userspace_addr);
@@ -6366,10 +6364,8 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
        if (!user_alloc && !old.user_alloc && old.rmap && !npages) {
                int ret;
 
-               down_write(&current->mm->mmap_sem);
-               ret = do_munmap(current->mm, old.userspace_addr,
+               ret = vm_munmap(old.userspace_addr,
                                old.npages * PAGE_SIZE);
-               up_write(&current->mm->mmap_sem);
                if (ret < 0)
                        printk(KERN_WARNING
                               "kvm_vm_ioctl_set_memory_region: "
index 25feb1ae71c5758273346057d8809232bdb1c769..b1e6c4b2e8eb228834edcbad9d9ff8ffbb9d99f9 100644 (file)
@@ -379,8 +379,8 @@ err_out:
        return;
 }
 
-/* Decode moffset16/32/64 */
-static void __get_moffset(struct insn *insn)
+/* Decode moffset16/32/64. Return 0 if failed */
+static int __get_moffset(struct insn *insn)
 {
        switch (insn->addr_bytes) {
        case 2:
@@ -397,15 +397,19 @@ static void __get_moffset(struct insn *insn)
                insn->moffset2.value = get_next(int, insn);
                insn->moffset2.nbytes = 4;
                break;
+       default:        /* opnd_bytes must be modified manually */
+               goto err_out;
        }
        insn->moffset1.got = insn->moffset2.got = 1;
 
+       return 1;
+
 err_out:
-       return;
+       return 0;
 }
 
-/* Decode imm v32(Iz) */
-static void __get_immv32(struct insn *insn)
+/* Decode imm v32(Iz). Return 0 if failed */
+static int __get_immv32(struct insn *insn)
 {
        switch (insn->opnd_bytes) {
        case 2:
@@ -417,14 +421,18 @@ static void __get_immv32(struct insn *insn)
                insn->immediate.value = get_next(int, insn);
                insn->immediate.nbytes = 4;
                break;
+       default:        /* opnd_bytes must be modified manually */
+               goto err_out;
        }
 
+       return 1;
+
 err_out:
-       return;
+       return 0;
 }
 
-/* Decode imm v64(Iv/Ov) */
-static void __get_immv(struct insn *insn)
+/* Decode imm v64(Iv/Ov), Return 0 if failed */
+static int __get_immv(struct insn *insn)
 {
        switch (insn->opnd_bytes) {
        case 2:
@@ -441,15 +449,18 @@ static void __get_immv(struct insn *insn)
                insn->immediate2.value = get_next(int, insn);
                insn->immediate2.nbytes = 4;
                break;
+       default:        /* opnd_bytes must be modified manually */
+               goto err_out;
        }
        insn->immediate1.got = insn->immediate2.got = 1;
 
+       return 1;
 err_out:
-       return;
+       return 0;
 }
 
 /* Decode ptr16:16/32(Ap) */
-static void __get_immptr(struct insn *insn)
+static int __get_immptr(struct insn *insn)
 {
        switch (insn->opnd_bytes) {
        case 2:
@@ -462,14 +473,17 @@ static void __get_immptr(struct insn *insn)
                break;
        case 8:
                /* ptr16:64 is not exist (no segment) */
-               return;
+               return 0;
+       default:        /* opnd_bytes must be modified manually */
+               goto err_out;
        }
        insn->immediate2.value = get_next(unsigned short, insn);
        insn->immediate2.nbytes = 2;
        insn->immediate1.got = insn->immediate2.got = 1;
 
+       return 1;
 err_out:
-       return;
+       return 0;
 }
 
 /**
@@ -489,7 +503,8 @@ void insn_get_immediate(struct insn *insn)
                insn_get_displacement(insn);
 
        if (inat_has_moffset(insn->attr)) {
-               __get_moffset(insn);
+               if (!__get_moffset(insn))
+                       goto err_out;
                goto done;
        }
 
@@ -517,16 +532,20 @@ void insn_get_immediate(struct insn *insn)
                insn->immediate2.nbytes = 4;
                break;
        case INAT_IMM_PTR:
-               __get_immptr(insn);
+               if (!__get_immptr(insn))
+                       goto err_out;
                break;
        case INAT_IMM_VWORD32:
-               __get_immv32(insn);
+               if (!__get_immv32(insn))
+                       goto err_out;
                break;
        case INAT_IMM_VWORD:
-               __get_immv(insn);
+               if (!__get_immv(insn))
+                       goto err_out;
                break;
        default:
-               break;
+               /* Here, insn must have an immediate, but failed */
+               goto err_out;
        }
        if (inat_has_second_immediate(insn->attr)) {
                insn->immediate2.value = get_next(char, insn);
index 97be9cb54483a05f8c5e9510d563f129ea863966..d6ae30bbd7bb833356049d89bdf8d0e5ae004b0c 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/highmem.h>
 #include <linux/module.h>
 
+#include <asm/word-at-a-time.h>
+
 /*
  * best effort, GUP based copy_from_user() that is NMI-safe
  */
@@ -41,3 +43,104 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
        return len;
 }
 EXPORT_SYMBOL_GPL(copy_from_user_nmi);
+
+static inline unsigned long count_bytes(unsigned long mask)
+{
+       mask = (mask - 1) & ~mask;
+       mask >>= 7;
+       return count_masked_bytes(mask);
+}
+
+/*
+ * Do a strncpy, return length of string without final '\0'.
+ * 'count' is the user-supplied count (return 'count' if we
+ * hit it), 'max' is the address space maximum (and we return
+ * -EFAULT if we hit it).
+ */
+static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max)
+{
+       long res = 0;
+
+       /*
+        * Truncate 'max' to the user-specified limit, so that
+        * we only have one limit we need to check in the loop
+        */
+       if (max > count)
+               max = count;
+
+       while (max >= sizeof(unsigned long)) {
+               unsigned long c;
+
+               /* Fall back to byte-at-a-time if we get a page fault */
+               if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
+                       break;
+               /* This can write a few bytes past the NUL character, but that's ok */
+               *(unsigned long *)(dst+res) = c;
+               c = has_zero(c);
+               if (c)
+                       return res + count_bytes(c);
+               res += sizeof(unsigned long);
+               max -= sizeof(unsigned long);
+       }
+
+       while (max) {
+               char c;
+
+               if (unlikely(__get_user(c,src+res)))
+                       return -EFAULT;
+               dst[res] = c;
+               if (!c)
+                       return res;
+               res++;
+               max--;
+       }
+
+       /*
+        * Uhhuh. We hit 'max'. But was that the user-specified maximum
+        * too? If so, that's ok - we got as much as the user asked for.
+        */
+       if (res >= count)
+               return res;
+
+       /*
+        * Nope: we hit the address space limit, and we still had more
+        * characters the caller would have wanted. That's an EFAULT.
+        */
+       return -EFAULT;
+}
+
+/**
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+long
+strncpy_from_user(char *dst, const char __user *src, long count)
+{
+       unsigned long max_addr, src_addr;
+
+       if (unlikely(count <= 0))
+               return 0;
+
+       max_addr = current_thread_info()->addr_limit.seg;
+       src_addr = (unsigned long)src;
+       if (likely(src_addr < max_addr)) {
+               unsigned long max = max_addr - src_addr;
+               return do_strncpy_from_user(dst, src, count, max);
+       }
+       return -EFAULT;
+}
+EXPORT_SYMBOL(strncpy_from_user);
index d9b094ca7aaaed9305564228f6d68810d8b8afa1..ef2a6a5d78e39ddc71c2c51d90dc56f9cbcab9ef 100644 (file)
@@ -32,93 +32,6 @@ static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned lon
 #define movsl_is_ok(a1, a2, n) \
        __movsl_is_ok((unsigned long)(a1), (unsigned long)(a2), (n))
 
-/*
- * Copy a null terminated string from userspace.
- */
-
-#define __do_strncpy_from_user(dst, src, count, res)                      \
-do {                                                                      \
-       int __d0, __d1, __d2;                                              \
-       might_fault();                                                     \
-       __asm__ __volatile__(                                              \
-               "       testl %1,%1\n"                                     \
-               "       jz 2f\n"                                           \
-               "0:     lodsb\n"                                           \
-               "       stosb\n"                                           \
-               "       testb %%al,%%al\n"                                 \
-               "       jz 1f\n"                                           \
-               "       decl %1\n"                                         \
-               "       jnz 0b\n"                                          \
-               "1:     subl %1,%0\n"                                      \
-               "2:\n"                                                     \
-               ".section .fixup,\"ax\"\n"                                 \
-               "3:     movl %5,%0\n"                                      \
-               "       jmp 2b\n"                                          \
-               ".previous\n"                                              \
-               _ASM_EXTABLE(0b,3b)                                        \
-               : "=&d"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1),    \
-                 "=&D" (__d2)                                             \
-               : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
-               : "memory");                                               \
-} while (0)
-
-/**
- * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
- * @dst:   Destination address, in kernel space.  This buffer must be at
- *         least @count bytes long.
- * @src:   Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- * Caller must check the specified block with access_ok() before calling
- * this function.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-long
-__strncpy_from_user(char *dst, const char __user *src, long count)
-{
-       long res;
-       __do_strncpy_from_user(dst, src, count, res);
-       return res;
-}
-EXPORT_SYMBOL(__strncpy_from_user);
-
-/**
- * strncpy_from_user: - Copy a NUL terminated string from userspace.
- * @dst:   Destination address, in kernel space.  This buffer must be at
- *         least @count bytes long.
- * @src:   Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
-       long res = -EFAULT;
-       if (access_ok(VERIFY_READ, src, 1))
-               __do_strncpy_from_user(dst, src, count, res);
-       return res;
-}
-EXPORT_SYMBOL(strncpy_from_user);
-
 /*
  * Zero Userspace
  */
index b7c2849ffb66015ed114a5ab2015956aecd69d7b..0d0326f388c0bdf9778ec2157c6d39cae3ff5c12 100644 (file)
@@ -8,55 +8,6 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
-/*
- * Copy a null terminated string from userspace.
- */
-
-#define __do_strncpy_from_user(dst,src,count,res)                         \
-do {                                                                      \
-       long __d0, __d1, __d2;                                             \
-       might_fault();                                                     \
-       __asm__ __volatile__(                                              \
-               "       testq %1,%1\n"                                     \
-               "       jz 2f\n"                                           \
-               "0:     lodsb\n"                                           \
-               "       stosb\n"                                           \
-               "       testb %%al,%%al\n"                                 \
-               "       jz 1f\n"                                           \
-               "       decq %1\n"                                         \
-               "       jnz 0b\n"                                          \
-               "1:     subq %1,%0\n"                                      \
-               "2:\n"                                                     \
-               ".section .fixup,\"ax\"\n"                                 \
-               "3:     movq %5,%0\n"                                      \
-               "       jmp 2b\n"                                          \
-               ".previous\n"                                              \
-               _ASM_EXTABLE(0b,3b)                                        \
-               : "=&r"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1),    \
-                 "=&D" (__d2)                                             \
-               : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
-               : "memory");                                               \
-} while (0)
-
-long
-__strncpy_from_user(char *dst, const char __user *src, long count)
-{
-       long res;
-       __do_strncpy_from_user(dst, src, count, res);
-       return res;
-}
-EXPORT_SYMBOL(__strncpy_from_user);
-
-long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
-       long res = -EFAULT;
-       if (access_ok(VERIFY_READ, src, 1))
-               return __strncpy_from_user(dst, src, count);
-       return res;
-}
-EXPORT_SYMBOL(strncpy_from_user);
-
 /*
  * Zero Userspace
  */
index 66870223f8c5e001e7fc5bbe02b659c8778def86..877b9a1b21523183d06973b60a9beb2459fff895 100644 (file)
  * r9d : hlen = skb->len - skb->data_len
  */
 #define SKBDATA        %r8
-
-sk_load_word_ind:
-       .globl  sk_load_word_ind
-
-       add     %ebx,%esi       /* offset += X */
-#      test    %esi,%esi       /* if (offset < 0) goto bpf_error; */
-       js      bpf_error
+#define SKF_MAX_NEG_OFF    $(-0x200000) /* SKF_LL_OFF from filter.h */
 
 sk_load_word:
        .globl  sk_load_word
 
+       test    %esi,%esi
+       js      bpf_slow_path_word_neg
+
+sk_load_word_positive_offset:
+       .globl  sk_load_word_positive_offset
+
        mov     %r9d,%eax               # hlen
        sub     %esi,%eax               # hlen - offset
        cmp     $3,%eax
@@ -37,16 +37,15 @@ sk_load_word:
        bswap   %eax                    /* ntohl() */
        ret
 
-
-sk_load_half_ind:
-       .globl sk_load_half_ind
-
-       add     %ebx,%esi       /* offset += X */
-       js      bpf_error
-
 sk_load_half:
        .globl  sk_load_half
 
+       test    %esi,%esi
+       js      bpf_slow_path_half_neg
+
+sk_load_half_positive_offset:
+       .globl  sk_load_half_positive_offset
+
        mov     %r9d,%eax
        sub     %esi,%eax               #       hlen - offset
        cmp     $1,%eax
@@ -55,14 +54,15 @@ sk_load_half:
        rol     $8,%ax                  # ntohs()
        ret
 
-sk_load_byte_ind:
-       .globl sk_load_byte_ind
-       add     %ebx,%esi       /* offset += X */
-       js      bpf_error
-
 sk_load_byte:
        .globl  sk_load_byte
 
+       test    %esi,%esi
+       js      bpf_slow_path_byte_neg
+
+sk_load_byte_positive_offset:
+       .globl  sk_load_byte_positive_offset
+
        cmp     %esi,%r9d   /* if (offset >= hlen) goto bpf_slow_path_byte */
        jle     bpf_slow_path_byte
        movzbl  (SKBDATA,%rsi),%eax
@@ -73,25 +73,21 @@ sk_load_byte:
  *
  * Implements BPF_S_LDX_B_MSH : ldxb  4*([offset]&0xf)
  * Must preserve A accumulator (%eax)
- * Inputs : %esi is the offset value, already known positive
+ * Inputs : %esi is the offset value
  */
-ENTRY(sk_load_byte_msh)
-       CFI_STARTPROC
+sk_load_byte_msh:
+       .globl  sk_load_byte_msh
+       test    %esi,%esi
+       js      bpf_slow_path_byte_msh_neg
+
+sk_load_byte_msh_positive_offset:
+       .globl  sk_load_byte_msh_positive_offset
        cmp     %esi,%r9d      /* if (offset >= hlen) goto bpf_slow_path_byte_msh */
        jle     bpf_slow_path_byte_msh
        movzbl  (SKBDATA,%rsi),%ebx
        and     $15,%bl
        shl     $2,%bl
        ret
-       CFI_ENDPROC
-ENDPROC(sk_load_byte_msh)
-
-bpf_error:
-# force a return 0 from jit handler
-       xor             %eax,%eax
-       mov             -8(%rbp),%rbx
-       leaveq
-       ret
 
 /* rsi contains offset and can be scratched */
 #define bpf_slow_path_common(LEN)              \
@@ -138,3 +134,67 @@ bpf_slow_path_byte_msh:
        shl     $2,%al
        xchg    %eax,%ebx
        ret
+
+#define sk_negative_common(SIZE)                               \
+       push    %rdi;   /* save skb */                          \
+       push    %r9;                                            \
+       push    SKBDATA;                                        \
+/* rsi already has offset */                                   \
+       mov     $SIZE,%ecx;     /* size */                      \
+       call    bpf_internal_load_pointer_neg_helper;           \
+       test    %rax,%rax;                                      \
+       pop     SKBDATA;                                        \
+       pop     %r9;                                            \
+       pop     %rdi;                                           \
+       jz      bpf_error
+
+
+bpf_slow_path_word_neg:
+       cmp     SKF_MAX_NEG_OFF, %esi   /* test range */
+       jl      bpf_error       /* offset lower -> error  */
+sk_load_word_negative_offset:
+       .globl  sk_load_word_negative_offset
+       sk_negative_common(4)
+       mov     (%rax), %eax
+       bswap   %eax
+       ret
+
+bpf_slow_path_half_neg:
+       cmp     SKF_MAX_NEG_OFF, %esi
+       jl      bpf_error
+sk_load_half_negative_offset:
+       .globl  sk_load_half_negative_offset
+       sk_negative_common(2)
+       mov     (%rax),%ax
+       rol     $8,%ax
+       movzwl  %ax,%eax
+       ret
+
+bpf_slow_path_byte_neg:
+       cmp     SKF_MAX_NEG_OFF, %esi
+       jl      bpf_error
+sk_load_byte_negative_offset:
+       .globl  sk_load_byte_negative_offset
+       sk_negative_common(1)
+       movzbl  (%rax), %eax
+       ret
+
+bpf_slow_path_byte_msh_neg:
+       cmp     SKF_MAX_NEG_OFF, %esi
+       jl      bpf_error
+sk_load_byte_msh_negative_offset:
+       .globl  sk_load_byte_msh_negative_offset
+       xchg    %eax,%ebx /* dont lose A , X is about to be scratched */
+       sk_negative_common(1)
+       movzbl  (%rax),%eax
+       and     $15,%al
+       shl     $2,%al
+       xchg    %eax,%ebx
+       ret
+
+bpf_error:
+# force a return 0 from jit handler
+       xor             %eax,%eax
+       mov             -8(%rbp),%rbx
+       leaveq
+       ret
index 5671752f8d9cbccb2c5fb708bca8780883d56e19..0597f95b6da663af5a43d5f5effd0bdf0447fe4f 100644 (file)
@@ -30,7 +30,10 @@ int bpf_jit_enable __read_mostly;
  * assembly code in arch/x86/net/bpf_jit.S
  */
 extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
-extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[];
+extern u8 sk_load_word_positive_offset[], sk_load_half_positive_offset[];
+extern u8 sk_load_byte_positive_offset[], sk_load_byte_msh_positive_offset[];
+extern u8 sk_load_word_negative_offset[], sk_load_half_negative_offset[];
+extern u8 sk_load_byte_negative_offset[], sk_load_byte_msh_negative_offset[];
 
 static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
 {
@@ -117,6 +120,8 @@ static inline void bpf_flush_icache(void *start, void *end)
        set_fs(old_fs);
 }
 
+#define CHOOSE_LOAD_FUNC(K, func) \
+       ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
 
 void bpf_jit_compile(struct sk_filter *fp)
 {
@@ -289,7 +294,7 @@ void bpf_jit_compile(struct sk_filter *fp)
                                        EMIT2(0x24, K & 0xFF); /* and imm8,%al */
                                } else if (K >= 0xFFFF0000) {
                                        EMIT2(0x66, 0x25);      /* and imm16,%ax */
-                                       EMIT2(K, 2);
+                                       EMIT(K, 2);
                                } else {
                                        EMIT1_off32(0x25, K);   /* and imm32,%eax */
                                }
@@ -473,44 +478,46 @@ void bpf_jit_compile(struct sk_filter *fp)
 #endif
                                break;
                        case BPF_S_LD_W_ABS:
-                               func = sk_load_word;
+                               func = CHOOSE_LOAD_FUNC(K, sk_load_word);
 common_load:                   seen |= SEEN_DATAREF;
-                               if ((int)K < 0) {
-                                       /* Abort the JIT because __load_pointer() is needed. */
-                                       goto out;
-                               }
                                t_offset = func - (image + addrs[i]);
                                EMIT1_off32(0xbe, K); /* mov imm32,%esi */
                                EMIT1_off32(0xe8, t_offset); /* call */
                                break;
                        case BPF_S_LD_H_ABS:
-                               func = sk_load_half;
+                               func = CHOOSE_LOAD_FUNC(K, sk_load_half);
                                goto common_load;
                        case BPF_S_LD_B_ABS:
-                               func = sk_load_byte;
+                               func = CHOOSE_LOAD_FUNC(K, sk_load_byte);
                                goto common_load;
                        case BPF_S_LDX_B_MSH:
-                               if ((int)K < 0) {
-                                       /* Abort the JIT because __load_pointer() is needed. */
-                                       goto out;
-                               }
+                               func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh);
                                seen |= SEEN_DATAREF | SEEN_XREG;
-                               t_offset = sk_load_byte_msh - (image + addrs[i]);
+                               t_offset = func - (image + addrs[i]);
                                EMIT1_off32(0xbe, K);   /* mov imm32,%esi */
                                EMIT1_off32(0xe8, t_offset); /* call sk_load_byte_msh */
                                break;
                        case BPF_S_LD_W_IND:
-                               func = sk_load_word_ind;
+                               func = sk_load_word;
 common_load_ind:               seen |= SEEN_DATAREF | SEEN_XREG;
                                t_offset = func - (image + addrs[i]);
-                               EMIT1_off32(0xbe, K);   /* mov imm32,%esi   */
+                               if (K) {
+                                       if (is_imm8(K)) {
+                                               EMIT3(0x8d, 0x73, K); /* lea imm8(%rbx), %esi */
+                                       } else {
+                                               EMIT2(0x8d, 0xb3); /* lea imm32(%rbx),%esi */
+                                               EMIT(K, 4);
+                                       }
+                               } else {
+                                       EMIT2(0x89,0xde); /* mov %ebx,%esi */
+                               }
                                EMIT1_off32(0xe8, t_offset);    /* call sk_load_xxx_ind */
                                break;
                        case BPF_S_LD_H_IND:
-                               func = sk_load_half_ind;
+                               func = sk_load_half;
                                goto common_load_ind;
                        case BPF_S_LD_B_IND:
-                               func = sk_load_byte_ind;
+                               func = sk_load_byte;
                                goto common_load_ind;
                        case BPF_S_JMP_JA:
                                t_offset = addrs[i + K] - addrs[i];
index 66d377e334f7711d0d2c388afe485e52d932212d..646e3b5b4bb6af37766f0fa81625b7d7f876d4d2 100644 (file)
@@ -63,7 +63,7 @@ static struct gpio_led net5501_leds[] = {
                .name = "net5501:1",
                .gpio = 6,
                .default_trigger = "default-on",
-               .active_low = 1,
+               .active_low = 0,
        },
 };
 
index e0a37233c0af7ca57362d23b3aba75a4d8bca30e..e31bcd8f2eeef2af6d2db13b824864b74867767d 100644 (file)
@@ -805,7 +805,7 @@ void intel_scu_devices_create(void)
                } else
                        i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
        }
-       intel_scu_notifier_post(SCU_AVAILABLE, 0L);
+       intel_scu_notifier_post(SCU_AVAILABLE, NULL);
 }
 EXPORT_SYMBOL_GPL(intel_scu_devices_create);
 
@@ -814,7 +814,7 @@ void intel_scu_devices_destroy(void)
 {
        int i;
 
-       intel_scu_notifier_post(SCU_DOWN, 0L);
+       intel_scu_notifier_post(SCU_DOWN, NULL);
 
        for (i = 0; i < ipc_next_dev; i++)
                platform_device_del(ipc_devs[i]);
index 47936830968c5240497725557be336f6fed112c9..218cdb16163c3ae7026a40f95f06dd139a862db8 100644 (file)
@@ -225,13 +225,13 @@ static void __restore_processor_state(struct saved_context *ctxt)
        fix_processor_context();
 
        do_fpu_end();
+       x86_platform.restore_sched_clock_state();
        mtrr_bp_restore();
 }
 
 /* Needed by apm.c */
 void restore_processor_state(void)
 {
-       x86_platform.restore_sched_clock_state();
        __restore_processor_state(&saved_context);
 }
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/um/asm/barrier.h b/arch/x86/um/asm/barrier.h
new file mode 100644 (file)
index 0000000..7d01b8c
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef _ASM_UM_BARRIER_H_
+#define _ASM_UM_BARRIER_H_
+
+#include <asm/asm.h>
+#include <asm/segment.h>
+#include <asm/cpufeature.h>
+#include <asm/cmpxchg.h>
+#include <asm/nops.h>
+
+#include <linux/kernel.h>
+#include <linux/irqflags.h>
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+#ifdef CONFIG_X86_32
+
+#define mb()   alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+#define rmb()  alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+#define wmb()  alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+
+#else /* CONFIG_X86_32 */
+
+#define mb()   asm volatile("mfence" : : : "memory")
+#define rmb()  asm volatile("lfence" : : : "memory")
+#define wmb()  asm volatile("sfence" : : : "memory")
+
+#endif /* CONFIG_X86_32 */
+
+#define read_barrier_depends() do { } while (0)
+
+#ifdef CONFIG_SMP
+
+#define smp_mb()       mb()
+#ifdef CONFIG_X86_PPRO_FENCE
+#define smp_rmb()      rmb()
+#else /* CONFIG_X86_PPRO_FENCE */
+#define smp_rmb()      barrier()
+#endif /* CONFIG_X86_PPRO_FENCE */
+
+#ifdef CONFIG_X86_OOSTORE
+#define smp_wmb()      wmb()
+#else /* CONFIG_X86_OOSTORE */
+#define smp_wmb()      barrier()
+#endif /* CONFIG_X86_OOSTORE */
+
+#define smp_read_barrier_depends()     read_barrier_depends()
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+
+#else /* CONFIG_SMP */
+
+#define smp_mb()       barrier()
+#define smp_rmb()      barrier()
+#define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+
+#endif /* CONFIG_SMP */
+
+/*
+ * Stop RDTSC speculation. This is needed when you need to use RDTSC
+ * (or get_cycles or vread that possibly accesses the TSC) in a defined
+ * code region.
+ *
+ * (Could use an alternative three way for this if there was one.)
+ */
+static inline void rdtsc_barrier(void)
+{
+       alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+       alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+}
+
+#endif
diff --git a/arch/x86/um/asm/system.h b/arch/x86/um/asm/system.h
deleted file mode 100644 (file)
index a459fd9..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb()   asm volatile("mfence":::"memory")
-#define rmb()  asm volatile("lfence":::"memory")
-#define wmb()  asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     b = 2;
- *     memory_barrier();
- *     p = &b;                         q = p;
- *                                     read_barrier_depends();
- *                                     d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     a = 2;
- *     memory_barrier();
- *     b = 3;                          y = b;
- *                                     read_barrier_depends();
- *                                     x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb()     rmb()
-#else
-# define smp_rmb()     barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb()     wmb()
-#else
-# define smp_wmb()     barrier()
-#endif
-#define smp_read_barrier_depends()     read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
-       alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
-       alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-extern void *_switch_to(void *prev, void *next, void *last);
-#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
-
-#endif
index c5ffb6ac870773d53e15857dc50749ab661ffc1d..d5644bbe8cbac5de5432005d1d694ffc36112563 100644 (file)
@@ -9,24 +9,34 @@
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/vgaarb.h>
 
 int fb_is_primary_device(struct fb_info *info)
 {
        struct device *device = info->device;
        struct pci_dev *pci_dev = NULL;
+       struct pci_dev *default_device = vga_default_device();
        struct resource *res = NULL;
-       int retval = 0;
 
        if (device)
                pci_dev = to_pci_dev(device);
 
-       if (pci_dev)
-               res = &pci_dev->resource[PCI_ROM_RESOURCE];
+       if (!pci_dev)
+               return 0;
+
+       if (default_device) {
+               if (pci_dev == default_device)
+                       return 1;
+               else
+                       return 0;
+       }
+
+       res = &pci_dev->resource[PCI_ROM_RESOURCE];
 
        if (res && res->flags & IORESOURCE_ROM_SHADOW)
-               retval = 1;
+               return 1;
 
-       return retval;
+       return 0;
 }
 EXPORT_SYMBOL(fb_is_primary_device);
 MODULE_LICENSE("GPL");
index b132ade26f778f2cfec7c2d5c7b6db48afe424d5..a8f8844b8d32690b8a189bc37d12cd3f286a81cd 100644 (file)
@@ -261,7 +261,8 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
 
 static bool __init xen_check_mwait(void)
 {
-#ifdef CONFIG_ACPI
+#if defined(CONFIG_ACPI) && !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) && \
+       !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
        struct xen_platform_op op = {
                .cmd                    = XENPF_set_processor_pminfo,
                .u.set_pminfo.id        = -1,
@@ -349,7 +350,6 @@ static void __init xen_init_cpuid_mask(void)
        /* Xen will set CR4.OSXSAVE if supported and not disabled by force */
        if ((cx & xsave_mask) != xsave_mask)
                cpuid_leaf1_ecx_mask &= ~xsave_mask; /* disable XSAVE & OSXSAVE */
-
        if (xen_check_mwait())
                cpuid_leaf1_ecx_set_mask = (1 << (X86_FEATURE_MWAIT % 32));
 }
@@ -967,7 +967,7 @@ void xen_setup_shared_info(void)
        xen_setup_mfn_list_list();
 }
 
-/* This is called once we have the cpu_possible_map */
+/* This is called once we have the cpu_possible_mask */
 void xen_setup_vcpu_info_placement(void)
 {
        int cpu;
index 988828b479ed29660363f87adda4c6c62707441b..b8e279479a6b31984a7e715c52eec4283e38e007 100644 (file)
@@ -1859,6 +1859,7 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
 #endif /* CONFIG_X86_64 */
 
 static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss;
+static unsigned char fake_ioapic_mapping[PAGE_SIZE] __page_aligned_bss;
 
 static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
 {
@@ -1899,7 +1900,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
                 * We just don't map the IO APIC - all access is via
                 * hypercalls.  Keep the address in the pte for reference.
                 */
-               pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL);
+               pte = pfn_pte(PFN_DOWN(__pa(fake_ioapic_mapping)), PAGE_KERNEL);
                break;
 #endif
 
@@ -2064,6 +2065,7 @@ void __init xen_init_mmu_ops(void)
        pv_mmu_ops = xen_mmu_ops;
 
        memset(dummy_mapping, 0xff, PAGE_SIZE);
+       memset(fake_ioapic_mapping, 0xfd, PAGE_SIZE);
 }
 
 /* Protected by xen_reservation_lock. */
index b480d4207a4cb23e584c40b5147f35a24872b8f2..967633ad98c48b262cf7739c7cdcdb7b8d79641a 100644 (file)
@@ -12,8 +12,8 @@ int xen_swiotlb __read_mostly;
 
 static struct dma_map_ops xen_swiotlb_dma_ops = {
        .mapping_error = xen_swiotlb_dma_mapping_error,
-       .alloc_coherent = xen_swiotlb_alloc_coherent,
-       .free_coherent = xen_swiotlb_free_coherent,
+       .alloc = xen_swiotlb_alloc_coherent,
+       .free = xen_swiotlb_free_coherent,
        .sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu,
        .sync_single_for_device = xen_swiotlb_sync_single_for_device,
        .sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu,
index 02900e8ce26cecba1e02bab8d4f2fdb48888d823..0503c0c493a9a64bf44b41fb237831cb290203fc 100644 (file)
@@ -59,7 +59,7 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id)
 
 static void __cpuinit cpu_bringup(void)
 {
-       int cpu = smp_processor_id();
+       int cpu;
 
        cpu_init();
        touch_softlockup_watchdog();
@@ -178,6 +178,7 @@ static void __init xen_fill_possible_map(void)
 static void __init xen_filter_cpu_maps(void)
 {
        int i, rc;
+       unsigned int subtract = 0;
 
        if (!xen_initial_domain())
                return;
@@ -192,8 +193,22 @@ static void __init xen_filter_cpu_maps(void)
                } else {
                        set_cpu_possible(i, false);
                        set_cpu_present(i, false);
+                       subtract++;
                }
        }
+#ifdef CONFIG_HOTPLUG_CPU
+       /* This is akin to using 'nr_cpus' on the Linux command line.
+        * Which is OK as when we use 'dom0_max_vcpus=X' we can only
+        * have up to X, while nr_cpu_ids is greater than X. This
+        * normally is not a problem, except when CPU hotplugging
+        * is involved and then there might be more than X CPUs
+        * in the guest - which will not work as there is no
+        * hypercall to expand the max number of VCPUs an already
+        * running guest has. So cap it up to X. */
+       if (subtract)
+               nr_cpu_ids = nr_cpu_ids - subtract;
+#endif
+
 }
 
 static void __init xen_smp_prepare_boot_cpu(void)
index 79d7362ad6d1f0e0a6fab6aad37700e2a5dd038a..3e45aa000718aa2cd63d78f5c849e42666905d0e 100644 (file)
@@ -96,7 +96,7 @@ ENTRY(xen_restore_fl_direct)
 
        /* check for unmasked and pending */
        cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending
-       jz 1f
+       jnz 1f
 2:     call check_events
 1:
 ENDPATCH(xen_restore_fl_direct)
index 26664cef8f11dc990383fb62d7a5f8f6e4d1aac1..91695a135498cb45958881747f749bb48d98aab9 100644 (file)
@@ -11,9 +11,6 @@
 #ifndef _XTENSA_HARDIRQ_H
 #define _XTENSA_HARDIRQ_H
 
-void ack_bad_irq(unsigned int irq);
-#define ack_bad_irq ack_bad_irq
-
 #include <asm-generic/hardirq.h>
 
 #endif /* _XTENSA_HARDIRQ_H */
index d04cd3a625fa54906eda4e4339855c19aaecc5f5..4beb43c087d3dd6498daa296548c29b854701c5d 100644 (file)
@@ -14,6 +14,7 @@
 #ifdef __KERNEL__
 #include <asm/byteorder.h>
 #include <asm/page.h>
+#include <linux/bug.h>
 #include <linux/kernel.h>
 
 #include <linux/types.h>
index b69b000349fcdb20888a6e080cf8045ae82fc6b7..d78869a00b11c8a2a4584d26b6528dd98ff685c7 100644 (file)
@@ -496,6 +496,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
        if (signr > 0) {
+               int ret;
 
                /* Are we from a system call? */
 
index 3a78b00edd71cfb7b667d50c9d3fe3265a5dba28..1f61b74867e41d3f74f61aeec539e8b00157dacf 100644 (file)
@@ -483,7 +483,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
        if (!q)
                return NULL;
 
-       q->id = ida_simple_get(&blk_queue_ida, 0, 0, GFP_KERNEL);
+       q->id = ida_simple_get(&blk_queue_ida, 0, 0, gfp_mask);
        if (q->id < 0)
                goto fail_q;
 
@@ -1277,7 +1277,8 @@ static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,
        list_for_each_entry_reverse(rq, &plug->list, queuelist) {
                int el_ret;
 
-               (*request_count)++;
+               if (rq->q == q)
+                       (*request_count)++;
 
                if (rq->q != q || !blk_rq_merge_ok(rq, bio))
                        continue;
index 5eed6a76721d1d78e8105f4bbde30e41f20a66cd..f2ddb94626bd49df5e942591998d19ff8665a0eb 100644 (file)
@@ -1218,7 +1218,7 @@ void blk_throtl_drain(struct request_queue *q)
        struct bio_list bl;
        struct bio *bio;
 
-       WARN_ON_ONCE(!queue_is_locked(q));
+       queue_lockdep_assert_held(q);
 
        bio_list_init(&bl);
 
index 457295253566e97179daca0502c57c320962ed24..3c38536bd52c3e3a25f1b8152e40a6ebe5192d36 100644 (file)
@@ -295,6 +295,7 @@ struct cfq_data {
        unsigned int cfq_slice_idle;
        unsigned int cfq_group_idle;
        unsigned int cfq_latency;
+       unsigned int cfq_target_latency;
 
        /*
         * Fallback dummy cfqq for extreme OOM conditions
@@ -604,7 +605,7 @@ cfq_group_slice(struct cfq_data *cfqd, struct cfq_group *cfqg)
 {
        struct cfq_rb_root *st = &cfqd->grp_service_tree;
 
-       return cfq_target_latency * cfqg->weight / st->total_weight;
+       return cfqd->cfq_target_latency * cfqg->weight / st->total_weight;
 }
 
 static inline unsigned
@@ -2271,7 +2272,8 @@ new_workload:
                 * to have higher weight. A more accurate thing would be to
                 * calculate system wide asnc/sync ratio.
                 */
-               tmp = cfq_target_latency * cfqg_busy_async_queues(cfqd, cfqg);
+               tmp = cfqd->cfq_target_latency *
+                       cfqg_busy_async_queues(cfqd, cfqg);
                tmp = tmp/cfqd->busy_queues;
                slice = min_t(unsigned, slice, tmp);
 
@@ -3737,6 +3739,7 @@ static void *cfq_init_queue(struct request_queue *q)
        cfqd->cfq_back_penalty = cfq_back_penalty;
        cfqd->cfq_slice[0] = cfq_slice_async;
        cfqd->cfq_slice[1] = cfq_slice_sync;
+       cfqd->cfq_target_latency = cfq_target_latency;
        cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
        cfqd->cfq_slice_idle = cfq_slice_idle;
        cfqd->cfq_group_idle = cfq_group_idle;
@@ -3788,6 +3791,7 @@ SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
 SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
 SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
 SHOW_FUNCTION(cfq_low_latency_show, cfqd->cfq_latency, 0);
+SHOW_FUNCTION(cfq_target_latency_show, cfqd->cfq_target_latency, 1);
 #undef SHOW_FUNCTION
 
 #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)                        \
@@ -3821,6 +3825,7 @@ STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
 STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1,
                UINT_MAX, 0);
 STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0);
+STORE_FUNCTION(cfq_target_latency_store, &cfqd->cfq_target_latency, 1, UINT_MAX, 1);
 #undef STORE_FUNCTION
 
 #define CFQ_ATTR(name) \
@@ -3838,6 +3843,7 @@ static struct elv_fs_entry cfq_attrs[] = {
        CFQ_ATTR(slice_idle),
        CFQ_ATTR(group_idle),
        CFQ_ATTR(low_latency),
+       CFQ_ATTR(target_latency),
        __ATTR_NULL
 };
 
index 21ff9d015432e2e50737db0278ed7bea41ff601c..8e84225c096b6adfafcde59d08e066e5751af9c2 100644 (file)
@@ -627,7 +627,7 @@ config CRYPTO_BLOWFISH_COMMON
 
 config CRYPTO_BLOWFISH_X86_64
        tristate "Blowfish cipher algorithm (x86_64)"
-       depends on (X86 || UML_X86) && 64BIT
+       depends on X86 && 64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_BLOWFISH_COMMON
        help
@@ -657,7 +657,7 @@ config CRYPTO_CAMELLIA
 
 config CRYPTO_CAMELLIA_X86_64
        tristate "Camellia cipher algorithm (x86_64)"
-       depends on (X86 || UML_X86) && 64BIT
+       depends on X86 && 64BIT
        depends on CRYPTO
        select CRYPTO_ALGAPI
        select CRYPTO_LRW
@@ -893,7 +893,7 @@ config CRYPTO_TWOFISH_X86_64
 
 config CRYPTO_TWOFISH_X86_64_3WAY
        tristate "Twofish cipher algorithm (x86_64, 3-way parallel)"
-       depends on (X86 || UML_X86) && 64BIT
+       depends on X86 && 64BIT
        select CRYPTO_ALGAPI
        select CRYPTO_TWOFISH_COMMON
        select CRYPTO_TWOFISH_X86_64
index a0f768c1d9aa75fdb94a70dba711e175d8f66c9f..8d3a056ebeeaf250d5ec61f4fe0cba990001528c 100644 (file)
@@ -613,8 +613,7 @@ out:
        return err;
 }
 
-static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
-                                                u32 mask)
+struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask)
 {
        struct crypto_alg *alg;
 
@@ -652,6 +651,7 @@ static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
 
        return ERR_PTR(crypto_givcipher_default(alg, type, mask));
 }
+EXPORT_SYMBOL_GPL(crypto_lookup_skcipher);
 
 int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
                         u32 type, u32 mask)
index 04add3dca6fe44dfc242e89a36741c56786327fa..e4cb35159be43fe365ec569908f84732c5c67042 100644 (file)
@@ -470,8 +470,7 @@ out:
        return err;
 }
 
-static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
-                                            u32 mask)
+struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
 {
        struct crypto_alg *alg;
 
@@ -503,6 +502,7 @@ static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
 
        return ERR_PTR(crypto_nivaead_default(alg, type, mask));
 }
+EXPORT_SYMBOL_GPL(crypto_lookup_aead);
 
 int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
                     u32 type, u32 mask)
index f76e42bcc6e7f4c213eef714761ee34630fbc483..f1ea0a0641350cbd0f7628bc3e7edde4fc38972d 100644 (file)
 #include <linux/module.h>
 #include <linux/crypto.h>
 #include <linux/cryptouser.h>
+#include <linux/sched.h>
 #include <net/netlink.h>
 #include <linux/security.h>
 #include <net/net_namespace.h>
+#include <crypto/internal/aead.h>
+#include <crypto/internal/skcipher.h>
+
 #include "internal.h"
 
 DEFINE_MUTEX(crypto_cfg_mutex);
@@ -301,6 +305,60 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
        return crypto_unregister_instance(alg);
 }
 
+static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type,
+                                                  u32 mask)
+{
+       int err;
+       struct crypto_alg *alg;
+
+       type = crypto_skcipher_type(type);
+       mask = crypto_skcipher_mask(mask);
+
+       for (;;) {
+               alg = crypto_lookup_skcipher(name,  type, mask);
+               if (!IS_ERR(alg))
+                       return alg;
+
+               err = PTR_ERR(alg);
+               if (err != -EAGAIN)
+                       break;
+               if (signal_pending(current)) {
+                       err = -EINTR;
+                       break;
+               }
+       }
+
+       return ERR_PTR(err);
+}
+
+static struct crypto_alg *crypto_user_aead_alg(const char *name, u32 type,
+                                              u32 mask)
+{
+       int err;
+       struct crypto_alg *alg;
+
+       type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+       type |= CRYPTO_ALG_TYPE_AEAD;
+       mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+       mask |= CRYPTO_ALG_TYPE_MASK;
+
+       for (;;) {
+               alg = crypto_lookup_aead(name,  type, mask);
+               if (!IS_ERR(alg))
+                       return alg;
+
+               err = PTR_ERR(alg);
+               if (err != -EAGAIN)
+                       break;
+               if (signal_pending(current)) {
+                       err = -EINTR;
+                       break;
+               }
+       }
+
+       return ERR_PTR(err);
+}
+
 static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
                          struct nlattr **attrs)
 {
@@ -325,7 +383,19 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
        else
                name = p->cru_name;
 
-       alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+       switch (p->cru_type & p->cru_mask & CRYPTO_ALG_TYPE_MASK) {
+       case CRYPTO_ALG_TYPE_AEAD:
+               alg = crypto_user_aead_alg(name, p->cru_type, p->cru_mask);
+               break;
+       case CRYPTO_ALG_TYPE_GIVCIPHER:
+       case CRYPTO_ALG_TYPE_BLKCIPHER:
+       case CRYPTO_ALG_TYPE_ABLKCIPHER:
+               alg = crypto_user_skcipher_alg(name, p->cru_type, p->cru_mask);
+               break;
+       default:
+               alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+       }
+
        if (IS_ERR(alg))
                return PTR_ERR(alg);
 
@@ -387,12 +457,20 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
        if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
            (nlh->nlmsg_flags & NLM_F_DUMP))) {
+               struct crypto_alg *alg;
+               u16 dump_alloc = 0;
+
                if (link->dump == NULL)
                        return -EINVAL;
+
+               list_for_each_entry(alg, &crypto_alg_list, cra_list)
+                       dump_alloc += CRYPTO_REPORT_MAXSIZE;
+
                {
                        struct netlink_dump_control c = {
                                .dump = link->dump,
                                .done = link->done,
+                               .min_dump_alloc = dump_alloc,
                        };
                        return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
                }
index 29a89dad68b664b0dcfefdf29a19631904b21e3f..b2c99dc1c5e2f244bab9cf8fafcedb0860df67f6 100644 (file)
@@ -280,11 +280,11 @@ static int pcrypt_aead_init_tfm(struct crypto_tfm *tfm)
 
        ictx->tfm_count++;
 
-       cpu_index = ictx->tfm_count % cpumask_weight(cpu_active_mask);
+       cpu_index = ictx->tfm_count % cpumask_weight(cpu_online_mask);
 
-       ctx->cb_cpu = cpumask_first(cpu_active_mask);
+       ctx->cb_cpu = cpumask_first(cpu_online_mask);
        for (cpu = 0; cpu < cpu_index; cpu++)
-               ctx->cb_cpu = cpumask_next(ctx->cb_cpu, cpu_active_mask);
+               ctx->cb_cpu = cpumask_next(ctx->cb_cpu, cpu_online_mask);
 
        cipher = crypto_spawn_aead(crypto_instance_ctx(inst));
 
@@ -472,7 +472,7 @@ static int pcrypt_init_padata(struct padata_pcrypt *pcrypt,
                goto err_free_padata;
        }
 
-       cpumask_and(mask->mask, cpu_possible_mask, cpu_active_mask);
+       cpumask_and(mask->mask, cpu_possible_mask, cpu_online_mask);
        rcu_assign_pointer(pcrypt->cb_cpumask, mask);
 
        pcrypt->nblock.notifier_call = pcrypt_cpumask_change_notify;
index 107f6f7be5e139129a1666f1f20aa3a6967c1ef0..dd30f40af9f505152bbc620211fa37d109eae1d7 100644 (file)
@@ -174,7 +174,7 @@ sha512_update(struct shash_desc *desc, const u8 *data, unsigned int len)
        index = sctx->count[0] & 0x7f;
 
        /* Update number of bytes */
-       if (!(sctx->count[0] += len))
+       if ((sctx->count[0] += len) < len)
                sctx->count[1]++;
 
         part_len = 128 - index;
index 6f0459cb745b8ccf6f338fe4750258537dcefef6..d236aef7e59fff7b7bc255cea2a86ce0a40425c1 100644 (file)
@@ -50,6 +50,8 @@ source "drivers/i2c/Kconfig"
 
 source "drivers/spi/Kconfig"
 
+source "drivers/hsi/Kconfig"
+
 source "drivers/pps/Kconfig"
 
 source "drivers/ptp/Kconfig"
index 262b19d6b627a7541266f0f569f97197be06e906..95952c82bf16653e40aa46ef1eeaa2f4fe96f8fa 100644 (file)
@@ -53,6 +53,7 @@ obj-$(CONFIG_ATA)             += ata/
 obj-$(CONFIG_TARGET_CORE)      += target/
 obj-$(CONFIG_MTD)              += mtd/
 obj-$(CONFIG_SPI)              += spi/
+obj-y                          += hsi/
 obj-y                          += net/
 obj-$(CONFIG_ATM)              += atm/
 obj-$(CONFIG_FUSION)           += message/
index ab513a972c95b2376703ebee11cad903c7721ba6..a716fede4f25781d8e4e0633c21626ab03c83719 100644 (file)
@@ -74,7 +74,8 @@ acpi_status acpi_reset(void)
 
        /* Check if the reset register is supported */
 
-       if (!reset_reg->address) {
+       if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
+           !reset_reg->address) {
                return_ACPI_STATUS(AE_NOT_EXIST);
        }
 
index b258cab9061ced6765fc7dda2f81c70eb9511a83..7586544fddb41b9cc1761a294dc57f79245d6286 100644 (file)
@@ -27,12 +27,6 @@ MODULE_PARM_DESC(write_support, "Dangerous, reboot and removal of battery may "
 
 static struct dentry *acpi_ec_debugfs_dir;
 
-static int acpi_ec_open_io(struct inode *i, struct file *f)
-{
-       f->private_data = i->i_private;
-       return 0;
-}
-
 static ssize_t acpi_ec_read_io(struct file *f, char __user *buf,
                               size_t count, loff_t *off)
 {
@@ -95,7 +89,7 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
 
 static const struct file_operations acpi_ec_io_ops = {
        .owner = THIS_MODULE,
-       .open  = acpi_ec_open_io,
+       .open  = simple_open,
        .read  = acpi_ec_read_io,
        .write = acpi_ec_write_io,
        .llseek = default_llseek,
index ba14fb93c92946097bafc866e316c79234ab02f3..c3881b2eb8b2c5a0ac9b353aa7d7bdd699001ba0 100644 (file)
@@ -607,8 +607,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
 
        acpi_irq_handler = handler;
        acpi_irq_context = context;
-       if (request_threaded_irq(irq, NULL, acpi_irq, IRQF_SHARED, "acpi",
-                                acpi_irq)) {
+       if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
                printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
                acpi_irq_handler = NULL;
                return AE_NOT_ACQUIRED;
index 7049a7d27c4f8bbd80991be1a633616474c0e2f4..330bb4d75852a02b928d3ac4bed0168458115bfc 100644 (file)
@@ -631,7 +631,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
         * We know a device's inferred power state when all the resources
         * required for a given D-state are 'on'.
         */
-       for (i = ACPI_STATE_D0; i < ACPI_STATE_D3; i++) {
+       for (i = ACPI_STATE_D0; i < ACPI_STATE_D3_HOT; i++) {
                list = &device->power.states[i].resources;
                if (list->count < 1)
                        continue;
index b3447f63e46b4f77a7e5edc7dc3bd5d0a7b3d33c..f3decb30223fd1b376775310ae25dec63424f920 100644 (file)
@@ -786,7 +786,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
        while (1) {
 
                if (cx->entry_method == ACPI_CSTATE_HALT)
-                       halt();
+                       safe_halt();
                else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
                        inb(cx->address);
                        /* See comment in acpi_idle_do_entry() */
index c1d612435939a5d62abb832d1f620faeeac7dc20..a6c77e8b37bde54c266cae17d620c441a896e3b9 100644 (file)
@@ -23,7 +23,8 @@ void acpi_reboot(void)
        /* Is the reset register supported? The spec says we should be
         * checking the bit width and bit offset, but Windows ignores
         * these fields */
-       /* Ignore also acpi_gbl_FADT.flags.ACPI_FADT_RESET_REGISTER */
+       if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
+               return;
 
        reset_value = acpi_gbl_FADT.reset_value;
 
index 767e2dcb96169a9ef676b409b808ff823c280578..7417267e88fa9763617e0cc7e36fde6154ff4335 100644 (file)
@@ -869,7 +869,7 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
        /*
         * Enumerate supported power management states
         */
-       for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
+       for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
                struct acpi_device_power_state *ps = &device->power.states[i];
                char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };
 
@@ -884,21 +884,18 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
                                acpi_bus_add_power_resource(ps->resources.handles[j]);
                }
 
-               /* The exist of _PR3 indicates D3Cold support */
-               if (i == ACPI_STATE_D3) {
-                       status = acpi_get_handle(device->handle, object_name, &handle);
-                       if (ACPI_SUCCESS(status))
-                               device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
-               }
-
                /* Evaluate "_PSx" to see if we can do explicit sets */
                object_name[2] = 'S';
                status = acpi_get_handle(device->handle, object_name, &handle);
                if (ACPI_SUCCESS(status))
                        ps->flags.explicit_set = 1;
 
-               /* State is valid if we have some power control */
-               if (ps->resources.count || ps->flags.explicit_set)
+               /*
+                * State is valid if there are means to put the device into it.
+                * D3hot is only valid if _PR3 present.
+                */
+               if (ps->resources.count ||
+                   (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT))
                        ps->flags.valid = 1;
 
                ps->power = -1; /* Unknown - driver assigned */
index 1d661b5c3287fb4b5083a6636d13e48643da8d51..eb6fd233764bdeb7f28bc04626c23a1488db9af7 100644 (file)
 #include "internal.h"
 #include "sleep.h"
 
+u8 wake_sleep_flags = ACPI_NO_OPTIONAL_METHODS;
 static unsigned int gts, bfs;
-module_param(gts, uint, 0644);
-module_param(bfs, uint, 0644);
-MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
-MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
-
-static u8 wake_sleep_flags(void)
+static int set_param_wake_flag(const char *val, struct kernel_param *kp)
 {
-       u8 flags = ACPI_NO_OPTIONAL_METHODS;
+       int ret = param_set_int(val, kp);
 
-       if (gts)
-               flags |= ACPI_EXECUTE_GTS;
-       if (bfs)
-               flags |= ACPI_EXECUTE_BFS;
+       if (ret)
+               return ret;
 
-       return flags;
+       if (kp->arg == (const char *)&gts) {
+               if (gts)
+                       wake_sleep_flags |= ACPI_EXECUTE_GTS;
+               else
+                       wake_sleep_flags &= ~ACPI_EXECUTE_GTS;
+       }
+       if (kp->arg == (const char *)&bfs) {
+               if (bfs)
+                       wake_sleep_flags |= ACPI_EXECUTE_BFS;
+               else
+                       wake_sleep_flags &= ~ACPI_EXECUTE_BFS;
+       }
+       return ret;
 }
+module_param_call(gts, set_param_wake_flag, param_get_int, &gts, 0644);
+module_param_call(bfs, set_param_wake_flag, param_get_int, &bfs, 0644);
+MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
+MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
 
 static u8 sleep_states[ACPI_S_STATE_COUNT];
 
@@ -263,7 +273,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 {
        acpi_status status = AE_OK;
        u32 acpi_state = acpi_target_sleep_state;
-       u8 flags = wake_sleep_flags();
        int error;
 
        ACPI_FLUSH_CPU_CACHE();
@@ -271,7 +280,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
        switch (acpi_state) {
        case ACPI_STATE_S1:
                barrier();
-               status = acpi_enter_sleep_state(acpi_state, flags);
+               status = acpi_enter_sleep_state(acpi_state, wake_sleep_flags);
                break;
 
        case ACPI_STATE_S3:
@@ -286,7 +295,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
        acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
 
        /* Reprogram control registers and execute _BFS */
-       acpi_leave_sleep_state_prep(acpi_state, flags);
+       acpi_leave_sleep_state_prep(acpi_state, wake_sleep_flags);
 
        /* ACPI 3.0 specs (P62) says that it's the responsibility
         * of the OSPM to clear the status bit [ implying that the
@@ -550,30 +559,27 @@ static int acpi_hibernation_begin(void)
 
 static int acpi_hibernation_enter(void)
 {
-       u8 flags = wake_sleep_flags();
        acpi_status status = AE_OK;
 
        ACPI_FLUSH_CPU_CACHE();
 
        /* This shouldn't return.  If it returns, we have a problem */
-       status = acpi_enter_sleep_state(ACPI_STATE_S4, flags);
+       status = acpi_enter_sleep_state(ACPI_STATE_S4, wake_sleep_flags);
        /* Reprogram control registers and execute _BFS */
-       acpi_leave_sleep_state_prep(ACPI_STATE_S4, flags);
+       acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags);
 
        return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
 
 static void acpi_hibernation_leave(void)
 {
-       u8 flags = wake_sleep_flags();
-
        /*
         * If ACPI is not enabled by the BIOS and the boot kernel, we need to
         * enable it here.
         */
        acpi_enable();
        /* Reprogram control registers and execute _BFS */
-       acpi_leave_sleep_state_prep(ACPI_STATE_S4, flags);
+       acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags);
        /* Check the hardware signature */
        if (facs && s4_hardware_signature != facs->hardware_signature) {
                printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
@@ -828,12 +834,10 @@ static void acpi_power_off_prepare(void)
 
 static void acpi_power_off(void)
 {
-       u8 flags = wake_sleep_flags();
-
        /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
        printk(KERN_DEBUG "%s called\n", __func__);
        local_irq_disable();
-       acpi_enter_sleep_state(ACPI_STATE_S5, flags);
+       acpi_enter_sleep_state(ACPI_STATE_S5, wake_sleep_flags);
 }
 
 /*
index 01c2cf4efcdde81ba9ec012ec67a1660524c8b86..cc273226dbd014868ac68342d07225e0b095d6e1 100644 (file)
@@ -247,8 +247,7 @@ static int amba_pm_restore(struct device *dev)
 /*
  * Hooks to provide runtime PM of the pclk (bus clock).  It is safe to
  * enable/disable the bus clock at runtime PM suspend/resume as this
- * does not result in loss of context.  However, disabling vcore power
- * would do, so we leave that to the driver.
+ * does not result in loss of context.
  */
 static int amba_pm_runtime_suspend(struct device *dev)
 {
@@ -354,39 +353,6 @@ static void amba_put_disable_pclk(struct amba_device *pcdev)
        clk_put(pclk);
 }
 
-static int amba_get_enable_vcore(struct amba_device *pcdev)
-{
-       struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
-       int ret;
-
-       pcdev->vcore = vcore;
-
-       if (IS_ERR(vcore)) {
-               /* It is OK not to supply a vcore regulator */
-               if (PTR_ERR(vcore) == -ENODEV)
-                       return 0;
-               return PTR_ERR(vcore);
-       }
-
-       ret = regulator_enable(vcore);
-       if (ret) {
-               regulator_put(vcore);
-               pcdev->vcore = ERR_PTR(-ENODEV);
-       }
-
-       return ret;
-}
-
-static void amba_put_disable_vcore(struct amba_device *pcdev)
-{
-       struct regulator *vcore = pcdev->vcore;
-
-       if (!IS_ERR(vcore)) {
-               regulator_disable(vcore);
-               regulator_put(vcore);
-       }
-}
-
 /*
  * These are the device model conversion veneers; they convert the
  * device model structures to our more specific structures.
@@ -399,10 +365,6 @@ static int amba_probe(struct device *dev)
        int ret;
 
        do {
-               ret = amba_get_enable_vcore(pcdev);
-               if (ret)
-                       break;
-
                ret = amba_get_enable_pclk(pcdev);
                if (ret)
                        break;
@@ -420,7 +382,6 @@ static int amba_probe(struct device *dev)
                pm_runtime_put_noidle(dev);
 
                amba_put_disable_pclk(pcdev);
-               amba_put_disable_vcore(pcdev);
        } while (0);
 
        return ret;
@@ -442,7 +403,6 @@ static int amba_remove(struct device *dev)
        pm_runtime_put_noidle(dev);
 
        amba_put_disable_pclk(pcdev);
-       amba_put_disable_vcore(pcdev);
 
        return ret;
 }
index 79a1e9dd56d98abfc68155d46df733acbb3ee8e0..ebaf67e4b2bc7382f4c2cc6e985df47c9de26c52 100644 (file)
@@ -394,6 +394,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9128 */
        { PCI_DEVICE(0x1b4b, 0x9125),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
+       { PCI_DEVICE(0x1b4b, 0x917a),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
        { PCI_DEVICE(0x1b4b, 0x91a3),
          .driver_data = board_ahci_yes_fbs },
 
index 0c86c77764bc7dec9f4bb6a2605aebac70abd18d..9e419e1c200629f9a556d519a0a553996727a554 100644 (file)
@@ -280,6 +280,7 @@ static struct dev_pm_ops ahci_pm_ops = {
 
 static const struct of_device_id ahci_of_match[] = {
        { .compatible = "calxeda,hb-ahci", },
+       { .compatible = "snps,spear-ahci", },
        {},
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
index 68013f96729ffc624aad80342ec92af6768b89fa..7857e8fd0a3e56e007004492482b3e306d8ba089 100644 (file)
@@ -329,6 +329,8 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        /* SATA Controller IDE (Lynx Point) */
        { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (DH89xxCC) */
+       { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        { }     /* terminate list */
 };
 
index e0bda9ff89cda7a6d0271980bbd83fb1c89a9a42..23763a1ec570aa08149e23f65de1a7fb0087c860 100644 (file)
@@ -95,7 +95,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
 static void ata_dev_xfermask(struct ata_device *dev);
 static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
 
-unsigned int ata_print_id = 1;
+atomic_t ata_print_id = ATOMIC_INIT(0);
 
 struct ata_force_param {
        const char      *name;
@@ -6029,7 +6029,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 
        /* give ports names and add SCSI hosts */
        for (i = 0; i < host->n_ports; i++)
-               host->ports[i]->print_id = ata_print_id++;
+               host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
 
 
        /* Create associated sysfs transport objects  */
index c61316e9d2f7fe0aa45cf542093be2fd811eec05..d1fbd59ead167b50544749e40f711ba09e138083 100644 (file)
@@ -3501,7 +3501,8 @@ static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg
        u64 now = get_jiffies_64();
        int *trials = void_arg;
 
-       if (ent->timestamp < now - min(now, interval))
+       if ((ent->eflags & ATA_EFLAG_OLD_ER) ||
+           (ent->timestamp < now - min(now, interval)))
                return -1;
 
        (*trials)++;
index 1ee00c8b5b0495674c30237f2be672dee81ee928..22226350cd0c296b2849e59bc3f1b5e2927da9d2 100644 (file)
@@ -3399,7 +3399,8 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                 */
                shost->max_host_blocked = 1;
 
-               rc = scsi_add_host(ap->scsi_host, &ap->tdev);
+               rc = scsi_add_host_with_dma(ap->scsi_host,
+                                               &ap->tdev, ap->host->dev);
                if (rc)
                        goto err_add;
        }
@@ -3838,18 +3839,25 @@ void ata_sas_port_stop(struct ata_port *ap)
 }
 EXPORT_SYMBOL_GPL(ata_sas_port_stop);
 
-int ata_sas_async_port_init(struct ata_port *ap)
+/**
+ * ata_sas_async_probe - simply schedule probing and return
+ * @ap: Port to probe
+ *
+ * For batch scheduling of probe for sas attached ata devices, assumes
+ * the port has already been through ata_sas_port_init()
+ */
+void ata_sas_async_probe(struct ata_port *ap)
 {
-       int rc = ap->ops->port_start(ap);
-
-       if (!rc) {
-               ap->print_id = ata_print_id++;
-               __ata_port_probe(ap);
-       }
+       __ata_port_probe(ap);
+}
+EXPORT_SYMBOL_GPL(ata_sas_async_probe);
 
-       return rc;
+int ata_sas_sync_probe(struct ata_port *ap)
+{
+       return ata_port_probe(ap);
 }
-EXPORT_SYMBOL_GPL(ata_sas_async_port_init);
+EXPORT_SYMBOL_GPL(ata_sas_sync_probe);
+
 
 /**
  *     ata_sas_port_init - Initialize a SATA device
@@ -3866,12 +3874,10 @@ int ata_sas_port_init(struct ata_port *ap)
 {
        int rc = ap->ops->port_start(ap);
 
-       if (!rc) {
-               ap->print_id = ata_print_id++;
-               rc = ata_port_probe(ap);
-       }
-
-       return rc;
+       if (rc)
+               return rc;
+       ap->print_id = atomic_inc_return(&ata_print_id);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(ata_sas_port_init);
 
index 74aaee30e264ce1959c3807cb6a9e4c8bad27c95..c341904853770f7dad45e5cc4e1180f76111e322 100644 (file)
@@ -294,6 +294,7 @@ int ata_tport_add(struct device *parent,
        device_enable_async_suspend(dev);
        pm_runtime_set_active(dev);
        pm_runtime_enable(dev);
+       pm_runtime_forbid(dev);
 
        transport_add_device(dev);
        transport_configure_device(dev);
index 2e26fcaf635b211192238dcfea0d7eebdad5b25b..9d0fd0b7185224239030e51d42dbe83f27ebbafb 100644 (file)
@@ -53,7 +53,7 @@ enum {
        ATA_DNXFER_QUIET        = (1 << 31),
 };
 
-extern unsigned int ata_print_id;
+extern atomic_t ata_print_id;
 extern int atapi_passthru16;
 extern int libata_fua;
 extern int libata_noacpi;
index fc2db2a89a6bb27b5d58722814a8e6f3f41957d8..3239517f4d902952654212f0a462d646fbd94608 100644 (file)
@@ -943,9 +943,9 @@ static int arasan_cf_resume(struct device *dev)
 
        return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(arasan_cf_pm_ops, arasan_cf_suspend, arasan_cf_resume);
-#endif
 
 static struct platform_driver arasan_cf_driver = {
        .probe          = arasan_cf_probe,
@@ -953,9 +953,7 @@ static struct platform_driver arasan_cf_driver = {
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
-#ifdef CONFIG_PM
                .pm     = &arasan_cf_pm_ops,
-#endif
        },
 };
 
index 38950ea8398a9ebb05425a62b448578acfe172a1..7336d4a7ab317c091b7b991a1355a712f58023ab 100644 (file)
@@ -4025,7 +4025,8 @@ static int mv_platform_probe(struct platform_device *pdev)
        struct ata_host *host;
        struct mv_host_priv *hpriv;
        struct resource *res;
-       int n_ports, rc;
+       int n_ports = 0;
+       int rc;
 
        ata_print_version_once(&pdev->dev, DRV_VERSION);
 
index 6c9387d646ecccc0d9c8fa62f6f8ce54593894a9..5401814c874df066833c8b5c3ac2dc28e2842490 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
-#include <linux/kthread.h>
+#include <linux/workqueue.h>
 #include <linux/highmem.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 
 #define to_dev(obj) container_of(obj, struct device, kobj)
 
@@ -81,6 +82,11 @@ enum {
 
 static int loading_timeout = 60;       /* In seconds */
 
+static inline long firmware_loading_timeout(void)
+{
+       return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT;
+}
+
 /* fw_lock could be moved to 'struct firmware_priv' but since it is just
  * guarding for corner cases a global lock should be OK */
 static DEFINE_MUTEX(fw_lock);
@@ -440,13 +446,11 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
 {
        struct firmware_priv *fw_priv;
        struct device *f_dev;
-       int error;
 
        fw_priv = kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL);
        if (!fw_priv) {
                dev_err(device, "%s: kmalloc failed\n", __func__);
-               error = -ENOMEM;
-               goto err_out;
+               return ERR_PTR(-ENOMEM);
        }
 
        fw_priv->fw = firmware;
@@ -463,98 +467,80 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
        f_dev->parent = device;
        f_dev->class = &firmware_class;
 
-       dev_set_uevent_suppress(f_dev, true);
-
-       /* Need to pin this module until class device is destroyed */
-       __module_get(THIS_MODULE);
-
-       error = device_add(f_dev);
-       if (error) {
-               dev_err(device, "%s: device_register failed\n", __func__);
-               goto err_put_dev;
-       }
-
-       error = device_create_bin_file(f_dev, &firmware_attr_data);
-       if (error) {
-               dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__);
-               goto err_del_dev;
-       }
-
-       error = device_create_file(f_dev, &dev_attr_loading);
-       if (error) {
-               dev_err(device, "%s: device_create_file failed\n", __func__);
-               goto err_del_bin_attr;
-       }
-
-       if (uevent)
-               dev_set_uevent_suppress(f_dev, false);
-
        return fw_priv;
-
-err_del_bin_attr:
-       device_remove_bin_file(f_dev, &firmware_attr_data);
-err_del_dev:
-       device_del(f_dev);
-err_put_dev:
-       put_device(f_dev);
-err_out:
-       return ERR_PTR(error);
 }
 
-static void fw_destroy_instance(struct firmware_priv *fw_priv)
-{
-       struct device *f_dev = &fw_priv->dev;
-
-       device_remove_file(f_dev, &dev_attr_loading);
-       device_remove_bin_file(f_dev, &firmware_attr_data);
-       device_unregister(f_dev);
-}
-
-static int _request_firmware(const struct firmware **firmware_p,
-                            const char *name, struct device *device,
-                            bool uevent, bool nowait)
+static struct firmware_priv *
+_request_firmware_prepare(const struct firmware **firmware_p, const char *name,
+                         struct device *device, bool uevent, bool nowait)
 {
-       struct firmware_priv *fw_priv;
        struct firmware *firmware;
-       int retval = 0;
+       struct firmware_priv *fw_priv;
 
        if (!firmware_p)
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
 
        *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
        if (!firmware) {
                dev_err(device, "%s: kmalloc(struct firmware) failed\n",
                        __func__);
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
        }
 
        if (fw_get_builtin_firmware(firmware, name)) {
                dev_dbg(device, "firmware: using built-in firmware %s\n", name);
-               return 0;
+               return NULL;
+       }
+
+       fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
+       if (IS_ERR(fw_priv)) {
+               release_firmware(firmware);
+               *firmware_p = NULL;
        }
+       return fw_priv;
+}
 
-       read_lock_usermodehelper();
+static void _request_firmware_cleanup(const struct firmware **firmware_p)
+{
+       release_firmware(*firmware_p);
+       *firmware_p = NULL;
+}
 
-       if (WARN_ON(usermodehelper_is_disabled())) {
-               dev_err(device, "firmware: %s will not be loaded\n", name);
-               retval = -EBUSY;
-               goto out;
+static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
+                                 long timeout)
+{
+       int retval = 0;
+       struct device *f_dev = &fw_priv->dev;
+
+       dev_set_uevent_suppress(f_dev, true);
+
+       /* Need to pin this module until class device is destroyed */
+       __module_get(THIS_MODULE);
+
+       retval = device_add(f_dev);
+       if (retval) {
+               dev_err(f_dev, "%s: device_register failed\n", __func__);
+               goto err_put_dev;
        }
 
-       if (uevent)
-               dev_dbg(device, "firmware: requesting %s\n", name);
+       retval = device_create_bin_file(f_dev, &firmware_attr_data);
+       if (retval) {
+               dev_err(f_dev, "%s: sysfs_create_bin_file failed\n", __func__);
+               goto err_del_dev;
+       }
 
-       fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
-       if (IS_ERR(fw_priv)) {
-               retval = PTR_ERR(fw_priv);
-               goto out;
+       retval = device_create_file(f_dev, &dev_attr_loading);
+       if (retval) {
+               dev_err(f_dev, "%s: device_create_file failed\n", __func__);
+               goto err_del_bin_attr;
        }
 
        if (uevent) {
-               if (loading_timeout > 0)
+               dev_set_uevent_suppress(f_dev, false);
+               dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_id);
+               if (timeout != MAX_SCHEDULE_TIMEOUT)
                        mod_timer(&fw_priv->timeout,
-                                 round_jiffies_up(jiffies +
-                                                  loading_timeout * HZ));
+                                 round_jiffies_up(jiffies + timeout));
 
                kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
        }
@@ -570,16 +556,13 @@ static int _request_firmware(const struct firmware **firmware_p,
        fw_priv->fw = NULL;
        mutex_unlock(&fw_lock);
 
-       fw_destroy_instance(fw_priv);
-
-out:
-       read_unlock_usermodehelper();
-
-       if (retval) {
-               release_firmware(firmware);
-               *firmware_p = NULL;
-       }
-
+       device_remove_file(f_dev, &dev_attr_loading);
+err_del_bin_attr:
+       device_remove_bin_file(f_dev, &firmware_attr_data);
+err_del_dev:
+       device_del(f_dev);
+err_put_dev:
+       put_device(f_dev);
        return retval;
 }
 
@@ -602,7 +585,26 @@ int
 request_firmware(const struct firmware **firmware_p, const char *name,
                  struct device *device)
 {
-        return _request_firmware(firmware_p, name, device, true, false);
+       struct firmware_priv *fw_priv;
+       int ret;
+
+       fw_priv = _request_firmware_prepare(firmware_p, name, device, true,
+                                           false);
+       if (IS_ERR_OR_NULL(fw_priv))
+               return PTR_RET(fw_priv);
+
+       ret = usermodehelper_read_trylock();
+       if (WARN_ON(ret)) {
+               dev_err(device, "firmware: %s will not be loaded\n", name);
+       } else {
+               ret = _request_firmware_load(fw_priv, true,
+                                       firmware_loading_timeout());
+               usermodehelper_read_unlock();
+       }
+       if (ret)
+               _request_firmware_cleanup(firmware_p);
+
+       return ret;
 }
 
 /**
@@ -629,25 +631,39 @@ struct firmware_work {
        bool uevent;
 };
 
-static int request_firmware_work_func(void *arg)
+static void request_firmware_work_func(struct work_struct *work)
 {
-       struct firmware_work *fw_work = arg;
+       struct firmware_work *fw_work;
        const struct firmware *fw;
+       struct firmware_priv *fw_priv;
+       long timeout;
        int ret;
 
-       if (!arg) {
-               WARN_ON(1);
-               return 0;
+       fw_work = container_of(work, struct firmware_work, work);
+       fw_priv = _request_firmware_prepare(&fw, fw_work->name, fw_work->device,
+                       fw_work->uevent, true);
+       if (IS_ERR_OR_NULL(fw_priv)) {
+               ret = PTR_RET(fw_priv);
+               goto out;
+       }
+
+       timeout = usermodehelper_read_lock_wait(firmware_loading_timeout());
+       if (timeout) {
+               ret = _request_firmware_load(fw_priv, fw_work->uevent, timeout);
+               usermodehelper_read_unlock();
+       } else {
+               dev_dbg(fw_work->device, "firmware: %s loading timed out\n",
+                       fw_work->name);
+               ret = -EAGAIN;
        }
+       if (ret)
+               _request_firmware_cleanup(&fw);
 
-       ret = _request_firmware(&fw, fw_work->name, fw_work->device,
-                               fw_work->uevent, true);
+ out:
        fw_work->cont(fw, fw_work->context);
 
        module_put(fw_work->module);
        kfree(fw_work);
-
-       return ret;
 }
 
 /**
@@ -673,7 +689,6 @@ request_firmware_nowait(
        const char *name, struct device *device, gfp_t gfp, void *context,
        void (*cont)(const struct firmware *fw, void *context))
 {
-       struct task_struct *task;
        struct firmware_work *fw_work;
 
        fw_work = kzalloc(sizeof (struct firmware_work), gfp);
@@ -692,15 +707,8 @@ request_firmware_nowait(
                return -EFAULT;
        }
 
-       task = kthread_run(request_firmware_work_func, fw_work,
-                           "firmware/%s", name);
-       if (IS_ERR(task)) {
-               fw_work->cont(NULL, fw_work->context);
-               module_put(fw_work->module);
-               kfree(fw_work);
-               return PTR_ERR(task);
-       }
-
+       INIT_WORK(&fw_work->work, request_firmware_work_func);
+       schedule_work(&fw_work->work);
        return 0;
 }
 
index 541f821d4ea68b163a15543159ac4cfee90f2aa7..bd0f3949bcf920a50c3a1baf586f620b4ef88394 100644 (file)
@@ -532,6 +532,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
        dev->power.suspend_time = ktime_set(0, 0);
        dev->power.max_time_suspended_ns = -1;
        dev->power.deferred_resume = false;
+       wake_up_all(&dev->power.wait_queue);
+
        if (retval == -EAGAIN || retval == -EBUSY) {
                dev->power.runtime_error = 0;
 
@@ -547,7 +549,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
        } else {
                pm_runtime_cancel_pending(dev);
        }
-       wake_up_all(&dev->power.wait_queue);
        goto out;
 }
 
index 5157fa04c2f0e04e6120878a97764d4375d52769..92b779ee002bba20b6af60953aa2132526380c4e 100644 (file)
@@ -138,6 +138,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
        unsigned int base, top;
        int nodes = 0;
        int registers = 0;
+       int average;
 
        mutex_lock(&map->lock);
 
@@ -152,8 +153,13 @@ static int rbtree_show(struct seq_file *s, void *ignored)
                registers += top - base + 1;
        }
 
+       if (nodes)
+               average = registers / nodes;
+       else
+               average = 0;
+
        seq_printf(s, "%d nodes, %d registers, average %d registers\n",
-                  nodes, registers, registers / nodes);
+                  nodes, registers, average);
 
        mutex_unlock(&map->lock);
 
@@ -396,7 +402,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
                                                           map->cache_word_size);
 
                        /* Is this the hardware default?  If so skip. */
-                       ret = regcache_lookup_reg(map, i);
+                       ret = regcache_lookup_reg(map, regtmp);
                        if (ret >= 0 && val == map->reg_defaults[ret].def)
                                continue;
 
index 87f54dbf601b90adf01e602ec200e5f967472d66..74b69095def6def7129d77a142936e7b751705d1 100644 (file)
@@ -346,6 +346,7 @@ out:
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(regcache_sync_region);
 
 /**
  * regcache_cache_only: Put a register map into cache only mode
index 58517a5dac1360b96b0779c0724d12e926d11c77..251eb70f83e7c0f626f6fd73ba86ec40e76d339f 100644 (file)
@@ -27,12 +27,6 @@ static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
        return strlen(buf);
 }
 
-static int regmap_open_file(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t regmap_name_read_file(struct file *file,
                                     char __user *user_buf, size_t count,
                                     loff_t *ppos)
@@ -57,7 +51,7 @@ static ssize_t regmap_name_read_file(struct file *file,
 }
 
 static const struct file_operations regmap_name_fops = {
-       .open = regmap_open_file,
+       .open = simple_open,
        .read = regmap_name_read_file,
        .llseek = default_llseek,
 };
@@ -174,7 +168,7 @@ static ssize_t regmap_map_write_file(struct file *file,
 #endif
 
 static const struct file_operations regmap_map_fops = {
-       .open = regmap_open_file,
+       .open = simple_open,
        .read = regmap_map_read_file,
        .write = regmap_map_write_file,
        .llseek = default_llseek,
@@ -243,7 +237,7 @@ out:
 }
 
 static const struct file_operations regmap_access_fops = {
-       .open = regmap_open_file,
+       .open = simple_open,
        .read = regmap_access_read_file,
        .llseek = default_llseek,
 };
index 05f150382da86fa70dd161067b26bdf59d33fc94..ba29b2e73d48936ab9a93a028abd0b0d9cd29691 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/sys_soc.h>
 #include <linux/err.h>
 
-static DEFINE_IDR(soc_ida);
+static DEFINE_IDA(soc_ida);
 static DEFINE_SPINLOCK(soc_lock);
 
 static ssize_t soc_info_get(struct device *dev,
@@ -168,8 +168,6 @@ void soc_device_unregister(struct soc_device *soc_dev)
 
 static int __init soc_bus_register(void)
 {
-       spin_lock_init(&soc_lock);
-
        return bus_register(&soc_bus_type);
 }
 core_initcall(soc_bus_register);
index c1172dafdffac1c7688155dc20a658628c6934ca..fb7c80fb721e2466d405deedc367967179ea1d80 100644 (file)
@@ -29,7 +29,7 @@ config BCMA_HOST_PCI
 
 config BCMA_DRIVER_PCI_HOSTMODE
        bool "Driver for PCI core working in hostmode"
-       depends on BCMA && MIPS
+       depends on BCMA && MIPS && BCMA_HOST_PCI
        help
          PCI core hostmode operation (external PCI bus).
 
index 4e20bcfa7ec5d3e62bdf34004601c2edca813ddc..d2097a11c3c7ae259f7e18dd4b5ff934c5ee85a9 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include "bcma_private.h"
+#include <linux/pci.h>
 #include <linux/export.h>
 #include <linux/bcma/bcma.h>
 #include <asm/paccess.h>
index cdcf75c0954febe06c4ac04f030568470284c160..3e2a6002aae6d8ed588de7d33838f9df024798b5 100644 (file)
@@ -404,16 +404,19 @@ int bcma_sprom_get(struct bcma_bus *bus)
                return -EOPNOTSUPP;
 
        if (!bcma_sprom_ext_available(bus)) {
+               bool sprom_onchip;
+
                /*
                 * External SPROM takes precedence so check
                 * on-chip OTP only when no external SPROM
                 * is present.
                 */
-               if (bcma_sprom_onchip_available(bus)) {
+               sprom_onchip = bcma_sprom_onchip_available(bus);
+               if (sprom_onchip) {
                        /* determine offset */
                        offset = bcma_sprom_onchip_offset(bus);
                }
-               if (!offset) {
+               if (!offset || !sprom_onchip) {
                        /*
                         * Maybe there is no SPROM on the device?
                         * Now we ask the arch code if there is some sprom
index e820b68d2f6cd4d74382b85b5e020069294f00f3..acda773b3720878495d14f5ebfbe1a82f50c0f74 100644 (file)
@@ -866,6 +866,7 @@ cciss_scsi_detect(ctlr_info_t *h)
        sh->can_queue = cciss_tape_cmds;
        sh->sg_tablesize = h->maxsgentries;
        sh->max_cmd_len = MAX_COMMAND_SIZE;
+       sh->max_sectors = h->cciss_max_sectors;
 
        ((struct cciss_scsi_adapter_data_t *) 
                h->scsi_ctlr)->scsi_host = sh;
@@ -1410,7 +1411,7 @@ static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c,
        /* track how many SG entries we are using */
        if (request_nsgs > h->maxSG)
                h->maxSG = request_nsgs;
-       c->Header.SGTotal = (__u8) request_nsgs + chained;
+       c->Header.SGTotal = (u16) request_nsgs + chained;
        if (request_nsgs > h->max_cmd_sgentries)
                c->Header.SGList = h->max_cmd_sgentries;
        else
index 76a08236430a0f1d2e6ca02ad347433115d7145e..b0b00d70c1669d6ef05993deb313dc516a23d552 100644 (file)
@@ -1030,37 +1030,6 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
        return 0;
 }
 
-static DEFINE_SPINLOCK(floppy_hlt_lock);
-static int hlt_disabled;
-static void floppy_disable_hlt(void)
-{
-       unsigned long flags;
-
-       WARN_ONCE(1, "floppy_disable_hlt() scheduled for removal in 2012");
-       spin_lock_irqsave(&floppy_hlt_lock, flags);
-       if (!hlt_disabled) {
-               hlt_disabled = 1;
-#ifdef HAVE_DISABLE_HLT
-               disable_hlt();
-#endif
-       }
-       spin_unlock_irqrestore(&floppy_hlt_lock, flags);
-}
-
-static void floppy_enable_hlt(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&floppy_hlt_lock, flags);
-       if (hlt_disabled) {
-               hlt_disabled = 0;
-#ifdef HAVE_DISABLE_HLT
-               enable_hlt();
-#endif
-       }
-       spin_unlock_irqrestore(&floppy_hlt_lock, flags);
-}
-
 static void setup_DMA(void)
 {
        unsigned long f;
@@ -1105,7 +1074,6 @@ static void setup_DMA(void)
        fd_enable_dma();
        release_dma_lock(f);
 #endif
-       floppy_disable_hlt();
 }
 
 static void show_floppy(void);
@@ -1707,7 +1675,6 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id)
        fd_disable_dma();
        release_dma_lock(f);
 
-       floppy_enable_hlt();
        do_floppy = NULL;
        if (fdc >= N_FDC || FDCS->address == -1) {
                /* we don't even know which FDC is the culprit */
@@ -1856,8 +1823,6 @@ static void floppy_shutdown(unsigned long data)
                show_floppy();
        cancel_activity();
 
-       floppy_enable_hlt();
-
        flags = claim_dma_lock();
        fd_disable_dma();
        release_dma_lock(flags);
@@ -4508,7 +4473,6 @@ static void floppy_release_irq_and_dma(void)
 #if N_FDC > 1
        set_dor(1, ~8, 0);
 #endif
-       floppy_enable_hlt();
 
        if (floppy_track_buffer && max_buffer_sectors) {
                tmpsize = max_buffer_sectors * 1024;
index b5dd14e072f2859a1c81fc036ffafd2146cc754a..0ba837fc62a874511a910dd077feea2f26dfbd37 100644 (file)
@@ -4,6 +4,6 @@
 
 config BLK_DEV_PCIESSD_MTIP32XX
        tristate "Block Device Driver for Micron PCIe SSDs"
-       depends on HOTPLUG_PCI_PCIE
+       depends on PCI
        help
           This enables the block driver for Micron PCIe SSDs.
index 8eb81c96608fbc47aadc382015a0e44db2b4599a..00f9fc992090099e72e8f753ab9d58fe47154b46 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/idr.h>
 #include <linux/kthread.h>
 #include <../drivers/ata/ahci.h>
+#include <linux/export.h>
 #include "mtip32xx.h"
 
 #define HW_CMD_SLOT_SZ         (MTIP_MAX_COMMAND_SLOTS * 32)
@@ -44,6 +45,7 @@
 #define HW_PORT_PRIV_DMA_SZ \
                (HW_CMD_SLOT_SZ + HW_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ)
 
+#define HOST_CAP_NZDMA         (1 << 19)
 #define HOST_HSORG             0xFC
 #define HSORG_DISABLE_SLOTGRP_INTR (1<<24)
 #define HSORG_DISABLE_SLOTGRP_PXIS (1<<16)
@@ -139,6 +141,12 @@ static void mtip_command_cleanup(struct driver_data *dd)
        int group = 0, commandslot = 0, commandindex = 0;
        struct mtip_cmd *command;
        struct mtip_port *port = dd->port;
+       static int in_progress;
+
+       if (in_progress)
+               return;
+
+       in_progress = 1;
 
        for (group = 0; group < 4; group++) {
                for (commandslot = 0; commandslot < 32; commandslot++) {
@@ -165,7 +173,8 @@ static void mtip_command_cleanup(struct driver_data *dd)
 
        up(&port->cmd_slot);
 
-       atomic_set(&dd->drv_cleanup_done, true);
+       set_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag);
+       in_progress = 0;
 }
 
 /*
@@ -262,6 +271,9 @@ static int hba_reset_nosleep(struct driver_data *dd)
                 && time_before(jiffies, timeout))
                mdelay(1);
 
+       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
+               return -1;
+
        if (readl(dd->mmio + HOST_CTL) & HOST_RESET)
                return -1;
 
@@ -294,6 +306,10 @@ static inline void mtip_issue_ncq_command(struct mtip_port *port, int tag)
                        port->cmd_issue[MTIP_TAG_INDEX(tag)]);
 
        spin_unlock_irqrestore(&port->cmd_issue_lock, flags);
+
+       /* Set the command's timeout value.*/
+       port->commands[tag].comp_time = jiffies + msecs_to_jiffies(
+                                       MTIP_NCQ_COMMAND_TIMEOUT_MS);
 }
 
 /*
@@ -420,7 +436,12 @@ static void mtip_init_port(struct mtip_port *port)
                writel(0xFFFFFFFF, port->completed[i]);
 
        /* Clear any pending interrupts for this port */
-       writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT);
+       writel(readl(port->dd->mmio + PORT_IRQ_STAT),
+                                       port->dd->mmio + PORT_IRQ_STAT);
+
+       /* Clear any pending interrupts on the HBA. */
+       writel(readl(port->dd->mmio + HOST_IRQ_STAT),
+                                       port->dd->mmio + HOST_IRQ_STAT);
 
        /* Enable port interrupts */
        writel(DEF_PORT_IRQ, port->mmio + PORT_IRQ_MASK);
@@ -447,6 +468,9 @@ static void mtip_restart_port(struct mtip_port *port)
                 && time_before(jiffies, timeout))
                ;
 
+       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+               return;
+
        /*
         * Chip quirk: escalate to hba reset if
         * PxCMD.CR not clear after 500 ms
@@ -475,6 +499,9 @@ static void mtip_restart_port(struct mtip_port *port)
        while (time_before(jiffies, timeout))
                ;
 
+       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+               return;
+
        /* Clear PxSCTL.DET */
        writel(readl(port->mmio + PORT_SCR_CTL) & ~1,
                         port->mmio + PORT_SCR_CTL);
@@ -486,15 +513,35 @@ static void mtip_restart_port(struct mtip_port *port)
                         && time_before(jiffies, timeout))
                ;
 
+       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+               return;
+
        if ((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0)
                dev_warn(&port->dd->pdev->dev,
                        "COM reset failed\n");
 
-       /* Clear SError, the PxSERR.DIAG.x should be set so clear it */
-       writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR);
+       mtip_init_port(port);
+       mtip_start_port(port);
 
-       /* Enable the DMA engine */
-       mtip_enable_engine(port, 1);
+}
+
+/*
+ * Helper function for tag logging
+ */
+static void print_tags(struct driver_data *dd,
+                       char *msg,
+                       unsigned long *tagbits,
+                       int cnt)
+{
+       unsigned char tagmap[128];
+       int group, tagmap_len = 0;
+
+       memset(tagmap, 0, sizeof(tagmap));
+       for (group = SLOTBITS_IN_LONGS; group > 0; group--)
+               tagmap_len = sprintf(tagmap + tagmap_len, "%016lX ",
+                                               tagbits[group-1]);
+       dev_warn(&dd->pdev->dev,
+                       "%d command(s) %s: tagmap [%s]", cnt, msg, tagmap);
 }
 
 /*
@@ -514,15 +561,18 @@ static void mtip_timeout_function(unsigned long int data)
        int tag, cmdto_cnt = 0;
        unsigned int bit, group;
        unsigned int num_command_slots = port->dd->slot_groups * 32;
+       unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
 
        if (unlikely(!port))
                return;
 
-       if (atomic_read(&port->dd->resumeflag) == true) {
+       if (test_bit(MTIP_DDF_RESUME_BIT, &port->dd->dd_flag)) {
                mod_timer(&port->cmd_timer,
                        jiffies + msecs_to_jiffies(30000));
                return;
        }
+       /* clear the tag accumulator */
+       memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
 
        for (tag = 0; tag < num_command_slots; tag++) {
                /*
@@ -540,12 +590,10 @@ static void mtip_timeout_function(unsigned long int data)
                        command = &port->commands[tag];
                        fis = (struct host_to_dev_fis *) command->command;
 
-                       dev_warn(&port->dd->pdev->dev,
-                               "Timeout for command tag %d\n", tag);
-
+                       set_bit(tag, tagaccum);
                        cmdto_cnt++;
                        if (cmdto_cnt == 1)
-                               set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+                               set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
 
                        /*
                         * Clear the completed bit. This should prevent
@@ -578,15 +626,29 @@ static void mtip_timeout_function(unsigned long int data)
                }
        }
 
-       if (cmdto_cnt) {
-               dev_warn(&port->dd->pdev->dev,
-                       "%d commands timed out: restarting port",
-                       cmdto_cnt);
+       if (cmdto_cnt && !test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+               print_tags(port->dd, "timed out", tagaccum, cmdto_cnt);
+
                mtip_restart_port(port);
-               clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+               clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
                wake_up_interruptible(&port->svc_wait);
        }
 
+       if (port->ic_pause_timer) {
+               to  = port->ic_pause_timer + msecs_to_jiffies(1000);
+               if (time_after(jiffies, to)) {
+                       if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+                               port->ic_pause_timer = 0;
+                               clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+                               clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
+                               clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
+                               wake_up_interruptible(&port->svc_wait);
+                       }
+
+
+               }
+       }
+
        /* Restart the timer */
        mod_timer(&port->cmd_timer,
                jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
@@ -681,23 +743,18 @@ static void mtip_completion(struct mtip_port *port,
        complete(waiting);
 }
 
-/*
- * Helper function for tag logging
- */
-static void print_tags(struct driver_data *dd,
-                       char *msg,
-                       unsigned long *tagbits)
+static void mtip_null_completion(struct mtip_port *port,
+                           int tag,
+                           void *data,
+                           int status)
 {
-       unsigned int tag, count = 0;
-
-       for (tag = 0; tag < (dd->slot_groups) * 32; tag++) {
-               if (test_bit(tag, tagbits))
-                       count++;
-       }
-       if (count)
-               dev_info(&dd->pdev->dev, "%s [%i tags]\n", msg, count);
+       return;
 }
 
+static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer,
+                               dma_addr_t buffer_dma, unsigned int sectors);
+static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
+                                               struct smart_attr *attrib);
 /*
  * Handle an error.
  *
@@ -708,12 +765,16 @@ static void print_tags(struct driver_data *dd,
  */
 static void mtip_handle_tfe(struct driver_data *dd)
 {
-       int group, tag, bit, reissue;
+       int group, tag, bit, reissue, rv;
        struct mtip_port *port;
-       struct mtip_cmd  *command;
+       struct mtip_cmd  *cmd;
        u32 completed;
        struct host_to_dev_fis *fis;
        unsigned long tagaccum[SLOTBITS_IN_LONGS];
+       unsigned int cmd_cnt = 0;
+       unsigned char *buf;
+       char *fail_reason = NULL;
+       int fail_all_ncq_write = 0, fail_all_ncq_cmds = 0;
 
        dev_warn(&dd->pdev->dev, "Taskfile error\n");
 
@@ -722,8 +783,11 @@ static void mtip_handle_tfe(struct driver_data *dd)
        /* Stop the timer to prevent command timeouts. */
        del_timer(&port->cmd_timer);
 
+       /* clear the tag accumulator */
+       memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+
        /* Set eh_active */
-       set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+       set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
 
        /* Loop through all the groups */
        for (group = 0; group < dd->slot_groups; group++) {
@@ -732,9 +796,6 @@ static void mtip_handle_tfe(struct driver_data *dd)
                /* clear completed status register in the hardware.*/
                writel(completed, port->completed[group]);
 
-               /* clear the tag accumulator */
-               memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
-
                /* Process successfully completed commands */
                for (bit = 0; bit < 32 && completed; bit++) {
                        if (!(completed & (1<<bit)))
@@ -745,13 +806,14 @@ static void mtip_handle_tfe(struct driver_data *dd)
                        if (tag == MTIP_TAG_INTERNAL)
                                continue;
 
-                       command = &port->commands[tag];
-                       if (likely(command->comp_func)) {
+                       cmd = &port->commands[tag];
+                       if (likely(cmd->comp_func)) {
                                set_bit(tag, tagaccum);
-                               atomic_set(&port->commands[tag].active, 0);
-                               command->comp_func(port,
+                               cmd_cnt++;
+                               atomic_set(&cmd->active, 0);
+                               cmd->comp_func(port,
                                         tag,
-                                        command->comp_data,
+                                        cmd->comp_data,
                                         0);
                        } else {
                                dev_err(&port->dd->pdev->dev,
@@ -765,12 +827,45 @@ static void mtip_handle_tfe(struct driver_data *dd)
                        }
                }
        }
-       print_tags(dd, "TFE tags completed:", tagaccum);
+
+       print_tags(dd, "completed (TFE)", tagaccum, cmd_cnt);
 
        /* Restart the port */
        mdelay(20);
        mtip_restart_port(port);
 
+       /* Trying to determine the cause of the error */
+       rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ,
+                               dd->port->log_buf,
+                               dd->port->log_buf_dma, 1);
+       if (rv) {
+               dev_warn(&dd->pdev->dev,
+                       "Error in READ LOG EXT (10h) command\n");
+               /* non-critical error, don't fail the load */
+       } else {
+               buf = (unsigned char *)dd->port->log_buf;
+               if (buf[259] & 0x1) {
+                       dev_info(&dd->pdev->dev,
+                               "Write protect bit is set.\n");
+                       set_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag);
+                       fail_all_ncq_write = 1;
+                       fail_reason = "write protect";
+               }
+               if (buf[288] == 0xF7) {
+                       dev_info(&dd->pdev->dev,
+                               "Exceeded Tmax, drive in thermal shutdown.\n");
+                       set_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag);
+                       fail_all_ncq_cmds = 1;
+                       fail_reason = "thermal shutdown";
+               }
+               if (buf[288] == 0xBF) {
+                       dev_info(&dd->pdev->dev,
+                               "Drive indicates rebuild has failed.\n");
+                       fail_all_ncq_cmds = 1;
+                       fail_reason = "rebuild failed";
+               }
+       }
+
        /* clear the tag accumulator */
        memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
 
@@ -779,32 +874,47 @@ static void mtip_handle_tfe(struct driver_data *dd)
                for (bit = 0; bit < 32; bit++) {
                        reissue = 1;
                        tag = (group << 5) + bit;
+                       cmd = &port->commands[tag];
 
                        /* If the active bit is set re-issue the command */
-                       if (atomic_read(&port->commands[tag].active) == 0)
+                       if (atomic_read(&cmd->active) == 0)
                                continue;
 
-                       fis = (struct host_to_dev_fis *)
-                               port->commands[tag].command;
+                       fis = (struct host_to_dev_fis *)cmd->command;
 
                        /* Should re-issue? */
                        if (tag == MTIP_TAG_INTERNAL ||
                            fis->command == ATA_CMD_SET_FEATURES)
                                reissue = 0;
+                       else {
+                               if (fail_all_ncq_cmds ||
+                                       (fail_all_ncq_write &&
+                                       fis->command == ATA_CMD_FPDMA_WRITE)) {
+                                       dev_warn(&dd->pdev->dev,
+                                       "  Fail: %s w/tag %d [%s].\n",
+                                       fis->command == ATA_CMD_FPDMA_WRITE ?
+                                               "write" : "read",
+                                       tag,
+                                       fail_reason != NULL ?
+                                               fail_reason : "unknown");
+                                       atomic_set(&cmd->active, 0);
+                                       if (cmd->comp_func) {
+                                               cmd->comp_func(port, tag,
+                                                       cmd->comp_data,
+                                                       -ENODATA);
+                                       }
+                                       continue;
+                               }
+                       }
 
                        /*
                         * First check if this command has
                         *  exceeded its retries.
                         */
-                       if (reissue &&
-                           (port->commands[tag].retries-- > 0)) {
+                       if (reissue && (cmd->retries-- > 0)) {
 
                                set_bit(tag, tagaccum);
 
-                               /* Update the timeout value. */
-                               port->commands[tag].comp_time =
-                                       jiffies + msecs_to_jiffies(
-                                       MTIP_NCQ_COMMAND_TIMEOUT_MS);
                                /* Re-issue the command. */
                                mtip_issue_ncq_command(port, tag);
 
@@ -814,13 +924,13 @@ static void mtip_handle_tfe(struct driver_data *dd)
                        /* Retire a command that will not be reissued */
                        dev_warn(&port->dd->pdev->dev,
                                "retiring tag %d\n", tag);
-                       atomic_set(&port->commands[tag].active, 0);
+                       atomic_set(&cmd->active, 0);
 
-                       if (port->commands[tag].comp_func)
-                               port->commands[tag].comp_func(
+                       if (cmd->comp_func)
+                               cmd->comp_func(
                                        port,
                                        tag,
-                                       port->commands[tag].comp_data,
+                                       cmd->comp_data,
                                        PORT_IRQ_TF_ERR);
                        else
                                dev_warn(&port->dd->pdev->dev,
@@ -828,10 +938,10 @@ static void mtip_handle_tfe(struct driver_data *dd)
                                        tag);
                }
        }
-       print_tags(dd, "TFE tags reissued:", tagaccum);
+       print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt);
 
        /* clear eh_active */
-       clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+       clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
        wake_up_interruptible(&port->svc_wait);
 
        mod_timer(&port->cmd_timer,
@@ -899,7 +1009,7 @@ static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat)
        struct mtip_port *port = dd->port;
        struct mtip_cmd *cmd = &port->commands[MTIP_TAG_INTERNAL];
 
-       if (test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) &&
+       if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags) &&
            (cmd != NULL) && !(readl(port->cmd_issue[MTIP_TAG_INTERNAL])
                & (1 << MTIP_TAG_INTERNAL))) {
                if (cmd->comp_func) {
@@ -911,8 +1021,6 @@ static inline void mtip_process_legacy(struct driver_data *dd, u32 port_stat)
                }
        }
 
-       dev_warn(&dd->pdev->dev, "IRQ status 0x%x ignored.\n", port_stat);
-
        return;
 }
 
@@ -968,6 +1076,9 @@ static inline irqreturn_t mtip_handle_irq(struct driver_data *data)
                                /* don't proceed further */
                                return IRQ_HANDLED;
                        }
+                       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+                                                       &dd->dd_flag))
+                               return rv;
 
                        mtip_process_errors(dd, port_stat & PORT_IRQ_ERR);
                }
@@ -1015,6 +1126,39 @@ static void mtip_issue_non_ncq_command(struct mtip_port *port, int tag)
                port->cmd_issue[MTIP_TAG_INDEX(tag)]);
 }
 
+static bool mtip_pause_ncq(struct mtip_port *port,
+                               struct host_to_dev_fis *fis)
+{
+       struct host_to_dev_fis *reply;
+       unsigned long task_file_data;
+
+       reply = port->rxfis + RX_FIS_D2H_REG;
+       task_file_data = readl(port->mmio+PORT_TFDATA);
+
+       if ((task_file_data & 1) || (fis->command == ATA_CMD_SEC_ERASE_UNIT))
+               return false;
+
+       if (fis->command == ATA_CMD_SEC_ERASE_PREP) {
+               set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+               port->ic_pause_timer = jiffies;
+               return true;
+       } else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) &&
+                                       (fis->features == 0x03)) {
+               set_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
+               port->ic_pause_timer = jiffies;
+               return true;
+       } else if ((fis->command == ATA_CMD_SEC_ERASE_UNIT) ||
+               ((fis->command == 0xFC) &&
+                       (fis->features == 0x27 || fis->features == 0x72 ||
+                        fis->features == 0x62 || fis->features == 0x26))) {
+               /* Com reset after secure erase or lowlevel format */
+               mtip_restart_port(port);
+               return false;
+       }
+
+       return false;
+}
+
 /*
  * Wait for port to quiesce
  *
@@ -1033,11 +1177,13 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
 
        to = jiffies + msecs_to_jiffies(timeout);
        do {
-               if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags) &&
-                       test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
+               if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) &&
+                       test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
                        msleep(20);
                        continue; /* svc thd is actively issuing commands */
                }
+               if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+                       return -EFAULT;
                /*
                 * Ignore s_active bit 0 of array element 0.
                 * This bit will always be set
@@ -1074,7 +1220,7 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
  *     -EAGAIN  Time out waiting for command to complete.
  */
 static int mtip_exec_internal_command(struct mtip_port *port,
-                                       void *fis,
+                                       struct host_to_dev_fis *fis,
                                        int fis_len,
                                        dma_addr_t buffer,
                                        int buf_len,
@@ -1084,8 +1230,9 @@ static int mtip_exec_internal_command(struct mtip_port *port,
 {
        struct mtip_cmd_sg *command_sg;
        DECLARE_COMPLETION_ONSTACK(wait);
-       int rv = 0;
+       int rv = 0, ready2go = 1;
        struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL];
+       unsigned long to;
 
        /* Make sure the buffer is 8 byte aligned. This is asic specific. */
        if (buffer & 0x00000007) {
@@ -1094,23 +1241,38 @@ static int mtip_exec_internal_command(struct mtip_port *port,
                return -EFAULT;
        }
 
-       /* Only one internal command should be running at a time */
-       if (test_and_set_bit(MTIP_TAG_INTERNAL, port->allocated)) {
+       to = jiffies + msecs_to_jiffies(timeout);
+       do {
+               ready2go = !test_and_set_bit(MTIP_TAG_INTERNAL,
+                                               port->allocated);
+               if (ready2go)
+                       break;
+               mdelay(100);
+       } while (time_before(jiffies, to));
+       if (!ready2go) {
                dev_warn(&port->dd->pdev->dev,
-                       "Internal command already active\n");
+                       "Internal cmd active. new cmd [%02X]\n", fis->command);
                return -EBUSY;
        }
-       set_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+       set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
+       port->ic_pause_timer = 0;
+
+       if (fis->command == ATA_CMD_SEC_ERASE_UNIT)
+               clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+       else if (fis->command == ATA_CMD_DOWNLOAD_MICRO)
+               clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
 
        if (atomic == GFP_KERNEL) {
-               /* wait for io to complete if non atomic */
-               if (mtip_quiesce_io(port, 5000) < 0) {
-                       dev_warn(&port->dd->pdev->dev,
-                               "Failed to quiesce IO\n");
-                       release_slot(port, MTIP_TAG_INTERNAL);
-                       clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
-                       wake_up_interruptible(&port->svc_wait);
-                       return -EBUSY;
+               if (fis->command != ATA_CMD_STANDBYNOW1) {
+                       /* wait for io to complete if non atomic */
+                       if (mtip_quiesce_io(port, 5000) < 0) {
+                               dev_warn(&port->dd->pdev->dev,
+                                       "Failed to quiesce IO\n");
+                               release_slot(port, MTIP_TAG_INTERNAL);
+                               clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
+                               wake_up_interruptible(&port->svc_wait);
+                               return -EBUSY;
+                       }
                }
 
                /* Set the completion function and data for the command. */
@@ -1120,7 +1282,7 @@ static int mtip_exec_internal_command(struct mtip_port *port,
        } else {
                /* Clear completion - we're going to poll */
                int_cmd->comp_data = NULL;
-               int_cmd->comp_func = NULL;
+               int_cmd->comp_func = mtip_null_completion;
        }
 
        /* Copy the command to the command table */
@@ -1159,6 +1321,12 @@ static int mtip_exec_internal_command(struct mtip_port *port,
                                "Internal command did not complete [%d] "
                                "within timeout of  %lu ms\n",
                                atomic, timeout);
+                       if (mtip_check_surprise_removal(port->dd->pdev) ||
+                               test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+                                               &port->dd->dd_flag)) {
+                               rv = -ENXIO;
+                               goto exec_ic_exit;
+                       }
                        rv = -EAGAIN;
                }
 
@@ -1166,31 +1334,59 @@ static int mtip_exec_internal_command(struct mtip_port *port,
                        & (1 << MTIP_TAG_INTERNAL)) {
                        dev_warn(&port->dd->pdev->dev,
                                "Retiring internal command but CI is 1.\n");
+                       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+                                               &port->dd->dd_flag)) {
+                               hba_reset_nosleep(port->dd);
+                               rv = -ENXIO;
+                       } else {
+                               mtip_restart_port(port);
+                               rv = -EAGAIN;
+                       }
+                       goto exec_ic_exit;
                }
 
        } else {
                /* Spin for <timeout> checking if command still outstanding */
                timeout = jiffies + msecs_to_jiffies(timeout);
-
-               while ((readl(
-                       port->cmd_issue[MTIP_TAG_INTERNAL])
-                       & (1 << MTIP_TAG_INTERNAL))
-                       && time_before(jiffies, timeout))
-                       ;
+               while ((readl(port->cmd_issue[MTIP_TAG_INTERNAL])
+                               & (1 << MTIP_TAG_INTERNAL))
+                               && time_before(jiffies, timeout)) {
+                       if (mtip_check_surprise_removal(port->dd->pdev)) {
+                               rv = -ENXIO;
+                               goto exec_ic_exit;
+                       }
+                       if ((fis->command != ATA_CMD_STANDBYNOW1) &&
+                               test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+                                               &port->dd->dd_flag)) {
+                               rv = -ENXIO;
+                               goto exec_ic_exit;
+                       }
+               }
 
                if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
                        & (1 << MTIP_TAG_INTERNAL)) {
                        dev_err(&port->dd->pdev->dev,
-                               "Internal command did not complete [%d]\n",
-                               atomic);
+                               "Internal command did not complete [atomic]\n");
                        rv = -EAGAIN;
+                       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+                                               &port->dd->dd_flag)) {
+                               hba_reset_nosleep(port->dd);
+                               rv = -ENXIO;
+                       } else {
+                               mtip_restart_port(port);
+                               rv = -EAGAIN;
+                       }
                }
        }
-
+exec_ic_exit:
        /* Clear the allocated and active bits for the internal command. */
        atomic_set(&int_cmd->active, 0);
        release_slot(port, MTIP_TAG_INTERNAL);
-       clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+       if (rv >= 0 && mtip_pause_ncq(port, fis)) {
+               /* NCQ paused */
+               return rv;
+       }
+       clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
        wake_up_interruptible(&port->svc_wait);
 
        return rv;
@@ -1240,6 +1436,9 @@ static int mtip_get_identify(struct mtip_port *port, void __user *user_buffer)
        int rv = 0;
        struct host_to_dev_fis fis;
 
+       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+               return -EFAULT;
+
        /* Build the FIS. */
        memset(&fis, 0, sizeof(struct host_to_dev_fis));
        fis.type        = 0x27;
@@ -1313,6 +1512,7 @@ static int mtip_standby_immediate(struct mtip_port *port)
 {
        int rv;
        struct host_to_dev_fis  fis;
+       unsigned long start;
 
        /* Build the FIS. */
        memset(&fis, 0, sizeof(struct host_to_dev_fis));
@@ -1320,15 +1520,150 @@ static int mtip_standby_immediate(struct mtip_port *port)
        fis.opts        = 1 << 7;
        fis.command     = ATA_CMD_STANDBYNOW1;
 
-       /* Execute the command.  Use a 15-second timeout for large drives. */
+       start = jiffies;
        rv = mtip_exec_internal_command(port,
                                        &fis,
                                        5,
                                        0,
                                        0,
                                        0,
-                                       GFP_KERNEL,
+                                       GFP_ATOMIC,
                                        15000);
+       dbg_printk(MTIP_DRV_NAME "Time taken to complete standby cmd: %d ms\n",
+                       jiffies_to_msecs(jiffies - start));
+       if (rv)
+               dev_warn(&port->dd->pdev->dev,
+                       "STANDBY IMMEDIATE command failed.\n");
+
+       return rv;
+}
+
+/*
+ * Issue a READ LOG EXT command to the device.
+ *
+ * @port       pointer to the port structure.
+ * @page       page number to fetch
+ * @buffer     pointer to buffer
+ * @buffer_dma dma address corresponding to @buffer
+ * @sectors    page length to fetch, in sectors
+ *
+ * return value
+ *     @rv     return value from mtip_exec_internal_command()
+ */
+static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer,
+                               dma_addr_t buffer_dma, unsigned int sectors)
+{
+       struct host_to_dev_fis fis;
+
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+       fis.type        = 0x27;
+       fis.opts        = 1 << 7;
+       fis.command     = ATA_CMD_READ_LOG_EXT;
+       fis.sect_count  = sectors & 0xFF;
+       fis.sect_cnt_ex = (sectors >> 8) & 0xFF;
+       fis.lba_low     = page;
+       fis.lba_mid     = 0;
+       fis.device      = ATA_DEVICE_OBS;
+
+       memset(buffer, 0, sectors * ATA_SECT_SIZE);
+
+       return mtip_exec_internal_command(port,
+                                       &fis,
+                                       5,
+                                       buffer_dma,
+                                       sectors * ATA_SECT_SIZE,
+                                       0,
+                                       GFP_ATOMIC,
+                                       MTIP_INTERNAL_COMMAND_TIMEOUT_MS);
+}
+
+/*
+ * Issue a SMART READ DATA command to the device.
+ *
+ * @port       pointer to the port structure.
+ * @buffer     pointer to buffer
+ * @buffer_dma dma address corresponding to @buffer
+ *
+ * return value
+ *     @rv     return value from mtip_exec_internal_command()
+ */
+static int mtip_get_smart_data(struct mtip_port *port, u8 *buffer,
+                                       dma_addr_t buffer_dma)
+{
+       struct host_to_dev_fis fis;
+
+       memset(&fis, 0, sizeof(struct host_to_dev_fis));
+       fis.type        = 0x27;
+       fis.opts        = 1 << 7;
+       fis.command     = ATA_CMD_SMART;
+       fis.features    = 0xD0;
+       fis.sect_count  = 1;
+       fis.lba_mid     = 0x4F;
+       fis.lba_hi      = 0xC2;
+       fis.device      = ATA_DEVICE_OBS;
+
+       return mtip_exec_internal_command(port,
+                                       &fis,
+                                       5,
+                                       buffer_dma,
+                                       ATA_SECT_SIZE,
+                                       0,
+                                       GFP_ATOMIC,
+                                       15000);
+}
+
+/*
+ * Get the value of a smart attribute
+ *
+ * @port       pointer to the port structure
+ * @id         attribute number
+ * @attrib     pointer to return attrib information corresponding to @id
+ *
+ * return value
+ *     -EINVAL NULL buffer passed or unsupported attribute @id.
+ *     -EPERM  Identify data not valid, SMART not supported or not enabled
+ */
+static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
+                                               struct smart_attr *attrib)
+{
+       int rv, i;
+       struct smart_attr *pattr;
+
+       if (!attrib)
+               return -EINVAL;
+
+       if (!port->identify_valid) {
+               dev_warn(&port->dd->pdev->dev, "IDENTIFY DATA not valid\n");
+               return -EPERM;
+       }
+       if (!(port->identify[82] & 0x1)) {
+               dev_warn(&port->dd->pdev->dev, "SMART not supported\n");
+               return -EPERM;
+       }
+       if (!(port->identify[85] & 0x1)) {
+               dev_warn(&port->dd->pdev->dev, "SMART not enabled\n");
+               return -EPERM;
+       }
+
+       memset(port->smart_buf, 0, ATA_SECT_SIZE);
+       rv = mtip_get_smart_data(port, port->smart_buf, port->smart_buf_dma);
+       if (rv) {
+               dev_warn(&port->dd->pdev->dev, "Failed to ge SMART data\n");
+               return rv;
+       }
+
+       pattr = (struct smart_attr *)(port->smart_buf + 2);
+       for (i = 0; i < 29; i++, pattr++)
+               if (pattr->attr_id == id) {
+                       memcpy(attrib, pattr, sizeof(struct smart_attr));
+                       break;
+               }
+
+       if (i == 29) {
+               dev_warn(&port->dd->pdev->dev,
+                       "Query for invalid SMART attribute ID\n");
+               rv = -EINVAL;
+       }
 
        return rv;
 }
@@ -1504,10 +1839,7 @@ static int exec_drive_task(struct mtip_port *port, u8 *command)
        fis.cyl_hi      = command[5];
        fis.device      = command[6] & ~0x10; /* Clear the dev bit*/
 
-
-       dbg_printk(MTIP_DRV_NAME "%s: User Command: cmd %x, feat %x, "
-               "nsect %x, sect %x, lcyl %x, "
-               "hcyl %x, sel %x\n",
+       dbg_printk(MTIP_DRV_NAME " %s: User Command: cmd %x, feat %x, nsect %x, sect %x, lcyl %x, hcyl %x, sel %x\n",
                __func__,
                command[0],
                command[1],
@@ -1534,8 +1866,7 @@ static int exec_drive_task(struct mtip_port *port, u8 *command)
        command[4] = reply->cyl_low;
        command[5] = reply->cyl_hi;
 
-       dbg_printk(MTIP_DRV_NAME "%s: Completion Status: stat %x, "
-               "err %x , cyl_lo %x cyl_hi %x\n",
+       dbg_printk(MTIP_DRV_NAME " %s: Completion Status: stat %x, err %x , cyl_lo %x cyl_hi %x\n",
                __func__,
                command[0],
                command[1],
@@ -1578,7 +1909,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
        }
 
        dbg_printk(MTIP_DRV_NAME
-               "%s: User Command: cmd %x, sect %x, "
+               " %s: User Command: cmd %x, sect %x, "
                "feat %x, sectcnt %x\n",
                __func__,
                command[0],
@@ -1607,7 +1938,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
        command[2] = command[3];
 
        dbg_printk(MTIP_DRV_NAME
-               "%s: Completion Status: stat %x, "
+               " %s: Completion Status: stat %x, "
                "err %x, cmd %x\n",
                __func__,
                command[0],
@@ -1810,9 +2141,10 @@ static int exec_drive_taskfile(struct driver_data *dd,
        }
 
        dbg_printk(MTIP_DRV_NAME
-               "taskfile: cmd %x, feat %x, nsect %x,"
+               " %s: cmd %x, feat %x, nsect %x,"
                " sect/lbal %x, lcyl/lbam %x, hcyl/lbah %x,"
                " head/dev %x\n",
+               __func__,
                fis.command,
                fis.features,
                fis.sect_count,
@@ -1823,8 +2155,8 @@ static int exec_drive_taskfile(struct driver_data *dd,
 
        switch (fis.command) {
        case ATA_CMD_DOWNLOAD_MICRO:
-               /* Change timeout for Download Microcode to 60 seconds.*/
-               timeout = 60000;
+               /* Change timeout for Download Microcode to 2 minutes */
+               timeout = 120000;
                break;
        case ATA_CMD_SEC_ERASE_UNIT:
                /* Change timeout for Security Erase Unit to 4 minutes.*/
@@ -1840,8 +2172,8 @@ static int exec_drive_taskfile(struct driver_data *dd,
                timeout = 10000;
                break;
        case ATA_CMD_SMART:
-               /* Change timeout for vendor unique command to 10 secs */
-               timeout = 10000;
+               /* Change timeout for vendor unique command to 15 secs */
+               timeout = 15000;
                break;
        default:
                timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS;
@@ -1903,18 +2235,8 @@ static int exec_drive_taskfile(struct driver_data *dd,
                req_task->hob_ports[1] = reply->features_ex;
                req_task->hob_ports[2] = reply->sect_cnt_ex;
        }
-
-       /* Com rest after secure erase or lowlevel format */
-       if (((fis.command == ATA_CMD_SEC_ERASE_UNIT) ||
-               ((fis.command == 0xFC) &&
-                       (fis.features == 0x27 || fis.features == 0x72 ||
-                        fis.features == 0x62 || fis.features == 0x26))) &&
-                        !(reply->command & 1)) {
-               mtip_restart_port(dd->port);
-       }
-
        dbg_printk(MTIP_DRV_NAME
-               "%s: Completion: stat %x,"
+               " %s: Completion: stat %x,"
                "err %x, sect_cnt %x, lbalo %x,"
                "lbamid %x, lbahi %x, dev %x\n",
                __func__,
@@ -2080,14 +2402,10 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        struct host_to_dev_fis  *fis;
        struct mtip_port *port = dd->port;
        struct mtip_cmd *command = &port->commands[tag];
+       int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 
        /* Map the scatter list for DMA access */
-       if (dir == READ)
-               nents = dma_map_sg(&dd->pdev->dev, command->sg,
-                                       nents, DMA_FROM_DEVICE);
-       else
-               nents = dma_map_sg(&dd->pdev->dev, command->sg,
-                                       nents, DMA_TO_DEVICE);
+       nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
 
        command->scatter_ents = nents;
 
@@ -2127,7 +2445,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
         */
        command->comp_data = dd;
        command->comp_func = mtip_async_complete;
-       command->direction = (dir == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+       command->direction = dma_dir;
 
        /*
         * Set the completion function and data for the command passed
@@ -2140,19 +2458,16 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
         * To prevent this command from being issued
         * if an internal command is in progress or error handling is active.
         */
-       if (unlikely(test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) ||
-                       test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags))) {
+       if (port->flags & MTIP_PF_PAUSE_IO) {
                set_bit(tag, port->cmds_to_issue);
-               set_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
+               set_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags);
                return;
        }
 
        /* Issue the command to the hardware */
        mtip_issue_ncq_command(port, tag);
 
-       /* Set the command's timeout value.*/
-       port->commands[tag].comp_time = jiffies + msecs_to_jiffies(
-                                       MTIP_NCQ_COMMAND_TIMEOUT_MS);
+       return;
 }
 
 /*
@@ -2191,6 +2506,10 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd,
        down(&dd->port->cmd_slot);
        *tag = get_slot(dd->port);
 
+       if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) {
+               up(&dd->port->cmd_slot);
+               return NULL;
+       }
        if (unlikely(*tag < 0))
                return NULL;
 
@@ -2207,7 +2526,7 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd,
  * return value
  *     The size, in bytes, of the data copied into buf.
  */
-static ssize_t hw_show_registers(struct device *dev,
+static ssize_t mtip_hw_show_registers(struct device *dev,
                                struct device_attribute *attr,
                                char *buf)
 {
@@ -2216,7 +2535,7 @@ static ssize_t hw_show_registers(struct device *dev,
        int size = 0;
        int n;
 
-       size += sprintf(&buf[size], "%s:\ns_active:\n", __func__);
+       size += sprintf(&buf[size], "S ACTive:\n");
 
        for (n = 0; n < dd->slot_groups; n++)
                size += sprintf(&buf[size], "0x%08x\n",
@@ -2240,20 +2559,39 @@ static ssize_t hw_show_registers(struct device *dev,
                                 group_allocated);
        }
 
-       size += sprintf(&buf[size], "completed:\n");
+       size += sprintf(&buf[size], "Completed:\n");
 
        for (n = 0; n < dd->slot_groups; n++)
                size += sprintf(&buf[size], "0x%08x\n",
                                readl(dd->port->completed[n]));
 
-       size += sprintf(&buf[size], "PORT_IRQ_STAT 0x%08x\n",
+       size += sprintf(&buf[size], "PORT IRQ STAT : 0x%08x\n",
                                readl(dd->port->mmio + PORT_IRQ_STAT));
-       size += sprintf(&buf[size], "HOST_IRQ_STAT 0x%08x\n",
+       size += sprintf(&buf[size], "HOST IRQ STAT : 0x%08x\n",
                                readl(dd->mmio + HOST_IRQ_STAT));
 
        return size;
 }
-static DEVICE_ATTR(registers, S_IRUGO, hw_show_registers, NULL);
+
+static ssize_t mtip_hw_show_status(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct driver_data *dd = dev_to_disk(dev)->private_data;
+       int size = 0;
+
+       if (test_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag))
+               size += sprintf(buf, "%s", "thermal_shutdown\n");
+       else if (test_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag))
+               size += sprintf(buf, "%s", "write_protect\n");
+       else
+               size += sprintf(buf, "%s", "online\n");
+
+       return size;
+}
+
+static DEVICE_ATTR(registers, S_IRUGO, mtip_hw_show_registers, NULL);
+static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);
 
 /*
  * Create the sysfs related attributes.
@@ -2272,7 +2610,10 @@ static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj)
 
        if (sysfs_create_file(kobj, &dev_attr_registers.attr))
                dev_warn(&dd->pdev->dev,
-                       "Error creating registers sysfs entry\n");
+                       "Error creating 'registers' sysfs entry\n");
+       if (sysfs_create_file(kobj, &dev_attr_status.attr))
+               dev_warn(&dd->pdev->dev,
+                       "Error creating 'status' sysfs entry\n");
        return 0;
 }
 
@@ -2292,6 +2633,7 @@ static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj)
                return -EINVAL;
 
        sysfs_remove_file(kobj, &dev_attr_registers.attr);
+       sysfs_remove_file(kobj, &dev_attr_status.attr);
 
        return 0;
 }
@@ -2384,10 +2726,12 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
                "FTL rebuild in progress. Polling for completion.\n");
 
        start = jiffies;
-       dd->ftlrebuildflag = 1;
        timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS);
 
        do {
+               if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+                               &dd->dd_flag)))
+                       return -EFAULT;
                if (mtip_check_surprise_removal(dd->pdev))
                        return -EFAULT;
 
@@ -2408,22 +2752,17 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
                        dev_warn(&dd->pdev->dev,
                                "FTL rebuild complete (%d secs).\n",
                        jiffies_to_msecs(jiffies - start) / 1000);
-                       dd->ftlrebuildflag = 0;
                        mtip_block_initialize(dd);
-                       break;
+                       return 0;
                }
                ssleep(10);
        } while (time_before(jiffies, timeout));
 
        /* Check for timeout */
-       if (dd->ftlrebuildflag) {
-               dev_err(&dd->pdev->dev,
+       dev_err(&dd->pdev->dev,
                "Timed out waiting for FTL rebuild to complete (%d secs).\n",
                jiffies_to_msecs(jiffies - start) / 1000);
-               return -EFAULT;
-       }
-
-       return 0;
+       return -EFAULT;
 }
 
 /*
@@ -2448,14 +2787,17 @@ static int mtip_service_thread(void *data)
                 * is in progress nor error handling is active
                 */
                wait_event_interruptible(port->svc_wait, (port->flags) &&
-                       !test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) &&
-                       !test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags));
+                       !(port->flags & MTIP_PF_PAUSE_IO));
 
                if (kthread_should_stop())
                        break;
 
-               set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
-               if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
+               if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+                               &dd->dd_flag)))
+                       break;
+
+               set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
+               if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
                        slot = 1;
                        /* used to restrict the loop to one iteration */
                        slot_start = num_cmd_slots;
@@ -2480,21 +2822,19 @@ static int mtip_service_thread(void *data)
                                /* Issue the command to the hardware */
                                mtip_issue_ncq_command(port, slot);
 
-                               /* Set the command's timeout value.*/
-                               port->commands[slot].comp_time = jiffies +
-                               msecs_to_jiffies(MTIP_NCQ_COMMAND_TIMEOUT_MS);
-
                                clear_bit(slot, port->cmds_to_issue);
                        }
 
-                       clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
-               } else if (test_bit(MTIP_FLAG_REBUILD_BIT, &port->flags)) {
-                       mtip_ftl_rebuild_poll(dd);
-                       clear_bit(MTIP_FLAG_REBUILD_BIT, &port->flags);
+                       clear_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags);
+               } else if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) {
+                       if (!mtip_ftl_rebuild_poll(dd))
+                               set_bit(MTIP_DDF_REBUILD_FAILED_BIT,
+                                                       &dd->dd_flag);
+                       clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
                }
-               clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
+               clear_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
 
-               if (test_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &port->flags))
+               if (test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
                        break;
        }
        return 0;
@@ -2513,6 +2853,9 @@ static int mtip_hw_init(struct driver_data *dd)
        int i;
        int rv;
        unsigned int num_command_slots;
+       unsigned long timeout, timetaken;
+       unsigned char *buf;
+       struct smart_attr attr242;
 
        dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR];
 
@@ -2547,7 +2890,7 @@ static int mtip_hw_init(struct driver_data *dd)
        /* Allocate memory for the command list. */
        dd->port->command_list =
                dmam_alloc_coherent(&dd->pdev->dev,
-                       HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+                       HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
                        &dd->port->command_list_dma,
                        GFP_KERNEL);
        if (!dd->port->command_list) {
@@ -2560,7 +2903,7 @@ static int mtip_hw_init(struct driver_data *dd)
        /* Clear the memory we have allocated. */
        memset(dd->port->command_list,
                0,
-               HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2));
+               HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4));
 
        /* Setup the addresse of the RX FIS. */
        dd->port->rxfis     = dd->port->command_list + HW_CMD_SLOT_SZ;
@@ -2576,10 +2919,19 @@ static int mtip_hw_init(struct driver_data *dd)
        dd->port->identify_dma = dd->port->command_tbl_dma +
                                        HW_CMD_TBL_AR_SZ;
 
-       /* Setup the address of the sector buffer. */
+       /* Setup the address of the sector buffer - for some non-ncq cmds */
        dd->port->sector_buffer = (void *) dd->port->identify + ATA_SECT_SIZE;
        dd->port->sector_buffer_dma = dd->port->identify_dma + ATA_SECT_SIZE;
 
+       /* Setup the address of the log buf - for read log command */
+       dd->port->log_buf = (void *)dd->port->sector_buffer  + ATA_SECT_SIZE;
+       dd->port->log_buf_dma = dd->port->sector_buffer_dma + ATA_SECT_SIZE;
+
+       /* Setup the address of the smart buf - for smart read data command */
+       dd->port->smart_buf = (void *)dd->port->log_buf  + ATA_SECT_SIZE;
+       dd->port->smart_buf_dma = dd->port->log_buf_dma + ATA_SECT_SIZE;
+
+
        /* Point the command headers at the command tables. */
        for (i = 0; i < num_command_slots; i++) {
                dd->port->commands[i].command_header =
@@ -2623,14 +2975,43 @@ static int mtip_hw_init(struct driver_data *dd)
                        dd->port->mmio + i*0x80 + PORT_SDBV;
        }
 
-       /* Reset the HBA. */
-       if (mtip_hba_reset(dd) < 0) {
-               dev_err(&dd->pdev->dev,
-                       "Card did not reset within timeout\n");
-               rv = -EIO;
+       timetaken = jiffies;
+       timeout = jiffies + msecs_to_jiffies(30000);
+       while (((readl(dd->port->mmio + PORT_SCR_STAT) & 0x0F) != 0x03) &&
+                time_before(jiffies, timeout)) {
+               mdelay(100);
+       }
+       if (unlikely(mtip_check_surprise_removal(dd->pdev))) {
+               timetaken = jiffies - timetaken;
+               dev_warn(&dd->pdev->dev,
+                       "Surprise removal detected at %u ms\n",
+                       jiffies_to_msecs(timetaken));
+               rv = -ENODEV;
+               goto out2 ;
+       }
+       if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) {
+               timetaken = jiffies - timetaken;
+               dev_warn(&dd->pdev->dev,
+                       "Removal detected at %u ms\n",
+                       jiffies_to_msecs(timetaken));
+               rv = -EFAULT;
                goto out2;
        }
 
+       /* Conditionally reset the HBA. */
+       if (!(readl(dd->mmio + HOST_CAP) & HOST_CAP_NZDMA)) {
+               if (mtip_hba_reset(dd) < 0) {
+                       dev_err(&dd->pdev->dev,
+                               "Card did not reset within timeout\n");
+                       rv = -EIO;
+                       goto out2;
+               }
+       } else {
+               /* Clear any pending interrupts on the HBA */
+               writel(readl(dd->mmio + HOST_IRQ_STAT),
+                       dd->mmio + HOST_IRQ_STAT);
+       }
+
        mtip_init_port(dd->port);
        mtip_start_port(dd->port);
 
@@ -2660,6 +3041,12 @@ static int mtip_hw_init(struct driver_data *dd)
        mod_timer(&dd->port->cmd_timer,
                jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
 
+
+       if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) {
+               rv = -EFAULT;
+               goto out3;
+       }
+
        if (mtip_get_identify(dd->port, NULL) < 0) {
                rv = -EFAULT;
                goto out3;
@@ -2667,10 +3054,47 @@ static int mtip_hw_init(struct driver_data *dd)
 
        if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) ==
                MTIP_FTL_REBUILD_MAGIC) {
-               set_bit(MTIP_FLAG_REBUILD_BIT, &dd->port->flags);
+               set_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags);
                return MTIP_FTL_REBUILD_MAGIC;
        }
        mtip_dump_identify(dd->port);
+
+       /* check write protect, over temp and rebuild statuses */
+       rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ,
+                               dd->port->log_buf,
+                               dd->port->log_buf_dma, 1);
+       if (rv) {
+               dev_warn(&dd->pdev->dev,
+                       "Error in READ LOG EXT (10h) command\n");
+               /* non-critical error, don't fail the load */
+       } else {
+               buf = (unsigned char *)dd->port->log_buf;
+               if (buf[259] & 0x1) {
+                       dev_info(&dd->pdev->dev,
+                               "Write protect bit is set.\n");
+                       set_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag);
+               }
+               if (buf[288] == 0xF7) {
+                       dev_info(&dd->pdev->dev,
+                               "Exceeded Tmax, drive in thermal shutdown.\n");
+                       set_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag);
+               }
+               if (buf[288] == 0xBF) {
+                       dev_info(&dd->pdev->dev,
+                               "Drive indicates rebuild has failed.\n");
+                       /* TODO */
+               }
+       }
+
+       /* get write protect progess */
+       memset(&attr242, 0, sizeof(struct smart_attr));
+       if (mtip_get_smart_attr(dd->port, 242, &attr242))
+               dev_warn(&dd->pdev->dev,
+                               "Unable to check write protect progress\n");
+       else
+               dev_info(&dd->pdev->dev,
+                               "Write protect progress: %d%% (%d blocks)\n",
+                               attr242.cur, attr242.data);
        return rv;
 
 out3:
@@ -2688,7 +3112,7 @@ out2:
 
        /* Free the command/command header memory. */
        dmam_free_coherent(&dd->pdev->dev,
-                               HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+                               HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
                                dd->port->command_list,
                                dd->port->command_list_dma);
 out1:
@@ -2712,9 +3136,12 @@ static int mtip_hw_exit(struct driver_data *dd)
         * Send standby immediate (E0h) to the drive so that it
         * saves its state.
         */
-       if (atomic_read(&dd->drv_cleanup_done) != true) {
+       if (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
 
-               mtip_standby_immediate(dd->port);
+               if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags))
+                       if (mtip_standby_immediate(dd->port))
+                               dev_warn(&dd->pdev->dev,
+                                       "STANDBY IMMEDIATE failed\n");
 
                /* de-initialize the port. */
                mtip_deinit_port(dd->port);
@@ -2734,7 +3161,7 @@ static int mtip_hw_exit(struct driver_data *dd)
 
        /* Free the command/command header memory. */
        dmam_free_coherent(&dd->pdev->dev,
-                       HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+                       HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
                        dd->port->command_list,
                        dd->port->command_list_dma);
        /* Free the memory allocated for the for structure. */
@@ -2892,6 +3319,9 @@ static int mtip_block_ioctl(struct block_device *dev,
        if (!dd)
                return -ENOTTY;
 
+       if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)))
+               return -ENOTTY;
+
        switch (cmd) {
        case BLKFLSBUF:
                return -ENOTTY;
@@ -2927,6 +3357,9 @@ static int mtip_block_compat_ioctl(struct block_device *dev,
        if (!dd)
                return -ENOTTY;
 
+       if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)))
+               return -ENOTTY;
+
        switch (cmd) {
        case BLKFLSBUF:
                return -ENOTTY;
@@ -3049,6 +3482,24 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
        int nents = 0;
        int tag = 0;
 
+       if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) {
+               if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+                                                       &dd->dd_flag))) {
+                       bio_endio(bio, -ENXIO);
+                       return;
+               }
+               if (unlikely(test_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag))) {
+                       bio_endio(bio, -ENODATA);
+                       return;
+               }
+               if (unlikely(test_bit(MTIP_DDF_WRITE_PROTECT_BIT,
+                                                       &dd->dd_flag) &&
+                               bio_data_dir(bio))) {
+                       bio_endio(bio, -ENODATA);
+                       return;
+               }
+       }
+
        if (unlikely(!bio_has_data(bio))) {
                blk_queue_flush(queue, 0);
                bio_endio(bio, 0);
@@ -3061,7 +3512,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
 
                if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) {
                        dev_warn(&dd->pdev->dev,
-                               "Maximum number of SGL entries exceeded");
+                               "Maximum number of SGL entries exceeded\n");
                        bio_io_error(bio);
                        mtip_hw_release_scatterlist(dd, tag);
                        return;
@@ -3210,8 +3661,10 @@ skip_create_disk:
                kobject_put(kobj);
        }
 
-       if (dd->mtip_svc_handler)
+       if (dd->mtip_svc_handler) {
+               set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
                return rv; /* service thread created for handling rebuild */
+       }
 
 start_service_thread:
        sprintf(thd_name, "mtip_svc_thd_%02d", index);
@@ -3220,12 +3673,15 @@ start_service_thread:
                                                dd, thd_name);
 
        if (IS_ERR(dd->mtip_svc_handler)) {
-               printk(KERN_ERR "mtip32xx: service thread failed to start\n");
+               dev_err(&dd->pdev->dev, "service thread failed to start\n");
                dd->mtip_svc_handler = NULL;
                rv = -EFAULT;
                goto kthread_run_error;
        }
 
+       if (wait_for_rebuild == MTIP_FTL_REBUILD_MAGIC)
+               rv = wait_for_rebuild;
+
        return rv;
 
 kthread_run_error:
@@ -3266,16 +3722,18 @@ static int mtip_block_remove(struct driver_data *dd)
        struct kobject *kobj;
 
        if (dd->mtip_svc_handler) {
-               set_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &dd->port->flags);
+               set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
                wake_up_interruptible(&dd->port->svc_wait);
                kthread_stop(dd->mtip_svc_handler);
        }
 
-       /* Clean up the sysfs attributes managed by the protocol layer. */
-       kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
-       if (kobj) {
-               mtip_hw_sysfs_exit(dd, kobj);
-               kobject_put(kobj);
+       /* Clean up the sysfs attributes, if created */
+       if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
+               kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
+               if (kobj) {
+                       mtip_hw_sysfs_exit(dd, kobj);
+                       kobject_put(kobj);
+               }
        }
 
        /*
@@ -3283,6 +3741,11 @@ static int mtip_block_remove(struct driver_data *dd)
         * from /dev
         */
        del_gendisk(dd->disk);
+
+       spin_lock(&rssd_index_lock);
+       ida_remove(&rssd_index_ida, dd->index);
+       spin_unlock(&rssd_index_lock);
+
        blk_cleanup_queue(dd->queue);
        dd->disk  = NULL;
        dd->queue = NULL;
@@ -3312,6 +3775,11 @@ static int mtip_block_shutdown(struct driver_data *dd)
 
        /* Delete our gendisk structure, and cleanup the blk queue. */
        del_gendisk(dd->disk);
+
+       spin_lock(&rssd_index_lock);
+       ida_remove(&rssd_index_ida, dd->index);
+       spin_unlock(&rssd_index_lock);
+
        blk_cleanup_queue(dd->queue);
        dd->disk  = NULL;
        dd->queue = NULL;
@@ -3359,11 +3827,6 @@ static int mtip_pci_probe(struct pci_dev *pdev,
                return -ENOMEM;
        }
 
-       /* Set the atomic variable as 1 in case of SRSI */
-       atomic_set(&dd->drv_cleanup_done, true);
-
-       atomic_set(&dd->resumeflag, false);
-
        /* Attach the private data to this PCI device.  */
        pci_set_drvdata(pdev, dd);
 
@@ -3420,7 +3883,8 @@ static int mtip_pci_probe(struct pci_dev *pdev,
         * instance number.
         */
        instance++;
-
+       if (rv != MTIP_FTL_REBUILD_MAGIC)
+               set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
        goto done;
 
 block_initialize_err:
@@ -3434,9 +3898,6 @@ iomap_err:
        pci_set_drvdata(pdev, NULL);
        return rv;
 done:
-       /* Set the atomic variable as 0 in case of SRSI */
-       atomic_set(&dd->drv_cleanup_done, true);
-
        return rv;
 }
 
@@ -3452,8 +3913,10 @@ static void mtip_pci_remove(struct pci_dev *pdev)
        struct driver_data *dd = pci_get_drvdata(pdev);
        int counter = 0;
 
+       set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
+
        if (mtip_check_surprise_removal(pdev)) {
-               while (atomic_read(&dd->drv_cleanup_done) == false) {
+               while (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
                        counter++;
                        msleep(20);
                        if (counter == 10) {
@@ -3463,8 +3926,6 @@ static void mtip_pci_remove(struct pci_dev *pdev)
                        }
                }
        }
-       /* Set the atomic variable as 1 in case of SRSI */
-       atomic_set(&dd->drv_cleanup_done, true);
 
        /* Clean up the block layer. */
        mtip_block_remove(dd);
@@ -3493,7 +3954,7 @@ static int mtip_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
                return -EFAULT;
        }
 
-       atomic_set(&dd->resumeflag, true);
+       set_bit(MTIP_DDF_RESUME_BIT, &dd->dd_flag);
 
        /* Disable ports & interrupts then send standby immediate */
        rv = mtip_block_suspend(dd);
@@ -3559,7 +4020,7 @@ static int mtip_pci_resume(struct pci_dev *pdev)
                dev_err(&pdev->dev, "Unable to resume\n");
 
 err:
-       atomic_set(&dd->resumeflag, false);
+       clear_bit(MTIP_DDF_RESUME_BIT, &dd->dd_flag);
 
        return rv;
 }
@@ -3608,18 +4069,25 @@ MODULE_DEVICE_TABLE(pci, mtip_pci_tbl);
  */
 static int __init mtip_init(void)
 {
+       int error;
+
        printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
 
        /* Allocate a major block device number to use with this driver. */
-       mtip_major = register_blkdev(0, MTIP_DRV_NAME);
-       if (mtip_major < 0) {
+       error = register_blkdev(0, MTIP_DRV_NAME);
+       if (error <= 0) {
                printk(KERN_ERR "Unable to register block device (%d)\n",
-               mtip_major);
+               error);
                return -EBUSY;
        }
+       mtip_major = error;
 
        /* Register our PCI operations. */
-       return pci_register_driver(&mtip_pci_driver);
+       error = pci_register_driver(&mtip_pci_driver);
+       if (error)
+               unregister_blkdev(mtip_major, MTIP_DRV_NAME);
+
+       return error;
 }
 
 /*
index e0554a8f2233faf85c8f98409fdf83c9cdd5cae7..4ef58336310a126af9b4d0847dc4099e4af23610 100644 (file)
@@ -34,8 +34,8 @@
 /* offset of Device Control register in PCIe extended capabilites space */
 #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET  0x48
 
-/* # of times to retry timed out IOs */
-#define MTIP_MAX_RETRIES       5
+/* # of times to retry timed out/failed IOs */
+#define MTIP_MAX_RETRIES       2
 
 /* Various timeout values in ms */
 #define MTIP_NCQ_COMMAND_TIMEOUT_MS       5000
 #define __force_bit2int (unsigned int __force)
 
 /* below are bit numbers in 'flags' defined in mtip_port */
-#define MTIP_FLAG_IC_ACTIVE_BIT                        0
-#define MTIP_FLAG_EH_ACTIVE_BIT                        1
-#define MTIP_FLAG_SVC_THD_ACTIVE_BIT           2
-#define MTIP_FLAG_ISSUE_CMDS_BIT               4
-#define MTIP_FLAG_REBUILD_BIT                  5
-#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT      8
+#define MTIP_PF_IC_ACTIVE_BIT          0 /* pio/ioctl */
+#define MTIP_PF_EH_ACTIVE_BIT          1 /* error handling */
+#define MTIP_PF_SE_ACTIVE_BIT          2 /* secure erase */
+#define MTIP_PF_DM_ACTIVE_BIT          3 /* download microcde */
+#define MTIP_PF_PAUSE_IO       ((1 << MTIP_PF_IC_ACTIVE_BIT) | \
+                               (1 << MTIP_PF_EH_ACTIVE_BIT) | \
+                               (1 << MTIP_PF_SE_ACTIVE_BIT) | \
+                               (1 << MTIP_PF_DM_ACTIVE_BIT))
+
+#define MTIP_PF_SVC_THD_ACTIVE_BIT     4
+#define MTIP_PF_ISSUE_CMDS_BIT         5
+#define MTIP_PF_REBUILD_BIT            6
+#define MTIP_PF_SVC_THD_STOP_BIT       8
+
+/* below are bit numbers in 'dd_flag' defined in driver_data */
+#define MTIP_DDF_REMOVE_PENDING_BIT    1
+#define MTIP_DDF_OVER_TEMP_BIT         2
+#define MTIP_DDF_WRITE_PROTECT_BIT     3
+#define MTIP_DDF_STOP_IO       ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \
+                               (1 << MTIP_DDF_OVER_TEMP_BIT) | \
+                               (1 << MTIP_DDF_WRITE_PROTECT_BIT))
+
+#define MTIP_DDF_CLEANUP_BIT           5
+#define MTIP_DDF_RESUME_BIT            6
+#define MTIP_DDF_INIT_DONE_BIT         7
+#define MTIP_DDF_REBUILD_FAILED_BIT    8
+
+__packed struct smart_attr{
+       u8 attr_id;
+       u16 flags;
+       u8 cur;
+       u8 worst;
+       u32 data;
+       u8 res[3];
+};
 
 /* Register Frame Information Structure (FIS), host to device. */
 struct host_to_dev_fis {
@@ -345,6 +374,12 @@ struct mtip_port {
         * when the command slot and all associated data structures
         * are no longer needed.
         */
+       u16 *log_buf;
+       dma_addr_t log_buf_dma;
+
+       u8 *smart_buf;
+       dma_addr_t smart_buf_dma;
+
        unsigned long allocated[SLOTBITS_IN_LONGS];
        /*
         * used to queue commands when an internal command is in progress
@@ -368,6 +403,7 @@ struct mtip_port {
         * Timer used to complete commands that have been active for too long.
         */
        struct timer_list cmd_timer;
+       unsigned long ic_pause_timer;
        /*
         * Semaphore used to block threads if there are no
         * command slots available.
@@ -404,13 +440,9 @@ struct driver_data {
 
        unsigned slot_groups; /* number of slot groups the product supports */
 
-       atomic_t drv_cleanup_done; /* Atomic variable for SRSI */
-
        unsigned long index; /* Index to determine the disk name */
 
-       unsigned int ftlrebuildflag; /* FTL rebuild flag */
-
-       atomic_t resumeflag; /* Atomic variable to track suspend/resume */
+       unsigned long dd_flag; /* NOTE: use atomic bit operations on this */
 
        struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
 };
index c4a60badf252caee7bffff38cc0cf115d0bd81a4..0d39f2f4294a3c2587e5c019e39904b3f8440fc2 100644 (file)
@@ -351,6 +351,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
                  cap_str_10, cap_str_2);
 
        set_capacity(vblk->disk, capacity);
+       revalidate_disk(vblk->disk);
 done:
        mutex_unlock(&vblk->config_lock);
 }
@@ -374,6 +375,34 @@ static int init_vq(struct virtio_blk *vblk)
        return err;
 }
 
+/*
+ * Legacy naming scheme used for virtio devices.  We are stuck with it for
+ * virtio blk but don't ever use it for any new driver.
+ */
+static int virtblk_name_format(char *prefix, int index, char *buf, int buflen)
+{
+       const int base = 'z' - 'a' + 1;
+       char *begin = buf + strlen(prefix);
+       char *end = buf + buflen;
+       char *p;
+       int unit;
+
+       p = end - 1;
+       *p = '\0';
+       unit = base;
+       do {
+               if (p == begin)
+                       return -EINVAL;
+               *--p = 'a' + (index % unit);
+               index = (index / unit) - 1;
+       } while (index >= 0);
+
+       memmove(begin, p, end - p);
+       memcpy(buf, prefix, strlen(prefix));
+
+       return 0;
+}
+
 static int __devinit virtblk_probe(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk;
@@ -442,18 +471,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 
        q->queuedata = vblk;
 
-       if (index < 26) {
-               sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26);
-       } else if (index < (26 + 1) * 26) {
-               sprintf(vblk->disk->disk_name, "vd%c%c",
-                       'a' + index / 26 - 1, 'a' + index % 26);
-       } else {
-               const unsigned int m1 = (index / 26 - 1) / 26 - 1;
-               const unsigned int m2 = (index / 26 - 1) % 26;
-               const unsigned int m3 =  index % 26;
-               sprintf(vblk->disk->disk_name, "vd%c%c%c",
-                       'a' + m1, 'a' + m2, 'a' + m3);
-       }
+       virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
 
        vblk->disk->major = major;
        vblk->disk->first_minor = index_to_minor(index);
index 0088bf60f3689db6a704c1856c4f94a682d7db44..73f196ca713f20e037e22adccba64d0e00c936b1 100644 (file)
@@ -321,6 +321,7 @@ struct seg_buf {
 static void xen_blkbk_unmap(struct pending_req *req)
 {
        struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+       struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        unsigned int i, invcount = 0;
        grant_handle_t handle;
        int ret;
@@ -332,25 +333,12 @@ static void xen_blkbk_unmap(struct pending_req *req)
                gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i),
                                    GNTMAP_host_map, handle);
                pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
+               pages[invcount] = virt_to_page(vaddr(req, i));
                invcount++;
        }
 
-       ret = HYPERVISOR_grant_table_op(
-               GNTTABOP_unmap_grant_ref, unmap, invcount);
+       ret = gnttab_unmap_refs(unmap, pages, invcount, false);
        BUG_ON(ret);
-       /*
-        * Note, we use invcount, so nr->pages, so we can't index
-        * using vaddr(req, i).
-        */
-       for (i = 0; i < invcount; i++) {
-               ret = m2p_remove_override(
-                       virt_to_page(unmap[i].host_addr), false);
-               if (ret) {
-                       pr_alert(DRV_PFX "Failed to remove M2P override for %lx\n",
-                                (unsigned long)unmap[i].host_addr);
-                       continue;
-               }
-       }
 }
 
 static int xen_blkbk_map(struct blkif_request *req,
@@ -378,7 +366,7 @@ static int xen_blkbk_map(struct blkif_request *req,
                                  pending_req->blkif->domid);
        }
 
-       ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
+       ret = gnttab_map_refs(map, NULL, &blkbk->pending_page(pending_req, 0), nseg);
        BUG_ON(ret);
 
        /*
@@ -398,15 +386,6 @@ static int xen_blkbk_map(struct blkif_request *req,
                if (ret)
                        continue;
 
-               ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr),
-                       blkbk->pending_page(pending_req, i), NULL);
-               if (ret) {
-                       pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n",
-                                (unsigned long)map[i].dev_bus_addr, ret);
-                       /* We could switch over to GNTTABOP_copy */
-                       continue;
-               }
-
                seg[i].buf  = map[i].dev_bus_addr |
                        (req->u.rw.seg[i].first_sect << 9);
        }
@@ -419,21 +398,18 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
        int err = 0;
        int status = BLKIF_RSP_OKAY;
        struct block_device *bdev = blkif->vbd.bdev;
+       unsigned long secure;
 
        blkif->st_ds_req++;
 
        xen_blkif_get(blkif);
-       if (blkif->blk_backend_type == BLKIF_BACKEND_PHY ||
-           blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
-               unsigned long secure = (blkif->vbd.discard_secure &&
-                       (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
-                       BLKDEV_DISCARD_SECURE : 0;
-               err = blkdev_issue_discard(bdev,
-                               req->u.discard.sector_number,
-                               req->u.discard.nr_sectors,
-                               GFP_KERNEL, secure);
-       } else
-               err = -EOPNOTSUPP;
+       secure = (blkif->vbd.discard_secure &&
+                (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
+                BLKDEV_DISCARD_SECURE : 0;
+
+       err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
+                                  req->u.discard.nr_sectors,
+                                  GFP_KERNEL, secure);
 
        if (err == -EOPNOTSUPP) {
                pr_debug(DRV_PFX "discard op failed, not supported\n");
@@ -830,7 +806,7 @@ static int __init xen_blkif_init(void)
        int i, mmap_pages;
        int rc = 0;
 
-       if (!xen_pv_domain())
+       if (!xen_domain())
                return -ENODEV;
 
        blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL);
index d0ee7edc9be8ad1819a91a491eb907f18d545fbf..773cf27dc23fc595d6fca48ea8ec6c4992438d18 100644 (file)
@@ -146,11 +146,6 @@ enum blkif_protocol {
        BLKIF_PROTOCOL_X86_64 = 3,
 };
 
-enum blkif_backend_type {
-       BLKIF_BACKEND_PHY  = 1,
-       BLKIF_BACKEND_FILE = 2,
-};
-
 struct xen_vbd {
        /* What the domain refers to this vbd as. */
        blkif_vdev_t            handle;
@@ -177,7 +172,6 @@ struct xen_blkif {
        unsigned int            irq;
        /* Comms information. */
        enum blkif_protocol     blk_protocol;
-       enum blkif_backend_type blk_backend_type;
        union blkif_back_rings  blk_rings;
        void                    *blk_ring;
        /* The VBD attached to this interface. */
index 24a2fb57e5d012d57c5d3e1fc1929f27ac3998ee..4f66171c668354b490f1284aec48278b8676bd84 100644 (file)
@@ -381,72 +381,49 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
        err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache",
                            "%d", state);
        if (err)
-               xenbus_dev_fatal(dev, err, "writing feature-flush-cache");
+               dev_warn(&dev->dev, "writing feature-flush-cache (%d)", err);
 
        return err;
 }
 
-int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
+static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
 {
        struct xenbus_device *dev = be->dev;
        struct xen_blkif *blkif = be->blkif;
-       char *type;
        int err;
        int state = 0;
+       struct block_device *bdev = be->blkif->vbd.bdev;
+       struct request_queue *q = bdev_get_queue(bdev);
 
-       type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL);
-       if (!IS_ERR(type)) {
-               if (strncmp(type, "file", 4) == 0) {
-                       state = 1;
-                       blkif->blk_backend_type = BLKIF_BACKEND_FILE;
+       if (blk_queue_discard(q)) {
+               err = xenbus_printf(xbt, dev->nodename,
+                       "discard-granularity", "%u",
+                       q->limits.discard_granularity);
+               if (err) {
+                       dev_warn(&dev->dev, "writing discard-granularity (%d)", err);
+                       return;
                }
-               if (strncmp(type, "phy", 3) == 0) {
-                       struct block_device *bdev = be->blkif->vbd.bdev;
-                       struct request_queue *q = bdev_get_queue(bdev);
-                       if (blk_queue_discard(q)) {
-                               err = xenbus_printf(xbt, dev->nodename,
-                                       "discard-granularity", "%u",
-                                       q->limits.discard_granularity);
-                               if (err) {
-                                       xenbus_dev_fatal(dev, err,
-                                               "writing discard-granularity");
-                                       goto kfree;
-                               }
-                               err = xenbus_printf(xbt, dev->nodename,
-                                       "discard-alignment", "%u",
-                                       q->limits.discard_alignment);
-                               if (err) {
-                                       xenbus_dev_fatal(dev, err,
-                                               "writing discard-alignment");
-                                       goto kfree;
-                               }
-                               state = 1;
-                               blkif->blk_backend_type = BLKIF_BACKEND_PHY;
-                       }
-                       /* Optional. */
-                       err = xenbus_printf(xbt, dev->nodename,
-                               "discard-secure", "%d",
-                               blkif->vbd.discard_secure);
-                       if (err) {
-                               xenbus_dev_fatal(dev, err,
-                                       "writting discard-secure");
-                               goto kfree;
-                       }
+               err = xenbus_printf(xbt, dev->nodename,
+                       "discard-alignment", "%u",
+                       q->limits.discard_alignment);
+               if (err) {
+                       dev_warn(&dev->dev, "writing discard-alignment (%d)", err);
+                       return;
+               }
+               state = 1;
+               /* Optional. */
+               err = xenbus_printf(xbt, dev->nodename,
+                                   "discard-secure", "%d",
+                                   blkif->vbd.discard_secure);
+               if (err) {
+                       dev_warn(&dev->dev, "writing discard-secure (%d)", err);
+                       return;
                }
-       } else {
-               err = PTR_ERR(type);
-               xenbus_dev_fatal(dev, err, "reading type");
-               goto out;
        }
-
        err = xenbus_printf(xbt, dev->nodename, "feature-discard",
                            "%d", state);
        if (err)
-               xenbus_dev_fatal(dev, err, "writing feature-discard");
-kfree:
-       kfree(type);
-out:
-       return err;
+               dev_warn(&dev->dev, "writing feature-discard (%d)", err);
 }
 int xen_blkbk_barrier(struct xenbus_transaction xbt,
                      struct backend_info *be, int state)
@@ -457,7 +434,7 @@ int xen_blkbk_barrier(struct xenbus_transaction xbt,
        err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
                            "%d", state);
        if (err)
-               xenbus_dev_fatal(dev, err, "writing feature-barrier");
+               dev_warn(&dev->dev, "writing feature-barrier (%d)", err);
 
        return err;
 }
@@ -689,14 +666,12 @@ again:
                return;
        }
 
-       err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support);
-       if (err)
-               goto abort;
+       /* If we can't advertise it is OK. */
+       xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support);
 
-       err = xen_blkbk_discard(xbt, be);
+       xen_blkbk_discard(xbt, be);
 
-       /* If we can't advertise it is OK. */
-       err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
+       xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
 
        err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
                            (unsigned long long)vbd_sz(&be->blkif->vbd));
index d5e1ab95674044361920140550b0c6b34f9be9b3..4e86393a09cf5c880917fd81d3e67e507a83c0f6 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/scatterlist.h>
+#include <linux/bitmap.h>
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
@@ -81,6 +82,7 @@ static const struct block_device_operations xlvbd_block_fops;
  */
 struct blkfront_info
 {
+       spinlock_t io_lock;
        struct mutex mutex;
        struct xenbus_device *xbdev;
        struct gendisk *gd;
@@ -105,8 +107,6 @@ struct blkfront_info
        int is_ready;
 };
 
-static DEFINE_SPINLOCK(blkif_io_lock);
-
 static unsigned int nr_minors;
 static unsigned long *minors;
 static DEFINE_SPINLOCK(minor_lock);
@@ -177,8 +177,7 @@ static int xlbd_reserve_minors(unsigned int minor, unsigned int nr)
 
        spin_lock(&minor_lock);
        if (find_next_bit(minors, end, minor) >= end) {
-               for (; minor < end; ++minor)
-                       __set_bit(minor, minors);
+               bitmap_set(minors, minor, nr);
                rc = 0;
        } else
                rc = -EBUSY;
@@ -193,8 +192,7 @@ static void xlbd_release_minors(unsigned int minor, unsigned int nr)
 
        BUG_ON(end > nr_minors);
        spin_lock(&minor_lock);
-       for (; minor < end; ++minor)
-               __clear_bit(minor, minors);
+       bitmap_clear(minors,  minor, nr);
        spin_unlock(&minor_lock);
 }
 
@@ -419,7 +417,7 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
        struct request_queue *rq;
        struct blkfront_info *info = gd->private_data;
 
-       rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
+       rq = blk_init_queue(do_blkif_request, &info->io_lock);
        if (rq == NULL)
                return -1;
 
@@ -636,14 +634,14 @@ static void xlvbd_release_gendisk(struct blkfront_info *info)
        if (info->rq == NULL)
                return;
 
-       spin_lock_irqsave(&blkif_io_lock, flags);
+       spin_lock_irqsave(&info->io_lock, flags);
 
        /* No more blkif_request(). */
        blk_stop_queue(info->rq);
 
        /* No more gnttab callback work. */
        gnttab_cancel_free_callback(&info->callback);
-       spin_unlock_irqrestore(&blkif_io_lock, flags);
+       spin_unlock_irqrestore(&info->io_lock, flags);
 
        /* Flush gnttab callback work. Must be done with no locks held. */
        flush_work_sync(&info->work);
@@ -675,16 +673,16 @@ static void blkif_restart_queue(struct work_struct *work)
 {
        struct blkfront_info *info = container_of(work, struct blkfront_info, work);
 
-       spin_lock_irq(&blkif_io_lock);
+       spin_lock_irq(&info->io_lock);
        if (info->connected == BLKIF_STATE_CONNECTED)
                kick_pending_request_queues(info);
-       spin_unlock_irq(&blkif_io_lock);
+       spin_unlock_irq(&info->io_lock);
 }
 
 static void blkif_free(struct blkfront_info *info, int suspend)
 {
        /* Prevent new requests being issued until we fix things up. */
-       spin_lock_irq(&blkif_io_lock);
+       spin_lock_irq(&info->io_lock);
        info->connected = suspend ?
                BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
        /* No more blkif_request(). */
@@ -692,7 +690,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
                blk_stop_queue(info->rq);
        /* No more gnttab callback work. */
        gnttab_cancel_free_callback(&info->callback);
-       spin_unlock_irq(&blkif_io_lock);
+       spin_unlock_irq(&info->io_lock);
 
        /* Flush gnttab callback work. Must be done with no locks held. */
        flush_work_sync(&info->work);
@@ -728,10 +726,10 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
        struct blkfront_info *info = (struct blkfront_info *)dev_id;
        int error;
 
-       spin_lock_irqsave(&blkif_io_lock, flags);
+       spin_lock_irqsave(&info->io_lock, flags);
 
        if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
-               spin_unlock_irqrestore(&blkif_io_lock, flags);
+               spin_unlock_irqrestore(&info->io_lock, flags);
                return IRQ_HANDLED;
        }
 
@@ -816,7 +814,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
 
        kick_pending_request_queues(info);
 
-       spin_unlock_irqrestore(&blkif_io_lock, flags);
+       spin_unlock_irqrestore(&info->io_lock, flags);
 
        return IRQ_HANDLED;
 }
@@ -991,6 +989,7 @@ static int blkfront_probe(struct xenbus_device *dev,
        }
 
        mutex_init(&info->mutex);
+       spin_lock_init(&info->io_lock);
        info->xbdev = dev;
        info->vdevice = vdevice;
        info->connected = BLKIF_STATE_DISCONNECTED;
@@ -1068,7 +1067,7 @@ static int blkif_recover(struct blkfront_info *info)
 
        xenbus_switch_state(info->xbdev, XenbusStateConnected);
 
-       spin_lock_irq(&blkif_io_lock);
+       spin_lock_irq(&info->io_lock);
 
        /* Now safe for us to use the shared ring */
        info->connected = BLKIF_STATE_CONNECTED;
@@ -1079,7 +1078,7 @@ static int blkif_recover(struct blkfront_info *info)
        /* Kick any other new requests queued since we resumed */
        kick_pending_request_queues(info);
 
-       spin_unlock_irq(&blkif_io_lock);
+       spin_unlock_irq(&info->io_lock);
 
        return 0;
 }
@@ -1277,10 +1276,10 @@ static void blkfront_connect(struct blkfront_info *info)
        xenbus_switch_state(info->xbdev, XenbusStateConnected);
 
        /* Kick pending requests. */
-       spin_lock_irq(&blkif_io_lock);
+       spin_lock_irq(&info->io_lock);
        info->connected = BLKIF_STATE_CONNECTED;
        kick_pending_request_queues(info);
-       spin_unlock_irq(&blkif_io_lock);
+       spin_unlock_irq(&info->io_lock);
 
        add_disk(info->gd);
 
@@ -1410,7 +1409,6 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
        mutex_lock(&blkfront_mutex);
 
        bdev = bdget_disk(disk, 0);
-       bdput(bdev);
 
        if (bdev->bd_openers)
                goto out;
@@ -1441,6 +1439,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode)
        }
 
 out:
+       bdput(bdev);
        mutex_unlock(&blkfront_mutex);
        return 0;
 }
@@ -1475,7 +1474,7 @@ static int __init xlblk_init(void)
        if (!xen_domain())
                return -ENODEV;
 
-       if (!xen_platform_pci_unplug)
+       if (xen_hvm_domain() && !xen_platform_pci_unplug)
                return -ENODEV;
 
        if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) {
index 48442476ec005415ec0d51c79c48e305ed31fb69..57fd867553d7ab1dc5fcf1737e3c19e8d8181257 100644 (file)
@@ -72,7 +72,11 @@ static struct usb_device_id ath3k_table[] = {
 
        /* Atheros AR3012 with sflash firmware*/
        { USB_DEVICE(0x0CF3, 0x3004) },
+       { USB_DEVICE(0x0CF3, 0x311D) },
        { USB_DEVICE(0x13d3, 0x3375) },
+       { USB_DEVICE(0x04CA, 0x3005) },
+       { USB_DEVICE(0x13d3, 0x3362) },
+       { USB_DEVICE(0x0CF3, 0xE004) },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE02C) },
@@ -89,7 +93,11 @@ static struct usb_device_id ath3k_blist_tbl[] = {
 
        /* Atheros AR3012 with sflash firmware*/
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
 
        { }     /* Terminating entry */
 };
index 6c20bbb54b71a8e51038f4ad84a59157d489dde0..428dbb7574bd75aa43d84ba5af353a134d1abfd3 100644 (file)
@@ -45,12 +45,6 @@ struct btmrvl_debugfs_data {
        struct dentry *txdnldready;
 };
 
-static int btmrvl_open_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t btmrvl_hscfgcmd_write(struct file *file,
                        const char __user *ubuf, size_t count, loff_t *ppos)
 {
@@ -93,7 +87,7 @@ static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf,
 static const struct file_operations btmrvl_hscfgcmd_fops = {
        .read   = btmrvl_hscfgcmd_read,
        .write  = btmrvl_hscfgcmd_write,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
@@ -134,7 +128,7 @@ static ssize_t btmrvl_psmode_read(struct file *file, char __user *userbuf,
 static const struct file_operations btmrvl_psmode_fops = {
        .read   = btmrvl_psmode_read,
        .write  = btmrvl_psmode_write,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
@@ -180,7 +174,7 @@ static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf,
 static const struct file_operations btmrvl_pscmd_fops = {
        .read = btmrvl_pscmd_read,
        .write = btmrvl_pscmd_write,
-       .open = btmrvl_open_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -221,7 +215,7 @@ static ssize_t btmrvl_gpiogap_read(struct file *file, char __user *userbuf,
 static const struct file_operations btmrvl_gpiogap_fops = {
        .read   = btmrvl_gpiogap_read,
        .write  = btmrvl_gpiogap_write,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
@@ -265,7 +259,7 @@ static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf,
 static const struct file_operations btmrvl_hscmd_fops = {
        .read   = btmrvl_hscmd_read,
        .write  = btmrvl_hscmd_write,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
@@ -305,7 +299,7 @@ static ssize_t btmrvl_hsmode_read(struct file *file, char __user * userbuf,
 static const struct file_operations btmrvl_hsmode_fops = {
        .read   = btmrvl_hsmode_read,
        .write  = btmrvl_hsmode_write,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
@@ -323,7 +317,7 @@ static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
 
 static const struct file_operations btmrvl_curpsmode_fops = {
        .read   = btmrvl_curpsmode_read,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
@@ -341,7 +335,7 @@ static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
 
 static const struct file_operations btmrvl_psstate_fops = {
        .read   = btmrvl_psstate_read,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
@@ -359,7 +353,7 @@ static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
 
 static const struct file_operations btmrvl_hsstate_fops = {
        .read   = btmrvl_hsstate_read,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
@@ -378,7 +372,7 @@ static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
 
 static const struct file_operations btmrvl_txdnldready_fops = {
        .read   = btmrvl_txdnldready_read,
-       .open   = btmrvl_open_generic,
+       .open   = simple_open,
        .llseek = default_llseek,
 };
 
index 480cad9200481fb0ad2eb9a91c5b9b55d2dea5c5..9217121362e10820da89b5678311b61ad6cac849 100644 (file)
@@ -61,7 +61,7 @@ static struct usb_device_id btusb_table[] = {
        { USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
 
        /* Broadcom SoftSailing reporting vendor specific */
-       { USB_DEVICE(0x05ac, 0x21e1) },
+       { USB_DEVICE(0x0a5c, 0x21e1) },
 
        /* Apple MacBookPro 7,1 */
        { USB_DEVICE(0x05ac, 0x8213) },
@@ -101,11 +101,16 @@ static struct usb_device_id btusb_table[] = {
        { USB_DEVICE(0x0c10, 0x0000) },
 
        /* Broadcom BCM20702A0 */
+       { USB_DEVICE(0x0489, 0xe042) },
        { USB_DEVICE(0x0a5c, 0x21e3) },
        { USB_DEVICE(0x0a5c, 0x21e6) },
+       { USB_DEVICE(0x0a5c, 0x21e8) },
        { USB_DEVICE(0x0a5c, 0x21f3) },
        { USB_DEVICE(0x413c, 0x8197) },
 
+       /* Foxconn - Hon Hai */
+       { USB_DEVICE(0x0489, 0xe033) },
+
        { }     /* Terminating entry */
 };
 
@@ -129,7 +134,11 @@ static struct usb_device_id blacklist_table[] = {
 
        /* Atheros 3012 with sflash firmware */
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
index fd5adb408f447a4a08b9dbece913e111d3fe9906..98a8c05d4f23a038dfa020cd98930c9d52283844 100644 (file)
@@ -299,11 +299,11 @@ static void hci_uart_tty_close(struct tty_struct *tty)
                        hci_uart_close(hdev);
 
                if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
-                       hu->proto->close(hu);
                        if (hdev) {
                                hci_unregister_dev(hdev);
                                hci_free_dev(hdev);
                        }
+                       hu->proto->close(hu);
                }
 
                kfree(hu);
index 17e05d1076b34f2ec9e762c38239b7a02993b06e..a0df182f6f7d392c7c18608d3ef55f914e4902c6 100644 (file)
@@ -958,7 +958,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
        if (set_memory_uc((unsigned long)table, 1 << page_order))
                printk(KERN_WARNING "Could not set GATT table memory to UC!\n");
 
-       bridge->gatt_table = (void *)table;
+       bridge->gatt_table = (u32 __iomem *)table;
 #else
        bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
                                        (PAGE_SIZE * (1 << page_order)));
@@ -1010,7 +1010,6 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
        case LVL2_APER_SIZE:
                /* The generic routines can't deal with 2 level gatt's */
                return -EINVAL;
-               break;
        default:
                page_order = 0;
                break;
@@ -1077,7 +1076,6 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
        case LVL2_APER_SIZE:
                /* The generic routines can't deal with 2 level gatt's */
                return -EINVAL;
-               break;
        default:
                num_entries = 0;
                break;
index 962e75dc47810a0c7d0eac323d596b2be507189c..74c2d9274c538f9a9fcef0a05bca018c9e9cdd63 100644 (file)
@@ -907,6 +907,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
        ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB),
        ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB),
        ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB),
+       ID(PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB),
        { }
 };
 
index 5da67f165afaf8df358d1c884083429948cf781e..c0091753a0d191c0268f8093f3ccc89fc4dd3280 100644 (file)
@@ -96,6 +96,7 @@
 #define G4x_GMCH_SIZE_VT_2M    (G4x_GMCH_SIZE_2M | G4x_GMCH_SIZE_VT_EN)
 
 #define GFX_FLSH_CNTL          0x2170 /* 915+ */
+#define GFX_FLSH_CNTL_VLV      0x101008
 
 #define I810_DRAM_CTL          0x3000
 #define I810_DRAM_ROW_0                0x00000001
 #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG         0x0166
 #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB             0x0158  /* Server */
 #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG         0x015A
+#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG         0x016A
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB              0x0F00 /* VLV1 */
+#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG              0x0F30
+#define PCI_DEVICE_ID_INTEL_HASWELL_HB                         0x0400 /* Desktop */
+#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG           0x0402
+#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG           0x0412
+#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB                       0x0404 /* Mobile */
+#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG           0x0406
+#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG           0x0416
+#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB                       0x0408 /* Server */
+#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG           0x040a
+#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG           0x041a
+#define PCI_DEVICE_ID_INTEL_HASWELL_SDV                0x0c16 /* SDV */
+#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB                       0x0c04
 
 int intel_gmch_probe(struct pci_dev *pdev,
                               struct agp_bridge_data *bridge);
index 5cf47ac2d401d2551661355d2d5fbaccfccdb72e..1237e7575c3f0f11df624b740a4a0e5e141e4297 100644 (file)
@@ -1179,6 +1179,20 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry,
        writel(addr | pte_flags, intel_private.gtt + entry);
 }
 
+static void valleyview_write_entry(dma_addr_t addr, unsigned int entry,
+                                  unsigned int flags)
+{
+       u32 pte_flags;
+
+       pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
+
+       /* gen6 has bit11-4 for physical addr bit39-32 */
+       addr |= (addr >> 28) & 0xff0;
+       writel(addr | pte_flags, intel_private.gtt + entry);
+
+       writel(1, intel_private.registers + GFX_FLSH_CNTL_VLV);
+}
+
 static void gen6_cleanup(void)
 {
 }
@@ -1190,7 +1204,6 @@ static inline int needs_idle_maps(void)
 {
 #ifdef CONFIG_INTEL_IOMMU
        const unsigned short gpu_devid = intel_private.pcidev->device;
-       extern int intel_iommu_gfx_mapped;
 
        /* Query intel_iommu to see if we need the workaround. Presumably that
         * was loaded first.
@@ -1206,12 +1219,16 @@ static inline int needs_idle_maps(void)
 static int i9xx_setup(void)
 {
        u32 reg_addr;
+       int size = KB(512);
 
        pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &reg_addr);
 
        reg_addr &= 0xfff80000;
 
-       intel_private.registers = ioremap(reg_addr, 128 * 4096);
+       if (INTEL_GTT_GEN >= 7)
+               size = MB(2);
+
+       intel_private.registers = ioremap(reg_addr, size);
        if (!intel_private.registers)
                return -ENOMEM;
 
@@ -1355,6 +1372,15 @@ static const struct intel_gtt_driver sandybridge_gtt_driver = {
        .check_flags = gen6_check_flags,
        .chipset_flush = i9xx_chipset_flush,
 };
+static const struct intel_gtt_driver valleyview_gtt_driver = {
+       .gen = 7,
+       .setup = i9xx_setup,
+       .cleanup = gen6_cleanup,
+       .write_entry = valleyview_write_entry,
+       .dma_mask_size = 40,
+       .check_flags = gen6_check_flags,
+       .chipset_flush = i9xx_chipset_flush,
+};
 
 /* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of
  * driver and gmch_driver must be non-null, and find_gmch will determine
@@ -1459,6 +1485,24 @@ static const struct intel_gtt_driver_description {
            "Ivybridge", &sandybridge_gtt_driver },
        { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG,
            "Ivybridge", &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG,
+           "Ivybridge", &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG,
+           "ValleyView", &valleyview_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG,
+           "Haswell", &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG,
+           "Haswell", &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG,
+           "Haswell", &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG,
+           "Haswell", &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG,
+           "Haswell", &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG,
+           "Haswell", &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_HASWELL_SDV,
+           "Haswell", &sandybridge_gtt_driver },
        { 0, NULL, NULL }
 };
 
index ffa888cd1c882818aebbe2eea0bedbc1929f439d..192000377737974f280aa75418a79864ce170455 100644 (file)
@@ -158,7 +158,6 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
                break;
        case LVL2_APER_SIZE:
                return -EINVAL;
-               break;
        default:
                num_entries = 0;
                break;
index 57501ca9204b017abce7b6a8f160a8e74769544e..46118f8459484a35c3a709c12a28512fd56820af 100644 (file)
@@ -301,7 +301,7 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)
                         * anything critical, chill a bit on each iteration.
                         */
                        while (wait_event_freezable(apm_suspend_waitqueue,
-                                       as->suspend_state == SUSPEND_DONE))
+                                       as->suspend_state != SUSPEND_ACKED))
                                msleep(10);
                        break;
                case SUSPEND_ACKTO:
index 3845ab44c3304e1d2e4ce0f8bfc7455cd5ef6717..dfd7876f127c0d23c9d45bc2922ccefe85ff3181 100644 (file)
@@ -906,8 +906,8 @@ int hpet_alloc(struct hpet_data *hdp)
                hpetp->hp_which, hdp->hd_phys_address,
                hpetp->hp_ntimer > 1 ? "s" : "");
        for (i = 0; i < hpetp->hp_ntimer; i++)
-               printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
-       printk("\n");
+               printk(KERN_CONT "%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
+       printk(KERN_CONT "\n");
 
        temp = hpetp->hp_tick_freq;
        remainder = do_div(temp, 1000000);
index 54ca8b23cde3f1aa5550d2806087300227531070..4ec04a754733baed5dd8595256a9c7998965d323 100644 (file)
@@ -1260,10 +1260,15 @@ static int proc_do_uuid(ctl_table *table, int write,
        uuid = table->data;
        if (!uuid) {
                uuid = tmp_uuid;
-               uuid[8] = 0;
-       }
-       if (uuid[8] == 0)
                generate_random_uuid(uuid);
+       } else {
+               static DEFINE_SPINLOCK(bootid_spinlock);
+
+               spin_lock(&bootid_spinlock);
+               if (!uuid[8])
+                       generate_random_uuid(uuid);
+               spin_unlock(&bootid_spinlock);
+       }
 
        sprintf(buf, "%pU", uuid);
 
index 4dc019408fac7aa04b59e95f7deed8fb586ffe9e..3b22a606f79dc143abbece02b4893a71deee6e1b 100644 (file)
@@ -194,17 +194,17 @@ static ssize_t srom_read(struct file *filp, char __user *buf,
 
                hv_retval = _srom_read(srom->hv_devhdl, kernbuf,
                                       *f_pos, bytes_this_pass);
-               if (hv_retval > 0) {
-                       if (copy_to_user(buf, kernbuf, hv_retval) != 0) {
-                               retval = -EFAULT;
-                               break;
-                       }
-               } else if (hv_retval <= 0) {
+               if (hv_retval <= 0) {
                        if (retval == 0)
                                retval = hv_retval;
                        break;
                }
 
+               if (copy_to_user(buf, kernbuf, hv_retval) != 0) {
+                       retval = -EFAULT;
+                       break;
+               }
+
                retval += hv_retval;
                *f_pos += hv_retval;
                buf += hv_retval;
index b58b5618706588936ebcf7a028bde7dba8f616c1..ddf86b6500b7d705ef5853405c265ef5b2f19868 100644 (file)
@@ -1038,12 +1038,6 @@ static struct attribute_group port_attribute_group = {
        .attrs = port_sysfs_entries,
 };
 
-static int debugfs_open(struct inode *inode, struct file *filp)
-{
-       filp->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t debugfs_read(struct file *filp, char __user *ubuf,
                            size_t count, loff_t *offp)
 {
@@ -1087,7 +1081,7 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf,
 
 static const struct file_operations port_debugfs_ops = {
        .owner = THIS_MODULE,
-       .open  = debugfs_open,
+       .open  = simple_open,
        .read  = debugfs_read,
 };
 
index 82e882028fcf2172e7a1faaf5aec0f125238a952..6b5cf02c35c88147970c69cd19048650bff7610d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/async.h>
 #include <asm/io.h>
 
 /*
@@ -180,15 +179,17 @@ static int verify_pmtmr_rate(void)
 /* Number of reads we try to get two different values */
 #define ACPI_PM_READ_CHECKS 10000
 
-static void __init acpi_pm_clocksource_async(void *unused, async_cookie_t cookie)
+static int __init init_acpi_pm_clocksource(void)
 {
        cycle_t value1, value2;
        unsigned int i, j = 0;
 
+       if (!pmtmr_ioport)
+               return -ENODEV;
 
        /* "verify" this timing source: */
        for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
-               usleep_range(100 * j, 100 * j + 100);
+               udelay(100 * j);
                value1 = clocksource_acpi_pm.read(&clocksource_acpi_pm);
                for (i = 0; i < ACPI_PM_READ_CHECKS; i++) {
                        value2 = clocksource_acpi_pm.read(&clocksource_acpi_pm);
@@ -202,34 +203,25 @@ static void __init acpi_pm_clocksource_async(void *unused, async_cookie_t cookie
                               " 0x%#llx, 0x%#llx - aborting.\n",
                               value1, value2);
                        pmtmr_ioport = 0;
-                       return;
+                       return -EINVAL;
                }
                if (i == ACPI_PM_READ_CHECKS) {
                        printk(KERN_INFO "PM-Timer failed consistency check "
                               " (0x%#llx) - aborting.\n", value1);
                        pmtmr_ioport = 0;
-                       return;
+                       return -ENODEV;
                }
        }
 
        if (verify_pmtmr_rate() != 0){
                pmtmr_ioport = 0;
-               return;
+               return -ENODEV;
        }
 
-       clocksource_register_hz(&clocksource_acpi_pm,
+       return clocksource_register_hz(&clocksource_acpi_pm,
                                                PMTMR_TICKS_PER_SEC);
 }
 
-static int __init init_acpi_pm_clocksource(void)
-{
-       if (!pmtmr_ioport)
-               return -ENODEV;
-
-       async_schedule(acpi_pm_clocksource_async, NULL);
-       return 0;
-}
-
 /* We use fs_initcall because we want the PCI fixups to have run
  * but we still need to load before device_initcall
  */
index 32d790dd818040cab62f2609c79b4cf08168b03d..5961e6415f082a54e4a29a0980d48857a724cc7c 100644 (file)
@@ -4,6 +4,7 @@
 
 config ARM_OMAP2PLUS_CPUFREQ
        bool "TI OMAP2+"
+       depends on ARCH_OMAP2PLUS
        default ARCH_OMAP2PLUS
        select CPU_FREQ_TABLE
 
@@ -51,9 +52,6 @@ config ARM_S5PV210_CPUFREQ
 config ARM_EXYNOS_CPUFREQ
        bool "SAMSUNG EXYNOS SoCs"
        depends on ARCH_EXYNOS
-       select ARM_EXYNOS4210_CPUFREQ if CPU_EXYNOS4210
-       select ARM_EXYNOS4X12_CPUFREQ if (SOC_EXYNOS4212 || SOC_EXYNOS4412)
-       select ARM_EXYNOS5250_CPUFREQ if SOC_EXYNOS5250
        default y
        help
          This adds the CPUFreq driver common part for Samsung
@@ -62,20 +60,19 @@ config ARM_EXYNOS_CPUFREQ
          If in doubt, say N.
 
 config ARM_EXYNOS4210_CPUFREQ
-       bool "Samsung EXYNOS4210"
-       depends on ARCH_EXYNOS
+       def_bool CPU_EXYNOS4210
        help
          This adds the CPUFreq driver for Samsung EXYNOS4210
          SoC (S5PV310 or S5PC210).
 
 config ARM_EXYNOS4X12_CPUFREQ
-       bool "Samsung EXYNOS4X12"
+       def_bool (SOC_EXYNOS4212 || SOC_EXYNOS4412)
        help
          This adds the CPUFreq driver for Samsung EXYNOS4X12
          SoC (EXYNOS4212 or EXYNOS4412).
 
 config ARM_EXYNOS5250_CPUFREQ
-       bool "Samsung EXYNOS5250"
+       def_bool SOC_EXYNOS5250
        help
          This adds the CPUFreq driver for Samsung EXYNOS5250
          SoC.
index a22ffa5bff9f85ca9ba961dc8896aa8be65c8fa3..0bf1b8910eebe74a6e86a32b3338ddf0a6d1ef1a 100644 (file)
@@ -142,7 +142,7 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
        policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */
 
        /* policy sharing between dual CPUs */
-       cpumask_copy(policy->cpus, &cpu_present_map);
+       cpumask_copy(policy->cpus, cpu_present_mask);
 
        policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
 
index 87411cebc57725223a994eb6467ad0aa209d3515..2f0083a51a9aeb5979e145eca98b686f4dd3c196 100644 (file)
@@ -74,7 +74,7 @@ static cpuidle_enter_t cpuidle_enter_ops;
 /**
  * cpuidle_play_dead - cpu off-lining
  *
- * Only returns in case of an error
+ * Returns in case of an error or no driver
  */
 int cpuidle_play_dead(void)
 {
@@ -83,6 +83,9 @@ int cpuidle_play_dead(void)
        int i, dead_state = -1;
        int power_usage = -1;
 
+       if (!drv)
+               return -ENODEV;
+
        /* Find lowest-power state that supports long-term idle */
        for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
                struct cpuidle_state *s = &drv->states[i];
index 0053d7ebb5cae0a479eacf0d22c69606509644ea..8f3f74ce8c7fd7ac95e241c2c4504f06a52da38c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/gfp.h>
+#include <linux/module.h>
 
 #include <crypto/ctr.h>
 #include <crypto/des.h>
index dc641c79652650dbe7bc02ce5d3b0e889427e376..921039e56f87f9360156074233c9e38828bc1612 100644 (file)
@@ -124,6 +124,9 @@ struct talitos_private {
        void __iomem *reg;
        int irq[2];
 
+       /* SEC global registers lock  */
+       spinlock_t reg_lock ____cacheline_aligned;
+
        /* SEC version geometry (from device tree node) */
        unsigned int num_channels;
        unsigned int chfifo_len;
@@ -412,6 +415,7 @@ static void talitos_done_##name(unsigned long data)                 \
 {                                                                      \
        struct device *dev = (struct device *)data;                     \
        struct talitos_private *priv = dev_get_drvdata(dev);            \
+       unsigned long flags;                                            \
                                                                        \
        if (ch_done_mask & 1)                                           \
                flush_channel(dev, 0, 0, 0);                            \
@@ -427,8 +431,10 @@ static void talitos_done_##name(unsigned long data)                        \
 out:                                                                   \
        /* At this point, all completed channels have been processed */ \
        /* Unmask done interrupts for channels completed later on. */   \
+       spin_lock_irqsave(&priv->reg_lock, flags);                      \
        setbits32(priv->reg + TALITOS_IMR, ch_done_mask);               \
        setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);     \
+       spin_unlock_irqrestore(&priv->reg_lock, flags);                 \
 }
 DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
 DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
@@ -619,22 +625,28 @@ static irqreturn_t talitos_interrupt_##name(int irq, void *data)         \
        struct device *dev = data;                                             \
        struct talitos_private *priv = dev_get_drvdata(dev);                   \
        u32 isr, isr_lo;                                                       \
+       unsigned long flags;                                                   \
                                                                               \
+       spin_lock_irqsave(&priv->reg_lock, flags);                             \
        isr = in_be32(priv->reg + TALITOS_ISR);                                \
        isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);                          \
        /* Acknowledge interrupt */                                            \
        out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
        out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);                          \
                                                                               \
-       if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo))    \
-               talitos_error(dev, isr, isr_lo);                               \
-       else                                                                   \
+       if (unlikely(isr & ch_err_mask || isr_lo)) {                           \
+               spin_unlock_irqrestore(&priv->reg_lock, flags);                \
+               talitos_error(dev, isr & ch_err_mask, isr_lo);                 \
+       }                                                                      \
+       else {                                                                 \
                if (likely(isr & ch_done_mask)) {                              \
                        /* mask further done interrupts. */                    \
                        clrbits32(priv->reg + TALITOS_IMR, ch_done_mask);      \
                        /* done_task will unmask done interrupts at exit */    \
                        tasklet_schedule(&priv->done_task[tlet]);              \
                }                                                              \
+               spin_unlock_irqrestore(&priv->reg_lock, flags);                \
+       }                                                                      \
                                                                               \
        return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED :  \
                                                                IRQ_NONE;      \
@@ -2719,6 +2731,8 @@ static int talitos_probe(struct platform_device *ofdev)
 
        priv->ofdev = ofdev;
 
+       spin_lock_init(&priv->reg_lock);
+
        err = talitos_probe_irq(ofdev);
        if (err)
                goto err_out;
index cf9da362d64f9a233512ce7a228bccad25906197..ef378b5b17e49079075f1fdf3f5834cca90f05a7 100644 (file)
@@ -91,11 +91,10 @@ config DW_DMAC
 
 config AT_HDMAC
        tristate "Atmel AHB DMA support"
-       depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
+       depends on ARCH_AT91
        select DMA_ENGINE
        help
-         Support the Atmel AHB DMA controller.  This can be integrated in
-         chips such as the Atmel AT91SAM9RL.
+         Support the Atmel AHB DMA controller.
 
 config FSL_DMA
        tristate "Freescale Elo and Elo Plus DMA support"
index c301a8ec31aa109583cd4ab54bc9304c3e95ceb2..3d704abd7912b1ce9a2bd236e84188fdd81aace3 100644 (file)
@@ -1429,6 +1429,7 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                         * signal
                         */
                        release_phy_channel(plchan);
+                       plchan->phychan_hold = 0;
                }
                /* Dequeue jobs and free LLIs */
                if (plchan->at) {
index 7aa58d2048923721d7448464120515137ecc961f..445fdf8116959e91bff7469bf45c6283e057b198 100644 (file)
@@ -221,10 +221,6 @@ static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first)
 
        vdbg_dump_regs(atchan);
 
-       /* clear any pending interrupt */
-       while (dma_readl(atdma, EBCISR))
-               cpu_relax();
-
        channel_writel(atchan, SADDR, 0);
        channel_writel(atchan, DADDR, 0);
        channel_writel(atchan, CTRLA, 0);
index dc89455f5550c90ffec150d16f3d0e06e5614ee0..750925f9638bab656b39ccff65bed7dbdbee405c 100644 (file)
@@ -104,13 +104,6 @@ static void coh901318_list_print(struct coh901318_chan *cohc,
 static struct coh901318_base *debugfs_dma_base;
 static struct dentry *dma_dentry;
 
-static int coh901318_debugfs_open(struct inode *inode, struct file *file)
-{
-
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static int coh901318_debugfs_read(struct file *file, char __user *buf,
                                  size_t count, loff_t *f_pos)
 {
@@ -158,7 +151,7 @@ static int coh901318_debugfs_read(struct file *file, char __user *buf,
 
 static const struct file_operations coh901318_debugfs_status_operations = {
        .owner          = THIS_MODULE,
-       .open           = coh901318_debugfs_open,
+       .open           = simple_open,
        .read           = coh901318_debugfs_read,
        .llseek         = default_llseek,
 };
index 767bcc31b3653b7813a9acbde71f2fcd1f3a0130..2397f6f451b15ccb274d367c9955cefa27c56013 100644 (file)
@@ -332,6 +332,20 @@ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type)
 }
 EXPORT_SYMBOL(dma_find_channel);
 
+/*
+ * net_dma_find_channel - find a channel for net_dma
+ * net_dma has alignment requirements
+ */
+struct dma_chan *net_dma_find_channel(void)
+{
+       struct dma_chan *chan = dma_find_channel(DMA_MEMCPY);
+       if (chan && !is_dma_copy_aligned(chan->device, 1, 1, 1))
+               return NULL;
+
+       return chan;
+}
+EXPORT_SYMBOL(net_dma_find_channel);
+
 /**
  * dma_issue_pending_all - flush all pending operations across all channels
  */
index a45b5d2a59879a02b3566dfaf2c8304f8d693921..bb787d8e15296ed17eef8032be17f4b52647d173 100644 (file)
@@ -571,11 +571,14 @@ static void imxdma_tasklet(unsigned long data)
        if (desc->desc.callback)
                desc->desc.callback(desc->desc.callback_param);
 
-       dma_cookie_complete(&desc->desc);
-
-       /* If we are dealing with a cyclic descriptor keep it on ld_active */
+       /* If we are dealing with a cyclic descriptor keep it on ld_active
+        * and dont mark the descripor as complete.
+        * Only in non-cyclic cases it would be marked as complete
+        */
        if (imxdma_chan_is_doing_cyclic(imxdmac))
                goto out;
+       else
+               dma_cookie_complete(&desc->desc);
 
        /* Free 2D slot if it was an interleaved transfer */
        if (imxdmac->enabled_2d) {
index 31493d80e0e9dd0538546703317dbf60abe2247e..73b2b65cb1deed2ccfb16d5f3e81dbeaa47f7ec1 100644 (file)
@@ -546,9 +546,9 @@ void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
                           PCI_DMA_TODEVICE, flags, 0);
 }
 
-unsigned long ioat_get_current_completion(struct ioat_chan_common *chan)
+dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan)
 {
-       unsigned long phys_complete;
+       dma_addr_t phys_complete;
        u64 completion;
 
        completion = *chan->completion;
@@ -569,7 +569,7 @@ unsigned long ioat_get_current_completion(struct ioat_chan_common *chan)
 }
 
 bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
-                          unsigned long *phys_complete)
+                          dma_addr_t *phys_complete)
 {
        *phys_complete = ioat_get_current_completion(chan);
        if (*phys_complete == chan->last_completion)
@@ -580,14 +580,14 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
        return true;
 }
 
-static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat_dma_chan *ioat, dma_addr_t phys_complete)
 {
        struct ioat_chan_common *chan = &ioat->base;
        struct list_head *_desc, *n;
        struct dma_async_tx_descriptor *tx;
 
-       dev_dbg(to_dev(chan), "%s: phys_complete: %lx\n",
-                __func__, phys_complete);
+       dev_dbg(to_dev(chan), "%s: phys_complete: %llx\n",
+                __func__, (unsigned long long) phys_complete);
        list_for_each_safe(_desc, n, &ioat->used_desc) {
                struct ioat_desc_sw *desc;
 
@@ -652,7 +652,7 @@ static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete)
 static void ioat1_cleanup(struct ioat_dma_chan *ioat)
 {
        struct ioat_chan_common *chan = &ioat->base;
-       unsigned long phys_complete;
+       dma_addr_t phys_complete;
 
        prefetch(chan->completion);
 
@@ -698,7 +698,7 @@ static void ioat1_timer_event(unsigned long data)
                mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);
                spin_unlock_bh(&ioat->desc_lock);
        } else if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
-               unsigned long phys_complete;
+               dma_addr_t phys_complete;
 
                spin_lock_bh(&ioat->desc_lock);
                /* if we haven't made progress and we have already
index c7888bccd9740c6cefba7719c1e33cc724a7152d..5e8fe01ba69d574c3eef5cf0cb8f3ab765fb7c72 100644 (file)
@@ -88,7 +88,7 @@ struct ioatdma_device {
 struct ioat_chan_common {
        struct dma_chan common;
        void __iomem *reg_base;
-       unsigned long last_completion;
+       dma_addr_t last_completion;
        spinlock_t cleanup_lock;
        unsigned long state;
        #define IOAT_COMPLETION_PENDING 0
@@ -310,7 +310,7 @@ int __devinit ioat_dma_self_test(struct ioatdma_device *device);
 void __devexit ioat_dma_remove(struct ioatdma_device *device);
 struct dca_provider * __devinit ioat_dca_init(struct pci_dev *pdev,
                                              void __iomem *iobase);
-unsigned long ioat_get_current_completion(struct ioat_chan_common *chan);
+dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan);
 void ioat_init_channel(struct ioatdma_device *device,
                       struct ioat_chan_common *chan, int idx);
 enum dma_status ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
@@ -318,7 +318,7 @@ enum dma_status ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
 void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
                    size_t len, struct ioat_dma_descriptor *hw);
 bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
-                          unsigned long *phys_complete);
+                          dma_addr_t *phys_complete);
 void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
 void ioat_kobject_del(struct ioatdma_device *device);
 extern const struct sysfs_ops ioat_sysfs_ops;
index e8e110ff3d965547b03f7bbf80cddcb58911a031..86895760b598ef61ca63ebce58f3c1f2e5093cbf 100644 (file)
@@ -128,7 +128,7 @@ static void ioat2_start_null_desc(struct ioat2_dma_chan *ioat)
        spin_unlock_bh(&ioat->prep_lock);
 }
 
-static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
 {
        struct ioat_chan_common *chan = &ioat->base;
        struct dma_async_tx_descriptor *tx;
@@ -179,7 +179,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
 static void ioat2_cleanup(struct ioat2_dma_chan *ioat)
 {
        struct ioat_chan_common *chan = &ioat->base;
-       unsigned long phys_complete;
+       dma_addr_t phys_complete;
 
        spin_lock_bh(&chan->cleanup_lock);
        if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -260,7 +260,7 @@ int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo)
 static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
 {
        struct ioat_chan_common *chan = &ioat->base;
-       unsigned long phys_complete;
+       dma_addr_t phys_complete;
 
        ioat2_quiesce(chan, 0);
        if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -275,7 +275,7 @@ void ioat2_timer_event(unsigned long data)
        struct ioat_chan_common *chan = &ioat->base;
 
        if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
-               unsigned long phys_complete;
+               dma_addr_t phys_complete;
                u64 status;
 
                status = ioat_chansts(chan);
@@ -572,9 +572,9 @@ bool reshape_ring(struct ioat2_dma_chan *ioat, int order)
         */
        struct ioat_chan_common *chan = &ioat->base;
        struct dma_chan *c = &chan->common;
-       const u16 curr_size = ioat2_ring_size(ioat);
+       const u32 curr_size = ioat2_ring_size(ioat);
        const u16 active = ioat2_ring_active(ioat);
-       const u16 new_size = 1 << order;
+       const u32 new_size = 1 << order;
        struct ioat_ring_ent **ring;
        u16 i;
 
index a2c413b2b8d8d77c8cd5b30e03956e8baed6da1c..be2a55b95c2365848a6da33de2bf91269ea97b14 100644 (file)
@@ -74,7 +74,7 @@ static inline struct ioat2_dma_chan *to_ioat2_chan(struct dma_chan *c)
        return container_of(chan, struct ioat2_dma_chan, base);
 }
 
-static inline u16 ioat2_ring_size(struct ioat2_dma_chan *ioat)
+static inline u32 ioat2_ring_size(struct ioat2_dma_chan *ioat)
 {
        return 1 << ioat->alloc_order;
 }
@@ -91,7 +91,7 @@ static inline u16 ioat2_ring_pending(struct ioat2_dma_chan *ioat)
        return CIRC_CNT(ioat->head, ioat->issued, ioat2_ring_size(ioat));
 }
 
-static inline u16 ioat2_ring_space(struct ioat2_dma_chan *ioat)
+static inline u32 ioat2_ring_space(struct ioat2_dma_chan *ioat)
 {
        return ioat2_ring_size(ioat) - ioat2_ring_active(ioat);
 }
index 2c4476c0e405be9ce3b547b6a0da7cc814eecc07..f7f1dc62c15c1a0dc4d27f676f86eefaebe73e5e 100644 (file)
@@ -257,7 +257,7 @@ static bool desc_has_ext(struct ioat_ring_ent *desc)
  * The difference from the dma_v2.c __cleanup() is that this routine
  * handles extended descriptors and dma-unmapping raid operations.
  */
-static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
 {
        struct ioat_chan_common *chan = &ioat->base;
        struct ioat_ring_ent *desc;
@@ -314,7 +314,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
 static void ioat3_cleanup(struct ioat2_dma_chan *ioat)
 {
        struct ioat_chan_common *chan = &ioat->base;
-       unsigned long phys_complete;
+       dma_addr_t phys_complete;
 
        spin_lock_bh(&chan->cleanup_lock);
        if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -333,7 +333,7 @@ static void ioat3_cleanup_event(unsigned long data)
 static void ioat3_restart_channel(struct ioat2_dma_chan *ioat)
 {
        struct ioat_chan_common *chan = &ioat->base;
-       unsigned long phys_complete;
+       dma_addr_t phys_complete;
 
        ioat2_quiesce(chan, 0);
        if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -348,7 +348,7 @@ static void ioat3_timer_event(unsigned long data)
        struct ioat_chan_common *chan = &ioat->base;
 
        if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
-               unsigned long phys_complete;
+               dma_addr_t phys_complete;
                u64 status;
 
                status = ioat_chansts(chan);
@@ -1149,6 +1149,44 @@ static int ioat3_reset_hw(struct ioat_chan_common *chan)
        return ioat2_reset_sync(chan, msecs_to_jiffies(200));
 }
 
+static bool is_jf_ioat(struct pci_dev *pdev)
+{
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF0:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF1:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF2:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF3:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF4:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF5:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF6:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF7:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF8:
+       case PCI_DEVICE_ID_INTEL_IOAT_JSF9:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool is_snb_ioat(struct pci_dev *pdev)
+{
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB0:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB1:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB2:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB3:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB4:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB5:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB6:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB7:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB8:
+       case PCI_DEVICE_ID_INTEL_IOAT_SNB9:
+               return true;
+       default:
+               return false;
+       }
+}
+
 int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
 {
        struct pci_dev *pdev = device->pdev;
@@ -1169,6 +1207,9 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
        dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;
        dma->device_free_chan_resources = ioat2_free_chan_resources;
 
+       if (is_jf_ioat(pdev) || is_snb_ioat(pdev))
+               dma->copy_align = 6;
+
        dma_cap_set(DMA_INTERRUPT, dma->cap_mask);
        dma->device_prep_dma_interrupt = ioat3_prep_interrupt_lock;
 
index da6c4c2c066a96b68cdb0765ba4e017112f1c7a6..79e3eba297029f465c4ba949f8e7c4a66a0c1a90 100644 (file)
@@ -1252,8 +1252,8 @@ iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
        struct page **pq_hw = &pq[IOP_ADMA_NUM_SRC_TEST+2];
        /* address conversion buffers (dma_map / page_address) */
        void *pq_sw[IOP_ADMA_NUM_SRC_TEST+2];
-       dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST];
-       dma_addr_t pq_dest[2];
+       dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST+2];
+       dma_addr_t *pq_dest = &pq_src[IOP_ADMA_NUM_SRC_TEST];
 
        int i;
        struct dma_async_tx_descriptor *tx;
index c81ef7e10e08283ce8eaf4fadf6166b5d3ddc19c..655d4ce6ed0d94fcae71ed687641f707e08a8ed8 100644 (file)
@@ -201,10 +201,6 @@ static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
 
 static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
-       struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(tx->chan);
-
-       mxs_dma_enable_chan(mxs_chan);
-
        return dma_cookie_assign(tx);
 }
 
@@ -558,9 +554,9 @@ static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
 
 static void mxs_dma_issue_pending(struct dma_chan *chan)
 {
-       /*
-        * Nothing to do. We only have a single descriptor.
-        */
+       struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+
+       mxs_dma_enable_chan(mxs_chan);
 }
 
 static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
index 282caf118be819c5e9257754a369efd292607951..2ee6e23930ad3258e89bef7513e2c3158b7fe06f 100644 (file)
@@ -2225,12 +2225,9 @@ static inline void free_desc_list(struct list_head *list)
 {
        struct dma_pl330_dmac *pdmac;
        struct dma_pl330_desc *desc;
-       struct dma_pl330_chan *pch;
+       struct dma_pl330_chan *pch = NULL;
        unsigned long flags;
 
-       if (list_empty(list))
-               return;
-
        /* Finish off the work list */
        list_for_each_entry(desc, list, node) {
                dma_async_tx_callback callback;
@@ -2247,6 +2244,10 @@ static inline void free_desc_list(struct list_head *list)
                desc->pchan = NULL;
        }
 
+       /* pch will be unset if list was empty */
+       if (!pch)
+               return;
+
        pdmac = pch->dmac;
 
        spin_lock_irqsave(&pdmac->pool_lock, flags);
@@ -2257,12 +2258,9 @@ static inline void free_desc_list(struct list_head *list)
 static inline void handle_cyclic_desc_list(struct list_head *list)
 {
        struct dma_pl330_desc *desc;
-       struct dma_pl330_chan *pch;
+       struct dma_pl330_chan *pch = NULL;
        unsigned long flags;
 
-       if (list_empty(list))
-               return;
-
        list_for_each_entry(desc, list, node) {
                dma_async_tx_callback callback;
 
@@ -2274,6 +2272,10 @@ static inline void handle_cyclic_desc_list(struct list_head *list)
                        callback(desc->txd.callback_param);
        }
 
+       /* pch will be unset if list was empty */
+       if (!pch)
+               return;
+
        spin_lock_irqsave(&pch->lock, flags);
        list_splice_tail_init(list, &pch->work_list);
        spin_unlock_irqrestore(&pch->lock, flags);
@@ -2926,8 +2928,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        INIT_LIST_HEAD(&pd->channels);
 
        /* Initialize channel parameters */
-       num_chan = max(pdat ? pdat->nr_valid_peri : (u8)pi->pcfg.num_peri,
-                       (u8)pi->pcfg.num_chan);
+       if (pdat)
+               num_chan = max_t(int, pdat->nr_valid_peri, pi->pcfg.num_chan);
+       else
+               num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);
+
        pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
 
        for (i = 0; i < num_chan; i++) {
index 16a6b48883cf28c131e7143f045b183f140b7cd8..ec78ccef91325c46dfb4098433da5de42007cc32 100644 (file)
@@ -585,7 +585,7 @@ static dma_cookie_t sa11x0_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 
 static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
        struct dma_chan *chan, struct scatterlist *sg, unsigned int sglen,
-       enum dma_transfer_direction dir, unsigned long flags)
+       enum dma_transfer_direction dir, unsigned long flags, void *context)
 {
        struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
        struct sa11x0_dma_desc *txd;
index bdd41d4bfa8d8f8bd129e4efffbf0b7187755fa1..2ed1ac3513f3d4de118d7937f40fadc202748a93 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/err.h>
 #include <linux/amba/bus.h>
+#include <linux/regulator/consumer.h>
 
 #include <plat/ste_dma40.h>
 
@@ -68,6 +69,22 @@ enum d40_command {
        D40_DMA_SUSPENDED       = 3
 };
 
+/*
+ * enum d40_events - The different Event Enables for the event lines.
+ *
+ * @D40_DEACTIVATE_EVENTLINE: De-activate Event line, stopping the logical chan.
+ * @D40_ACTIVATE_EVENTLINE: Activate the Event line, to start a logical chan.
+ * @D40_SUSPEND_REQ_EVENTLINE: Requesting for suspending a event line.
+ * @D40_ROUND_EVENTLINE: Status check for event line.
+ */
+
+enum d40_events {
+       D40_DEACTIVATE_EVENTLINE        = 0,
+       D40_ACTIVATE_EVENTLINE          = 1,
+       D40_SUSPEND_REQ_EVENTLINE       = 2,
+       D40_ROUND_EVENTLINE             = 3
+};
+
 /*
  * These are the registers that has to be saved and later restored
  * when the DMA hw is powered off.
@@ -870,8 +887,8 @@ static void d40_save_restore_registers(struct d40_base *base, bool save)
 }
 #endif
 
-static int d40_channel_execute_command(struct d40_chan *d40c,
-                                      enum d40_command command)
+static int __d40_execute_command_phy(struct d40_chan *d40c,
+                                    enum d40_command command)
 {
        u32 status;
        int i;
@@ -880,6 +897,12 @@ static int d40_channel_execute_command(struct d40_chan *d40c,
        unsigned long flags;
        u32 wmask;
 
+       if (command == D40_DMA_STOP) {
+               ret = __d40_execute_command_phy(d40c, D40_DMA_SUSPEND_REQ);
+               if (ret)
+                       return ret;
+       }
+
        spin_lock_irqsave(&d40c->base->execmd_lock, flags);
 
        if (d40c->phy_chan->num % 2 == 0)
@@ -973,67 +996,109 @@ static void d40_term_all(struct d40_chan *d40c)
                }
 
        d40c->pending_tx = 0;
-       d40c->busy = false;
 }
 
-static void __d40_config_set_event(struct d40_chan *d40c, bool enable,
-                                  u32 event, int reg)
+static void __d40_config_set_event(struct d40_chan *d40c,
+                                  enum d40_events event_type, u32 event,
+                                  int reg)
 {
        void __iomem *addr = chan_base(d40c) + reg;
        int tries;
+       u32 status;
+
+       switch (event_type) {
+
+       case D40_DEACTIVATE_EVENTLINE:
 
-       if (!enable) {
                writel((D40_DEACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event))
                       | ~D40_EVENTLINE_MASK(event), addr);
-               return;
-       }
+               break;
+
+       case D40_SUSPEND_REQ_EVENTLINE:
+               status = (readl(addr) & D40_EVENTLINE_MASK(event)) >>
+                         D40_EVENTLINE_POS(event);
+
+               if (status == D40_DEACTIVATE_EVENTLINE ||
+                   status == D40_SUSPEND_REQ_EVENTLINE)
+                       break;
 
+               writel((D40_SUSPEND_REQ_EVENTLINE << D40_EVENTLINE_POS(event))
+                      | ~D40_EVENTLINE_MASK(event), addr);
+
+               for (tries = 0 ; tries < D40_SUSPEND_MAX_IT; tries++) {
+
+                       status = (readl(addr) & D40_EVENTLINE_MASK(event)) >>
+                                 D40_EVENTLINE_POS(event);
+
+                       cpu_relax();
+                       /*
+                        * Reduce the number of bus accesses while
+                        * waiting for the DMA to suspend.
+                        */
+                       udelay(3);
+
+                       if (status == D40_DEACTIVATE_EVENTLINE)
+                               break;
+               }
+
+               if (tries == D40_SUSPEND_MAX_IT) {
+                       chan_err(d40c,
+                               "unable to stop the event_line chl %d (log: %d)"
+                               "status %x\n", d40c->phy_chan->num,
+                                d40c->log_num, status);
+               }
+               break;
+
+       case D40_ACTIVATE_EVENTLINE:
        /*
         * The hardware sometimes doesn't register the enable when src and dst
         * event lines are active on the same logical channel.  Retry to ensure
         * it does.  Usually only one retry is sufficient.
         */
-       tries = 100;
-       while (--tries) {
-               writel((D40_ACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event))
-                      | ~D40_EVENTLINE_MASK(event), addr);
+               tries = 100;
+               while (--tries) {
+                       writel((D40_ACTIVATE_EVENTLINE <<
+                               D40_EVENTLINE_POS(event)) |
+                               ~D40_EVENTLINE_MASK(event), addr);
 
-               if (readl(addr) & D40_EVENTLINE_MASK(event))
-                       break;
-       }
+                       if (readl(addr) & D40_EVENTLINE_MASK(event))
+                               break;
+               }
 
-       if (tries != 99)
-               dev_dbg(chan2dev(d40c),
-                       "[%s] workaround enable S%cLNK (%d tries)\n",
-                       __func__, reg == D40_CHAN_REG_SSLNK ? 'S' : 'D',
-                       100 - tries);
+               if (tries != 99)
+                       dev_dbg(chan2dev(d40c),
+                               "[%s] workaround enable S%cLNK (%d tries)\n",
+                               __func__, reg == D40_CHAN_REG_SSLNK ? 'S' : 'D',
+                               100 - tries);
 
-       WARN_ON(!tries);
-}
+               WARN_ON(!tries);
+               break;
 
-static void d40_config_set_event(struct d40_chan *d40c, bool do_enable)
-{
-       unsigned long flags;
+       case D40_ROUND_EVENTLINE:
+               BUG();
+               break;
 
-       spin_lock_irqsave(&d40c->phy_chan->lock, flags);
+       }
+}
 
+static void d40_config_set_event(struct d40_chan *d40c,
+                                enum d40_events event_type)
+{
        /* Enable event line connected to device (or memcpy) */
        if ((d40c->dma_cfg.dir ==  STEDMA40_PERIPH_TO_MEM) ||
            (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) {
                u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
 
-               __d40_config_set_event(d40c, do_enable, event,
+               __d40_config_set_event(d40c, event_type, event,
                                       D40_CHAN_REG_SSLNK);
        }
 
        if (d40c->dma_cfg.dir !=  STEDMA40_PERIPH_TO_MEM) {
                u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
 
-               __d40_config_set_event(d40c, do_enable, event,
+               __d40_config_set_event(d40c, event_type, event,
                                       D40_CHAN_REG_SDLNK);
        }
-
-       spin_unlock_irqrestore(&d40c->phy_chan->lock, flags);
 }
 
 static u32 d40_chan_has_events(struct d40_chan *d40c)
@@ -1047,6 +1112,64 @@ static u32 d40_chan_has_events(struct d40_chan *d40c)
        return val;
 }
 
+static int
+__d40_execute_command_log(struct d40_chan *d40c, enum d40_command command)
+{
+       unsigned long flags;
+       int ret = 0;
+       u32 active_status;
+       void __iomem *active_reg;
+
+       if (d40c->phy_chan->num % 2 == 0)
+               active_reg = d40c->base->virtbase + D40_DREG_ACTIVE;
+       else
+               active_reg = d40c->base->virtbase + D40_DREG_ACTIVO;
+
+
+       spin_lock_irqsave(&d40c->phy_chan->lock, flags);
+
+       switch (command) {
+       case D40_DMA_STOP:
+       case D40_DMA_SUSPEND_REQ:
+
+               active_status = (readl(active_reg) &
+                                D40_CHAN_POS_MASK(d40c->phy_chan->num)) >>
+                                D40_CHAN_POS(d40c->phy_chan->num);
+
+               if (active_status == D40_DMA_RUN)
+                       d40_config_set_event(d40c, D40_SUSPEND_REQ_EVENTLINE);
+               else
+                       d40_config_set_event(d40c, D40_DEACTIVATE_EVENTLINE);
+
+               if (!d40_chan_has_events(d40c) && (command == D40_DMA_STOP))
+                       ret = __d40_execute_command_phy(d40c, command);
+
+               break;
+
+       case D40_DMA_RUN:
+
+               d40_config_set_event(d40c, D40_ACTIVATE_EVENTLINE);
+               ret = __d40_execute_command_phy(d40c, command);
+               break;
+
+       case D40_DMA_SUSPENDED:
+               BUG();
+               break;
+       }
+
+       spin_unlock_irqrestore(&d40c->phy_chan->lock, flags);
+       return ret;
+}
+
+static int d40_channel_execute_command(struct d40_chan *d40c,
+                                      enum d40_command command)
+{
+       if (chan_is_logical(d40c))
+               return __d40_execute_command_log(d40c, command);
+       else
+               return __d40_execute_command_phy(d40c, command);
+}
+
 static u32 d40_get_prmo(struct d40_chan *d40c)
 {
        static const unsigned int phy_map[] = {
@@ -1149,15 +1272,7 @@ static int d40_pause(struct d40_chan *d40c)
        spin_lock_irqsave(&d40c->lock, flags);
 
        res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
-       if (res == 0) {
-               if (chan_is_logical(d40c)) {
-                       d40_config_set_event(d40c, false);
-                       /* Resume the other logical channels if any */
-                       if (d40_chan_has_events(d40c))
-                               res = d40_channel_execute_command(d40c,
-                                                                 D40_DMA_RUN);
-               }
-       }
+
        pm_runtime_mark_last_busy(d40c->base->dev);
        pm_runtime_put_autosuspend(d40c->base->dev);
        spin_unlock_irqrestore(&d40c->lock, flags);
@@ -1174,45 +1289,17 @@ static int d40_resume(struct d40_chan *d40c)
 
        spin_lock_irqsave(&d40c->lock, flags);
        pm_runtime_get_sync(d40c->base->dev);
-       if (d40c->base->rev == 0)
-               if (chan_is_logical(d40c)) {
-                       res = d40_channel_execute_command(d40c,
-                                                         D40_DMA_SUSPEND_REQ);
-                       goto no_suspend;
-               }
 
        /* If bytes left to transfer or linked tx resume job */
-       if (d40_residue(d40c) || d40_tx_is_linked(d40c)) {
-
-               if (chan_is_logical(d40c))
-                       d40_config_set_event(d40c, true);
-
+       if (d40_residue(d40c) || d40_tx_is_linked(d40c))
                res = d40_channel_execute_command(d40c, D40_DMA_RUN);
-       }
 
-no_suspend:
        pm_runtime_mark_last_busy(d40c->base->dev);
        pm_runtime_put_autosuspend(d40c->base->dev);
        spin_unlock_irqrestore(&d40c->lock, flags);
        return res;
 }
 
-static int d40_terminate_all(struct d40_chan *chan)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       ret = d40_pause(chan);
-       if (!ret && chan_is_physical(chan))
-               ret = d40_channel_execute_command(chan, D40_DMA_STOP);
-
-       spin_lock_irqsave(&chan->lock, flags);
-       d40_term_all(chan);
-       spin_unlock_irqrestore(&chan->lock, flags);
-
-       return ret;
-}
-
 static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
 {
        struct d40_chan *d40c = container_of(tx->chan,
@@ -1232,20 +1319,6 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
 
 static int d40_start(struct d40_chan *d40c)
 {
-       if (d40c->base->rev == 0) {
-               int err;
-
-               if (chan_is_logical(d40c)) {
-                       err = d40_channel_execute_command(d40c,
-                                                         D40_DMA_SUSPEND_REQ);
-                       if (err)
-                               return err;
-               }
-       }
-
-       if (chan_is_logical(d40c))
-               d40_config_set_event(d40c, true);
-
        return d40_channel_execute_command(d40c, D40_DMA_RUN);
 }
 
@@ -1258,10 +1331,10 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
        d40d = d40_first_queued(d40c);
 
        if (d40d != NULL) {
-               if (!d40c->busy)
+               if (!d40c->busy) {
                        d40c->busy = true;
-
-               pm_runtime_get_sync(d40c->base->dev);
+                       pm_runtime_get_sync(d40c->base->dev);
+               }
 
                /* Remove from queue */
                d40_desc_remove(d40d);
@@ -1388,8 +1461,8 @@ static void dma_tasklet(unsigned long data)
 
        return;
 
- err:
-       /* Rescue manoeuvre if receiving double interrupts */
+err:
+       /* Rescue manouver if receiving double interrupts */
        if (d40c->pending_tx > 0)
                d40c->pending_tx--;
        spin_unlock_irqrestore(&d40c->lock, flags);
@@ -1770,7 +1843,6 @@ static int d40_config_memcpy(struct d40_chan *d40c)
        return 0;
 }
 
-
 static int d40_free_dma(struct d40_chan *d40c)
 {
 
@@ -1806,43 +1878,18 @@ static int d40_free_dma(struct d40_chan *d40c)
        }
 
        pm_runtime_get_sync(d40c->base->dev);
-       res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
+       res = d40_channel_execute_command(d40c, D40_DMA_STOP);
        if (res) {
-               chan_err(d40c, "suspend failed\n");
+               chan_err(d40c, "stop failed\n");
                goto out;
        }
 
-       if (chan_is_logical(d40c)) {
-               /* Release logical channel, deactivate the event line */
+       d40_alloc_mask_free(phy, is_src, chan_is_logical(d40c) ? event : 0);
 
-               d40_config_set_event(d40c, false);
+       if (chan_is_logical(d40c))
                d40c->base->lookup_log_chans[d40c->log_num] = NULL;
-
-               /*
-                * Check if there are more logical allocation
-                * on this phy channel.
-                */
-               if (!d40_alloc_mask_free(phy, is_src, event)) {
-                       /* Resume the other logical channels if any */
-                       if (d40_chan_has_events(d40c)) {
-                               res = d40_channel_execute_command(d40c,
-                                                                 D40_DMA_RUN);
-                               if (res)
-                                       chan_err(d40c,
-                                               "Executing RUN command\n");
-                       }
-                       goto out;
-               }
-       } else {
-               (void) d40_alloc_mask_free(phy, is_src, 0);
-       }
-
-       /* Release physical channel */
-       res = d40_channel_execute_command(d40c, D40_DMA_STOP);
-       if (res) {
-               chan_err(d40c, "Failed to stop channel\n");
-               goto out;
-       }
+       else
+               d40c->base->lookup_phy_chans[phy->num] = NULL;
 
        if (d40c->busy) {
                pm_runtime_mark_last_busy(d40c->base->dev);
@@ -1852,7 +1899,6 @@ static int d40_free_dma(struct d40_chan *d40c)
        d40c->busy = false;
        d40c->phy_chan = NULL;
        d40c->configured = false;
-       d40c->base->lookup_phy_chans[phy->num] = NULL;
 out:
 
        pm_runtime_mark_last_busy(d40c->base->dev);
@@ -2070,7 +2116,7 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
        if (sg_next(&sg_src[sg_len - 1]) == sg_src)
                desc->cyclic = true;
 
-       if (direction != DMA_NONE) {
+       if (direction != DMA_TRANS_NONE) {
                dma_addr_t dev_addr = d40_get_dev_addr(chan, direction);
 
                if (direction == DMA_DEV_TO_MEM)
@@ -2371,6 +2417,31 @@ static void d40_issue_pending(struct dma_chan *chan)
        spin_unlock_irqrestore(&d40c->lock, flags);
 }
 
+static void d40_terminate_all(struct dma_chan *chan)
+{
+       unsigned long flags;
+       struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
+       int ret;
+
+       spin_lock_irqsave(&d40c->lock, flags);
+
+       pm_runtime_get_sync(d40c->base->dev);
+       ret = d40_channel_execute_command(d40c, D40_DMA_STOP);
+       if (ret)
+               chan_err(d40c, "Failed to stop channel\n");
+
+       d40_term_all(d40c);
+       pm_runtime_mark_last_busy(d40c->base->dev);
+       pm_runtime_put_autosuspend(d40c->base->dev);
+       if (d40c->busy) {
+               pm_runtime_mark_last_busy(d40c->base->dev);
+               pm_runtime_put_autosuspend(d40c->base->dev);
+       }
+       d40c->busy = false;
+
+       spin_unlock_irqrestore(&d40c->lock, flags);
+}
+
 static int
 dma40_config_to_halfchannel(struct d40_chan *d40c,
                            struct stedma40_half_channel_info *info,
@@ -2551,7 +2622,8 @@ static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 
        switch (cmd) {
        case DMA_TERMINATE_ALL:
-               return d40_terminate_all(d40c);
+               d40_terminate_all(chan);
+               return 0;
        case DMA_PAUSE:
                return d40_pause(d40c);
        case DMA_RESUME:
@@ -2908,6 +2980,12 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
        dev_info(&pdev->dev, "hardware revision: %d @ 0x%x\n",
                 rev, res->start);
 
+       if (rev < 2) {
+               d40_err(&pdev->dev, "hardware revision: %d is not supported",
+                       rev);
+               goto failure;
+       }
+
        plat_data = pdev->dev.platform_data;
 
        /* Count the number of logical channels in use */
@@ -2998,6 +3076,7 @@ failure:
 
        if (base) {
                kfree(base->lcla_pool.alloc_map);
+               kfree(base->reg_val_backup_chan);
                kfree(base->lookup_log_chans);
                kfree(base->lookup_phy_chans);
                kfree(base->phy_res);
index 8d3d490968a3a8240b6f91e1631609a2425c3f4f..51e8e5396e9bd960dbc9f51925567a7b8f768275 100644 (file)
@@ -62,8 +62,6 @@
 #define D40_SREG_ELEM_LOG_LIDX_MASK    (0xFF << D40_SREG_ELEM_LOG_LIDX_POS)
 
 /* Link register */
-#define D40_DEACTIVATE_EVENTLINE       0x0
-#define D40_ACTIVATE_EVENTLINE         0x1
 #define D40_EVENTLINE_POS(i)           (2 * i)
 #define D40_EVENTLINE_MASK(i)          (0x3 << D40_EVENTLINE_POS(i))
 
index 36e1486eb9aa0578583f60697e647ace8c8631b4..d0c372e30de41766cac54568c12d2994738cbf38 100644 (file)
@@ -754,9 +754,7 @@ static int __init mce_amd_init(void)
        if (c->x86_vendor != X86_VENDOR_AMD)
                return 0;
 
-       if ((c->x86 < 0xf || c->x86 > 0x12) &&
-           (c->x86 != 0x14 || c->x86_model > 0xf) &&
-           (c->x86 != 0x15 || c->x86_model > 0xf))
+       if (c->x86 < 0xf || c->x86 > 0x15)
                return 0;
 
        fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
@@ -797,7 +795,7 @@ static int __init mce_amd_init(void)
                break;
 
        default:
-               printk(KERN_WARNING "Huh? What family is that: %d?!\n", c->x86);
+               printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
                kfree(fam_ops);
                return -EINVAL;
        }
index 1d5cf06f6c6b9757de37fc5ed86b50f93bb048e7..e99d00976189344193e974cc9b972512a8f7359e 100644 (file)
@@ -145,7 +145,11 @@ static int __devinit tile_edac_mc_probe(struct platform_device *pdev)
        mci->edac_ctl_cap = EDAC_FLAG_SECDED;
 
        mci->mod_name = DRV_NAME;
+#ifdef __tilegx__
+       mci->ctl_name = "TILEGx_Memory_Controller";
+#else
        mci->ctl_name = "TILEPro_Memory_Controller";
+#endif
        mci->dev_name = dev_name(&pdev->dev);
        mci->edac_check = tile_edac_check;
 
index d25599f2a3f8bbb882ada61957239f030a06fa18..47408e802ab6effa670f8b3ba0637a3a75a14b36 100644 (file)
@@ -191,6 +191,190 @@ utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
        }
 }
 
+static bool
+validate_device_path(struct efi_variable *var, int match, u8 *buffer,
+                    unsigned long len)
+{
+       struct efi_generic_dev_path *node;
+       int offset = 0;
+
+       node = (struct efi_generic_dev_path *)buffer;
+
+       if (len < sizeof(*node))
+               return false;
+
+       while (offset <= len - sizeof(*node) &&
+              node->length >= sizeof(*node) &&
+               node->length <= len - offset) {
+               offset += node->length;
+
+               if ((node->type == EFI_DEV_END_PATH ||
+                    node->type == EFI_DEV_END_PATH2) &&
+                   node->sub_type == EFI_DEV_END_ENTIRE)
+                       return true;
+
+               node = (struct efi_generic_dev_path *)(buffer + offset);
+       }
+
+       /*
+        * If we're here then either node->length pointed past the end
+        * of the buffer or we reached the end of the buffer without
+        * finding a device path end node.
+        */
+       return false;
+}
+
+static bool
+validate_boot_order(struct efi_variable *var, int match, u8 *buffer,
+                   unsigned long len)
+{
+       /* An array of 16-bit integers */
+       if ((len % 2) != 0)
+               return false;
+
+       return true;
+}
+
+static bool
+validate_load_option(struct efi_variable *var, int match, u8 *buffer,
+                    unsigned long len)
+{
+       u16 filepathlength;
+       int i, desclength = 0, namelen;
+
+       namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));
+
+       /* Either "Boot" or "Driver" followed by four digits of hex */
+       for (i = match; i < match+4; i++) {
+               if (var->VariableName[i] > 127 ||
+                   hex_to_bin(var->VariableName[i] & 0xff) < 0)
+                       return true;
+       }
+
+       /* Reject it if there's 4 digits of hex and then further content */
+       if (namelen > match + 4)
+               return false;
+
+       /* A valid entry must be at least 8 bytes */
+       if (len < 8)
+               return false;
+
+       filepathlength = buffer[4] | buffer[5] << 8;
+
+       /*
+        * There's no stored length for the description, so it has to be
+        * found by hand
+        */
+       desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
+
+       /* Each boot entry must have a descriptor */
+       if (!desclength)
+               return false;
+
+       /*
+        * If the sum of the length of the description, the claimed filepath
+        * length and the original header are greater than the length of the
+        * variable, it's malformed
+        */
+       if ((desclength + filepathlength + 6) > len)
+               return false;
+
+       /*
+        * And, finally, check the filepath
+        */
+       return validate_device_path(var, match, buffer + desclength + 6,
+                                   filepathlength);
+}
+
+static bool
+validate_uint16(struct efi_variable *var, int match, u8 *buffer,
+               unsigned long len)
+{
+       /* A single 16-bit integer */
+       if (len != 2)
+               return false;
+
+       return true;
+}
+
+static bool
+validate_ascii_string(struct efi_variable *var, int match, u8 *buffer,
+                     unsigned long len)
+{
+       int i;
+
+       for (i = 0; i < len; i++) {
+               if (buffer[i] > 127)
+                       return false;
+
+               if (buffer[i] == 0)
+                       return true;
+       }
+
+       return false;
+}
+
+struct variable_validate {
+       char *name;
+       bool (*validate)(struct efi_variable *var, int match, u8 *data,
+                        unsigned long len);
+};
+
+static const struct variable_validate variable_validate[] = {
+       { "BootNext", validate_uint16 },
+       { "BootOrder", validate_boot_order },
+       { "DriverOrder", validate_boot_order },
+       { "Boot*", validate_load_option },
+       { "Driver*", validate_load_option },
+       { "ConIn", validate_device_path },
+       { "ConInDev", validate_device_path },
+       { "ConOut", validate_device_path },
+       { "ConOutDev", validate_device_path },
+       { "ErrOut", validate_device_path },
+       { "ErrOutDev", validate_device_path },
+       { "Timeout", validate_uint16 },
+       { "Lang", validate_ascii_string },
+       { "PlatformLang", validate_ascii_string },
+       { "", NULL },
+};
+
+static bool
+validate_var(struct efi_variable *var, u8 *data, unsigned long len)
+{
+       int i;
+       u16 *unicode_name = var->VariableName;
+
+       for (i = 0; variable_validate[i].validate != NULL; i++) {
+               const char *name = variable_validate[i].name;
+               int match;
+
+               for (match = 0; ; match++) {
+                       char c = name[match];
+                       u16 u = unicode_name[match];
+
+                       /* All special variables are plain ascii */
+                       if (u > 127)
+                               return true;
+
+                       /* Wildcard in the matching name means we've matched */
+                       if (c == '*')
+                               return variable_validate[i].validate(var,
+                                                            match, data, len);
+
+                       /* Case sensitive match */
+                       if (c != u)
+                               break;
+
+                       /* Reached the end of the string while matching */
+                       if (!c)
+                               return variable_validate[i].validate(var,
+                                                            match, data, len);
+               }
+       }
+
+       return true;
+}
+
 static efi_status_t
 get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
 {
@@ -324,6 +508,12 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
                return -EINVAL;
        }
 
+       if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
+           validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
+               printk(KERN_ERR "efivars: Malformed variable content\n");
+               return -EINVAL;
+       }
+
        spin_lock(&efivars->lock);
        status = efivars->ops->set_variable(new_var->VariableName,
                                            &new_var->VendorGuid,
@@ -626,6 +816,12 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
+       if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
+           validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
+               printk(KERN_ERR "efivars: Malformed variable content\n");
+               return -EINVAL;
+       }
+
        spin_lock(&efivars->lock);
 
        /*
index edadbdad31d04c2f228166afa8f1971f21573044..e03653d6935778423a5f3dd44d4ac06722d5f15f 100644 (file)
@@ -430,7 +430,7 @@ config GPIO_ML_IOH
 
 config GPIO_SODAVILLE
        bool "Intel Sodaville GPIO support"
-       depends on X86 && PCI && OF && BROKEN
+       depends on X86 && PCI && OF
        select GPIO_GENERIC
        select GENERIC_IRQ_CHIP
        help
index 9ad1703d1408aa0c8661de5826e3247ddeaf3f30..ae5d7f12ce661f49900f9be1b7aec0d7374bdf90 100644 (file)
@@ -252,7 +252,7 @@ static irqreturn_t adp5588_irq_handler(int irq, void *devid)
                if (ret < 0)
                        memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
 
-               for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
+               for (bank = 0, bit = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
                        bank++, bit = 0) {
                        pending = dev->irq_stat[bank] & dev->irq_mask[bank];
 
index 5689ce62fd81badc2fdeceeb604fdf866d5b3bda..fc3ace3fd4cbc64030764abe51a3788afc7f2e0e 100644 (file)
@@ -64,6 +64,7 @@ struct pxa_gpio_chip {
        unsigned long   irq_mask;
        unsigned long   irq_edge_rise;
        unsigned long   irq_edge_fall;
+       int (*set_wake)(unsigned int gpio, unsigned int on);
 
 #ifdef CONFIG_PM
        unsigned long   saved_gplr;
@@ -269,7 +270,8 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
                                (value ? GPSR_OFFSET : GPCR_OFFSET));
 }
 
-static int __devinit pxa_init_gpio_chip(int gpio_end)
+static int __devinit pxa_init_gpio_chip(int gpio_end,
+                                       int (*set_wake)(unsigned int, unsigned int))
 {
        int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
        struct pxa_gpio_chip *chips;
@@ -285,6 +287,7 @@ static int __devinit pxa_init_gpio_chip(int gpio_end)
 
                sprintf(chips[i].label, "gpio-%d", i);
                chips[i].regbase = gpio_reg_base + BANK_OFF(i);
+               chips[i].set_wake = set_wake;
 
                c->base  = gpio;
                c->label = chips[i].label;
@@ -412,6 +415,17 @@ static void pxa_mask_muxed_gpio(struct irq_data *d)
        writel_relaxed(gfer, c->regbase + GFER_OFFSET);
 }
 
+static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on)
+{
+       int gpio = pxa_irq_to_gpio(d->irq);
+       struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+       if (c->set_wake)
+               return c->set_wake(gpio, on);
+       else
+               return 0;
+}
+
 static void pxa_unmask_muxed_gpio(struct irq_data *d)
 {
        int gpio = pxa_irq_to_gpio(d->irq);
@@ -427,6 +441,7 @@ static struct irq_chip pxa_muxed_gpio_chip = {
        .irq_mask       = pxa_mask_muxed_gpio,
        .irq_unmask     = pxa_unmask_muxed_gpio,
        .irq_set_type   = pxa_gpio_irq_type,
+       .irq_set_wake   = pxa_gpio_set_wake,
 };
 
 static int pxa_gpio_nums(void)
@@ -471,6 +486,7 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
        struct pxa_gpio_chip *c;
        struct resource *res;
        struct clk *clk;
+       struct pxa_gpio_platform_data *info;
        int gpio, irq, ret;
        int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
 
@@ -516,7 +532,8 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
        }
 
        /* Initialize GPIO chips */
-       pxa_init_gpio_chip(pxa_last_gpio);
+       info = dev_get_platdata(&pdev->dev);
+       pxa_init_gpio_chip(pxa_last_gpio, info ? info->gpio_set_wake : NULL);
 
        /* clear all GPIO edge detects */
        for_each_gpio_chip(gpio, c) {
index 46277877b7ecc1bea7448391d20a7a4f710c4577..19d6fc0229c3505d802e068553db8be4e5b1361e 100644 (file)
@@ -2382,8 +2382,8 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
 #endif
 };
 
-static struct samsung_gpio_chip exynos5_gpios_1[] = {
 #ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_1[] = {
        {
                .chip   = {
                        .base   = EXYNOS5_GPA0(0),
@@ -2541,11 +2541,11 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = {
                        .to_irq = samsung_gpiolib_to_irq,
                },
        },
-#endif
 };
+#endif
 
-static struct samsung_gpio_chip exynos5_gpios_2[] = {
 #ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_2[] = {
        {
                .chip   = {
                        .base   = EXYNOS5_GPE0(0),
@@ -2602,11 +2602,11 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = {
 
                },
        },
-#endif
 };
+#endif
 
-static struct samsung_gpio_chip exynos5_gpios_3[] = {
 #ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_3[] = {
        {
                .chip   = {
                        .base   = EXYNOS5_GPV0(0),
@@ -2638,11 +2638,11 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = {
                        .label  = "GPV4",
                },
        },
-#endif
 };
+#endif
 
-static struct samsung_gpio_chip exynos5_gpios_4[] = {
 #ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_4[] = {
        {
                .chip   = {
                        .base   = EXYNOS5_GPZ(0),
@@ -2650,8 +2650,8 @@ static struct samsung_gpio_chip exynos5_gpios_4[] = {
                        .label  = "GPZ",
                },
        },
-#endif
 };
+#endif
 
 
 #if defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF)
index 9ba15d31d242f500315761ff8b74944ce3e8bb3e..031e5d24837dc6e8d8b8fe4a2016c306903d9f9a 100644 (file)
@@ -41,7 +41,7 @@
 struct sdv_gpio_chip_data {
        int irq_base;
        void __iomem *gpio_pub_base;
-       struct irq_domain id;
+       struct irq_domain *id;
        struct irq_chip_generic *gc;
        struct bgpio_chip bgpio;
 };
@@ -51,10 +51,9 @@ static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type)
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct sdv_gpio_chip_data *sd = gc->private;
        void __iomem *type_reg;
-       u32 irq_offs = d->irq - sd->irq_base;
        u32 reg;
 
-       if (irq_offs < 8)
+       if (d->hwirq < 8)
                type_reg = sd->gpio_pub_base + GPIT1R0;
        else
                type_reg = sd->gpio_pub_base + GPIT1R1;
@@ -63,11 +62,11 @@ static int sdv_gpio_pub_set_type(struct irq_data *d, unsigned int type)
 
        switch (type) {
        case IRQ_TYPE_LEVEL_HIGH:
-               reg &= ~BIT(4 * (irq_offs % 8));
+               reg &= ~BIT(4 * (d->hwirq % 8));
                break;
 
        case IRQ_TYPE_LEVEL_LOW:
-               reg |= BIT(4 * (irq_offs % 8));
+               reg |= BIT(4 * (d->hwirq % 8));
                break;
 
        default:
@@ -91,7 +90,7 @@ static irqreturn_t sdv_gpio_pub_irq_handler(int irq, void *data)
                u32 irq_bit = __fls(irq_stat);
 
                irq_stat &= ~BIT(irq_bit);
-               generic_handle_irq(sd->irq_base + irq_bit);
+               generic_handle_irq(irq_find_mapping(sd->id, irq_bit));
        }
 
        return IRQ_HANDLED;
@@ -127,7 +126,7 @@ static int sdv_xlate(struct irq_domain *h, struct device_node *node,
 }
 
 static struct irq_domain_ops irq_domain_sdv_ops = {
-       .dt_translate   = sdv_xlate,
+       .xlate = sdv_xlate,
 };
 
 static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
@@ -149,10 +148,6 @@ static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
        if (ret)
                goto out_free_desc;
 
-       sd->id.irq_base = sd->irq_base;
-       sd->id.of_node = of_node_get(pdev->dev.of_node);
-       sd->id.ops = &irq_domain_sdv_ops;
-
        /*
         * This gpio irq controller latches level irqs. Testing shows that if
         * we unmask & ACK the IRQ before the source of the interrupt is gone
@@ -179,7 +174,10 @@ static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
                        IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST,
                        IRQ_LEVEL | IRQ_NOPROBE);
 
-       irq_domain_add(&sd->id);
+       sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS,
+                               sd->irq_base, 0, &irq_domain_sdv_ops, sd);
+       if (!sd->id)
+               goto out_free_irq;
        return 0;
 out_free_irq:
        free_irq(pdev->irq, sd);
@@ -260,7 +258,6 @@ static void sdv_gpio_remove(struct pci_dev *pdev)
 {
        struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev);
 
-       irq_domain_del(&sd->id);
        free_irq(pdev->irq, sd);
        irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
 
index 32de6707e3c456a19750e33dd21923bde2fcd41e..12f349b3830d29589a6373b32e722f268bac58f9 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
-#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/irqdomain.h>
@@ -37,7 +37,8 @@
 #define GPIO_PORT(x)           (((x) >> 3) & 0x3)
 #define GPIO_BIT(x)            ((x) & 0x7)
 
-#define GPIO_REG(x)            (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
+#define GPIO_REG(x)            (GPIO_BANK(x) * tegra_gpio_bank_stride + \
+                                       GPIO_PORT(x) * 4)
 
 #define GPIO_CNF(x)            (GPIO_REG(x) + 0x00)
 #define GPIO_OE(x)             (GPIO_REG(x) + 0x10)
 #define GPIO_INT_LVL(x)                (GPIO_REG(x) + 0x60)
 #define GPIO_INT_CLR(x)                (GPIO_REG(x) + 0x70)
 
-#define GPIO_MSK_CNF(x)                (GPIO_REG(x) + 0x800)
-#define GPIO_MSK_OE(x)         (GPIO_REG(x) + 0x810)
-#define GPIO_MSK_OUT(x)                (GPIO_REG(x) + 0X820)
-#define GPIO_MSK_INT_STA(x)    (GPIO_REG(x) + 0x840)
-#define GPIO_MSK_INT_ENB(x)    (GPIO_REG(x) + 0x850)
-#define GPIO_MSK_INT_LVL(x)    (GPIO_REG(x) + 0x860)
+#define GPIO_MSK_CNF(x)                (GPIO_REG(x) + tegra_gpio_upper_offset + 0x00)
+#define GPIO_MSK_OE(x)         (GPIO_REG(x) + tegra_gpio_upper_offset + 0x10)
+#define GPIO_MSK_OUT(x)                (GPIO_REG(x) + tegra_gpio_upper_offset + 0X20)
+#define GPIO_MSK_INT_STA(x)    (GPIO_REG(x) + tegra_gpio_upper_offset + 0x40)
+#define GPIO_MSK_INT_ENB(x)    (GPIO_REG(x) + tegra_gpio_upper_offset + 0x50)
+#define GPIO_MSK_INT_LVL(x)    (GPIO_REG(x) + tegra_gpio_upper_offset + 0x60)
 
 #define GPIO_INT_LVL_MASK              0x010101
 #define GPIO_INT_LVL_EDGE_RISING       0x000101
@@ -78,6 +79,8 @@ struct tegra_gpio_bank {
 static struct irq_domain *irq_domain;
 static void __iomem *regs;
 static u32 tegra_gpio_bank_count;
+static u32 tegra_gpio_bank_stride;
+static u32 tegra_gpio_upper_offset;
 static struct tegra_gpio_bank *tegra_gpio_banks;
 
 static inline void tegra_gpio_writel(u32 val, u32 reg)
@@ -333,6 +336,26 @@ static struct irq_chip tegra_gpio_irq_chip = {
 #endif
 };
 
+struct tegra_gpio_soc_config {
+       u32 bank_stride;
+       u32 upper_offset;
+};
+
+static struct tegra_gpio_soc_config tegra20_gpio_config = {
+       .bank_stride = 0x80,
+       .upper_offset = 0x800,
+};
+
+static struct tegra_gpio_soc_config tegra30_gpio_config = {
+       .bank_stride = 0x100,
+       .upper_offset = 0x80,
+};
+
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+       { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
+       { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
+       { },
+};
 
 /* This lock class tells lockdep that GPIO irqs are in a different
  * category than their parents, so it won't report false recursion.
@@ -341,6 +364,8 @@ static struct lock_class_key gpio_lock_class;
 
 static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *match;
+       struct tegra_gpio_soc_config *config;
        int irq_base;
        struct resource *res;
        struct tegra_gpio_bank *bank;
@@ -348,6 +373,15 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
        int i;
        int j;
 
+       match = of_match_device(tegra_gpio_of_match, &pdev->dev);
+       if (match)
+               config = (struct tegra_gpio_soc_config *)match->data;
+       else
+               config = &tegra20_gpio_config;
+
+       tegra_gpio_bank_stride = config->bank_stride;
+       tegra_gpio_upper_offset = config->upper_offset;
+
        for (;;) {
                res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count);
                if (!res)
@@ -402,7 +436,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       for (i = 0; i < 7; i++) {
+       for (i = 0; i < tegra_gpio_bank_count; i++) {
                for (j = 0; j < 4; j++) {
                        int gpio = tegra_gpio_compose(i, j, 0);
                        tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
@@ -441,11 +475,6 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
-       { .compatible = "nvidia,tegra20-gpio", },
-       { },
-};
-
 static struct platform_driver tegra_gpio_driver = {
        .driver         = {
                .name   = "tegra-gpio",
@@ -485,7 +514,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
        int i;
        int j;
 
-       for (i = 0; i < 7; i++) {
+       for (i = 0; i < tegra_gpio_bank_count; i++) {
                for (j = 0; j < 4; j++) {
                        int gpio = tegra_gpio_compose(i, j, 0);
                        seq_printf(s,
index cc1148837e241d2c95332a630609a838d9ae59ee..e354bc0b052a22c22da2bf553586f665d2434000 100644 (file)
@@ -9,6 +9,7 @@ menuconfig DRM
        depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
        select I2C
        select I2C_ALGOBIT
+       select DMA_SHARED_BUFFER
        help
          Kernel-level support for the Direct Rendering Infrastructure (DRI)
          introduced in XFree86 4.0. If you say Y here, you need to select
index a858532806ae34ae341c608d5c985a577992739e..c20da5bda3551cdcbc7c24d9605a24ef8654196b 100644 (file)
@@ -12,7 +12,7 @@ drm-y       :=        drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
                drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
                drm_crtc.o drm_modes.o drm_edid.o \
                drm_info.o drm_debugfs.o drm_encoder_slave.o \
-               drm_trace_points.o drm_global.o
+               drm_trace_points.o drm_global.o drm_prime.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 
index 30372f7b2d457a8803e819d9050ccd3c525e7825..348b367debebdcf1823ac4f781915097e3fb027a 100644 (file)
@@ -1510,8 +1510,8 @@ int drm_freebufs(struct drm_device *dev, void *data,
  * \param arg pointer to a drm_buf_map structure.
  * \return zero on success or a negative number on failure.
  *
- * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
- * about each buffer into user space. For PCI buffers, it calls do_mmap() with
+ * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
+ * about each buffer into user space. For PCI buffers, it calls vm_mmap() with
  * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
  * drm_mmap_dma().
  */
@@ -1553,18 +1553,14 @@ int drm_mapbufs(struct drm_device *dev, void *data,
                                retcode = -EINVAL;
                                goto done;
                        }
-                       down_write(&current->mm->mmap_sem);
-                       virtual = do_mmap(file_priv->filp, 0, map->size,
+                       virtual = vm_mmap(file_priv->filp, 0, map->size,
                                          PROT_READ | PROT_WRITE,
                                          MAP_SHARED,
                                          token);
-                       up_write(&current->mm->mmap_sem);
                } else {
-                       down_write(&current->mm->mmap_sem);
-                       virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
+                       virtual = vm_mmap(file_priv->filp, 0, dma->byte_count,
                                          PROT_READ | PROT_WRITE,
                                          MAP_SHARED, 0);
-                       up_write(&current->mm->mmap_sem);
                }
                if (virtual > -1024UL) {
                        /* Real error */
index 4b8653b932f9a3216a3b43038b22ed96bb8709c9..08758e061478eb77e2db77794d1d5e54c8625474 100644 (file)
@@ -98,3 +98,26 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)
 #endif
 }
 EXPORT_SYMBOL(drm_clflush_pages);
+
+void
+drm_clflush_virt_range(char *addr, unsigned long length)
+{
+#if defined(CONFIG_X86)
+       if (cpu_has_clflush) {
+               char *end = addr + length;
+               mb();
+               for (; addr < end; addr += boot_cpu_data.x86_clflush_size)
+                       clflush(addr);
+               clflush(end - 1);
+               mb();
+               return;
+       }
+
+       if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
+               printk(KERN_ERR "Timed out waiting for cache flush.\n");
+#else
+       printk(KERN_ERR "Architecture has no drm_cache.c support\n");
+       WARN_ON_ONCE(1);
+#endif
+}
+EXPORT_SYMBOL(drm_clflush_virt_range);
index 325365f6d355c3c12bf2386bb354bd095d873061..affa629589ace645952535d707df72e14813b67b 100644 (file)
@@ -85,11 +85,12 @@ again:
        mutex_lock(&dev->struct_mutex);
        ret = idr_get_new_above(&dev->ctx_idr, NULL,
                                DRM_RESERVED_CONTEXTS, &new_id);
-       if (ret == -EAGAIN) {
-               mutex_unlock(&dev->struct_mutex);
-               goto again;
-       }
        mutex_unlock(&dev->struct_mutex);
+       if (ret == -EAGAIN)
+               goto again;
+       else if (ret)
+               return ret;
+
        return new_id;
 }
 
index d3aaeb6ae2362167f360d3a8d1aa846028714fdd..ee63a123235cf3b632f73ab0b02c2368cc7ef987 100644 (file)
@@ -227,7 +227,7 @@ static int drm_mode_object_get(struct drm_device *dev,
 again:
        if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
                DRM_ERROR("Ran out memory getting a mode number\n");
-               return -EINVAL;
+               return -ENOMEM;
        }
 
        mutex_lock(&dev->mode_config.idr_mutex);
@@ -235,6 +235,8 @@ again:
        mutex_unlock(&dev->mode_config.idr_mutex);
        if (ret == -EAGAIN)
                goto again;
+       else if (ret)
+               return ret;
 
        obj->id = new_id;
        obj->type = obj_type;
@@ -2102,7 +2104,7 @@ int drm_mode_addfb(struct drm_device *dev,
 
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
        if (IS_ERR(fb)) {
-               DRM_ERROR("could not create framebuffer\n");
+               DRM_DEBUG_KMS("could not create framebuffer\n");
                ret = PTR_ERR(fb);
                goto out;
        }
@@ -2185,6 +2187,47 @@ static int format_check(struct drm_mode_fb_cmd2 *r)
        }
 }
 
+static int framebuffer_check(struct drm_mode_fb_cmd2 *r)
+{
+       int ret, hsub, vsub, num_planes, i;
+
+       ret = format_check(r);
+       if (ret) {
+               DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format);
+               return ret;
+       }
+
+       hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
+       vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
+       num_planes = drm_format_num_planes(r->pixel_format);
+
+       if (r->width == 0 || r->width % hsub) {
+               DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height);
+               return -EINVAL;
+       }
+
+       if (r->height == 0 || r->height % vsub) {
+               DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < num_planes; i++) {
+               unsigned int width = r->width / (i != 0 ? hsub : 1);
+
+               if (!r->handles[i]) {
+                       DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
+                       return -EINVAL;
+               }
+
+               if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * width) {
+                       DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * drm_mode_addfb2 - add an FB to the graphics configuration
  * @inode: inode from the ioctl
@@ -2214,27 +2257,25 @@ int drm_mode_addfb2(struct drm_device *dev,
                return -EINVAL;
 
        if ((config->min_width > r->width) || (r->width > config->max_width)) {
-               DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n",
+               DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
                          r->width, config->min_width, config->max_width);
                return -EINVAL;
        }
        if ((config->min_height > r->height) || (r->height > config->max_height)) {
-               DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n",
+               DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
                          r->height, config->min_height, config->max_height);
                return -EINVAL;
        }
 
-       ret = format_check(r);
-       if (ret) {
-               DRM_ERROR("bad framebuffer format 0x%08x\n", r->pixel_format);
+       ret = framebuffer_check(r);
+       if (ret)
                return ret;
-       }
 
        mutex_lock(&dev->mode_config.mutex);
 
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
        if (IS_ERR(fb)) {
-               DRM_ERROR("could not create framebuffer\n");
+               DRM_DEBUG_KMS("could not create framebuffer\n");
                ret = PTR_ERR(fb);
                goto out;
        }
@@ -3335,10 +3376,12 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
 
        ret = crtc->funcs->page_flip(crtc, fb, e);
        if (ret) {
-               spin_lock_irqsave(&dev->event_lock, flags);
-               file_priv->event_space += sizeof e->event;
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               kfree(e);
+               if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+                       spin_lock_irqsave(&dev->event_lock, flags);
+                       file_priv->event_space += sizeof e->event;
+                       spin_unlock_irqrestore(&dev->event_lock, flags);
+                       kfree(e);
+               }
        }
 
 out:
@@ -3466,3 +3509,140 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
        }
 }
 EXPORT_SYMBOL(drm_fb_get_bpp_depth);
+
+/**
+ * drm_format_num_planes - get the number of planes for format
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * RETURNS:
+ * The number of planes used by the specified pixel format.
+ */
+int drm_format_num_planes(uint32_t format)
+{
+       switch (format) {
+       case DRM_FORMAT_YUV410:
+       case DRM_FORMAT_YVU410:
+       case DRM_FORMAT_YUV411:
+       case DRM_FORMAT_YVU411:
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+       case DRM_FORMAT_YUV422:
+       case DRM_FORMAT_YVU422:
+       case DRM_FORMAT_YUV444:
+       case DRM_FORMAT_YVU444:
+               return 3;
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+       case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV61:
+               return 2;
+       default:
+               return 1;
+       }
+}
+EXPORT_SYMBOL(drm_format_num_planes);
+
+/**
+ * drm_format_plane_cpp - determine the bytes per pixel value
+ * @format: pixel format (DRM_FORMAT_*)
+ * @plane: plane index
+ *
+ * RETURNS:
+ * The bytes per pixel value for the specified plane.
+ */
+int drm_format_plane_cpp(uint32_t format, int plane)
+{
+       unsigned int depth;
+       int bpp;
+
+       if (plane >= drm_format_num_planes(format))
+               return 0;
+
+       switch (format) {
+       case DRM_FORMAT_YUYV:
+       case DRM_FORMAT_YVYU:
+       case DRM_FORMAT_UYVY:
+       case DRM_FORMAT_VYUY:
+               return 2;
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+       case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV61:
+               return plane ? 2 : 1;
+       case DRM_FORMAT_YUV410:
+       case DRM_FORMAT_YVU410:
+       case DRM_FORMAT_YUV411:
+       case DRM_FORMAT_YVU411:
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+       case DRM_FORMAT_YUV422:
+       case DRM_FORMAT_YVU422:
+       case DRM_FORMAT_YUV444:
+       case DRM_FORMAT_YVU444:
+               return 1;
+       default:
+               drm_fb_get_bpp_depth(format, &depth, &bpp);
+               return bpp >> 3;
+       }
+}
+EXPORT_SYMBOL(drm_format_plane_cpp);
+
+/**
+ * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * RETURNS:
+ * The horizontal chroma subsampling factor for the
+ * specified pixel format.
+ */
+int drm_format_horz_chroma_subsampling(uint32_t format)
+{
+       switch (format) {
+       case DRM_FORMAT_YUV411:
+       case DRM_FORMAT_YVU411:
+       case DRM_FORMAT_YUV410:
+       case DRM_FORMAT_YVU410:
+               return 4;
+       case DRM_FORMAT_YUYV:
+       case DRM_FORMAT_YVYU:
+       case DRM_FORMAT_UYVY:
+       case DRM_FORMAT_VYUY:
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+       case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV61:
+       case DRM_FORMAT_YUV422:
+       case DRM_FORMAT_YVU422:
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+               return 2;
+       default:
+               return 1;
+       }
+}
+EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
+
+/**
+ * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
+ * @format: pixel format (DRM_FORMAT_*)
+ *
+ * RETURNS:
+ * The vertical chroma subsampling factor for the
+ * specified pixel format.
+ */
+int drm_format_vert_chroma_subsampling(uint32_t format)
+{
+       switch (format) {
+       case DRM_FORMAT_YUV410:
+       case DRM_FORMAT_YVU410:
+               return 4;
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+       case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV21:
+               return 2;
+       default:
+               return 1;
+       }
+}
+EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
index 81118893264c26e3cd472827dee324e6570dad04..974196ab7b2262b527508f0996ec9a184c678e92 100644 (file)
@@ -1023,36 +1023,3 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
                queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0);
 }
 EXPORT_SYMBOL(drm_helper_hpd_irq_event);
-
-
-/**
- * drm_format_num_planes - get the number of planes for format
- * @format: pixel format (DRM_FORMAT_*)
- *
- * RETURNS:
- * The number of planes used by the specified pixel format.
- */
-int drm_format_num_planes(uint32_t format)
-{
-       switch (format) {
-       case DRM_FORMAT_YUV410:
-       case DRM_FORMAT_YVU410:
-       case DRM_FORMAT_YUV411:
-       case DRM_FORMAT_YVU411:
-       case DRM_FORMAT_YUV420:
-       case DRM_FORMAT_YVU420:
-       case DRM_FORMAT_YUV422:
-       case DRM_FORMAT_YVU422:
-       case DRM_FORMAT_YUV444:
-       case DRM_FORMAT_YVU444:
-               return 3;
-       case DRM_FORMAT_NV12:
-       case DRM_FORMAT_NV21:
-       case DRM_FORMAT_NV16:
-       case DRM_FORMAT_NV61:
-               return 2;
-       default:
-               return 1;
-       }
-}
-EXPORT_SYMBOL(drm_format_num_planes);
index 0b65fbc8a6308c9b1f7aae823e7d10149d75c380..6116e3b75393c033da09649490c3603e49ddf206 100644 (file)
@@ -136,6 +136,10 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
 
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
index 5a18b0df82850a046608c57c7fedb4cf75d03e4b..608bddfc7e35ad93ebe7c522c2b2fb77cd8a44b6 100644 (file)
@@ -81,7 +81,7 @@ struct detailed_mode_closure {
 #define LEVEL_CVT      3
 
 static struct edid_quirk {
-       char *vendor;
+       char vendor[4];
        int product_id;
        u32 quirks;
 } edid_quirk_list[] = {
@@ -149,13 +149,13 @@ EXPORT_SYMBOL(drm_edid_header_is_valid);
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
  */
-bool drm_edid_block_valid(u8 *raw_edid)
+bool drm_edid_block_valid(u8 *raw_edid, int block)
 {
        int i;
        u8 csum = 0;
        struct edid *edid = (struct edid *)raw_edid;
 
-       if (raw_edid[0] == 0x00) {
+       if (block == 0) {
                int score = drm_edid_header_is_valid(raw_edid);
                if (score == 8) ;
                else if (score >= 6) {
@@ -219,7 +219,7 @@ bool drm_edid_is_valid(struct edid *edid)
                return false;
 
        for (i = 0; i <= edid->extensions; i++)
-               if (!drm_edid_block_valid(raw + i * EDID_LENGTH))
+               if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i))
                        return false;
 
        return true;
@@ -299,7 +299,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
        for (i = 0; i < 4; i++) {
                if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
                        goto out;
-               if (drm_edid_block_valid(block))
+               if (drm_edid_block_valid(block, 0))
                        break;
                if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
                        connector->null_edid_counter++;
@@ -324,7 +324,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
                                  block + (valid_extensions + 1) * EDID_LENGTH,
                                  j, EDID_LENGTH))
                                goto out;
-                       if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH)) {
+                       if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j)) {
                                valid_extensions++;
                                break;
                        }
@@ -486,23 +486,47 @@ static void edid_fixup_preferred(struct drm_connector *connector,
        preferred_mode->type |= DRM_MODE_TYPE_PREFERRED;
 }
 
+static bool
+mode_is_rb(const struct drm_display_mode *mode)
+{
+       return (mode->htotal - mode->hdisplay == 160) &&
+              (mode->hsync_end - mode->hdisplay == 80) &&
+              (mode->hsync_end - mode->hsync_start == 32) &&
+              (mode->vsync_start - mode->vdisplay == 3);
+}
+
+/*
+ * drm_mode_find_dmt - Create a copy of a mode if present in DMT
+ * @dev: Device to duplicate against
+ * @hsize: Mode width
+ * @vsize: Mode height
+ * @fresh: Mode refresh rate
+ * @rb: Mode reduced-blanking-ness
+ *
+ * Walk the DMT mode list looking for a match for the given parameters.
+ * Return a newly allocated copy of the mode, or NULL if not found.
+ */
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
-                                          int hsize, int vsize, int fresh)
+                                          int hsize, int vsize, int fresh,
+                                          bool rb)
 {
-       struct drm_display_mode *mode = NULL;
        int i;
 
        for (i = 0; i < drm_num_dmt_modes; i++) {
                const struct drm_display_mode *ptr = &drm_dmt_modes[i];
-               if (hsize == ptr->hdisplay &&
-                       vsize == ptr->vdisplay &&
-                       fresh == drm_mode_vrefresh(ptr)) {
-                       /* get the expected default mode */
-                       mode = drm_mode_duplicate(dev, ptr);
-                       break;
-               }
+               if (hsize != ptr->hdisplay)
+                       continue;
+               if (vsize != ptr->vdisplay)
+                       continue;
+               if (fresh != drm_mode_vrefresh(ptr))
+                       continue;
+               if (rb != mode_is_rb(ptr))
+                       continue;
+
+               return drm_mode_duplicate(dev, ptr);
        }
-       return mode;
+
+       return NULL;
 }
 EXPORT_SYMBOL(drm_mode_find_dmt);
 
@@ -731,10 +755,17 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid,
        }
 
        /* check whether it can be found in default mode table */
-       mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate);
+       if (drm_monitor_supports_rb(edid)) {
+               mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate,
+                                        true);
+               if (mode)
+                       return mode;
+       }
+       mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate, false);
        if (mode)
                return mode;
 
+       /* okay, generate it */
        switch (timing_level) {
        case LEVEL_DMT:
                break;
@@ -748,6 +779,8 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid,
                 * secondary GTF curve.  Please don't do that.
                 */
                mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
+               if (!mode)
+                       return NULL;
                if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) {
                        drm_mode_destroy(dev, mode);
                        mode = drm_gtf_mode_complex(dev, hsize, vsize,
@@ -908,15 +941,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        return mode;
 }
 
-static bool
-mode_is_rb(const struct drm_display_mode *mode)
-{
-       return (mode->htotal - mode->hdisplay == 160) &&
-              (mode->hsync_end - mode->hdisplay == 80) &&
-              (mode->hsync_end - mode->hsync_start == 32) &&
-              (mode->vsync_start - mode->vdisplay == 3);
-}
-
 static bool
 mode_in_hsync_range(const struct drm_display_mode *mode,
                    struct edid *edid, u8 *t)
@@ -994,12 +1018,8 @@ mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
        return true;
 }
 
-/*
- * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will
- * need to account for them.
- */
 static int
-drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
+drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
                        struct detailed_timing *timing)
 {
        int i, modes = 0;
@@ -1019,17 +1039,110 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
        return modes;
 }
 
+/* fix up 1366x768 mode from 1368x768;
+ * GFT/CVT can't express 1366 width which isn't dividable by 8
+ */
+static void fixup_mode_1366x768(struct drm_display_mode *mode)
+{
+       if (mode->hdisplay == 1368 && mode->vdisplay == 768) {
+               mode->hdisplay = 1366;
+               mode->hsync_start--;
+               mode->hsync_end--;
+               drm_mode_set_name(mode);
+       }
+}
+
+static int
+drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
+                       struct detailed_timing *timing)
+{
+       int i, modes = 0;
+       struct drm_display_mode *newmode;
+       struct drm_device *dev = connector->dev;
+
+       for (i = 0; i < num_extra_modes; i++) {
+               const struct minimode *m = &extra_modes[i];
+               newmode = drm_gtf_mode(dev, m->w, m->h, m->r, 0, 0);
+               if (!newmode)
+                       return modes;
+
+               fixup_mode_1366x768(newmode);
+               if (!mode_in_range(newmode, edid, timing)) {
+                       drm_mode_destroy(dev, newmode);
+                       continue;
+               }
+
+               drm_mode_probed_add(connector, newmode);
+               modes++;
+       }
+
+       return modes;
+}
+
+static int
+drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
+                       struct detailed_timing *timing)
+{
+       int i, modes = 0;
+       struct drm_display_mode *newmode;
+       struct drm_device *dev = connector->dev;
+       bool rb = drm_monitor_supports_rb(edid);
+
+       for (i = 0; i < num_extra_modes; i++) {
+               const struct minimode *m = &extra_modes[i];
+               newmode = drm_cvt_mode(dev, m->w, m->h, m->r, rb, 0, 0);
+               if (!newmode)
+                       return modes;
+
+               fixup_mode_1366x768(newmode);
+               if (!mode_in_range(newmode, edid, timing)) {
+                       drm_mode_destroy(dev, newmode);
+                       continue;
+               }
+
+               drm_mode_probed_add(connector, newmode);
+               modes++;
+       }
+
+       return modes;
+}
+
 static void
 do_inferred_modes(struct detailed_timing *timing, void *c)
 {
        struct detailed_mode_closure *closure = c;
        struct detailed_non_pixel *data = &timing->data.other_data;
-       int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
+       struct detailed_data_monitor_range *range = &data->data.range;
+
+       if (data->type != EDID_DETAIL_MONITOR_RANGE)
+               return;
 
-       if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE)
+       closure->modes += drm_dmt_modes_for_range(closure->connector,
+                                                 closure->edid,
+                                                 timing);
+       
+       if (!version_greater(closure->edid, 1, 1))
+               return; /* GTF not defined yet */
+
+       switch (range->flags) {
+       case 0x02: /* secondary gtf, XXX could do more */
+       case 0x00: /* default gtf */
                closure->modes += drm_gtf_modes_for_range(closure->connector,
                                                          closure->edid,
                                                          timing);
+               break;
+       case 0x04: /* cvt, only in 1.4+ */
+               if (!version_greater(closure->edid, 1, 3))
+                       break;
+
+               closure->modes += drm_cvt_modes_for_range(closure->connector,
+                                                         closure->edid,
+                                                         timing);
+               break;
+       case 0x01: /* just the ranges, no formula */
+       default:
+               break;
+       }
 }
 
 static int
@@ -1062,8 +1175,8 @@ drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing)
                                mode = drm_mode_find_dmt(connector->dev,
                                                         est3_modes[m].w,
                                                         est3_modes[m].h,
-                                                        est3_modes[m].r
-                                                        /*, est3_modes[m].rb */);
+                                                        est3_modes[m].r,
+                                                        est3_modes[m].rb);
                                if (mode) {
                                        drm_mode_probed_add(connector, mode);
                                        modes++;
@@ -1312,6 +1425,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
 #define VENDOR_BLOCK    0x03
 #define SPEAKER_BLOCK  0x04
 #define EDID_BASIC_AUDIO       (1 << 6)
+#define EDID_CEA_YCRCB444      (1 << 5)
+#define EDID_CEA_YCRCB422      (1 << 4)
 
 /**
  * Search EDID for CEA extension block.
@@ -1666,13 +1781,29 @@ static void drm_add_display_info(struct edid *edid,
        info->bpc = 0;
        info->color_formats = 0;
 
-       /* Only defined for 1.4 with digital displays */
-       if (edid->revision < 4)
+       if (edid->revision < 3)
                return;
 
        if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
                return;
 
+       /* Get data from CEA blocks if present */
+       edid_ext = drm_find_cea_extension(edid);
+       if (edid_ext) {
+               info->cea_rev = edid_ext[1];
+
+               /* The existence of a CEA block should imply RGB support */
+               info->color_formats = DRM_COLOR_FORMAT_RGB444;
+               if (edid_ext[3] & EDID_CEA_YCRCB444)
+                       info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
+               if (edid_ext[3] & EDID_CEA_YCRCB422)
+                       info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
+       }
+
+       /* Only defined for 1.4 with digital displays */
+       if (edid->revision < 4)
+               return;
+
        switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
        case DRM_EDID_DIGITAL_DEPTH_6:
                info->bpc = 6;
@@ -1698,18 +1829,11 @@ static void drm_add_display_info(struct edid *edid,
                break;
        }
 
-       info->color_formats = DRM_COLOR_FORMAT_RGB444;
-       if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB444)
-               info->color_formats = DRM_COLOR_FORMAT_YCRCB444;
-       if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB422)
-               info->color_formats = DRM_COLOR_FORMAT_YCRCB422;
-
-       /* Get data from CEA blocks if present */
-       edid_ext = drm_find_cea_extension(edid);
-       if (!edid_ext)
-               return;
-
-       info->cea_rev = edid_ext[1];
+       info->color_formats |= DRM_COLOR_FORMAT_RGB444;
+       if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
+               info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
+       if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
+               info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
 }
 
 /**
index da9acba2dd6c7f7dc7de62361ac8e832c81eed66..48c927c37041ed7071e9a5d2b1b2a5b79c8f9184 100644 (file)
@@ -173,7 +173,7 @@ static int edid_load(struct drm_connector *connector, char *name,
        }
        memcpy(edid, fwdata, fwsize);
 
-       if (!drm_edid_block_valid(edid)) {
+       if (!drm_edid_block_valid(edid, 0)) {
                DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
                    name);
                kfree(edid);
@@ -185,7 +185,7 @@ static int edid_load(struct drm_connector *connector, char *name,
                if (i != valid_extensions + 1)
                        memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
                            edid + i * EDID_LENGTH, EDID_LENGTH);
-               if (drm_edid_block_valid(edid + i * EDID_LENGTH))
+               if (drm_edid_block_valid(edid + i * EDID_LENGTH, i))
                        valid_extensions++;
        }
 
index a91ffb1172208beea3b85b5d04ff0def347f89ef..ff98a7eb38ddd24ff82358b784e1569c92eaf05f 100644 (file)
@@ -30,7 +30,6 @@
 /*
  * Autogenerated from the DMT spec.
  * This table is copied from xfree86/modes/xf86EdidModes.c.
- * But the mode with Reduced blank feature is deleted.
  */
 static const struct drm_display_mode drm_dmt_modes[] = {
        /* 640x350@85Hz */
@@ -81,6 +80,10 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832,
                   896, 1048, 0, 600, 601, 604, 631, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 800x600@120Hz RB */
+       { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 73250, 800, 848,
+                  880, 960, 0, 600, 603, 607, 636, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 848x480@60Hz */
        { DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864,
                   976, 1088, 0, 480, 486, 494, 517, 0,
@@ -106,10 +109,18 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072,
                   1168, 1376, 0, 768, 769, 772, 808, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1024x768@120Hz RB */
+       { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 115500, 1024, 1072,
+                  1104, 1184, 0, 768, 771, 775, 813, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1152x864@75Hz */
        { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
                   1344, 1600, 0, 864, 865, 868, 900, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1280x768@60Hz RB */
+       { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 68250, 1280, 1328,
+                  1360, 1440, 0, 768, 771, 778, 790, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1280x768@60Hz */
        { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
                   1472, 1664, 0, 768, 771, 778, 798, 0,
@@ -122,6 +133,14 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360,
                   1496, 1712, 0, 768, 771, 778, 809, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1280x768@120Hz RB */
+       { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 140250, 1280, 1328,
+                  1360, 1440, 0, 768, 771, 778, 813, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+       /* 1280x800@60Hz RB */
+       { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 71000, 1280, 1328,
+                  1360, 1440, 0, 800, 803, 809, 823, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1280x800@60Hz */
        { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
                   1480, 1680, 0, 800, 803, 809, 831, 0,
@@ -134,6 +153,10 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360,
                   1496, 1712, 0, 800, 803, 809, 843, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1280x800@120Hz RB */
+       { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 146250, 1280, 1328,
+                  1360, 1440, 0, 800, 803, 809, 847, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1280x960@60Hz */
        { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
                   1488, 1800, 0, 960, 961, 964, 1000, 0,
@@ -142,6 +165,10 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344,
                   1504, 1728, 0, 960, 961, 964, 1011, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1280x960@120Hz RB */
+       { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 175500, 1280, 1328,
+                  1360, 1440, 0, 960, 963, 967, 1017, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1280x1024@60Hz */
        { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
                   1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
@@ -154,22 +181,42 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344,
                   1504, 1728, 0, 1024, 1025, 1028, 1072, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1280x1024@120Hz RB */
+       { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 187250, 1280, 1328,
+                  1360, 1440, 0, 1024, 1027, 1034, 1084, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1360x768@60Hz */
        { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
                   1536, 1792, 0, 768, 771, 777, 795, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
-       /* 1440x1050@60Hz */
+       /* 1360x768@120Hz RB */
+       { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 148250, 1360, 1408,
+                  1440, 1520, 0, 768, 771, 776, 813, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+       /* 1400x1050@60Hz RB */
+       { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 101000, 1400, 1448,
+                  1480, 1560, 0, 1050, 1053, 1057, 1080, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+       /* 1400x1050@60Hz */
        { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
                   1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-       /* 1440x1050@75Hz */
+       /* 1400x1050@75Hz */
        { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504,
                   1648, 1896, 0, 1050, 1053, 1057, 1099, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-       /* 1440x1050@85Hz */
+       /* 1400x1050@85Hz */
        { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504,
                   1656, 1912, 0, 1050, 1053, 1057, 1105, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1400x1050@120Hz RB */
+       { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 208000, 1400, 1448,
+                  1480, 1560, 0, 1050, 1053, 1057, 1112, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+       /* 1440x900@60Hz RB */
+       { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 88750, 1440, 1488,
+                  1520, 1600, 0, 900, 903, 909, 926, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1440x900@60Hz */
        { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
                   1672, 1904, 0, 900, 903, 909, 934, 0,
@@ -182,6 +229,10 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544,
                   1696, 1952, 0, 900, 903, 909, 948, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1440x900@120Hz RB */
+       { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 182750, 1440, 1488,
+                  1520, 1600, 0, 900, 903, 909, 953, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1600x1200@60Hz */
        { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
                   1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
@@ -202,6 +253,14 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664,
                   1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1600x1200@120Hz RB */
+       { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 268250, 1600, 1648,
+                  1680, 1760, 0, 1200, 1203, 1207, 1271, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+       /* 1680x1050@60Hz RB */
+       { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 119000, 1680, 1728,
+                  1760, 1840, 0, 1050, 1053, 1059, 1080, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1680x1050@60Hz */
        { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
                   1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
@@ -214,15 +273,23 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808,
                   1984, 2288, 0, 1050, 1053, 1059, 1105, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1680x1050@120Hz RB */
+       { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 245500, 1680, 1728,
+                  1760, 1840, 0, 1050, 1053, 1059, 1112, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1792x1344@60Hz */
        { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
                   2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-       /* 1729x1344@75Hz */
+       /* 1792x1344@75Hz */
        { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888,
                   2104, 2456, 0, 1344, 1345, 1348, 1417, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
-       /* 1853x1392@60Hz */
+       /* 1792x1344@120Hz RB */
+       { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 333250, 1792, 1840,
+                  1872, 1952, 0, 1344, 1347, 1351, 1423, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+       /* 1856x1392@60Hz */
        { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
                   2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
@@ -230,6 +297,14 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984,
                   2208, 2560, 0, 1392, 1395, 1399, 1500, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1856x1392@120Hz RB */
+       { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 356500, 1856, 1904,
+                  1936, 2016, 0, 1392, 1395, 1399, 1474, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+       /* 1920x1200@60Hz RB */
+       { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 154000, 1920, 1968,
+                  2000, 2080, 0, 1200, 1203, 1209, 1235, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1920x1200@60Hz */
        { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
                   2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
@@ -242,6 +317,10 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064,
                   2272, 2624, 0, 1200, 1203, 1209, 1262, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1920x1200@120Hz RB */
+       { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 317000, 1920, 1968,
+                  2000, 2080, 0, 1200, 1203, 1209, 1271, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 1920x1440@60Hz */
        { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
                   2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
@@ -250,6 +329,14 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064,
                   2288, 2640, 0, 1440, 1441, 1444, 1500, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 1920x1440@120Hz RB */
+       { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 380500, 1920, 1968,
+                  2000, 2080, 0, 1440, 1443, 1447, 1525, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+       /* 2560x1600@60Hz RB */
+       { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 268500, 2560, 2608,
+                  2640, 2720, 0, 1600, 1603, 1609, 1646, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
        /* 2560x1600@60Hz */
        { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
                   3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
@@ -262,6 +349,11 @@ static const struct drm_display_mode drm_dmt_modes[] = {
        { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768,
                   3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
                   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+       /* 2560x1600@120Hz RB */
+       { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 552750, 2560, 2608,
+                  2640, 2720, 0, 1600, 1603, 1609, 1694, 0,
+                  DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+
 };
 static const int drm_num_dmt_modes =
        sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
@@ -320,12 +412,14 @@ static const struct drm_display_mode edid_est_modes[] = {
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */
 };
 
-static const struct {
+struct minimode {
        short w;
        short h;
        short r;
        short rb;
-} est3_modes[] = {
+};
+
+static const struct minimode est3_modes[] = {
        /* byte 6 */
        { 640, 350, 85, 0 },
        { 640, 400, 85, 0 },
@@ -377,288 +471,304 @@ static const struct {
        { 1920, 1440, 60, 0 },
        { 1920, 1440, 75, 0 },
 };
-static const int num_est3_modes = sizeof(est3_modes) / sizeof(est3_modes[0]);
+static const int num_est3_modes = ARRAY_SIZE(est3_modes);
+
+static const struct minimode extra_modes[] = {
+       { 1024, 576,  60, 0 },
+       { 1366, 768,  60, 0 },
+       { 1600, 900,  60, 0 },
+       { 1680, 945,  60, 0 },
+       { 1920, 1080, 60, 0 },
+       { 2048, 1152, 60, 0 },
+       { 2048, 1536, 60, 0 },
+};
+static const int num_extra_modes = ARRAY_SIZE(extra_modes);
 
 /*
  * Probably taken from CEA-861 spec.
  * This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c.
  */
 static const struct drm_display_mode edid_cea_modes[] = {
-       /* 640x480@60Hz */
+       /* 1 - 640x480@60Hz */
        { 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) },
-       /* 720x480@60Hz */
+       /* 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) },
-       /* 720x480@60Hz */
+       /* 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) },
-       /* 1280x720@60Hz */
+       /* 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) },
-       /* 1920x1080i@60Hz */
+       /* 5 - 1920x1080i@60Hz */
        { DRM_MODE("1920x1080", 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) },
-       /* 1440x480i@60Hz */
+       /* 6 - 1440x480i@60Hz */
        { DRM_MODE("1440x480", 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) },
-       /* 1440x480i@60Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 7 - 1440x480i@60Hz */
        { DRM_MODE("1440x480", 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) },
-       /* 1440x240@60Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 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) },
-       /* 1440x240@60Hz */
+                  DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
+                       DRM_MODE_FLAG_DBLCLK) },
+       /* 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) },
-       /* 2880x480i@60Hz */
+                  DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
+                       DRM_MODE_FLAG_DBLCLK) },
+       /* 10 - 2880x480i@60Hz */
        { DRM_MODE("2880x480", 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) },
-       /* 2880x480i@60Hz */
+       /* 11 - 2880x480i@60Hz */
        { DRM_MODE("2880x480", 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) },
-       /* 2880x240@60Hz */
+       /* 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) },
-       /* 2880x240@60Hz */
+       /* 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) },
-       /* 1440x480@60Hz */
+       /* 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) },
-       /* 1440x480@60Hz */
+       /* 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) },
-       /* 1920x1080@60Hz */
+       /* 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) },
-       /* 720x576@50Hz */
+       /* 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) },
-       /* 720x576@50Hz */
+       /* 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) },
-       /* 1280x720@50Hz */
+       /* 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) },
-       /* 1920x1080i@50Hz */
+       /* 20 - 1920x1080i@50Hz */
        { DRM_MODE("1920x1080", 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) },
-       /* 1440x576i@50Hz */
+       /* 21 - 1440x576i@50Hz */
        { DRM_MODE("1440x576", 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) },
-       /* 1440x576i@50Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 22 - 1440x576i@50Hz */
        { DRM_MODE("1440x576", 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) },
-       /* 1440x288@50Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 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) },
-       /* 1440x288@50Hz */
+                  DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
+                       DRM_MODE_FLAG_DBLCLK) },
+       /* 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) },
-       /* 2880x576i@50Hz */
+                  DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
+                       DRM_MODE_FLAG_DBLCLK) },
+       /* 25 - 2880x576i@50Hz */
        { DRM_MODE("2880x576", 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) },
-       /* 2880x576i@50Hz */
+       /* 26 - 2880x576i@50Hz */
        { DRM_MODE("2880x576", 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) },
-       /* 2880x288@50Hz */
+       /* 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) },
-       /* 2880x288@50Hz */
+       /* 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) },
-       /* 1440x576@50Hz */
+       /* 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) },
-       /* 1440x576@50Hz */
+       /* 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) },
-       /* 1920x1080@50Hz */
+       /* 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) },
-       /* 1920x1080@24Hz */
+       /* 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) },
-       /* 1920x1080@25Hz */
+       /* 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) },
-       /* 1920x1080@30Hz */
+       /* 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) },
-       /* 2880x480@60Hz */
+       /* 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) },
-       /* 2880x480@60Hz */
+       /* 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) },
-       /* 2880x576@50Hz */
+       /* 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) },
-       /* 2880x576@50Hz */
+       /* 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) },
-       /* 1920x1080i@50Hz */
+       /* 39 - 1920x1080i@50Hz */
        { DRM_MODE("1920x1080", 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) },
-       /* 1920x1080i@100Hz */
+       /* 40 - 1920x1080i@100Hz */
        { DRM_MODE("1920x1080", 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) },
-       /* 1280x720@100Hz */
+       /* 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) },
-       /* 720x576@100Hz */
+       /* 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) },
-       /* 720x576@100Hz */
+       /* 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) },
-       /* 1440x576i@100Hz */
+       /* 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) },
-       /* 1440x576i@100Hz */
+                  DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
+                       DRM_MODE_FLAG_DBLCLK) },
+       /* 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) },
-       /* 1920x1080i@120Hz */
+                  DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
+                       DRM_MODE_FLAG_DBLCLK) },
+       /* 46 - 1920x1080i@120Hz */
        { DRM_MODE("1920x1080", 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) },
-       /* 1280x720@120Hz */
+       /* 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) },
-       /* 720x480@120Hz */
+       /* 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) },
-       /* 720x480@120Hz */
+       /* 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) },
-       /* 1440x480i@120Hz */
+       /* 50 - 1440x480i@120Hz */
        { DRM_MODE("1440x480", 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) },
-       /* 1440x480i@120Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 51 - 1440x480i@120Hz */
        { DRM_MODE("1440x480", 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) },
-       /* 720x576@200Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 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) },
-       /* 720x576@200Hz */
+       /* 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) },
-       /* 1440x576i@200Hz */
+       /* 54 - 1440x576i@200Hz */
        { DRM_MODE("1440x576", 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) },
-       /* 1440x576i@200Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 55 - 1440x576i@200Hz */
        { DRM_MODE("1440x576", 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) },
-       /* 720x480@240Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 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) },
-       /* 720x480@240Hz */
+       /* 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) },
-       /* 1440x480i@240 */
+       /* 58 - 1440x480i@240 */
        { DRM_MODE("1440x480", 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) },
-       /* 1440x480i@240 */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 59 - 1440x480i@240 */
        { DRM_MODE("1440x480", 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) },
-       /* 1280x720@24Hz */
+                       DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
+       /* 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) },
-       /* 1280x720@25Hz */
+       /* 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) },
-       /* 1280x720@30Hz */
+       /* 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) },
-       /* 1920x1080@120Hz */
+       /* 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) },
-       /* 1920x1080@100Hz */
+       /* 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) },
 };
-static const int drm_num_cea_modes =
-       sizeof (edid_cea_modes) / sizeof (edid_cea_modes[0]);
+static const int drm_num_cea_modes = ARRAY_SIZE(edid_cea_modes);
index 7740dd26f00706d3b2059f475d10399f8f66d068..6e19dd156be023f8a060b523d2db1f824dde8ea4 100644 (file)
@@ -559,9 +559,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
 
        /* Need to resize the fb object !!! */
-       if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
+       if (var->bits_per_pixel > fb->bits_per_pixel ||
+           var->xres > fb->width || var->yres > fb->height ||
+           var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
                DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
-                         "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
+                         "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
+                         var->xres, var->yres, var->bits_per_pixel,
+                         var->xres_virtual, var->yres_virtual,
                          fb->width, fb->height, fb->bits_per_pixel);
                return -EINVAL;
        }
@@ -1079,7 +1083,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
 
        /* try and find a 1024x768 mode on each connector */
        can_clone = true;
-       dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60);
+       dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false);
 
        for (i = 0; i < fb_helper->connector_count; i++) {
 
index 7348a3dab250a47046eb1f025f12fb3365a5df16..123de28f94ef0613441b6656e9be9f309577c387 100644 (file)
@@ -271,6 +271,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
        if (dev->driver->driver_features & DRIVER_GEM)
                drm_gem_open(dev, priv);
 
+       if (drm_core_check_feature(dev, DRIVER_PRIME))
+               drm_prime_init_file_private(&priv->prime);
+
        if (dev->driver->open) {
                ret = dev->driver->open(dev, priv);
                if (ret < 0)
@@ -504,12 +507,12 @@ int drm_release(struct inode *inode, struct file *filp)
 
        drm_events_release(file_priv);
 
-       if (dev->driver->driver_features & DRIVER_GEM)
-               drm_gem_release(dev, file_priv);
-
        if (dev->driver->driver_features & DRIVER_MODESET)
                drm_fb_release(file_priv);
 
+       if (dev->driver->driver_features & DRIVER_GEM)
+               drm_gem_release(dev, file_priv);
+
        mutex_lock(&dev->ctxlist_mutex);
        if (!list_empty(&dev->ctxlist)) {
                struct drm_ctx_list *pos, *n;
@@ -571,6 +574,10 @@ int drm_release(struct inode *inode, struct file *filp)
 
        if (dev->driver->postclose)
                dev->driver->postclose(dev, file_priv);
+
+       if (drm_core_check_feature(dev, DRIVER_PRIME))
+               drm_prime_destroy_file_private(&file_priv->prime);
+
        kfree(file_priv);
 
        /* ========================================================
index 0ef358e5324542a6be54751527e889c8eb8f3eca..1ab29a7345c5eee126c25d0466429da3ea28ecef 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/mman.h>
 #include <linux/pagemap.h>
 #include <linux/shmem_fs.h>
+#include <linux/dma-buf.h>
 #include "drmP.h"
 
 /** @file drm_gem.c
@@ -232,6 +233,10 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
        idr_remove(&filp->object_idr, handle);
        spin_unlock(&filp->table_lock);
 
+       if (obj->import_attach)
+               drm_prime_remove_imported_buf_handle(&filp->prime,
+                               obj->import_attach->dmabuf);
+
        if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, filp);
        drm_gem_object_handle_unreference_unlocked(obj);
@@ -267,8 +272,7 @@ again:
        spin_unlock(&file_priv->table_lock);
        if (ret == -EAGAIN)
                goto again;
-
-       if (ret != 0)
+       else if (ret)
                return ret;
 
        drm_gem_object_handle_reference(obj);
@@ -451,8 +455,7 @@ again:
 
                if (ret == -EAGAIN)
                        goto again;
-
-               if (ret != 0)
+               else if (ret)
                        goto err;
 
                /* Allocate a reference for the name table.  */
@@ -527,6 +530,10 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
        struct drm_gem_object *obj = ptr;
        struct drm_device *dev = obj->dev;
 
+       if (obj->import_attach)
+               drm_prime_remove_imported_buf_handle(&file_priv->prime,
+                               obj->import_attach->dmabuf);
+
        if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, file_priv);
 
@@ -619,7 +626,7 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
        drm_gem_object_reference(obj);
 
        mutex_lock(&obj->dev->struct_mutex);
-       drm_vm_open_locked(vma);
+       drm_vm_open_locked(obj->dev, vma);
        mutex_unlock(&obj->dev->struct_mutex);
 }
 EXPORT_SYMBOL(drm_gem_vm_open);
@@ -630,7 +637,7 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
        struct drm_device *dev = obj->dev;
 
        mutex_lock(&dev->struct_mutex);
-       drm_vm_close_locked(vma);
+       drm_vm_close_locked(obj->dev, vma);
        drm_gem_object_unreference(obj);
        mutex_unlock(&dev->struct_mutex);
 }
@@ -703,7 +710,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
         */
        drm_gem_object_reference(obj);
 
-       drm_vm_open_locked(vma);
+       drm_vm_open_locked(dev, vma);
 
 out_unlock:
        mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
new file mode 100644 (file)
index 0000000..1bdf2b5
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Copyright Â© 2012 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *      Dave Airlie <airlied@redhat.com>
+ *      Rob Clark <rob.clark@linaro.org>
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/dma-buf.h>
+#include "drmP.h"
+
+/*
+ * DMA-BUF/GEM Object references and lifetime overview:
+ *
+ * On the export the dma_buf holds a reference to the exporting GEM
+ * object. It takes this reference in handle_to_fd_ioctl, when it
+ * first calls .prime_export and stores the exporting GEM object in
+ * the dma_buf priv. This reference is released when the dma_buf
+ * object goes away in the driver .release function.
+ *
+ * On the import the importing GEM object holds a reference to the
+ * dma_buf (which in turn holds a ref to the exporting GEM object).
+ * It takes that reference in the fd_to_handle ioctl.
+ * It calls dma_buf_get, creates an attachment to it and stores the
+ * attachment in the GEM object. When this attachment is destroyed
+ * when the imported object is destroyed, we remove the attachment
+ * and drop the reference to the dma_buf.
+ *
+ * Thus the chain of references always flows in one direction
+ * (avoiding loops): importing_gem -> dmabuf -> exporting_gem
+ *
+ * Self-importing: if userspace is using PRIME as a replacement for flink
+ * then it will get a fd->handle request for a GEM object that it created.
+ * Drivers should detect this situation and return back the gem object
+ * from the dma-buf private.
+ */
+
+struct drm_prime_member {
+       struct list_head entry;
+       struct dma_buf *dma_buf;
+       uint32_t handle;
+};
+
+int drm_gem_prime_handle_to_fd(struct drm_device *dev,
+               struct drm_file *file_priv, uint32_t handle, uint32_t flags,
+               int *prime_fd)
+{
+       struct drm_gem_object *obj;
+       void *buf;
+
+       obj = drm_gem_object_lookup(dev, file_priv, handle);
+       if (!obj)
+               return -ENOENT;
+
+       mutex_lock(&file_priv->prime.lock);
+       /* re-export the original imported object */
+       if (obj->import_attach) {
+               get_dma_buf(obj->import_attach->dmabuf);
+               *prime_fd = dma_buf_fd(obj->import_attach->dmabuf, flags);
+               drm_gem_object_unreference_unlocked(obj);
+               mutex_unlock(&file_priv->prime.lock);
+               return 0;
+       }
+
+       if (obj->export_dma_buf) {
+               get_dma_buf(obj->export_dma_buf);
+               *prime_fd = dma_buf_fd(obj->export_dma_buf, flags);
+               drm_gem_object_unreference_unlocked(obj);
+       } else {
+               buf = dev->driver->gem_prime_export(dev, obj, flags);
+               if (IS_ERR(buf)) {
+                       /* normally the created dma-buf takes ownership of the ref,
+                        * but if that fails then drop the ref
+                        */
+                       drm_gem_object_unreference_unlocked(obj);
+                       mutex_unlock(&file_priv->prime.lock);
+                       return PTR_ERR(buf);
+               }
+               obj->export_dma_buf = buf;
+               *prime_fd = dma_buf_fd(buf, flags);
+       }
+       mutex_unlock(&file_priv->prime.lock);
+       return 0;
+}
+EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
+
+int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+               struct drm_file *file_priv, int prime_fd, uint32_t *handle)
+{
+       struct dma_buf *dma_buf;
+       struct drm_gem_object *obj;
+       int ret;
+
+       dma_buf = dma_buf_get(prime_fd);
+       if (IS_ERR(dma_buf))
+               return PTR_ERR(dma_buf);
+
+       mutex_lock(&file_priv->prime.lock);
+
+       ret = drm_prime_lookup_imported_buf_handle(&file_priv->prime,
+                       dma_buf, handle);
+       if (!ret) {
+               ret = 0;
+               goto out_put;
+       }
+
+       /* never seen this one, need to import */
+       obj = dev->driver->gem_prime_import(dev, dma_buf);
+       if (IS_ERR(obj)) {
+               ret = PTR_ERR(obj);
+               goto out_put;
+       }
+
+       ret = drm_gem_handle_create(file_priv, obj, handle);
+       drm_gem_object_unreference_unlocked(obj);
+       if (ret)
+               goto out_put;
+
+       ret = drm_prime_add_imported_buf_handle(&file_priv->prime,
+                       dma_buf, *handle);
+       if (ret)
+               goto fail;
+
+       mutex_unlock(&file_priv->prime.lock);
+       return 0;
+
+fail:
+       /* hmm, if driver attached, we are relying on the free-object path
+        * to detach.. which seems ok..
+        */
+       drm_gem_object_handle_unreference_unlocked(obj);
+out_put:
+       dma_buf_put(dma_buf);
+       mutex_unlock(&file_priv->prime.lock);
+       return ret;
+}
+EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
+
+int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+{
+       struct drm_prime_handle *args = data;
+       uint32_t flags;
+
+       if (!drm_core_check_feature(dev, DRIVER_PRIME))
+               return -EINVAL;
+
+       if (!dev->driver->prime_handle_to_fd)
+               return -ENOSYS;
+
+       /* check flags are valid */
+       if (args->flags & ~DRM_CLOEXEC)
+               return -EINVAL;
+
+       /* we only want to pass DRM_CLOEXEC which is == O_CLOEXEC */
+       flags = args->flags & DRM_CLOEXEC;
+
+       return dev->driver->prime_handle_to_fd(dev, file_priv,
+                       args->handle, flags, &args->fd);
+}
+
+int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+{
+       struct drm_prime_handle *args = data;
+
+       if (!drm_core_check_feature(dev, DRIVER_PRIME))
+               return -EINVAL;
+
+       if (!dev->driver->prime_fd_to_handle)
+               return -ENOSYS;
+
+       return dev->driver->prime_fd_to_handle(dev, file_priv,
+                       args->fd, &args->handle);
+}
+
+/*
+ * drm_prime_pages_to_sg
+ *
+ * this helper creates an sg table object from a set of pages
+ * the driver is responsible for mapping the pages into the
+ * importers address space
+ */
+struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
+{
+       struct sg_table *sg = NULL;
+       struct scatterlist *iter;
+       int i;
+       int ret;
+
+       sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+       if (!sg)
+               goto out;
+
+       ret = sg_alloc_table(sg, nr_pages, GFP_KERNEL);
+       if (ret)
+               goto out;
+
+       for_each_sg(sg->sgl, iter, nr_pages, i)
+               sg_set_page(iter, pages[i], PAGE_SIZE, 0);
+
+       return sg;
+out:
+       kfree(sg);
+       return NULL;
+}
+EXPORT_SYMBOL(drm_prime_pages_to_sg);
+
+/* helper function to cleanup a GEM/prime object */
+void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
+{
+       struct dma_buf_attachment *attach;
+       struct dma_buf *dma_buf;
+       attach = obj->import_attach;
+       if (sg)
+               dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
+       dma_buf = attach->dmabuf;
+       dma_buf_detach(attach->dmabuf, attach);
+       /* remove the reference */
+       dma_buf_put(dma_buf);
+}
+EXPORT_SYMBOL(drm_prime_gem_destroy);
+
+void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
+{
+       INIT_LIST_HEAD(&prime_fpriv->head);
+       mutex_init(&prime_fpriv->lock);
+}
+EXPORT_SYMBOL(drm_prime_init_file_private);
+
+void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
+{
+       struct drm_prime_member *member, *safe;
+       list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
+               list_del(&member->entry);
+               kfree(member);
+       }
+}
+EXPORT_SYMBOL(drm_prime_destroy_file_private);
+
+int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
+{
+       struct drm_prime_member *member;
+
+       member = kmalloc(sizeof(*member), GFP_KERNEL);
+       if (!member)
+               return -ENOMEM;
+
+       member->dma_buf = dma_buf;
+       member->handle = handle;
+       list_add(&member->entry, &prime_fpriv->head);
+       return 0;
+}
+EXPORT_SYMBOL(drm_prime_add_imported_buf_handle);
+
+int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
+{
+       struct drm_prime_member *member;
+
+       list_for_each_entry(member, &prime_fpriv->head, entry) {
+               if (member->dma_buf == dma_buf) {
+                       *handle = member->handle;
+                       return 0;
+               }
+       }
+       return -ENOENT;
+}
+EXPORT_SYMBOL(drm_prime_lookup_imported_buf_handle);
+
+void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
+{
+       struct drm_prime_member *member, *safe;
+
+       mutex_lock(&prime_fpriv->lock);
+       list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
+               if (member->dma_buf == dma_buf) {
+                       list_del(&member->entry);
+                       kfree(member);
+               }
+       }
+       mutex_unlock(&prime_fpriv->lock);
+}
+EXPORT_SYMBOL(drm_prime_remove_imported_buf_handle);
index aa454f80e1098c641fa82834bc9034df001c578f..ae1ccf1d5d96c68cc27427aaee469b15519e6e06 100644 (file)
@@ -122,11 +122,10 @@ again:
        ret = idr_get_new_above(&drm_minors_idr, NULL,
                                base, &new_id);
        mutex_unlock(&dev->struct_mutex);
-       if (ret == -EAGAIN) {
+       if (ret == -EAGAIN)
                goto again;
-       } else if (ret) {
+       else if (ret)
                return ret;
-       }
 
        if (new_id >= limit) {
                idr_remove(&drm_minors_idr, new_id);
index c8c83dad2ce1443d67782ef94fd3ae70b0505983..37c9a523dd1c6f0c8391766023e43421b36ec57b 100644 (file)
@@ -1,6 +1,6 @@
 #include "drmP.h"
 #include <linux/usb.h>
-#include <linux/export.h>
+#include <linux/module.h>
 
 int drm_get_usb_dev(struct usb_interface *interface,
                    const struct usb_device_id *id,
@@ -114,3 +114,7 @@ void drm_usb_exit(struct drm_driver *driver,
        usb_deregister(udriver);
 }
 EXPORT_SYMBOL(drm_usb_exit);
+
+MODULE_AUTHOR("David Airlie");
+MODULE_DESCRIPTION("USB DRM support");
+MODULE_LICENSE("GPL and additional rights");
index 149561818349e602e39dc469e60a385394c5bdf7..961ee08927fe873cc791dcaa003beb437dd3b0aa 100644 (file)
@@ -406,10 +406,9 @@ static const struct vm_operations_struct drm_vm_sg_ops = {
  * Create a new drm_vma_entry structure as the \p vma private data entry and
  * add it to drm_device::vmalist.
  */
-void drm_vm_open_locked(struct vm_area_struct *vma)
+void drm_vm_open_locked(struct drm_device *dev,
+               struct vm_area_struct *vma)
 {
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *vma_entry;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -430,14 +429,13 @@ static void drm_vm_open(struct vm_area_struct *vma)
        struct drm_device *dev = priv->minor->dev;
 
        mutex_lock(&dev->struct_mutex);
-       drm_vm_open_locked(vma);
+       drm_vm_open_locked(dev, vma);
        mutex_unlock(&dev->struct_mutex);
 }
 
-void drm_vm_close_locked(struct vm_area_struct *vma)
+void drm_vm_close_locked(struct drm_device *dev,
+               struct vm_area_struct *vma)
 {
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *pt, *temp;
 
        DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -467,7 +465,7 @@ static void drm_vm_close(struct vm_area_struct *vma)
        struct drm_device *dev = priv->minor->dev;
 
        mutex_lock(&dev->struct_mutex);
-       drm_vm_close_locked(vma);
+       drm_vm_close_locked(dev, vma);
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -519,7 +517,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        vma->vm_flags |= VM_RESERVED;   /* Don't swap */
        vma->vm_flags |= VM_DONTEXPAND;
 
-       drm_vm_open_locked(vma);
+       drm_vm_open_locked(dev, vma);
        return 0;
 }
 
@@ -670,7 +668,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
        vma->vm_flags |= VM_RESERVED;   /* Don't swap */
        vma->vm_flags |= VM_DONTEXPAND;
 
-       drm_vm_open_locked(vma);
+       drm_vm_open_locked(dev, vma);
        return 0;
 }
 
index 4a3a5f72ed4a42938dd38b998752c63baf953304..de8d2090bce32c769c3c04b0d8105933b648340a 100644 (file)
 static int lowlevel_buffer_allocate(struct drm_device *dev,
                unsigned int flags, struct exynos_drm_gem_buf *buf)
 {
-       dma_addr_t start_addr, end_addr;
+       dma_addr_t start_addr;
        unsigned int npages, page_size, i = 0;
        struct scatterlist *sgl;
        int ret = 0;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (flags & EXYNOS_BO_NONCONTIG) {
+       if (IS_NONCONTIG_BUFFER(flags)) {
                DRM_DEBUG_KMS("not support allocation type.\n");
                return -EINVAL;
        }
@@ -52,13 +52,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
        }
 
        if (buf->size >= SZ_1M) {
-               npages = (buf->size >> SECTION_SHIFT) + 1;
+               npages = buf->size >> SECTION_SHIFT;
                page_size = SECTION_SIZE;
        } else if (buf->size >= SZ_64K) {
-               npages = (buf->size >> 16) + 1;
+               npages = buf->size >> 16;
                page_size = SZ_64K;
        } else {
-               npages = (buf->size >> PAGE_SHIFT) + 1;
+               npages = buf->size >> PAGE_SHIFT;
                page_size = PAGE_SIZE;
        }
 
@@ -76,26 +76,13 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
                return -ENOMEM;
        }
 
-               buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
-                               &buf->dma_addr, GFP_KERNEL);
-               if (!buf->kvaddr) {
-                       DRM_ERROR("failed to allocate buffer.\n");
-                       ret = -ENOMEM;
-                       goto err1;
-               }
-
-               start_addr = buf->dma_addr;
-               end_addr = buf->dma_addr + buf->size;
-
-               buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
-               if (!buf->pages) {
-                       DRM_ERROR("failed to allocate pages.\n");
-                       ret = -ENOMEM;
-                       goto err2;
-               }
-
-       start_addr = buf->dma_addr;
-       end_addr = buf->dma_addr + buf->size;
+       buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
+                       &buf->dma_addr, GFP_KERNEL);
+       if (!buf->kvaddr) {
+               DRM_ERROR("failed to allocate buffer.\n");
+               ret = -ENOMEM;
+               goto err1;
+       }
 
        buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
        if (!buf->pages) {
@@ -105,23 +92,17 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
        }
 
        sgl = buf->sgt->sgl;
+       start_addr = buf->dma_addr;
 
        while (i < npages) {
                buf->pages[i] = phys_to_page(start_addr);
                sg_set_page(sgl, buf->pages[i], page_size, 0);
                sg_dma_address(sgl) = start_addr;
                start_addr += page_size;
-               if (end_addr - start_addr < page_size)
-                       break;
                sgl = sg_next(sgl);
                i++;
        }
 
-       buf->pages[i] = phys_to_page(start_addr);
-
-       sgl = sg_next(sgl);
-       sg_set_page(sgl, buf->pages[i+1], end_addr - start_addr, 0);
-
        DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
                        (unsigned long)buf->kvaddr,
                        (unsigned long)buf->dma_addr,
@@ -150,7 +131,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
         * non-continuous memory would be released by exynos
         * gem framework.
         */
-       if (flags & EXYNOS_BO_NONCONTIG) {
+       if (IS_NONCONTIG_BUFFER(flags)) {
                DRM_DEBUG_KMS("not support allocation type.\n");
                return;
        }
index 411832e8e17aa9fcd9eed13fc614be878f781403..eaf630dc5dba951e78f8a68c2d0bcc1b25ae40b3 100644 (file)
@@ -54,16 +54,18 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
                 *
                 * P.S. note that this driver is considered for modularization.
                 */
-               ret = subdrv->probe(dev, subdrv->manager.dev);
+               ret = subdrv->probe(dev, subdrv->dev);
                if (ret)
                        return ret;
        }
 
-       if (subdrv->is_local)
+       if (!subdrv->manager)
                return 0;
 
+       subdrv->manager->dev = subdrv->dev;
+
        /* create and initialize a encoder for this sub driver. */
-       encoder = exynos_drm_encoder_create(dev, &subdrv->manager,
+       encoder = exynos_drm_encoder_create(dev, subdrv->manager,
                        (1 << MAX_CRTC) - 1);
        if (!encoder) {
                DRM_ERROR("failed to create encoder\n");
@@ -186,7 +188,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
 
        list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
                if (subdrv->open) {
-                       ret = subdrv->open(dev, subdrv->manager.dev, file);
+                       ret = subdrv->open(dev, subdrv->dev, file);
                        if (ret)
                                goto err;
                }
@@ -197,7 +199,7 @@ int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
 err:
        list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
                if (subdrv->close)
-                       subdrv->close(dev, subdrv->manager.dev, file);
+                       subdrv->close(dev, subdrv->dev, file);
        }
        return ret;
 }
@@ -209,7 +211,7 @@ void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
 
        list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
                if (subdrv->close)
-                       subdrv->close(dev, subdrv->manager.dev, file);
+                       subdrv->close(dev, subdrv->dev, file);
        }
 }
 EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
index fbd0a232c93dea173fc4582ebf9aa98c3c620f90..1d814175cd491d39d0411b31fa330c498f02c8c3 100644 (file)
@@ -225,24 +225,25 @@ struct exynos_drm_private {
  * Exynos drm sub driver structure.
  *
  * @list: sub driver has its own list object to register to exynos drm driver.
+ * @dev: pointer to device object for subdrv device driver.
  * @drm_dev: pointer to drm_device and this pointer would be set
  *     when sub driver calls exynos_drm_subdrv_register().
- * @is_local: appear encoder and connector disrelated device.
+ * @manager: subdrv has its own manager to control a hardware appropriately
+ *     and we can access a hardware drawing on this manager.
  * @probe: this callback would be called by exynos drm driver after
  *     subdrv is registered to it.
  * @remove: this callback is used to release resources created
  *     by probe callback.
  * @open: this would be called with drm device file open.
  * @close: this would be called with drm device file close.
- * @manager: subdrv has its own manager to control a hardware appropriately
- *     and we can access a hardware drawing on this manager.
  * @encoder: encoder object owned by this sub driver.
  * @connector: connector object owned by this sub driver.
  */
 struct exynos_drm_subdrv {
        struct list_head list;
+       struct device *dev;
        struct drm_device *drm_dev;
-       bool is_local;
+       struct exynos_drm_manager *manager;
 
        int (*probe)(struct drm_device *drm_dev, struct device *dev);
        void (*remove)(struct drm_device *dev);
@@ -251,7 +252,6 @@ struct exynos_drm_subdrv {
        void (*close)(struct drm_device *drm_dev, struct device *dev,
                        struct drm_file *file);
 
-       struct exynos_drm_manager manager;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
 };
index ecb6db2297008f420ebb7b05e9e19b333bd37286..29fdbfeb43cb79645d034da2d7f8a7aba27dbe5b 100644 (file)
@@ -172,7 +172,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
 static void fimd_apply(struct device *subdrv_dev)
 {
        struct fimd_context *ctx = get_fimd_context(subdrv_dev);
-       struct exynos_drm_manager *mgr = &ctx->subdrv.manager;
+       struct exynos_drm_manager *mgr = ctx->subdrv.manager;
        struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
        struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
        struct fimd_win_data *win_data;
@@ -577,6 +577,13 @@ static struct exynos_drm_overlay_ops fimd_overlay_ops = {
        .disable = fimd_win_disable,
 };
 
+static struct exynos_drm_manager fimd_manager = {
+       .pipe           = -1,
+       .ops            = &fimd_manager_ops,
+       .overlay_ops    = &fimd_overlay_ops,
+       .display_ops    = &fimd_display_ops,
+};
+
 static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
 {
        struct exynos_drm_private *dev_priv = drm_dev->dev_private;
@@ -628,7 +635,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
        struct fimd_context *ctx = (struct fimd_context *)dev_id;
        struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
        struct drm_device *drm_dev = subdrv->drm_dev;
-       struct exynos_drm_manager *manager = &subdrv->manager;
+       struct exynos_drm_manager *manager = subdrv->manager;
        u32 val;
 
        val = readl(ctx->regs + VIDINTCON1);
@@ -744,7 +751,7 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
 static int fimd_power_on(struct fimd_context *ctx, bool enable)
 {
        struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-       struct device *dev = subdrv->manager.dev;
+       struct device *dev = subdrv->dev;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
@@ -867,13 +874,10 @@ static int __devinit fimd_probe(struct platform_device *pdev)
 
        subdrv = &ctx->subdrv;
 
+       subdrv->dev = dev;
+       subdrv->manager = &fimd_manager;
        subdrv->probe = fimd_subdrv_probe;
        subdrv->remove = fimd_subdrv_remove;
-       subdrv->manager.pipe = -1;
-       subdrv->manager.ops = &fimd_manager_ops;
-       subdrv->manager.overlay_ops = &fimd_overlay_ops;
-       subdrv->manager.display_ops = &fimd_display_ops;
-       subdrv->manager.dev = dev;
 
        mutex_init(&ctx->lock);
 
index fa1aa94a3d8e3066f5abf21fdd02331b1d9b5219..1dffa8359f88fd6749d99c2882364797ac0e1eee 100644 (file)
@@ -56,9 +56,28 @@ static unsigned int convert_to_vm_err_msg(int msg)
        return out_msg;
 }
 
-static unsigned int mask_gem_flags(unsigned int flags)
+static int check_gem_flags(unsigned int flags)
 {
-       return flags &= EXYNOS_BO_NONCONTIG;
+       if (flags & ~(EXYNOS_BO_MASK)) {
+               DRM_ERROR("invalid flags.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
+{
+       if (!IS_NONCONTIG_BUFFER(flags)) {
+               if (size >= SZ_1M)
+                       return roundup(size, SECTION_SIZE);
+               else if (size >= SZ_64K)
+                       return roundup(size, SZ_64K);
+               else
+                       goto out;
+       }
+out:
+       return roundup(size, PAGE_SIZE);
 }
 
 static struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
@@ -130,22 +149,12 @@ static int exynos_drm_gem_map_pages(struct drm_gem_object *obj,
        unsigned long pfn;
 
        if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
-               unsigned long usize = buf->size;
-
                if (!buf->pages)
                        return -EINTR;
 
-               while (usize > 0) {
-                       pfn = page_to_pfn(buf->pages[page_offset++]);
-                       vm_insert_mixed(vma, f_vaddr, pfn);
-                       f_vaddr += PAGE_SIZE;
-                       usize -= PAGE_SIZE;
-               }
-
-               return 0;
-       }
-
-       pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
+               pfn = page_to_pfn(buf->pages[page_offset++]);
+       } else
+               pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
 
        return vm_insert_mixed(vma, f_vaddr, pfn);
 }
@@ -319,10 +328,17 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
        struct exynos_drm_gem_buf *buf;
        int ret;
 
-       size = roundup(size, PAGE_SIZE);
-       DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
+       if (!size) {
+               DRM_ERROR("invalid size.\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       size = roundup_gem_size(size, flags);
+       DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       flags = mask_gem_flags(flags);
+       ret = check_gem_flags(flags);
+       if (ret)
+               return ERR_PTR(ret);
 
        buf = exynos_drm_init_buf(dev, size);
        if (!buf)
@@ -331,7 +347,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
        exynos_gem_obj = exynos_drm_gem_init(dev, size);
        if (!exynos_gem_obj) {
                ret = -ENOMEM;
-               goto err;
+               goto err_fini_buf;
        }
 
        exynos_gem_obj->buffer = buf;
@@ -347,18 +363,19 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
                ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);
                if (ret < 0) {
                        drm_gem_object_release(&exynos_gem_obj->base);
-                       goto err;
+                       goto err_fini_buf;
                }
        } else {
                ret = exynos_drm_alloc_buf(dev, buf, flags);
                if (ret < 0) {
                        drm_gem_object_release(&exynos_gem_obj->base);
-                       goto err;
+                       goto err_fini_buf;
                }
        }
 
        return exynos_gem_obj;
-err:
+
+err_fini_buf:
        exynos_drm_fini_buf(dev, buf);
        return ERR_PTR(ret);
 }
@@ -497,6 +514,8 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
                if (!buffer->pages)
                        return -EINVAL;
 
+               vma->vm_flags |= VM_MIXEDMAP;
+
                do {
                        ret = vm_insert_page(vma, uaddr, buffer->pages[i++]);
                        if (ret) {
@@ -554,10 +573,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
        obj->filp->f_op = &exynos_drm_gem_fops;
        obj->filp->private_data = obj;
 
-       down_write(&current->mm->mmap_sem);
-       addr = do_mmap(obj->filp, 0, args->size,
+       addr = vm_mmap(obj->filp, 0, args->size,
                        PROT_READ | PROT_WRITE, MAP_SHARED, 0);
-       up_write(&current->mm->mmap_sem);
 
        drm_gem_object_unreference_unlocked(obj);
 
@@ -685,7 +702,6 @@ int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
 int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_gem_object *obj = vma->vm_private_data;
-       struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
        struct drm_device *dev = obj->dev;
        unsigned long f_vaddr;
        pgoff_t page_offset;
@@ -697,21 +713,10 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        mutex_lock(&dev->struct_mutex);
 
-       /*
-        * allocate all pages as desired size if user wants to allocate
-        * physically non-continuous memory.
-        */
-       if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
-               ret = exynos_drm_gem_get_pages(obj);
-               if (ret < 0)
-                       goto err;
-       }
-
        ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset);
        if (ret < 0)
                DRM_ERROR("failed to map pages.\n");
 
-err:
        mutex_unlock(&dev->struct_mutex);
 
        return convert_to_vm_err_msg(ret);
index e40fbad8b70552abf83d2cf86ccd2cd4e10a5630..4ed842039505d5b6311b7252d5bdc514ec9df721 100644 (file)
@@ -29,6 +29,8 @@
 #define to_exynos_gem_obj(x)   container_of(x,\
                        struct exynos_drm_gem_obj, base)
 
+#define IS_NONCONTIG_BUFFER(f)         (f & EXYNOS_BO_NONCONTIG)
+
 /*
  * exynos drm gem buffer structure.
  *
index 14eb26b0ba1cb1fc70fb533be2adb38fd935ac71..3424463676e0997d4f653b11a400c7cf1f8aefd9 100644 (file)
@@ -30,9 +30,8 @@
                                        struct drm_hdmi_context, subdrv);
 
 /* these callback points shoud be set by specific drivers. */
-static struct exynos_hdmi_display_ops *hdmi_display_ops;
-static struct exynos_hdmi_manager_ops *hdmi_manager_ops;
-static struct exynos_hdmi_overlay_ops *hdmi_overlay_ops;
+static struct exynos_hdmi_ops *hdmi_ops;
+static struct exynos_mixer_ops *mixer_ops;
 
 struct drm_hdmi_context {
        struct exynos_drm_subdrv        subdrv;
@@ -40,31 +39,20 @@ struct drm_hdmi_context {
        struct exynos_drm_hdmi_context  *mixer_ctx;
 };
 
-void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops
-                                       *display_ops)
+void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
 {
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (display_ops)
-               hdmi_display_ops = display_ops;
+       if (ops)
+               hdmi_ops = ops;
 }
 
-void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops
-                                       *manager_ops)
+void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
 {
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (manager_ops)
-               hdmi_manager_ops = manager_ops;
-}
-
-void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops
-                                       *overlay_ops)
-{
-       DRM_DEBUG_KMS("%s\n", __FILE__);
-
-       if (overlay_ops)
-               hdmi_overlay_ops = overlay_ops;
+       if (ops)
+               mixer_ops = ops;
 }
 
 static bool drm_hdmi_is_connected(struct device *dev)
@@ -73,8 +61,8 @@ static bool drm_hdmi_is_connected(struct device *dev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_display_ops && hdmi_display_ops->is_connected)
-               return hdmi_display_ops->is_connected(ctx->hdmi_ctx->ctx);
+       if (hdmi_ops && hdmi_ops->is_connected)
+               return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
 
        return false;
 }
@@ -86,9 +74,9 @@ static int drm_hdmi_get_edid(struct device *dev,
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_display_ops && hdmi_display_ops->get_edid)
-               return hdmi_display_ops->get_edid(ctx->hdmi_ctx->ctx,
-                               connector, edid, len);
+       if (hdmi_ops && hdmi_ops->get_edid)
+               return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid,
+                                         len);
 
        return 0;
 }
@@ -99,9 +87,8 @@ static int drm_hdmi_check_timing(struct device *dev, void *timing)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_display_ops && hdmi_display_ops->check_timing)
-               return hdmi_display_ops->check_timing(ctx->hdmi_ctx->ctx,
-                               timing);
+       if (hdmi_ops && hdmi_ops->check_timing)
+               return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);
 
        return 0;
 }
@@ -112,8 +99,8 @@ static int drm_hdmi_power_on(struct device *dev, int mode)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_display_ops && hdmi_display_ops->power_on)
-               return hdmi_display_ops->power_on(ctx->hdmi_ctx->ctx, mode);
+       if (hdmi_ops && hdmi_ops->power_on)
+               return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
 
        return 0;
 }
@@ -130,13 +117,13 @@ static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
 {
        struct drm_hdmi_context *ctx = to_context(subdrv_dev);
        struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-       struct exynos_drm_manager *manager = &subdrv->manager;
+       struct exynos_drm_manager *manager = subdrv->manager;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_overlay_ops && hdmi_overlay_ops->enable_vblank)
-               return hdmi_overlay_ops->enable_vblank(ctx->mixer_ctx->ctx,
-                                                       manager->pipe);
+       if (mixer_ops && mixer_ops->enable_vblank)
+               return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
+                                               manager->pipe);
 
        return 0;
 }
@@ -147,8 +134,8 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_overlay_ops && hdmi_overlay_ops->disable_vblank)
-               return hdmi_overlay_ops->disable_vblank(ctx->mixer_ctx->ctx);
+       if (mixer_ops && mixer_ops->disable_vblank)
+               return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
 }
 
 static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
@@ -160,9 +147,9 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_manager_ops && hdmi_manager_ops->mode_fixup)
-               hdmi_manager_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector,
-                                               mode, adjusted_mode);
+       if (hdmi_ops && hdmi_ops->mode_fixup)
+               hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode,
+                                    adjusted_mode);
 }
 
 static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
@@ -171,8 +158,8 @@ static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_manager_ops && hdmi_manager_ops->mode_set)
-               hdmi_manager_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
+       if (hdmi_ops && hdmi_ops->mode_set)
+               hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
 }
 
 static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
@@ -182,9 +169,8 @@ static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_manager_ops && hdmi_manager_ops->get_max_resol)
-               hdmi_manager_ops->get_max_resol(ctx->hdmi_ctx->ctx, width,
-                                                       height);
+       if (hdmi_ops && hdmi_ops->get_max_resol)
+               hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
 }
 
 static void drm_hdmi_commit(struct device *subdrv_dev)
@@ -193,8 +179,8 @@ static void drm_hdmi_commit(struct device *subdrv_dev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_manager_ops && hdmi_manager_ops->commit)
-               hdmi_manager_ops->commit(ctx->hdmi_ctx->ctx);
+       if (hdmi_ops && hdmi_ops->commit)
+               hdmi_ops->commit(ctx->hdmi_ctx->ctx);
 }
 
 static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
@@ -209,8 +195,8 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
-               if (hdmi_manager_ops && hdmi_manager_ops->disable)
-                       hdmi_manager_ops->disable(ctx->hdmi_ctx->ctx);
+               if (hdmi_ops && hdmi_ops->disable)
+                       hdmi_ops->disable(ctx->hdmi_ctx->ctx);
                break;
        default:
                DRM_DEBUG_KMS("unkown dps mode: %d\n", mode);
@@ -235,8 +221,8 @@ static void drm_mixer_mode_set(struct device *subdrv_dev,
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_overlay_ops && hdmi_overlay_ops->win_mode_set)
-               hdmi_overlay_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
+       if (mixer_ops && mixer_ops->win_mode_set)
+               mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
 }
 
 static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
@@ -245,8 +231,8 @@ static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_overlay_ops && hdmi_overlay_ops->win_commit)
-               hdmi_overlay_ops->win_commit(ctx->mixer_ctx->ctx, zpos);
+       if (mixer_ops && mixer_ops->win_commit)
+               mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos);
 }
 
 static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
@@ -255,8 +241,8 @@ static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (hdmi_overlay_ops && hdmi_overlay_ops->win_disable)
-               hdmi_overlay_ops->win_disable(ctx->mixer_ctx->ctx, zpos);
+       if (mixer_ops && mixer_ops->win_disable)
+               mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos);
 }
 
 static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
@@ -265,6 +251,12 @@ static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
        .disable = drm_mixer_disable,
 };
 
+static struct exynos_drm_manager hdmi_manager = {
+       .pipe           = -1,
+       .ops            = &drm_hdmi_manager_ops,
+       .overlay_ops    = &drm_hdmi_overlay_ops,
+       .display_ops    = &drm_hdmi_display_ops,
+};
 
 static int hdmi_subdrv_probe(struct drm_device *drm_dev,
                struct device *dev)
@@ -332,12 +324,9 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
 
        subdrv = &ctx->subdrv;
 
+       subdrv->dev = dev;
+       subdrv->manager = &hdmi_manager;
        subdrv->probe = hdmi_subdrv_probe;
-       subdrv->manager.pipe = -1;
-       subdrv->manager.ops = &drm_hdmi_manager_ops;
-       subdrv->manager.overlay_ops = &drm_hdmi_overlay_ops;
-       subdrv->manager.display_ops = &drm_hdmi_display_ops;
-       subdrv->manager.dev = dev;
 
        platform_set_drvdata(pdev, subdrv);
 
index 44497cfb6c74174ebb6faab6f5f0729ad712c43c..f3ae192c8dcf6e21b5977e5e210ceaf547f84999 100644 (file)
@@ -38,15 +38,15 @@ struct exynos_drm_hdmi_context {
        void                    *ctx;
 };
 
-struct exynos_hdmi_display_ops {
+struct exynos_hdmi_ops {
+       /* display */
        bool (*is_connected)(void *ctx);
        int (*get_edid)(void *ctx, struct drm_connector *connector,
                        u8 *edid, int len);
        int (*check_timing)(void *ctx, void *timing);
        int (*power_on)(void *ctx, int mode);
-};
 
-struct exynos_hdmi_manager_ops {
+       /* manager */
        void (*mode_fixup)(void *ctx, struct drm_connector *connector,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode);
@@ -57,22 +57,17 @@ struct exynos_hdmi_manager_ops {
        void (*disable)(void *ctx);
 };
 
-struct exynos_hdmi_overlay_ops {
+struct exynos_mixer_ops {
+       /* manager */
        int (*enable_vblank)(void *ctx, int pipe);
        void (*disable_vblank)(void *ctx);
+
+       /* overlay */
        void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
        void (*win_commit)(void *ctx, int zpos);
        void (*win_disable)(void *ctx, int zpos);
 };
 
-extern struct platform_driver hdmi_driver;
-extern struct platform_driver mixer_driver;
-
-void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops
-                                       *display_ops);
-void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops
-                                       *manager_ops);
-void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops
-                                       *overlay_ops);
-
+void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops);
+void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);
 #endif
index c277a3a445f5a206209dc898ded6f15500b084a7..f92fe4c6174ad163bf250786e77949c9e2d9230e 100644 (file)
@@ -24,6 +24,10 @@ struct exynos_plane {
 
 static const uint32_t formats[] = {
        DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_NV12,
+       DRM_FORMAT_NV12M,
+       DRM_FORMAT_NV12MT,
 };
 
 static int
index 8e1339f9fe1fac6bcfde1a07e46d53f3e6558d00..7b9c153dceb610776f59711d4c5c3c303ff21228 100644 (file)
@@ -199,7 +199,7 @@ static void vidi_dpms(struct device *subdrv_dev, int mode)
 static void vidi_apply(struct device *subdrv_dev)
 {
        struct vidi_context *ctx = get_vidi_context(subdrv_dev);
-       struct exynos_drm_manager *mgr = &ctx->subdrv.manager;
+       struct exynos_drm_manager *mgr = ctx->subdrv.manager;
        struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
        struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
        struct vidi_win_data *win_data;
@@ -374,6 +374,13 @@ static struct exynos_drm_overlay_ops vidi_overlay_ops = {
        .disable = vidi_win_disable,
 };
 
+static struct exynos_drm_manager vidi_manager = {
+       .pipe           = -1,
+       .ops            = &vidi_manager_ops,
+       .overlay_ops    = &vidi_overlay_ops,
+       .display_ops    = &vidi_display_ops,
+};
+
 static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc)
 {
        struct exynos_drm_private *dev_priv = drm_dev->dev_private;
@@ -425,7 +432,7 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
        struct vidi_context *ctx = container_of(work, struct vidi_context,
                                        work);
        struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-       struct exynos_drm_manager *manager = &subdrv->manager;
+       struct exynos_drm_manager *manager = subdrv->manager;
 
        if (manager->pipe < 0)
                return;
@@ -471,7 +478,7 @@ static void vidi_subdrv_remove(struct drm_device *drm_dev)
 static int vidi_power_on(struct vidi_context *ctx, bool enable)
 {
        struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
-       struct device *dev = subdrv->manager.dev;
+       struct device *dev = subdrv->dev;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
@@ -611,13 +618,10 @@ static int __devinit vidi_probe(struct platform_device *pdev)
        ctx->raw_edid = (struct edid *)fake_edid_info;
 
        subdrv = &ctx->subdrv;
+       subdrv->dev = dev;
+       subdrv->manager = &vidi_manager;
        subdrv->probe = vidi_subdrv_probe;
        subdrv->remove = vidi_subdrv_remove;
-       subdrv->manager.pipe = -1;
-       subdrv->manager.ops = &vidi_manager_ops;
-       subdrv->manager.overlay_ops = &vidi_overlay_ops;
-       subdrv->manager.display_ops = &vidi_display_ops;
-       subdrv->manager.dev = dev;
 
        mutex_init(&ctx->lock);
 
index 575a8cbd35337b2719195b733485c4d04aee580c..b00353876458577f702f1b104f67bbd3c20915bf 100644 (file)
@@ -40,7 +40,6 @@
 
 #include "exynos_hdmi.h"
 
-#define HDMI_OVERLAY_NUMBER    3
 #define MAX_WIDTH              1920
 #define MAX_HEIGHT             1080
 #define get_hdmi_context(dev)  platform_get_drvdata(to_platform_device(dev))
@@ -1194,7 +1193,7 @@ static int hdmi_conf_index(struct hdmi_context *hdata,
 
 static bool hdmi_is_connected(void *ctx)
 {
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+       struct hdmi_context *hdata = ctx;
        u32 val = hdmi_reg_read(hdata, HDMI_HPD_STATUS);
 
        if (val)
@@ -1207,7 +1206,7 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
                                u8 *edid, int len)
 {
        struct edid *raw_edid;
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+       struct hdmi_context *hdata = ctx;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
@@ -1275,7 +1274,7 @@ static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
 
 static int hdmi_check_timing(void *ctx, void *timing)
 {
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+       struct hdmi_context *hdata = ctx;
        struct fb_videomode *check_timing = timing;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1312,13 +1311,6 @@ static int hdmi_display_power_on(void *ctx, int mode)
        return 0;
 }
 
-static struct exynos_hdmi_display_ops display_ops = {
-       .is_connected   = hdmi_is_connected,
-       .get_edid       = hdmi_get_edid,
-       .check_timing   = hdmi_check_timing,
-       .power_on       = hdmi_display_power_on,
-};
-
 static void hdmi_set_acr(u32 freq, u8 *acr)
 {
        u32 n, cts;
@@ -1914,7 +1906,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
                                struct drm_display_mode *adjusted_mode)
 {
        struct drm_display_mode *m;
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+       struct hdmi_context *hdata = ctx;
        int index;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1951,7 +1943,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
 
 static void hdmi_mode_set(void *ctx, void *mode)
 {
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+       struct hdmi_context *hdata = ctx;
        int conf_idx;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1974,7 +1966,7 @@ static void hdmi_get_max_resol(void *ctx, unsigned int *width,
 
 static void hdmi_commit(void *ctx)
 {
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+       struct hdmi_context *hdata = ctx;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
@@ -1985,7 +1977,7 @@ static void hdmi_commit(void *ctx)
 
 static void hdmi_disable(void *ctx)
 {
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+       struct hdmi_context *hdata = ctx;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
@@ -1996,7 +1988,14 @@ static void hdmi_disable(void *ctx)
        }
 }
 
-static struct exynos_hdmi_manager_ops manager_ops = {
+static struct exynos_hdmi_ops hdmi_ops = {
+       /* display */
+       .is_connected   = hdmi_is_connected,
+       .get_edid       = hdmi_get_edid,
+       .check_timing   = hdmi_check_timing,
+       .power_on       = hdmi_display_power_on,
+
+       /* manager */
        .mode_fixup     = hdmi_mode_fixup,
        .mode_set       = hdmi_mode_set,
        .get_max_resol  = hdmi_get_max_resol,
@@ -2020,7 +2019,7 @@ static void hdmi_hotplug_func(struct work_struct *work)
 static irqreturn_t hdmi_irq_handler(int irq, void *arg)
 {
        struct exynos_drm_hdmi_context *ctx = arg;
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx;
+       struct hdmi_context *hdata = ctx->ctx;
        u32 intc_flag;
 
        intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
@@ -2173,7 +2172,7 @@ static int hdmi_runtime_suspend(struct device *dev)
 
        DRM_DEBUG_KMS("%s\n", __func__);
 
-       hdmi_resource_poweroff((struct hdmi_context *)ctx->ctx);
+       hdmi_resource_poweroff(ctx->ctx);
 
        return 0;
 }
@@ -2184,7 +2183,7 @@ static int hdmi_runtime_resume(struct device *dev)
 
        DRM_DEBUG_KMS("%s\n", __func__);
 
-       hdmi_resource_poweron((struct hdmi_context *)ctx->ctx);
+       hdmi_resource_poweron(ctx->ctx);
 
        return 0;
 }
@@ -2322,8 +2321,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
        hdata->irq = res->start;
 
        /* register specific callbacks to common hdmi. */
-       exynos_drm_display_ops_register(&display_ops);
-       exynos_drm_manager_ops_register(&manager_ops);
+       exynos_hdmi_ops_register(&hdmi_ops);
 
        hdmi_resource_poweron(hdata);
 
@@ -2351,7 +2349,7 @@ err_data:
 static int __devexit hdmi_remove(struct platform_device *pdev)
 {
        struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
-       struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx;
+       struct hdmi_context *hdata = ctx->ctx;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
index 4d5f41e19527f0514fd63d4d46fb958701247462..e15438c01129249e397a32ae2bea7c15eb10af86 100644 (file)
@@ -37,7 +37,8 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_hdmi.h"
 
-#define HDMI_OVERLAY_NUMBER    3
+#define MIXER_WIN_NR           3
+#define MIXER_DEFAULT_WIN      0
 
 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
 
@@ -75,16 +76,12 @@ struct mixer_resources {
 };
 
 struct mixer_context {
-       struct fb_videomode     *default_timing;
-       unsigned int            default_win;
-       unsigned int            default_bpp;
        unsigned int            irq;
        int                     pipe;
        bool                    interlace;
-       bool                    vp_enabled;
 
        struct mixer_resources  mixer_res;
-       struct hdmi_win_data    win_data[HDMI_OVERLAY_NUMBER];
+       struct hdmi_win_data    win_data[MIXER_WIN_NR];
 };
 
 static const u8 filter_y_horiz_tap8[] = {
@@ -643,9 +640,9 @@ static void mixer_win_mode_set(void *ctx,
 
        win = overlay->zpos;
        if (win == DEFAULT_ZPOS)
-               win = mixer_ctx->default_win;
+               win = MIXER_DEFAULT_WIN;
 
-       if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
+       if (win < 0 || win > MIXER_WIN_NR) {
                DRM_ERROR("overlay plane[%d] is wrong\n", win);
                return;
        }
@@ -683,9 +680,9 @@ static void mixer_win_commit(void *ctx, int zpos)
        DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
 
        if (win == DEFAULT_ZPOS)
-               win = mixer_ctx->default_win;
+               win = MIXER_DEFAULT_WIN;
 
-       if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
+       if (win < 0 || win > MIXER_WIN_NR) {
                DRM_ERROR("overlay plane[%d] is wrong\n", win);
                return;
        }
@@ -706,9 +703,9 @@ static void mixer_win_disable(void *ctx, int zpos)
        DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
 
        if (win == DEFAULT_ZPOS)
-               win = mixer_ctx->default_win;
+               win = MIXER_DEFAULT_WIN;
 
-       if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
+       if (win < 0 || win > MIXER_WIN_NR) {
                DRM_ERROR("overlay plane[%d] is wrong\n", win);
                return;
        }
@@ -722,9 +719,12 @@ static void mixer_win_disable(void *ctx, int zpos)
        spin_unlock_irqrestore(&res->reg_slock, flags);
 }
 
-static struct exynos_hdmi_overlay_ops overlay_ops = {
+static struct exynos_mixer_ops mixer_ops = {
+       /* manager */
        .enable_vblank          = mixer_enable_vblank,
        .disable_vblank         = mixer_disable_vblank,
+
+       /* overlay */
        .win_mode_set           = mixer_win_mode_set,
        .win_commit             = mixer_win_commit,
        .win_disable            = mixer_win_disable,
@@ -771,8 +771,7 @@ static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
 static irqreturn_t mixer_irq_handler(int irq, void *arg)
 {
        struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
-       struct mixer_context *ctx =
-                       (struct mixer_context *)drm_hdmi_ctx->ctx;
+       struct mixer_context *ctx = drm_hdmi_ctx->ctx;
        struct mixer_resources *res = &ctx->mixer_res;
        u32 val, val_base;
 
@@ -902,7 +901,7 @@ static int mixer_runtime_resume(struct device *dev)
 
        DRM_DEBUG_KMS("resume - start\n");
 
-       mixer_resource_poweron((struct mixer_context *)ctx->ctx);
+       mixer_resource_poweron(ctx->ctx);
 
        return 0;
 }
@@ -913,7 +912,7 @@ static int mixer_runtime_suspend(struct device *dev)
 
        DRM_DEBUG_KMS("suspend - start\n");
 
-       mixer_resource_poweroff((struct mixer_context *)ctx->ctx);
+       mixer_resource_poweroff(ctx->ctx);
 
        return 0;
 }
@@ -926,8 +925,7 @@ static const struct dev_pm_ops mixer_pm_ops = {
 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
                                 struct platform_device *pdev)
 {
-       struct mixer_context *mixer_ctx =
-                       (struct mixer_context *)ctx->ctx;
+       struct mixer_context *mixer_ctx = ctx->ctx;
        struct device *dev = &pdev->dev;
        struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
        struct resource *res;
@@ -1076,7 +1074,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
                goto fail;
 
        /* register specific callback point to common hdmi. */
-       exynos_drm_overlay_ops_register(&overlay_ops);
+       exynos_mixer_ops_register(&mixer_ops);
 
        mixer_resource_poweron(ctx);
 
@@ -1093,7 +1091,7 @@ static int mixer_remove(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct exynos_drm_hdmi_context *drm_hdmi_ctx =
                                        platform_get_drvdata(pdev);
-       struct mixer_context *ctx = (struct mixer_context *)drm_hdmi_ctx->ctx;
+       struct mixer_context *ctx = drm_hdmi_ctx->ctx;
 
        dev_info(dev, "remove successful\n");
 
index 1583982917ceb15d67bbcb36b9d0fe3fdaa4265a..abfa2a93f0d0326bba0b8d7e14c9c0b69909d56c 100644 (file)
@@ -1,7 +1,7 @@
 #
 #      KMS driver for the GMA500
 #
-ccflags-y += -Iinclude/drm
+ccflags-y += -I$(srctree)/include/drm
 
 gma500_gfx-y += gem_glue.o \
          accel_2d.o \
@@ -12,7 +12,6 @@ gma500_gfx-y += gem_glue.o \
          intel_bios.o \
          intel_i2c.o \
          intel_gmbus.o \
-         intel_opregion.o \
          mmu.o \
          power.o \
          psb_drv.o \
@@ -25,6 +24,8 @@ gma500_gfx-y += gem_glue.o \
          psb_device.o \
          mid_bios.o
 
+gma500_gfx-$(CONFIG_ACPI) +=  opregion.o \
+
 gma500_gfx-$(CONFIG_DRM_GMA3600) +=  cdv_device.o \
          cdv_intel_crt.o \
          cdv_intel_display.o \
index a54cc738926ae01b4159ae44ce22076bdfddc000..8e393303f53af3a2bf0c49aea8c89a7ee378970f 100644 (file)
@@ -49,13 +49,15 @@ static void cdv_disable_vga(struct drm_device *dev)
 static int cdv_output_init(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
+
+       drm_mode_create_scaling_mode_property(dev);
+
        cdv_disable_vga(dev);
 
        cdv_intel_crt_init(dev, &dev_priv->mode_dev);
        cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
 
-       /* These bits indicate HDMI not SDVO on CDV, but we don't yet support
-          the HDMI interface */
+       /* These bits indicate HDMI not SDVO on CDV */
        if (REG_READ(SDVOB) & SDVO_DETECTED)
                cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
        if (REG_READ(SDVOC) & SDVO_DETECTED)
@@ -66,76 +68,71 @@ static int cdv_output_init(struct drm_device *dev)
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 
 /*
- *     Poulsbo Backlight Interfaces
+ *     Cedartrail Backlght Interfaces
  */
 
-#define BLC_PWM_PRECISION_FACTOR 100   /* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-
-#define PSB_BLC_PWM_PRECISION_FACTOR    10
-#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
-#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
-
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT    (16)
-
-static int cdv_brightness;
 static struct backlight_device *cdv_backlight_device;
 
-static int cdv_get_brightness(struct backlight_device *bd)
+static int cdv_backlight_combination_mode(struct drm_device *dev)
 {
-       /* return locally cached var instead of HW read (due to DPST etc.) */
-       /* FIXME: ideally return actual value in case firmware fiddled with
-          it */
-       return cdv_brightness;
+       return REG_READ(BLC_PWM_CTL2) & PWM_LEGACY_MODE;
 }
 
-
-static int cdv_backlight_setup(struct drm_device *dev)
+static int cdv_get_brightness(struct backlight_device *bd)
 {
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       unsigned long core_clock;
-       /* u32 bl_max_freq; */
-       /* unsigned long value; */
-       u16 bl_max_freq;
-       uint32_t value;
-       uint32_t blc_pwm_precision_factor;
-
-       /* get bl_max_freq and pol from dev_priv*/
-       if (!dev_priv->lvds_bl) {
-               dev_err(dev->dev, "Has no valid LVDS backlight info\n");
-               return -ENOENT;
-       }
-       bl_max_freq = dev_priv->lvds_bl->freq;
-       blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
+       struct drm_device *dev = bl_get_data(bd);
+       u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
 
-       core_clock = dev_priv->core_freq;
+       if (cdv_backlight_combination_mode(dev)) {
+               u8 lbpc;
 
-       value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
-       value *= blc_pwm_precision_factor;
-       value /= bl_max_freq;
-       value /= blc_pwm_precision_factor;
+               val &= ~1;
+               pci_read_config_byte(dev->pdev, 0xF4, &lbpc);
+               val *= lbpc;
+       }
+       return val;
+}
 
-       if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
-                value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
-                               return -ERANGE;
-       else {
-               /* FIXME */
+static u32 cdv_get_max_backlight(struct drm_device *dev)
+{
+       u32 max = REG_READ(BLC_PWM_CTL);
+
+       if (max == 0) {
+               DRM_DEBUG_KMS("LVDS Panel PWM value is 0!\n");
+               /* i915 does this, I believe which means that we should not
+                * smash PWM control as firmware will take control of it. */
+               return 1;
        }
-       return 0;
+
+       max >>= 16;
+       if (cdv_backlight_combination_mode(dev))
+               max *= 0xff;
+       return max;
 }
 
 static int cdv_set_brightness(struct backlight_device *bd)
 {
+       struct drm_device *dev = bl_get_data(bd);
        int level = bd->props.brightness;
+       u32 blc_pwm_ctl;
 
        /* Percentage 1-100% being valid */
        if (level < 1)
                level = 1;
 
-       /*cdv_intel_lvds_set_brightness(dev, level); FIXME */
-       cdv_brightness = level;
+       if (cdv_backlight_combination_mode(dev)) {
+               u32 max = cdv_get_max_backlight(dev);
+               u8 lbpc;
+
+               lbpc = level * 0xfe / max + 1;
+               level /= lbpc;
+
+               pci_write_config_byte(dev->pdev, 0xF4, lbpc);
+       }
+
+       blc_pwm_ctl = REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       REG_WRITE(BLC_PWM_CTL, (blc_pwm_ctl |
+                               (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
        return 0;
 }
 
@@ -147,7 +144,6 @@ static const struct backlight_ops cdv_ops = {
 static int cdv_backlight_init(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
-       int ret;
        struct backlight_properties props;
 
        memset(&props, 0, sizeof(struct backlight_properties));
@@ -159,14 +155,9 @@ static int cdv_backlight_init(struct drm_device *dev)
        if (IS_ERR(cdv_backlight_device))
                return PTR_ERR(cdv_backlight_device);
 
-       ret = cdv_backlight_setup(dev);
-       if (ret < 0) {
-               backlight_device_unregister(cdv_backlight_device);
-               cdv_backlight_device = NULL;
-               return ret;
-       }
-       cdv_backlight_device->props.brightness = 100;
-       cdv_backlight_device->props.max_brightness = 100;
+       cdv_backlight_device->props.brightness =
+                       cdv_get_brightness(cdv_backlight_device);
+       cdv_backlight_device->props.max_brightness = cdv_get_max_backlight(dev);
        backlight_update_status(cdv_backlight_device);
        dev_priv->backlight_device = cdv_backlight_device;
        return 0;
@@ -238,6 +229,19 @@ static void cdv_init_pm(struct drm_device *dev)
        dev_err(dev->dev, "GPU: power management timed out.\n");
 }
 
+static void cdv_errata(struct drm_device *dev)
+{
+       /* Disable bonus launch.
+        *      CPU and GPU competes for memory and display misses updates and
+        *      flickers. Worst with dual core, dual displays.
+        *
+        *      Fixes were done to Win 7 gfx driver to disable a feature called
+        *      Bonus Launch to work around the issue, by degrading
+        *      performance.
+        */
+        CDV_MSG_WRITE32(3, 0x30, 0x08027108);
+}
+
 /**
  *     cdv_save_display_registers      -       save registers lost on suspend
  *     @dev: our DRM device
@@ -251,7 +255,7 @@ static int cdv_save_display_registers(struct drm_device *dev)
        struct psb_save_area *regs = &dev_priv->regs;
        struct drm_connector *connector;
 
-       dev_info(dev->dev, "Saving GPU registers.\n");
+       dev_dbg(dev->dev, "Saving GPU registers.\n");
 
        pci_read_config_byte(dev->pdev, 0xF4, &regs->cdv.saveLBB);
 
@@ -355,7 +359,7 @@ static int cdv_restore_display_registers(struct drm_device *dev)
        REG_WRITE(PSB_INT_MASK_R, regs->cdv.saveIMR);
 
        /* Fix arbitration bug */
-       CDV_MSG_WRITE32(3, 0x30, 0x08027108);
+       cdv_errata(dev);
 
        drm_mode_config_reset(dev);
 
@@ -447,13 +451,106 @@ static void cdv_get_core_freq(struct drm_device *dev)
        }
 }
 
+static void cdv_hotplug_work_func(struct work_struct *work)
+{
+        struct drm_psb_private *dev_priv = container_of(work, struct drm_psb_private,
+                                                       hotplug_work);                 
+        struct drm_device *dev = dev_priv->dev;
+
+        /* Just fire off a uevent and let userspace tell us what to do */
+        drm_helper_hpd_irq_event(dev);
+}                       
+
+/* The core driver has received a hotplug IRQ. We are in IRQ context
+   so extract the needed information and kick off queued processing */
+   
+static int cdv_hotplug_event(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       schedule_work(&dev_priv->hotplug_work);
+       REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
+       return 1;
+}
+
+static void cdv_hotplug_enable(struct drm_device *dev, bool on)
+{
+       if (on) {
+               u32 hotplug = REG_READ(PORT_HOTPLUG_EN);
+               hotplug |= HDMIB_HOTPLUG_INT_EN | HDMIC_HOTPLUG_INT_EN |
+                          HDMID_HOTPLUG_INT_EN | CRT_HOTPLUG_INT_EN;
+               REG_WRITE(PORT_HOTPLUG_EN, hotplug);
+       }  else {
+               REG_WRITE(PORT_HOTPLUG_EN, 0);
+               REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
+       }       
+}
+
+/* Cedarview */
+static const struct psb_offset cdv_regmap[2] = {
+       {
+               .fp0 = FPA0,
+               .fp1 = FPA1,
+               .cntr = DSPACNTR,
+               .conf = PIPEACONF,
+               .src = PIPEASRC,
+               .dpll = DPLL_A,
+               .dpll_md = DPLL_A_MD,
+               .htotal = HTOTAL_A,
+               .hblank = HBLANK_A,
+               .hsync = HSYNC_A,
+               .vtotal = VTOTAL_A,
+               .vblank = VBLANK_A,
+               .vsync = VSYNC_A,
+               .stride = DSPASTRIDE,
+               .size = DSPASIZE,
+               .pos = DSPAPOS,
+               .base = DSPABASE,
+               .surf = DSPASURF,
+               .addr = DSPABASE,
+               .status = PIPEASTAT,
+               .linoff = DSPALINOFF,
+               .tileoff = DSPATILEOFF,
+               .palette = PALETTE_A,
+       },
+       {
+               .fp0 = FPB0,
+               .fp1 = FPB1,
+               .cntr = DSPBCNTR,
+               .conf = PIPEBCONF,
+               .src = PIPEBSRC,
+               .dpll = DPLL_B,
+               .dpll_md = DPLL_B_MD,
+               .htotal = HTOTAL_B,
+               .hblank = HBLANK_B,
+               .hsync = HSYNC_B,
+               .vtotal = VTOTAL_B,
+               .vblank = VBLANK_B,
+               .vsync = VSYNC_B,
+               .stride = DSPBSTRIDE,
+               .size = DSPBSIZE,
+               .pos = DSPBPOS,
+               .base = DSPBBASE,
+               .surf = DSPBSURF,
+               .addr = DSPBBASE,
+               .status = PIPEBSTAT,
+               .linoff = DSPBLINOFF,
+               .tileoff = DSPBTILEOFF,
+               .palette = PALETTE_B,
+       }
+};
+
 static int cdv_chip_setup(struct drm_device *dev)
 {
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       INIT_WORK(&dev_priv->hotplug_work, cdv_hotplug_work_func);
+
+       if (pci_enable_msi(dev->pdev))
+               dev_warn(dev->dev, "Enabling MSI failed!\n");
+       dev_priv->regmap = cdv_regmap;
        cdv_get_core_freq(dev);
-       gma_intel_opregion_init(dev);
+       psb_intel_opregion_init(dev);
        psb_intel_init_bios(dev);
-       REG_WRITE(PORT_HOTPLUG_EN, 0);
-       REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
+       cdv_hotplug_enable(dev, false);
        return 0;
 }
 
@@ -464,13 +561,18 @@ const struct psb_ops cdv_chip_ops = {
        .accel_2d = 0,
        .pipes = 2,
        .crtcs = 2,
+       .hdmi_mask = (1 << 0) | (1 << 1),
+       .lvds_mask = (1 << 1),
        .sgx_offset = MRST_SGX_OFFSET,
        .chip_setup = cdv_chip_setup,
+       .errata = cdv_errata,
 
        .crtc_helper = &cdv_intel_helper_funcs,
        .crtc_funcs = &cdv_intel_crtc_funcs,
 
        .output_init = cdv_output_init,
+       .hotplug = cdv_hotplug_event,
+       .hotplug_enable = cdv_hotplug_enable,
 
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
        .backlight_init = cdv_backlight_init,
index a71a6cd95bdd6e5a522ca58e156d506d12caed6c..187422018601354e656e626ac1198f731aa94923 100644 (file)
@@ -67,8 +67,6 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
 static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
                                struct drm_display_mode *mode)
 {
-       struct drm_psb_private *dev_priv = connector->dev->dev_private;
-       int max_clock = 0;
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
 
@@ -77,18 +75,9 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
                return MODE_CLOCK_LOW;
 
        /* The max clock for CDV is 355 instead of 400 */
-       max_clock = 355000;
-       if (mode->clock > max_clock)
+       if (mode->clock > 355000)
                return MODE_CLOCK_HIGH;
 
-       if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
-               return MODE_PANEL;
-
-       /* We assume worst case scenario of 32 bpp here, since we don't know */
-       if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
-           dev_priv->vram_stolen_size)
-               return MODE_MEM;
-
        return MODE_OK;
 }
 
@@ -156,13 +145,7 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector,
        struct drm_device *dev = connector->dev;
        u32 hotplug_en;
        int i, tries = 0, ret = false;
-       u32 adpa_orig;
-
-       /* disable the DAC when doing the hotplug detection */
-
-       adpa_orig = REG_READ(ADPA);
-
-       REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE));
+       u32 orig;
 
        /*
         * On a CDV thep, CRT detect sequence need to be done twice
@@ -170,7 +153,7 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector,
         */
        tries = 2;
 
-       hotplug_en = REG_READ(PORT_HOTPLUG_EN);
+       orig = hotplug_en = REG_READ(PORT_HOTPLUG_EN);
        hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK);
        hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
 
@@ -195,8 +178,11 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector,
            CRT_HOTPLUG_MONITOR_NONE)
                ret = true;
 
-       /* Restore the saved ADPA */
-       REG_WRITE(ADPA, adpa_orig);
+        /* clear the interrupt we just generated, if any */
+       REG_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
+
+       /* and put the bits back */
+       REG_WRITE(PORT_HOTPLUG_EN, orig);
        return ret;
 }
 
index be8455919b3306b41c66020d00fe6fa82b21863f..c3e9a0f701df4fe56d1b427419db3492c839ada0 100644 (file)
@@ -216,22 +216,22 @@ static void cdv_sb_reset(struct drm_device *dev)
  */
 static int
 cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
-                              struct cdv_intel_clock_t *clock)
+                              struct cdv_intel_clock_t *clock, bool is_lvds)
 {
-       struct psb_intel_crtc *psb_crtc =
-                               to_psb_intel_crtc(crtc);
+       struct psb_intel_crtc *psb_crtc = to_psb_intel_crtc(crtc);
        int pipe = psb_crtc->pipe;
        u32 m, n_vco, p;
        int ret = 0;
        int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+       int ref_sfr = (pipe == 0) ? SB_REF_DPLLA : SB_REF_DPLLB;
        u32 ref_value;
+       u32 lane_reg, lane_value;
 
        cdv_sb_reset(dev);
 
-       if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) {
-               DRM_ERROR("Attempting to set DPLL with refclk disabled\n");
-               return -EBUSY;
-       }
+       REG_WRITE(dpll_reg, DPLL_SYNCLOCK_ENABLE | DPLL_VGA_MODE_DIS);
+
+       udelay(100);
 
        /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */
        ref_value = 0x68A701;
@@ -241,6 +241,35 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
        /* We don't know what the other fields of these regs are, so
         * leave them in place.
         */
+       /* 
+        * The BIT 14:13 of 0x8010/0x8030 is used to select the ref clk
+        * for the pipe A/B. Display spec 1.06 has wrong definition.
+        * Correct definition is like below:
+        *
+        * refclka mean use clock from same PLL
+        *
+        * if DPLLA sets 01 and DPLLB sets 01, they use clock from their pll
+        *
+        * if DPLLA sets 01 and DPLLB sets 02, both use clk from DPLLA
+        *
+        */  
+       ret = cdv_sb_read(dev, ref_sfr, &ref_value);
+       if (ret)
+               return ret;
+       ref_value &= ~(REF_CLK_MASK);
+
+       /* use DPLL_A for pipeB on CRT/HDMI */
+       if (pipe == 1 && !is_lvds) {
+               DRM_DEBUG_KMS("use DPLLA for pipe B\n");
+               ref_value |= REF_CLK_DPLLA;
+       } else {
+               DRM_DEBUG_KMS("use their DPLL for pipe A/B\n");
+               ref_value |= REF_CLK_DPLL;
+       }
+       ret = cdv_sb_write(dev, ref_sfr, ref_value);
+       if (ret)
+               return ret;
+
        ret = cdv_sb_read(dev, SB_M(pipe), &m);
        if (ret)
                return ret;
@@ -307,36 +336,29 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
        if (ret)
                return ret;
 
-       /* always Program the Lane Register for the Pipe A*/
-       if (pipe == 0) {
-               /* Program the Lane0/1 for HDMI B */
-               u32 lane_reg, lane_value;
-
-               lane_reg = PSB_LANE0;
-               cdv_sb_read(dev, lane_reg, &lane_value);
-               lane_value &= ~(LANE_PLL_MASK);
-               lane_value |= LANE_PLL_ENABLE;
-               cdv_sb_write(dev, lane_reg, lane_value);
-
-               lane_reg = PSB_LANE1;
-               cdv_sb_read(dev, lane_reg, &lane_value);
-               lane_value &= ~(LANE_PLL_MASK);
-               lane_value |= LANE_PLL_ENABLE;
-               cdv_sb_write(dev, lane_reg, lane_value);
-
-               /* Program the Lane2/3 for HDMI C */
-               lane_reg = PSB_LANE2;
-               cdv_sb_read(dev, lane_reg, &lane_value);
-               lane_value &= ~(LANE_PLL_MASK);
-               lane_value |= LANE_PLL_ENABLE;
-               cdv_sb_write(dev, lane_reg, lane_value);
-
-               lane_reg = PSB_LANE3;
-               cdv_sb_read(dev, lane_reg, &lane_value);
-               lane_value &= ~(LANE_PLL_MASK);
-               lane_value |= LANE_PLL_ENABLE;
-               cdv_sb_write(dev, lane_reg, lane_value);
-       }
+       lane_reg = PSB_LANE0;
+       cdv_sb_read(dev, lane_reg, &lane_value);
+       lane_value &= ~(LANE_PLL_MASK);
+       lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
+       cdv_sb_write(dev, lane_reg, lane_value);
+
+       lane_reg = PSB_LANE1;
+       cdv_sb_read(dev, lane_reg, &lane_value);
+       lane_value &= ~(LANE_PLL_MASK);
+       lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
+       cdv_sb_write(dev, lane_reg, lane_value);
+
+       lane_reg = PSB_LANE2;
+       cdv_sb_read(dev, lane_reg, &lane_value);
+       lane_value &= ~(LANE_PLL_MASK);
+       lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
+       cdv_sb_write(dev, lane_reg, lane_value);
+
+       lane_reg = PSB_LANE3;
+       cdv_sb_read(dev, lane_reg, &lane_value);
+       lane_value &= ~(LANE_PLL_MASK);
+       lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
+       cdv_sb_write(dev, lane_reg, lane_value);
 
        return 0;
 }
@@ -480,14 +502,12 @@ static int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
                            int x, int y, struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
        int pipe = psb_intel_crtc->pipe;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
-       int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
-       int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
-       int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
        u32 dspcntr;
        int ret = 0;
 
@@ -509,9 +529,9 @@ static int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
        start = psbfb->gtt->offset;
        offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
 
-       REG_WRITE(dspstride, crtc->fb->pitches[0]);
+       REG_WRITE(map->stride, crtc->fb->pitches[0]);
 
-       dspcntr = REG_READ(dspcntr_reg);
+       dspcntr = REG_READ(map->cntr);
        dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
        switch (crtc->fb->bits_per_pixel) {
@@ -533,15 +553,15 @@ static int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
                ret = -EINVAL;
                goto psb_intel_pipe_set_base_exit;
        }
-       REG_WRITE(dspcntr_reg, dspcntr);
+       REG_WRITE(map->cntr, dspcntr);
 
        dev_dbg(dev->dev,
                "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
 
-       REG_WRITE(dspbase, offset);
-       REG_READ(dspbase);
-       REG_WRITE(dspsurf, start);
-       REG_READ(dspsurf);
+       REG_WRITE(map->base, offset);
+       REG_READ(map->base);
+       REG_WRITE(map->surf, start);
+       REG_READ(map->surf);
 
 psb_intel_pipe_cleaner:
        /* If there was a previous display we can now unpin it */
@@ -553,6 +573,199 @@ psb_intel_pipe_set_base_exit:
        return ret;
 }
 
+#define                FIFO_PIPEA              (1 << 0)
+#define                FIFO_PIPEB              (1 << 1)
+
+static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
+{
+       struct drm_crtc *crtc;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_crtc *psb_intel_crtc = NULL;
+
+       crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+       psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+       if (crtc->fb == NULL || !psb_intel_crtc->active)
+               return false;
+       return true;
+}
+
+static bool cdv_intel_single_pipe_active (struct drm_device *dev)
+{
+       uint32_t pipe_enabled = 0;
+
+       if (cdv_intel_pipe_enabled(dev, 0))
+               pipe_enabled |= FIFO_PIPEA;
+
+       if (cdv_intel_pipe_enabled(dev, 1))
+               pipe_enabled |= FIFO_PIPEB;
+
+
+       DRM_DEBUG_KMS("pipe enabled %x\n", pipe_enabled);
+
+       if (pipe_enabled == FIFO_PIPEA || pipe_enabled == FIFO_PIPEB)
+               return true;
+       else
+               return false;
+}
+
+static bool is_pipeb_lvds(struct drm_device *dev, struct drm_crtc *crtc)
+{
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_connector *connector;
+
+       if (psb_intel_crtc->pipe != 1)
+               return false;
+
+       list_for_each_entry(connector, &mode_config->connector_list, head) {
+               struct psb_intel_encoder *psb_intel_encoder =
+                                       psb_intel_attached_encoder(connector);
+
+               if (!connector->encoder
+                   || connector->encoder->crtc != crtc)
+                       continue;
+
+               if (psb_intel_encoder->type == INTEL_OUTPUT_LVDS)
+                       return true;
+       }
+
+       return false;
+}
+
+static void cdv_intel_disable_self_refresh (struct drm_device *dev)
+{
+       if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) {
+
+               /* Disable self-refresh before adjust WM */
+               REG_WRITE(FW_BLC_SELF, (REG_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN));
+               REG_READ(FW_BLC_SELF);
+
+               cdv_intel_wait_for_vblank(dev);
+
+               /* Cedarview workaround to write ovelay plane, which force to leave
+                * MAX_FIFO state.
+                */
+               REG_WRITE(OV_OVADD, 0/*dev_priv->ovl_offset*/);
+               REG_READ(OV_OVADD);
+
+               cdv_intel_wait_for_vblank(dev);
+       }
+
+}
+
+static void cdv_intel_update_watermark (struct drm_device *dev, struct drm_crtc *crtc)
+{
+
+       if (cdv_intel_single_pipe_active(dev)) {
+               u32 fw;
+
+               fw = REG_READ(DSPFW1);
+               fw &= ~DSP_FIFO_SR_WM_MASK;
+               fw |= (0x7e << DSP_FIFO_SR_WM_SHIFT);
+               fw &= ~CURSOR_B_FIFO_WM_MASK;
+               fw |= (0x4 << CURSOR_B_FIFO_WM_SHIFT);
+               REG_WRITE(DSPFW1, fw);
+
+               fw = REG_READ(DSPFW2);
+               fw &= ~CURSOR_A_FIFO_WM_MASK;
+               fw |= (0x6 << CURSOR_A_FIFO_WM_SHIFT);
+               fw &= ~DSP_PLANE_C_FIFO_WM_MASK;
+               fw |= (0x8 << DSP_PLANE_C_FIFO_WM_SHIFT);
+               REG_WRITE(DSPFW2, fw);
+
+               REG_WRITE(DSPFW3, 0x36000000);
+
+               /* ignore FW4 */
+
+               if (is_pipeb_lvds(dev, crtc)) {
+                       REG_WRITE(DSPFW5, 0x00040330);
+               } else {
+                       fw = (3 << DSP_PLANE_B_FIFO_WM1_SHIFT) |
+                            (4 << DSP_PLANE_A_FIFO_WM1_SHIFT) |
+                            (3 << CURSOR_B_FIFO_WM1_SHIFT) |
+                            (4 << CURSOR_FIFO_SR_WM1_SHIFT);
+                       REG_WRITE(DSPFW5, fw);
+               }
+
+               REG_WRITE(DSPFW6, 0x10);
+
+               cdv_intel_wait_for_vblank(dev);
+
+               /* enable self-refresh for single pipe active */
+               REG_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+               REG_READ(FW_BLC_SELF);
+               cdv_intel_wait_for_vblank(dev);
+
+       } else {
+
+               /* HW team suggested values... */
+               REG_WRITE(DSPFW1, 0x3f880808);
+               REG_WRITE(DSPFW2, 0x0b020202);
+               REG_WRITE(DSPFW3, 0x24000000);
+               REG_WRITE(DSPFW4, 0x08030202);
+               REG_WRITE(DSPFW5, 0x01010101);
+               REG_WRITE(DSPFW6, 0x1d0);
+
+               cdv_intel_wait_for_vblank(dev);
+
+               cdv_intel_disable_self_refresh(dev);
+       
+       }
+}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+static void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       int palreg = PALETTE_A;
+       int i;
+
+       /* The clocks have to be on to load the palette. */
+       if (!crtc->enabled)
+               return;
+
+       switch (psb_intel_crtc->pipe) {
+       case 0:
+               break;
+       case 1:
+               palreg = PALETTE_B;
+               break;
+       case 2:
+               palreg = PALETTE_C;
+               break;
+       default:
+               dev_err(dev->dev, "Illegal Pipe Number.\n");
+               return;
+       }
+
+       if (gma_power_begin(dev, false)) {
+               for (i = 0; i < 256; i++) {
+                       REG_WRITE(palreg + 4 * i,
+                                 ((psb_intel_crtc->lut_r[i] +
+                                 psb_intel_crtc->lut_adj[i]) << 16) |
+                                 ((psb_intel_crtc->lut_g[i] +
+                                 psb_intel_crtc->lut_adj[i]) << 8) |
+                                 (psb_intel_crtc->lut_b[i] +
+                                 psb_intel_crtc->lut_adj[i]));
+               }
+               gma_power_end(dev);
+       } else {
+               for (i = 0; i < 256; i++) {
+                       dev_priv->regs.pipe[0].palette[i] =
+                                 ((psb_intel_crtc->lut_r[i] +
+                                 psb_intel_crtc->lut_adj[i]) << 16) |
+                                 ((psb_intel_crtc->lut_g[i] +
+                                 psb_intel_crtc->lut_adj[i]) << 8) |
+                                 (psb_intel_crtc->lut_b[i] +
+                                 psb_intel_crtc->lut_adj[i]);
+               }
+
+       }
+}
+
 /**
  * Sets the power management mode of the pipe and plane.
  *
@@ -562,62 +775,80 @@ psb_intel_pipe_set_base_exit:
 static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        u32 temp;
 
        /* XXX: When our outputs are all unaware of DPMS modes other than off
         * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
         */
+       cdv_intel_disable_self_refresh(dev);
+
        switch (mode) {
        case DRM_MODE_DPMS_ON:
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
+               if (psb_intel_crtc->active)
+                       return;
+
+               psb_intel_crtc->active = true;
+
                /* Enable the DPLL */
-               temp = REG_READ(dpll_reg);
+               temp = REG_READ(map->dpll);
                if ((temp & DPLL_VCO_ENABLE) == 0) {
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
                }
 
                /* Jim Bish - switch plan and pipe per scott */
                /* Enable the plane */
-               temp = REG_READ(dspcntr_reg);
+               temp = REG_READ(map->cntr);
                if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(dspcntr_reg,
+                       REG_WRITE(map->cntr,
                                  temp | DISPLAY_PLANE_ENABLE);
                        /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                       REG_WRITE(map->base, REG_READ(map->base));
                }
 
                udelay(150);
 
                /* Enable the pipe */
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_ENABLE) == 0)
-                       REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
+                       REG_WRITE(map->conf, temp | PIPEACONF_ENABLE);
+
+               temp = REG_READ(map->status);
+               temp &= ~(0xFFFF);
+               temp |= PIPE_FIFO_UNDERRUN;
+               REG_WRITE(map->status, temp);
+               REG_READ(map->status);
 
-               psb_intel_crtc_load_lut(crtc);
+               cdv_intel_update_watermark(dev, crtc);
+               cdv_intel_crtc_load_lut(crtc);
 
                /* Give the overlay scaler a chance to enable
                 * if it's on this pipe */
                /* psb_intel_crtc_dpms_video(crtc, true); TODO */
+               psb_intel_crtc->crtc_enable = true;
                break;
        case DRM_MODE_DPMS_OFF:
+               if (!psb_intel_crtc->active)
+                       return;
+
+               psb_intel_crtc->active = false;
+
                /* Give the overlay scaler a chance to disable
                 * if it's on this pipe */
                /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
@@ -627,14 +858,15 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 
                /* Jim Bish - changed pipe/plane here as well. */
 
+               drm_vblank_off(dev, pipe);
                /* Wait for vblank for the disable to take effect */
                cdv_intel_wait_for_vblank(dev);
 
                /* Next, disable display pipes */
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_ENABLE) != 0) {
-                       REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-                       REG_READ(pipeconf_reg);
+                       REG_WRITE(map->conf, temp & ~PIPEACONF_ENABLE);
+                       REG_READ(map->conf);
                }
 
                /* Wait for vblank for the disable to take effect. */
@@ -643,23 +875,25 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
                udelay(150);
 
                /* Disable display plane */
-               temp = REG_READ(dspcntr_reg);
+               temp = REG_READ(map->cntr);
                if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(dspcntr_reg,
+                       REG_WRITE(map->cntr,
                                  temp & ~DISPLAY_PLANE_ENABLE);
                        /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                       REG_READ(dspbase_reg);
+                       REG_WRITE(map->base, REG_READ(map->base));
+                       REG_READ(map->base);
                }
 
-               temp = REG_READ(dpll_reg);
+               temp = REG_READ(map->dpll);
                if ((temp & DPLL_VCO_ENABLE) != 0) {
-                       REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp & ~DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                }
 
                /* Wait for the clocks to turn off. */
                udelay(150);
+               cdv_intel_update_watermark(dev, crtc);
+               psb_intel_crtc->crtc_enable = false;
                break;
        }
        /*Set FIFO Watermarks*/
@@ -709,21 +943,10 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
                               struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
-       int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
-       int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
-       int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
-       int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
-       int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
-       int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
-       int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
-       int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        int refclk;
        struct cdv_intel_clock_t clock;
        u32 dpll = 0, dspcntr, pipeconf;
@@ -757,13 +980,18 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
-       refclk = 96000;
-
-       /* Hack selection about ref clk for CRT */
-       /* Select 27MHz as the reference clk for HDMI */
-       if (is_crt || is_hdmi)
+       if (dev_priv->dplla_96mhz)
+               /* low-end sku, 96/100 mhz */
+               refclk = 96000;
+       else
+               /* high-end sku, 27/100 mhz */
                refclk = 27000;
 
+       if (is_lvds && dev_priv->lvds_use_ssc) {
+               refclk = dev_priv->lvds_ssc_freq * 1000;
+               DRM_DEBUG_KMS("Use SSC reference clock %d Mhz\n", dev_priv->lvds_ssc_freq);
+       }
+
        drm_mode_debug_printmodeline(adjusted_mode);
 
        ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
@@ -779,18 +1007,17 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 /*     dpll |= PLL_REF_INPUT_TVCLKINBC; */
                dpll |= 3;
        }
-               dpll |= PLL_REF_INPUT_DREFCLK;
+/*             dpll |= PLL_REF_INPUT_DREFCLK; */
 
        dpll |= DPLL_SYNCLOCK_ENABLE;
-       dpll |= DPLL_VGA_MODE_DIS;
-       if (is_lvds)
+/*     if (is_lvds)
                dpll |= DPLLB_MODE_LVDS;
        else
-               dpll |= DPLLB_MODE_DAC_SERIAL;
+               dpll |= DPLLB_MODE_DAC_SERIAL; */
        /* dpll |= (2 << 11); */
 
        /* setup pipeconf */
-       pipeconf = REG_READ(pipeconf_reg);
+       pipeconf = REG_READ(map->conf);
 
        /* Set up the display plane register */
        dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -803,10 +1030,10 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
        dspcntr |= DISPLAY_PLANE_ENABLE;
        pipeconf |= PIPEACONF_ENABLE;
 
-       REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
-       REG_READ(dpll_reg);
+       REG_WRITE(map->dpll, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
+       REG_READ(map->dpll);
 
-       cdv_dpll_set_clock_cdv(dev, crtc, &clock);
+       cdv_dpll_set_clock_cdv(dev, crtc, &clock, is_lvds);
 
        udelay(150);
 
@@ -848,48 +1075,48 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
        DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
        drm_mode_debug_printmodeline(mode);
 
-       REG_WRITE(dpll_reg,
-               (REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE);
-       REG_READ(dpll_reg);
+       REG_WRITE(map->dpll,
+               (REG_READ(map->dpll) & ~DPLL_LOCK) | DPLL_VCO_ENABLE);
+       REG_READ(map->dpll);
        /* Wait for the clocks to stabilize. */
        udelay(150); /* 42 usec w/o calibration, 110 with.  rounded up. */
 
-       if (!(REG_READ(dpll_reg) & DPLL_LOCK)) {
+       if (!(REG_READ(map->dpll) & DPLL_LOCK)) {
                dev_err(dev->dev, "Failed to get DPLL lock\n");
                return -EBUSY;
        }
 
        {
                int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
-               REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+               REG_WRITE(map->dpll_md, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
        }
 
-       REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+       REG_WRITE(map->htotal, (adjusted_mode->crtc_hdisplay - 1) |
                  ((adjusted_mode->crtc_htotal - 1) << 16));
-       REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+       REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start - 1) |
                  ((adjusted_mode->crtc_hblank_end - 1) << 16));
-       REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+       REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start - 1) |
                  ((adjusted_mode->crtc_hsync_end - 1) << 16));
-       REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+       REG_WRITE(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) |
                  ((adjusted_mode->crtc_vtotal - 1) << 16));
-       REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+       REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start - 1) |
                  ((adjusted_mode->crtc_vblank_end - 1) << 16));
-       REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+       REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start - 1) |
                  ((adjusted_mode->crtc_vsync_end - 1) << 16));
        /* pipesrc and dspsize control the size that is scaled from,
         * which should always be the user's requested size.
         */
-       REG_WRITE(dspsize_reg,
+       REG_WRITE(map->size,
                  ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
-       REG_WRITE(dsppos_reg, 0);
-       REG_WRITE(pipesrc_reg,
+       REG_WRITE(map->pos, 0);
+       REG_WRITE(map->src,
                  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
-       REG_WRITE(pipeconf_reg, pipeconf);
-       REG_READ(pipeconf_reg);
+       REG_WRITE(map->conf, pipeconf);
+       REG_READ(map->conf);
 
        cdv_intel_wait_for_vblank(dev);
 
-       REG_WRITE(dspcntr_reg, dspcntr);
+       REG_WRITE(map->cntr, dspcntr);
 
        /* Flush the plane changes */
        {
@@ -903,58 +1130,6 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
        return 0;
 }
 
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-static void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_psb_private *dev_priv =
-                               (struct drm_psb_private *)dev->dev_private;
-       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int palreg = PALETTE_A;
-       int i;
-
-       /* The clocks have to be on to load the palette. */
-       if (!crtc->enabled)
-               return;
-
-       switch (psb_intel_crtc->pipe) {
-       case 0:
-               break;
-       case 1:
-               palreg = PALETTE_B;
-               break;
-       case 2:
-               palreg = PALETTE_C;
-               break;
-       default:
-               dev_err(dev->dev, "Illegal Pipe Number.\n");
-               return;
-       }
-
-       if (gma_power_begin(dev, false)) {
-               for (i = 0; i < 256; i++) {
-                       REG_WRITE(palreg + 4 * i,
-                                 ((psb_intel_crtc->lut_r[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 16) |
-                                 ((psb_intel_crtc->lut_g[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 8) |
-                                 (psb_intel_crtc->lut_b[i] +
-                                 psb_intel_crtc->lut_adj[i]));
-               }
-               gma_power_end(dev);
-       } else {
-               for (i = 0; i < 256; i++) {
-                       dev_priv->regs.psb.save_palette_a[i] =
-                                 ((psb_intel_crtc->lut_r[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 16) |
-                                 ((psb_intel_crtc->lut_g[i] +
-                                 psb_intel_crtc->lut_adj[i]) << 8) |
-                                 (psb_intel_crtc->lut_b[i] +
-                                 psb_intel_crtc->lut_adj[i]);
-               }
-
-       }
-}
 
 /**
  * Save HW states of giving crtc
@@ -962,11 +1137,10 @@ static void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
 static void cdv_intel_crtc_save(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
-       /* struct drm_psb_private *dev_priv =
-                       (struct drm_psb_private *)dev->dev_private; */
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
-       int pipeA = (psb_intel_crtc->pipe == 0);
+       const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
        uint32_t paletteReg;
        int i;
 
@@ -975,25 +1149,25 @@ static void cdv_intel_crtc_save(struct drm_crtc *crtc)
                return;
        }
 
-       crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
-       crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
-       crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
-       crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
-       crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
-       crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
-       crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
-       crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
-       crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
-       crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
-       crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
-       crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
-       crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
+       crtc_state->saveDSPCNTR = REG_READ(map->cntr);
+       crtc_state->savePIPECONF = REG_READ(map->conf);
+       crtc_state->savePIPESRC = REG_READ(map->src);
+       crtc_state->saveFP0 = REG_READ(map->fp0);
+       crtc_state->saveFP1 = REG_READ(map->fp1);
+       crtc_state->saveDPLL = REG_READ(map->dpll);
+       crtc_state->saveHTOTAL = REG_READ(map->htotal);
+       crtc_state->saveHBLANK = REG_READ(map->hblank);
+       crtc_state->saveHSYNC = REG_READ(map->hsync);
+       crtc_state->saveVTOTAL = REG_READ(map->vtotal);
+       crtc_state->saveVBLANK = REG_READ(map->vblank);
+       crtc_state->saveVSYNC = REG_READ(map->vsync);
+       crtc_state->saveDSPSTRIDE = REG_READ(map->stride);
 
        /*NOTE: DSPSIZE DSPPOS only for psb*/
-       crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
-       crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
+       crtc_state->saveDSPSIZE = REG_READ(map->size);
+       crtc_state->saveDSPPOS = REG_READ(map->pos);
 
-       crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
+       crtc_state->saveDSPBASE = REG_READ(map->base);
 
        DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
                        crtc_state->saveDSPCNTR,
@@ -1014,7 +1188,7 @@ static void cdv_intel_crtc_save(struct drm_crtc *crtc)
                        crtc_state->saveDSPBASE
                );
 
-       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+       paletteReg = map->palette;
        for (i = 0; i < 256; ++i)
                crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
 }
@@ -1025,12 +1199,10 @@ static void cdv_intel_crtc_save(struct drm_crtc *crtc)
 static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
-       /* struct drm_psb_private * dev_priv =
-                               (struct drm_psb_private *)dev->dev_private; */
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
        struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
-       /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
-       int pipeA = (psb_intel_crtc->pipe == 0);
+       const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
        uint32_t paletteReg;
        int i;
 
@@ -1041,23 +1213,23 @@ static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
 
        DRM_DEBUG(
                "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-               REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
-               REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
-               REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
-               REG_READ(pipeA ? FPA0 : FPB0),
-               REG_READ(pipeA ? FPA1 : FPB1),
-               REG_READ(pipeA ? DPLL_A : DPLL_B),
-               REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
-               REG_READ(pipeA ? HBLANK_A : HBLANK_B),
-               REG_READ(pipeA ? HSYNC_A : HSYNC_B),
-               REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
-               REG_READ(pipeA ? VBLANK_A : VBLANK_B),
-               REG_READ(pipeA ? VSYNC_A : VSYNC_B),
-               REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
-               REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
-               REG_READ(pipeA ? DSPAPOS : DSPBPOS),
-               REG_READ(pipeA ? DSPABASE : DSPBBASE)
-               );
+               REG_READ(map->cntr),
+               REG_READ(map->conf),
+               REG_READ(map->src),
+               REG_READ(map->fp0),
+               REG_READ(map->fp1),
+               REG_READ(map->dpll),
+               REG_READ(map->htotal),
+               REG_READ(map->hblank),
+               REG_READ(map->hsync),
+               REG_READ(map->vtotal),
+               REG_READ(map->vblank),
+               REG_READ(map->vsync),
+               REG_READ(map->stride),
+               REG_READ(map->size),
+               REG_READ(map->pos),
+               REG_READ(map->base)
+       );
 
        DRM_DEBUG(
                "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
@@ -1077,51 +1249,51 @@ static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
                crtc_state->saveDSPSIZE,
                crtc_state->saveDSPPOS,
                crtc_state->saveDSPBASE
-               );
+       );
 
 
        if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
-               REG_WRITE(pipeA ? DPLL_A : DPLL_B,
-                       crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
-               REG_READ(pipeA ? DPLL_A : DPLL_B);
+               REG_WRITE(map->dpll,
+                               crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
+               REG_READ(map->dpll);
                DRM_DEBUG("write dpll: %x\n",
-                               REG_READ(pipeA ? DPLL_A : DPLL_B));
+                               REG_READ(map->dpll));
                udelay(150);
        }
 
-       REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
-       REG_READ(pipeA ? FPA0 : FPB0);
+       REG_WRITE(map->fp0, crtc_state->saveFP0);
+       REG_READ(map->fp0);
 
-       REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
-       REG_READ(pipeA ? FPA1 : FPB1);
+       REG_WRITE(map->fp1, crtc_state->saveFP1);
+       REG_READ(map->fp1);
 
-       REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
-       REG_READ(pipeA ? DPLL_A : DPLL_B);
+       REG_WRITE(map->dpll, crtc_state->saveDPLL);
+       REG_READ(map->dpll);
        udelay(150);
 
-       REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
-       REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
-       REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
-       REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
-       REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
-       REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
-       REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
+       REG_WRITE(map->htotal, crtc_state->saveHTOTAL);
+       REG_WRITE(map->hblank, crtc_state->saveHBLANK);
+       REG_WRITE(map->hsync, crtc_state->saveHSYNC);
+       REG_WRITE(map->vtotal, crtc_state->saveVTOTAL);
+       REG_WRITE(map->vblank, crtc_state->saveVBLANK);
+       REG_WRITE(map->vsync, crtc_state->saveVSYNC);
+       REG_WRITE(map->stride, crtc_state->saveDSPSTRIDE);
 
-       REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
-       REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
+       REG_WRITE(map->size, crtc_state->saveDSPSIZE);
+       REG_WRITE(map->pos, crtc_state->saveDSPPOS);
 
-       REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
-       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
-       REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
+       REG_WRITE(map->src, crtc_state->savePIPESRC);
+       REG_WRITE(map->base, crtc_state->saveDSPBASE);
+       REG_WRITE(map->conf, crtc_state->savePIPECONF);
 
        cdv_intel_wait_for_vblank(dev);
 
-       REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
-       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+       REG_WRITE(map->cntr, crtc_state->saveDSPCNTR);
+       REG_WRITE(map->base, crtc_state->saveDSPBASE);
 
        cdv_intel_wait_for_vblank(dev);
 
-       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+       paletteReg = map->palette;
        for (i = 0; i < 256; ++i)
                REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
 }
@@ -1296,35 +1468,30 @@ static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
 static int cdv_intel_crtc_clock_get(struct drm_device *dev,
                                struct drm_crtc *crtc)
 {
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        int pipe = psb_intel_crtc->pipe;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        u32 dpll;
        u32 fp;
        struct cdv_intel_clock_t clock;
        bool is_lvds;
-       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
 
        if (gma_power_begin(dev, false)) {
-               dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
+               dpll = REG_READ(map->dpll);
                if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-                       fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
+                       fp = REG_READ(map->fp0);
                else
-                       fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
+                       fp = REG_READ(map->fp1);
                is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
                gma_power_end(dev);
        } else {
-               dpll = (pipe == 0) ?
-                       dev_priv->regs.psb.saveDPLL_A :
-                       dev_priv->regs.psb.saveDPLL_B;
-
+               dpll = p->dpll;
                if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-                       fp = (pipe == 0) ?
-                               dev_priv->regs.psb.saveFPA0 :
-                               dev_priv->regs.psb.saveFPB0;
+                       fp = p->fp0;
                else
-                       fp = (pipe == 0) ?
-                               dev_priv->regs.psb.saveFPA1 :
-                               dev_priv->regs.psb.saveFPB1;
+                       fp = p->fp1;
 
                is_lvds = (pipe == 1) &&
                                (dev_priv->regs.psb.saveLVDS & LVDS_PORT_EN);
@@ -1382,32 +1549,26 @@ struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
 {
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        int pipe = psb_intel_crtc->pipe;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        struct drm_display_mode *mode;
        int htot;
        int hsync;
        int vtot;
        int vsync;
-       struct drm_psb_private *dev_priv = dev->dev_private;
 
        if (gma_power_begin(dev, false)) {
-               htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
-               hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
-               vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
-               vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+               htot = REG_READ(map->htotal);
+               hsync = REG_READ(map->hsync);
+               vtot = REG_READ(map->vtotal);
+               vsync = REG_READ(map->vsync);
                gma_power_end(dev);
        } else {
-               htot = (pipe == 0) ?
-                       dev_priv->regs.psb.saveHTOTAL_A :
-                       dev_priv->regs.psb.saveHTOTAL_B;
-               hsync = (pipe == 0) ?
-                       dev_priv->regs.psb.saveHSYNC_A :
-                       dev_priv->regs.psb.saveHSYNC_B;
-               vtot = (pipe == 0) ?
-                       dev_priv->regs.psb.saveVTOTAL_A :
-                       dev_priv->regs.psb.saveVTOTAL_B;
-               vsync = (pipe == 0) ?
-                       dev_priv->regs.psb.saveVSYNC_A :
-                       dev_priv->regs.psb.saveVSYNC_B;
+               htot = p->htotal;
+               hsync = p->hsync;
+               vtot = p->vtotal;
+               vsync = p->vsync;
        }
 
        mode = kzalloc(sizeof(*mode), GFP_KERNEL);
index 8d526955500538faf0f76e59f941b6e79fd32a44..88b59d4a7b7fceb11bda72d60b52ad662525e11b 100644 (file)
@@ -242,8 +242,6 @@ static int cdv_hdmi_get_modes(struct drm_connector *connector)
 static int cdv_hdmi_mode_valid(struct drm_connector *connector,
                                 struct drm_display_mode *mode)
 {
-       struct drm_psb_private *dev_priv = connector->dev->dev_private;
-
        if (mode->clock > 165000)
                return MODE_CLOCK_HIGH;
        if (mode->clock < 20000)
@@ -257,11 +255,6 @@ static int cdv_hdmi_mode_valid(struct drm_connector *connector,
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                return MODE_NO_INTERLACE;
 
-       /* We assume worst case scenario of 32 bpp here, since we don't know */
-       if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
-           dev_priv->vram_stolen_size)
-               return MODE_MEM;
-
        return MODE_OK;
 }
 
index 8359c1a3f45f79b4edecbb8bb2b2e14b63bfb3b9..ff5b58eb878c9f60c6a6c11229429386fdbbd462 100644 (file)
@@ -356,6 +356,8 @@ static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
 {
        struct drm_device *dev = encoder->dev;
        struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(
+                                                       encoder->crtc);
        u32 pfit_control;
 
        /*
@@ -377,6 +379,8 @@ static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
        else
                pfit_control = 0;
 
+       pfit_control |= psb_intel_crtc->pipe << PFIT_PIPE_SHIFT;
+
        if (dev_priv->lvds_dither)
                pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 
@@ -552,10 +556,60 @@ static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
        drm_encoder_cleanup(encoder);
 }
 
-const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
+static const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
        .destroy = cdv_intel_lvds_enc_destroy,
 };
 
+/*
+ * Enumerate the child dev array parsed from VBT to check whether
+ * the LVDS is present.
+ * If it is present, return 1.
+ * If it is not present, return false.
+ * If no child dev is parsed from VBT, it assumes that the LVDS is present.
+ */
+static bool lvds_is_present_in_vbt(struct drm_device *dev,
+                                  u8 *i2c_pin)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int i;
+
+       if (!dev_priv->child_dev_num)
+               return true;
+
+       for (i = 0; i < dev_priv->child_dev_num; i++) {
+               struct child_device_config *child = dev_priv->child_dev + i;
+
+               /* If the device type is not LFP, continue.
+                * We have to check both the new identifiers as well as the
+                * old for compatibility with some BIOSes.
+                */
+               if (child->device_type != DEVICE_TYPE_INT_LFP &&
+                   child->device_type != DEVICE_TYPE_LFP)
+                       continue;
+
+               if (child->i2c_pin)
+                   *i2c_pin = child->i2c_pin;
+
+               /* However, we cannot trust the BIOS writers to populate
+                * the VBT correctly.  Since LVDS requires additional
+                * information from AIM blocks, a non-zero addin offset is
+                * a good indicator that the LVDS is actually present.
+                */
+               if (child->addin_offset)
+                       return true;
+
+               /* But even then some BIOS writers perform some black magic
+                * and instantiate the device without reference to any
+                * additional data.  Trust that if the VBT was written into
+                * the OpRegion then they have validated the LVDS's existence.
+                */
+               if (dev_priv->opregion.vbt)
+                       return true;
+       }
+
+       return false;
+}
+
 /**
  * cdv_intel_lvds_init - setup LVDS connectors on this device
  * @dev: drm device
@@ -576,6 +630,13 @@ void cdv_intel_lvds_init(struct drm_device *dev,
        struct drm_psb_private *dev_priv = dev->dev_private;
        u32 lvds;
        int pipe;
+       u8 pin;
+
+       pin = GMBUS_PORT_PANEL;
+       if (!lvds_is_present_in_vbt(dev, &pin)) {
+               DRM_DEBUG_KMS("LVDS is not present in VBT\n");
+               return;
+       }
 
        psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder),
                                    GFP_KERNEL);
@@ -710,6 +771,19 @@ void cdv_intel_lvds_init(struct drm_device *dev,
                goto failed_find;
        }
 
+       /* setup PWM */
+       {
+               u32 pwm;
+
+               pwm = REG_READ(BLC_PWM_CTL2);
+               if (pipe == 1)
+                       pwm |= PWM_PIPE_B;
+               else
+                       pwm &= ~PWM_PIPE_B;
+               pwm |= PWM_ENABLE;
+               REG_WRITE(BLC_PWM_CTL2, pwm);
+       }
+
 out:
        drm_sysfs_connector_add(connector);
        return;
index 8ea202f1ba504ad159f807ffe23380657aad5a9f..659ed3933b5bc722ff330eb82849e53d81ee9ce6 100644 (file)
@@ -408,6 +408,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
                        return -ENOMEM;
        }
 
+       memset(dev_priv->vram_addr + backing->offset, 0, size);
+
        mutex_lock(&dev->struct_mutex);
 
        info = framebuffer_alloc(0, device);
@@ -453,8 +455,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
        info->fix.ypanstep = 0;
 
        /* Accessed stolen memory directly */
-       info->screen_base = (char *)dev_priv->vram_addr +
-                                                       backing->offset;
+       info->screen_base = dev_priv->vram_addr + backing->offset;
        info->screen_size = size;
 
        if (dev_priv->gtt.stolen_size) {
@@ -475,7 +476,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 
        /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
 
-       dev_info(dev->dev, "allocated %dx%d fb\n",
+       dev_dbg(dev->dev, "allocated %dx%d fb\n",
                                        psbfb->base.width, psbfb->base.height);
 
        mutex_unlock(&dev->struct_mutex);
@@ -543,9 +544,25 @@ static int psbfb_probe(struct drm_fb_helper *helper,
                                struct drm_fb_helper_surface_size *sizes)
 {
        struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
+       struct drm_device *dev = psb_fbdev->psb_fb_helper.dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        int new_fb = 0;
+       int bytespp;
        int ret;
 
+       bytespp = sizes->surface_bpp / 8;
+       if (bytespp == 3)       /* no 24bit packed */
+               bytespp = 4;
+
+       /* If the mode will not fit in 32bit then switch to 16bit to get
+          a console on full resolution. The X mode setting server will
+          allocate its own 32bit GEM framebuffer */
+       if (ALIGN(sizes->fb_width * bytespp, 64) * sizes->fb_height >
+                       dev_priv->vram_stolen_size) {
+                sizes->surface_bpp = 16;
+                sizes->surface_depth = 16;
+        }
+
        if (!helper->fb) {
                ret = psbfb_create(psb_fbdev, sizes);
                if (ret)
@@ -555,7 +572,7 @@ static int psbfb_probe(struct drm_fb_helper *helper,
        return new_fb;
 }
 
-struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+static struct drm_fb_helper_funcs psb_fb_helper_funcs = {
        .gamma_set = psbfb_gamma_set,
        .gamma_get = psbfb_gamma_get,
        .fb_probe = psbfb_probe,
@@ -732,10 +749,7 @@ static void psb_setup_outputs(struct drm_device *dev)
                        clone_mask = (1 << INTEL_OUTPUT_SDVO);
                        break;
                case INTEL_OUTPUT_LVDS:
-                       if (IS_MRST(dev))
-                               crtc_mask = (1 << 0);
-                       else
-                               crtc_mask = (1 << 1);
+                       crtc_mask = dev_priv->ops->lvds_mask;
                        clone_mask = (1 << INTEL_OUTPUT_LVDS);
                        break;
                case INTEL_OUTPUT_MIPI:
@@ -747,10 +761,7 @@ static void psb_setup_outputs(struct drm_device *dev)
                        clone_mask = (1 << INTEL_OUTPUT_MIPI2);
                        break;
                case INTEL_OUTPUT_HDMI:
-                       if (IS_MFLD(dev))
-                               crtc_mask = (1 << 1);
-                       else    
-                               crtc_mask = (1 << 0);
+                       crtc_mask = dev_priv->ops->hdmi_mask;
                        clone_mask = (1 << INTEL_OUTPUT_HDMI);
                        break;
                }
@@ -786,6 +797,9 @@ void psb_modeset_init(struct drm_device *dev)
        dev->mode_config.max_height = 2048;
 
        psb_setup_outputs(dev);
+
+       if (dev_priv->ops->errata)
+               dev_priv->ops->errata(dev);
 }
 
 void psb_modeset_cleanup(struct drm_device *dev)
index 9fbb86868e2ee9c9d5e218b57c04c445415f0e56..fc7d144bc2d3c1a2eeeb01d5749052c1cf708080 100644 (file)
@@ -124,6 +124,8 @@ static int psb_gem_create(struct drm_file *file,
                dev_err(dev->dev, "GEM init failed for %lld\n", size);
                return -ENOMEM;
        }
+       /* Limit the object to 32bit mappings */
+       mapping_set_gfp_mask(r->gem.filp->f_mapping, GFP_KERNEL | __GFP_DMA32);
        /* Give the object a handle so we can carry it more easily */
        ret = drm_gem_handle_create(file, &r->gem, &handle);
        if (ret) {
index c6465b40090f788c28153c686fd96656c67a7d2e..04a371aceb349359bd405ff787174cbb154ab3e1 100644 (file)
@@ -39,6 +39,10 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
 {
        uint32_t mask = PSB_PTE_VALID;
 
+       /* Ensure we explode rather than put an invalid low mapping of
+          a high mapping page into the gtt */
+       BUG_ON(pfn & ~(0xFFFFFFFF >> PAGE_SHIFT));
+
        if (type & PSB_MMU_CACHED_MEMORY)
                mask |= PSB_PTE_CACHED;
        if (type & PSB_MMU_RO_MEMORY)
@@ -57,7 +61,7 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
  *     Given a gtt_range object return the GTT offset of the page table
  *     entries for this gtt_range
  */
-static u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
+static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        unsigned long offset;
@@ -78,7 +82,8 @@ static u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
  */
 static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
 {
-       u32 *gtt_slot, pte;
+       u32 __iomem *gtt_slot;
+       u32 pte;
        struct page **pages;
        int i;
 
@@ -93,7 +98,7 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
        pages = r->pages;
 
        /* Make sure changes are visible to the GPU */
-       set_pages_array_uc(pages, r->npage);
+       set_pages_array_wc(pages, r->npage);
 
        /* Write our page entries into the GTT itself */
        for (i = r->roll; i < r->npage; i++) {
@@ -122,7 +127,8 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
 static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 *gtt_slot, pte;
+       u32 __iomem *gtt_slot;
+       u32 pte;
        int i;
 
        WARN_ON(r->stolen);
@@ -148,7 +154,8 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
  */
 void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
 {
-       u32 *gtt_slot, pte;
+       u32 __iomem *gtt_slot;
+       u32 pte;
        int i;
 
        if (roll >= r->npage) {
@@ -409,8 +416,6 @@ int psb_gtt_init(struct drm_device *dev, int resume)
        unsigned long stolen_size, vram_stolen_size;
        unsigned i, num_pages;
        unsigned pfn_base;
-       uint32_t vram_pages;
-       uint32_t dvmt_mode = 0;
        struct psb_gtt *pg;
 
        int ret = 0;
@@ -483,13 +488,8 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 
        stolen_size = vram_stolen_size;
 
-       printk(KERN_INFO "Stolen memory information\n");
-       printk(KERN_INFO "       base in RAM: 0x%x\n", dev_priv->stolen_base);
-       printk(KERN_INFO "       size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
-               vram_stolen_size/1024);
-       dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
-       printk(KERN_INFO "      the correct size should be: %dM(dvmt mode=%d)\n",
-               (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+       dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n",
+                       dev_priv->stolen_base, vram_stolen_size / 1024);
 
        if (resume && (gtt_pages != pg->gtt_pages) &&
            (stolen_size != pg->stolen_size)) {
@@ -525,8 +525,8 @@ int psb_gtt_init(struct drm_device *dev, int resume)
         */
 
        pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
-       vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
-       printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
+       num_pages = vram_stolen_size >> PAGE_SHIFT;
+       dev_dbg(dev->dev, "Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
                num_pages, pfn_base << PAGE_SHIFT, 0);
        for (i = 0; i < num_pages; ++i) {
                pte = psb_gtt_mask_pte(pfn_base + i, 0);
index d4d0c5b8bf919cd8182ec6d9b82505700efdc642..479e4497d26ce19257425898342298e660d27311 100644 (file)
@@ -26,6 +26,8 @@
 #include "psb_intel_reg.h"
 #include "intel_bios.h"
 
+#define        SLAVE_ADDR1     0x70
+#define        SLAVE_ADDR2     0x72
 
 static void *find_section(struct bdb_header *bdb, int section_id)
 {
@@ -52,6 +54,16 @@ static void *find_section(struct bdb_header *bdb, int section_id)
        return NULL;
 }
 
+static u16
+get_blocksize(void *p)
+{
+       u16 *block_ptr, block_size;
+
+       block_ptr = (u16 *)((char *)p - 2);
+       block_size = *block_ptr;
+       return block_size;
+}
+
 static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
                        struct lvds_dvo_timing *dvo_timing)
 {
@@ -75,6 +87,16 @@ static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
        panel_fixed_mode->clock = dvo_timing->clock * 10;
        panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
 
+       if (dvo_timing->hsync_positive)
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (dvo_timing->vsync_positive)
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
+
        /* Some VBTs have bogus h/vtotal values */
        if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
                panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
@@ -217,6 +239,180 @@ static void parse_general_features(struct drm_psb_private *dev_priv,
        }
 }
 
+static void
+parse_sdvo_device_mapping(struct drm_psb_private *dev_priv,
+                         struct bdb_header *bdb)
+{
+       struct sdvo_device_mapping *p_mapping;
+       struct bdb_general_definitions *p_defs;
+       struct child_device_config *p_child;
+       int i, child_device_num, count;
+       u16     block_size;
+
+       p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+       if (!p_defs) {
+               DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");
+               return;
+       }
+       /* judge whether the size of child device meets the requirements.
+        * If the child device size obtained from general definition block
+        * is different with sizeof(struct child_device_config), skip the
+        * parsing of sdvo device info
+        */
+       if (p_defs->child_dev_size != sizeof(*p_child)) {
+               /* different child dev size . Ignore it */
+               DRM_DEBUG_KMS("different child size is found. Invalid.\n");
+               return;
+       }
+       /* get the block size of general definitions */
+       block_size = get_blocksize(p_defs);
+       /* get the number of child device */
+       child_device_num = (block_size - sizeof(*p_defs)) /
+                               sizeof(*p_child);
+       count = 0;
+       for (i = 0; i < child_device_num; i++) {
+               p_child = &(p_defs->devices[i]);
+               if (!p_child->device_type) {
+                       /* skip the device block if device type is invalid */
+                       continue;
+               }
+               if (p_child->slave_addr != SLAVE_ADDR1 &&
+                       p_child->slave_addr != SLAVE_ADDR2) {
+                       /*
+                        * If the slave address is neither 0x70 nor 0x72,
+                        * it is not a SDVO device. Skip it.
+                        */
+                       continue;
+               }
+               if (p_child->dvo_port != DEVICE_PORT_DVOB &&
+                       p_child->dvo_port != DEVICE_PORT_DVOC) {
+                       /* skip the incorrect SDVO port */
+                       DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
+                       continue;
+               }
+               DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
+                               " %s port\n",
+                               p_child->slave_addr,
+                               (p_child->dvo_port == DEVICE_PORT_DVOB) ?
+                                       "SDVOB" : "SDVOC");
+               p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
+               if (!p_mapping->initialized) {
+                       p_mapping->dvo_port = p_child->dvo_port;
+                       p_mapping->slave_addr = p_child->slave_addr;
+                       p_mapping->dvo_wiring = p_child->dvo_wiring;
+                       p_mapping->ddc_pin = p_child->ddc_pin;
+                       p_mapping->i2c_pin = p_child->i2c_pin;
+                       p_mapping->initialized = 1;
+                       DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
+                                     p_mapping->dvo_port,
+                                     p_mapping->slave_addr,
+                                     p_mapping->dvo_wiring,
+                                     p_mapping->ddc_pin,
+                                     p_mapping->i2c_pin);
+               } else {
+                       DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
+                                        "two SDVO device.\n");
+               }
+               if (p_child->slave2_addr) {
+                       /* Maybe this is a SDVO device with multiple inputs */
+                       /* And the mapping info is not added */
+                       DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
+                               " is a SDVO device with multiple inputs.\n");
+               }
+               count++;
+       }
+
+       if (!count) {
+               /* No SDVO device info is found */
+               DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");
+       }
+       return;
+}
+
+
+static void
+parse_driver_features(struct drm_psb_private *dev_priv,
+                     struct bdb_header *bdb)
+{
+       struct bdb_driver_features *driver;
+
+       driver = find_section(bdb, BDB_DRIVER_FEATURES);
+       if (!driver)
+               return;
+
+       /* This bit means to use 96Mhz for DPLL_A or not */
+       if (driver->primary_lfp_id)
+               dev_priv->dplla_96mhz = true;
+       else
+               dev_priv->dplla_96mhz = false;
+}
+
+static void
+parse_device_mapping(struct drm_psb_private *dev_priv,
+                      struct bdb_header *bdb)
+{
+       struct bdb_general_definitions *p_defs;
+       struct child_device_config *p_child, *child_dev_ptr;
+       int i, child_device_num, count;
+       u16     block_size;
+
+       p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+       if (!p_defs) {
+               DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
+               return;
+       }
+       /* judge whether the size of child device meets the requirements.
+        * If the child device size obtained from general definition block
+        * is different with sizeof(struct child_device_config), skip the
+        * parsing of sdvo device info
+        */
+       if (p_defs->child_dev_size != sizeof(*p_child)) {
+               /* different child dev size . Ignore it */
+               DRM_DEBUG_KMS("different child size is found. Invalid.\n");
+               return;
+       }
+       /* get the block size of general definitions */
+       block_size = get_blocksize(p_defs);
+       /* get the number of child device */
+       child_device_num = (block_size - sizeof(*p_defs)) /
+                               sizeof(*p_child);
+       count = 0;
+       /* get the number of child devices that are present */
+       for (i = 0; i < child_device_num; i++) {
+               p_child = &(p_defs->devices[i]);
+               if (!p_child->device_type) {
+                       /* skip the device block if device type is invalid */
+                       continue;
+               }
+               count++;
+       }
+       if (!count) {
+               DRM_DEBUG_KMS("no child dev is parsed from VBT\n");
+               return;
+       }
+       dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL);
+       if (!dev_priv->child_dev) {
+               DRM_DEBUG_KMS("No memory space for child devices\n");
+               return;
+       }
+
+       dev_priv->child_dev_num = count;
+       count = 0;
+       for (i = 0; i < child_device_num; i++) {
+               p_child = &(p_defs->devices[i]);
+               if (!p_child->device_type) {
+                       /* skip the device block if device type is invalid */
+                       continue;
+               }
+               child_dev_ptr = dev_priv->child_dev + count;
+               count++;
+               memcpy((void *)child_dev_ptr, (void *)p_child,
+                                       sizeof(*p_child));
+       }
+       return;
+}
+
+
 /**
  * psb_intel_init_bios - initialize VBIOS settings & find VBT
  * @dev: DRM device
@@ -236,38 +432,54 @@ bool psb_intel_init_bios(struct drm_device *dev)
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct pci_dev *pdev = dev->pdev;
        struct vbt_header *vbt = NULL;
-       struct bdb_header *bdb;
-       u8 __iomem *bios;
+       struct bdb_header *bdb = NULL;
+       u8 __iomem *bios = NULL;
        size_t size;
        int i;
 
-       bios = pci_map_rom(pdev, &size);
-       if (!bios)
-               return -1;
+       /* XXX Should this validation be moved to intel_opregion.c? */
+       if (dev_priv->opregion.vbt) {
+               struct vbt_header *vbt = dev_priv->opregion.vbt;
+               if (memcmp(vbt->signature, "$VBT", 4) == 0) {
+                       DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
+                                        vbt->signature);
+                       bdb = (struct bdb_header *)((char *)vbt + vbt->bdb_offset);
+               } else
+                       dev_priv->opregion.vbt = NULL;
+       }
 
-       /* Scour memory looking for the VBT signature */
-       for (i = 0; i + 4 < size; i++) {
-               if (!memcmp(bios + i, "$VBT", 4)) {
-                       vbt = (struct vbt_header *)(bios + i);
-                       break;
+       if (bdb == NULL) {
+               bios = pci_map_rom(pdev, &size);
+               if (!bios)
+                       return -1;
+
+               /* Scour memory looking for the VBT signature */
+               for (i = 0; i + 4 < size; i++) {
+                       if (!memcmp(bios + i, "$VBT", 4)) {
+                               vbt = (struct vbt_header *)(bios + i);
+                               break;
+                       }
                }
-       }
 
-       if (!vbt) {
-               dev_err(dev->dev, "VBT signature missing\n");
-               pci_unmap_rom(pdev, bios);
-               return -1;
+               if (!vbt) {
+                       dev_err(dev->dev, "VBT signature missing\n");
+                       pci_unmap_rom(pdev, bios);
+                       return -1;
+               }
+               bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
        }
 
-       bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
-
-       /* Grab useful general definitions */
+       /* Grab useful general dxefinitions */
        parse_general_features(dev_priv, bdb);
+       parse_driver_features(dev_priv, bdb);
        parse_lfp_panel_data(dev_priv, bdb);
        parse_sdvo_panel_data(dev_priv, bdb);
+       parse_sdvo_device_mapping(dev_priv, bdb);
+       parse_device_mapping(dev_priv, bdb);
        parse_backlight_data(dev_priv, bdb);
 
-       pci_unmap_rom(pdev, bios);
+       if (bios)
+               pci_unmap_rom(pdev, bios);
 
        return 0;
 }
index 70f1bf018183d9399c73cdae7cbc8469e3a8880c..0a738663eb5adc4f82a7c32df6c586ed04b51d71 100644 (file)
@@ -127,9 +127,93 @@ struct bdb_general_features {
        /* bits 5 */
        u8 int_crt_support:1;
        u8 int_tv_support:1;
-       u8 rsvd11:6; /* finish byte */
+       u8 int_efp_support:1;
+       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));
 
+/* pre-915 */
+#define GPIO_PIN_DVI_LVDS      0x03 /* "DVI/LVDS DDC GPIO pins" */
+#define GPIO_PIN_ADD_I2C       0x05 /* "ADDCARD I2C GPIO pins" */
+#define GPIO_PIN_ADD_DDC       0x04 /* "ADDCARD DDC GPIO pins" */
+#define GPIO_PIN_ADD_DDC_I2C   0x06 /* "ADDCARD DDC/I2C GPIO pins" */
+
+/* Pre 915 */
+#define DEVICE_TYPE_NONE       0x00
+#define DEVICE_TYPE_CRT                0x01
+#define DEVICE_TYPE_TV         0x09
+#define DEVICE_TYPE_EFP                0x12
+#define DEVICE_TYPE_LFP                0x22
+/* On 915+ */
+#define DEVICE_TYPE_CRT_DPMS           0x6001
+#define DEVICE_TYPE_CRT_DPMS_HOTPLUG   0x4001
+#define DEVICE_TYPE_TV_COMPOSITE       0x0209
+#define DEVICE_TYPE_TV_MACROVISION     0x0289
+#define DEVICE_TYPE_TV_RF_COMPOSITE    0x020c
+#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE        0x0609
+#define DEVICE_TYPE_TV_SCART           0x0209
+#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
+#define DEVICE_TYPE_EFP_HOTPLUG_PWR    0x6012
+#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR        0x6052
+#define DEVICE_TYPE_EFP_DVI_I          0x6053
+#define DEVICE_TYPE_EFP_DVI_D_DUAL     0x6152
+#define DEVICE_TYPE_EFP_DVI_D_HDCP     0x60d2
+#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR        0x6062
+#define DEVICE_TYPE_OPENLDI_DUALPIX    0x6162
+#define DEVICE_TYPE_LFP_PANELLINK      0x5012
+#define DEVICE_TYPE_LFP_CMOS_PWR       0x5042
+#define DEVICE_TYPE_LFP_LVDS_PWR       0x5062
+#define DEVICE_TYPE_LFP_LVDS_DUAL      0x5162
+#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2
+
+#define DEVICE_CFG_NONE                0x00
+#define DEVICE_CFG_12BIT_DVOB  0x01
+#define DEVICE_CFG_12BIT_DVOC  0x02
+#define DEVICE_CFG_24BIT_DVOBC 0x09
+#define DEVICE_CFG_24BIT_DVOCB 0x0a
+#define DEVICE_CFG_DUAL_DVOB   0x11
+#define DEVICE_CFG_DUAL_DVOC   0x12
+#define DEVICE_CFG_DUAL_DVOBC  0x13
+#define DEVICE_CFG_DUAL_LINK_DVOBC     0x19
+#define DEVICE_CFG_DUAL_LINK_DVOCB     0x1a
+
+#define DEVICE_WIRE_NONE       0x00
+#define DEVICE_WIRE_DVOB       0x01
+#define DEVICE_WIRE_DVOC       0x02
+#define DEVICE_WIRE_DVOBC      0x03
+#define DEVICE_WIRE_DVOBB      0x05
+#define DEVICE_WIRE_DVOCC      0x06
+#define DEVICE_WIRE_DVOB_MASTER 0x0d
+#define DEVICE_WIRE_DVOC_MASTER 0x0e
+
+#define DEVICE_PORT_DVOA       0x00 /* none on 845+ */
+#define DEVICE_PORT_DVOB       0x01
+#define DEVICE_PORT_DVOC       0x02
+
+struct child_device_config {
+       u16 handle;
+       u16 device_type;
+       u8  device_id[10]; /* ascii string */
+       u16 addin_offset;
+       u8  dvo_port; /* See Device_PORT_* above */
+       u8  i2c_pin;
+       u8  slave_addr;
+       u8  ddc_pin;
+       u16 edid_ptr;
+       u8  dvo_cfg; /* See DEVICE_CFG_* above */
+       u8  dvo2_port;
+       u8  i2c2_pin;
+       u8  slave2_addr;
+       u8  ddc2_pin;
+       u8  capabilities;
+       u8  dvo_wiring;/* See DEVICE_WIRE_* above */
+       u8  dvo2_wiring;
+       u16 extended_type;
+       u8  dvo_function;
+} __attribute__((packed));
+
+
 struct bdb_general_definitions {
        /* DDC GPIO */
        u8 crt_ddc_gmbus_pin;
@@ -144,13 +228,18 @@ struct bdb_general_definitions {
        u8 boot_display[2];
        u8 child_dev_size;
 
-       /* device info */
-       u8 tv_or_lvds_info[33];
-       u8 dev1[33];
-       u8 dev2[33];
-       u8 dev3[33];
-       u8 dev4[33];
-       /* may be another device block here on some platforms */
+       /*
+        * Device info:
+        * If TV is present, it'll be at devices[0].
+        * LVDS will be next, either devices[0] or [1], if present.
+        * On some platforms the number of device is 6. But could be as few as
+        * 4 if both TV and LVDS are missing.
+        * And the device num is related with the size of general definition
+        * block. It is obtained by using the following formula:
+        * number = (block_size - sizeof(bdb_general_definitions))/
+        *           sizeof(child_device_config);
+        */
+       struct child_device_config devices[0];
 };
 
 struct bdb_lvds_options {
@@ -302,6 +391,45 @@ struct bdb_sdvo_lvds_options {
        u8 panel_misc_bits_4;
 } __attribute__((packed));
 
+struct bdb_driver_features {
+       u8 boot_dev_algorithm:1;
+       u8 block_display_switch:1;
+       u8 allow_display_switch:1;
+       u8 hotplug_dvo:1;
+       u8 dual_view_zoom:1;
+       u8 int15h_hook:1;
+       u8 sprite_in_clone:1;
+       u8 primary_lfp_id:1;
+
+       u16 boot_mode_x;
+       u16 boot_mode_y;
+       u8 boot_mode_bpp;
+       u8 boot_mode_refresh;
+
+       u16 enable_lfp_primary:1;
+       u16 selective_mode_pruning:1;
+       u16 dual_frequency:1;
+       u16 render_clock_freq:1; /* 0: high freq; 1: low freq */
+       u16 nt_clone_support:1;
+       u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
+       u16 sprite_display_assign:1; /* 0: secondary; 1: primary */
+       u16 cui_aspect_scaling:1;
+       u16 preserve_aspect_ratio:1;
+       u16 sdvo_device_power_down:1;
+       u16 crt_hotplug:1;
+       u16 lvds_config:2;
+       u16 tv_hotplug:1;
+       u16 hdmi_config:2;
+
+       u8 static_display:1;
+       u8 reserved2:7;
+       u16 legacy_crt_max_x;
+       u16 legacy_crt_max_y;
+       u8 legacy_crt_max_refresh;
+
+       u8 hdmi_termination;
+       u8 custom_vbt_version;
+} __attribute__((packed));
 
 extern bool psb_intel_init_bios(struct drm_device *dev);
 extern void psb_intel_destroy_bios(struct drm_device *dev);
@@ -427,4 +555,21 @@ extern void psb_intel_destroy_bios(struct drm_device *dev);
 #define   SWF14_APM_STANDBY    0x1
 #define   SWF14_APM_RESTORE    0x0
 
+/* Add the device class for LFP, TV, HDMI */
+#define         DEVICE_TYPE_INT_LFP    0x1022
+#define         DEVICE_TYPE_INT_TV     0x1009
+#define         DEVICE_TYPE_HDMI       0x60D2
+#define         DEVICE_TYPE_DP         0x68C6
+#define         DEVICE_TYPE_eDP        0x78C6
+
+/* define the DVO port for HDMI output type */
+#define                DVO_B           1
+#define                DVO_C           2
+#define                DVO_D           3
+
+/* define the PORT for DP output type */
+#define                PORT_IDPB       7
+#define                PORT_IDPC       8
+#define                PORT_IDPD       9
+
 #endif /* _I830_BIOS_H_ */
diff --git a/drivers/gpu/drm/gma500/intel_opregion.c b/drivers/gpu/drm/gma500/intel_opregion.c
deleted file mode 100644 (file)
index d946bc1..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * FIXME: resolve with the i915 version
- */
-
-#include "psb_drv.h"
-
-struct opregion_header {
-       u8 signature[16];
-       u32 size;
-       u32 opregion_ver;
-       u8 bios_ver[32];
-       u8 vbios_ver[16];
-       u8 driver_ver[16];
-       u32 mboxes;
-       u8 reserved[164];
-} __packed;
-
-struct opregion_apci {
-       /*FIXME: add it later*/
-} __packed;
-
-struct opregion_swsci {
-       /*FIXME: add it later*/
-} __packed;
-
-struct opregion_acpi {
-       /*FIXME: add it later*/
-} __packed;
-
-int gma_intel_opregion_init(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       u32 opregion_phy;
-       void *base;
-       u32 *lid_state;
-
-       dev_priv->lid_state = NULL;
-
-       pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
-       if (opregion_phy == 0)
-               return -ENOTSUPP;
-
-       base = ioremap(opregion_phy, 8*1024);
-       if (!base)
-               return -ENOMEM;
-
-       lid_state = base + 0x01ac;
-
-       dev_priv->lid_state = lid_state;
-       dev_priv->lid_last_state = readl(lid_state);
-       return 0;
-}
-
-int gma_intel_opregion_exit(struct drm_device *dev)
-{
-       struct drm_psb_private *dev_priv = dev->dev_private;
-       if (dev_priv->lid_state)
-               iounmap(dev_priv->lid_state);
-       return 0;
-}
index af656787db0f5fcdf4e3c5d5be441db47f64937a..2d8e741e06d7b8b6dcc78c717f442a98bd7ab410 100644 (file)
@@ -163,142 +163,30 @@ struct backlight_device *mdfld_get_backlight_device(void)
  *
  * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
  */
-static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
+static int mdfld_save_display_registers(struct drm_device *dev, int pipenum)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct medfield_state *regs = &dev_priv->regs.mdfld;
+       struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum];
+       const struct psb_offset *map = &dev_priv->regmap[pipenum];
        int i;
+       u32 *mipi_val;
 
        /* register */
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 fp_reg = MRST_FPA0;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 htot_reg = HTOTAL_A;
-       u32 hblank_reg = HBLANK_A;
-       u32 hsync_reg = HSYNC_A;
-       u32 vtot_reg = VTOTAL_A;
-       u32 vblank_reg = VBLANK_A;
-       u32 vsync_reg = VSYNC_A;
-       u32 pipesrc_reg = PIPEASRC;
-       u32 dspstride_reg = DSPASTRIDE;
-       u32 dsplinoff_reg = DSPALINOFF;
-       u32 dsptileoff_reg = DSPATILEOFF;
-       u32 dspsize_reg = DSPASIZE;
-       u32 dsppos_reg = DSPAPOS;
-       u32 dspsurf_reg = DSPASURF;
        u32 mipi_reg = MIPI;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 dspstatus_reg = PIPEASTAT;
-       u32 palette_reg = PALETTE_A;
-
-       /* pointer to values */
-       u32 *dpll_val = &regs->saveDPLL_A;
-       u32 *fp_val = &regs->saveFPA0;
-       u32 *pipeconf_val = &regs->savePIPEACONF;
-       u32 *htot_val = &regs->saveHTOTAL_A;
-       u32 *hblank_val = &regs->saveHBLANK_A;
-       u32 *hsync_val = &regs->saveHSYNC_A;
-       u32 *vtot_val = &regs->saveVTOTAL_A;
-       u32 *vblank_val = &regs->saveVBLANK_A;
-       u32 *vsync_val = &regs->saveVSYNC_A;
-       u32 *pipesrc_val = &regs->savePIPEASRC;
-       u32 *dspstride_val = &regs->saveDSPASTRIDE;
-       u32 *dsplinoff_val = &regs->saveDSPALINOFF;
-       u32 *dsptileoff_val = &regs->saveDSPATILEOFF;
-       u32 *dspsize_val = &regs->saveDSPASIZE;
-       u32 *dsppos_val = &regs->saveDSPAPOS;
-       u32 *dspsurf_val = &regs->saveDSPASURF;
-       u32 *mipi_val = &regs->saveMIPI;
-       u32 *dspcntr_val = &regs->saveDSPACNTR;
-       u32 *dspstatus_val = &regs->saveDSPASTATUS;
-       u32 *palette_val = regs->save_palette_a;
-
-       switch (pipe) {
+
+       switch (pipenum) {
        case 0:
+               mipi_val = &regs->saveMIPI;
                break;
        case 1:
-               /* regester */
-               dpll_reg = MDFLD_DPLL_B;
-               fp_reg = MDFLD_DPLL_DIV0;
-               pipeconf_reg = PIPEBCONF;
-               htot_reg = HTOTAL_B;
-               hblank_reg = HBLANK_B;
-               hsync_reg = HSYNC_B;
-               vtot_reg = VTOTAL_B;
-               vblank_reg = VBLANK_B;
-               vsync_reg = VSYNC_B;
-               pipesrc_reg = PIPEBSRC;
-               dspstride_reg = DSPBSTRIDE;
-               dsplinoff_reg = DSPBLINOFF;
-               dsptileoff_reg = DSPBTILEOFF;
-               dspsize_reg = DSPBSIZE;
-               dsppos_reg = DSPBPOS;
-               dspsurf_reg = DSPBSURF;
-               dspcntr_reg = DSPBCNTR;
-               dspstatus_reg = PIPEBSTAT;
-               palette_reg = PALETTE_B;
-
-               /* values */
-               dpll_val = &regs->saveDPLL_B;
-               fp_val = &regs->saveFPB0;
-               pipeconf_val = &regs->savePIPEBCONF;
-               htot_val = &regs->saveHTOTAL_B;
-               hblank_val = &regs->saveHBLANK_B;
-               hsync_val = &regs->saveHSYNC_B;
-               vtot_val = &regs->saveVTOTAL_B;
-               vblank_val = &regs->saveVBLANK_B;
-               vsync_val = &regs->saveVSYNC_B;
-               pipesrc_val = &regs->savePIPEBSRC;
-               dspstride_val = &regs->saveDSPBSTRIDE;
-               dsplinoff_val = &regs->saveDSPBLINOFF;
-               dsptileoff_val = &regs->saveDSPBTILEOFF;
-               dspsize_val = &regs->saveDSPBSIZE;
-               dsppos_val = &regs->saveDSPBPOS;
-               dspsurf_val = &regs->saveDSPBSURF;
-               dspcntr_val = &regs->saveDSPBCNTR;
-               dspstatus_val = &regs->saveDSPBSTATUS;
-               palette_val = regs->save_palette_b;
+               mipi_val = &regs->saveMIPI;
                break;
        case 2:
                /* register */
-               pipeconf_reg = PIPECCONF;
-               htot_reg = HTOTAL_C;
-               hblank_reg = HBLANK_C;
-               hsync_reg = HSYNC_C;
-               vtot_reg = VTOTAL_C;
-               vblank_reg = VBLANK_C;
-               vsync_reg = VSYNC_C;
-               pipesrc_reg = PIPECSRC;
-               dspstride_reg = DSPCSTRIDE;
-               dsplinoff_reg = DSPCLINOFF;
-               dsptileoff_reg = DSPCTILEOFF;
-               dspsize_reg = DSPCSIZE;
-               dsppos_reg = DSPCPOS;
-               dspsurf_reg = DSPCSURF;
                mipi_reg = MIPI_C;
-               dspcntr_reg = DSPCCNTR;
-               dspstatus_reg = PIPECSTAT;
-               palette_reg = PALETTE_C;
-
                /* pointer to values */
-               pipeconf_val = &regs->savePIPECCONF;
-               htot_val = &regs->saveHTOTAL_C;
-               hblank_val = &regs->saveHBLANK_C;
-               hsync_val = &regs->saveHSYNC_C;
-               vtot_val = &regs->saveVTOTAL_C;
-               vblank_val = &regs->saveVBLANK_C;
-               vsync_val = &regs->saveVSYNC_C;
-               pipesrc_val = &regs->savePIPECSRC;
-               dspstride_val = &regs->saveDSPCSTRIDE;
-               dsplinoff_val = &regs->saveDSPCLINOFF;
-               dsptileoff_val = &regs->saveDSPCTILEOFF;
-               dspsize_val = &regs->saveDSPCSIZE;
-               dsppos_val = &regs->saveDSPCPOS;
-               dspsurf_val = &regs->saveDSPCSURF;
                mipi_val = &regs->saveMIPI_C;
-               dspcntr_val = &regs->saveDSPCCNTR;
-               dspstatus_val = &regs->saveDSPCSTATUS;
-               palette_val = regs->save_palette_c;
                break;
        default:
                DRM_ERROR("%s, invalid pipe number.\n", __func__);
@@ -306,30 +194,30 @@ static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
        }
 
        /* Pipe & plane A info */
-       *dpll_val = PSB_RVDC32(dpll_reg);
-       *fp_val = PSB_RVDC32(fp_reg);
-       *pipeconf_val = PSB_RVDC32(pipeconf_reg);
-       *htot_val = PSB_RVDC32(htot_reg);
-       *hblank_val = PSB_RVDC32(hblank_reg);
-       *hsync_val = PSB_RVDC32(hsync_reg);
-       *vtot_val = PSB_RVDC32(vtot_reg);
-       *vblank_val = PSB_RVDC32(vblank_reg);
-       *vsync_val = PSB_RVDC32(vsync_reg);
-       *pipesrc_val = PSB_RVDC32(pipesrc_reg);
-       *dspstride_val = PSB_RVDC32(dspstride_reg);
-       *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
-       *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
-       *dspsize_val = PSB_RVDC32(dspsize_reg);
-       *dsppos_val = PSB_RVDC32(dsppos_reg);
-       *dspsurf_val = PSB_RVDC32(dspsurf_reg);
-       *dspcntr_val = PSB_RVDC32(dspcntr_reg);
-       *dspstatus_val = PSB_RVDC32(dspstatus_reg);
+       pipe->dpll = PSB_RVDC32(map->dpll);
+       pipe->fp0 = PSB_RVDC32(map->fp0);
+       pipe->conf = PSB_RVDC32(map->conf);
+       pipe->htotal = PSB_RVDC32(map->htotal);
+       pipe->hblank = PSB_RVDC32(map->hblank);
+       pipe->hsync = PSB_RVDC32(map->hsync);
+       pipe->vtotal = PSB_RVDC32(map->vtotal);
+       pipe->vblank = PSB_RVDC32(map->vblank);
+       pipe->vsync = PSB_RVDC32(map->vsync);
+       pipe->src = PSB_RVDC32(map->src);
+       pipe->stride = PSB_RVDC32(map->stride);
+       pipe->linoff = PSB_RVDC32(map->linoff);
+       pipe->tileoff = PSB_RVDC32(map->tileoff);
+       pipe->size = PSB_RVDC32(map->size);
+       pipe->pos = PSB_RVDC32(map->pos);
+       pipe->surf = PSB_RVDC32(map->surf);
+       pipe->cntr = PSB_RVDC32(map->cntr);
+       pipe->status = PSB_RVDC32(map->status);
 
        /*save palette (gamma) */
        for (i = 0; i < 256; i++)
-               palette_val[i] = PSB_RVDC32(palette_reg + (i << 2));
+               pipe->palette[i] = PSB_RVDC32(map->palette + (i << 2));
 
-       if (pipe == 1) {
+       if (pipenum == 1) {
                regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
                regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
 
@@ -349,7 +237,7 @@ static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
  *
  * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
  */
-static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
+static int mdfld_restore_display_registers(struct drm_device *dev, int pipenum)
 {
        /* To get  panel out of ULPS mode. */
        u32 temp = 0;
@@ -357,142 +245,30 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct mdfld_dsi_config *dsi_config = NULL;
        struct medfield_state *regs = &dev_priv->regs.mdfld;
-       u32 i = 0;
-       u32 dpll = 0;
+       struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum];
+       const struct psb_offset *map = &dev_priv->regmap[pipenum];
+       u32 i;
+       u32 dpll;
        u32 timeout = 0;
 
-       /* regester */
-       u32 dpll_reg = MRST_DPLL_A;
-       u32 fp_reg = MRST_FPA0;
-       u32 pipeconf_reg = PIPEACONF;
-       u32 htot_reg = HTOTAL_A;
-       u32 hblank_reg = HBLANK_A;
-       u32 hsync_reg = HSYNC_A;
-       u32 vtot_reg = VTOTAL_A;
-       u32 vblank_reg = VBLANK_A;
-       u32 vsync_reg = VSYNC_A;
-       u32 pipesrc_reg = PIPEASRC;
-       u32 dspstride_reg = DSPASTRIDE;
-       u32 dsplinoff_reg = DSPALINOFF;
-       u32 dsptileoff_reg = DSPATILEOFF;
-       u32 dspsize_reg = DSPASIZE;
-       u32 dsppos_reg = DSPAPOS;
-       u32 dspsurf_reg = DSPASURF;
-       u32 dspstatus_reg = PIPEASTAT;
+       /* register */
        u32 mipi_reg = MIPI;
-       u32 dspcntr_reg = DSPACNTR;
-       u32 palette_reg = PALETTE_A;
 
        /* values */
-       u32 dpll_val = regs->saveDPLL_A & ~DPLL_VCO_ENABLE;
-       u32 fp_val = regs->saveFPA0;
-       u32 pipeconf_val = regs->savePIPEACONF;
-       u32 htot_val = regs->saveHTOTAL_A;
-       u32 hblank_val = regs->saveHBLANK_A;
-       u32 hsync_val = regs->saveHSYNC_A;
-       u32 vtot_val = regs->saveVTOTAL_A;
-       u32 vblank_val = regs->saveVBLANK_A;
-       u32 vsync_val = regs->saveVSYNC_A;
-       u32 pipesrc_val = regs->savePIPEASRC;
-       u32 dspstride_val = regs->saveDSPASTRIDE;
-       u32 dsplinoff_val = regs->saveDSPALINOFF;
-       u32 dsptileoff_val = regs->saveDSPATILEOFF;
-       u32 dspsize_val = regs->saveDSPASIZE;
-       u32 dsppos_val = regs->saveDSPAPOS;
-       u32 dspsurf_val = regs->saveDSPASURF;
-       u32 dspstatus_val = regs->saveDSPASTATUS;
+       u32 dpll_val = pipe->dpll;
        u32 mipi_val = regs->saveMIPI;
-       u32 dspcntr_val = regs->saveDSPACNTR;
-       u32 *palette_val = regs->save_palette_a;
 
-       switch (pipe) {
+       switch (pipenum) {
        case 0:
+               dpll_val &= ~DPLL_VCO_ENABLE;
                dsi_config = dev_priv->dsi_configs[0];
                break;
        case 1:
-               /* regester */
-               dpll_reg = MDFLD_DPLL_B;
-               fp_reg = MDFLD_DPLL_DIV0;
-               pipeconf_reg = PIPEBCONF;
-               htot_reg = HTOTAL_B;
-               hblank_reg = HBLANK_B;
-               hsync_reg = HSYNC_B;
-               vtot_reg = VTOTAL_B;
-               vblank_reg = VBLANK_B;
-               vsync_reg = VSYNC_B;
-               pipesrc_reg = PIPEBSRC;
-               dspstride_reg = DSPBSTRIDE;
-               dsplinoff_reg = DSPBLINOFF;
-               dsptileoff_reg = DSPBTILEOFF;
-               dspsize_reg = DSPBSIZE;
-               dsppos_reg = DSPBPOS;
-               dspsurf_reg = DSPBSURF;
-               dspcntr_reg = DSPBCNTR;
-               dspstatus_reg = PIPEBSTAT;
-               palette_reg = PALETTE_B;
-
-               /* values */
-               dpll_val = regs->saveDPLL_B & ~DPLL_VCO_ENABLE;
-               fp_val = regs->saveFPB0;
-               pipeconf_val = regs->savePIPEBCONF;
-               htot_val = regs->saveHTOTAL_B;
-               hblank_val = regs->saveHBLANK_B;
-               hsync_val = regs->saveHSYNC_B;
-               vtot_val = regs->saveVTOTAL_B;
-               vblank_val = regs->saveVBLANK_B;
-               vsync_val = regs->saveVSYNC_B;
-               pipesrc_val = regs->savePIPEBSRC;
-               dspstride_val = regs->saveDSPBSTRIDE;
-               dsplinoff_val = regs->saveDSPBLINOFF;
-               dsptileoff_val = regs->saveDSPBTILEOFF;
-               dspsize_val = regs->saveDSPBSIZE;
-               dsppos_val = regs->saveDSPBPOS;
-               dspsurf_val = regs->saveDSPBSURF;
-               dspcntr_val = regs->saveDSPBCNTR;
-               dspstatus_val = regs->saveDSPBSTATUS;
-               palette_val = regs->save_palette_b;
+               dpll_val &= ~DPLL_VCO_ENABLE;
                break;
        case 2:
-               /* regester */
-               pipeconf_reg = PIPECCONF;
-               htot_reg = HTOTAL_C;
-               hblank_reg = HBLANK_C;
-               hsync_reg = HSYNC_C;
-               vtot_reg = VTOTAL_C;
-               vblank_reg = VBLANK_C;
-               vsync_reg = VSYNC_C;
-               pipesrc_reg = PIPECSRC;
-               dspstride_reg = DSPCSTRIDE;
-               dsplinoff_reg = DSPCLINOFF;
-               dsptileoff_reg = DSPCTILEOFF;
-               dspsize_reg = DSPCSIZE;
-               dsppos_reg = DSPCPOS;
-               dspsurf_reg = DSPCSURF;
                mipi_reg = MIPI_C;
-               dspcntr_reg = DSPCCNTR;
-               dspstatus_reg = PIPECSTAT;
-               palette_reg = PALETTE_C;
-
-               /* values */
-               pipeconf_val = regs->savePIPECCONF;
-               htot_val = regs->saveHTOTAL_C;
-               hblank_val = regs->saveHBLANK_C;
-               hsync_val = regs->saveHSYNC_C;
-               vtot_val = regs->saveVTOTAL_C;
-               vblank_val = regs->saveVBLANK_C;
-               vsync_val = regs->saveVSYNC_C;
-               pipesrc_val = regs->savePIPECSRC;
-               dspstride_val = regs->saveDSPCSTRIDE;
-               dsplinoff_val = regs->saveDSPCLINOFF;
-               dsptileoff_val = regs->saveDSPCTILEOFF;
-               dspsize_val = regs->saveDSPCSIZE;
-               dsppos_val = regs->saveDSPCPOS;
-               dspsurf_val = regs->saveDSPCSURF;
                mipi_val = regs->saveMIPI_C;
-               dspcntr_val = regs->saveDSPCCNTR;
-               dspstatus_val = regs->saveDSPCSTATUS;
-               palette_val = regs->save_palette_c;
-
                dsi_config = dev_priv->dsi_configs[1];
                break;
        default:
@@ -503,14 +279,14 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
        /*make sure VGA plane is off. it initializes to on after reset!*/
        PSB_WVDC32(0x80000000, VGACNTRL);
 
-       if (pipe == 1) {
-               PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
-               PSB_RVDC32(dpll_reg);
+       if (pipenum == 1) {
+               PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, map->dpll);
+               PSB_RVDC32(map->dpll);
 
-               PSB_WVDC32(fp_val, fp_reg);
+               PSB_WVDC32(pipe->fp0, map->fp0);
        } else {
 
-               dpll = PSB_RVDC32(dpll_reg);
+               dpll = PSB_RVDC32(map->dpll);
 
                if (!(dpll & DPLL_VCO_ENABLE)) {
 
@@ -518,23 +294,23 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
                           before enable the VCO */
                        if (dpll & MDFLD_PWR_GATE_EN) {
                                dpll &= ~MDFLD_PWR_GATE_EN;
-                               PSB_WVDC32(dpll, dpll_reg);
+                               PSB_WVDC32(dpll, map->dpll);
                                /* FIXME_MDFLD PO - change 500 to 1 after PO */
                                udelay(500);
                        }
 
-                       PSB_WVDC32(fp_val, fp_reg);
-                       PSB_WVDC32(dpll_val, dpll_reg);
+                       PSB_WVDC32(pipe->fp0, map->fp0);
+                       PSB_WVDC32(dpll_val, map->dpll);
                        /* FIXME_MDFLD PO - change 500 to 1 after PO */
                        udelay(500);
 
                        dpll_val |= DPLL_VCO_ENABLE;
-                       PSB_WVDC32(dpll_val, dpll_reg);
-                       PSB_RVDC32(dpll_reg);
+                       PSB_WVDC32(dpll_val, map->dpll);
+                       PSB_RVDC32(map->dpll);
 
                        /* wait for DSI PLL to lock */
                        while (timeout < 20000 &&
-                         !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+                         !(PSB_RVDC32(map->conf) & PIPECONF_DSIPLL_LOCK)) {
                                udelay(150);
                                timeout++;
                        }
@@ -547,28 +323,28 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
                }
        }
        /* Restore mode */
-       PSB_WVDC32(htot_val, htot_reg);
-       PSB_WVDC32(hblank_val, hblank_reg);
-       PSB_WVDC32(hsync_val, hsync_reg);
-       PSB_WVDC32(vtot_val, vtot_reg);
-       PSB_WVDC32(vblank_val, vblank_reg);
-       PSB_WVDC32(vsync_val, vsync_reg);
-       PSB_WVDC32(pipesrc_val, pipesrc_reg);
-       PSB_WVDC32(dspstatus_val, dspstatus_reg);
+       PSB_WVDC32(pipe->htotal, map->htotal);
+       PSB_WVDC32(pipe->hblank, map->hblank);
+       PSB_WVDC32(pipe->hsync, map->hsync);
+       PSB_WVDC32(pipe->vtotal, map->vtotal);
+       PSB_WVDC32(pipe->vblank, map->vblank);
+       PSB_WVDC32(pipe->vsync, map->vsync);
+       PSB_WVDC32(pipe->src, map->src);
+       PSB_WVDC32(pipe->status, map->status);
 
        /*set up the plane*/
-       PSB_WVDC32(dspstride_val, dspstride_reg);
-       PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
-       PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
-       PSB_WVDC32(dspsize_val, dspsize_reg);
-       PSB_WVDC32(dsppos_val, dsppos_reg);
-       PSB_WVDC32(dspsurf_val, dspsurf_reg);
-
-       if (pipe == 1) {
+       PSB_WVDC32(pipe->stride, map->stride);
+       PSB_WVDC32(pipe->linoff, map->linoff);
+       PSB_WVDC32(pipe->tileoff, map->tileoff);
+       PSB_WVDC32(pipe->size, map->size);
+       PSB_WVDC32(pipe->pos, map->pos);
+       PSB_WVDC32(pipe->surf, map->surf);
+
+       if (pipenum == 1) {
                /* restore palette (gamma) */
                /*DRM_UDELAY(50000); */
                for (i = 0; i < 256; i++)
-                       PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
+                       PSB_WVDC32(pipe->palette[i], map->palette + (i << 2));
 
                PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL);
                PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
@@ -578,7 +354,7 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
                /*TODO: resume pipe*/
 
                /*enable the plane*/
-               PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg);
+               PSB_WVDC32(pipe->cntr & ~DISPLAY_PLANE_ENABLE, map->cntr);
 
                return 0;
        }
@@ -588,7 +364,7 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
 
        /*setup MIPI adapter + MIPI IP registers*/
        if (dsi_config)
-               mdfld_dsi_controller_init(dsi_config, pipe);
+               mdfld_dsi_controller_init(dsi_config, pipenum);
 
        if (in_atomic() || in_interrupt())
                mdelay(20);
@@ -596,7 +372,7 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
                msleep(20);
 
        /*enable the plane*/
-       PSB_WVDC32(dspcntr_val, dspcntr_reg);
+       PSB_WVDC32(pipe->cntr, map->cntr);
 
        if (in_atomic() || in_interrupt())
                mdelay(20);
@@ -625,12 +401,12 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
        mdelay(1);
 
        /*enable the pipe*/
-       PSB_WVDC32(pipeconf_val, pipeconf_reg);
+       PSB_WVDC32(pipe->conf, map->conf);
 
        /* restore palette (gamma) */
        /*DRM_UDELAY(50000); */
        for (i = 0; i < 256; i++)
-               PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
+               PSB_WVDC32(pipe->palette[i], map->palette + (i << 2));
 
        return 0;
 }
@@ -667,14 +443,97 @@ static int mdfld_power_up(struct drm_device *dev)
        return 0;
 }
 
+/* Medfield  */
+static const struct psb_offset mdfld_regmap[3] = {
+       {
+               .fp0 = MRST_FPA0,
+               .fp1 = MRST_FPA1,
+               .cntr = DSPACNTR,
+               .conf = PIPEACONF,
+               .src = PIPEASRC,
+               .dpll = MRST_DPLL_A,
+               .htotal = HTOTAL_A,
+               .hblank = HBLANK_A,
+               .hsync = HSYNC_A,
+               .vtotal = VTOTAL_A,
+               .vblank = VBLANK_A,
+               .vsync = VSYNC_A,
+               .stride = DSPASTRIDE,
+               .size = DSPASIZE,
+               .pos = DSPAPOS,
+               .surf = DSPASURF,
+               .addr = MRST_DSPABASE,
+               .status = PIPEASTAT,
+               .linoff = DSPALINOFF,
+               .tileoff = DSPATILEOFF,
+               .palette = PALETTE_A,
+       },
+       {
+               .fp0 = MDFLD_DPLL_DIV0,
+               .cntr = DSPBCNTR,
+               .conf = PIPEBCONF,
+               .src = PIPEBSRC,
+               .dpll = MDFLD_DPLL_B,
+               .htotal = HTOTAL_B,
+               .hblank = HBLANK_B,
+               .hsync = HSYNC_B,
+               .vtotal = VTOTAL_B,
+               .vblank = VBLANK_B,
+               .vsync = VSYNC_B,
+               .stride = DSPBSTRIDE,
+               .size = DSPBSIZE,
+               .pos = DSPBPOS,
+               .surf = DSPBSURF,
+               .addr = MRST_DSPBBASE,
+               .status = PIPEBSTAT,
+               .linoff = DSPBLINOFF,
+               .tileoff = DSPBTILEOFF,
+               .palette = PALETTE_B,
+       },
+       {
+               .fp0 = MRST_FPA0,       /* This is what the old code did ?? */
+               .cntr = DSPCCNTR,
+               .conf = PIPECCONF,
+               .src = PIPECSRC,
+               /* No DPLL_C */
+               .dpll = MRST_DPLL_A,
+               .htotal = HTOTAL_C,
+               .hblank = HBLANK_C,
+               .hsync = HSYNC_C,
+               .vtotal = VTOTAL_C,
+               .vblank = VBLANK_C,
+               .vsync = VSYNC_C,
+               .stride = DSPCSTRIDE,
+               .size = DSPBSIZE,
+               .pos = DSPCPOS,
+               .surf = DSPCSURF,
+               .addr = MDFLD_DSPCBASE,
+               .status = PIPECSTAT,
+               .linoff = DSPCLINOFF,
+               .tileoff = DSPCTILEOFF,
+               .palette = PALETTE_C,
+       },
+};
+
+static int mdfld_chip_setup(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       if (pci_enable_msi(dev->pdev))
+               dev_warn(dev->dev, "Enabling MSI failed!\n");
+       dev_priv->regmap = mdfld_regmap;
+       return mid_chip_setup(dev);
+}
+
 const struct psb_ops mdfld_chip_ops = {
        .name = "mdfld",
        .accel_2d = 0,
        .pipes = 3,
        .crtcs = 3,
+       .lvds_mask = (1 << 1),
+       .hdmi_mask = (1 << 1),
        .sgx_offset = MRST_SGX_OFFSET,
 
-       .chip_setup = mid_chip_setup,
+       .chip_setup = mdfld_chip_setup,
        .crtc_helper = &mdfld_helper_funcs,
        .crtc_funcs = &psb_intel_crtc_funcs,
 
index d52358b744a0d1c295731699314141949b1923a0..b34ff097b97936a0017b348517e25466f609c270 100644 (file)
@@ -869,7 +869,6 @@ void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
                mdfld_set_pipe_timing(dsi_config, pipe);
 
                REG_WRITE(DSPABASE, 0x00);
-               REG_WRITE(DSPASTRIDE, (mode->hdisplay * 4));
                REG_WRITE(DSPASIZE,
                        ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
 
index 21071cef92a4c60a7791969cd63771855fac4540..36eb0744841c7c2f4071da62b11ba45006d7b466 100644 (file)
@@ -29,7 +29,6 @@
 #define __MDFLD_DSI_OUTPUT_H__
 
 #include <linux/backlight.h>
-#include <linux/version.h>
 #include <drm/drmP.h>
 #include <drm/drm.h>
 #include <drm/drm_crtc.h>
index baa0e14165e0fb531833cdb57492f371443c30f5..489ffd2c66e5dd300ec9bb44a154015c41596df6 100644 (file)
@@ -605,6 +605,8 @@ int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
        struct mdfld_dsi_config *dsi_config =
                                mdfld_dsi_get_config(dsi_connector);
        struct drm_device *dev = dsi_config->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        u32 mipi_val = 0;
 
        if (!dsi_connector) {
@@ -632,21 +634,13 @@ int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
        pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
 
        /*init regs*/
-       if (pipe == 0) {
-               pkg_sender->dpll_reg = MRST_DPLL_A;
-               pkg_sender->dspcntr_reg = DSPACNTR;
-               pkg_sender->pipeconf_reg = PIPEACONF;
-               pkg_sender->dsplinoff_reg = DSPALINOFF;
-               pkg_sender->dspsurf_reg = DSPASURF;
-               pkg_sender->pipestat_reg = PIPEASTAT;
-       } else if (pipe == 2) {
-               pkg_sender->dpll_reg = MRST_DPLL_A;
-               pkg_sender->dspcntr_reg = DSPCCNTR;
-               pkg_sender->pipeconf_reg = PIPECCONF;
-               pkg_sender->dsplinoff_reg = DSPCLINOFF;
-               pkg_sender->dspsurf_reg = DSPCSURF;
-               pkg_sender->pipestat_reg = PIPECSTAT;
-       }
+       /* FIXME: should just copy the regmap ptr ? */
+       pkg_sender->dpll_reg = map->dpll;
+       pkg_sender->dspcntr_reg = map->cntr;
+       pkg_sender->pipeconf_reg = map->conf;
+       pkg_sender->dsplinoff_reg = map->linoff;
+       pkg_sender->dspsurf_reg = map->surf;
+       pkg_sender->pipestat_reg = map->status;
 
        pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
        pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
index a35a2921bdf723572fd9f1e2d9929d69e047a7b4..3f3cd619c79f87895243c8885c52fe7a066ce82f 100644 (file)
@@ -50,17 +50,14 @@ struct mrst_clock_t {
 
 void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
 {
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        int count, temp;
-       u32 pipeconf_reg = PIPEACONF;
 
        switch (pipe) {
        case 0:
-               break;
        case 1:
-               pipeconf_reg = PIPEBCONF;
-               break;
        case 2:
-               pipeconf_reg = PIPECCONF;
                break;
        default:
                DRM_ERROR("Illegal Pipe Number.\n");
@@ -73,7 +70,7 @@ void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
 
        /* Wait for for the pipe disable to take effect. */
        for (count = 0; count < COUNT_MAX; count++) {
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_PIPE_STATE) == 0)
                        break;
        }
@@ -81,17 +78,14 @@ void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
 
 void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
 {
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        int count, temp;
-       u32 pipeconf_reg = PIPEACONF;
 
        switch (pipe) {
        case 0:
-               break;
        case 1:
-               pipeconf_reg = PIPEBCONF;
-               break;
        case 2:
-               pipeconf_reg = PIPECCONF;
                break;
        default:
                DRM_ERROR("Illegal Pipe Number.\n");
@@ -104,7 +98,7 @@ void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
 
        /* Wait for for the pipe enable to take effect. */
        for (count = 0; count < COUNT_MAX; count++) {
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_PIPE_STATE) == 1)
                        break;
        }
@@ -189,15 +183,12 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                                struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
-       /* struct drm_i915_master_private *master_priv; */
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
        int pipe = psb_intel_crtc->pipe;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
-       int dsplinoff = DSPALINOFF;
-       int dspsurf = DSPASURF;
-       int dspstride = DSPASTRIDE;
-       int dspcntr_reg = DSPACNTR;
        u32 dspcntr;
        int ret;
 
@@ -215,23 +206,7 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        if (ret)
                return ret;
 
-       switch (pipe) {
-       case 0:
-               dsplinoff = DSPALINOFF;
-               break;
-       case 1:
-               dsplinoff = DSPBLINOFF;
-               dspsurf = DSPBSURF;
-               dspstride = DSPBSTRIDE;
-               dspcntr_reg = DSPBCNTR;
-               break;
-       case 2:
-               dsplinoff = DSPCLINOFF;
-               dspsurf = DSPCSURF;
-               dspstride = DSPCSTRIDE;
-               dspcntr_reg = DSPCCNTR;
-               break;
-       default:
+       if (pipe > 2) {
                DRM_ERROR("Illegal Pipe Number.\n");
                return -EINVAL;
        }
@@ -242,8 +217,8 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        start = psbfb->gtt->offset;
        offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
 
-       REG_WRITE(dspstride, crtc->fb->pitches[0]);
-       dspcntr = REG_READ(dspcntr_reg);
+       REG_WRITE(map->stride, crtc->fb->pitches[0]);
+       dspcntr = REG_READ(map->cntr);
        dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
        switch (crtc->fb->bits_per_pixel) {
@@ -261,14 +236,14 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
                break;
        }
-       REG_WRITE(dspcntr_reg, dspcntr);
+       REG_WRITE(map->cntr, dspcntr);
 
        dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n",
                                                start, offset, x, y);
-       REG_WRITE(dsplinoff, offset);
-       REG_READ(dsplinoff);
-       REG_WRITE(dspsurf, start);
-       REG_READ(dspsurf);
+       REG_WRITE(map->linoff, offset);
+       REG_READ(map->linoff);
+       REG_WRITE(map->surf, start);
+       REG_READ(map->surf);
 
        gma_power_end(dev);
 
@@ -281,78 +256,56 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
  */
 void mdfld_disable_crtc(struct drm_device *dev, int pipe)
 {
-       int dpll_reg = MRST_DPLL_A;
-       int dspcntr_reg = DSPACNTR;
-       int dspbase_reg = MRST_DSPABASE;
-       int pipeconf_reg = PIPEACONF;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        u32 temp;
 
        dev_dbg(dev->dev, "pipe = %d\n", pipe);
 
 
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               dpll_reg = MDFLD_DPLL_B;
-               dspcntr_reg = DSPBCNTR;
-               dspbase_reg = DSPBSURF;
-               pipeconf_reg = PIPEBCONF;
-               break;
-       case 2:
-               dpll_reg = MRST_DPLL_A;
-               dspcntr_reg = DSPCCNTR;
-               dspbase_reg = MDFLD_DSPCBASE;
-               pipeconf_reg = PIPECCONF;
-               break;
-       default:
-               DRM_ERROR("Illegal Pipe Number.\n");
-               return;
-       }
-
        if (pipe != 1)
                mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe),
                                HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
 
        /* Disable display plane */
-       temp = REG_READ(dspcntr_reg);
+       temp = REG_READ(map->cntr);
        if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-               REG_WRITE(dspcntr_reg,
+               REG_WRITE(map->cntr,
                          temp & ~DISPLAY_PLANE_ENABLE);
                /* Flush the plane changes */
-               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-               REG_READ(dspbase_reg);
+               REG_WRITE(map->base, REG_READ(map->base));
+               REG_READ(map->base);
        }
 
        /* FIXME_JLIU7 MDFLD_PO revisit */
 
        /* Next, disable display pipes */
-       temp = REG_READ(pipeconf_reg);
+       temp = REG_READ(map->conf);
        if ((temp & PIPEACONF_ENABLE) != 0) {
                temp &= ~PIPEACONF_ENABLE;
                temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
-               REG_WRITE(pipeconf_reg, temp);
-               REG_READ(pipeconf_reg);
+               REG_WRITE(map->conf, temp);
+               REG_READ(map->conf);
 
                /* Wait for for the pipe disable to take effect. */
                mdfldWaitForPipeDisable(dev, pipe);
        }
 
-       temp = REG_READ(dpll_reg);
+       temp = REG_READ(map->dpll);
        if (temp & DPLL_VCO_ENABLE) {
                if ((pipe != 1 &&
                        !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF))
                                & PIPEACONF_ENABLE)) || pipe == 1) {
                        temp &= ~(DPLL_VCO_ENABLE);
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to turn off. */
                        /* FIXME_MDFLD PO may need more delay */
                        udelay(500);
 
                        if (!(temp & MDFLD_PWR_GATE_EN)) {
                                /* gating power of DPLL */
-                               REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+                               REG_WRITE(map->dpll, temp | MDFLD_PWR_GATE_EN);
                                /* FIXME_MDFLD PO - change 500 to 1 after PO */
                                udelay(5000);
                        }
@@ -373,41 +326,15 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = MRST_DPLL_A;
-       int dspcntr_reg = DSPACNTR;
-       int dspbase_reg = MRST_DSPABASE;
-       int pipeconf_reg = PIPEACONF;
-       u32 pipestat_reg = PIPEASTAT;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        u32 pipeconf = dev_priv->pipeconf[pipe];
        u32 temp;
        int timeout = 0;
 
        dev_dbg(dev->dev, "mode = %d, pipe = %d\n", mode, pipe);
 
-/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
-/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
-
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               dpll_reg = DPLL_B;
-               dspcntr_reg = DSPBCNTR;
-               dspbase_reg = MRST_DSPBBASE;
-               pipeconf_reg = PIPEBCONF;
-               dpll_reg = MDFLD_DPLL_B;
-               break;
-       case 2:
-               dpll_reg = MRST_DPLL_A;
-               dspcntr_reg = DSPCCNTR;
-               dspbase_reg = MDFLD_DSPCBASE;
-               pipeconf_reg = PIPECCONF;
-               pipestat_reg = PIPECSTAT;
-               break;
-       default:
-               DRM_ERROR("Illegal Pipe Number.\n");
-               return;
-       }
+       /* Note: Old code uses pipe a stat for pipe b but that appears
+          to be a bug */
 
        if (!gma_power_begin(dev, true))
                return;
@@ -420,25 +347,25 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
                /* Enable the DPLL */
-               temp = REG_READ(dpll_reg);
+               temp = REG_READ(map->dpll);
 
                if ((temp & DPLL_VCO_ENABLE) == 0) {
                        /* When ungating power of DPLL, needs to wait 0.5us
                           before enable the VCO */
                        if (temp & MDFLD_PWR_GATE_EN) {
                                temp &= ~MDFLD_PWR_GATE_EN;
-                               REG_WRITE(dpll_reg, temp);
+                               REG_WRITE(map->dpll, temp);
                                /* FIXME_MDFLD PO - change 500 to 1 after PO */
                                udelay(500);
                        }
 
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp);
+                       REG_READ(map->dpll);
                        /* FIXME_MDFLD PO - change 500 to 1 after PO */
                        udelay(500);
 
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
 
                        /**
                         * wait for DSI PLL to lock
@@ -446,25 +373,25 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
                         * since both MIPI pipes share the same PLL.
                         */
                        while ((pipe != 2) && (timeout < 20000) &&
-                         !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+                         !(REG_READ(map->conf) & PIPECONF_DSIPLL_LOCK)) {
                                udelay(150);
                                timeout++;
                        }
                }
 
                /* Enable the plane */
-               temp = REG_READ(dspcntr_reg);
+               temp = REG_READ(map->cntr);
                if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(dspcntr_reg,
+                       REG_WRITE(map->cntr,
                                temp | DISPLAY_PLANE_ENABLE);
                        /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                       REG_WRITE(map->base, REG_READ(map->base));
                }
 
                /* Enable the pipe */
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_ENABLE) == 0) {
-                       REG_WRITE(pipeconf_reg, pipeconf);
+                       REG_WRITE(map->conf, pipeconf);
 
                        /* Wait for for the pipe enable to take effect. */
                        mdfldWaitForPipeEnable(dev, pipe);
@@ -473,39 +400,39 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
                /*workaround for sighting 3741701 Random X blank display*/
                /*perform w/a in video mode only on pipe A or C*/
                if (pipe == 0 || pipe == 2) {
-                       REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
+                       REG_WRITE(map->status, REG_READ(map->status));
                        msleep(100);
-                       if (PIPE_VBLANK_STATUS & REG_READ(pipestat_reg))
+                       if (PIPE_VBLANK_STATUS & REG_READ(map->status))
                                dev_dbg(dev->dev, "OK");
                        else {
                                dev_dbg(dev->dev, "STUCK!!!!");
                                /*shutdown controller*/
-                               temp = REG_READ(dspcntr_reg);
-                               REG_WRITE(dspcntr_reg,
+                               temp = REG_READ(map->cntr);
+                               REG_WRITE(map->cntr,
                                                temp & ~DISPLAY_PLANE_ENABLE);
-                               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                               REG_WRITE(map->base, REG_READ(map->base));
                                /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
                                REG_WRITE(0xb048, 1);
                                msleep(100);
-                               temp = REG_READ(pipeconf_reg);
+                               temp = REG_READ(map->conf);
                                temp &= ~PIPEACONF_ENABLE;
-                               REG_WRITE(pipeconf_reg, temp);
+                               REG_WRITE(map->conf, temp);
                                msleep(100); /*wait for pipe disable*/
                                REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0);
                                msleep(100);
                                REG_WRITE(0xb004, REG_READ(0xb004));
                                /* try to bring the controller back up again*/
                                REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 1);
-                               temp = REG_READ(dspcntr_reg);
-                               REG_WRITE(dspcntr_reg,
+                               temp = REG_READ(map->cntr);
+                               REG_WRITE(map->cntr,
                                                temp | DISPLAY_PLANE_ENABLE);
-                               REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                               REG_WRITE(map->base, REG_READ(map->base));
                                /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
                                REG_WRITE(0xb048, 2);
                                msleep(100);
-                               temp = REG_READ(pipeconf_reg);
+                               temp = REG_READ(map->conf);
                                temp |= PIPEACONF_ENABLE;
-                               REG_WRITE(pipeconf_reg, temp);
+                               REG_WRITE(map->conf, temp);
                        }
                }
 
@@ -529,35 +456,35 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
                REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
 
                /* Disable display plane */
-               temp = REG_READ(dspcntr_reg);
+               temp = REG_READ(map->cntr);
                if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(dspcntr_reg,
+                       REG_WRITE(map->cntr,
                                  temp & ~DISPLAY_PLANE_ENABLE);
                        /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                       REG_READ(dspbase_reg);
+                       REG_WRITE(map->base, REG_READ(map->base));
+                       REG_READ(map->base);
                }
 
                /* Next, disable display pipes */
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_ENABLE) != 0) {
                        temp &= ~PIPEACONF_ENABLE;
                        temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
-                       REG_WRITE(pipeconf_reg, temp);
-                       REG_READ(pipeconf_reg);
+                       REG_WRITE(map->conf, temp);
+                       REG_READ(map->conf);
 
                        /* Wait for for the pipe disable to take effect. */
                        mdfldWaitForPipeDisable(dev, pipe);
                }
 
-               temp = REG_READ(dpll_reg);
+               temp = REG_READ(map->dpll);
                if (temp & DPLL_VCO_ENABLE) {
                        if ((pipe != 1 && !((REG_READ(PIPEACONF)
                                | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
                                        || pipe == 1) {
                                temp &= ~(DPLL_VCO_ENABLE);
-                               REG_WRITE(dpll_reg, temp);
-                               REG_READ(dpll_reg);
+                               REG_WRITE(map->dpll, temp);
+                               REG_READ(map->dpll);
                                /* Wait for the clocks to turn off. */
                                /* FIXME_MDFLD PO may need more delay */
                                udelay(500);
@@ -764,21 +691,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct drm_psb_private *dev_priv = dev->dev_private;
        int pipe = psb_intel_crtc->pipe;
-       int fp_reg = MRST_FPA0;
-       int dpll_reg = MRST_DPLL_A;
-       int dspcntr_reg = DSPACNTR;
-       int pipeconf_reg = PIPEACONF;
-       int htot_reg = HTOTAL_A;
-       int hblank_reg = HBLANK_A;
-       int hsync_reg = HSYNC_A;
-       int vtot_reg = VTOTAL_A;
-       int vblank_reg = VBLANK_A;
-       int vsync_reg = VSYNC_A;
-       int dspsize_reg = DSPASIZE;
-       int dsppos_reg = DSPAPOS;
-       int pipesrc_reg = PIPEASRC;
-       u32 *pipeconf = &dev_priv->pipeconf[pipe];
-       u32 *dspcntr = &dev_priv->dspcntr[pipe];
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        int refclk = 0;
        int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0,
                                                                clk_tmp = 0;
@@ -806,45 +719,6 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
        }
 #endif
 
-       switch (pipe) {
-       case 0:
-               break;
-       case 1:
-               fp_reg = FPB0;
-               dpll_reg = DPLL_B;
-               dspcntr_reg = DSPBCNTR;
-               pipeconf_reg = PIPEBCONF;
-               htot_reg = HTOTAL_B;
-               hblank_reg = HBLANK_B;
-               hsync_reg = HSYNC_B;
-               vtot_reg = VTOTAL_B;
-               vblank_reg = VBLANK_B;
-               vsync_reg = VSYNC_B;
-               dspsize_reg = DSPBSIZE;
-               dsppos_reg = DSPBPOS;
-               pipesrc_reg = PIPEBSRC;
-               fp_reg = MDFLD_DPLL_DIV0;
-               dpll_reg = MDFLD_DPLL_B;
-               break;
-       case 2:
-               dpll_reg = MRST_DPLL_A;
-               dspcntr_reg = DSPCCNTR;
-               pipeconf_reg = PIPECCONF;
-               htot_reg = HTOTAL_C;
-               hblank_reg = HBLANK_C;
-               hsync_reg = HSYNC_C;
-               vtot_reg = VTOTAL_C;
-               vblank_reg = VBLANK_C;
-               vsync_reg = VSYNC_C;
-               dspsize_reg = DSPCSIZE;
-               dsppos_reg = DSPCPOS;
-               pipesrc_reg = PIPECSRC;
-               break;
-       default:
-               DRM_ERROR("Illegal Pipe Number.\n");
-               return 0;
-       }
-
        ret = check_fb(crtc->fb);
        if (ret)
                return ret;
@@ -929,21 +803,21 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
                 * contained within the displayable area of the screen image
                 * (frame buffer).
                 */
-               REG_WRITE(dspsize_reg, ((min(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
+               REG_WRITE(map->size, ((min(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
                                | (min(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
                /* Set the CRTC with encoder mode. */
-               REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
+               REG_WRITE(map->src, ((mode->crtc_hdisplay - 1) << 16)
                                 | (mode->crtc_vdisplay - 1));
        } else {
-               REG_WRITE(dspsize_reg,
+               REG_WRITE(map->size,
                                ((mode->crtc_vdisplay - 1) << 16) |
                                                (mode->crtc_hdisplay - 1));
-               REG_WRITE(pipesrc_reg,
+               REG_WRITE(map->src,
                                ((mode->crtc_hdisplay - 1) << 16) |
                                                (mode->crtc_vdisplay - 1));
        }
 
-       REG_WRITE(dsppos_reg, 0);
+       REG_WRITE(map->pos, 0);
 
        if (psb_intel_encoder)
                drm_connector_property_get_value(connector,
@@ -961,34 +835,34 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
                offsetY = (adjusted_mode->crtc_vdisplay -
                                        mode->crtc_vdisplay) / 2;
 
-               REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
+               REG_WRITE(map->htotal, (mode->crtc_hdisplay - 1) |
                        ((adjusted_mode->crtc_htotal - 1) << 16));
-               REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
+               REG_WRITE(map->vtotal, (mode->crtc_vdisplay - 1) |
                        ((adjusted_mode->crtc_vtotal - 1) << 16));
-               REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start -
+               REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start -
                                                                offsetX - 1) |
                        ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
-               REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start -
+               REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start -
                                                                offsetX - 1) |
                        ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
-               REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start -
+               REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start -
                                                                offsetY - 1) |
                        ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
-               REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start -
+               REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start -
                                                                offsetY - 1) |
                        ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
        } else {
-               REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+               REG_WRITE(map->htotal, (adjusted_mode->crtc_hdisplay - 1) |
                        ((adjusted_mode->crtc_htotal - 1) << 16));
-               REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+               REG_WRITE(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) |
                        ((adjusted_mode->crtc_vtotal - 1) << 16));
-               REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+               REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start - 1) |
                        ((adjusted_mode->crtc_hblank_end - 1) << 16));
-               REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+               REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start - 1) |
                        ((adjusted_mode->crtc_hsync_end - 1) << 16));
-               REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+               REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start - 1) |
                        ((adjusted_mode->crtc_vblank_end - 1) << 16));
-               REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+               REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start - 1) |
                        ((adjusted_mode->crtc_vsync_end - 1) << 16));
        }
 
@@ -1000,12 +874,12 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        /* setup pipeconf */
-       *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
+       dev_priv->pipeconf[pipe] = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
 
        /* Set up the display plane register */
-       *dspcntr = REG_READ(dspcntr_reg);
-       *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
-       *dspcntr |= DISPLAY_PLANE_ENABLE;
+       dev_priv->dspcntr[pipe] = REG_READ(map->cntr);
+       dev_priv->dspcntr[pipe] |= pipe << DISPPLANE_SEL_PIPE_POS;
+       dev_priv->dspcntr[pipe] |= DISPLAY_PLANE_ENABLE;
 
        if (is_mipi2)
                goto mrst_crtc_mode_set_exit;
@@ -1070,21 +944,21 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
                                        clock.p1, m_conv);
                }
 
-               dpll = REG_READ(dpll_reg);
+               dpll = REG_READ(map->dpll);
 
                if (dpll & DPLL_VCO_ENABLE) {
                        dpll &= ~DPLL_VCO_ENABLE;
-                       REG_WRITE(dpll_reg, dpll);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, dpll);
+                       REG_READ(map->dpll);
 
                        /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
                        /* FIXME_MDFLD PO - change 500 to 1 after PO */
                        udelay(500);
 
                        /* reset M1, N1 & P1 */
-                       REG_WRITE(fp_reg, 0);
+                       REG_WRITE(map->fp0, 0);
                        dpll &= ~MDFLD_P1_MASK;
-                       REG_WRITE(dpll_reg, dpll);
+                       REG_WRITE(map->dpll, dpll);
                        /* FIXME_MDFLD PO - change 500 to 1 after PO */
                        udelay(500);
                }
@@ -1093,7 +967,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
                 * enable the VCO */
                if (dpll & MDFLD_PWR_GATE_EN) {
                        dpll &= ~MDFLD_PWR_GATE_EN;
-                       REG_WRITE(dpll_reg, dpll);
+                       REG_WRITE(map->dpll, dpll);
                        /* FIXME_MDFLD PO - change 500 to 1 after PO */
                        udelay(500);
                }
@@ -1134,18 +1008,18 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
                fp = 0x000000c1;
        }
 
-       REG_WRITE(fp_reg, fp);
-       REG_WRITE(dpll_reg, dpll);
+       REG_WRITE(map->fp0, fp);
+       REG_WRITE(map->dpll, dpll);
        /* FIXME_MDFLD PO - change 500 to 1 after PO */
        udelay(500);
 
        dpll |= DPLL_VCO_ENABLE;
-       REG_WRITE(dpll_reg, dpll);
-       REG_READ(dpll_reg);
+       REG_WRITE(map->dpll, dpll);
+       REG_READ(map->dpll);
 
        /* wait for DSI PLL to lock */
        while (timeout < 20000 &&
-                       !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+                       !(REG_READ(map->conf) & PIPECONF_DSIPLL_LOCK)) {
                udelay(150);
                timeout++;
        }
@@ -1155,11 +1029,11 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
 
        dev_dbg(dev->dev, "is_mipi = 0x%x\n", is_mipi);
 
-       REG_WRITE(pipeconf_reg, *pipeconf);
-       REG_READ(pipeconf_reg);
+       REG_WRITE(map->conf, dev_priv->pipeconf[pipe]);
+       REG_READ(map->conf);
 
        /* Wait for for the pipe enable to take effect. */
-       REG_WRITE(dspcntr_reg, *dspcntr);
+       REG_WRITE(map->cntr, dev_priv->dspcntr[pipe]);
        psb_intel_wait_for_vblank(dev);
 
 mrst_crtc_mode_set_exit:
index 5eee9ad80da422e321dde59ee1a690f53edc1c65..b2a790bd9899d16b76cd05b964514065b267be96 100644 (file)
@@ -118,139 +118,214 @@ static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
                                        dev_priv->platform_rev_id);
 }
 
+struct vbt_header {
+       u32 signature;
+       u8 revision;
+} __packed;
+
+/* The same for r0 and r1 */
+struct vbt_r0 {
+       struct vbt_header vbt_header;
+       u8 size;
+       u8 checksum;
+} __packed;
+
+struct vbt_r10 {
+       struct vbt_header vbt_header;
+       u8 checksum;
+       u16 size;
+       u8 panel_count;
+       u8 primary_panel_idx;
+       u8 secondary_panel_idx;
+       u8 __reserved[5];
+} __packed;
+
+static int read_vbt_r0(u32 addr, struct vbt_r0 *vbt)
+{
+       void __iomem *vbt_virtual;
+
+       vbt_virtual = ioremap(addr, sizeof(*vbt));
+       if (vbt_virtual == NULL)
+               return -1;
+
+       memcpy_fromio(vbt, vbt_virtual, sizeof(*vbt));
+       iounmap(vbt_virtual);
+
+       return 0;
+}
+
+static int read_vbt_r10(u32 addr, struct vbt_r10 *vbt)
+{
+       void __iomem *vbt_virtual;
+
+       vbt_virtual = ioremap(addr, sizeof(*vbt));
+       if (!vbt_virtual)
+               return -1;
+
+       memcpy_fromio(vbt, vbt_virtual, sizeof(*vbt));
+       iounmap(vbt_virtual);
+
+       return 0;
+}
+
+static int mid_get_vbt_data_r0(struct drm_psb_private *dev_priv, u32 addr)
+{
+       struct vbt_r0 vbt;
+       void __iomem *gct_virtual;
+       struct gct_r0 gct;
+       u8 bpi;
+
+       if (read_vbt_r0(addr, &vbt))
+               return -1;
+
+       gct_virtual = ioremap(addr + sizeof(vbt), vbt.size - sizeof(vbt));
+       if (!gct_virtual)
+               return -1;
+       memcpy_fromio(&gct, gct_virtual, sizeof(gct));
+       iounmap(gct_virtual);
+
+       bpi = gct.PD.BootPanelIndex;
+       dev_priv->gct_data.bpi = bpi;
+       dev_priv->gct_data.pt = gct.PD.PanelType;
+       dev_priv->gct_data.DTD = gct.panel[bpi].DTD;
+       dev_priv->gct_data.Panel_Port_Control =
+               gct.panel[bpi].Panel_Port_Control;
+       dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+               gct.panel[bpi].Panel_MIPI_Display_Descriptor;
+
+       return 0;
+}
+
+static int mid_get_vbt_data_r1(struct drm_psb_private *dev_priv, u32 addr)
+{
+       struct vbt_r0 vbt;
+       void __iomem *gct_virtual;
+       struct gct_r1 gct;
+       u8 bpi;
+
+       if (read_vbt_r0(addr, &vbt))
+               return -1;
+
+       gct_virtual = ioremap(addr + sizeof(vbt), vbt.size - sizeof(vbt));
+       if (!gct_virtual)
+               return -1;
+       memcpy_fromio(&gct, gct_virtual, sizeof(gct));
+       iounmap(gct_virtual);
+
+       bpi = gct.PD.BootPanelIndex;
+       dev_priv->gct_data.bpi = bpi;
+       dev_priv->gct_data.pt = gct.PD.PanelType;
+       dev_priv->gct_data.DTD = gct.panel[bpi].DTD;
+       dev_priv->gct_data.Panel_Port_Control =
+               gct.panel[bpi].Panel_Port_Control;
+       dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+               gct.panel[bpi].Panel_MIPI_Display_Descriptor;
+
+       return 0;
+}
+
+static int mid_get_vbt_data_r10(struct drm_psb_private *dev_priv, u32 addr)
+{
+       struct vbt_r10 vbt;
+       void __iomem *gct_virtual;
+       struct gct_r10 *gct;
+       struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD;
+       struct gct_r10_timing_info *ti;
+       int ret = -1;
+
+       if (read_vbt_r10(addr, &vbt))
+               return -1;
+
+       gct = kmalloc(sizeof(*gct) * vbt.panel_count, GFP_KERNEL);
+       if (!gct)
+               return -1;
+
+       gct_virtual = ioremap(addr + sizeof(vbt),
+                       sizeof(*gct) * vbt.panel_count);
+       if (!gct_virtual)
+               goto out;
+       memcpy_fromio(gct, gct_virtual, sizeof(*gct));
+       iounmap(gct_virtual);
+
+       dev_priv->gct_data.bpi = vbt.primary_panel_idx;
+       dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+               gct[vbt.primary_panel_idx].Panel_MIPI_Display_Descriptor;
+
+       ti = &gct[vbt.primary_panel_idx].DTD;
+       dp_ti->pixel_clock = ti->pixel_clock;
+       dp_ti->hactive_hi = ti->hactive_hi;
+       dp_ti->hactive_lo = ti->hactive_lo;
+       dp_ti->hblank_hi = ti->hblank_hi;
+       dp_ti->hblank_lo = ti->hblank_lo;
+       dp_ti->hsync_offset_hi = ti->hsync_offset_hi;
+       dp_ti->hsync_offset_lo = ti->hsync_offset_lo;
+       dp_ti->hsync_pulse_width_hi = ti->hsync_pulse_width_hi;
+       dp_ti->hsync_pulse_width_lo = ti->hsync_pulse_width_lo;
+       dp_ti->vactive_hi = ti->vactive_hi;
+       dp_ti->vactive_lo = ti->vactive_lo;
+       dp_ti->vblank_hi = ti->vblank_hi;
+       dp_ti->vblank_lo = ti->vblank_lo;
+       dp_ti->vsync_offset_hi = ti->vsync_offset_hi;
+       dp_ti->vsync_offset_lo = ti->vsync_offset_lo;
+       dp_ti->vsync_pulse_width_hi = ti->vsync_pulse_width_hi;
+       dp_ti->vsync_pulse_width_lo = ti->vsync_pulse_width_lo;
+
+       ret = 0;
+out:
+       kfree(gct);
+       return ret;
+}
+
 static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
-       struct oaktrail_vbt *vbt = &dev_priv->vbt_data;
        u32 addr;
-       u16 new_size;
-       u8 *vbt_virtual;
-       u8 bpi;
-       u8 number_desc = 0;
-       struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD;
-       struct gct_r10_timing_info ti;
-       void *pGCT;
+       u8 __iomem *vbt_virtual;
+       struct vbt_header vbt_header;
        struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+       int ret = -1;
 
-       /* Get the address of the platform config vbt, B0:D2:F0;0xFC */
+       /* Get the address of the platform config vbt */
        pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
        pci_dev_put(pci_gfx_root);
 
        dev_dbg(dev->dev, "drm platform config address is %x\n", addr);
 
-       /* check for platform config address == 0. */
-       /* this means fw doesn't support vbt */
-
-       if (addr == 0) {
-               vbt->size = 0;
-               return;
-       }
+       if (!addr)
+               goto out;
 
        /* get the virtual address of the vbt */
-       vbt_virtual = ioremap(addr, sizeof(*vbt));
-       if (vbt_virtual == NULL) {
-               vbt->size = 0;
-               return;
-       }
+       vbt_virtual = ioremap(addr, sizeof(vbt_header));
+       if (!vbt_virtual)
+               goto out;
 
-       memcpy(vbt, vbt_virtual, sizeof(*vbt));
-       iounmap(vbt_virtual); /* Free virtual address space */
+       memcpy_fromio(&vbt_header, vbt_virtual, sizeof(vbt_header));
+       iounmap(vbt_virtual);
 
-       /* No matching signature don't process the data */
-       if (memcmp(vbt->signature, "$GCT", 4)) {
-               vbt->size = 0;
-               return;
-       }
+       if (memcmp(&vbt_header.signature, "$GCT", 4))
+               goto out;
+
+       dev_dbg(dev->dev, "GCT revision is %02x\n", vbt_header.revision);
 
-       dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
-
-       switch (vbt->revision) {
-       case 0:
-               vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4,
-                                       vbt->size - sizeof(*vbt) + 4);
-               pGCT = vbt->oaktrail_gct;
-               bpi = ((struct oaktrail_gct_v1 *)pGCT)->PD.BootPanelIndex;
-               dev_priv->gct_data.bpi = bpi;
-               dev_priv->gct_data.pt =
-                       ((struct oaktrail_gct_v1 *)pGCT)->PD.PanelType;
-               memcpy(&dev_priv->gct_data.DTD,
-                       &((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].DTD,
-                               sizeof(struct oaktrail_timing_info));
-               dev_priv->gct_data.Panel_Port_Control =
-                 ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
-               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-                       ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+       switch (vbt_header.revision) {
+       case 0x00:
+               ret = mid_get_vbt_data_r0(dev_priv, addr);
                break;
-       case 1:
-               vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4,
-                                       vbt->size - sizeof(*vbt) + 4);
-               pGCT = vbt->oaktrail_gct;
-               bpi = ((struct oaktrail_gct_v2 *)pGCT)->PD.BootPanelIndex;
-               dev_priv->gct_data.bpi = bpi;
-               dev_priv->gct_data.pt =
-                       ((struct oaktrail_gct_v2 *)pGCT)->PD.PanelType;
-               memcpy(&dev_priv->gct_data.DTD,
-                       &((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].DTD,
-                               sizeof(struct oaktrail_timing_info));
-               dev_priv->gct_data.Panel_Port_Control =
-                 ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
-               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-                       ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+       case 0x01:
+               ret = mid_get_vbt_data_r1(dev_priv, addr);
                break;
        case 0x10:
-               /*header definition changed from rev 01 (v2) to rev 10h. */
-               /*so, some values have changed location*/
-               new_size = vbt->checksum; /*checksum contains lo size byte*/
-               /*LSB of oaktrail_gct contains hi size byte*/
-               new_size |= ((0xff & (unsigned int)(long)vbt->oaktrail_gct)) << 8;
-
-               vbt->checksum = vbt->size; /*size contains the checksum*/
-               if (new_size > 0xff)
-                       vbt->size = 0xff; /*restrict size to 255*/
-               else
-                       vbt->size = new_size;
-
-               /* number of descriptors defined in the GCT */
-               number_desc = ((0xff00 & (unsigned int)(long)vbt->oaktrail_gct)) >> 8;
-               bpi = ((0xff0000 & (unsigned int)(long)vbt->oaktrail_gct)) >> 16;
-               vbt->oaktrail_gct = ioremap(addr + GCT_R10_HEADER_SIZE,
-                               GCT_R10_DISPLAY_DESC_SIZE * number_desc);
-               pGCT = vbt->oaktrail_gct;
-               pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
-               dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
-
-               /*copy the GCT display timings into a temp structure*/
-               memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
-
-               /*now copy the temp struct into the dev_priv->gct_data*/
-               dp_ti->pixel_clock = ti.pixel_clock;
-               dp_ti->hactive_hi = ti.hactive_hi;
-               dp_ti->hactive_lo = ti.hactive_lo;
-               dp_ti->hblank_hi = ti.hblank_hi;
-               dp_ti->hblank_lo = ti.hblank_lo;
-               dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
-               dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
-               dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
-               dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
-               dp_ti->vactive_hi = ti.vactive_hi;
-               dp_ti->vactive_lo = ti.vactive_lo;
-               dp_ti->vblank_hi = ti.vblank_hi;
-               dp_ti->vblank_lo = ti.vblank_lo;
-               dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
-               dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
-               dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
-               dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
-
-               /* Move the MIPI_Display_Descriptor data from GCT to dev priv */
-               dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-                                                       *((u8 *)pGCT + 0x0d);
-               dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
-                                               (*((u8 *)pGCT + 0x0e)) << 8;
+               ret = mid_get_vbt_data_r10(dev_priv, addr);
                break;
        default:
                dev_err(dev->dev, "Unknown revision of GCT!\n");
-               vbt->size = 0;
        }
+
+out:
+       if (ret)
+               dev_err(dev->dev, "Unable to read GCT!");
+       else
+               dev_priv->has_gct = true;
 }
 
 int mid_chip_setup(struct drm_device *dev)
index 2da1f368f14e5ff565ac9f67e6d23f0a3c363537..f2f9f38a5362236ea235d128d25191c7b1fc5563 100644 (file)
 
 /* MID device specific descriptors */
 
-struct oaktrail_vbt {
-       s8 signature[4];        /*4 bytes,"$GCT" */
-       u8 revision;
-       u8 size;
-       u8 checksum;
-       void *oaktrail_gct;
-} __packed;
-
 struct oaktrail_timing_info {
        u16 pixel_clock;
        u8 hactive_lo;
@@ -161,7 +153,7 @@ union oaktrail_panel_rx {
        u16 panel_receiver;
 } __packed;
 
-struct oaktrail_gct_v1 {
+struct gct_r0 {
        union { /*8 bits,Defined as follows: */
                struct {
                        u8 PanelType:4; /*4 bits, Bit field for panels*/
@@ -178,7 +170,7 @@ struct oaktrail_gct_v1 {
        union oaktrail_panel_rx panelrx[4]; /* panel receivers*/
 } __packed;
 
-struct oaktrail_gct_v2 {
+struct gct_r1 {
        union { /*8 bits,Defined as follows: */
                struct {
                        u8 PanelType:4; /*4 bits, Bit field for panels*/
@@ -195,6 +187,16 @@ struct oaktrail_gct_v2 {
        union oaktrail_panel_rx panelrx[4]; /* panel receivers*/
 } __packed;
 
+struct gct_r10 {
+       struct gct_r10_timing_info DTD;
+       u16 Panel_MIPI_Display_Descriptor;
+       u16 Panel_MIPI_Receiver_Descriptor;
+       u16 Panel_Backlight_Inverter_Descriptor;
+       u8 Panel_Initial_Brightness;
+       u32 MIPI_Ctlr_Init_ptr;
+       u32 MIPI_Panel_Init_ptr;
+} __packed;
+
 struct oaktrail_gct_data {
        u8 bpi; /* boot panel index, number of panel used during boot */
        u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */
@@ -213,9 +215,6 @@ struct oaktrail_gct_data {
 #define MODE_SETTING_IN_DSR            0x4
 #define MODE_SETTING_ENCODER_DONE      0x8
 
-#define GCT_R10_HEADER_SIZE            16
-#define GCT_R10_DISPLAY_DESC_SIZE      28
-
 /*
  *     Moorestown HDMI interfaces
  */
index a39b0d0d680f9890914dec5b2a9d5f170437dc23..f821c835ca907aec23e5b6a4a1e96f9fe25d8426 100644 (file)
@@ -162,12 +162,10 @@ mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
 static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        u32 temp;
 
        if (!gma_power_begin(dev, true))
@@ -181,32 +179,32 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
                /* Enable the DPLL */
-               temp = REG_READ(dpll_reg);
+               temp = REG_READ(map->dpll);
                if ((temp & DPLL_VCO_ENABLE) == 0) {
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
                }
                /* Enable the pipe */
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_ENABLE) == 0)
-                       REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
+                       REG_WRITE(map->conf, temp | PIPEACONF_ENABLE);
                /* Enable the plane */
-               temp = REG_READ(dspcntr_reg);
+               temp = REG_READ(map->cntr);
                if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(dspcntr_reg,
+                       REG_WRITE(map->cntr,
                                  temp | DISPLAY_PLANE_ENABLE);
                        /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                       REG_WRITE(map->base, REG_READ(map->base));
                }
 
                psb_intel_crtc_load_lut(crtc);
@@ -223,28 +221,28 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
                /* Disable the VGA plane that we never use */
                REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
                /* Disable display plane */
-               temp = REG_READ(dspcntr_reg);
+               temp = REG_READ(map->cntr);
                if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(dspcntr_reg,
+                       REG_WRITE(map->cntr,
                                  temp & ~DISPLAY_PLANE_ENABLE);
                        /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                       REG_READ(dspbase_reg);
+                       REG_WRITE(map->base, REG_READ(map->base));
+                       REG_READ(map->base);
                }
 
                /* Next, disable display pipes */
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_ENABLE) != 0) {
-                       REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-                       REG_READ(pipeconf_reg);
+                       REG_WRITE(map->conf, temp & ~PIPEACONF_ENABLE);
+                       REG_READ(map->conf);
                }
                /* Wait for for the pipe disable to take effect. */
                psb_intel_wait_for_vblank(dev);
 
-               temp = REG_READ(dpll_reg);
+               temp = REG_READ(map->dpll);
                if ((temp & DPLL_VCO_ENABLE) != 0) {
-                       REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp & ~DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                }
 
                /* Wait for the clocks to turn off. */
@@ -292,17 +290,7 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct drm_psb_private *dev_priv = dev->dev_private;
        int pipe = psb_intel_crtc->pipe;
-       int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0;
-       int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
-       int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
-       int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
-       int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
-       int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
-       int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
-       int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        int refclk = 0;
        struct oaktrail_clock_t clock;
        u32 dpll = 0, fp = 0, dspcntr, pipeconf;
@@ -350,7 +338,7 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
        if (oaktrail_panel_fitter_pipe(dev) == pipe)
                REG_WRITE(PFIT_CONTROL, 0);
 
-       REG_WRITE(pipesrc_reg,
+       REG_WRITE(map->src,
                  ((mode->crtc_hdisplay - 1) << 16) |
                  (mode->crtc_vdisplay - 1));
 
@@ -369,34 +357,34 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
                offsetY = (adjusted_mode->crtc_vdisplay -
                           mode->crtc_vdisplay) / 2;
 
-               REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
+               REG_WRITE(map->htotal, (mode->crtc_hdisplay - 1) |
                        ((adjusted_mode->crtc_htotal - 1) << 16));
-               REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
+               REG_WRITE(map->vtotal, (mode->crtc_vdisplay - 1) |
                        ((adjusted_mode->crtc_vtotal - 1) << 16));
-               REG_WRITE(hblank_reg,
+               REG_WRITE(map->hblank,
                        (adjusted_mode->crtc_hblank_start - offsetX - 1) |
                        ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
-               REG_WRITE(hsync_reg,
+               REG_WRITE(map->hsync,
                        (adjusted_mode->crtc_hsync_start - offsetX - 1) |
                        ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
-               REG_WRITE(vblank_reg,
+               REG_WRITE(map->vblank,
                        (adjusted_mode->crtc_vblank_start - offsetY - 1) |
                        ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
-               REG_WRITE(vsync_reg,
+               REG_WRITE(map->vsync,
                        (adjusted_mode->crtc_vsync_start - offsetY - 1) |
                        ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
        } else {
-               REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+               REG_WRITE(map->htotal, (adjusted_mode->crtc_hdisplay - 1) |
                        ((adjusted_mode->crtc_htotal - 1) << 16));
-               REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+               REG_WRITE(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) |
                        ((adjusted_mode->crtc_vtotal - 1) << 16));
-               REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+               REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start - 1) |
                        ((adjusted_mode->crtc_hblank_end - 1) << 16));
-               REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+               REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start - 1) |
                        ((adjusted_mode->crtc_hsync_end - 1) << 16));
-               REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+               REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start - 1) |
                        ((adjusted_mode->crtc_vblank_end - 1) << 16));
-               REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+               REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start - 1) |
                        ((adjusted_mode->crtc_vsync_end - 1) << 16));
        }
 
@@ -408,10 +396,10 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        /* setup pipeconf */
-       pipeconf = REG_READ(pipeconf_reg);
+       pipeconf = REG_READ(map->conf);
 
        /* Set up the display plane register */
-       dspcntr = REG_READ(dspcntr_reg);
+       dspcntr = REG_READ(map->cntr);
        dspcntr |= DISPPLANE_GAMMA_ENABLE;
 
        if (pipe == 0)
@@ -467,30 +455,30 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
        mrstPrintPll("chosen", &clock);
 
        if (dpll & DPLL_VCO_ENABLE) {
-               REG_WRITE(fp_reg, fp);
-               REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
-               REG_READ(dpll_reg);
+               REG_WRITE(map->fp0, fp);
+               REG_WRITE(map->dpll, dpll & ~DPLL_VCO_ENABLE);
+               REG_READ(map->dpll);
                /* Check the DPLLA lock bit PIPEACONF[29] */
                udelay(150);
        }
 
-       REG_WRITE(fp_reg, fp);
-       REG_WRITE(dpll_reg, dpll);
-       REG_READ(dpll_reg);
+       REG_WRITE(map->fp0, fp);
+       REG_WRITE(map->dpll, dpll);
+       REG_READ(map->dpll);
        /* Wait for the clocks to stabilize. */
        udelay(150);
 
        /* write it again -- the BIOS does, after all */
-       REG_WRITE(dpll_reg, dpll);
-       REG_READ(dpll_reg);
+       REG_WRITE(map->dpll, dpll);
+       REG_READ(map->dpll);
        /* Wait for the clocks to stabilize. */
        udelay(150);
 
-       REG_WRITE(pipeconf_reg, pipeconf);
-       REG_READ(pipeconf_reg);
+       REG_WRITE(map->conf, pipeconf);
+       REG_READ(map->conf);
        psb_intel_wait_for_vblank(dev);
 
-       REG_WRITE(dspcntr_reg, dspcntr);
+       REG_WRITE(map->cntr, dspcntr);
        psb_intel_wait_for_vblank(dev);
 
 oaktrail_crtc_mode_set_exit:
@@ -509,15 +497,13 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
                            int x, int y, struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
        int pipe = psb_intel_crtc->pipe;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
 
-       int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE);
-       int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
-       int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
        u32 dspcntr;
        int ret = 0;
 
@@ -533,9 +519,9 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
        start = psbfb->gtt->offset;
        offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
 
-       REG_WRITE(dspstride, crtc->fb->pitches[0]);
+       REG_WRITE(map->stride, crtc->fb->pitches[0]);
 
-       dspcntr = REG_READ(dspcntr_reg);
+       dspcntr = REG_READ(map->cntr);
        dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
        switch (crtc->fb->bits_per_pixel) {
@@ -557,12 +543,12 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
                ret = -EINVAL;
                goto pipe_set_base_exit;
        }
-       REG_WRITE(dspcntr_reg, dspcntr);
+       REG_WRITE(map->cntr, dspcntr);
 
-       REG_WRITE(dspbase, offset);
-       REG_READ(dspbase);
-       REG_WRITE(dspsurf, start);
-       REG_READ(dspsurf);
+       REG_WRITE(map->base, offset);
+       REG_READ(map->base);
+       REG_WRITE(map->surf, start);
+       REG_READ(map->surf);
 
 pipe_set_base_exit:
        gma_power_end(dev);
index 41d1924ea31e300ca20d6a3eb1793072b43bb69e..7a8ff8e2dfc0c00291b4c3fcf960eabf2c91a052 100644 (file)
@@ -187,6 +187,7 @@ static int oaktrail_save_display_registers(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_save_area *regs = &dev_priv->regs;
+       struct psb_pipe *p = &regs->pipe[0];
        int i;
        u32 pp_stat;
 
@@ -201,24 +202,24 @@ static int oaktrail_save_display_registers(struct drm_device *dev)
        regs->psb.saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
 
        /* Pipe & plane A info */
-       regs->psb.savePIPEACONF = PSB_RVDC32(PIPEACONF);
-       regs->psb.savePIPEASRC = PSB_RVDC32(PIPEASRC);
-       regs->psb.saveFPA0 = PSB_RVDC32(MRST_FPA0);
-       regs->psb.saveFPA1 = PSB_RVDC32(MRST_FPA1);
-       regs->psb.saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
-       regs->psb.saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
-       regs->psb.saveHBLANK_A = PSB_RVDC32(HBLANK_A);
-       regs->psb.saveHSYNC_A = PSB_RVDC32(HSYNC_A);
-       regs->psb.saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
-       regs->psb.saveVBLANK_A = PSB_RVDC32(VBLANK_A);
-       regs->psb.saveVSYNC_A = PSB_RVDC32(VSYNC_A);
+       p->conf = PSB_RVDC32(PIPEACONF);
+       p->src = PSB_RVDC32(PIPEASRC);
+       p->fp0 = PSB_RVDC32(MRST_FPA0);
+       p->fp1 = PSB_RVDC32(MRST_FPA1);
+       p->dpll = PSB_RVDC32(MRST_DPLL_A);
+       p->htotal = PSB_RVDC32(HTOTAL_A);
+       p->hblank = PSB_RVDC32(HBLANK_A);
+       p->hsync = PSB_RVDC32(HSYNC_A);
+       p->vtotal = PSB_RVDC32(VTOTAL_A);
+       p->vblank = PSB_RVDC32(VBLANK_A);
+       p->vsync = PSB_RVDC32(VSYNC_A);
        regs->psb.saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
-       regs->psb.saveDSPACNTR = PSB_RVDC32(DSPACNTR);
-       regs->psb.saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
-       regs->psb.saveDSPAADDR = PSB_RVDC32(DSPABASE);
-       regs->psb.saveDSPASURF = PSB_RVDC32(DSPASURF);
-       regs->psb.saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
-       regs->psb.saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
+       p->cntr = PSB_RVDC32(DSPACNTR);
+       p->stride = PSB_RVDC32(DSPASTRIDE);
+       p->addr = PSB_RVDC32(DSPABASE);
+       p->surf = PSB_RVDC32(DSPASURF);
+       p->linoff = PSB_RVDC32(DSPALINOFF);
+       p->tileoff = PSB_RVDC32(DSPATILEOFF);
 
        /* Save cursor regs */
        regs->psb.saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
@@ -227,7 +228,7 @@ static int oaktrail_save_display_registers(struct drm_device *dev)
 
        /* Save palette (gamma) */
        for (i = 0; i < 256; i++)
-               regs->psb.save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
+               p->palette[i] = PSB_RVDC32(PALETTE_A + (i << 2));
 
        if (dev_priv->hdmi_priv)
                oaktrail_hdmi_save(dev);
@@ -300,6 +301,7 @@ static int oaktrail_restore_display_registers(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_save_area *regs = &dev_priv->regs;
+       struct psb_pipe *p = &regs->pipe[0];
        u32 pp_stat;
        int i;
 
@@ -317,21 +319,21 @@ static int oaktrail_restore_display_registers(struct drm_device *dev)
        PSB_WVDC32(0x80000000, VGACNTRL);
 
        /* set the plls */
-       PSB_WVDC32(regs->psb.saveFPA0, MRST_FPA0);
-       PSB_WVDC32(regs->psb.saveFPA1, MRST_FPA1);
+       PSB_WVDC32(p->fp0, MRST_FPA0);
+       PSB_WVDC32(p->fp1, MRST_FPA1);
 
        /* Actually enable it */
-       PSB_WVDC32(regs->psb.saveDPLL_A, MRST_DPLL_A);
+       PSB_WVDC32(p->dpll, MRST_DPLL_A);
        DRM_UDELAY(150);
 
        /* Restore mode */
-       PSB_WVDC32(regs->psb.saveHTOTAL_A, HTOTAL_A);
-       PSB_WVDC32(regs->psb.saveHBLANK_A, HBLANK_A);
-       PSB_WVDC32(regs->psb.saveHSYNC_A, HSYNC_A);
-       PSB_WVDC32(regs->psb.saveVTOTAL_A, VTOTAL_A);
-       PSB_WVDC32(regs->psb.saveVBLANK_A, VBLANK_A);
-       PSB_WVDC32(regs->psb.saveVSYNC_A, VSYNC_A);
-       PSB_WVDC32(regs->psb.savePIPEASRC, PIPEASRC);
+       PSB_WVDC32(p->htotal, HTOTAL_A);
+       PSB_WVDC32(p->hblank, HBLANK_A);
+       PSB_WVDC32(p->hsync, HSYNC_A);
+       PSB_WVDC32(p->vtotal, VTOTAL_A);
+       PSB_WVDC32(p->vblank, VBLANK_A);
+       PSB_WVDC32(p->vsync, VSYNC_A);
+       PSB_WVDC32(p->src, PIPEASRC);
        PSB_WVDC32(regs->psb.saveBCLRPAT_A, BCLRPAT_A);
 
        /* Restore performance mode*/
@@ -339,16 +341,16 @@ static int oaktrail_restore_display_registers(struct drm_device *dev)
 
        /* Enable the pipe*/
        if (dev_priv->iLVDS_enable)
-               PSB_WVDC32(regs->psb.savePIPEACONF, PIPEACONF);
+               PSB_WVDC32(p->conf, PIPEACONF);
 
        /* Set up the plane*/
-       PSB_WVDC32(regs->psb.saveDSPALINOFF, DSPALINOFF);
-       PSB_WVDC32(regs->psb.saveDSPASTRIDE, DSPASTRIDE);
-       PSB_WVDC32(regs->psb.saveDSPATILEOFF, DSPATILEOFF);
+       PSB_WVDC32(p->linoff, DSPALINOFF);
+       PSB_WVDC32(p->stride, DSPASTRIDE);
+       PSB_WVDC32(p->tileoff, DSPATILEOFF);
 
        /* Enable the plane */
-       PSB_WVDC32(regs->psb.saveDSPACNTR, DSPACNTR);
-       PSB_WVDC32(regs->psb.saveDSPASURF, DSPASURF);
+       PSB_WVDC32(p->cntr, DSPACNTR);
+       PSB_WVDC32(p->surf, DSPASURF);
 
        /* Enable Cursor A */
        PSB_WVDC32(regs->psb.saveDSPACURSOR_CTRL, CURACNTR);
@@ -357,7 +359,7 @@ static int oaktrail_restore_display_registers(struct drm_device *dev)
 
        /* Restore palette (gamma) */
        for (i = 0; i < 256; i++)
-               PSB_WVDC32(regs->psb.save_palette_a[i], PALETTE_A + (i << 2));
+               PSB_WVDC32(p->palette[i], PALETTE_A + (i << 2));
 
        if (dev_priv->hdmi_priv)
                oaktrail_hdmi_restore(dev);
@@ -454,31 +456,84 @@ static int oaktrail_power_up(struct drm_device *dev)
        return 0;
 }
 
+/* Oaktrail */
+static const struct psb_offset oaktrail_regmap[2] = {
+       {
+               .fp0 = MRST_FPA0,
+               .fp1 = MRST_FPA1,
+               .cntr = DSPACNTR,
+               .conf = PIPEACONF,
+               .src = PIPEASRC,
+               .dpll = MRST_DPLL_A,
+               .htotal = HTOTAL_A,
+               .hblank = HBLANK_A,
+               .hsync = HSYNC_A,
+               .vtotal = VTOTAL_A,
+               .vblank = VBLANK_A,
+               .vsync = VSYNC_A,
+               .stride = DSPASTRIDE,
+               .size = DSPASIZE,
+               .pos = DSPAPOS,
+               .surf = DSPASURF,
+               .addr = MRST_DSPABASE,
+               .status = PIPEASTAT,
+               .linoff = DSPALINOFF,
+               .tileoff = DSPATILEOFF,
+               .palette = PALETTE_A,
+       },
+       {
+               .fp0 = FPB0,
+               .fp1 = FPB1,
+               .cntr = DSPBCNTR,
+               .conf = PIPEBCONF,
+               .src = PIPEBSRC,
+               .dpll = DPLL_B,
+               .htotal = HTOTAL_B,
+               .hblank = HBLANK_B,
+               .hsync = HSYNC_B,
+               .vtotal = VTOTAL_B,
+               .vblank = VBLANK_B,
+               .vsync = VSYNC_B,
+               .stride = DSPBSTRIDE,
+               .size = DSPBSIZE,
+               .pos = DSPBPOS,
+               .surf = DSPBSURF,
+               .addr = DSPBBASE,
+               .status = PIPEBSTAT,
+               .linoff = DSPBLINOFF,
+               .tileoff = DSPBTILEOFF,
+               .palette = PALETTE_B,
+       },
+};
 
 static int oaktrail_chip_setup(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
-       struct oaktrail_vbt *vbt = &dev_priv->vbt_data;
        int ret;
        
+       if (pci_enable_msi(dev->pdev))
+               dev_warn(dev->dev, "Enabling MSI failed!\n");
+
+       dev_priv->regmap = oaktrail_regmap;
+
        ret = mid_chip_setup(dev);
        if (ret < 0)
                return ret;
-       if (vbt->size == 0) {
+       if (!dev_priv->has_gct) {
                /* Now pull the BIOS data */
-               gma_intel_opregion_init(dev);
+               psb_intel_opregion_init(dev);
                psb_intel_init_bios(dev);
        }
+       oaktrail_hdmi_setup(dev);
        return 0;
 }
 
 static void oaktrail_teardown(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
-       struct oaktrail_vbt *vbt = &dev_priv->vbt_data;
 
        oaktrail_hdmi_teardown(dev);
-       if (vbt->size == 0)
+       if (!dev_priv->has_gct)
                psb_intel_destroy_bios(dev);
 }
 
@@ -487,6 +542,8 @@ const struct psb_ops oaktrail_chip_ops = {
        .accel_2d = 1,
        .pipes = 2,
        .crtcs = 2,
+       .hdmi_mask = (1 << 0),
+       .lvds_mask = (1 << 0),
        .sgx_offset = MRST_SGX_OFFSET,
 
        .chip_setup = oaktrail_chip_setup,
index f8b367b45f66051405d6744467252bb68a535e8c..c10899c953b9f9d9fb7ef84bb17335465c032cea 100644 (file)
@@ -179,7 +179,6 @@ static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode)
 static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
                                struct drm_display_mode *mode)
 {
-       struct drm_psb_private *dev_priv = connector->dev->dev_private;
        if (mode->clock > 165000)
                return MODE_CLOCK_HIGH;
        if (mode->clock < 20000)
@@ -188,11 +187,6 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
 
-       /* We assume worst case scenario of 32 bpp here, since we don't know */
-       if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
-           dev_priv->vram_stolen_size)
-               return MODE_MEM;
-
        return MODE_OK;
 }
 
@@ -440,6 +434,7 @@ void oaktrail_hdmi_save(struct drm_device *dev)
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
        struct psb_state *regs = &dev_priv->regs.psb;
+       struct psb_pipe *pipeb = &dev_priv->regs.pipe[1];
        int i;
 
        /* dpll */
@@ -450,14 +445,14 @@ void oaktrail_hdmi_save(struct drm_device *dev)
        hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
 
        /* pipe B */
-       regs->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
-       regs->savePIPEBSRC  = PSB_RVDC32(PIPEBSRC);
-       regs->saveHTOTAL_B  = PSB_RVDC32(HTOTAL_B);
-       regs->saveHBLANK_B  = PSB_RVDC32(HBLANK_B);
-       regs->saveHSYNC_B   = PSB_RVDC32(HSYNC_B);
-       regs->saveVTOTAL_B  = PSB_RVDC32(VTOTAL_B);
-       regs->saveVBLANK_B  = PSB_RVDC32(VBLANK_B);
-       regs->saveVSYNC_B   = PSB_RVDC32(VSYNC_B);
+       pipeb->conf = PSB_RVDC32(PIPEBCONF);
+       pipeb->src = PSB_RVDC32(PIPEBSRC);
+       pipeb->htotal = PSB_RVDC32(HTOTAL_B);
+       pipeb->hblank = PSB_RVDC32(HBLANK_B);
+       pipeb->hsync = PSB_RVDC32(HSYNC_B);
+       pipeb->vtotal = PSB_RVDC32(VTOTAL_B);
+       pipeb->vblank = PSB_RVDC32(VBLANK_B);
+       pipeb->vsync = PSB_RVDC32(VSYNC_B);
 
        hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
        hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
@@ -469,12 +464,12 @@ void oaktrail_hdmi_save(struct drm_device *dev)
        hdmi_dev->savePCH_VSYNC_B  = PSB_RVDC32(PCH_VSYNC_B);
 
        /* plane */
-       regs->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
-       regs->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
-       regs->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
-       regs->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
-       regs->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
-       regs->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
+       pipeb->cntr = PSB_RVDC32(DSPBCNTR);
+       pipeb->stride = PSB_RVDC32(DSPBSTRIDE);
+       pipeb->addr = PSB_RVDC32(DSPBBASE);
+       pipeb->surf = PSB_RVDC32(DSPBSURF);
+       pipeb->linoff = PSB_RVDC32(DSPBLINOFF);
+       pipeb->tileoff = PSB_RVDC32(DSPBTILEOFF);
 
        /* cursor B */
        regs->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
@@ -483,7 +478,7 @@ void oaktrail_hdmi_save(struct drm_device *dev)
 
        /* save palette */
        for (i = 0; i < 256; i++)
-               regs->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
+               pipeb->palette[i] = PSB_RVDC32(PALETTE_B + (i << 2));
 }
 
 /* restore HDMI register state */
@@ -492,6 +487,7 @@ void oaktrail_hdmi_restore(struct drm_device *dev)
        struct drm_psb_private *dev_priv = dev->dev_private;
        struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
        struct psb_state *regs = &dev_priv->regs.psb;
+       struct psb_pipe *pipeb = &dev_priv->regs.pipe[1];
        int i;
 
        /* dpll */
@@ -503,13 +499,13 @@ void oaktrail_hdmi_restore(struct drm_device *dev)
        DRM_UDELAY(150);
 
        /* pipe */
-       PSB_WVDC32(regs->savePIPEBSRC, PIPEBSRC);
-       PSB_WVDC32(regs->saveHTOTAL_B, HTOTAL_B);
-       PSB_WVDC32(regs->saveHBLANK_B, HBLANK_B);
-       PSB_WVDC32(regs->saveHSYNC_B,  HSYNC_B);
-       PSB_WVDC32(regs->saveVTOTAL_B, VTOTAL_B);
-       PSB_WVDC32(regs->saveVBLANK_B, VBLANK_B);
-       PSB_WVDC32(regs->saveVSYNC_B,  VSYNC_B);
+       PSB_WVDC32(pipeb->src, PIPEBSRC);
+       PSB_WVDC32(pipeb->htotal, HTOTAL_B);
+       PSB_WVDC32(pipeb->hblank, HBLANK_B);
+       PSB_WVDC32(pipeb->hsync,  HSYNC_B);
+       PSB_WVDC32(pipeb->vtotal, VTOTAL_B);
+       PSB_WVDC32(pipeb->vblank, VBLANK_B);
+       PSB_WVDC32(pipeb->vsync,  VSYNC_B);
 
        PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
        PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
@@ -519,15 +515,15 @@ void oaktrail_hdmi_restore(struct drm_device *dev)
        PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
        PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B,  PCH_VSYNC_B);
 
-       PSB_WVDC32(regs->savePIPEBCONF, PIPEBCONF);
+       PSB_WVDC32(pipeb->conf, PIPEBCONF);
        PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
 
        /* plane */
-       PSB_WVDC32(regs->saveDSPBLINOFF, DSPBLINOFF);
-       PSB_WVDC32(regs->saveDSPBSTRIDE, DSPBSTRIDE);
-       PSB_WVDC32(regs->saveDSPBTILEOFF, DSPBTILEOFF);
-       PSB_WVDC32(regs->saveDSPBCNTR, DSPBCNTR);
-       PSB_WVDC32(regs->saveDSPBSURF, DSPBSURF);
+       PSB_WVDC32(pipeb->linoff, DSPBLINOFF);
+       PSB_WVDC32(pipeb->stride, DSPBSTRIDE);
+       PSB_WVDC32(pipeb->tileoff, DSPBTILEOFF);
+       PSB_WVDC32(pipeb->cntr, DSPBCNTR);
+       PSB_WVDC32(pipeb->surf, DSPBSURF);
 
        /* cursor B */
        PSB_WVDC32(regs->saveDSPBCURSOR_CTRL, CURBCNTR);
@@ -536,5 +532,5 @@ void oaktrail_hdmi_restore(struct drm_device *dev)
 
        /* restore palette */
        for (i = 0; i < 256; i++)
-               PSB_WVDC32(regs->save_palette_b[i], PALETTE_B + (i << 2));
+               PSB_WVDC32(pipeb->palette[i], PALETTE_B + (i << 2));
 }
index 5e84fbde749b554571daad28bb0ddd6bad821075..88627e3ba1e3a12a72725ba48902d35882b1fa52 100644 (file)
@@ -250,7 +250,7 @@ static irqreturn_t oaktrail_hdmi_i2c_handler(int this_irq, void *dev)
  */
 static void oaktrail_hdmi_i2c_gpio_fix(void)
 {
-       void *base;
+       void __iomem *base;
        unsigned int gpio_base = 0xff12c000;
        int gpio_len = 0x1000;
        u32 temp;
index 654f32b22b21f3511791cf326a5ca2df7cdb55ac..558c77fb55ece6af098a641497477f045b83c905 100644 (file)
@@ -257,7 +257,7 @@ static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev,
        mode_dev->panel_fixed_mode = NULL;
 
        /* Use the firmware provided data on Moorestown */
-       if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/
+       if (dev_priv->has_gct) {
                mode = kzalloc(sizeof(*mode), GFP_KERNEL);
                if (!mode)
                        return;
@@ -371,7 +371,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
                                        BRIGHTNESS_MAX_LEVEL);
 
        mode_dev->panel_wants_dither = false;
-       if (dev_priv->vbt_data.size != 0x00)
+       if (dev_priv->has_gct)
                mode_dev->panel_wants_dither = (dev_priv->gct_data.
                        Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE);
         if (dev_priv->lvds_dither)
diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c
new file mode 100644 (file)
index 0000000..aa9e89f
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include <linux/acpi.h>
+#include <linux/acpi_io.h>
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+
+#define PCI_ASLE 0xe4
+#define PCI_ASLS 0xfc
+
+#define OPREGION_HEADER_OFFSET 0
+#define OPREGION_ACPI_OFFSET   0x100
+#define   ACPI_CLID 0x01ac /* current lid state indicator */
+#define   ACPI_CDCK 0x01b0 /* current docking state indicator */
+#define OPREGION_SWSCI_OFFSET  0x200
+#define OPREGION_ASLE_OFFSET   0x300
+#define OPREGION_VBT_OFFSET    0x400
+
+#define OPREGION_SIGNATURE "IntelGraphicsMem"
+#define MBOX_ACPI      (1<<0)
+#define MBOX_SWSCI     (1<<1)
+#define MBOX_ASLE      (1<<2)
+
+struct opregion_header {
+       u8 signature[16];
+       u32 size;
+       u32 opregion_ver;
+       u8 bios_ver[32];
+       u8 vbios_ver[16];
+       u8 driver_ver[16];
+       u32 mboxes;
+       u8 reserved[164];
+} __packed;
+
+/* OpRegion mailbox #1: public ACPI methods */
+struct opregion_acpi {
+       u32 drdy;       /* driver readiness */
+       u32 csts;       /* notification status */
+       u32 cevt;       /* current event */
+       u8 rsvd1[20];
+       u32 didl[8];    /* supported display devices ID list */
+       u32 cpdl[8];    /* currently presented display list */
+       u32 cadl[8];    /* currently active display list */
+       u32 nadl[8];    /* next active devices list */
+       u32 aslp;       /* ASL sleep time-out */
+       u32 tidx;       /* toggle table index */
+       u32 chpd;       /* current hotplug enable indicator */
+       u32 clid;       /* current lid state*/
+       u32 cdck;       /* current docking state */
+       u32 sxsw;       /* Sx state resume */
+       u32 evts;       /* ASL supported events */
+       u32 cnot;       /* current OS notification */
+       u32 nrdy;       /* driver status */
+       u8 rsvd2[60];
+} __packed;
+
+/* OpRegion mailbox #2: SWSCI */
+struct opregion_swsci {
+       /*FIXME: add it later*/
+} __packed;
+
+/* OpRegion mailbox #3: ASLE */
+struct opregion_asle {
+       u32 ardy;       /* driver readiness */
+       u32 aslc;       /* ASLE interrupt command */
+       u32 tche;       /* technology enabled indicator */
+       u32 alsi;       /* current ALS illuminance reading */
+       u32 bclp;       /* backlight brightness to set */
+       u32 pfit;       /* panel fitting state */
+       u32 cblv;       /* current brightness level */
+       u16 bclm[20];   /* backlight level duty cycle mapping table */
+       u32 cpfm;       /* current panel fitting mode */
+       u32 epfm;       /* enabled panel fitting modes */
+       u8 plut[74];    /* panel LUT and identifier */
+       u32 pfmb;       /* PWM freq and min brightness */
+       u8 rsvd[102];
+} __packed;
+
+/* ASLE irq request bits */
+#define ASLE_SET_ALS_ILLUM     (1 << 0)
+#define ASLE_SET_BACKLIGHT     (1 << 1)
+#define ASLE_SET_PFIT          (1 << 2)
+#define ASLE_SET_PWM_FREQ      (1 << 3)
+#define ASLE_REQ_MSK           0xf
+
+/* response bits of ASLE irq request */
+#define ASLE_ALS_ILLUM_FAILED   (1<<10)
+#define ASLE_BACKLIGHT_FAILED   (1<<12)
+#define ASLE_PFIT_FAILED        (1<<14)
+#define ASLE_PWM_FREQ_FAILED    (1<<16)
+
+/* ASLE backlight brightness to set */
+#define ASLE_BCLP_VALID                (1<<31)
+#define ASLE_BCLP_MSK          (~(1<<31))
+
+/* ASLE panel fitting request */
+#define ASLE_PFIT_VALID         (1<<31)
+#define ASLE_PFIT_CENTER (1<<0)
+#define ASLE_PFIT_STRETCH_TEXT (1<<1)
+#define ASLE_PFIT_STRETCH_GFX (1<<2)
+
+/* response bits of ASLE irq request */
+#define ASLE_ALS_ILLUM_FAILED  (1<<10)
+#define ASLE_BACKLIGHT_FAILED  (1<<12)
+#define ASLE_PFIT_FAILED       (1<<14)
+#define ASLE_PWM_FREQ_FAILED   (1<<16)
+
+/* ASLE backlight brightness to set */
+#define ASLE_BCLP_VALID                (1<<31)
+#define ASLE_BCLP_MSK          (~(1<<31))
+
+/* ASLE panel fitting request */
+#define ASLE_PFIT_VALID         (1<<31)
+#define ASLE_PFIT_CENTER (1<<0)
+#define ASLE_PFIT_STRETCH_TEXT (1<<1)
+#define ASLE_PFIT_STRETCH_GFX (1<<2)
+
+/* PWM frequency and minimum brightness */
+#define ASLE_PFMB_BRIGHTNESS_MASK (0xff)
+#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8)
+#define ASLE_PFMB_PWM_MASK (0x7ffffe00)
+#define ASLE_PFMB_PWM_VALID (1<<31)
+
+#define ASLE_CBLV_VALID         (1<<31)
+
+static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct opregion_asle *asle = dev_priv->opregion.asle;
+       struct backlight_device *bd = dev_priv->backlight_device;
+       u32 max;
+
+       DRM_DEBUG_DRIVER("asle set backlight %x\n", bclp);
+
+       if (!(bclp & ASLE_BCLP_VALID))
+               return ASLE_BACKLIGHT_FAILED;
+
+       if (bd == NULL)
+               return ASLE_BACKLIGHT_FAILED;
+
+       bclp &= ASLE_BCLP_MSK;
+       if (bclp > 255)
+               return ASLE_BACKLIGHT_FAILED;
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+       max = bd->props.max_brightness;
+       bd->props.brightness = bclp * max / 255;
+       backlight_update_status(bd);
+#endif
+       asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID;
+
+       return 0;
+}
+
+void psb_intel_opregion_asle_intr(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct opregion_asle *asle = dev_priv->opregion.asle;
+       u32 asle_stat = 0;
+       u32 asle_req;
+
+       if (!asle)
+               return;
+
+       asle_req = asle->aslc & ASLE_REQ_MSK;
+       if (!asle_req) {
+               DRM_DEBUG_DRIVER("non asle set request??\n");
+               return;
+       }
+
+       if (asle_req & ASLE_SET_BACKLIGHT)
+               asle_stat |= asle_set_backlight(dev, asle->bclp);
+
+       asle->aslc = asle_stat;
+}
+
+#define ASLE_ALS_EN    (1<<0)
+#define ASLE_BLC_EN    (1<<1)
+#define ASLE_PFIT_EN   (1<<2)
+#define ASLE_PFMB_EN   (1<<3)
+
+void psb_intel_opregion_enable_asle(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct opregion_asle *asle = dev_priv->opregion.asle;
+
+       if (asle) {
+               /* Don't do this on Medfield or other non PC like devices, they
+                  use the bit for something different altogether */
+               psb_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE);
+               psb_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE);
+
+               asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN
+                                                               | ASLE_PFMB_EN;
+               asle->ardy = 1;
+       }
+}
+
+#define ACPI_EV_DISPLAY_SWITCH (1<<0)
+#define ACPI_EV_LID            (1<<1)
+#define ACPI_EV_DOCK           (1<<2)
+
+static struct psb_intel_opregion *system_opregion;
+
+static int psb_intel_opregion_video_event(struct notifier_block *nb,
+                                         unsigned long val, void *data)
+{
+       /* The only video events relevant to opregion are 0x80. These indicate
+          either a docking event, lid switch or display switch request. In
+          Linux, these are handled by the dock, button and video drivers.
+          We might want to fix the video driver to be opregion-aware in
+          future, but right now we just indicate to the firmware that the
+          request has been handled */
+
+       struct opregion_acpi *acpi;
+
+       if (!system_opregion)
+               return NOTIFY_DONE;
+
+       acpi = system_opregion->acpi;
+       acpi->csts = 0;
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block psb_intel_opregion_notifier = {
+       .notifier_call = psb_intel_opregion_video_event,
+};
+
+void psb_intel_opregion_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_opregion *opregion = &dev_priv->opregion;
+
+       if (!opregion->header)
+               return;
+
+       if (opregion->acpi) {
+               /* Notify BIOS we are ready to handle ACPI video ext notifs.
+                * Right now, all the events are handled by the ACPI video
+                * module. We don't actually need to do anything with them. */
+               opregion->acpi->csts = 0;
+               opregion->acpi->drdy = 1;
+
+               system_opregion = opregion;
+               register_acpi_notifier(&psb_intel_opregion_notifier);
+       }
+
+       if (opregion->asle)
+               psb_intel_opregion_enable_asle(dev);
+}
+
+void psb_intel_opregion_fini(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_opregion *opregion = &dev_priv->opregion;
+
+       if (!opregion->header)
+               return;
+
+       if (opregion->acpi) {
+               opregion->acpi->drdy = 0;
+
+               system_opregion = NULL;
+               unregister_acpi_notifier(&psb_intel_opregion_notifier);
+       }
+
+       /* just clear all opregion memory pointers now */
+       iounmap(opregion->header);
+       opregion->header = NULL;
+       opregion->acpi = NULL;
+       opregion->swsci = NULL;
+       opregion->asle = NULL;
+       opregion->vbt = NULL;
+}
+
+int psb_intel_opregion_setup(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_intel_opregion *opregion = &dev_priv->opregion;
+       u32 opregion_phy, mboxes;
+       void __iomem *base;
+       int err = 0;
+
+       pci_read_config_dword(dev->pdev, PCI_ASLS, &opregion_phy);
+       if (opregion_phy == 0) {
+               DRM_DEBUG_DRIVER("ACPI Opregion not supported\n");
+               return -ENOTSUPP;
+       }
+       DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
+       base = acpi_os_ioremap(opregion_phy, 8*1024);
+       if (!base)
+               return -ENOMEM;
+
+       if (memcmp(base, OPREGION_SIGNATURE, 16)) {
+               DRM_DEBUG_DRIVER("opregion signature mismatch\n");
+               err = -EINVAL;
+               goto err_out;
+       }
+
+       opregion->header = base;
+       opregion->vbt = base + OPREGION_VBT_OFFSET;
+
+       opregion->lid_state = base + ACPI_CLID;
+
+       mboxes = opregion->header->mboxes;
+       if (mboxes & MBOX_ACPI) {
+               DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
+               opregion->acpi = base + OPREGION_ACPI_OFFSET;
+       }
+
+       if (mboxes & MBOX_ASLE) {
+               DRM_DEBUG_DRIVER("ASLE supported\n");
+               opregion->asle = base + OPREGION_ASLE_OFFSET;
+       }
+
+       return 0;
+
+err_out:
+       iounmap(base);
+       return err;
+}
+
diff --git a/drivers/gpu/drm/gma500/opregion.h b/drivers/gpu/drm/gma500/opregion.h
new file mode 100644 (file)
index 0000000..72dc6b9
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#if defined(CONFIG_ACPI)
+extern void psb_intel_opregion_asle_intr(struct drm_device *dev);
+extern void psb_intel_opregion_init(struct drm_device *dev);
+extern void psb_intel_opregion_fini(struct drm_device *dev);
+extern int psb_intel_opregion_setup(struct drm_device *dev);
+
+#else
+
+extern inline void psb_intel_opregion_asle_intr(struct drm_device *dev)
+{
+}
+
+extern inline void psb_intel_opregion_init(struct drm_device *dev)
+{
+}
+
+extern inline void psb_intel_opregion_fini(struct drm_device *dev)
+{
+}
+
+extern inline int psb_intel_opregion_setup(struct drm_device *dev)
+{
+       return 0;
+}
+#endif
index 95d163e4f1f465e5c6d44ee502f4d98e858e1f4b..651af6768e144aaa76a7f3c2e9d90864e852e4a7 100644 (file)
@@ -289,11 +289,65 @@ static void psb_get_core_freq(struct drm_device *dev)
        }
 }
 
+/* Poulsbo */
+static const struct psb_offset psb_regmap[2] = {
+       {
+               .fp0 = FPA0,
+               .fp1 = FPA1,
+               .cntr = DSPACNTR,
+               .conf = PIPEACONF,
+               .src = PIPEASRC,
+               .dpll = DPLL_A,
+               .htotal = HTOTAL_A,
+               .hblank = HBLANK_A,
+               .hsync = HSYNC_A,
+               .vtotal = VTOTAL_A,
+               .vblank = VBLANK_A,
+               .vsync = VSYNC_A,
+               .stride = DSPASTRIDE,
+               .size = DSPASIZE,
+               .pos = DSPAPOS,
+               .base = DSPABASE,
+               .surf = DSPASURF,
+               .addr = DSPABASE,
+               .status = PIPEASTAT,
+               .linoff = DSPALINOFF,
+               .tileoff = DSPATILEOFF,
+               .palette = PALETTE_A,
+       },
+       {
+               .fp0 = FPB0,
+               .fp1 = FPB1,
+               .cntr = DSPBCNTR,
+               .conf = PIPEBCONF,
+               .src = PIPEBSRC,
+               .dpll = DPLL_B,
+               .htotal = HTOTAL_B,
+               .hblank = HBLANK_B,
+               .hsync = HSYNC_B,
+               .vtotal = VTOTAL_B,
+               .vblank = VBLANK_B,
+               .vsync = VSYNC_B,
+               .stride = DSPBSTRIDE,
+               .size = DSPBSIZE,
+               .pos = DSPBPOS,
+               .base = DSPBBASE,
+               .surf = DSPBSURF,
+               .addr = DSPBBASE,
+               .status = PIPEBSTAT,
+               .linoff = DSPBLINOFF,
+               .tileoff = DSPBTILEOFF,
+               .palette = PALETTE_B,
+       }
+};
+
 static int psb_chip_setup(struct drm_device *dev)
 {
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       dev_priv->regmap = psb_regmap;
        psb_get_core_freq(dev);
        gma_intel_setup_gmbus(dev);
-       gma_intel_opregion_init(dev);
+       psb_intel_opregion_init(dev);
        psb_intel_init_bios(dev);
        return 0;
 }
@@ -308,6 +362,8 @@ const struct psb_ops psb_chip_ops = {
        .accel_2d = 1,
        .pipes = 2,
        .crtcs = 2,
+       .hdmi_mask = (1 << 0),
+       .lvds_mask = (1 << 1),
        .sgx_offset = PSB_SGX_OFFSET,
        .chip_setup = psb_chip_setup,
        .chip_teardown = psb_chip_teardown,
index c34adf9d910ac11ab72986bfab539e203a7ae330..7473d3b8fffe20ffcd643ea1609f8512b89cbd6c 100644 (file)
@@ -79,6 +79,14 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
        { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
        { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
        { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0bea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0beb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0bec, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0bed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0bee, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0bef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
 #endif
        { 0, }
 };
@@ -172,24 +180,6 @@ static int psb_do_init(struct drm_device *dev)
        dev_priv->gatt_free_offset = pg->mmu_gatt_start +
            (stolen_gtt << PAGE_SHIFT) * 1024;
 
-       if (1 || drm_debug) {
-               uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID);
-               uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION);
-               DRM_INFO("SGX core id = 0x%08x\n", core_id);
-               DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n",
-                        (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >>
-                        _PSB_CC_REVISION_MAJOR_SHIFT,
-                        (core_rev & _PSB_CC_REVISION_MINOR_MASK) >>
-                        _PSB_CC_REVISION_MINOR_SHIFT);
-               DRM_INFO
-                   ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n",
-                    (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >>
-                    _PSB_CC_REVISION_MAINTENANCE_SHIFT,
-                    (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >>
-                    _PSB_CC_REVISION_DESIGNER_SHIFT);
-       }
-
-
        spin_lock_init(&dev_priv->irqmask_lock);
        spin_lock_init(&dev_priv->lock_2d);
 
@@ -215,12 +205,11 @@ static int psb_driver_unload(struct drm_device *dev)
        /* Kill vblank etc here */
 
        gma_backlight_exit(dev);
-
        psb_modeset_cleanup(dev);
 
        if (dev_priv) {
+               psb_intel_opregion_fini(dev);
                psb_lid_timer_takedown(dev_priv);
-               gma_intel_opregion_exit(dev);
 
                if (dev_priv->ops->chip_teardown)
                        dev_priv->ops->chip_teardown(dev);
@@ -246,6 +235,7 @@ static int psb_driver_unload(struct drm_device *dev)
                }
                psb_gtt_takedown(dev);
                if (dev_priv->scratch_page) {
+                       set_pages_wb(dev_priv->scratch_page, 1);
                        __free_page(dev_priv->scratch_page);
                        dev_priv->scratch_page = NULL;
                }
@@ -290,11 +280,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
        pci_set_master(dev->pdev);
 
-       if (!IS_PSB(dev)) {
-               if (pci_enable_msi(dev->pdev))
-                       dev_warn(dev->dev, "Enabling MSI failed!\n");
-       }
-
        dev_priv->num_pipe = dev_priv->ops->pipes;
 
        resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
@@ -309,6 +294,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        if (!dev_priv->sgx_reg)
                goto out_err;
 
+       psb_intel_opregion_setup(dev);
+
        ret = dev_priv->ops->chip_setup(dev);
        if (ret)
                goto out_err;
@@ -348,9 +335,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
        PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);
 
-/*     igd_opregion_init(&dev_priv->opregion_dev); */
        acpi_video_register();
-       if (dev_priv->lid_state)
+       if (dev_priv->opregion.lid_state)
                psb_lid_timer_init(dev_priv);
 
        ret = drm_vblank_init(dev, dev_priv->num_pipe);
@@ -370,8 +356,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
        PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
        spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-       if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET))
-               drm_irq_install(dev);
+
+       drm_irq_install(dev);
 
        dev->vblank_disable_allowed = 1;
 
index 40ce2c9bc2e45611a19c84d7b1d613219befefb6..fd1bc8f6bf979243760bc0a6da90d72026cd95c5 100644 (file)
@@ -30,6 +30,7 @@
 #include "psb_intel_drv.h"
 #include "gtt.h"
 #include "power.h"
+#include "opregion.h"
 #include "oaktrail.h"
 
 /* Append new drm mode definition here, align with libdrm definition */
@@ -120,6 +121,7 @@ enum {
 #define PSB_HWSTAM               0x2098
 #define PSB_INSTPM               0x20C0
 #define PSB_INT_IDENTITY_R        0x20A4
+#define _PSB_IRQ_ASLE            (1<<0)
 #define _MDFLD_PIPEC_EVENT_FLAG   (1<<2)
 #define _MDFLD_PIPEC_VBLANK_FLAG  (1<<3)
 #define _PSB_DPST_PIPEB_FLAG      (1<<4)
@@ -130,6 +132,7 @@ enum {
 #define _PSB_VSYNC_PIPEA_FLAG    (1<<7)
 #define _MDFLD_MIPIA_FLAG        (1<<16)
 #define _MDFLD_MIPIC_FLAG        (1<<17)
+#define _PSB_IRQ_DISP_HOTSYNC    (1<<17)
 #define _PSB_IRQ_SGX_FLAG        (1<<18)
 #define _PSB_IRQ_MSVDX_FLAG      (1<<19)
 #define _LNC_IRQ_TOPAZ_FLAG      (1<<20)
@@ -257,7 +260,8 @@ struct psb_intel_opregion {
        struct opregion_acpi *acpi;
        struct opregion_swsci *swsci;
        struct opregion_asle *asle;
-       int enabled;
+       void *vbt;
+       u32 __iomem *lid_state;
 };
 
 struct sdvo_device_mapping {
@@ -276,51 +280,73 @@ struct intel_gmbus {
        u32 reg0;
 };
 
+/*
+ *     Register offset maps
+ */
+
+struct psb_offset {
+       u32     fp0;
+       u32     fp1;
+       u32     cntr;
+       u32     conf;
+       u32     src;
+       u32     dpll;
+       u32     dpll_md;
+       u32     htotal;
+       u32     hblank;
+       u32     hsync;
+       u32     vtotal;
+       u32     vblank;
+       u32     vsync;
+       u32     stride;
+       u32     size;
+       u32     pos;
+       u32     surf;
+       u32     addr;
+       u32     base;
+       u32     status;
+       u32     linoff;
+       u32     tileoff;
+       u32     palette;
+};
+
 /*
  *     Register save state. This is used to hold the context when the
  *     device is powered off. In the case of Oaktrail this can (but does not
  *     yet) include screen blank. Operations occuring during the save
  *     update the register cache instead.
  */
+
+/*
+ *     Common status for pipes.
+ */
+struct psb_pipe {
+       u32     fp0;
+       u32     fp1;
+       u32     cntr;
+       u32     conf;
+       u32     src;
+       u32     dpll;
+       u32     dpll_md;
+       u32     htotal;
+       u32     hblank;
+       u32     hsync;
+       u32     vtotal;
+       u32     vblank;
+       u32     vsync;
+       u32     stride;
+       u32     size;
+       u32     pos;
+       u32     base;
+       u32     surf;
+       u32     addr;
+       u32     status;
+       u32     linoff;
+       u32     tileoff;
+       u32     palette[256];
+};
+
 struct psb_state {
-       uint32_t saveDSPACNTR;
-       uint32_t saveDSPBCNTR;
-       uint32_t savePIPEACONF;
-       uint32_t savePIPEBCONF;
-       uint32_t savePIPEASRC;
-       uint32_t savePIPEBSRC;
-       uint32_t saveFPA0;
-       uint32_t saveFPA1;
-       uint32_t saveDPLL_A;
-       uint32_t saveDPLL_A_MD;
-       uint32_t saveHTOTAL_A;
-       uint32_t saveHBLANK_A;
-       uint32_t saveHSYNC_A;
-       uint32_t saveVTOTAL_A;
-       uint32_t saveVBLANK_A;
-       uint32_t saveVSYNC_A;
-       uint32_t saveDSPASTRIDE;
-       uint32_t saveDSPASIZE;
-       uint32_t saveDSPAPOS;
-       uint32_t saveDSPABASE;
-       uint32_t saveDSPASURF;
-       uint32_t saveDSPASTATUS;
-       uint32_t saveFPB0;
-       uint32_t saveFPB1;
-       uint32_t saveDPLL_B;
-       uint32_t saveDPLL_B_MD;
-       uint32_t saveHTOTAL_B;
-       uint32_t saveHBLANK_B;
-       uint32_t saveHSYNC_B;
-       uint32_t saveVTOTAL_B;
-       uint32_t saveVBLANK_B;
-       uint32_t saveVSYNC_B;
-       uint32_t saveDSPBSTRIDE;
-       uint32_t saveDSPBSIZE;
-       uint32_t saveDSPBPOS;
-       uint32_t saveDSPBBASE;
-       uint32_t saveDSPBSURF;
-       uint32_t saveDSPBSTATUS;
        uint32_t saveVCLK_DIVISOR_VGA0;
        uint32_t saveVCLK_DIVISOR_VGA1;
        uint32_t saveVCLK_POST_DIV;
@@ -335,14 +361,8 @@ struct psb_state {
        uint32_t savePP_CONTROL;
        uint32_t savePP_CYCLE;
        uint32_t savePFIT_CONTROL;
-       uint32_t savePaletteA[256];
-       uint32_t savePaletteB[256];
        uint32_t saveCLOCKGATING;
        uint32_t saveDSPARB;
-       uint32_t saveDSPATILEOFF;
-       uint32_t saveDSPBTILEOFF;
-       uint32_t saveDSPAADDR;
-       uint32_t saveDSPBADDR;
        uint32_t savePFIT_AUTO_RATIOS;
        uint32_t savePFIT_PGM_RATIOS;
        uint32_t savePP_ON_DELAYS;
@@ -350,8 +370,6 @@ struct psb_state {
        uint32_t savePP_DIVISOR;
        uint32_t saveBCLRPAT_A;
        uint32_t saveBCLRPAT_B;
-       uint32_t saveDSPALINOFF;
-       uint32_t saveDSPBLINOFF;
        uint32_t savePERF_MODE;
        uint32_t saveDSPFW1;
        uint32_t saveDSPFW2;
@@ -366,8 +384,6 @@ struct psb_state {
        uint32_t saveDSPBCURSOR_BASE;
        uint32_t saveDSPACURSOR_POS;
        uint32_t saveDSPBCURSOR_POS;
-       uint32_t save_palette_a[256];
-       uint32_t save_palette_b[256];
        uint32_t saveOV_OVADD;
        uint32_t saveOV_OGAMC0;
        uint32_t saveOV_OGAMC1;
@@ -390,64 +406,7 @@ struct psb_state {
 };
 
 struct medfield_state {
-       uint32_t saveDPLL_A;
-       uint32_t saveFPA0;
-       uint32_t savePIPEACONF;
-       uint32_t saveHTOTAL_A;
-       uint32_t saveHBLANK_A;
-       uint32_t saveHSYNC_A;
-       uint32_t saveVTOTAL_A;
-       uint32_t saveVBLANK_A;
-       uint32_t saveVSYNC_A;
-       uint32_t savePIPEASRC;
-       uint32_t saveDSPASTRIDE;
-       uint32_t saveDSPALINOFF;
-       uint32_t saveDSPATILEOFF;
-       uint32_t saveDSPASIZE;
-       uint32_t saveDSPAPOS;
-       uint32_t saveDSPASURF;
-       uint32_t saveDSPACNTR;
-       uint32_t saveDSPASTATUS;
-       uint32_t save_palette_a[256];
        uint32_t saveMIPI;
-
-       uint32_t saveDPLL_B;
-       uint32_t saveFPB0;
-       uint32_t savePIPEBCONF;
-       uint32_t saveHTOTAL_B;
-       uint32_t saveHBLANK_B;
-       uint32_t saveHSYNC_B;
-       uint32_t saveVTOTAL_B;
-       uint32_t saveVBLANK_B;
-       uint32_t saveVSYNC_B;
-       uint32_t savePIPEBSRC;
-       uint32_t saveDSPBSTRIDE;
-       uint32_t saveDSPBLINOFF;
-       uint32_t saveDSPBTILEOFF;
-       uint32_t saveDSPBSIZE;
-       uint32_t saveDSPBPOS;
-       uint32_t saveDSPBSURF;
-       uint32_t saveDSPBCNTR;
-       uint32_t saveDSPBSTATUS;
-       uint32_t save_palette_b[256];
-
-       uint32_t savePIPECCONF;
-       uint32_t saveHTOTAL_C;
-       uint32_t saveHBLANK_C;
-       uint32_t saveHSYNC_C;
-       uint32_t saveVTOTAL_C;
-       uint32_t saveVBLANK_C;
-       uint32_t saveVSYNC_C;
-       uint32_t savePIPECSRC;
-       uint32_t saveDSPCSTRIDE;
-       uint32_t saveDSPCLINOFF;
-       uint32_t saveDSPCTILEOFF;
-       uint32_t saveDSPCSIZE;
-       uint32_t saveDSPCPOS;
-       uint32_t saveDSPCSURF;
-       uint32_t saveDSPCCNTR;
-       uint32_t saveDSPCSTATUS;
-       uint32_t save_palette_c[256];
        uint32_t saveMIPI_C;
 
        uint32_t savePFIT_CONTROL;
@@ -476,6 +435,7 @@ struct cdv_state {
 };
 
 struct psb_save_area {
+       struct psb_pipe pipe[3];
        uint32_t saveBSM;
        uint32_t saveVBT;
        union {
@@ -494,15 +454,19 @@ struct psb_ops;
 struct drm_psb_private {
        struct drm_device *dev;
        const struct psb_ops *ops;
+       const struct psb_offset *regmap;
+       
+       struct child_device_config *child_dev;
+       int child_dev_num;
 
        struct psb_gtt gtt;
 
        /* GTT Memory manager */
        struct psb_gtt_mm *gtt_mm;
        struct page *scratch_page;
-       u32 *gtt_map;
+       u32 __iomem *gtt_map;
        uint32_t stolen_base;
-       void *vram_addr;
+       u8 __iomem *vram_addr;
        unsigned long vram_stolen_size;
        int gtt_initialized;
        u16 gmch_ctrl;          /* Saved GTT setup */
@@ -518,8 +482,8 @@ struct drm_psb_private {
         * Register base
         */
 
-       uint8_t *sgx_reg;
-       uint8_t *vdc_reg;
+       uint8_t __iomem *sgx_reg;
+       uint8_t __iomem *vdc_reg;
        uint32_t gatt_free_offset;
 
        /*
@@ -605,7 +569,7 @@ struct drm_psb_private {
        int rpm_enabled;
 
        /* MID specific */
-       struct oaktrail_vbt vbt_data;
+       bool has_gct;
        struct oaktrail_gct_data gct_data;
 
        /* Oaktrail HDMI state */
@@ -621,6 +585,11 @@ struct drm_psb_private {
        uint32_t msi_addr;
        uint32_t msi_data;
 
+       /*
+        * Hotplug handling
+        */
+
+       struct work_struct hotplug_work;
 
        /*
         * LID-Switch
@@ -628,7 +597,6 @@ struct drm_psb_private {
        spinlock_t lid_lock;
        struct timer_list lid_timer;
        struct psb_intel_opregion opregion;
-       u32 *lid_state;
        u32 lid_last_state;
 
        /*
@@ -669,6 +637,8 @@ struct drm_psb_private {
        u32 dspcntr[3];
 
        int mdfld_panel_id;
+
+       bool dplla_96mhz;       /* DPLL data from the VBT */
 };
 
 
@@ -682,6 +652,8 @@ struct psb_ops {
        int pipes;              /* Number of output pipes */
        int crtcs;              /* Number of CRTCs */
        int sgx_offset;         /* Base offset of SGX device */
+       int hdmi_mask;          /* Mask of HDMI CRTCs */
+       int lvds_mask;          /* Mask of LVDS CRTCs */
 
        /* Sub functions */
        struct drm_crtc_helper_funcs const *crtc_helper;
@@ -690,9 +662,13 @@ struct psb_ops {
        /* Setup hooks */
        int (*chip_setup)(struct drm_device *dev);
        void (*chip_teardown)(struct drm_device *dev);
+       /* Optional helper caller after modeset */
+       void (*errata)(struct drm_device *dev);
 
        /* Display management hooks */
        int (*output_init)(struct drm_device *dev);
+       int (*hotplug)(struct drm_device *dev);
+       void (*hotplug_enable)(struct drm_device *dev, bool on);
        /* Power management hooks */
        void (*init_pm)(struct drm_device *dev);
        int (*save_regs)(struct drm_device *dev);
@@ -788,12 +764,6 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
 
 extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
 
-/*
- * intel_opregion.c
- */
-extern int gma_intel_opregion_init(struct drm_device *dev);
-extern int gma_intel_opregion_exit(struct drm_device *dev);
-
 /*
  * framebuffer.c
  */
index 2616558457c8e1beccf5818d3fc21d9e50ee151c..f3a3160aafdc91b740b8edf4e91a116ab62ae1b0 100644 (file)
@@ -337,15 +337,12 @@ static int psb_intel_pipe_set_base(struct drm_crtc *crtc,
                            int x, int y, struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
-       /* struct drm_i915_master_private *master_priv; */
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
        int pipe = psb_intel_crtc->pipe;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        unsigned long start, offset;
-       int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
-       int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
-       int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
        u32 dspcntr;
        int ret = 0;
 
@@ -367,9 +364,9 @@ static int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 
        offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
 
-       REG_WRITE(dspstride, crtc->fb->pitches[0]);
+       REG_WRITE(map->stride, crtc->fb->pitches[0]);
 
-       dspcntr = REG_READ(dspcntr_reg);
+       dspcntr = REG_READ(map->cntr);
        dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
 
        switch (crtc->fb->bits_per_pixel) {
@@ -392,18 +389,10 @@ static int psb_intel_pipe_set_base(struct drm_crtc *crtc,
                psb_gtt_unpin(psbfb->gtt);
                goto psb_intel_pipe_set_base_exit;
        }
-       REG_WRITE(dspcntr_reg, dspcntr);
-
+       REG_WRITE(map->cntr, dspcntr);
 
-       if (0 /* FIXMEAC - check what PSB needs */) {
-               REG_WRITE(dspbase, offset);
-               REG_READ(dspbase);
-               REG_WRITE(dspsurf, start);
-               REG_READ(dspsurf);
-       } else {
-               REG_WRITE(dspbase, start + offset);
-               REG_READ(dspbase);
-       }
+       REG_WRITE(map->base, start + offset);
+       REG_READ(map->base);
 
 psb_intel_pipe_cleaner:
        /* If there was a previous display we can now unpin it */
@@ -424,14 +413,10 @@ psb_intel_pipe_set_base_exit:
 static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct drm_device *dev = crtc->dev;
-       /* struct drm_i915_master_private *master_priv; */
-       /* struct drm_i915_private *dev_priv = dev->dev_private; */
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        int pipe = psb_intel_crtc->pipe;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        u32 temp;
 
        /* XXX: When our outputs are all unaware of DPMS modes other than off
@@ -442,34 +427,34 @@ static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
                /* Enable the DPLL */
-               temp = REG_READ(dpll_reg);
+               temp = REG_READ(map->dpll);
                if ((temp & DPLL_VCO_ENABLE) == 0) {
-                       REG_WRITE(dpll_reg, temp);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
-                       REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                        /* Wait for the clocks to stabilize. */
                        udelay(150);
                }
 
                /* Enable the pipe */
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_ENABLE) == 0)
-                       REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
+                       REG_WRITE(map->conf, temp | PIPEACONF_ENABLE);
 
                /* Enable the plane */
-               temp = REG_READ(dspcntr_reg);
+               temp = REG_READ(map->cntr);
                if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-                       REG_WRITE(dspcntr_reg,
+                       REG_WRITE(map->cntr,
                                  temp | DISPLAY_PLANE_ENABLE);
                        /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+                       REG_WRITE(map->base, REG_READ(map->base));
                }
 
                psb_intel_crtc_load_lut(crtc);
@@ -487,29 +472,29 @@ static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
                REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
 
                /* Disable display plane */
-               temp = REG_READ(dspcntr_reg);
+               temp = REG_READ(map->cntr);
                if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
-                       REG_WRITE(dspcntr_reg,
+                       REG_WRITE(map->cntr,
                                  temp & ~DISPLAY_PLANE_ENABLE);
                        /* Flush the plane changes */
-                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
-                       REG_READ(dspbase_reg);
+                       REG_WRITE(map->base, REG_READ(map->base));
+                       REG_READ(map->base);
                }
 
                /* Next, disable display pipes */
-               temp = REG_READ(pipeconf_reg);
+               temp = REG_READ(map->conf);
                if ((temp & PIPEACONF_ENABLE) != 0) {
-                       REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
-                       REG_READ(pipeconf_reg);
+                       REG_WRITE(map->conf, temp & ~PIPEACONF_ENABLE);
+                       REG_READ(map->conf);
                }
 
                /* Wait for vblank for the disable to take effect. */
                psb_intel_wait_for_vblank(dev);
 
-               temp = REG_READ(dpll_reg);
+               temp = REG_READ(map->dpll);
                if ((temp & DPLL_VCO_ENABLE) != 0) {
-                       REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
-                       REG_READ(dpll_reg);
+                       REG_WRITE(map->dpll, temp & ~DPLL_VCO_ENABLE);
+                       REG_READ(map->dpll);
                }
 
                /* Wait for the clocks to turn off. */
@@ -589,22 +574,11 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
                               struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
        int pipe = psb_intel_crtc->pipe;
-       int fp_reg = (pipe == 0) ? FPA0 : FPB0;
-       int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
-       int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
-       int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
-       int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
-       int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
-       int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
-       int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
-       int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
-       int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
-       int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
-       int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        int refclk;
        struct psb_intel_clock_t clock;
        u32 dpll = 0, fp = 0, dspcntr, pipeconf;
@@ -690,7 +664,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
        dpll |= PLL_REF_INPUT_DREFCLK;
 
        /* setup pipeconf */
-       pipeconf = REG_READ(pipeconf_reg);
+       pipeconf = REG_READ(map->conf);
 
        /* Set up the display plane register */
        dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -712,9 +686,9 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
        drm_mode_debug_printmodeline(mode);
 
        if (dpll & DPLL_VCO_ENABLE) {
-               REG_WRITE(fp_reg, fp);
-               REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
-               REG_READ(dpll_reg);
+               REG_WRITE(map->fp0, fp);
+               REG_WRITE(map->dpll, dpll & ~DPLL_VCO_ENABLE);
+               REG_READ(map->dpll);
                udelay(150);
        }
 
@@ -747,45 +721,45 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
                REG_READ(LVDS);
        }
 
-       REG_WRITE(fp_reg, fp);
-       REG_WRITE(dpll_reg, dpll);
-       REG_READ(dpll_reg);
+       REG_WRITE(map->fp0, fp);
+       REG_WRITE(map->dpll, dpll);
+       REG_READ(map->dpll);
        /* Wait for the clocks to stabilize. */
        udelay(150);
 
        /* write it again -- the BIOS does, after all */
-       REG_WRITE(dpll_reg, dpll);
+       REG_WRITE(map->dpll, dpll);
 
-       REG_READ(dpll_reg);
+       REG_READ(map->dpll);
        /* Wait for the clocks to stabilize. */
        udelay(150);
 
-       REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+       REG_WRITE(map->htotal, (adjusted_mode->crtc_hdisplay - 1) |
                  ((adjusted_mode->crtc_htotal - 1) << 16));
-       REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+       REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start - 1) |
                  ((adjusted_mode->crtc_hblank_end - 1) << 16));
-       REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+       REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start - 1) |
                  ((adjusted_mode->crtc_hsync_end - 1) << 16));
-       REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+       REG_WRITE(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) |
                  ((adjusted_mode->crtc_vtotal - 1) << 16));
-       REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+       REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start - 1) |
                  ((adjusted_mode->crtc_vblank_end - 1) << 16));
-       REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+       REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start - 1) |
                  ((adjusted_mode->crtc_vsync_end - 1) << 16));
        /* pipesrc and dspsize control the size that is scaled from,
         * which should always be the user's requested size.
         */
-       REG_WRITE(dspsize_reg,
+       REG_WRITE(map->size,
                  ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
-       REG_WRITE(dsppos_reg, 0);
-       REG_WRITE(pipesrc_reg,
+       REG_WRITE(map->pos, 0);
+       REG_WRITE(map->src,
                  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
-       REG_WRITE(pipeconf_reg, pipeconf);
-       REG_READ(pipeconf_reg);
+       REG_WRITE(map->conf, pipeconf);
+       REG_READ(map->conf);
 
        psb_intel_wait_for_vblank(dev);
 
-       REG_WRITE(dspcntr_reg, dspcntr);
+       REG_WRITE(map->cntr, dspcntr);
 
        /* Flush the plane changes */
        crtc_funcs->mode_set_base(crtc, x, y, old_fb);
@@ -799,10 +773,10 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_psb_private *dev_priv =
-                               (struct drm_psb_private *)dev->dev_private;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-       int palreg = PALETTE_A;
+       const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
+       int palreg = map->palette;
        int i;
 
        /* The clocks have to be on to load the palette. */
@@ -811,12 +785,7 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
 
        switch (psb_intel_crtc->pipe) {
        case 0:
-               break;
        case 1:
-               palreg = PALETTE_B;
-               break;
-       case 2:
-               palreg = PALETTE_C;
                break;
        default:
                dev_err(dev->dev, "Illegal Pipe Number.\n");
@@ -836,7 +805,7 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
                gma_power_end(dev);
        } else {
                for (i = 0; i < 256; i++) {
-                       dev_priv->regs.psb.save_palette_a[i] =
+                       dev_priv->regs.pipe[0].palette[i] =
                                  ((psb_intel_crtc->lut_r[i] +
                                  psb_intel_crtc->lut_adj[i]) << 16) |
                                  ((psb_intel_crtc->lut_g[i] +
@@ -854,11 +823,10 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
 static void psb_intel_crtc_save(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
-       /* struct drm_psb_private *dev_priv =
-                       (struct drm_psb_private *)dev->dev_private; */
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
        struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
-       int pipeA = (psb_intel_crtc->pipe == 0);
+       const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
        uint32_t paletteReg;
        int i;
 
@@ -867,27 +835,27 @@ static void psb_intel_crtc_save(struct drm_crtc *crtc)
                return;
        }
 
-       crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
-       crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
-       crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
-       crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
-       crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
-       crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
-       crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
-       crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
-       crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
-       crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
-       crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
-       crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
-       crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
+       crtc_state->saveDSPCNTR = REG_READ(map->cntr);
+       crtc_state->savePIPECONF = REG_READ(map->conf);
+       crtc_state->savePIPESRC = REG_READ(map->src);
+       crtc_state->saveFP0 = REG_READ(map->fp0);
+       crtc_state->saveFP1 = REG_READ(map->fp1);
+       crtc_state->saveDPLL = REG_READ(map->dpll);
+       crtc_state->saveHTOTAL = REG_READ(map->htotal);
+       crtc_state->saveHBLANK = REG_READ(map->hblank);
+       crtc_state->saveHSYNC = REG_READ(map->hsync);
+       crtc_state->saveVTOTAL = REG_READ(map->vtotal);
+       crtc_state->saveVBLANK = REG_READ(map->vblank);
+       crtc_state->saveVSYNC = REG_READ(map->vsync);
+       crtc_state->saveDSPSTRIDE = REG_READ(map->stride);
 
        /*NOTE: DSPSIZE DSPPOS only for psb*/
-       crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
-       crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
+       crtc_state->saveDSPSIZE = REG_READ(map->size);
+       crtc_state->saveDSPPOS = REG_READ(map->pos);
 
-       crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
+       crtc_state->saveDSPBASE = REG_READ(map->base);
 
-       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+       paletteReg = map->palette;
        for (i = 0; i < 256; ++i)
                crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
 }
@@ -898,12 +866,10 @@ static void psb_intel_crtc_save(struct drm_crtc *crtc)
 static void psb_intel_crtc_restore(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
-       /* struct drm_psb_private * dev_priv =
-                               (struct drm_psb_private *)dev->dev_private; */
+       struct drm_psb_private *dev_priv = dev->dev_private;
        struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
        struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
-       /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
-       int pipeA = (psb_intel_crtc->pipe == 0);
+       const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
        uint32_t paletteReg;
        int i;
 
@@ -913,45 +879,45 @@ static void psb_intel_crtc_restore(struct drm_crtc *crtc)
        }
 
        if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
-               REG_WRITE(pipeA ? DPLL_A : DPLL_B,
+               REG_WRITE(map->dpll,
                        crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
-               REG_READ(pipeA ? DPLL_A : DPLL_B);
+               REG_READ(map->dpll);
                udelay(150);
        }
 
-       REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
-       REG_READ(pipeA ? FPA0 : FPB0);
+       REG_WRITE(map->fp0, crtc_state->saveFP0);
+       REG_READ(map->fp0);
 
-       REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
-       REG_READ(pipeA ? FPA1 : FPB1);
+       REG_WRITE(map->fp1, crtc_state->saveFP1);
+       REG_READ(map->fp1);
 
-       REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
-       REG_READ(pipeA ? DPLL_A : DPLL_B);
+       REG_WRITE(map->dpll, crtc_state->saveDPLL);
+       REG_READ(map->dpll);
        udelay(150);
 
-       REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
-       REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
-       REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
-       REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
-       REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
-       REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
-       REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
+       REG_WRITE(map->htotal, crtc_state->saveHTOTAL);
+       REG_WRITE(map->hblank, crtc_state->saveHBLANK);
+       REG_WRITE(map->hsync, crtc_state->saveHSYNC);
+       REG_WRITE(map->vtotal, crtc_state->saveVTOTAL);
+       REG_WRITE(map->vblank, crtc_state->saveVBLANK);
+       REG_WRITE(map->vsync, crtc_state->saveVSYNC);
+       REG_WRITE(map->stride, crtc_state->saveDSPSTRIDE);
 
-       REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
-       REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
+       REG_WRITE(map->size, crtc_state->saveDSPSIZE);
+       REG_WRITE(map->pos, crtc_state->saveDSPPOS);
 
-       REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
-       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
-       REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
+       REG_WRITE(map->src, crtc_state->savePIPESRC);
+       REG_WRITE(map->base, crtc_state->saveDSPBASE);
+       REG_WRITE(map->conf, crtc_state->savePIPECONF);
 
        psb_intel_wait_for_vblank(dev);
 
-       REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
-       REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+       REG_WRITE(map->cntr, crtc_state->saveDSPCNTR);
+       REG_WRITE(map->base, crtc_state->saveDSPBASE);
 
        psb_intel_wait_for_vblank(dev);
 
-       paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+       paletteReg = map->palette;
        for (i = 0; i < 256; ++i)
                REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
 }
@@ -1115,34 +1081,30 @@ static int psb_intel_crtc_clock_get(struct drm_device *dev,
                                struct drm_crtc *crtc)
 {
        struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+       struct drm_psb_private *dev_priv = dev->dev_private;
        int pipe = psb_intel_crtc->pipe;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
        u32 dpll;
        u32 fp;
        struct psb_intel_clock_t clock;
        bool is_lvds;
-       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
 
        if (gma_power_begin(dev, false)) {
-               dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
+               dpll = REG_READ(map->dpll);
                if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-                       fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
+                       fp = REG_READ(map->fp0);
                else
-                       fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
+                       fp = REG_READ(map->fp1);
                is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
                gma_power_end(dev);
        } else {
-               dpll = (pipe == 0) ?
-                       dev_priv->regs.psb.saveDPLL_A :
-                       dev_priv->regs.psb.saveDPLL_B;
+               dpll = p->dpll;
 
                if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-                       fp = (pipe == 0) ?
-                               dev_priv->regs.psb.saveFPA0 :
-                               dev_priv->regs.psb.saveFPB0;
+                       fp = p->fp0;
                else
-                       fp = (pipe == 0) ?
-                               dev_priv->regs.psb.saveFPA1 :
-                               dev_priv->regs.psb.saveFPB1;
+                       fp = p->fp1;
 
                is_lvds = (pipe == 1) && (dev_priv->regs.psb.saveLVDS &
                                                                LVDS_PORT_EN);
@@ -1202,26 +1164,20 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
        int vtot;
        int vsync;
        struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
 
        if (gma_power_begin(dev, false)) {
-               htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
-               hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
-               vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
-               vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+               htot = REG_READ(map->htotal);
+               hsync = REG_READ(map->hsync);
+               vtot = REG_READ(map->vtotal);
+               vsync = REG_READ(map->vsync);
                gma_power_end(dev);
        } else {
-               htot = (pipe == 0) ?
-                       dev_priv->regs.psb.saveHTOTAL_A :
-                       dev_priv->regs.psb.saveHTOTAL_B;
-               hsync = (pipe == 0) ?
-                       dev_priv->regs.psb.saveHSYNC_A :
-                       dev_priv->regs.psb.saveHSYNC_B;
-               vtot = (pipe == 0) ?
-                       dev_priv->regs.psb.saveVTOTAL_A :
-                       dev_priv->regs.psb.saveVTOTAL_B;
-               vsync = (pipe == 0) ?
-                       dev_priv->regs.psb.saveVSYNC_A :
-                       dev_priv->regs.psb.saveVSYNC_B;
+               htot = p->htotal;
+               hsync = p->hsync;
+               vtot = p->vtotal;
+               vsync = p->vsync;
        }
 
        mode = kzalloc(sizeof(*mode), GFP_KERNEL);
index f40535e566898e67cd858a4a78104f0d2e64ddf6..81852b48654c3bde86f24f3e748440a3988f9ffa 100644 (file)
@@ -193,6 +193,9 @@ struct psb_intel_crtc {
        /*crtc mode setting flags*/
        u32 mode_flags;
 
+       bool active;
+       bool crtc_enable;
+
        /* Saved Crtc HW states */
        struct psb_intel_crtc_state *crtc_state;
 };
index e89d3a2e8fdcad01f43e04eb7119dc911e106115..8e8c8efb0a89852ec2c9d2b623f43ca25ac2273e 100644 (file)
@@ -91,6 +91,9 @@
 
 #define BLC_PWM_CTL            0x61254
 #define BLC_PWM_CTL2           0x61250
+#define  PWM_ENABLE            (1 << 31)
+#define  PWM_LEGACY_MODE       (1 << 30)
+#define  PWM_PIPE_B            (1 << 29)
 #define BLC_PWM_CTL_C          0x62254
 #define BLC_PWM_CTL2_C         0x62250
 #define BACKLIGHT_MODULATION_FREQ_SHIFT                (17)
 #define DPLLB_LVDS_P2_CLOCK_DIV_14     (0 << 24)       /* i915 */
 #define DPLLB_LVDS_P2_CLOCK_DIV_7      (1 << 24)       /* i915 */
 #define DPLL_P2_CLOCK_DIV_MASK         0x03000000      /* i915 */
-#define DPLL_FPA01_P1_POST_DIV_MASK    0x00ff0000      /* i915 */
+#define DPLL_FPA0h1_P1_POST_DIV_MASK   0x00ff0000      /* i915 */
 #define DPLL_LOCK                      (1 << 15)       /* CDV */
 
 /*
 #define FP_M2_DIV_SHIFT                        0
 
 #define PORT_HOTPLUG_EN                0x61110
+#define HDMIB_HOTPLUG_INT_EN           (1 << 29)
+#define HDMIC_HOTPLUG_INT_EN           (1 << 28)
+#define HDMID_HOTPLUG_INT_EN           (1 << 27)
 #define SDVOB_HOTPLUG_INT_EN           (1 << 26)
 #define SDVOC_HOTPLUG_INT_EN           (1 << 25)
 #define TV_HOTPLUG_INT_EN              (1 << 18)
 #define PIPE_VBLANK_INTERRUPT_ENABLE           (1UL << 17)
 #define PIPE_START_VBLANK_INTERRUPT_ENABLE     (1UL << 18)
 #define PIPE_TE_ENABLE                         (1UL << 22)
+#define PIPE_LEGACY_BLC_EVENT_ENABLE           (1UL << 22)
 #define PIPE_DPST_EVENT_ENABLE                 (1UL << 23)
 #define PIPE_VSYNC_ENABL                       (1UL << 25)
 #define PIPE_HDMI_AUDIO_UNDERRUN               (1UL << 26)
 #define PIPE_HDMI_AUDIO_BUFFER_DONE            (1UL << 27)
+#define PIPE_FIFO_UNDERRUN                     (1UL << 31)
 #define PIPE_HDMI_AUDIO_INT_MASK               (PIPE_HDMI_AUDIO_UNDERRUN | \
                                                PIPE_HDMI_AUDIO_BUFFER_DONE)
 #define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16))
@@ -569,12 +577,27 @@ struct dpst_guardband {
 #define PIPE_PIXEL_MASK                0x00ffffff
 #define PIPE_PIXEL_SHIFT       0
 
+#define FW_BLC_SELF            0x20e0 
+#define FW_BLC_SELF_EN          (1<<15)
+
 #define DSPARB                 0x70030
 #define DSPFW1                 0x70034
+#define DSP_FIFO_SR_WM_MASK            0xFF800000
+#define DSP_FIFO_SR_WM_SHIFT           23
+#define CURSOR_B_FIFO_WM_MASK          0x003F0000
+#define CURSOR_B_FIFO_WM_SHIFT         16
 #define DSPFW2                 0x70038
+#define CURSOR_A_FIFO_WM_MASK          0x3F00
+#define CURSOR_A_FIFO_WM_SHIFT         8
+#define DSP_PLANE_C_FIFO_WM_MASK       0x7F
+#define DSP_PLANE_C_FIFO_WM_SHIFT      0
 #define DSPFW3                 0x7003c
 #define DSPFW4                 0x70050
 #define DSPFW5                 0x70054
+#define DSP_PLANE_B_FIFO_WM1_SHIFT     24
+#define DSP_PLANE_A_FIFO_WM1_SHIFT     16
+#define CURSOR_B_FIFO_WM1_SHIFT                8
+#define CURSOR_FIFO_SR_WM1_SHIFT       0
 #define DSPFW6                 0x70058
 #define DSPCHICKENBIT          0x70400
 #define DSPACNTR               0x70180
@@ -1290,6 +1313,15 @@ No status bits are changed.
 #define SB_N_CB_TUNE_MASK                      PSB_MASK(25, 24)
 #define SB_N_CB_TUNE_SHIFT                     24
 
+/* the bit 14:13 is used to select between the different reference clock for Pipe A/B */
+#define SB_REF_DPLLA           0x8010
+#define SB_REF_DPLLB           0x8030
+#define        REF_CLK_MASK            (0x3 << 13)
+#define REF_CLK_CORE           (0 << 13)
+#define REF_CLK_DPLL           (1 << 13)
+#define REF_CLK_DPLLA          (2 << 13)
+/* For the DPLL B, it will use the reference clk from DPLL A when using (2 << 13) */
+
 #define _SB_REF_A              0x8018
 #define _SB_REF_B              0x8038
 #define SB_REF_SFR(pipe)       _PIPE(pipe, _SB_REF_A, _SB_REF_B)
@@ -1313,6 +1345,7 @@ No status bits are changed.
 
 #define LANE_PLL_MASK          (0x7 << 20)
 #define LANE_PLL_ENABLE                (0x3 << 20)
+#define LANE_PLL_PIPE(p)       (((p) == 0) ? (1 << 21) : (0 << 21))
 
 
 #endif
index 36330cabcea2c6b14f736a16daa54cffd8afe03a..d39b15be76496362570ba6fa4b71eefc9bda883d 100644 (file)
@@ -1141,7 +1141,6 @@ static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
 static int psb_intel_sdvo_mode_valid(struct drm_connector *connector,
                                 struct drm_display_mode *mode)
 {
-       struct drm_psb_private *dev_priv = connector->dev->dev_private;
        struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector);
 
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -1161,11 +1160,6 @@ static int psb_intel_sdvo_mode_valid(struct drm_connector *connector,
                        return MODE_PANEL;
        }
 
-       /* We assume worst case scenario of 32 bpp here, since we don't know */
-       if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) >
-           dev_priv->vram_stolen_size)
-               return MODE_MEM;
-
        return MODE_OK;
 }
 
@@ -2044,8 +2038,7 @@ psb_intel_sdvo_add_hdmi_properties(struct psb_intel_sdvo_connector *connector)
        struct drm_device *dev = connector->base.base.dev;
 
        intel_attach_force_audio_property(&connector->base.base);
-       if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev))
-               intel_attach_broadcast_rgb_property(&connector->base.base);
+       intel_attach_broadcast_rgb_property(&connector->base.base);
        */
 }
 
index 1869586457b1c3f1ba138f52926f3b0855fcd0a8..8652cdf3f03f9d3dcb74d952be4d85d822223d83 100644 (file)
@@ -190,6 +190,9 @@ static void mid_pipe_event_handler(struct drm_device *dev, int pipe)
  */
 static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
 {
+       if (vdc_stat & _PSB_IRQ_ASLE)
+               psb_intel_opregion_asle_intr(dev);
+
        if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
                mid_pipe_event_handler(dev, 0);
 
@@ -199,11 +202,9 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
 
 irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
 {
-       struct drm_device *dev = (struct drm_device *) arg;
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
-
-       uint32_t vdc_stat, dsp_int = 0, sgx_int = 0;
+       struct drm_device *dev = arg;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0;
        int handled = 0;
 
        spin_lock(&dev_priv->irqmask_lock);
@@ -220,6 +221,8 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
 
        if (vdc_stat & _PSB_IRQ_SGX_FLAG)
                sgx_int = 1;
+       if (vdc_stat & _PSB_IRQ_DISP_HOTSYNC)
+               hotplug_int = 1;
 
        vdc_stat &= dev_priv->vdc_irq_mask;
        spin_unlock(&dev_priv->irqmask_lock);
@@ -241,6 +244,13 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
                handled = 1;
        }
 
+       /* Note: this bit has other meanings on some devices, so we will
+          need to address that later if it ever matters */
+       if (hotplug_int && dev_priv->ops->hotplug) {
+               handled = dev_priv->ops->hotplug(dev);
+               REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
+       }
+
        PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
        (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
        DRM_READMEMORYBARRIER();
@@ -273,6 +283,11 @@ void psb_irq_preinstall(struct drm_device *dev)
                dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
        */
 
+       /* Revisit this area - want per device masks ? */
+       if (dev_priv->ops->hotplug)
+               dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC;
+       dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE;
+
        /* This register is safe even if display island is off */
        PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
        spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
@@ -305,18 +320,23 @@ int psb_irq_postinstall(struct drm_device *dev)
        else
                psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
 
+       if (dev_priv->ops->hotplug_enable)
+               dev_priv->ops->hotplug_enable(dev, true);
+
        spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
        return 0;
 }
 
 void psb_irq_uninstall(struct drm_device *dev)
 {
-       struct drm_psb_private *dev_priv =
-           (struct drm_psb_private *) dev->dev_private;
+       struct drm_psb_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
 
        spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
+       if (dev_priv->ops->hotplug_enable)
+               dev_priv->ops->hotplug_enable(dev, false);
+
        PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
 
        if (dev->vblank_enabled[0])
@@ -406,7 +426,7 @@ void psb_irq_turn_off_dpst(struct drm_device *dev)
                psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
 
                pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-               PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE),
+               PSB_WVDC32(pwm_reg & ~PWM_PHASEIN_INT_ENABLE,
                                                        PWM_CONTROL_LOGIC);
                pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
 
index b867aabe6bf3e405b501191f88f4da1c90410136..7ff8bb2bdc23371f7023b821604117f9c61a20a3 100644 (file)
@@ -29,7 +29,7 @@ static void psb_lid_timer_func(unsigned long data)
        struct drm_device *dev = (struct drm_device *)dev_priv->dev;
        struct timer_list *lid_timer = &dev_priv->lid_timer;
        unsigned long irq_flags;
-       u32 *lid_state = dev_priv->lid_state;
+       u32 __iomem *lid_state = dev_priv->opregion.lid_state;
        u32 pp_status;
 
        if (readl(lid_state) == dev_priv->lid_last_state)
index 2c8a60c3b98eacdbeac6673e75f763dff8e065da..f920fb5e42b63846e3d8b7b782b492e547e18eef 100644 (file)
@@ -129,6 +129,7 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
        if (buf_priv->currently_mapped == I810_BUF_MAPPED)
                return -EINVAL;
 
+       /* This is all entirely broken */
        down_write(&current->mm->mmap_sem);
        old_fops = file_priv->filp->f_op;
        file_priv->filp->f_op = &i810_buffer_fops;
@@ -157,11 +158,8 @@ static int i810_unmap_buffer(struct drm_buf *buf)
        if (buf_priv->currently_mapped != I810_BUF_MAPPED)
                return -EINVAL;
 
-       down_write(&current->mm->mmap_sem);
-       retcode = do_munmap(current->mm,
-                           (unsigned long)buf_priv->virtual,
+       retcode = vm_munmap((unsigned long)buf_priv->virtual,
                            (size_t) buf->total);
-       up_write(&current->mm->mmap_sem);
 
        buf_priv->currently_mapped = I810_BUF_UNMAPPED;
        buf_priv->virtual = NULL;
index ce7fc77678b4ce00e6eae112166af5773c44bb0a..8b8bbc70f86b31e3ff78a7944f29b445afd2194f 100644 (file)
@@ -11,7 +11,9 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
          i915_gem_evict.o \
          i915_gem_execbuffer.o \
          i915_gem_gtt.o \
+         i915_gem_stolen.o \
          i915_gem_tiling.o \
+         i915_sysfs.o \
          i915_trace_points.o \
          intel_display.o \
          intel_crt.o \
@@ -22,6 +24,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
          intel_sdvo.o \
          intel_modes.o \
          intel_panel.o \
+         intel_pm.o \
          intel_i2c.o \
          intel_fb.o \
          intel_tv.o \
index fdb7ccefffbdfc77a1dc7328c2ae727e371a7bad..950f72a0d729fcd653746501b78dd27fdcd58286 100644 (file)
@@ -47,7 +47,6 @@ enum {
        FLUSHING_LIST,
        INACTIVE_LIST,
        PINNED_LIST,
-       DEFERRED_FREE_LIST,
 };
 
 static const char *yesno(int v)
@@ -178,18 +177,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
                seq_printf(m, "Inactive:\n");
                head = &dev_priv->mm.inactive_list;
                break;
-       case PINNED_LIST:
-               seq_printf(m, "Pinned:\n");
-               head = &dev_priv->mm.pinned_list;
-               break;
        case FLUSHING_LIST:
                seq_printf(m, "Flushing:\n");
                head = &dev_priv->mm.flushing_list;
                break;
-       case DEFERRED_FREE_LIST:
-               seq_printf(m, "Deferred free:\n");
-               head = &dev_priv->mm.deferred_free_list;
-               break;
        default:
                mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
@@ -251,21 +242,11 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
        seq_printf(m, "  %u [%u] active objects, %zu [%zu] bytes\n",
                   count, mappable_count, size, mappable_size);
 
-       size = count = mappable_size = mappable_count = 0;
-       count_objects(&dev_priv->mm.pinned_list, mm_list);
-       seq_printf(m, "  %u [%u] pinned objects, %zu [%zu] bytes\n",
-                  count, mappable_count, size, mappable_size);
-
        size = count = mappable_size = mappable_count = 0;
        count_objects(&dev_priv->mm.inactive_list, mm_list);
        seq_printf(m, "  %u [%u] inactive objects, %zu [%zu] bytes\n",
                   count, mappable_count, size, mappable_size);
 
-       size = count = mappable_size = mappable_count = 0;
-       count_objects(&dev_priv->mm.deferred_free_list, mm_list);
-       seq_printf(m, "  %u [%u] freed objects, %zu [%zu] bytes\n",
-                  count, mappable_count, size, mappable_size);
-
        size = count = mappable_size = mappable_count = 0;
        list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
                if (obj->fault_mappable) {
@@ -294,6 +275,7 @@ static int i915_gem_gtt_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;
+       uintptr_t list = (uintptr_t) node->info_ent->data;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
        size_t total_obj_size, total_gtt_size;
@@ -305,6 +287,9 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)
 
        total_obj_size = total_gtt_size = count = 0;
        list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+               if (list == PINNED_LIST && obj->pin_count == 0)
+                       continue;
+
                seq_printf(m, "   ");
                describe_obj(m, obj);
                seq_printf(m, "\n");
@@ -321,7 +306,6 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)
        return 0;
 }
 
-
 static int i915_gem_pageflip_info(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -430,10 +414,6 @@ static void i915_ring_seqno_info(struct seq_file *m,
        if (ring->get_seqno) {
                seq_printf(m, "Current sequence (%s): %d\n",
                           ring->name, ring->get_seqno(ring));
-               seq_printf(m, "Waiter sequence (%s):  %d\n",
-                          ring->name, ring->waiting_seqno);
-               seq_printf(m, "IRQ sequence (%s):     %d\n",
-                          ring->name, ring->irq_seqno);
        }
 }
 
@@ -468,7 +448,45 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
        if (ret)
                return ret;
 
-       if (!HAS_PCH_SPLIT(dev)) {
+       if (IS_VALLEYVIEW(dev)) {
+               seq_printf(m, "Display IER:\t%08x\n",
+                          I915_READ(VLV_IER));
+               seq_printf(m, "Display IIR:\t%08x\n",
+                          I915_READ(VLV_IIR));
+               seq_printf(m, "Display IIR_RW:\t%08x\n",
+                          I915_READ(VLV_IIR_RW));
+               seq_printf(m, "Display IMR:\t%08x\n",
+                          I915_READ(VLV_IMR));
+               for_each_pipe(pipe)
+                       seq_printf(m, "Pipe %c stat:\t%08x\n",
+                                  pipe_name(pipe),
+                                  I915_READ(PIPESTAT(pipe)));
+
+               seq_printf(m, "Master IER:\t%08x\n",
+                          I915_READ(VLV_MASTER_IER));
+
+               seq_printf(m, "Render IER:\t%08x\n",
+                          I915_READ(GTIER));
+               seq_printf(m, "Render IIR:\t%08x\n",
+                          I915_READ(GTIIR));
+               seq_printf(m, "Render IMR:\t%08x\n",
+                          I915_READ(GTIMR));
+
+               seq_printf(m, "PM IER:\t\t%08x\n",
+                          I915_READ(GEN6_PMIER));
+               seq_printf(m, "PM IIR:\t\t%08x\n",
+                          I915_READ(GEN6_PMIIR));
+               seq_printf(m, "PM IMR:\t\t%08x\n",
+                          I915_READ(GEN6_PMIMR));
+
+               seq_printf(m, "Port hotplug:\t%08x\n",
+                          I915_READ(PORT_HOTPLUG_EN));
+               seq_printf(m, "DPFLIPSTAT:\t%08x\n",
+                          I915_READ(VLV_DPFLIPSTAT));
+               seq_printf(m, "DPINVGTT:\t%08x\n",
+                          I915_READ(DPINVGTT));
+
+       } else if (!HAS_PCH_SPLIT(dev)) {
                seq_printf(m, "Interrupt enable:    %08x\n",
                           I915_READ(IER));
                seq_printf(m, "Interrupt identity:  %08x\n",
@@ -564,69 +582,6 @@ static int i915_hws_info(struct seq_file *m, void *data)
        return 0;
 }
 
-static int i915_ringbuffer_data(struct seq_file *m, void *data)
-{
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_device *dev = node->minor->dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct intel_ring_buffer *ring;
-       int ret;
-
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               return ret;
-
-       ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
-       if (!ring->obj) {
-               seq_printf(m, "No ringbuffer setup\n");
-       } else {
-               const u8 __iomem *virt = ring->virtual_start;
-               uint32_t off;
-
-               for (off = 0; off < ring->size; off += 4) {
-                       uint32_t *ptr = (uint32_t *)(virt + off);
-                       seq_printf(m, "%08x :  %08x\n", off, *ptr);
-               }
-       }
-       mutex_unlock(&dev->struct_mutex);
-
-       return 0;
-}
-
-static int i915_ringbuffer_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;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct intel_ring_buffer *ring;
-       int ret;
-
-       ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
-       if (ring->size == 0)
-               return 0;
-
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               return ret;
-
-       seq_printf(m, "Ring %s:\n", ring->name);
-       seq_printf(m, "  Head :    %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR);
-       seq_printf(m, "  Tail :    %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR);
-       seq_printf(m, "  Size :    %08x\n", ring->size);
-       seq_printf(m, "  Active :  %08x\n", intel_ring_get_active_head(ring));
-       seq_printf(m, "  NOPID :   %08x\n", I915_READ_NOPID(ring));
-       if (IS_GEN6(dev) || IS_GEN7(dev)) {
-               seq_printf(m, "  Sync 0 :   %08x\n", I915_READ_SYNC_0(ring));
-               seq_printf(m, "  Sync 1 :   %08x\n", I915_READ_SYNC_1(ring));
-       }
-       seq_printf(m, "  Control : %08x\n", I915_READ_CTL(ring));
-       seq_printf(m, "  Start :   %08x\n", I915_READ_START(ring));
-
-       mutex_unlock(&dev->struct_mutex);
-
-       return 0;
-}
-
 static const char *ring_str(int ring)
 {
        switch (ring) {
@@ -704,6 +659,7 @@ static void i915_ring_error_state(struct seq_file *m,
                                  struct drm_i915_error_state *error,
                                  unsigned ring)
 {
+       BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
        seq_printf(m, "%s command stream:\n", ring_str(ring));
        seq_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
        seq_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
@@ -718,8 +674,8 @@ static void i915_ring_error_state(struct seq_file *m,
        if (INTEL_INFO(dev)->gen >= 4)
                seq_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
        seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
+       seq_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
        if (INTEL_INFO(dev)->gen >= 6) {
-               seq_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
                seq_printf(m, "  FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
                seq_printf(m, "  SYNC_0: 0x%08x\n",
                           error->semaphore_mboxes[ring][0]);
@@ -727,31 +683,35 @@ static void i915_ring_error_state(struct seq_file *m,
                           error->semaphore_mboxes[ring][1]);
        }
        seq_printf(m, "  seqno: 0x%08x\n", error->seqno[ring]);
+       seq_printf(m, "  waiting: %s\n", yesno(error->waiting[ring]));
        seq_printf(m, "  ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
        seq_printf(m, "  ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
 }
 
+struct i915_error_state_file_priv {
+       struct drm_device *dev;
+       struct drm_i915_error_state *error;
+};
+
 static int i915_error_state(struct seq_file *m, void *unused)
 {
-       struct drm_info_node *node = (struct drm_info_node *) m->private;
-       struct drm_device *dev = node->minor->dev;
+       struct i915_error_state_file_priv *error_priv = m->private;
+       struct drm_device *dev = error_priv->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_error_state *error;
-       unsigned long flags;
+       struct drm_i915_error_state *error = error_priv->error;
        int i, j, page, offset, elt;
 
-       spin_lock_irqsave(&dev_priv->error_lock, flags);
-       if (!dev_priv->first_error) {
+       if (!error) {
                seq_printf(m, "no error state collected\n");
-               goto out;
+               return 0;
        }
 
-       error = dev_priv->first_error;
 
        seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
                   error->time.tv_usec);
        seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
        seq_printf(m, "EIR: 0x%08x\n", error->eir);
+       seq_printf(m, "IER: 0x%08x\n", error->ier);
        seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
 
        for (i = 0; i < dev_priv->num_fence_regs; i++)
@@ -828,12 +788,71 @@ static int i915_error_state(struct seq_file *m, void *unused)
        if (error->display)
                intel_display_print_error_state(m, dev, error->display);
 
-out:
+       return 0;
+}
+
+static ssize_t
+i915_error_state_write(struct file *filp,
+                      const char __user *ubuf,
+                      size_t cnt,
+                      loff_t *ppos)
+{
+       struct seq_file *m = filp->private_data;
+       struct i915_error_state_file_priv *error_priv = m->private;
+       struct drm_device *dev = error_priv->dev;
+
+       DRM_DEBUG_DRIVER("Resetting error state\n");
+
+       mutex_lock(&dev->struct_mutex);
+       i915_destroy_error_state(dev);
+       mutex_unlock(&dev->struct_mutex);
+
+       return cnt;
+}
+
+static int i915_error_state_open(struct inode *inode, struct file *file)
+{
+       struct drm_device *dev = inode->i_private;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct i915_error_state_file_priv *error_priv;
+       unsigned long flags;
+
+       error_priv = kzalloc(sizeof(*error_priv), GFP_KERNEL);
+       if (!error_priv)
+               return -ENOMEM;
+
+       error_priv->dev = dev;
+
+       spin_lock_irqsave(&dev_priv->error_lock, flags);
+       error_priv->error = dev_priv->first_error;
+       if (error_priv->error)
+               kref_get(&error_priv->error->ref);
        spin_unlock_irqrestore(&dev_priv->error_lock, flags);
 
-       return 0;
+       return single_open(file, i915_error_state, error_priv);
+}
+
+static int i915_error_state_release(struct inode *inode, struct file *file)
+{
+       struct seq_file *m = file->private_data;
+       struct i915_error_state_file_priv *error_priv = m->private;
+
+       if (error_priv->error)
+               kref_put(&error_priv->error->ref, i915_error_state_free);
+       kfree(error_priv);
+
+       return single_release(inode, file);
 }
 
+static const struct file_operations i915_error_state_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_error_state_open,
+       .read = seq_read,
+       .write = i915_error_state_write,
+       .llseek = default_llseek,
+       .release = i915_error_state_release,
+};
+
 static int i915_rstdby_delays(struct seq_file *m, void *unused)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -1132,6 +1151,17 @@ static int gen6_drpc_info(struct seq_file *m)
 
        seq_printf(m, "Core Power Down: %s\n",
                   yesno(gt_core_status & GEN6_CORE_CPD_STATE_MASK));
+
+       /* Not exactly sure what this is */
+       seq_printf(m, "RC6 \"Locked to RPn\" residency since boot: %u\n",
+                  I915_READ(GEN6_GT_GFX_RC6_LOCKED));
+       seq_printf(m, "RC6 residency since boot: %u\n",
+                  I915_READ(GEN6_GT_GFX_RC6));
+       seq_printf(m, "RC6+ residency since boot: %u\n",
+                  I915_READ(GEN6_GT_GFX_RC6p));
+       seq_printf(m, "RC6++ residency since boot: %u\n",
+                  I915_READ(GEN6_GT_GFX_RC6pp));
+
        return 0;
 }
 
@@ -1224,6 +1254,9 @@ static int i915_emon_status(struct seq_file *m, void *unused)
        unsigned long temp, chipset, gfx;
        int ret;
 
+       if (!IS_GEN5(dev))
+               return -ENODEV;
+
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
@@ -1303,17 +1336,25 @@ static int i915_opregion(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_opregion *opregion = &dev_priv->opregion;
+       void *data = kmalloc(OPREGION_SIZE, GFP_KERNEL);
        int ret;
 
+       if (data == NULL)
+               return -ENOMEM;
+
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
-               return ret;
+               goto out;
 
-       if (opregion->header)
-               seq_write(m, opregion->header, OPREGION_SIZE);
+       if (opregion->header) {
+               memcpy_fromio(data, opregion->header, OPREGION_SIZE);
+               seq_write(m, data, OPREGION_SIZE);
+       }
 
        mutex_unlock(&dev->struct_mutex);
 
+out:
+       kfree(data);
        return 0;
 }
 
@@ -1502,11 +1543,50 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
        return 0;
 }
 
-static int
-i915_debugfs_common_open(struct inode *inode,
-                        struct file *filp)
+static int i915_dpio_info(struct seq_file *m, void *data)
 {
-       filp->private_data = inode->i_private;
+       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;
+
+
+       if (!IS_VALLEYVIEW(dev)) {
+               seq_printf(m, "unsupported\n");
+               return 0;
+       }
+
+       ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+       if (ret)
+               return ret;
+
+       seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
+
+       seq_printf(m, "DPIO_DIV_A: 0x%08x\n",
+                  intel_dpio_read(dev_priv, _DPIO_DIV_A));
+       seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
+                  intel_dpio_read(dev_priv, _DPIO_DIV_B));
+
+       seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
+                  intel_dpio_read(dev_priv, _DPIO_REFSFR_A));
+       seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
+                  intel_dpio_read(dev_priv, _DPIO_REFSFR_B));
+
+       seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
+                  intel_dpio_read(dev_priv, _DPIO_CORE_CLK_A));
+       seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
+                  intel_dpio_read(dev_priv, _DPIO_CORE_CLK_B));
+
+       seq_printf(m, "DPIO_LFP_COEFF_A: 0x%08x\n",
+                  intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_A));
+       seq_printf(m, "DPIO_LFP_COEFF_B: 0x%08x\n",
+                  intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_B));
+
+       seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
+                  intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
+
+       mutex_unlock(&dev->mode_config.mutex);
+
        return 0;
 }
 
@@ -1560,12 +1640,71 @@ i915_wedged_write(struct file *filp,
 
 static const struct file_operations i915_wedged_fops = {
        .owner = THIS_MODULE,
-       .open = i915_debugfs_common_open,
+       .open = simple_open,
        .read = i915_wedged_read,
        .write = i915_wedged_write,
        .llseek = default_llseek,
 };
 
+static ssize_t
+i915_ring_stop_read(struct file *filp,
+                   char __user *ubuf,
+                   size_t max,
+                   loff_t *ppos)
+{
+       struct drm_device *dev = filp->private_data;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       char buf[20];
+       int len;
+
+       len = snprintf(buf, sizeof(buf),
+                      "0x%08x\n", dev_priv->stop_rings);
+
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+
+       return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+}
+
+static ssize_t
+i915_ring_stop_write(struct file *filp,
+                    const char __user *ubuf,
+                    size_t cnt,
+                    loff_t *ppos)
+{
+       struct drm_device *dev = filp->private_data;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       char buf[20];
+       int val = 0;
+
+       if (cnt > 0) {
+               if (cnt > sizeof(buf) - 1)
+                       return -EINVAL;
+
+               if (copy_from_user(buf, ubuf, cnt))
+                       return -EFAULT;
+               buf[cnt] = 0;
+
+               val = simple_strtoul(buf, NULL, 0);
+       }
+
+       DRM_DEBUG_DRIVER("Stopping rings 0x%08x\n", val);
+
+       mutex_lock(&dev->struct_mutex);
+       dev_priv->stop_rings = val;
+       mutex_unlock(&dev->struct_mutex);
+
+       return cnt;
+}
+
+static const struct file_operations i915_ring_stop_fops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .read = i915_ring_stop_read,
+       .write = i915_ring_stop_write,
+       .llseek = default_llseek,
+};
+
 static ssize_t
 i915_max_freq_read(struct file *filp,
                   char __user *ubuf,
@@ -1622,7 +1761,7 @@ i915_max_freq_write(struct file *filp,
 
 static const struct file_operations i915_max_freq_fops = {
        .owner = THIS_MODULE,
-       .open = i915_debugfs_common_open,
+       .open = simple_open,
        .read = i915_max_freq_read,
        .write = i915_max_freq_write,
        .llseek = default_llseek,
@@ -1693,7 +1832,7 @@ i915_cache_sharing_write(struct file *filp,
 
 static const struct file_operations i915_cache_sharing_fops = {
        .owner = THIS_MODULE,
-       .open = i915_debugfs_common_open,
+       .open = simple_open,
        .read = i915_cache_sharing_read,
        .write = i915_cache_sharing_write,
        .llseek = default_llseek,
@@ -1743,7 +1882,7 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-int i915_forcewake_release(struct inode *inode, struct file *file)
+static int i915_forcewake_release(struct inode *inode, struct file *file)
 {
        struct drm_device *dev = inode->i_private;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1808,11 +1947,10 @@ static struct drm_info_list i915_debugfs_list[] = {
        {"i915_capabilities", i915_capabilities, 0},
        {"i915_gem_objects", i915_gem_object_info, 0},
        {"i915_gem_gtt", i915_gem_gtt_info, 0},
+       {"i915_gem_pinned", i915_gem_gtt_info, 0, (void *) PINNED_LIST},
        {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
        {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
        {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
-       {"i915_gem_pinned", i915_gem_object_list_info, 0, (void *) PINNED_LIST},
-       {"i915_gem_deferred_free", i915_gem_object_list_info, 0, (void *) DEFERRED_FREE_LIST},
        {"i915_gem_pageflip", i915_gem_pageflip_info, 0},
        {"i915_gem_request", i915_gem_request_info, 0},
        {"i915_gem_seqno", i915_gem_seqno_info, 0},
@@ -1821,13 +1959,6 @@ static struct drm_info_list i915_debugfs_list[] = {
        {"i915_gem_hws", i915_hws_info, 0, (void *)RCS},
        {"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
        {"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
-       {"i915_ringbuffer_data", i915_ringbuffer_data, 0, (void *)RCS},
-       {"i915_ringbuffer_info", i915_ringbuffer_info, 0, (void *)RCS},
-       {"i915_bsd_ringbuffer_data", i915_ringbuffer_data, 0, (void *)VCS},
-       {"i915_bsd_ringbuffer_info", i915_ringbuffer_info, 0, (void *)VCS},
-       {"i915_blt_ringbuffer_data", i915_ringbuffer_data, 0, (void *)BCS},
-       {"i915_blt_ringbuffer_info", i915_ringbuffer_info, 0, (void *)BCS},
-       {"i915_error_state", i915_error_state, 0},
        {"i915_rstdby_delays", i915_rstdby_delays, 0},
        {"i915_cur_delayinfo", i915_cur_delayinfo, 0},
        {"i915_delayfreq_table", i915_delayfreq_table, 0},
@@ -1844,6 +1975,7 @@ static struct drm_info_list i915_debugfs_list[] = {
        {"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0},
        {"i915_swizzle_info", i915_swizzle_info, 0},
        {"i915_ppgtt_info", i915_ppgtt_info, 0},
+       {"i915_dpio", i915_dpio_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
@@ -1872,6 +2004,17 @@ int i915_debugfs_init(struct drm_minor *minor)
                                  &i915_cache_sharing_fops);
        if (ret)
                return ret;
+       ret = i915_debugfs_create(minor->debugfs_root, minor,
+                                 "i915_ring_stop",
+                                 &i915_ring_stop_fops);
+       if (ret)
+               return ret;
+
+       ret = i915_debugfs_create(minor->debugfs_root, minor,
+                                 "i915_error_state",
+                                 &i915_error_state_fops);
+       if (ret)
+               return ret;
 
        return drm_debugfs_create_files(i915_debugfs_list,
                                        I915_DEBUGFS_ENTRIES,
@@ -1890,6 +2033,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
                                 1, minor);
        drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops,
                                 1, minor);
+       drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops,
+                                1, minor);
 }
 
 #endif /* CONFIG_DEBUG_FS */
index 9341eb8ce93b6624f98ab1bc6680d4a3fb98d5cd..42d91e841629f731957370e07c16cb9214f7c734 100644 (file)
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc_helper.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "i915_trace.h"
-#include "../../../platform/x86/intel_ips.h"
 #include <linux/pci.h>
 #include <linux/vgaarb.h>
 #include <linux/acpi.h>
 #include <linux/pnp.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
-#include <linux/module.h>
 #include <acpi/video.h>
+#include <asm/pat.h>
+
+#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
+
+#define BEGIN_LP_RING(n) \
+       intel_ring_begin(LP_RING(dev_priv), (n))
+
+#define OUT_RING(x) \
+       intel_ring_emit(LP_RING(dev_priv), x)
+
+#define ADVANCE_LP_RING() \
+       intel_ring_advance(LP_RING(dev_priv))
+
+/**
+ * Lock test for when it's just for synchronization of ring access.
+ *
+ * In that case, we don't need to do it when GEM is initialized as nobody else
+ * has access to the ring.
+ */
+#define RING_LOCK_TEST_WITH_RETURN(dev, file) do {                     \
+       if (LP_RING(dev->dev_private)->obj == NULL)                     \
+               LOCK_TEST_WITH_RETURN(dev, file);                       \
+} while (0)
+
+static inline u32
+intel_read_legacy_status_page(struct drm_i915_private *dev_priv, int reg)
+{
+       if (I915_NEED_GFX_HWS(dev_priv->dev))
+               return ioread32(dev_priv->dri1.gfx_hws_cpu_addr + reg);
+       else
+               return intel_read_status_page(LP_RING(dev_priv), reg);
+}
+
+#define READ_HWSP(dev_priv, reg) intel_read_legacy_status_page(dev_priv, reg)
+#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
+#define I915_BREADCRUMB_INDEX          0x21
+
+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;
+
+       if (dev->primary->master) {
+               master_priv = dev->primary->master->driver_priv;
+               if (master_priv->sarea_priv)
+                       master_priv->sarea_priv->last_dispatch =
+                               READ_BREADCRUMB(dev_priv);
+       }
+}
 
 static void i915_write_hws_pga(struct drm_device *dev)
 {
@@ -97,7 +146,7 @@ static void i915_free_hws(struct drm_device *dev)
 
        if (ring->status_page.gfx_addr) {
                ring->status_page.gfx_addr = 0;
-               drm_core_ioremapfree(&dev_priv->hws_map, dev);
+               iounmap(dev_priv->dri1.gfx_hws_cpu_addr);
        }
 
        /* Need to rewrite hardware status page */
@@ -195,7 +244,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
 
        /* Allow hardware batchbuffers unless told otherwise.
         */
-       dev_priv->allow_batchbuffer = 1;
+       dev_priv->dri1.allow_batchbuffer = 1;
 
        return 0;
 }
@@ -207,7 +256,7 @@ static int i915_dma_resume(struct drm_device * dev)
 
        DRM_DEBUG_DRIVER("%s\n", __func__);
 
-       if (ring->map.handle == NULL) {
+       if (ring->virtual_start == NULL) {
                DRM_ERROR("can not ioremap virtual address for"
                          " ring buffer\n");
                return -ENOMEM;
@@ -236,6 +285,9 @@ static int i915_dma_init(struct drm_device *dev, void *data,
        drm_i915_init_t *init = data;
        int retcode = 0;
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
        switch (init->func) {
        case I915_INIT_DMA:
                retcode = i915_initialize(dev, init);
@@ -578,6 +630,9 @@ static int i915_flush_ioctl(struct drm_device *dev, void *data,
 {
        int ret;
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
        RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        mutex_lock(&dev->struct_mutex);
@@ -598,7 +653,10 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
        int ret;
        struct drm_clip_rect *cliprects = NULL;
 
-       if (!dev_priv->allow_batchbuffer) {
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
+       if (!dev_priv->dri1.allow_batchbuffer) {
                DRM_ERROR("Batchbuffer ioctl disabled\n");
                return -EINVAL;
        }
@@ -655,6 +713,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
        DRM_DEBUG_DRIVER("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
                        cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
        RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (cmdbuf->num_cliprects < 0)
@@ -706,11 +767,166 @@ fail_batch_free:
        return ret;
 }
 
+static int i915_emit_irq(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+
+       i915_kernel_lost_context(dev);
+
+       DRM_DEBUG_DRIVER("\n");
+
+       dev_priv->counter++;
+       if (dev_priv->counter > 0x7FFFFFFFUL)
+               dev_priv->counter = 1;
+       if (master_priv->sarea_priv)
+               master_priv->sarea_priv->last_enqueue = dev_priv->counter;
+
+       if (BEGIN_LP_RING(4) == 0) {
+               OUT_RING(MI_STORE_DWORD_INDEX);
+               OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+               OUT_RING(dev_priv->counter);
+               OUT_RING(MI_USER_INTERRUPT);
+               ADVANCE_LP_RING();
+       }
+
+       return dev_priv->counter;
+}
+
+static int i915_wait_irq(struct drm_device * dev, int irq_nr)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+       int ret = 0;
+       struct intel_ring_buffer *ring = LP_RING(dev_priv);
+
+       DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
+                 READ_BREADCRUMB(dev_priv));
+
+       if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
+               if (master_priv->sarea_priv)
+                       master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+               return 0;
+       }
+
+       if (master_priv->sarea_priv)
+               master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+
+       if (ring->irq_get(ring)) {
+               DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ,
+                           READ_BREADCRUMB(dev_priv) >= irq_nr);
+               ring->irq_put(ring);
+       } else if (wait_for(READ_BREADCRUMB(dev_priv) >= irq_nr, 3000))
+               ret = -EBUSY;
+
+       if (ret == -EBUSY) {
+               DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
+                         READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
+       }
+
+       return ret;
+}
+
+/* Needs the lock as it touches the ring.
+ */
+static int i915_irq_emit(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_irq_emit_t *emit = data;
+       int result;
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
+       if (!dev_priv || !LP_RING(dev_priv)->virtual_start) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       mutex_lock(&dev->struct_mutex);
+       result = i915_emit_irq(dev);
+       mutex_unlock(&dev->struct_mutex);
+
+       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/* Doesn't need the hardware lock.
+ */
+static int i915_irq_wait(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_irq_wait_t *irqwait = data;
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       return i915_wait_irq(dev, irqwait->irq_seq);
+}
+
+static int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_vblank_pipe_t *pipe = data;
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
+
+       return 0;
+}
+
+/**
+ * Schedule buffer swap at given vertical blank.
+ */
+static int i915_vblank_swap(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
+{
+       /* The delayed swap mechanism was fundamentally racy, and has been
+        * removed.  The model was that the client requested a delayed flip/swap
+        * from the kernel, then waited for vblank before continuing to perform
+        * rendering.  The problem was that the kernel might wake the client
+        * up before it dispatched the vblank swap (since the lock has to be
+        * held while touching the ringbuffer), in which case the client would
+        * clear and start the next frame before the swap occurred, and
+        * flicker would occur in addition to likely missing the vblank.
+        *
+        * In the absence of this ioctl, userland falls back to a correct path
+        * of waiting for a vblank, then dispatching the swap on its own.
+        * Context switching to userland and back is plenty fast enough for
+        * meeting the requirements of vblank swapping.
+        */
+       return -EINVAL;
+}
+
 static int i915_flip_bufs(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
        int ret;
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
        DRM_DEBUG_DRIVER("%s\n", __func__);
 
        RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
@@ -739,7 +955,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
                value = dev->pdev->irq ? 1 : 0;
                break;
        case I915_PARAM_ALLOW_BATCHBUFFER:
-               value = dev_priv->allow_batchbuffer ? 1 : 0;
+               value = dev_priv->dri1.allow_batchbuffer ? 1 : 0;
                break;
        case I915_PARAM_LAST_DISPATCH:
                value = READ_BREADCRUMB(dev_priv);
@@ -748,7 +964,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
                value = dev->pci_device;
                break;
        case I915_PARAM_HAS_GEM:
-               value = dev_priv->has_gem;
+               value = 1;
                break;
        case I915_PARAM_NUM_FENCES_AVAIL:
                value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
@@ -761,7 +977,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
                break;
        case I915_PARAM_HAS_EXECBUF2:
                /* depends on GEM */
-               value = dev_priv->has_gem;
+               value = 1;
                break;
        case I915_PARAM_HAS_BSD:
                value = HAS_BSD(dev);
@@ -787,6 +1003,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
        case I915_PARAM_HAS_LLC:
                value = HAS_LLC(dev);
                break;
+       case I915_PARAM_HAS_ALIASING_PPGTT:
+               value = dev_priv->mm.aliasing_ppgtt ? 1 : 0;
+               break;
        default:
                DRM_DEBUG_DRIVER("Unknown parameter %d\n",
                                 param->param);
@@ -816,10 +1035,9 @@ static int i915_setparam(struct drm_device *dev, void *data,
        case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
                break;
        case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
-               dev_priv->tex_lru_log_granularity = param->value;
                break;
        case I915_SETPARAM_ALLOW_BATCHBUFFER:
-               dev_priv->allow_batchbuffer = param->value;
+               dev_priv->dri1.allow_batchbuffer = param->value ? 1 : 0;
                break;
        case I915_SETPARAM_NUM_USED_FENCES:
                if (param->value > dev_priv->num_fence_regs ||
@@ -844,6 +1062,9 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
        drm_i915_hws_addr_t *hws = data;
        struct intel_ring_buffer *ring = LP_RING(dev_priv);
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
        if (!I915_NEED_GFX_HWS(dev))
                return -EINVAL;
 
@@ -861,23 +1082,17 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
 
        ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12);
 
-       dev_priv->hws_map.offset = dev->agp->base + hws->addr;
-       dev_priv->hws_map.size = 4*1024;
-       dev_priv->hws_map.type = 0;
-       dev_priv->hws_map.flags = 0;
-       dev_priv->hws_map.mtrr = 0;
-
-       drm_core_ioremap_wc(&dev_priv->hws_map, dev);
-       if (dev_priv->hws_map.handle == NULL) {
+       dev_priv->dri1.gfx_hws_cpu_addr = ioremap_wc(dev->agp->base + hws->addr,
+                                                    4096);
+       if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) {
                i915_dma_cleanup(dev);
                ring->status_page.gfx_addr = 0;
                DRM_ERROR("can not ioremap virtual address for"
                                " G33 hw status page\n");
                return -ENOMEM;
        }
-       ring->status_page.page_addr =
-               (void __force __iomem *)dev_priv->hws_map.handle;
-       memset_io(ring->status_page.page_addr, 0, PAGE_SIZE);
+
+       memset_io(dev_priv->dri1.gfx_hws_cpu_addr, 0, PAGE_SIZE);
        I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
 
        DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
@@ -1013,133 +1228,6 @@ intel_teardown_mchbar(struct drm_device *dev)
                release_resource(&dev_priv->mch_res);
 }
 
-#define PTE_ADDRESS_MASK               0xfffff000
-#define PTE_ADDRESS_MASK_HIGH          0x000000f0 /* i915+ */
-#define PTE_MAPPING_TYPE_UNCACHED      (0 << 1)
-#define PTE_MAPPING_TYPE_DCACHE                (1 << 1) /* i830 only */
-#define PTE_MAPPING_TYPE_CACHED                (3 << 1)
-#define PTE_MAPPING_TYPE_MASK          (3 << 1)
-#define PTE_VALID                      (1 << 0)
-
-/**
- * i915_stolen_to_phys - take an offset into stolen memory and turn it into
- *                       a physical one
- * @dev: drm device
- * @offset: address to translate
- *
- * Some chip functions require allocations from stolen space and need the
- * physical address of the memory in question.
- */
-static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct pci_dev *pdev = dev_priv->bridge_dev;
-       u32 base;
-
-#if 0
-       /* On the machines I have tested the Graphics Base of Stolen Memory
-        * is unreliable, so compute the base by subtracting the stolen memory
-        * from the Top of Low Usable DRAM which is where the BIOS places
-        * the graphics stolen memory.
-        */
-       if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
-               /* top 32bits are reserved = 0 */
-               pci_read_config_dword(pdev, 0xA4, &base);
-       } else {
-               /* XXX presume 8xx is the same as i915 */
-               pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base);
-       }
-#else
-       if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
-               u16 val;
-               pci_read_config_word(pdev, 0xb0, &val);
-               base = val >> 4 << 20;
-       } else {
-               u8 val;
-               pci_read_config_byte(pdev, 0x9c, &val);
-               base = val >> 3 << 27;
-       }
-       base -= dev_priv->mm.gtt->stolen_size;
-#endif
-
-       return base + offset;
-}
-
-static void i915_warn_stolen(struct drm_device *dev)
-{
-       DRM_ERROR("not enough stolen space for compressed buffer, disabling\n");
-       DRM_ERROR("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n");
-}
-
-static void i915_setup_compression(struct drm_device *dev, int size)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
-       unsigned long cfb_base;
-       unsigned long ll_base = 0;
-
-       /* Just in case the BIOS is doing something questionable. */
-       intel_disable_fbc(dev);
-
-       compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
-       if (compressed_fb)
-               compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
-       if (!compressed_fb)
-               goto err;
-
-       cfb_base = i915_stolen_to_phys(dev, compressed_fb->start);
-       if (!cfb_base)
-               goto err_fb;
-
-       if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) {
-               compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
-                                                   4096, 4096, 0);
-               if (compressed_llb)
-                       compressed_llb = drm_mm_get_block(compressed_llb,
-                                                         4096, 4096);
-               if (!compressed_llb)
-                       goto err_fb;
-
-               ll_base = i915_stolen_to_phys(dev, compressed_llb->start);
-               if (!ll_base)
-                       goto err_llb;
-       }
-
-       dev_priv->cfb_size = size;
-
-       dev_priv->compressed_fb = compressed_fb;
-       if (HAS_PCH_SPLIT(dev))
-               I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
-       else if (IS_GM45(dev)) {
-               I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
-       } else {
-               I915_WRITE(FBC_CFB_BASE, cfb_base);
-               I915_WRITE(FBC_LL_BASE, ll_base);
-               dev_priv->compressed_llb = compressed_llb;
-       }
-
-       DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n",
-                     cfb_base, ll_base, size >> 20);
-       return;
-
-err_llb:
-       drm_mm_put_block(compressed_llb);
-err_fb:
-       drm_mm_put_block(compressed_fb);
-err:
-       dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
-       i915_warn_stolen(dev);
-}
-
-static void i915_cleanup_compression(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       drm_mm_put_block(dev_priv->compressed_fb);
-       if (dev_priv->compressed_llb)
-               drm_mm_put_block(dev_priv->compressed_llb);
-}
-
 /* true = enable decode, false = disable decoder */
 static unsigned int i915_vga_set_decode(void *cookie, bool state)
 {
@@ -1158,14 +1246,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
        struct drm_device *dev = pci_get_drvdata(pdev);
        pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
        if (state == VGA_SWITCHEROO_ON) {
-               printk(KERN_INFO "i915: switched on\n");
+               pr_info("switched on\n");
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
                /* i915 resume handler doesn't set to D0 */
                pci_set_power_state(dev->pdev, PCI_D0);
                i915_resume(dev);
                dev->switch_power_state = DRM_SWITCH_POWER_ON;
        } else {
-               printk(KERN_ERR "i915: switched off\n");
+               pr_err("switched off\n");
                dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
                i915_suspend(dev, pmm);
                dev->switch_power_state = DRM_SWITCH_POWER_OFF;
@@ -1183,71 +1271,11 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
        return can_switch;
 }
 
-static int i915_load_gem_init(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long prealloc_size, gtt_size, mappable_size;
-       int ret;
-
-       prealloc_size = dev_priv->mm.gtt->stolen_size;
-       gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
-       mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
-
-       /* Basic memrange allocator for stolen space */
-       drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
-
-       mutex_lock(&dev->struct_mutex);
-       if (i915_enable_ppgtt && HAS_ALIASING_PPGTT(dev)) {
-               /* PPGTT pdes are stolen from global gtt ptes, so shrink the
-                * aperture accordingly when using aliasing ppgtt. */
-               gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
-               /* For paranoia keep the guard page in between. */
-               gtt_size -= PAGE_SIZE;
-
-               i915_gem_do_init(dev, 0, mappable_size, gtt_size);
-
-               ret = i915_gem_init_aliasing_ppgtt(dev);
-               if (ret)
-                       return ret;
-       } else {
-               /* Let GEM Manage all of the aperture.
-                *
-                * However, leave one page at the end still bound to the scratch
-                * page.  There are a number of places where the hardware
-                * apparently prefetches past the end of the object, and we've
-                * seen multiple hangs with the GPU head pointer stuck in a
-                * batchbuffer bound at the last page of the aperture.  One page
-                * should be enough to keep any prefetching inside of the
-                * aperture.
-                */
-               i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE);
-       }
-
-       ret = i915_gem_init_hw(dev);
-       mutex_unlock(&dev->struct_mutex);
-       if (ret) {
-               i915_gem_cleanup_aliasing_ppgtt(dev);
-               return ret;
-       }
-
-       /* Try to set up FBC with a reasonable compressed buffer size */
-       if (I915_HAS_FBC(dev) && i915_powersave) {
-               int cfb_size;
-
-               /* Leave 1M for line length buffer & misc. */
-
-               /* Try to get a 32M buffer... */
-               if (prealloc_size > (36*1024*1024))
-                       cfb_size = 32*1024*1024;
-               else /* fall back to 7/8 of the stolen space */
-                       cfb_size = prealloc_size * 7 / 8;
-               i915_setup_compression(dev, cfb_size);
-       }
-
-       /* Allow hardware batchbuffers unless told otherwise. */
-       dev_priv->allow_batchbuffer = 1;
-       return 0;
-}
+static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
+       .set_gpu_state = i915_switcheroo_set_state,
+       .reprobe = NULL,
+       .can_switch = i915_switcheroo_can_switch,
+};
 
 static int i915_load_modeset_init(struct drm_device *dev)
 {
@@ -1271,22 +1299,22 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
        intel_register_dsm_handler();
 
-       ret = vga_switcheroo_register_client(dev->pdev,
-                                            i915_switcheroo_set_state,
-                                            NULL,
-                                            i915_switcheroo_can_switch);
+       ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops);
        if (ret)
                goto cleanup_vga_client;
 
-       /* IIR "flip pending" bit means done if this bit is set */
-       if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
-               dev_priv->flip_pending_is_done = true;
+       /* Initialise stolen first so that we may reserve preallocated
+        * objects for the BIOS to KMS transition.
+        */
+       ret = i915_gem_init_stolen(dev);
+       if (ret)
+               goto cleanup_vga_switcheroo;
 
        intel_modeset_init(dev);
 
-       ret = i915_load_gem_init(dev);
+       ret = i915_gem_init(dev);
        if (ret)
-               goto cleanup_vga_switcheroo;
+               goto cleanup_gem_stolen;
 
        intel_modeset_gem_init(dev);
 
@@ -1316,6 +1344,8 @@ cleanup_gem:
        i915_gem_cleanup_ringbuffer(dev);
        mutex_unlock(&dev->struct_mutex);
        i915_gem_cleanup_aliasing_ppgtt(dev);
+cleanup_gem_stolen:
+       i915_gem_cleanup_stolen(dev);
 cleanup_vga_switcheroo:
        vga_switcheroo_unregister_client(dev->pdev);
 cleanup_vga_client:
@@ -1348,569 +1378,26 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
        master->driver_priv = NULL;
 }
 
-static void i915_pineview_get_mem_freq(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       u32 tmp;
-
-       tmp = I915_READ(CLKCFG);
-
-       switch (tmp & CLKCFG_FSB_MASK) {
-       case CLKCFG_FSB_533:
-               dev_priv->fsb_freq = 533; /* 133*4 */
-               break;
-       case CLKCFG_FSB_800:
-               dev_priv->fsb_freq = 800; /* 200*4 */
-               break;
-       case CLKCFG_FSB_667:
-               dev_priv->fsb_freq =  667; /* 167*4 */
-               break;
-       case CLKCFG_FSB_400:
-               dev_priv->fsb_freq = 400; /* 100*4 */
-               break;
-       }
-
-       switch (tmp & CLKCFG_MEM_MASK) {
-       case CLKCFG_MEM_533:
-               dev_priv->mem_freq = 533;
-               break;
-       case CLKCFG_MEM_667:
-               dev_priv->mem_freq = 667;
-               break;
-       case CLKCFG_MEM_800:
-               dev_priv->mem_freq = 800;
-               break;
-       }
-
-       /* detect pineview DDR3 setting */
-       tmp = I915_READ(CSHRDDR3CTL);
-       dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
-}
-
-static void i915_ironlake_get_mem_freq(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       u16 ddrpll, csipll;
-
-       ddrpll = I915_READ16(DDRMPLL1);
-       csipll = I915_READ16(CSIPLL0);
-
-       switch (ddrpll & 0xff) {
-       case 0xc:
-               dev_priv->mem_freq = 800;
-               break;
-       case 0x10:
-               dev_priv->mem_freq = 1066;
-               break;
-       case 0x14:
-               dev_priv->mem_freq = 1333;
-               break;
-       case 0x18:
-               dev_priv->mem_freq = 1600;
-               break;
-       default:
-               DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n",
-                                ddrpll & 0xff);
-               dev_priv->mem_freq = 0;
-               break;
-       }
-
-       dev_priv->r_t = dev_priv->mem_freq;
-
-       switch (csipll & 0x3ff) {
-       case 0x00c:
-               dev_priv->fsb_freq = 3200;
-               break;
-       case 0x00e:
-               dev_priv->fsb_freq = 3733;
-               break;
-       case 0x010:
-               dev_priv->fsb_freq = 4266;
-               break;
-       case 0x012:
-               dev_priv->fsb_freq = 4800;
-               break;
-       case 0x014:
-               dev_priv->fsb_freq = 5333;
-               break;
-       case 0x016:
-               dev_priv->fsb_freq = 5866;
-               break;
-       case 0x018:
-               dev_priv->fsb_freq = 6400;
-               break;
-       default:
-               DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n",
-                                csipll & 0x3ff);
-               dev_priv->fsb_freq = 0;
-               break;
-       }
-
-       if (dev_priv->fsb_freq == 3200) {
-               dev_priv->c_m = 0;
-       } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) {
-               dev_priv->c_m = 1;
-       } else {
-               dev_priv->c_m = 2;
-       }
-}
-
-static const struct cparams {
-       u16 i;
-       u16 t;
-       u16 m;
-       u16 c;
-} cparams[] = {
-       { 1, 1333, 301, 28664 },
-       { 1, 1066, 294, 24460 },
-       { 1, 800, 294, 25192 },
-       { 0, 1333, 276, 27605 },
-       { 0, 1066, 276, 27605 },
-       { 0, 800, 231, 23784 },
-};
-
-unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
-{
-       u64 total_count, diff, ret;
-       u32 count1, count2, count3, m = 0, c = 0;
-       unsigned long now = jiffies_to_msecs(jiffies), diff1;
-       int i;
-
-       diff1 = now - dev_priv->last_time1;
-
-       /* Prevent division-by-zero if we are asking too fast.
-        * Also, we don't get interesting results if we are polling
-        * faster than once in 10ms, so just return the saved value
-        * in such cases.
-        */
-       if (diff1 <= 10)
-               return dev_priv->chipset_power;
-
-       count1 = I915_READ(DMIEC);
-       count2 = I915_READ(DDREC);
-       count3 = I915_READ(CSIEC);
-
-       total_count = count1 + count2 + count3;
-
-       /* FIXME: handle per-counter overflow */
-       if (total_count < dev_priv->last_count1) {
-               diff = ~0UL - dev_priv->last_count1;
-               diff += total_count;
-       } else {
-               diff = total_count - dev_priv->last_count1;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(cparams); i++) {
-               if (cparams[i].i == dev_priv->c_m &&
-                   cparams[i].t == dev_priv->r_t) {
-                       m = cparams[i].m;
-                       c = cparams[i].c;
-                       break;
-               }
-       }
-
-       diff = div_u64(diff, diff1);
-       ret = ((m * diff) + c);
-       ret = div_u64(ret, 10);
-
-       dev_priv->last_count1 = total_count;
-       dev_priv->last_time1 = now;
-
-       dev_priv->chipset_power = ret;
-
-       return ret;
-}
-
-unsigned long i915_mch_val(struct drm_i915_private *dev_priv)
-{
-       unsigned long m, x, b;
-       u32 tsfs;
-
-       tsfs = I915_READ(TSFS);
-
-       m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT);
-       x = I915_READ8(TR1);
-
-       b = tsfs & TSFS_INTR_MASK;
-
-       return ((m * x) / 127) - b;
-}
-
-static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
-{
-       static const struct v_table {
-               u16 vd; /* in .1 mil */
-               u16 vm; /* in .1 mil */
-       } v_table[] = {
-               { 0, 0, },
-               { 375, 0, },
-               { 500, 0, },
-               { 625, 0, },
-               { 750, 0, },
-               { 875, 0, },
-               { 1000, 0, },
-               { 1125, 0, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4125, 3000, },
-               { 4250, 3125, },
-               { 4375, 3250, },
-               { 4500, 3375, },
-               { 4625, 3500, },
-               { 4750, 3625, },
-               { 4875, 3750, },
-               { 5000, 3875, },
-               { 5125, 4000, },
-               { 5250, 4125, },
-               { 5375, 4250, },
-               { 5500, 4375, },
-               { 5625, 4500, },
-               { 5750, 4625, },
-               { 5875, 4750, },
-               { 6000, 4875, },
-               { 6125, 5000, },
-               { 6250, 5125, },
-               { 6375, 5250, },
-               { 6500, 5375, },
-               { 6625, 5500, },
-               { 6750, 5625, },
-               { 6875, 5750, },
-               { 7000, 5875, },
-               { 7125, 6000, },
-               { 7250, 6125, },
-               { 7375, 6250, },
-               { 7500, 6375, },
-               { 7625, 6500, },
-               { 7750, 6625, },
-               { 7875, 6750, },
-               { 8000, 6875, },
-               { 8125, 7000, },
-               { 8250, 7125, },
-               { 8375, 7250, },
-               { 8500, 7375, },
-               { 8625, 7500, },
-               { 8750, 7625, },
-               { 8875, 7750, },
-               { 9000, 7875, },
-               { 9125, 8000, },
-               { 9250, 8125, },
-               { 9375, 8250, },
-               { 9500, 8375, },
-               { 9625, 8500, },
-               { 9750, 8625, },
-               { 9875, 8750, },
-               { 10000, 8875, },
-               { 10125, 9000, },
-               { 10250, 9125, },
-               { 10375, 9250, },
-               { 10500, 9375, },
-               { 10625, 9500, },
-               { 10750, 9625, },
-               { 10875, 9750, },
-               { 11000, 9875, },
-               { 11125, 10000, },
-               { 11250, 10125, },
-               { 11375, 10250, },
-               { 11500, 10375, },
-               { 11625, 10500, },
-               { 11750, 10625, },
-               { 11875, 10750, },
-               { 12000, 10875, },
-               { 12125, 11000, },
-               { 12250, 11125, },
-               { 12375, 11250, },
-               { 12500, 11375, },
-               { 12625, 11500, },
-               { 12750, 11625, },
-               { 12875, 11750, },
-               { 13000, 11875, },
-               { 13125, 12000, },
-               { 13250, 12125, },
-               { 13375, 12250, },
-               { 13500, 12375, },
-               { 13625, 12500, },
-               { 13750, 12625, },
-               { 13875, 12750, },
-               { 14000, 12875, },
-               { 14125, 13000, },
-               { 14250, 13125, },
-               { 14375, 13250, },
-               { 14500, 13375, },
-               { 14625, 13500, },
-               { 14750, 13625, },
-               { 14875, 13750, },
-               { 15000, 13875, },
-               { 15125, 14000, },
-               { 15250, 14125, },
-               { 15375, 14250, },
-               { 15500, 14375, },
-               { 15625, 14500, },
-               { 15750, 14625, },
-               { 15875, 14750, },
-               { 16000, 14875, },
-               { 16125, 15000, },
-       };
-       if (dev_priv->info->is_mobile)
-               return v_table[pxvid].vm;
-       else
-               return v_table[pxvid].vd;
-}
-
-void i915_update_gfx_val(struct drm_i915_private *dev_priv)
+static void
+i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base,
+               unsigned long size)
 {
-       struct timespec now, diff1;
-       u64 diff;
-       unsigned long diffms;
-       u32 count;
-
-       getrawmonotonic(&now);
-       diff1 = timespec_sub(now, dev_priv->last_time2);
+       dev_priv->mm.gtt_mtrr = -1;
 
-       /* Don't divide by 0 */
-       diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
-       if (!diffms)
+#if defined(CONFIG_X86_PAT)
+       if (cpu_has_pat)
                return;
+#endif
 
-       count = I915_READ(GFXEC);
-
-       if (count < dev_priv->last_count2) {
-               diff = ~0UL - dev_priv->last_count2;
-               diff += count;
-       } else {
-               diff = count - dev_priv->last_count2;
-       }
-
-       dev_priv->last_count2 = count;
-       dev_priv->last_time2 = now;
-
-       /* More magic constants... */
-       diff = diff * 1181;
-       diff = div_u64(diff, diffms * 10);
-       dev_priv->gfx_power = diff;
-}
-
-unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
-{
-       unsigned long t, corr, state1, corr2, state2;
-       u32 pxvid, ext_v;
-
-       pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
-       pxvid = (pxvid >> 24) & 0x7f;
-       ext_v = pvid_to_extvid(dev_priv, pxvid);
-
-       state1 = ext_v;
-
-       t = i915_mch_val(dev_priv);
-
-       /* Revel in the empirically derived constants */
-
-       /* Correction factor in 1/100000 units */
-       if (t > 80)
-               corr = ((t * 2349) + 135940);
-       else if (t >= 50)
-               corr = ((t * 964) + 29317);
-       else /* < 50 */
-               corr = ((t * 301) + 1004);
-
-       corr = corr * ((150142 * state1) / 10000 - 78642);
-       corr /= 100000;
-       corr2 = (corr * dev_priv->corr);
-
-       state2 = (corr2 * state1) / 10000;
-       state2 /= 100; /* convert to mW */
-
-       i915_update_gfx_val(dev_priv);
-
-       return dev_priv->gfx_power + state2;
-}
-
-/* Global for IPS driver to get at the current i915 device */
-static struct drm_i915_private *i915_mch_dev;
-/*
- * Lock protecting IPS related data structures
- *   - i915_mch_dev
- *   - dev_priv->max_delay
- *   - dev_priv->min_delay
- *   - dev_priv->fmax
- *   - dev_priv->gpu_busy
- */
-static DEFINE_SPINLOCK(mchdev_lock);
-
-/**
- * i915_read_mch_val - return value for IPS use
- *
- * Calculate and return a value for the IPS driver to use when deciding whether
- * we have thermal and power headroom to increase CPU or GPU power budget.
- */
-unsigned long i915_read_mch_val(void)
-{
-       struct drm_i915_private *dev_priv;
-       unsigned long chipset_val, graphics_val, ret = 0;
-
-       spin_lock(&mchdev_lock);
-       if (!i915_mch_dev)
-               goto out_unlock;
-       dev_priv = i915_mch_dev;
-
-       chipset_val = i915_chipset_val(dev_priv);
-       graphics_val = i915_gfx_val(dev_priv);
-
-       ret = chipset_val + graphics_val;
-
-out_unlock:
-       spin_unlock(&mchdev_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(i915_read_mch_val);
-
-/**
- * i915_gpu_raise - raise GPU frequency limit
- *
- * Raise the limit; IPS indicates we have thermal headroom.
- */
-bool i915_gpu_raise(void)
-{
-       struct drm_i915_private *dev_priv;
-       bool ret = true;
-
-       spin_lock(&mchdev_lock);
-       if (!i915_mch_dev) {
-               ret = false;
-               goto out_unlock;
-       }
-       dev_priv = i915_mch_dev;
-
-       if (dev_priv->max_delay > dev_priv->fmax)
-               dev_priv->max_delay--;
-
-out_unlock:
-       spin_unlock(&mchdev_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(i915_gpu_raise);
-
-/**
- * i915_gpu_lower - lower GPU frequency limit
- *
- * IPS indicates we're close to a thermal limit, so throttle back the GPU
- * frequency maximum.
- */
-bool i915_gpu_lower(void)
-{
-       struct drm_i915_private *dev_priv;
-       bool ret = true;
-
-       spin_lock(&mchdev_lock);
-       if (!i915_mch_dev) {
-               ret = false;
-               goto out_unlock;
-       }
-       dev_priv = i915_mch_dev;
-
-       if (dev_priv->max_delay < dev_priv->min_delay)
-               dev_priv->max_delay++;
-
-out_unlock:
-       spin_unlock(&mchdev_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(i915_gpu_lower);
-
-/**
- * i915_gpu_busy - indicate GPU business to IPS
- *
- * Tell the IPS driver whether or not the GPU is busy.
- */
-bool i915_gpu_busy(void)
-{
-       struct drm_i915_private *dev_priv;
-       bool ret = false;
-
-       spin_lock(&mchdev_lock);
-       if (!i915_mch_dev)
-               goto out_unlock;
-       dev_priv = i915_mch_dev;
-
-       ret = dev_priv->busy;
-
-out_unlock:
-       spin_unlock(&mchdev_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(i915_gpu_busy);
-
-/**
- * i915_gpu_turbo_disable - disable graphics turbo
- *
- * Disable graphics turbo by resetting the max frequency and setting the
- * current frequency to the default.
- */
-bool i915_gpu_turbo_disable(void)
-{
-       struct drm_i915_private *dev_priv;
-       bool ret = true;
-
-       spin_lock(&mchdev_lock);
-       if (!i915_mch_dev) {
-               ret = false;
-               goto out_unlock;
-       }
-       dev_priv = i915_mch_dev;
-
-       dev_priv->max_delay = dev_priv->fstart;
-
-       if (!ironlake_set_drps(dev_priv->dev, dev_priv->fstart))
-               ret = false;
-
-out_unlock:
-       spin_unlock(&mchdev_lock);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
-
-/**
- * Tells the intel_ips driver that the i915 driver is now loaded, if
- * IPS got loaded first.
- *
- * This awkward dance is so that neither module has to depend on the
- * other in order for IPS to do the appropriate communication of
- * GPU turbo limits to i915.
- */
-static void
-ips_ping_for_i915_load(void)
-{
-       void (*link)(void);
-
-       link = symbol_get(ips_link_to_i915_driver);
-       if (link) {
-               link();
-               symbol_put(ips_link_to_i915_driver);
+       /* Set up a WC MTRR for non-PAT systems.  This is more common than
+        * one would think, because the kernel disables PAT on first
+        * generation Core chips because WC PAT gets overridden by a UC
+        * MTRR if present.  Even if a UC MTRR isn't present.
+        */
+       dev_priv->mm.gtt_mtrr = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1);
+       if (dev_priv->mm.gtt_mtrr < 0) {
+               DRM_INFO("MTRR allocation failed.  Graphics "
+                        "performance may suffer.\n");
        }
 }
 
@@ -1928,8 +1415,16 @@ ips_ping_for_i915_load(void)
 int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
        struct drm_i915_private *dev_priv;
+       struct intel_device_info *info;
        int ret = 0, mmio_bar;
-       uint32_t agp_size;
+       uint32_t aperture_size;
+
+       info = (struct intel_device_info *) flags;
+
+       /* Refuse to load on gen6+ without kms enabled. */
+       if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
 
        /* i915 has 4 more counters */
        dev->counters += 4;
@@ -1944,7 +1439,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        dev->dev_private = (void *)dev_priv;
        dev_priv->dev = dev;
-       dev_priv->info = (struct intel_device_info *) flags;
+       dev_priv->info = info;
 
        if (i915_get_bridge_dev(dev)) {
                ret = -EIO;
@@ -1983,27 +1478,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto out_rmmap;
        }
 
-       agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
+       aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
 
        dev_priv->mm.gtt_mapping =
-               io_mapping_create_wc(dev->agp->base, agp_size);
+               io_mapping_create_wc(dev->agp->base, aperture_size);
        if (dev_priv->mm.gtt_mapping == NULL) {
                ret = -EIO;
                goto out_rmmap;
        }
 
-       /* Set up a WC MTRR for non-PAT systems.  This is more common than
-        * one would think, because the kernel disables PAT on first
-        * generation Core chips because WC PAT gets overridden by a UC
-        * MTRR if present.  Even if a UC MTRR isn't present.
-        */
-       dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
-                                        agp_size,
-                                        MTRR_TYPE_WRCOMB, 1);
-       if (dev_priv->mm.gtt_mtrr < 0) {
-               DRM_INFO("MTRR allocation failed.  Graphics "
-                        "performance may suffer.\n");
-       }
+       i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size);
 
        /* The i915 workqueue is primarily used for batched retirement of
         * requests (and thus managing bo) once the task has been completed
@@ -2027,9 +1511,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto out_mtrrfree;
        }
 
-       /* enable GEM by default */
-       dev_priv->has_gem = 1;
-
        intel_irq_init(dev);
 
        /* Try to make sure MCHBAR is enabled before poking at it */
@@ -2049,11 +1530,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                        goto out_gem_unload;
        }
 
-       if (IS_PINEVIEW(dev))
-               i915_pineview_get_mem_freq(dev);
-       else if (IS_GEN5(dev))
-               i915_ironlake_get_mem_freq(dev);
-
        /* On the 945G/GM, the chipset reports the MSI capability on the
         * integrated graphics even though the support isn't actually there
         * according to the published specs.  It doesn't appear to function
@@ -2073,7 +1549,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        spin_lock_init(&dev_priv->error_lock);
        spin_lock_init(&dev_priv->rps_lock);
 
-       if (IS_IVYBRIDGE(dev))
+       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
                dev_priv->num_pipe = 3;
        else if (IS_MOBILE(dev) || !IS_GEN2(dev))
                dev_priv->num_pipe = 2;
@@ -2097,6 +1573,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                }
        }
 
+       i915_setup_sysfs(dev);
+
        /* Must be done after probing outputs */
        intel_opregion_init(dev);
        acpi_video_register();
@@ -2104,12 +1582,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
                    (unsigned long) dev);
 
-       spin_lock(&mchdev_lock);
-       i915_mch_dev = dev_priv;
-       dev_priv->mchdev_lock = &mchdev_lock;
-       spin_unlock(&mchdev_lock);
-
-       ips_ping_for_i915_load();
+       if (IS_GEN5(dev))
+               intel_gpu_ips_init(dev_priv);
 
        return 0;
 
@@ -2144,17 +1618,18 @@ int i915_driver_unload(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
-       spin_lock(&mchdev_lock);
-       i915_mch_dev = NULL;
-       spin_unlock(&mchdev_lock);
+       intel_gpu_ips_teardown();
+
+       i915_teardown_sysfs(dev);
 
        if (dev_priv->mm.inactive_shrinker.shrink)
                unregister_shrinker(&dev_priv->mm.inactive_shrinker);
 
        mutex_lock(&dev->struct_mutex);
-       ret = i915_gpu_idle(dev, true);
+       ret = i915_gpu_idle(dev);
        if (ret)
                DRM_ERROR("failed to idle hardware: %d\n", ret);
+       i915_gem_retire_requests(dev);
        mutex_unlock(&dev->struct_mutex);
 
        /* Cancel the retire work handler, which should be idle now. */
@@ -2206,8 +1681,7 @@ int i915_driver_unload(struct drm_device *dev)
                i915_gem_cleanup_ringbuffer(dev);
                mutex_unlock(&dev->struct_mutex);
                i915_gem_cleanup_aliasing_ppgtt(dev);
-               if (I915_HAS_FBC(dev) && i915_powersave)
-                       i915_cleanup_compression(dev);
+               i915_gem_cleanup_stolen(dev);
                drm_mm_takedown(&dev_priv->mm.stolen);
 
                intel_cleanup_overlay(dev);
@@ -2255,7 +1729,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
  * mode setting case, we want to restore the kernel's initial mode (just
  * in case the last client left us in a bad state).
  *
- * Additionally, in the non-mode setting case, we'll tear down the AGP
+ * Additionally, in the non-mode setting case, we'll tear down the GTT
  * and DMA structures, since the kernel won't be using them, and clea
  * up any GEM state.
  */
@@ -2300,7 +1774,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
        DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP,  drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE,  drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH),
        DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
        DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -2333,16 +1807,10 @@ struct drm_ioctl_desc i915_ioctls[] = {
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
 
-/**
- * Determine if the device really is AGP or not.
- *
- * All Intel graphics chipsets are treated as AGP, even if they are really
- * PCI-e.
- *
- * \param dev   The device to be tested.
- *
- * \returns
- * A value of 1 is always retured to indictate every i9x5 is AGP.
+/*
+ * This is really ugly: Because old userspace abused the linux agp interface to
+ * manage the gtt, we need to claim that all intel devices are agp.  For
+ * otherwise the drm core refuses to initialize the agp support code.
  */
 int i915_driver_device_is_agp(struct drm_device * dev)
 {
index 1a7559b59997cfaa8782e898e7c39cce09465f02..77b7a50e2014bdc96d452a0389da1b0cbfdf9fc0 100644 (file)
@@ -64,9 +64,13 @@ MODULE_PARM_DESC(semaphores,
                "Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
 
 int i915_enable_rc6 __read_mostly = -1;
-module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
+module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0400);
 MODULE_PARM_DESC(i915_enable_rc6,
-               "Enable power-saving render C-state 6 (default: -1 (use per-chip default)");
+               "Enable power-saving render C-state 6. "
+               "Different stages can be selected via bitmask values "
+               "(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). "
+               "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
+               "default: -1 (use per-chip default)");
 
 int i915_enable_fbc __read_mostly = -1;
 module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
@@ -80,6 +84,12 @@ MODULE_PARM_DESC(lvds_downclock,
                "Use panel (LVDS/eDP) downclocking for power savings "
                "(default: false)");
 
+int i915_lvds_channel_mode __read_mostly;
+module_param_named(lvds_channel_mode, i915_lvds_channel_mode, int, 0600);
+MODULE_PARM_DESC(lvds_channel_mode,
+                "Specify LVDS channel mode "
+                "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)");
+
 int i915_panel_use_ssc __read_mostly = -1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
 MODULE_PARM_DESC(lvds_use_ssc,
@@ -89,8 +99,8 @@ MODULE_PARM_DESC(lvds_use_ssc,
 int i915_vbt_sdvo_panel_type __read_mostly = -1;
 module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
 MODULE_PARM_DESC(vbt_sdvo_panel_type,
-               "Override selection of SDVO panel mode in the VBT "
-               "(default: auto)");
+               "Override/Ignore selection of SDVO panel mode in the VBT "
+               "(-2=ignore, -1=auto [default], index in VBT BIOS table)");
 
 static bool i915_try_reset __read_mostly = true;
 module_param_named(reset, i915_try_reset, bool, 0600);
@@ -103,8 +113,8 @@ MODULE_PARM_DESC(enable_hangcheck,
                "WARNING: Disabling this can cause system wide hangs. "
                "(default: true)");
 
-bool i915_enable_ppgtt __read_mostly = 1;
-module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, bool, 0600);
+int i915_enable_ppgtt __read_mostly = -1;
+module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
                "Enable PPGTT (default: true)");
 
@@ -205,6 +215,7 @@ static const struct intel_device_info intel_ironlake_d_info = {
        .gen = 5,
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_bsd_ring = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_ironlake_m_info = {
@@ -212,6 +223,7 @@ static const struct intel_device_info intel_ironlake_m_info = {
        .need_gfx_hws = 1, .has_hotplug = 1,
        .has_fbc = 1,
        .has_bsd_ring = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_d_info = {
@@ -220,6 +232,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
        .has_llc = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_m_info = {
@@ -229,6 +242,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
        .has_llc = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_d_info = {
@@ -237,6 +251,7 @@ static const struct intel_device_info intel_ivybridge_d_info = {
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
        .has_llc = 1,
+       .has_pch_split = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_m_info = {
@@ -246,6 +261,43 @@ static const struct intel_device_info intel_ivybridge_m_info = {
        .has_bsd_ring = 1,
        .has_blt_ring = 1,
        .has_llc = 1,
+       .has_pch_split = 1,
+};
+
+static const struct intel_device_info intel_valleyview_m_info = {
+       .gen = 7, .is_mobile = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_fbc = 0,
+       .has_bsd_ring = 1,
+       .has_blt_ring = 1,
+       .is_valleyview = 1,
+};
+
+static const struct intel_device_info intel_valleyview_d_info = {
+       .gen = 7,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_fbc = 0,
+       .has_bsd_ring = 1,
+       .has_blt_ring = 1,
+       .is_valleyview = 1,
+};
+
+static const struct intel_device_info intel_haswell_d_info = {
+       .is_haswell = 1, .gen = 7,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_bsd_ring = 1,
+       .has_blt_ring = 1,
+       .has_llc = 1,
+       .has_pch_split = 1,
+};
+
+static const struct intel_device_info intel_haswell_m_info = {
+       .is_haswell = 1, .gen = 7, .is_mobile = 1,
+       .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_bsd_ring = 1,
+       .has_blt_ring = 1,
+       .has_llc = 1,
+       .has_pch_split = 1,
 };
 
 static const struct pci_device_id pciidlist[] = {              /* aka */
@@ -292,6 +344,7 @@ static const struct pci_device_id pciidlist[] = {           /* aka */
        INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
        INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
        INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
+       INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
        {0, 0, 0}
 };
 
@@ -303,6 +356,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE   0x3b00
 #define INTEL_PCH_CPT_DEVICE_ID_TYPE   0x1c00
 #define INTEL_PCH_PPT_DEVICE_ID_TYPE   0x1e00
+#define INTEL_PCH_LPT_DEVICE_ID_TYPE   0x8c00
 
 void intel_detect_pch(struct drm_device *dev)
 {
@@ -323,20 +377,43 @@ void intel_detect_pch(struct drm_device *dev)
 
                        if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_IBX;
+                               dev_priv->num_pch_pll = 2;
                                DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
                        } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_CPT;
+                               dev_priv->num_pch_pll = 2;
                                DRM_DEBUG_KMS("Found CougarPoint PCH\n");
                        } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
                                /* PantherPoint is CPT compatible */
                                dev_priv->pch_type = PCH_CPT;
+                               dev_priv->num_pch_pll = 2;
                                DRM_DEBUG_KMS("Found PatherPoint PCH\n");
+                       } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
+                               dev_priv->pch_type = PCH_LPT;
+                               dev_priv->num_pch_pll = 0;
+                               DRM_DEBUG_KMS("Found LynxPoint PCH\n");
                        }
+                       BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);
                }
                pci_dev_put(pch);
        }
 }
 
+bool i915_semaphore_is_enabled(struct drm_device *dev)
+{
+       if (INTEL_INFO(dev)->gen < 6)
+               return 0;
+
+       if (i915_semaphores >= 0)
+               return i915_semaphores;
+
+       /* Enable semaphores on SNB when IO remapping is off */
+       if (INTEL_INFO(dev)->gen == 6)
+               return !intel_iommu_enabled;
+
+       return 1;
+}
+
 void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 {
        int count;
@@ -361,7 +438,7 @@ void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
        while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1))
                udelay(10);
 
-       I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1);
+       I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
        POSTING_READ(FORCEWAKE_MT);
 
        count = 0;
@@ -403,7 +480,7 @@ void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 
 void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
 {
-       I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0);
+       I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
        /* The below doubles as a POSTING_READ */
        gen6_gt_check_fifodbg(dev_priv);
 }
@@ -441,6 +518,31 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
        return ret;
 }
 
+void vlv_force_wake_get(struct drm_i915_private *dev_priv)
+{
+       int count;
+
+       count = 0;
+
+       /* Already awake? */
+       if ((I915_READ(0x130094) & 0xa1) == 0xa1)
+               return;
+
+       I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
+       POSTING_READ(FORCEWAKE_VLV);
+
+       count = 0;
+       while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0)
+               udelay(10);
+}
+
+void vlv_force_wake_put(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000);
+       /* FIXME: confirm VLV behavior with Punit folks */
+       POSTING_READ(FORCEWAKE_VLV);
+}
+
 static int i915_drm_freeze(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -533,7 +635,9 @@ static int i915_drm_thaw(struct drm_device *dev)
                drm_irq_install(dev);
 
                /* Resume the modeset for every activated CRTC */
+               mutex_lock(&dev->mode_config.mutex);
                drm_helper_resume_force_mode(dev);
+               mutex_unlock(&dev->mode_config.mutex);
 
                if (IS_IRONLAKE_M(dev))
                        ironlake_enable_rc6(dev);
@@ -569,7 +673,7 @@ int i915_resume(struct drm_device *dev)
        return 0;
 }
 
-static int i8xx_do_reset(struct drm_device *dev, u8 flags)
+static int i8xx_do_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -603,11 +707,12 @@ static int i965_reset_complete(struct drm_device *dev)
 {
        u8 gdrst;
        pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
-       return gdrst & 0x1;
+       return (gdrst & GRDOM_RESET_ENABLE) == 0;
 }
 
-static int i965_do_reset(struct drm_device *dev, u8 flags)
+static int i965_do_reset(struct drm_device *dev)
 {
+       int ret;
        u8 gdrst;
 
        /*
@@ -616,20 +721,43 @@ static int i965_do_reset(struct drm_device *dev, u8 flags)
         * triggers the reset; when done, the hardware will clear it.
         */
        pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
-       pci_write_config_byte(dev->pdev, I965_GDRST, gdrst | flags | 0x1);
+       pci_write_config_byte(dev->pdev, I965_GDRST,
+                             gdrst | GRDOM_RENDER |
+                             GRDOM_RESET_ENABLE);
+       ret =  wait_for(i965_reset_complete(dev), 500);
+       if (ret)
+               return ret;
+
+       /* We can't reset render&media without also resetting display ... */
+       pci_read_config_byte(dev->pdev, I965_GDRST, &gdrst);
+       pci_write_config_byte(dev->pdev, I965_GDRST,
+                             gdrst | GRDOM_MEDIA |
+                             GRDOM_RESET_ENABLE);
 
        return wait_for(i965_reset_complete(dev), 500);
 }
 
-static int ironlake_do_reset(struct drm_device *dev, u8 flags)
+static int ironlake_do_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
-       I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, gdrst | flags | 0x1);
+       u32 gdrst;
+       int ret;
+
+       gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
+       I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
+                  gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
+       ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
+       if (ret)
+               return ret;
+
+       /* We can't reset render&media without also resetting display ... */
+       gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
+       I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
+                  gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
        return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
 }
 
-static int gen6_do_reset(struct drm_device *dev, u8 flags)
+static int gen6_do_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int     ret;
@@ -664,10 +792,44 @@ static int gen6_do_reset(struct drm_device *dev, u8 flags)
        return ret;
 }
 
+static int intel_gpu_reset(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret = -ENODEV;
+
+       switch (INTEL_INFO(dev)->gen) {
+       case 7:
+       case 6:
+               ret = gen6_do_reset(dev);
+               break;
+       case 5:
+               ret = ironlake_do_reset(dev);
+               break;
+       case 4:
+               ret = i965_do_reset(dev);
+               break;
+       case 2:
+               ret = i8xx_do_reset(dev);
+               break;
+       }
+
+       /* Also reset the gpu hangman. */
+       if (dev_priv->stop_rings) {
+               DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n");
+               dev_priv->stop_rings = 0;
+               if (ret == -ENODEV) {
+                       DRM_ERROR("Reset not implemented, but ignoring "
+                                 "error for simulated gpu hangs\n");
+                       ret = 0;
+               }
+       }
+
+       return ret;
+}
+
 /**
  * i915_reset - reset chip after a hang
  * @dev: drm device to reset
- * @flags: reset domains
  *
  * Reset the chip.  Useful if a hang is detected. Returns zero on successful
  * reset or otherwise an error code.
@@ -680,14 +842,9 @@ static int gen6_do_reset(struct drm_device *dev, u8 flags)
  *   - re-init interrupt state
  *   - re-init display
  */
-int i915_reset(struct drm_device *dev, u8 flags)
+int i915_reset(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       /*
-        * We really should only reset the display subsystem if we actually
-        * need to
-        */
-       bool need_display = true;
        int ret;
 
        if (!i915_try_reset)
@@ -696,26 +853,16 @@ int i915_reset(struct drm_device *dev, u8 flags)
        if (!mutex_trylock(&dev->struct_mutex))
                return -EBUSY;
 
+       dev_priv->stop_rings = 0;
+
        i915_gem_reset(dev);
 
        ret = -ENODEV;
-       if (get_seconds() - dev_priv->last_gpu_reset < 5) {
+       if (get_seconds() - dev_priv->last_gpu_reset < 5)
                DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
-       } else switch (INTEL_INFO(dev)->gen) {
-       case 7:
-       case 6:
-               ret = gen6_do_reset(dev, flags);
-               break;
-       case 5:
-               ret = ironlake_do_reset(dev, flags);
-               break;
-       case 4:
-               ret = i965_do_reset(dev, flags);
-               break;
-       case 2:
-               ret = i8xx_do_reset(dev, flags);
-               break;
-       }
+       else
+               ret = intel_gpu_reset(dev);
+
        dev_priv->last_gpu_reset = get_seconds();
        if (ret) {
                DRM_ERROR("Failed to reset chip.\n");
@@ -752,23 +899,14 @@ int i915_reset(struct drm_device *dev, u8 flags)
                i915_gem_init_ppgtt(dev);
 
                mutex_unlock(&dev->struct_mutex);
-               drm_irq_uninstall(dev);
-               drm_mode_config_reset(dev);
-               drm_irq_install(dev);
-               mutex_lock(&dev->struct_mutex);
-       }
 
-       mutex_unlock(&dev->struct_mutex);
+               if (drm_core_check_feature(dev, DRIVER_MODESET))
+                       intel_modeset_init_hw(dev);
 
-       /*
-        * Perform a full modeset as on later generations, e.g. Ironlake, we may
-        * need to retrain the display link and cannot just restore the register
-        * values.
-        */
-       if (need_display) {
-               mutex_lock(&dev->mode_config.mutex);
-               drm_helper_resume_force_mode(dev);
-               mutex_unlock(&dev->mode_config.mutex);
+               drm_irq_uninstall(dev);
+               drm_irq_install(dev);
+       } else {
+               mutex_unlock(&dev->struct_mutex);
        }
 
        return 0;
@@ -986,6 +1124,13 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL and additional rights");
 
+/* We give fast paths for the really cool registers */
+#define NEEDS_FORCE_WAKE(dev_priv, reg) \
+       (((dev_priv)->info->gen >= 6) && \
+        ((reg) < 0x40000) &&            \
+        ((reg) != FORCEWAKE)) && \
+       (!IS_VALLEYVIEW((dev_priv)->dev))
+
 #define __i915_read(x, y) \
 u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
        u##x val = 0; \
index c0f19f57200488ba3220f1c0aaf138a22d2888de..e03a4f80c5c99479cf212badceaeab6c79d900aa 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/i2c-algo-bit.h>
 #include <drm/intel-gtt.h>
 #include <linux/backlight.h>
+#include <linux/intel-iommu.h>
+#include <linux/kref.h>
 
 /* General customization:
  */
@@ -63,10 +65,30 @@ enum plane {
 };
 #define plane_name(p) ((p) + 'A')
 
+enum port {
+       PORT_A = 0,
+       PORT_B,
+       PORT_C,
+       PORT_D,
+       PORT_E,
+       I915_MAX_PORTS
+};
+#define port_name(p) ((p) + 'A')
+
 #define I915_GEM_GPU_DOMAINS   (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
 
 #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++)
 
+struct intel_pch_pll {
+       int refcount; /* count of number of CRTCs sharing this PLL */
+       int active; /* count of number of active CRTCs (i.e. DPMS on) */
+       bool on; /* is the PLL actually active? Disabled during modeset */
+       int pll_reg;
+       int fp0_reg;
+       int fp1_reg;
+};
+#define I915_NUM_PLLS 2
+
 /* Interface history:
  *
  * 1.1: Original.
@@ -111,11 +133,11 @@ struct opregion_asle;
 struct drm_i915_private;
 
 struct intel_opregion {
-       struct opregion_header *header;
-       struct opregion_acpi *acpi;
-       struct opregion_swsci *swsci;
-       struct opregion_asle *asle;
-       void *vbt;
+       struct opregion_header __iomem *header;
+       struct opregion_acpi __iomem *acpi;
+       struct opregion_swsci __iomem *swsci;
+       struct opregion_asle __iomem *asle;
+       void __iomem *vbt;
        u32 __iomem *lid_state;
 };
 #define OPREGION_SIZE            (8*1024)
@@ -135,7 +157,6 @@ struct drm_i915_master_private {
 struct drm_i915_fence_reg {
        struct list_head lru_list;
        struct drm_i915_gem_object *obj;
-       uint32_t setup_seqno;
        int pin_count;
 };
 
@@ -151,8 +172,11 @@ struct sdvo_device_mapping {
 struct intel_display_error_state;
 
 struct drm_i915_error_state {
+       struct kref ref;
        u32 eir;
        u32 pgtbl_er;
+       u32 ier;
+       bool waiting[I915_NUM_RINGS];
        u32 pipestat[I915_MAX_PIPES];
        u32 tail[I915_NUM_RINGS];
        u32 head[I915_NUM_RINGS];
@@ -218,11 +242,13 @@ struct drm_i915_display_funcs {
        void (*update_wm)(struct drm_device *dev);
        void (*update_sprite_wm)(struct drm_device *dev, int pipe,
                                 uint32_t sprite_width, int pixel_size);
+       void (*sanitize_pm)(struct drm_device *dev);
        int (*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);
+       void (*off)(struct drm_crtc *crtc);
        void (*write_eld)(struct drm_connector *connector,
                          struct drm_crtc *crtc);
        void (*fdi_link_train)(struct drm_crtc *crtc);
@@ -255,6 +281,9 @@ struct intel_device_info {
        u8 is_broadwater:1;
        u8 is_crestline:1;
        u8 is_ivybridge:1;
+       u8 is_valleyview:1;
+       u8 has_pch_split:1;
+       u8 is_haswell:1;
        u8 has_fbc:1;
        u8 has_pipe_cxsr:1;
        u8 has_hotplug:1;
@@ -291,10 +320,12 @@ enum no_fbc_reason {
 enum intel_pch {
        PCH_IBX,        /* Ibexpeak PCH */
        PCH_CPT,        /* Cougarpoint PCH */
+       PCH_LPT,        /* Lynxpoint PCH */
 };
 
 #define QUIRK_PIPEA_FORCE (1<<0)
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
+#define QUIRK_INVERT_BRIGHTNESS (1<<2)
 
 struct intel_fbdev;
 struct intel_fbc_work;
@@ -302,7 +333,6 @@ struct intel_fbc_work;
 struct intel_gmbus {
        struct i2c_adapter adapter;
        bool force_bit;
-       bool has_gpio;
        u32 reg0;
        u32 gpio_reg;
        struct i2c_algo_bit_data bit_algo;
@@ -314,7 +344,6 @@ typedef struct drm_i915_private {
 
        const struct intel_device_info *info;
 
-       int has_gem;
        int relative_constants_mode;
 
        void __iomem *regs;
@@ -326,19 +355,23 @@ typedef struct drm_i915_private {
        /** gt_lock is also taken in irq contexts. */
        struct spinlock gt_lock;
 
-       struct intel_gmbus *gmbus;
+       struct intel_gmbus gmbus[GMBUS_NUM_PORTS];
 
        /** gmbus_mutex protects against concurrent usage of the single hw gmbus
         * controller on different i2c buses. */
        struct mutex gmbus_mutex;
 
+       /**
+        * Base address of the gmbus and gpio block.
+        */
+       uint32_t gpio_mmio_base;
+
        struct pci_dev *bridge_dev;
        struct intel_ring_buffer ring[I915_NUM_RINGS];
        uint32_t next_seqno;
 
        drm_dma_handle_t *status_page_dmah;
        uint32_t counter;
-       drm_local_map_t hws_map;
        struct drm_i915_gem_object *pwrctx;
        struct drm_i915_gem_object *renderctx;
 
@@ -354,6 +387,10 @@ typedef struct drm_i915_private {
 
        /* protects the irq masks */
        spinlock_t irq_lock;
+
+       /* DPIO indirect register protection */
+       spinlock_t dpio_lock;
+
        /** Cached value of IMR to avoid reads in updating the bitfield */
        u32 pipestat[2];
        u32 irq_mask;
@@ -363,11 +400,9 @@ typedef struct drm_i915_private {
        u32 hotplug_supported_mask;
        struct work_struct hotplug_work;
 
-       int tex_lru_log_granularity;
-       int allow_batchbuffer;
        unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
-       int vblank_pipe;
        int num_pipe;
+       int num_pch_pll;
 
        /* For hangcheck timer */
 #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
@@ -379,6 +414,8 @@ typedef struct drm_i915_private {
        uint32_t last_instdone;
        uint32_t last_instdone1;
 
+       unsigned int stop_rings;
+
        unsigned long cfb_size;
        unsigned int cfb_fb;
        enum plane cfb_plane;
@@ -405,6 +442,8 @@ typedef struct drm_i915_private {
        unsigned int lvds_use_ssc:1;
        unsigned int display_clock_mode:1;
        int lvds_ssc_freq;
+       unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
+       unsigned int lvds_val; /* used for checking LVDS channel mode */
        struct {
                int rate;
                int lanes;
@@ -428,6 +467,7 @@ typedef struct drm_i915_private {
        unsigned int fsb_freq, mem_freq, is_ddr3;
 
        spinlock_t error_lock;
+       /* Protected by dev->error_lock. */
        struct drm_i915_error_state *first_error;
        struct work_struct error_work;
        struct completion error_completion;
@@ -652,23 +692,9 @@ typedef struct drm_i915_private {
                 */
                struct list_head inactive_list;
 
-               /**
-                * LRU list of objects which are not in the ringbuffer but
-                * are still pinned in the GTT.
-                */
-               struct list_head pinned_list;
-
                /** LRU list of objects with fence regs on them. */
                struct list_head fence_list;
 
-               /**
-                * List of objects currently pending being freed.
-                *
-                * These objects are no longer in use, but due to a signal
-                * we were prevented from freeing them at the appointed time.
-                */
-               struct list_head deferred_free_list;
-
                /**
                 * We leave the user IRQ off as much as possible,
                 * but this means that requests will finish and never
@@ -717,6 +743,16 @@ typedef struct drm_i915_private {
                size_t object_memory;
                u32 object_count;
        } mm;
+
+       /* Old dri1 support infrastructure, beware the dragons ya fools entering
+        * here! */
+       struct {
+               unsigned allow_batchbuffer : 1;
+               u32 __iomem *gfx_hws_cpu_addr;
+       } dri1;
+
+       /* Kernel Modesetting */
+
        struct sdvo_device_mapping sdvo_mappings[2];
        /* indicate whether the LVDS_BORDER should be enabled or not */
        unsigned int lvds_border_bits;
@@ -726,7 +762,8 @@ typedef struct drm_i915_private {
        struct drm_crtc *plane_to_crtc_mapping[3];
        struct drm_crtc *pipe_to_crtc_mapping[3];
        wait_queue_head_t pending_flip_queue;
-       bool flip_pending_is_done;
+
+       struct intel_pch_pll pch_plls[I915_NUM_PLLS];
 
        /* Reclocking support */
        bool render_reclock_avail;
@@ -844,7 +881,14 @@ struct drm_i915_gem_object {
         * Current tiling mode for the object.
         */
        unsigned int tiling_mode:2;
-       unsigned int tiling_changed:1;
+       /**
+        * Whether the tiling parameters for the currently associated fence
+        * register have changed. Note that for the purposes of tracking
+        * tiling changes we also treat the unfenced register, the register
+        * slot that the object occupies whilst it executes a fenced
+        * command (such as BLT on gen2/3), as a "fence".
+        */
+       unsigned int fence_dirty:1;
 
        /** How many users have pinned this object in GTT space. The following
         * users can each hold at most one reference: pwrite/pread, pin_ioctl
@@ -881,6 +925,7 @@ struct drm_i915_gem_object {
        unsigned int cache_level:2;
 
        unsigned int has_aliasing_ppgtt_mapping:1;
+       unsigned int has_global_gtt_mapping:1;
 
        struct page **pages;
 
@@ -904,13 +949,12 @@ struct drm_i915_gem_object {
         */
        uint32_t gtt_offset;
 
-       /** Breadcrumb of last rendering to the buffer. */
-       uint32_t last_rendering_seqno;
        struct intel_ring_buffer *ring;
 
+       /** Breadcrumb of last rendering to the buffer. */
+       uint32_t last_rendering_seqno;
        /** Breadcrumb of last fenced GPU access to the buffer. */
        uint32_t last_fenced_seqno;
-       struct intel_ring_buffer *last_fenced_ring;
 
        /** Current tiling stride for the object, if it's tiled. */
        uint32_t stride;
@@ -918,13 +962,6 @@ struct drm_i915_gem_object {
        /** Record of address bit 17 of each page at last unbind. */
        unsigned long *bit_17;
 
-
-       /**
-        * If present, while GEM_DOMAIN_CPU is in the read domain this array
-        * flags which individual pages are valid.
-        */
-       uint8_t *page_cpu_valid;
-
        /** User space pin count and filp owning the pin */
        uint32_t user_pin_count;
        struct drm_file *pin_filp;
@@ -1001,6 +1038,8 @@ struct drm_i915_file_private {
 #define IS_IRONLAKE_D(dev)     ((dev)->pci_device == 0x0042)
 #define IS_IRONLAKE_M(dev)     ((dev)->pci_device == 0x0046)
 #define IS_IVYBRIDGE(dev)      (INTEL_INFO(dev)->is_ivybridge)
+#define IS_VALLEYVIEW(dev)     (INTEL_INFO(dev)->is_valleyview)
+#define IS_HASWELL(dev)        (INTEL_INFO(dev)->is_haswell)
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 
 /*
@@ -1044,15 +1083,37 @@ struct drm_i915_file_private {
 #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
 #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
 
-#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev))
+#define HAS_PCH_SPLIT(dev) (INTEL_INFO(dev)->has_pch_split)
 #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5)
 
 #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
+#define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)
 #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
 #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
 
 #include "i915_trace.h"
 
+/**
+ * RC6 is a special power stage which allows the GPU to enter an very
+ * low-voltage mode when idle, using down to 0V while at this stage.  This
+ * stage is entered automatically when the GPU is idle when RC6 support is
+ * enabled, and as soon as new workload arises GPU wakes up automatically as well.
+ *
+ * There are different RC6 modes available in Intel GPU, which differentiate
+ * among each other with the latency required to enter and leave RC6 and
+ * voltage consumed by the GPU in different states.
+ *
+ * The combination of the following flags define which states GPU is allowed
+ * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and
+ * RC6pp is deepest RC6. Their support by hardware varies according to the
+ * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one
+ * which brings the most power savings; deeper states save more power, but
+ * require higher latency to switch to and wake up.
+ */
+#define INTEL_RC6_ENABLE                       (1<<0)
+#define INTEL_RC6p_ENABLE                      (1<<1)
+#define INTEL_RC6pp_ENABLE                     (1<<2)
+
 extern struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
 extern unsigned int i915_fbpercrtc __always_unused;
@@ -1060,12 +1121,13 @@ extern int i915_panel_ignore_lid __read_mostly;
 extern unsigned int i915_powersave __read_mostly;
 extern int i915_semaphores __read_mostly;
 extern unsigned int i915_lvds_downclock __read_mostly;
+extern int i915_lvds_channel_mode __read_mostly;
 extern int i915_panel_use_ssc __read_mostly;
 extern int i915_vbt_sdvo_panel_type __read_mostly;
 extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
-extern bool i915_enable_ppgtt __read_mostly;
+extern int i915_enable_ppgtt __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
@@ -1073,6 +1135,7 @@ extern int i915_master_create(struct drm_device *dev, struct drm_master *master)
 extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
 
                                /* i915_dma.c */
+void i915_update_dri1_breadcrumb(struct drm_device *dev);
 extern void i915_kernel_lost_context(struct drm_device * dev);
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
 extern int i915_driver_unload(struct drm_device *);
@@ -1083,12 +1146,14 @@ extern void i915_driver_preclose(struct drm_device *dev,
 extern void i915_driver_postclose(struct drm_device *dev,
                                  struct drm_file *file_priv);
 extern int i915_driver_device_is_agp(struct drm_device * dev);
+#ifdef CONFIG_COMPAT
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
+#endif
 extern int i915_emit_box(struct drm_device *dev,
                         struct drm_clip_rect *box,
                         int DR1, int DR4);
-extern int i915_reset(struct drm_device *dev, u8 flags);
+extern int i915_reset(struct drm_device *dev);
 extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
@@ -1098,19 +1163,10 @@ extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
 /* i915_irq.c */
 void i915_hangcheck_elapsed(unsigned long data);
 void i915_handle_error(struct drm_device *dev, bool wedged);
-extern int i915_irq_emit(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int i915_irq_wait(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
 
 extern void intel_irq_init(struct drm_device *dev);
 
-extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
-extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
-extern int i915_vblank_swap(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv);
+void i915_error_state_free(struct kref *error_ref);
 
 void
 i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
@@ -1186,6 +1242,8 @@ void i915_gem_lastclose(struct drm_device *dev);
 
 int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
 int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj);
+int i915_gem_object_sync(struct drm_i915_gem_object *obj,
+                        struct intel_ring_buffer *to);
 void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
                                    struct intel_ring_buffer *ring,
                                    u32 seqno);
@@ -1208,17 +1266,18 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
 
 u32 i915_gem_next_request_seqno(struct intel_ring_buffer *ring);
 
-int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
-                                          struct intel_ring_buffer *pipelined);
+int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
 
-static inline void
+static inline bool
 i915_gem_object_pin_fence(struct drm_i915_gem_object *obj)
 {
        if (obj->fence_reg != I915_FENCE_REG_NONE) {
                struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
                dev_priv->fence_regs[obj->fence_reg].pin_count++;
-       }
+               return true;
+       } else
+               return false;
 }
 
 static inline void
@@ -1239,27 +1298,25 @@ int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
                                            uint32_t read_domains,
                                            uint32_t write_domain);
 int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
+int __must_check i915_gem_init(struct drm_device *dev);
 int __must_check i915_gem_init_hw(struct drm_device *dev);
 void i915_gem_init_swizzling(struct drm_device *dev);
 void i915_gem_init_ppgtt(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
-void i915_gem_do_init(struct drm_device *dev,
-                     unsigned long start,
-                     unsigned long mappable_end,
-                     unsigned long end);
-int __must_check i915_gpu_idle(struct drm_device *dev, bool do_retire);
+int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
 int __must_check i915_add_request(struct intel_ring_buffer *ring,
                                  struct drm_file *file,
                                  struct drm_i915_gem_request *request);
 int __must_check i915_wait_request(struct intel_ring_buffer *ring,
-                                  uint32_t seqno,
-                                  bool do_retire);
+                                  uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int __must_check
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
                                  bool write);
 int __must_check
+i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write);
+int __must_check
 i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                                     u32 alignment,
                                     struct intel_ring_buffer *pipelined);
@@ -1290,18 +1347,24 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
                              struct drm_i915_gem_object *obj);
 
 void i915_gem_restore_gtt_mappings(struct drm_device *dev);
-int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj);
-void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
+int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
+void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
                                enum i915_cache_level cache_level);
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
+void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
+void i915_gem_init_global_gtt(struct drm_device *dev,
+                             unsigned long start,
+                             unsigned long mappable_end,
+                             unsigned long end);
 
 /* i915_gem_evict.c */
 int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size,
                                          unsigned alignment, bool mappable);
-int __must_check i915_gem_evict_everything(struct drm_device *dev,
-                                          bool purgeable_only);
-int __must_check i915_gem_evict_inactive(struct drm_device *dev,
-                                        bool purgeable_only);
+int i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only);
+
+/* i915_gem_stolen.c */
+int i915_gem_init_stolen(struct drm_device *dev);
+void i915_gem_cleanup_stolen(struct drm_device *dev);
 
 /* i915_gem_tiling.c */
 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
@@ -1333,9 +1396,20 @@ extern int i915_restore_state(struct drm_device *dev);
 extern int i915_save_state(struct drm_device *dev);
 extern int i915_restore_state(struct drm_device *dev);
 
+/* i915_sysfs.c */
+void i915_setup_sysfs(struct drm_device *dev_priv);
+void i915_teardown_sysfs(struct drm_device *dev_priv);
+
 /* intel_i2c.c */
 extern int intel_setup_gmbus(struct drm_device *dev);
 extern void intel_teardown_gmbus(struct drm_device *dev);
+extern inline bool intel_gmbus_is_port_valid(unsigned port)
+{
+       return (port >= GMBUS_PORT_SSC && port <= GMBUS_PORT_DPD);
+}
+
+extern struct i2c_adapter *intel_gmbus_get_adapter(
+               struct drm_i915_private *dev_priv, unsigned port);
 extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
 extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
 extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
@@ -1370,6 +1444,7 @@ static inline void intel_unregister_dsm_handler(void) { return; }
 #endif /* CONFIG_ACPI */
 
 /* modesetting */
+extern void intel_modeset_init_hw(struct drm_device *dev);
 extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
@@ -1382,12 +1457,17 @@ extern void ironlake_enable_rc6(struct drm_device *dev);
 extern void gen6_set_rps(struct drm_device *dev, u8 val);
 extern void intel_detect_pch(struct drm_device *dev);
 extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
+extern int intel_enable_rc6(const struct drm_device *dev);
 
+extern bool i915_semaphore_is_enabled(struct drm_device *dev);
 extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
 extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv);
 extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
 extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv);
 
+extern void vlv_force_wake_get(struct drm_i915_private *dev_priv);
+extern void vlv_force_wake_put(struct drm_i915_private *dev_priv);
+
 /* overlay */
 #ifdef CONFIG_DEBUG_FS
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
@@ -1399,28 +1479,6 @@ extern void intel_display_print_error_state(struct seq_file *m,
                                            struct intel_display_error_state *error);
 #endif
 
-#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
-
-#define BEGIN_LP_RING(n) \
-       intel_ring_begin(LP_RING(dev_priv), (n))
-
-#define OUT_RING(x) \
-       intel_ring_emit(LP_RING(dev_priv), x)
-
-#define ADVANCE_LP_RING() \
-       intel_ring_advance(LP_RING(dev_priv))
-
-/**
- * Lock test for when it's just for synchronization of ring access.
- *
- * In that case, we don't need to do it when GEM is initialized as nobody else
- * has access to the ring.
- */
-#define RING_LOCK_TEST_WITH_RETURN(dev, file) do {                     \
-       if (LP_RING(dev->dev_private)->obj == NULL)                     \
-               LOCK_TEST_WITH_RETURN(dev, file);                       \
-} while (0)
-
 /* On SNB platform, before reading ring registers forcewake bit
  * must be set to prevent GT core from power down and stale values being
  * returned.
@@ -1429,12 +1487,6 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
 void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
 int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
 
-/* We give fast paths for the really cool registers */
-#define NEEDS_FORCE_WAKE(dev_priv, reg) \
-       (((dev_priv)->info->gen >= 6) && \
-        ((reg) < 0x40000) &&            \
-        ((reg) != FORCEWAKE))
-
 #define __i915_read(x, y) \
        u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
 
index 1f441f5c240570abe8111fadc66c42d91c10440e..44a5f241b1a0698f18ece0600794789d5858c4b8 100644 (file)
 static __must_check int i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj);
 static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj);
-static __must_check int i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj,
-                                                         bool write);
-static __must_check int i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj,
-                                                                 uint64_t offset,
-                                                                 uint64_t size);
-static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj);
 static __must_check int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
                                                    unsigned alignment,
                                                    bool map_and_fenceable);
-static void i915_gem_clear_fence_reg(struct drm_device *dev,
-                                    struct drm_i915_fence_reg *reg);
 static int i915_gem_phys_pwrite(struct drm_device *dev,
                                struct drm_i915_gem_object *obj,
                                struct drm_i915_gem_pwrite *args,
                                struct drm_file *file);
-static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj);
+
+static void i915_gem_write_fence(struct drm_device *dev, int reg,
+                                struct drm_i915_gem_object *obj);
+static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
+                                        struct drm_i915_fence_reg *fence,
+                                        bool enable);
 
 static int i915_gem_inactive_shrink(struct shrinker *shrinker,
                                    struct shrink_control *sc);
 static void i915_gem_object_truncate(struct drm_i915_gem_object *obj);
 
+static inline void i915_gem_object_fence_lost(struct drm_i915_gem_object *obj)
+{
+       if (obj->tiling_mode)
+               i915_gem_release_mmap(obj);
+
+       /* As we do not have an associated fence register, we will force
+        * a tiling change if we ever need to acquire one.
+        */
+       obj->fence_dirty = false;
+       obj->fence_reg = I915_FENCE_REG_NONE;
+}
+
 /* some bookkeeping */
 static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
                                  size_t size)
@@ -122,26 +131,7 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
 static inline bool
 i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)
 {
-       return obj->gtt_space && !obj->active && obj->pin_count == 0;
-}
-
-void i915_gem_do_init(struct drm_device *dev,
-                     unsigned long start,
-                     unsigned long mappable_end,
-                     unsigned long end)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       drm_mm_init(&dev_priv->mm.gtt_space, start, end - start);
-
-       dev_priv->mm.gtt_start = start;
-       dev_priv->mm.gtt_mappable_end = mappable_end;
-       dev_priv->mm.gtt_end = end;
-       dev_priv->mm.gtt_total = end - start;
-       dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start;
-
-       /* Take over this portion of the GTT */
-       intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE);
+       return !obj->active;
 }
 
 int
@@ -150,12 +140,20 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data,
 {
        struct drm_i915_gem_init *args = data;
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
+
        if (args->gtt_start >= args->gtt_end ||
            (args->gtt_end | args->gtt_start) & (PAGE_SIZE - 1))
                return -EINVAL;
 
+       /* GEM with user mode setting was never supported on ilk and later. */
+       if (INTEL_INFO(dev)->gen >= 5)
+               return -ENODEV;
+
        mutex_lock(&dev->struct_mutex);
-       i915_gem_do_init(dev, args->gtt_start, args->gtt_end, args->gtt_end);
+       i915_gem_init_global_gtt(dev, args->gtt_start,
+                                args->gtt_end, args->gtt_end);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -170,13 +168,11 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
        struct drm_i915_gem_object *obj;
        size_t pinned;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        pinned = 0;
        mutex_lock(&dev->struct_mutex);
-       list_for_each_entry(obj, &dev_priv->mm.pinned_list, mm_list)
-               pinned += obj->gtt_space->size;
+       list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list)
+               if (obj->pin_count)
+                       pinned += obj->gtt_space->size;
        mutex_unlock(&dev->struct_mutex);
 
        args->aper_size = dev_priv->mm.gtt_total;
@@ -247,6 +243,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
                      struct drm_file *file)
 {
        struct drm_i915_gem_create *args = data;
+
        return i915_gem_create(file, dev,
                               args->size, &args->handle);
 }
@@ -259,66 +256,6 @@ static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
                obj->tiling_mode != I915_TILING_NONE;
 }
 
-/**
- * This is the fast shmem pread path, which attempts to copy_from_user directly
- * from the backing pages of the object to the user's address space.  On a
- * fault, it fails so we can fall back to i915_gem_shmem_pwrite_slow().
- */
-static int
-i915_gem_shmem_pread_fast(struct drm_device *dev,
-                         struct drm_i915_gem_object *obj,
-                         struct drm_i915_gem_pread *args,
-                         struct drm_file *file)
-{
-       struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
-       ssize_t remain;
-       loff_t offset;
-       char __user *user_data;
-       int page_offset, page_length;
-
-       user_data = (char __user *) (uintptr_t) args->data_ptr;
-       remain = args->size;
-
-       offset = args->offset;
-
-       while (remain > 0) {
-               struct page *page;
-               char *vaddr;
-               int ret;
-
-               /* Operation in this page
-                *
-                * page_offset = offset within page
-                * page_length = bytes to copy for this page
-                */
-               page_offset = offset_in_page(offset);
-               page_length = remain;
-               if ((page_offset + remain) > PAGE_SIZE)
-                       page_length = PAGE_SIZE - page_offset;
-
-               page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
-               if (IS_ERR(page))
-                       return PTR_ERR(page);
-
-               vaddr = kmap_atomic(page);
-               ret = __copy_to_user_inatomic(user_data,
-                                             vaddr + page_offset,
-                                             page_length);
-               kunmap_atomic(vaddr);
-
-               mark_page_accessed(page);
-               page_cache_release(page);
-               if (ret)
-                       return -EFAULT;
-
-               remain -= page_length;
-               user_data += page_length;
-               offset += page_length;
-       }
-
-       return 0;
-}
-
 static inline int
 __copy_to_user_swizzled(char __user *cpu_vaddr,
                        const char *gpu_vaddr, int gpu_offset,
@@ -346,8 +283,8 @@ __copy_to_user_swizzled(char __user *cpu_vaddr,
 }
 
 static inline int
-__copy_from_user_swizzled(char __user *gpu_vaddr, int gpu_offset,
-                         const char *cpu_vaddr,
+__copy_from_user_swizzled(char *gpu_vaddr, int gpu_offset,
+                         const char __user *cpu_vaddr,
                          int length)
 {
        int ret, cpu_offset = 0;
@@ -371,37 +308,121 @@ __copy_from_user_swizzled(char __user *gpu_vaddr, int gpu_offset,
        return 0;
 }
 
-/**
- * This is the fallback shmem pread path, which allocates temporary storage
- * in kernel space to copy_to_user into outside of the struct_mutex, so we
- * can copy out of the object's backing pages while holding the struct mutex
- * and not take page faults.
- */
+/* Per-page copy function for the shmem pread fastpath.
+ * Flushes invalid cachelines before reading the target if
+ * needs_clflush is set. */
 static int
-i915_gem_shmem_pread_slow(struct drm_device *dev,
-                         struct drm_i915_gem_object *obj,
-                         struct drm_i915_gem_pread *args,
-                         struct drm_file *file)
+shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length,
+                char __user *user_data,
+                bool page_do_bit17_swizzling, bool needs_clflush)
+{
+       char *vaddr;
+       int ret;
+
+       if (unlikely(page_do_bit17_swizzling))
+               return -EINVAL;
+
+       vaddr = kmap_atomic(page);
+       if (needs_clflush)
+               drm_clflush_virt_range(vaddr + shmem_page_offset,
+                                      page_length);
+       ret = __copy_to_user_inatomic(user_data,
+                                     vaddr + shmem_page_offset,
+                                     page_length);
+       kunmap_atomic(vaddr);
+
+       return ret;
+}
+
+static void
+shmem_clflush_swizzled_range(char *addr, unsigned long length,
+                            bool swizzled)
+{
+       if (unlikely(swizzled)) {
+               unsigned long start = (unsigned long) addr;
+               unsigned long end = (unsigned long) addr + length;
+
+               /* For swizzling simply ensure that we always flush both
+                * channels. Lame, but simple and it works. Swizzled
+                * pwrite/pread is far from a hotpath - current userspace
+                * doesn't use it at all. */
+               start = round_down(start, 128);
+               end = round_up(end, 128);
+
+               drm_clflush_virt_range((void *)start, end - start);
+       } else {
+               drm_clflush_virt_range(addr, length);
+       }
+
+}
+
+/* Only difference to the fast-path function is that this can handle bit17
+ * and uses non-atomic copy and kmap functions. */
+static int
+shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length,
+                char __user *user_data,
+                bool page_do_bit17_swizzling, bool needs_clflush)
+{
+       char *vaddr;
+       int ret;
+
+       vaddr = kmap(page);
+       if (needs_clflush)
+               shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
+                                            page_length,
+                                            page_do_bit17_swizzling);
+
+       if (page_do_bit17_swizzling)
+               ret = __copy_to_user_swizzled(user_data,
+                                             vaddr, shmem_page_offset,
+                                             page_length);
+       else
+               ret = __copy_to_user(user_data,
+                                    vaddr + shmem_page_offset,
+                                    page_length);
+       kunmap(page);
+
+       return ret;
+}
+
+static int
+i915_gem_shmem_pread(struct drm_device *dev,
+                    struct drm_i915_gem_object *obj,
+                    struct drm_i915_gem_pread *args,
+                    struct drm_file *file)
 {
        struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
        char __user *user_data;
        ssize_t remain;
        loff_t offset;
-       int shmem_page_offset, page_length, ret;
+       int shmem_page_offset, page_length, ret = 0;
        int obj_do_bit17_swizzling, page_do_bit17_swizzling;
+       int hit_slowpath = 0;
+       int prefaulted = 0;
+       int needs_clflush = 0;
+       int release_page;
 
        user_data = (char __user *) (uintptr_t) args->data_ptr;
        remain = args->size;
 
        obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
 
-       offset = args->offset;
+       if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) {
+               /* If we're not in the cpu read domain, set ourself into the gtt
+                * read domain and manually flush cachelines (if required). This
+                * optimizes for the case when the gpu will dirty the data
+                * anyway again before the next pread happens. */
+               if (obj->cache_level == I915_CACHE_NONE)
+                       needs_clflush = 1;
+               ret = i915_gem_object_set_to_gtt_domain(obj, false);
+               if (ret)
+                       return ret;
+       }
 
-       mutex_unlock(&dev->struct_mutex);
+       offset = args->offset;
 
        while (remain > 0) {
                struct page *page;
-               char *vaddr;
 
                /* Operation in this page
                 *
@@ -413,28 +434,51 @@ i915_gem_shmem_pread_slow(struct drm_device *dev,
                if ((shmem_page_offset + page_length) > PAGE_SIZE)
                        page_length = PAGE_SIZE - shmem_page_offset;
 
-               page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
-               if (IS_ERR(page)) {
-                       ret = PTR_ERR(page);
-                       goto out;
+               if (obj->pages) {
+                       page = obj->pages[offset >> PAGE_SHIFT];
+                       release_page = 0;
+               } else {
+                       page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
+                       if (IS_ERR(page)) {
+                               ret = PTR_ERR(page);
+                               goto out;
+                       }
+                       release_page = 1;
                }
 
                page_do_bit17_swizzling = obj_do_bit17_swizzling &&
                        (page_to_phys(page) & (1 << 17)) != 0;
 
-               vaddr = kmap(page);
-               if (page_do_bit17_swizzling)
-                       ret = __copy_to_user_swizzled(user_data,
-                                                     vaddr, shmem_page_offset,
-                                                     page_length);
-               else
-                       ret = __copy_to_user(user_data,
-                                            vaddr + shmem_page_offset,
-                                            page_length);
-               kunmap(page);
+               ret = shmem_pread_fast(page, shmem_page_offset, page_length,
+                                      user_data, page_do_bit17_swizzling,
+                                      needs_clflush);
+               if (ret == 0)
+                       goto next_page;
 
-               mark_page_accessed(page);
+               hit_slowpath = 1;
+               page_cache_get(page);
+               mutex_unlock(&dev->struct_mutex);
+
+               if (!prefaulted) {
+                       ret = fault_in_multipages_writeable(user_data, remain);
+                       /* Userspace is tricking us, but we've already clobbered
+                        * its pages with the prefault and promised to write the
+                        * data up to the first fault. Hence ignore any errors
+                        * and just continue. */
+                       (void)ret;
+                       prefaulted = 1;
+               }
+
+               ret = shmem_pread_slow(page, shmem_page_offset, page_length,
+                                      user_data, page_do_bit17_swizzling,
+                                      needs_clflush);
+
+               mutex_lock(&dev->struct_mutex);
                page_cache_release(page);
+next_page:
+               mark_page_accessed(page);
+               if (release_page)
+                       page_cache_release(page);
 
                if (ret) {
                        ret = -EFAULT;
@@ -447,10 +491,11 @@ i915_gem_shmem_pread_slow(struct drm_device *dev,
        }
 
 out:
-       mutex_lock(&dev->struct_mutex);
-       /* Fixup: Kill any reinstated backing storage pages */
-       if (obj->madv == __I915_MADV_PURGED)
-               i915_gem_object_truncate(obj);
+       if (hit_slowpath) {
+               /* Fixup: Kill any reinstated backing storage pages */
+               if (obj->madv == __I915_MADV_PURGED)
+                       i915_gem_object_truncate(obj);
+       }
 
        return ret;
 }
@@ -476,11 +521,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
                       args->size))
                return -EFAULT;
 
-       ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr,
-                                      args->size);
-       if (ret)
-               return -EFAULT;
-
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                return ret;
@@ -500,17 +540,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
 
        trace_i915_gem_object_pread(obj, args->offset, args->size);
 
-       ret = i915_gem_object_set_cpu_read_domain_range(obj,
-                                                       args->offset,
-                                                       args->size);
-       if (ret)
-               goto out;
-
-       ret = -EFAULT;
-       if (!i915_gem_object_needs_bit17_swizzle(obj))
-               ret = i915_gem_shmem_pread_fast(dev, obj, args, file);
-       if (ret == -EFAULT)
-               ret = i915_gem_shmem_pread_slow(dev, obj, args, file);
+       ret = i915_gem_shmem_pread(dev, obj, args, file);
 
 out:
        drm_gem_object_unreference(&obj->base);
@@ -529,40 +559,19 @@ fast_user_write(struct io_mapping *mapping,
                char __user *user_data,
                int length)
 {
-       char *vaddr_atomic;
+       void __iomem *vaddr_atomic;
+       void *vaddr;
        unsigned long unwritten;
 
        vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
-       unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
+       /* We can use the cpu mem copy function because this is X86. */
+       vaddr = (void __force*)vaddr_atomic + page_offset;
+       unwritten = __copy_from_user_inatomic_nocache(vaddr,
                                                      user_data, length);
        io_mapping_unmap_atomic(vaddr_atomic);
        return unwritten;
 }
 
-/* Here's the write path which can sleep for
- * page faults
- */
-
-static inline void
-slow_kernel_write(struct io_mapping *mapping,
-                 loff_t gtt_base, int gtt_offset,
-                 struct page *user_page, int user_offset,
-                 int length)
-{
-       char __iomem *dst_vaddr;
-       char *src_vaddr;
-
-       dst_vaddr = io_mapping_map_wc(mapping, gtt_base);
-       src_vaddr = kmap(user_page);
-
-       memcpy_toio(dst_vaddr + gtt_offset,
-                   src_vaddr + user_offset,
-                   length);
-
-       kunmap(user_page);
-       io_mapping_unmap(dst_vaddr);
-}
-
 /**
  * This is the fast pwrite path, where we copy the data directly from the
  * user into the GTT, uncached.
@@ -577,7 +586,19 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
        ssize_t remain;
        loff_t offset, page_base;
        char __user *user_data;
-       int page_offset, page_length;
+       int page_offset, page_length, ret;
+
+       ret = i915_gem_object_pin(obj, 0, true);
+       if (ret)
+               goto out;
+
+       ret = i915_gem_object_set_to_gtt_domain(obj, true);
+       if (ret)
+               goto out_unpin;
+
+       ret = i915_gem_object_put_fence(obj);
+       if (ret)
+               goto out_unpin;
 
        user_data = (char __user *) (uintptr_t) args->data_ptr;
        remain = args->size;
@@ -602,214 +623,133 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
                 * retry in the slow path.
                 */
                if (fast_user_write(dev_priv->mm.gtt_mapping, page_base,
-                                   page_offset, user_data, page_length))
-                       return -EFAULT;
+                                   page_offset, user_data, page_length)) {
+                       ret = -EFAULT;
+                       goto out_unpin;
+               }
 
                remain -= page_length;
                user_data += page_length;
                offset += page_length;
        }
 
-       return 0;
+out_unpin:
+       i915_gem_object_unpin(obj);
+out:
+       return ret;
 }
 
-/**
- * This is the fallback GTT pwrite path, which uses get_user_pages to pin
- * the memory and maps it using kmap_atomic for copying.
- *
- * This code resulted in x11perf -rgb10text consuming about 10% more CPU
- * than using i915_gem_gtt_pwrite_fast on a G45 (32-bit).
- */
+/* Per-page copy function for the shmem pwrite fastpath.
+ * Flushes invalid cachelines before writing to the target if
+ * needs_clflush_before is set and flushes out any written cachelines after
+ * writing if needs_clflush is set. */
 static int
-i915_gem_gtt_pwrite_slow(struct drm_device *dev,
-                        struct drm_i915_gem_object *obj,
-                        struct drm_i915_gem_pwrite *args,
-                        struct drm_file *file)
+shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length,
+                 char __user *user_data,
+                 bool page_do_bit17_swizzling,
+                 bool needs_clflush_before,
+                 bool needs_clflush_after)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       ssize_t remain;
-       loff_t gtt_page_base, offset;
-       loff_t first_data_page, last_data_page, num_pages;
-       loff_t pinned_pages, i;
-       struct page **user_pages;
-       struct mm_struct *mm = current->mm;
-       int gtt_page_offset, data_page_offset, data_page_index, page_length;
+       char *vaddr;
        int ret;
-       uint64_t data_ptr = args->data_ptr;
-
-       remain = args->size;
-
-       /* Pin the user pages containing the data.  We can't fault while
-        * holding the struct mutex, and all of the pwrite implementations
-        * want to hold it while dereferencing the user data.
-        */
-       first_data_page = data_ptr / PAGE_SIZE;
-       last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE;
-       num_pages = last_data_page - first_data_page + 1;
-
-       user_pages = drm_malloc_ab(num_pages, sizeof(struct page *));
-       if (user_pages == NULL)
-               return -ENOMEM;
-
-       mutex_unlock(&dev->struct_mutex);
-       down_read(&mm->mmap_sem);
-       pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr,
-                                     num_pages, 0, 0, user_pages, NULL);
-       up_read(&mm->mmap_sem);
-       mutex_lock(&dev->struct_mutex);
-       if (pinned_pages < num_pages) {
-               ret = -EFAULT;
-               goto out_unpin_pages;
-       }
-
-       ret = i915_gem_object_set_to_gtt_domain(obj, true);
-       if (ret)
-               goto out_unpin_pages;
-
-       ret = i915_gem_object_put_fence(obj);
-       if (ret)
-               goto out_unpin_pages;
-
-       offset = obj->gtt_offset + args->offset;
 
-       while (remain > 0) {
-               /* Operation in this page
-                *
-                * gtt_page_base = page offset within aperture
-                * gtt_page_offset = offset within page in aperture
-                * data_page_index = page number in get_user_pages return
-                * data_page_offset = offset with data_page_index page.
-                * page_length = bytes to copy for this page
-                */
-               gtt_page_base = offset & PAGE_MASK;
-               gtt_page_offset = offset_in_page(offset);
-               data_page_index = data_ptr / PAGE_SIZE - first_data_page;
-               data_page_offset = offset_in_page(data_ptr);
-
-               page_length = remain;
-               if ((gtt_page_offset + page_length) > PAGE_SIZE)
-                       page_length = PAGE_SIZE - gtt_page_offset;
-               if ((data_page_offset + page_length) > PAGE_SIZE)
-                       page_length = PAGE_SIZE - data_page_offset;
-
-               slow_kernel_write(dev_priv->mm.gtt_mapping,
-                                 gtt_page_base, gtt_page_offset,
-                                 user_pages[data_page_index],
-                                 data_page_offset,
-                                 page_length);
-
-               remain -= page_length;
-               offset += page_length;
-               data_ptr += page_length;
-       }
+       if (unlikely(page_do_bit17_swizzling))
+               return -EINVAL;
 
-out_unpin_pages:
-       for (i = 0; i < pinned_pages; i++)
-               page_cache_release(user_pages[i]);
-       drm_free_large(user_pages);
+       vaddr = kmap_atomic(page);
+       if (needs_clflush_before)
+               drm_clflush_virt_range(vaddr + shmem_page_offset,
+                                      page_length);
+       ret = __copy_from_user_inatomic_nocache(vaddr + shmem_page_offset,
+                                               user_data,
+                                               page_length);
+       if (needs_clflush_after)
+               drm_clflush_virt_range(vaddr + shmem_page_offset,
+                                      page_length);
+       kunmap_atomic(vaddr);
 
        return ret;
 }
 
-/**
- * This is the fast shmem pwrite path, which attempts to directly
- * copy_from_user into the kmapped pages backing the object.
- */
+/* Only difference to the fast-path function is that this can handle bit17
+ * and uses non-atomic copy and kmap functions. */
 static int
-i915_gem_shmem_pwrite_fast(struct drm_device *dev,
-                          struct drm_i915_gem_object *obj,
-                          struct drm_i915_gem_pwrite *args,
-                          struct drm_file *file)
+shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length,
+                 char __user *user_data,
+                 bool page_do_bit17_swizzling,
+                 bool needs_clflush_before,
+                 bool needs_clflush_after)
 {
-       struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
-       ssize_t remain;
-       loff_t offset;
-       char __user *user_data;
-       int page_offset, page_length;
-
-       user_data = (char __user *) (uintptr_t) args->data_ptr;
-       remain = args->size;
-
-       offset = args->offset;
-       obj->dirty = 1;
-
-       while (remain > 0) {
-               struct page *page;
-               char *vaddr;
-               int ret;
-
-               /* Operation in this page
-                *
-                * page_offset = offset within page
-                * page_length = bytes to copy for this page
-                */
-               page_offset = offset_in_page(offset);
-               page_length = remain;
-               if ((page_offset + remain) > PAGE_SIZE)
-                       page_length = PAGE_SIZE - page_offset;
-
-               page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
-               if (IS_ERR(page))
-                       return PTR_ERR(page);
+       char *vaddr;
+       int ret;
 
-               vaddr = kmap_atomic(page);
-               ret = __copy_from_user_inatomic(vaddr + page_offset,
+       vaddr = kmap(page);
+       if (unlikely(needs_clflush_before || page_do_bit17_swizzling))
+               shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
+                                            page_length,
+                                            page_do_bit17_swizzling);
+       if (page_do_bit17_swizzling)
+               ret = __copy_from_user_swizzled(vaddr, shmem_page_offset,
                                                user_data,
                                                page_length);
-               kunmap_atomic(vaddr);
-
-               set_page_dirty(page);
-               mark_page_accessed(page);
-               page_cache_release(page);
-
-               /* If we get a fault while copying data, then (presumably) our
-                * source page isn't available.  Return the error and we'll
-                * retry in the slow path.
-                */
-               if (ret)
-                       return -EFAULT;
-
-               remain -= page_length;
-               user_data += page_length;
-               offset += page_length;
-       }
+       else
+               ret = __copy_from_user(vaddr + shmem_page_offset,
+                                      user_data,
+                                      page_length);
+       if (needs_clflush_after)
+               shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
+                                            page_length,
+                                            page_do_bit17_swizzling);
+       kunmap(page);
 
-       return 0;
+       return ret;
 }
 
-/**
- * This is the fallback shmem pwrite path, which uses get_user_pages to pin
- * the memory and maps it using kmap_atomic for copying.
- *
- * This avoids taking mmap_sem for faulting on the user's address while the
- * struct_mutex is held.
- */
 static int
-i915_gem_shmem_pwrite_slow(struct drm_device *dev,
-                          struct drm_i915_gem_object *obj,
-                          struct drm_i915_gem_pwrite *args,
-                          struct drm_file *file)
+i915_gem_shmem_pwrite(struct drm_device *dev,
+                     struct drm_i915_gem_object *obj,
+                     struct drm_i915_gem_pwrite *args,
+                     struct drm_file *file)
 {
        struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
        ssize_t remain;
        loff_t offset;
        char __user *user_data;
-       int shmem_page_offset, page_length, ret;
+       int shmem_page_offset, page_length, ret = 0;
        int obj_do_bit17_swizzling, page_do_bit17_swizzling;
+       int hit_slowpath = 0;
+       int needs_clflush_after = 0;
+       int needs_clflush_before = 0;
+       int release_page;
 
        user_data = (char __user *) (uintptr_t) args->data_ptr;
        remain = args->size;
 
        obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
 
+       if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
+               /* If we're not in the cpu write domain, set ourself into the gtt
+                * write domain and manually flush cachelines (if required). This
+                * optimizes for the case when the gpu will use the data
+                * right away and we therefore have to clflush anyway. */
+               if (obj->cache_level == I915_CACHE_NONE)
+                       needs_clflush_after = 1;
+               ret = i915_gem_object_set_to_gtt_domain(obj, true);
+               if (ret)
+                       return ret;
+       }
+       /* Same trick applies for invalidate partially written cachelines before
+        * writing.  */
+       if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)
+           && obj->cache_level == I915_CACHE_NONE)
+               needs_clflush_before = 1;
+
        offset = args->offset;
        obj->dirty = 1;
 
-       mutex_unlock(&dev->struct_mutex);
-
        while (remain > 0) {
                struct page *page;
-               char *vaddr;
+               int partial_cacheline_write;
 
                /* Operation in this page
                 *
@@ -822,29 +762,51 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev,
                if ((shmem_page_offset + page_length) > PAGE_SIZE)
                        page_length = PAGE_SIZE - shmem_page_offset;
 
-               page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
-               if (IS_ERR(page)) {
-                       ret = PTR_ERR(page);
-                       goto out;
+               /* If we don't overwrite a cacheline completely we need to be
+                * careful to have up-to-date data by first clflushing. Don't
+                * overcomplicate things and flush the entire patch. */
+               partial_cacheline_write = needs_clflush_before &&
+                       ((shmem_page_offset | page_length)
+                               & (boot_cpu_data.x86_clflush_size - 1));
+
+               if (obj->pages) {
+                       page = obj->pages[offset >> PAGE_SHIFT];
+                       release_page = 0;
+               } else {
+                       page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
+                       if (IS_ERR(page)) {
+                               ret = PTR_ERR(page);
+                               goto out;
+                       }
+                       release_page = 1;
                }
 
                page_do_bit17_swizzling = obj_do_bit17_swizzling &&
                        (page_to_phys(page) & (1 << 17)) != 0;
 
-               vaddr = kmap(page);
-               if (page_do_bit17_swizzling)
-                       ret = __copy_from_user_swizzled(vaddr, shmem_page_offset,
-                                                       user_data,
-                                                       page_length);
-               else
-                       ret = __copy_from_user(vaddr + shmem_page_offset,
-                                              user_data,
-                                              page_length);
-               kunmap(page);
+               ret = shmem_pwrite_fast(page, shmem_page_offset, page_length,
+                                       user_data, page_do_bit17_swizzling,
+                                       partial_cacheline_write,
+                                       needs_clflush_after);
+               if (ret == 0)
+                       goto next_page;
 
+               hit_slowpath = 1;
+               page_cache_get(page);
+               mutex_unlock(&dev->struct_mutex);
+
+               ret = shmem_pwrite_slow(page, shmem_page_offset, page_length,
+                                       user_data, page_do_bit17_swizzling,
+                                       partial_cacheline_write,
+                                       needs_clflush_after);
+
+               mutex_lock(&dev->struct_mutex);
+               page_cache_release(page);
+next_page:
                set_page_dirty(page);
                mark_page_accessed(page);
-               page_cache_release(page);
+               if (release_page)
+                       page_cache_release(page);
 
                if (ret) {
                        ret = -EFAULT;
@@ -857,17 +819,21 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev,
        }
 
 out:
-       mutex_lock(&dev->struct_mutex);
-       /* Fixup: Kill any reinstated backing storage pages */
-       if (obj->madv == __I915_MADV_PURGED)
-               i915_gem_object_truncate(obj);
-       /* and flush dirty cachelines in case the object isn't in the cpu write
-        * domain anymore. */
-       if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
-               i915_gem_clflush_object(obj);
-               intel_gtt_chipset_flush();
+       if (hit_slowpath) {
+               /* Fixup: Kill any reinstated backing storage pages */
+               if (obj->madv == __I915_MADV_PURGED)
+                       i915_gem_object_truncate(obj);
+               /* and flush dirty cachelines in case the object isn't in the cpu write
+                * domain anymore. */
+               if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
+                       i915_gem_clflush_object(obj);
+                       intel_gtt_chipset_flush();
+               }
        }
 
+       if (needs_clflush_after)
+               intel_gtt_chipset_flush();
+
        return ret;
 }
 
@@ -892,8 +858,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
                       args->size))
                return -EFAULT;
 
-       ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr,
-                                     args->size);
+       ret = fault_in_multipages_readable((char __user *)(uintptr_t)args->data_ptr,
+                                          args->size);
        if (ret)
                return -EFAULT;
 
@@ -916,6 +882,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 
        trace_i915_gem_object_pwrite(obj, args->offset, args->size);
 
+       ret = -EFAULT;
        /* We can only do the GTT pwrite on untiled buffers, as otherwise
         * it would end up going through the fenced access, and we'll get
         * different detiling behavior between reading and writing.
@@ -928,42 +895,18 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
        }
 
        if (obj->gtt_space &&
+           obj->cache_level == I915_CACHE_NONE &&
+           obj->tiling_mode == I915_TILING_NONE &&
+           obj->map_and_fenceable &&
            obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
-               ret = i915_gem_object_pin(obj, 0, true);
-               if (ret)
-                       goto out;
-
-               ret = i915_gem_object_set_to_gtt_domain(obj, true);
-               if (ret)
-                       goto out_unpin;
-
-               ret = i915_gem_object_put_fence(obj);
-               if (ret)
-                       goto out_unpin;
-
                ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file);
-               if (ret == -EFAULT)
-                       ret = i915_gem_gtt_pwrite_slow(dev, obj, args, file);
-
-out_unpin:
-               i915_gem_object_unpin(obj);
-
-               if (ret != -EFAULT)
-                       goto out;
-               /* Fall through to the shmfs paths because the gtt paths might
-                * fail with non-page-backed user pointers (e.g. gtt mappings
-                * when moving data between textures). */
+               /* Note that the gtt paths might fail with non-page-backed user
+                * pointers (e.g. gtt mappings when moving data between
+                * textures). Fallback to the shmem path in that case. */
        }
 
-       ret = i915_gem_object_set_to_cpu_domain(obj, 1);
-       if (ret)
-               goto out;
-
-       ret = -EFAULT;
-       if (!i915_gem_object_needs_bit17_swizzle(obj))
-               ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file);
        if (ret == -EFAULT)
-               ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file);
+               ret = i915_gem_shmem_pwrite(dev, obj, args, file);
 
 out:
        drm_gem_object_unreference(&obj->base);
@@ -986,9 +929,6 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
        uint32_t write_domain = args->write_domain;
        int ret;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        /* Only handle setting domains to types used by the CPU. */
        if (write_domain & I915_GEM_GPU_DOMAINS)
                return -EINVAL;
@@ -1042,9 +982,6 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
        struct drm_i915_gem_object *obj;
        int ret = 0;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                return ret;
@@ -1080,18 +1017,13 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
        struct drm_gem_object *obj;
        unsigned long addr;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        obj = drm_gem_object_lookup(dev, file, args->handle);
        if (obj == NULL)
                return -ENOENT;
 
-       down_write(&current->mm->mmap_sem);
-       addr = do_mmap(obj->filp, 0, args->size,
+       addr = vm_mmap(obj->filp, 0, args->size,
                       PROT_READ | PROT_WRITE, MAP_SHARED,
                       args->offset);
-       up_write(&current->mm->mmap_sem);
        drm_gem_object_unreference_unlocked(obj);
        if (IS_ERR((void *)addr))
                return addr;
@@ -1153,10 +1085,10 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                        goto unlock;
        }
 
-       if (obj->tiling_mode == I915_TILING_NONE)
-               ret = i915_gem_object_put_fence(obj);
-       else
-               ret = i915_gem_object_get_fence(obj, NULL);
+       if (!obj->has_global_gtt_mapping)
+               i915_gem_gtt_bind_object(obj, obj->cache_level);
+
+       ret = i915_gem_object_get_fence(obj);
        if (ret)
                goto unlock;
 
@@ -1310,9 +1242,6 @@ i915_gem_mmap_gtt(struct drm_file *file,
        struct drm_i915_gem_object *obj;
        int ret;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                return ret;
@@ -1370,9 +1299,6 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
 {
        struct drm_i915_gem_mmap_gtt *args = data;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
        return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
 }
 
@@ -1472,16 +1398,18 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
        list_move_tail(&obj->ring_list, &ring->active_list);
 
        obj->last_rendering_seqno = seqno;
-       if (obj->fenced_gpu_access) {
-               struct drm_i915_fence_reg *reg;
-
-               BUG_ON(obj->fence_reg == I915_FENCE_REG_NONE);
 
+       if (obj->fenced_gpu_access) {
                obj->last_fenced_seqno = seqno;
-               obj->last_fenced_ring = ring;
 
-               reg = &dev_priv->fence_regs[obj->fence_reg];
-               list_move_tail(&reg->lru_list, &dev_priv->mm.fence_list);
+               /* Bump MRU to take account of the delayed flush */
+               if (obj->fence_reg != I915_FENCE_REG_NONE) {
+                       struct drm_i915_fence_reg *reg;
+
+                       reg = &dev_priv->fence_regs[obj->fence_reg];
+                       list_move_tail(&reg->lru_list,
+                                      &dev_priv->mm.fence_list);
+               }
        }
 }
 
@@ -1490,6 +1418,7 @@ i915_gem_object_move_off_active(struct drm_i915_gem_object *obj)
 {
        list_del_init(&obj->ring_list);
        obj->last_rendering_seqno = 0;
+       obj->last_fenced_seqno = 0;
 }
 
 static void
@@ -1510,10 +1439,7 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (obj->pin_count != 0)
-               list_move_tail(&obj->mm_list, &dev_priv->mm.pinned_list);
-       else
-               list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+       list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
        BUG_ON(!list_empty(&obj->gpu_write_list));
        BUG_ON(!obj->active);
@@ -1543,6 +1469,9 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)
        inode = obj->base.filp->f_path.dentry->d_inode;
        shmem_truncate_range(inode, 0, (loff_t)-1);
 
+       if (obj->base.map_list.map)
+               drm_gem_free_mmap_offset(&obj->base);
+
        obj->madv = __I915_MADV_PURGED;
 }
 
@@ -1708,20 +1637,18 @@ static void i915_gem_reset_fences(struct drm_device *dev)
 
        for (i = 0; i < dev_priv->num_fence_regs; i++) {
                struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
-               struct drm_i915_gem_object *obj = reg->obj;
 
-               if (!obj)
-                       continue;
+               i915_gem_write_fence(dev, i, NULL);
 
-               if (obj->tiling_mode)
-                       i915_gem_release_mmap(obj);
+               if (reg->obj)
+                       i915_gem_object_fence_lost(reg->obj);
 
-               reg->obj->fence_reg = I915_FENCE_REG_NONE;
-               reg->obj->fenced_gpu_access = false;
-               reg->obj->last_fenced_seqno = 0;
-               reg->obj->last_fenced_ring = NULL;
-               i915_gem_clear_fence_reg(dev, reg);
+               reg->pin_count = 0;
+               reg->obj = NULL;
+               INIT_LIST_HEAD(&reg->lru_list);
        }
+
+       INIT_LIST_HEAD(&dev_priv->mm.fence_list);
 }
 
 void i915_gem_reset(struct drm_device *dev)
@@ -1838,20 +1765,6 @@ i915_gem_retire_requests(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        int i;
 
-       if (!list_empty(&dev_priv->mm.deferred_free_list)) {
-           struct drm_i915_gem_object *obj, *next;
-
-           /* We must be careful that during unbind() we do not
-            * accidentally infinitely recurse into retire requests.
-            * Currently:
-            *   retire -> free -> unbind -> wait -> retire_ring
-            */
-           list_for_each_entry_safe(obj, next,
-                                    &dev_priv->mm.deferred_free_list,
-                                    mm_list)
-                   i915_gem_free_object_tail(obj);
-       }
-
        for (i = 0; i < I915_NUM_RINGS; i++)
                i915_gem_retire_requests_ring(&dev_priv->ring[i]);
 }
@@ -1904,20 +1817,10 @@ i915_gem_retire_work_handler(struct work_struct *work)
        mutex_unlock(&dev->struct_mutex);
 }
 
-/**
- * Waits for a sequence number to be signaled, and cleans up the
- * request and object lists appropriately for that event.
- */
-int
-i915_wait_request(struct intel_ring_buffer *ring,
-                 uint32_t seqno,
-                 bool do_retire)
+static int
+i915_gem_check_wedge(struct drm_i915_private *dev_priv)
 {
-       drm_i915_private_t *dev_priv = ring->dev->dev_private;
-       u32 ier;
-       int ret = 0;
-
-       BUG_ON(seqno == 0);
+       BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
        if (atomic_read(&dev_priv->mm.wedged)) {
                struct completion *x = &dev_priv->error_completion;
@@ -1932,6 +1835,20 @@ i915_wait_request(struct intel_ring_buffer *ring,
                return recovery_complete ? -EIO : -EAGAIN;
        }
 
+       return 0;
+}
+
+/*
+ * Compare seqno against outstanding lazy request. Emit a request if they are
+ * equal.
+ */
+static int
+i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
+{
+       int ret = 0;
+
+       BUG_ON(!mutex_is_locked(&ring->dev->struct_mutex));
+
        if (seqno == ring->outstanding_lazy_request) {
                struct drm_i915_gem_request *request;
 
@@ -1945,54 +1862,67 @@ i915_wait_request(struct intel_ring_buffer *ring,
                        return ret;
                }
 
-               seqno = request->seqno;
+               BUG_ON(seqno != request->seqno);
        }
 
-       if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {
-               if (HAS_PCH_SPLIT(ring->dev))
-                       ier = I915_READ(DEIER) | I915_READ(GTIER);
-               else
-                       ier = I915_READ(IER);
-               if (!ier) {
-                       DRM_ERROR("something (likely vbetool) disabled "
-                                 "interrupts, re-enabling\n");
-                       ring->dev->driver->irq_preinstall(ring->dev);
-                       ring->dev->driver->irq_postinstall(ring->dev);
-               }
+       return ret;
+}
 
-               trace_i915_gem_request_wait_begin(ring, seqno);
-
-               ring->waiting_seqno = seqno;
-               if (ring->irq_get(ring)) {
-                       if (dev_priv->mm.interruptible)
-                               ret = wait_event_interruptible(ring->irq_queue,
-                                                              i915_seqno_passed(ring->get_seqno(ring), seqno)
-                                                              || atomic_read(&dev_priv->mm.wedged));
-                       else
-                               wait_event(ring->irq_queue,
-                                          i915_seqno_passed(ring->get_seqno(ring), seqno)
-                                          || atomic_read(&dev_priv->mm.wedged));
-
-                       ring->irq_put(ring);
-               } else if (wait_for_atomic(i915_seqno_passed(ring->get_seqno(ring),
-                                                            seqno) ||
-                                          atomic_read(&dev_priv->mm.wedged), 3000))
-                       ret = -EBUSY;
-               ring->waiting_seqno = 0;
-
-               trace_i915_gem_request_wait_end(ring, seqno);
-       }
+static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
+                       bool interruptible)
+{
+       drm_i915_private_t *dev_priv = ring->dev->dev_private;
+       int ret = 0;
+
+       if (i915_seqno_passed(ring->get_seqno(ring), seqno))
+               return 0;
+
+       trace_i915_gem_request_wait_begin(ring, seqno);
+       if (WARN_ON(!ring->irq_get(ring)))
+               return -ENODEV;
+
+#define EXIT_COND \
+       (i915_seqno_passed(ring->get_seqno(ring), seqno) || \
+       atomic_read(&dev_priv->mm.wedged))
+
+       if (interruptible)
+               ret = wait_event_interruptible(ring->irq_queue,
+                                              EXIT_COND);
+       else
+               wait_event(ring->irq_queue, EXIT_COND);
+
+       ring->irq_put(ring);
+       trace_i915_gem_request_wait_end(ring, seqno);
+#undef EXIT_COND
+
+       return ret;
+}
+
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
+int
+i915_wait_request(struct intel_ring_buffer *ring,
+                 uint32_t seqno)
+{
+       drm_i915_private_t *dev_priv = ring->dev->dev_private;
+       int ret = 0;
+
+       BUG_ON(seqno == 0);
+
+       ret = i915_gem_check_wedge(dev_priv);
+       if (ret)
+               return ret;
+
+       ret = i915_gem_check_olr(ring, seqno);
+       if (ret)
+               return ret;
+
+       ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible);
        if (atomic_read(&dev_priv->mm.wedged))
                ret = -EAGAIN;
 
-       /* Directly dispatch request retiring.  While we have the work queue
-        * to handle this, the waiter on a request often wants an associated
-        * buffer to have made it to the inactive list, and we would need
-        * a separate wait queue to handle that.
-        */
-       if (ret == 0 && do_retire)
-               i915_gem_retire_requests_ring(ring);
-
        return ret;
 }
 
@@ -2014,15 +1944,58 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
         * it.
         */
        if (obj->active) {
-               ret = i915_wait_request(obj->ring, obj->last_rendering_seqno,
-                                       true);
+               ret = i915_wait_request(obj->ring, obj->last_rendering_seqno);
                if (ret)
                        return ret;
+               i915_gem_retire_requests_ring(obj->ring);
        }
 
        return 0;
 }
 
+/**
+ * i915_gem_object_sync - sync an object to a ring.
+ *
+ * @obj: object which may be in use on another ring.
+ * @to: ring we wish to use the object on. May be NULL.
+ *
+ * This code is meant to abstract object synchronization with the GPU.
+ * Calling with NULL implies synchronizing the object with the CPU
+ * rather than a particular GPU ring.
+ *
+ * Returns 0 if successful, else propagates up the lower layer error.
+ */
+int
+i915_gem_object_sync(struct drm_i915_gem_object *obj,
+                    struct intel_ring_buffer *to)
+{
+       struct intel_ring_buffer *from = obj->ring;
+       u32 seqno;
+       int ret, idx;
+
+       if (from == NULL || to == from)
+               return 0;
+
+       if (to == NULL || !i915_semaphore_is_enabled(obj->base.dev))
+               return i915_gem_object_wait_rendering(obj);
+
+       idx = intel_ring_sync_index(from, to);
+
+       seqno = obj->last_rendering_seqno;
+       if (seqno <= from->sync_seqno[idx])
+               return 0;
+
+       ret = i915_gem_check_olr(obj->ring, seqno);
+       if (ret)
+               return ret;
+
+       ret = to->sync_to(to, from, seqno);
+       if (!ret)
+               from->sync_seqno[idx] = seqno;
+
+       return ret;
+}
+
 static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
 {
        u32 old_write_domain, old_read_domains;
@@ -2065,7 +2038,7 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
        }
 
        ret = i915_gem_object_finish_gpu(obj);
-       if (ret == -ERESTARTSYS)
+       if (ret)
                return ret;
        /* Continue on if we fail due to EIO, the GPU is hung so we
         * should be safe and we need to cleanup or else we might
@@ -2092,16 +2065,18 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 
        /* release the fence reg _after_ flushing */
        ret = i915_gem_object_put_fence(obj);
-       if (ret == -ERESTARTSYS)
+       if (ret)
                return ret;
 
        trace_i915_gem_object_unbind(obj);
 
-       i915_gem_gtt_unbind_object(obj);
+       if (obj->has_global_gtt_mapping)
+               i915_gem_gtt_unbind_object(obj);
        if (obj->has_aliasing_ppgtt_mapping) {
                i915_ppgtt_unbind_object(dev_priv->mm.aliasing_ppgtt, obj);
                obj->has_aliasing_ppgtt_mapping = 0;
        }
+       i915_gem_gtt_finish_object(obj);
 
        i915_gem_object_put_pages_gtt(obj);
 
@@ -2142,7 +2117,7 @@ i915_gem_flush_ring(struct intel_ring_buffer *ring,
        return 0;
 }
 
-static int i915_ring_idle(struct intel_ring_buffer *ring, bool do_retire)
+static int i915_ring_idle(struct intel_ring_buffer *ring)
 {
        int ret;
 
@@ -2156,18 +2131,17 @@ static int i915_ring_idle(struct intel_ring_buffer *ring, bool do_retire)
                        return ret;
        }
 
-       return i915_wait_request(ring, i915_gem_next_request_seqno(ring),
-                                do_retire);
+       return i915_wait_request(ring, i915_gem_next_request_seqno(ring));
 }
 
-int i915_gpu_idle(struct drm_device *dev, bool do_retire)
+int i915_gpu_idle(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        int ret, i;
 
        /* Flush everything onto the inactive list. */
        for (i = 0; i < I915_NUM_RINGS; i++) {
-               ret = i915_ring_idle(&dev_priv->ring[i], do_retire);
+               ret = i915_ring_idle(&dev_priv->ring[i]);
                if (ret)
                        return ret;
        }
@@ -2175,189 +2149,178 @@ int i915_gpu_idle(struct drm_device *dev, bool do_retire)
        return 0;
 }
 
-static int sandybridge_write_fence_reg(struct drm_i915_gem_object *obj,
-                                      struct intel_ring_buffer *pipelined)
+static void sandybridge_write_fence_reg(struct drm_device *dev, int reg,
+                                       struct drm_i915_gem_object *obj)
 {
-       struct drm_device *dev = obj->base.dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u32 size = obj->gtt_space->size;
-       int regnum = obj->fence_reg;
        uint64_t val;
 
-       val = (uint64_t)((obj->gtt_offset + size - 4096) &
-                        0xfffff000) << 32;
-       val |= obj->gtt_offset & 0xfffff000;
-       val |= (uint64_t)((obj->stride / 128) - 1) <<
-               SANDYBRIDGE_FENCE_PITCH_SHIFT;
+       if (obj) {
+               u32 size = obj->gtt_space->size;
 
-       if (obj->tiling_mode == I915_TILING_Y)
-               val |= 1 << I965_FENCE_TILING_Y_SHIFT;
-       val |= I965_FENCE_REG_VALID;
+               val = (uint64_t)((obj->gtt_offset + size - 4096) &
+                                0xfffff000) << 32;
+               val |= obj->gtt_offset & 0xfffff000;
+               val |= (uint64_t)((obj->stride / 128) - 1) <<
+                       SANDYBRIDGE_FENCE_PITCH_SHIFT;
 
-       if (pipelined) {
-               int ret = intel_ring_begin(pipelined, 6);
-               if (ret)
-                       return ret;
-
-               intel_ring_emit(pipelined, MI_NOOP);
-               intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(2));
-               intel_ring_emit(pipelined, FENCE_REG_SANDYBRIDGE_0 + regnum*8);
-               intel_ring_emit(pipelined, (u32)val);
-               intel_ring_emit(pipelined, FENCE_REG_SANDYBRIDGE_0 + regnum*8 + 4);
-               intel_ring_emit(pipelined, (u32)(val >> 32));
-               intel_ring_advance(pipelined);
+               if (obj->tiling_mode == I915_TILING_Y)
+                       val |= 1 << I965_FENCE_TILING_Y_SHIFT;
+               val |= I965_FENCE_REG_VALID;
        } else
-               I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + regnum * 8, val);
+               val = 0;
 
-       return 0;
+       I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + reg * 8, val);
+       POSTING_READ(FENCE_REG_SANDYBRIDGE_0 + reg * 8);
 }
 
-static int i965_write_fence_reg(struct drm_i915_gem_object *obj,
-                               struct intel_ring_buffer *pipelined)
+static void i965_write_fence_reg(struct drm_device *dev, int reg,
+                                struct drm_i915_gem_object *obj)
 {
-       struct drm_device *dev = obj->base.dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u32 size = obj->gtt_space->size;
-       int regnum = obj->fence_reg;
        uint64_t val;
 
-       val = (uint64_t)((obj->gtt_offset + size - 4096) &
-                   0xfffff000) << 32;
-       val |= obj->gtt_offset & 0xfffff000;
-       val |= ((obj->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT;
-       if (obj->tiling_mode == I915_TILING_Y)
-               val |= 1 << I965_FENCE_TILING_Y_SHIFT;
-       val |= I965_FENCE_REG_VALID;
-
-       if (pipelined) {
-               int ret = intel_ring_begin(pipelined, 6);
-               if (ret)
-                       return ret;
+       if (obj) {
+               u32 size = obj->gtt_space->size;
 
-               intel_ring_emit(pipelined, MI_NOOP);
-               intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(2));
-               intel_ring_emit(pipelined, FENCE_REG_965_0 + regnum*8);
-               intel_ring_emit(pipelined, (u32)val);
-               intel_ring_emit(pipelined, FENCE_REG_965_0 + regnum*8 + 4);
-               intel_ring_emit(pipelined, (u32)(val >> 32));
-               intel_ring_advance(pipelined);
+               val = (uint64_t)((obj->gtt_offset + size - 4096) &
+                                0xfffff000) << 32;
+               val |= obj->gtt_offset & 0xfffff000;
+               val |= ((obj->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT;
+               if (obj->tiling_mode == I915_TILING_Y)
+                       val |= 1 << I965_FENCE_TILING_Y_SHIFT;
+               val |= I965_FENCE_REG_VALID;
        } else
-               I915_WRITE64(FENCE_REG_965_0 + regnum * 8, val);
+               val = 0;
 
-       return 0;
+       I915_WRITE64(FENCE_REG_965_0 + reg * 8, val);
+       POSTING_READ(FENCE_REG_965_0 + reg * 8);
 }
 
-static int i915_write_fence_reg(struct drm_i915_gem_object *obj,
-                               struct intel_ring_buffer *pipelined)
+static void i915_write_fence_reg(struct drm_device *dev, int reg,
+                                struct drm_i915_gem_object *obj)
 {
-       struct drm_device *dev = obj->base.dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u32 size = obj->gtt_space->size;
-       u32 fence_reg, val, pitch_val;
-       int tile_width;
-
-       if (WARN((obj->gtt_offset & ~I915_FENCE_START_MASK) ||
-                (size & -size) != size ||
-                (obj->gtt_offset & (size - 1)),
-                "object 0x%08x [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n",
-                obj->gtt_offset, obj->map_and_fenceable, size))
-               return -EINVAL;
+       u32 val;
 
-       if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
-               tile_width = 128;
-       else
-               tile_width = 512;
-
-       /* Note: pitch better be a power of two tile widths */
-       pitch_val = obj->stride / tile_width;
-       pitch_val = ffs(pitch_val) - 1;
-
-       val = obj->gtt_offset;
-       if (obj->tiling_mode == I915_TILING_Y)
-               val |= 1 << I830_FENCE_TILING_Y_SHIFT;
-       val |= I915_FENCE_SIZE_BITS(size);
-       val |= pitch_val << I830_FENCE_PITCH_SHIFT;
-       val |= I830_FENCE_REG_VALID;
-
-       fence_reg = obj->fence_reg;
-       if (fence_reg < 8)
-               fence_reg = FENCE_REG_830_0 + fence_reg * 4;
-       else
-               fence_reg = FENCE_REG_945_8 + (fence_reg - 8) * 4;
+       if (obj) {
+               u32 size = obj->gtt_space->size;
+               int pitch_val;
+               int tile_width;
 
-       if (pipelined) {
-               int ret = intel_ring_begin(pipelined, 4);
-               if (ret)
-                       return ret;
+               WARN((obj->gtt_offset & ~I915_FENCE_START_MASK) ||
+                    (size & -size) != size ||
+                    (obj->gtt_offset & (size - 1)),
+                    "object 0x%08x [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n",
+                    obj->gtt_offset, obj->map_and_fenceable, size);
 
-               intel_ring_emit(pipelined, MI_NOOP);
-               intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit(pipelined, fence_reg);
-               intel_ring_emit(pipelined, val);
-               intel_ring_advance(pipelined);
+               if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
+                       tile_width = 128;
+               else
+                       tile_width = 512;
+
+               /* Note: pitch better be a power of two tile widths */
+               pitch_val = obj->stride / tile_width;
+               pitch_val = ffs(pitch_val) - 1;
+
+               val = obj->gtt_offset;
+               if (obj->tiling_mode == I915_TILING_Y)
+                       val |= 1 << I830_FENCE_TILING_Y_SHIFT;
+               val |= I915_FENCE_SIZE_BITS(size);
+               val |= pitch_val << I830_FENCE_PITCH_SHIFT;
+               val |= I830_FENCE_REG_VALID;
        } else
-               I915_WRITE(fence_reg, val);
+               val = 0;
 
-       return 0;
+       if (reg < 8)
+               reg = FENCE_REG_830_0 + reg * 4;
+       else
+               reg = FENCE_REG_945_8 + (reg - 8) * 4;
+
+       I915_WRITE(reg, val);
+       POSTING_READ(reg);
 }
 
-static int i830_write_fence_reg(struct drm_i915_gem_object *obj,
-                               struct intel_ring_buffer *pipelined)
+static void i830_write_fence_reg(struct drm_device *dev, int reg,
+                               struct drm_i915_gem_object *obj)
 {
-       struct drm_device *dev = obj->base.dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u32 size = obj->gtt_space->size;
-       int regnum = obj->fence_reg;
        uint32_t val;
-       uint32_t pitch_val;
 
-       if (WARN((obj->gtt_offset & ~I830_FENCE_START_MASK) ||
-                (size & -size) != size ||
-                (obj->gtt_offset & (size - 1)),
-                "object 0x%08x not 512K or pot-size 0x%08x aligned\n",
-                obj->gtt_offset, size))
-               return -EINVAL;
-
-       pitch_val = obj->stride / 128;
-       pitch_val = ffs(pitch_val) - 1;
-
-       val = obj->gtt_offset;
-       if (obj->tiling_mode == I915_TILING_Y)
-               val |= 1 << I830_FENCE_TILING_Y_SHIFT;
-       val |= I830_FENCE_SIZE_BITS(size);
-       val |= pitch_val << I830_FENCE_PITCH_SHIFT;
-       val |= I830_FENCE_REG_VALID;
+       if (obj) {
+               u32 size = obj->gtt_space->size;
+               uint32_t pitch_val;
+
+               WARN((obj->gtt_offset & ~I830_FENCE_START_MASK) ||
+                    (size & -size) != size ||
+                    (obj->gtt_offset & (size - 1)),
+                    "object 0x%08x not 512K or pot-size 0x%08x aligned\n",
+                    obj->gtt_offset, size);
+
+               pitch_val = obj->stride / 128;
+               pitch_val = ffs(pitch_val) - 1;
+
+               val = obj->gtt_offset;
+               if (obj->tiling_mode == I915_TILING_Y)
+                       val |= 1 << I830_FENCE_TILING_Y_SHIFT;
+               val |= I830_FENCE_SIZE_BITS(size);
+               val |= pitch_val << I830_FENCE_PITCH_SHIFT;
+               val |= I830_FENCE_REG_VALID;
+       } else
+               val = 0;
 
-       if (pipelined) {
-               int ret = intel_ring_begin(pipelined, 4);
-               if (ret)
-                       return ret;
+       I915_WRITE(FENCE_REG_830_0 + reg * 4, val);
+       POSTING_READ(FENCE_REG_830_0 + reg * 4);
+}
 
-               intel_ring_emit(pipelined, MI_NOOP);
-               intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit(pipelined, FENCE_REG_830_0 + regnum*4);
-               intel_ring_emit(pipelined, val);
-               intel_ring_advance(pipelined);
-       } else
-               I915_WRITE(FENCE_REG_830_0 + regnum * 4, val);
+static void i915_gem_write_fence(struct drm_device *dev, int reg,
+                                struct drm_i915_gem_object *obj)
+{
+       switch (INTEL_INFO(dev)->gen) {
+       case 7:
+       case 6: sandybridge_write_fence_reg(dev, reg, obj); break;
+       case 5:
+       case 4: i965_write_fence_reg(dev, reg, obj); break;
+       case 3: i915_write_fence_reg(dev, reg, obj); break;
+       case 2: i830_write_fence_reg(dev, reg, obj); break;
+       default: break;
+       }
+}
 
-       return 0;
+static inline int fence_number(struct drm_i915_private *dev_priv,
+                              struct drm_i915_fence_reg *fence)
+{
+       return fence - dev_priv->fence_regs;
 }
 
-static bool ring_passed_seqno(struct intel_ring_buffer *ring, u32 seqno)
+static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
+                                        struct drm_i915_fence_reg *fence,
+                                        bool enable)
 {
-       return i915_seqno_passed(ring->get_seqno(ring), seqno);
+       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+       int reg = fence_number(dev_priv, fence);
+
+       i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL);
+
+       if (enable) {
+               obj->fence_reg = reg;
+               fence->obj = obj;
+               list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
+       } else {
+               obj->fence_reg = I915_FENCE_REG_NONE;
+               fence->obj = NULL;
+               list_del_init(&fence->lru_list);
+       }
 }
 
 static int
-i915_gem_object_flush_fence(struct drm_i915_gem_object *obj,
-                           struct intel_ring_buffer *pipelined)
+i915_gem_object_flush_fence(struct drm_i915_gem_object *obj)
 {
        int ret;
 
        if (obj->fenced_gpu_access) {
                if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-                       ret = i915_gem_flush_ring(obj->last_fenced_ring,
+                       ret = i915_gem_flush_ring(obj->ring,
                                                  0, obj->base.write_domain);
                        if (ret)
                                return ret;
@@ -2366,18 +2329,12 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj,
                obj->fenced_gpu_access = false;
        }
 
-       if (obj->last_fenced_seqno && pipelined != obj->last_fenced_ring) {
-               if (!ring_passed_seqno(obj->last_fenced_ring,
-                                      obj->last_fenced_seqno)) {
-                       ret = i915_wait_request(obj->last_fenced_ring,
-                                               obj->last_fenced_seqno,
-                                               true);
-                       if (ret)
-                               return ret;
-               }
+       if (obj->last_fenced_seqno) {
+               ret = i915_wait_request(obj->ring, obj->last_fenced_seqno);
+               if (ret)
+                       return ret;
 
                obj->last_fenced_seqno = 0;
-               obj->last_fenced_ring = NULL;
        }
 
        /* Ensure that all CPU reads are completed before installing a fence
@@ -2392,34 +2349,29 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj,
 int
 i915_gem_object_put_fence(struct drm_i915_gem_object *obj)
 {
+       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
        int ret;
 
-       if (obj->tiling_mode)
-               i915_gem_release_mmap(obj);
-
-       ret = i915_gem_object_flush_fence(obj, NULL);
+       ret = i915_gem_object_flush_fence(obj);
        if (ret)
                return ret;
 
-       if (obj->fence_reg != I915_FENCE_REG_NONE) {
-               struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-
-               WARN_ON(dev_priv->fence_regs[obj->fence_reg].pin_count);
-               i915_gem_clear_fence_reg(obj->base.dev,
-                                        &dev_priv->fence_regs[obj->fence_reg]);
+       if (obj->fence_reg == I915_FENCE_REG_NONE)
+               return 0;
 
-               obj->fence_reg = I915_FENCE_REG_NONE;
-       }
+       i915_gem_object_update_fence(obj,
+                                    &dev_priv->fence_regs[obj->fence_reg],
+                                    false);
+       i915_gem_object_fence_lost(obj);
 
        return 0;
 }
 
 static struct drm_i915_fence_reg *
-i915_find_fence_reg(struct drm_device *dev,
-                   struct intel_ring_buffer *pipelined)
+i915_find_fence_reg(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_fence_reg *reg, *first, *avail;
+       struct drm_i915_fence_reg *reg, *avail;
        int i;
 
        /* First try to find a free reg */
@@ -2437,204 +2389,77 @@ i915_find_fence_reg(struct drm_device *dev,
                return NULL;
 
        /* None available, try to steal one or wait for a user to finish */
-       avail = first = NULL;
        list_for_each_entry(reg, &dev_priv->mm.fence_list, lru_list) {
                if (reg->pin_count)
                        continue;
 
-               if (first == NULL)
-                       first = reg;
-
-               if (!pipelined ||
-                   !reg->obj->last_fenced_ring ||
-                   reg->obj->last_fenced_ring == pipelined) {
-                       avail = reg;
-                       break;
-               }
+               return reg;
        }
 
-       if (avail == NULL)
-               avail = first;
-
-       return avail;
+       return NULL;
 }
 
 /**
- * i915_gem_object_get_fence - set up a fence reg for an object
+ * i915_gem_object_get_fence - set up fencing for an object
  * @obj: object to map through a fence reg
- * @pipelined: ring on which to queue the change, or NULL for CPU access
- * @interruptible: must we wait uninterruptibly for the register to retire?
  *
  * When mapping objects through the GTT, userspace wants to be able to write
  * to them without having to worry about swizzling if the object is tiled.
- *
  * This function walks the fence regs looking for a free one for @obj,
  * stealing one if it can't find any.
  *
  * It then sets up the reg based on the object's properties: address, pitch
  * and tiling format.
+ *
+ * For an untiled surface, this removes any existing fence.
  */
 int
-i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
-                         struct intel_ring_buffer *pipelined)
+i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
 {
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       bool enable = obj->tiling_mode != I915_TILING_NONE;
        struct drm_i915_fence_reg *reg;
        int ret;
 
-       /* XXX disable pipelining. There are bugs. Shocking. */
-       pipelined = NULL;
+       /* Have we updated the tiling parameters upon the object and so
+        * will need to serialise the write to the associated fence register?
+        */
+       if (obj->fence_dirty) {
+               ret = i915_gem_object_flush_fence(obj);
+               if (ret)
+                       return ret;
+       }
 
        /* Just update our place in the LRU if our fence is getting reused. */
        if (obj->fence_reg != I915_FENCE_REG_NONE) {
                reg = &dev_priv->fence_regs[obj->fence_reg];
-               list_move_tail(&reg->lru_list, &dev_priv->mm.fence_list);
-
-               if (obj->tiling_changed) {
-                       ret = i915_gem_object_flush_fence(obj, pipelined);
-                       if (ret)
-                               return ret;
-
-                       if (!obj->fenced_gpu_access && !obj->last_fenced_seqno)
-                               pipelined = NULL;
-
-                       if (pipelined) {
-                               reg->setup_seqno =
-                                       i915_gem_next_request_seqno(pipelined);
-                               obj->last_fenced_seqno = reg->setup_seqno;
-                               obj->last_fenced_ring = pipelined;
-                       }
-
-                       goto update;
+               if (!obj->fence_dirty) {
+                       list_move_tail(&reg->lru_list,
+                                      &dev_priv->mm.fence_list);
+                       return 0;
                }
+       } else if (enable) {
+               reg = i915_find_fence_reg(dev);
+               if (reg == NULL)
+                       return -EDEADLK;
 
-               if (!pipelined) {
-                       if (reg->setup_seqno) {
-                               if (!ring_passed_seqno(obj->last_fenced_ring,
-                                                      reg->setup_seqno)) {
-                                       ret = i915_wait_request(obj->last_fenced_ring,
-                                                               reg->setup_seqno,
-                                                               true);
-                                       if (ret)
-                                               return ret;
-                               }
+               if (reg->obj) {
+                       struct drm_i915_gem_object *old = reg->obj;
 
-                               reg->setup_seqno = 0;
-                       }
-               } else if (obj->last_fenced_ring &&
-                          obj->last_fenced_ring != pipelined) {
-                       ret = i915_gem_object_flush_fence(obj, pipelined);
+                       ret = i915_gem_object_flush_fence(old);
                        if (ret)
                                return ret;
-               }
-
-               return 0;
-       }
 
-       reg = i915_find_fence_reg(dev, pipelined);
-       if (reg == NULL)
-               return -EDEADLK;
-
-       ret = i915_gem_object_flush_fence(obj, pipelined);
-       if (ret)
-               return ret;
-
-       if (reg->obj) {
-               struct drm_i915_gem_object *old = reg->obj;
-
-               drm_gem_object_reference(&old->base);
-
-               if (old->tiling_mode)
-                       i915_gem_release_mmap(old);
-
-               ret = i915_gem_object_flush_fence(old, pipelined);
-               if (ret) {
-                       drm_gem_object_unreference(&old->base);
-                       return ret;
+                       i915_gem_object_fence_lost(old);
                }
+       } else
+               return 0;
 
-               if (old->last_fenced_seqno == 0 && obj->last_fenced_seqno == 0)
-                       pipelined = NULL;
-
-               old->fence_reg = I915_FENCE_REG_NONE;
-               old->last_fenced_ring = pipelined;
-               old->last_fenced_seqno =
-                       pipelined ? i915_gem_next_request_seqno(pipelined) : 0;
-
-               drm_gem_object_unreference(&old->base);
-       } else if (obj->last_fenced_seqno == 0)
-               pipelined = NULL;
-
-       reg->obj = obj;
-       list_move_tail(&reg->lru_list, &dev_priv->mm.fence_list);
-       obj->fence_reg = reg - dev_priv->fence_regs;
-       obj->last_fenced_ring = pipelined;
-
-       reg->setup_seqno =
-               pipelined ? i915_gem_next_request_seqno(pipelined) : 0;
-       obj->last_fenced_seqno = reg->setup_seqno;
-
-update:
-       obj->tiling_changed = false;
-       switch (INTEL_INFO(dev)->gen) {
-       case 7:
-       case 6:
-               ret = sandybridge_write_fence_reg(obj, pipelined);
-               break;
-       case 5:
-       case 4:
-               ret = i965_write_fence_reg(obj, pipelined);
-               break;
-       case 3:
-               ret = i915_write_fence_reg(obj, pipelined);
-               break;
-       case 2:
-               ret = i830_write_fence_reg(obj, pipelined);
-               break;
-       }
-
-       return ret;
-}
-
-/**
- * i915_gem_clear_fence_reg - clear out fence register info
- * @obj: object to clear
- *
- * Zeroes out the fence register itself and clears out the associated
- * data structures in dev_priv and obj.
- */
-static void
-i915_gem_clear_fence_reg(struct drm_device *dev,
-                        struct drm_i915_fence_reg *reg)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       uint32_t fence_reg = reg - dev_priv->fence_regs;
-
-       switch (INTEL_INFO(dev)->gen) {
-       case 7:
-       case 6:
-               I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + fence_reg*8, 0);
-               break;
-       case 5:
-       case 4:
-               I915_WRITE64(FENCE_REG_965_0 + fence_reg*8, 0);
-               break;
-       case 3:
-               if (fence_reg >= 8)
-                       fence_reg = FENCE_REG_945_8 + (fence_reg - 8) * 4;
-               else
-       case 2:
-                       fence_reg = FENCE_REG_830_0 + fence_reg * 4;
-
-               I915_WRITE(fence_reg, 0);
-               break;
-       }
+       i915_gem_object_update_fence(obj, reg, enable);
+       obj->fence_dirty = false;
 
-       list_del_init(&reg->lru_list);
-       reg->obj = NULL;
-       reg->setup_seqno = 0;
-       reg->pin_count = 0;
+       return 0;
 }
 
 /**
@@ -2746,7 +2571,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
                return ret;
        }
 
-       ret = i915_gem_gtt_bind_object(obj);
+       ret = i915_gem_gtt_prepare_object(obj);
        if (ret) {
                i915_gem_object_put_pages_gtt(obj);
                drm_mm_put_block(obj->gtt_space);
@@ -2758,6 +2583,9 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
                goto search_free;
        }
 
+       if (!dev_priv->mm.aliasing_ppgtt)
+               i915_gem_gtt_bind_object(obj, obj->cache_level);
+
        list_add_tail(&obj->gtt_list, &dev_priv->mm.gtt_list);
        list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
@@ -2875,6 +2703,7 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
 int
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 {
+       drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
        uint32_t old_write_domain, old_read_domains;
        int ret;
 
@@ -2915,6 +2744,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
                                            old_read_domains,
                                            old_write_domain);
 
+       /* And bump the LRU for this access */
+       if (i915_gem_object_is_inactive(obj))
+               list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+
        return 0;
 }
 
@@ -2950,7 +2783,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
                                return ret;
                }
 
-               i915_gem_gtt_rebind_object(obj, cache_level);
+               if (obj->has_global_gtt_mapping)
+                       i915_gem_gtt_bind_object(obj, cache_level);
                if (obj->has_aliasing_ppgtt_mapping)
                        i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
                                               obj, cache_level);
@@ -2987,11 +2821,6 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
  * Prepare buffer for display plane (scanout, cursors, etc).
  * Can be called from an uninterruptible phase (modesetting) and allows
  * any flushes to be pipelined (for pageflips).
- *
- * For the display plane, we want to be in the GTT but out of any write
- * domains. So in many ways this looks like set_to_gtt_domain() apart from the
- * ability to pipeline the waits, pinning and any additional subtleties
- * that may differentiate the display plane from ordinary buffers.
  */
 int
 i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
@@ -3006,8 +2835,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                return ret;
 
        if (pipelined != obj->ring) {
-               ret = i915_gem_object_wait_rendering(obj);
-               if (ret == -ERESTARTSYS)
+               ret = i915_gem_object_sync(obj, pipelined);
+               if (ret)
                        return ret;
        }
 
@@ -3079,7 +2908,7 @@ i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
  * This function returns when the move is complete, including waiting on
  * flushes to occur.
  */
-static int
+int
 i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
 {
        uint32_t old_write_domain, old_read_domains;
@@ -3092,17 +2921,14 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
        if (ret)
                return ret;
 
-       ret = i915_gem_object_wait_rendering(obj);
-       if (ret)
-               return ret;
+       if (write || obj->pending_gpu_write) {
+               ret = i915_gem_object_wait_rendering(obj);
+               if (ret)
+                       return ret;
+       }
 
        i915_gem_object_flush_gtt_write_domain(obj);
 
-       /* If we have a partially-valid cache of the object in the CPU,
-        * finish invalidating it and free the per-page flags.
-        */
-       i915_gem_object_set_to_full_cpu_read_domain(obj);
-
        old_write_domain = obj->base.write_domain;
        old_read_domains = obj->base.read_domains;
 
@@ -3133,113 +2959,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
        return 0;
 }
 
-/**
- * Moves the object from a partially CPU read to a full one.
- *
- * Note that this only resolves i915_gem_object_set_cpu_read_domain_range(),
- * and doesn't handle transitioning from !(read_domains & I915_GEM_DOMAIN_CPU).
- */
-static void
-i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj)
-{
-       if (!obj->page_cpu_valid)
-               return;
-
-       /* If we're partially in the CPU read domain, finish moving it in.
-        */
-       if (obj->base.read_domains & I915_GEM_DOMAIN_CPU) {
-               int i;
-
-               for (i = 0; i <= (obj->base.size - 1) / PAGE_SIZE; i++) {
-                       if (obj->page_cpu_valid[i])
-                               continue;
-                       drm_clflush_pages(obj->pages + i, 1);
-               }
-       }
-
-       /* Free the page_cpu_valid mappings which are now stale, whether
-        * or not we've got I915_GEM_DOMAIN_CPU.
-        */
-       kfree(obj->page_cpu_valid);
-       obj->page_cpu_valid = NULL;
-}
-
-/**
- * Set the CPU read domain on a range of the object.
- *
- * The object ends up with I915_GEM_DOMAIN_CPU in its read flags although it's
- * not entirely valid.  The page_cpu_valid member of the object flags which
- * pages have been flushed, and will be respected by
- * i915_gem_object_set_to_cpu_domain() if it's called on to get a valid mapping
- * of the whole object.
- *
- * This function returns when the move is complete, including waiting on
- * flushes to occur.
- */
-static int
-i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj,
-                                         uint64_t offset, uint64_t size)
-{
-       uint32_t old_read_domains;
-       int i, ret;
-
-       if (offset == 0 && size == obj->base.size)
-               return i915_gem_object_set_to_cpu_domain(obj, 0);
-
-       ret = i915_gem_object_flush_gpu_write_domain(obj);
-       if (ret)
-               return ret;
-
-       ret = i915_gem_object_wait_rendering(obj);
-       if (ret)
-               return ret;
-
-       i915_gem_object_flush_gtt_write_domain(obj);
-
-       /* If we're already fully in the CPU read domain, we're done. */
-       if (obj->page_cpu_valid == NULL &&
-           (obj->base.read_domains & I915_GEM_DOMAIN_CPU) != 0)
-               return 0;
-
-       /* Otherwise, create/clear the per-page CPU read domain flag if we're
-        * newly adding I915_GEM_DOMAIN_CPU
-        */
-       if (obj->page_cpu_valid == NULL) {
-               obj->page_cpu_valid = kzalloc(obj->base.size / PAGE_SIZE,
-                                             GFP_KERNEL);
-               if (obj->page_cpu_valid == NULL)
-                       return -ENOMEM;
-       } else if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0)
-               memset(obj->page_cpu_valid, 0, obj->base.size / PAGE_SIZE);
-
-       /* Flush the cache on any pages that are still invalid from the CPU's
-        * perspective.
-        */
-       for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE;
-            i++) {
-               if (obj->page_cpu_valid[i])
-                       continue;
-
-               drm_clflush_pages(obj->pages + i, 1);
-
-               obj->page_cpu_valid[i] = 1;
-       }
-
-       /* It should now be out of any other write domains, and we can update
-        * the domain values for our changes.
-        */
-       BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
-
-       old_read_domains = obj->base.read_domains;
-       obj->base.read_domains |= I915_GEM_DOMAIN_CPU;
-
-       trace_i915_gem_object_change_domain(obj,
-                                           old_read_domains,
-                                           obj->base.write_domain);
-
-       return 0;
-}
-
 /* Throttle our rendering by waiting until the ring has completed our requests
  * emitted over 20 msec ago.
  *
@@ -3277,28 +2996,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
        if (seqno == 0)
                return 0;
 
-       ret = 0;
-       if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {
-               /* And wait for the seqno passing without holding any locks and
-                * causing extra latency for others. This is safe as the irq
-                * generation is designed to be run atomically and so is
-                * lockless.
-                */
-               if (ring->irq_get(ring)) {
-                       ret = wait_event_interruptible(ring->irq_queue,
-                                                      i915_seqno_passed(ring->get_seqno(ring), seqno)
-                                                      || atomic_read(&dev_priv->mm.wedged));
-                       ring->irq_put(ring);
-
-                       if (ret == 0 && atomic_read(&dev_priv->mm.wedged))
-                               ret = -EIO;
-               } else if (wait_for_atomic(i915_seqno_passed(ring->get_seqno(ring),
-                                                            seqno) ||
-                                   atomic_read(&dev_priv->mm.wedged), 3000)) {
-                       ret = -EBUSY;
-               }
-       }
-
+       ret = __wait_seqno(ring, seqno, true);
        if (ret == 0)
                queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0);
 
@@ -3310,12 +3008,9 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
                    uint32_t alignment,
                    bool map_and_fenceable)
 {
-       struct drm_device *dev = obj->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
        BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
-       WARN_ON(i915_verify_lists(dev));
 
        if (obj->gtt_space != NULL) {
                if ((alignment && obj->gtt_offset & (alignment - 1)) ||
@@ -3340,34 +3035,23 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
                        return ret;
        }
 
-       if (obj->pin_count++ == 0) {
-               if (!obj->active)
-                       list_move_tail(&obj->mm_list,
-                                      &dev_priv->mm.pinned_list);
-       }
+       if (!obj->has_global_gtt_mapping && map_and_fenceable)
+               i915_gem_gtt_bind_object(obj, obj->cache_level);
+
+       obj->pin_count++;
        obj->pin_mappable |= map_and_fenceable;
 
-       WARN_ON(i915_verify_lists(dev));
        return 0;
 }
 
 void
 i915_gem_object_unpin(struct drm_i915_gem_object *obj)
 {
-       struct drm_device *dev = obj->base.dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       WARN_ON(i915_verify_lists(dev));
        BUG_ON(obj->pin_count == 0);
        BUG_ON(obj->gtt_space == NULL);
 
-       if (--obj->pin_count == 0) {
-               if (!obj->active)
-                       list_move_tail(&obj->mm_list,
-                                      &dev_priv->mm.inactive_list);
+       if (--obj->pin_count == 0)
                obj->pin_mappable = false;
-       }
-       WARN_ON(i915_verify_lists(dev));
 }
 
 int
@@ -3491,20 +3175,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
                if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
                        ret = i915_gem_flush_ring(obj->ring,
                                                  0, obj->base.write_domain);
-               } else if (obj->ring->outstanding_lazy_request ==
-                          obj->last_rendering_seqno) {
-                       struct drm_i915_gem_request *request;
-
-                       /* This ring is not being cleared by active usage,
-                        * so emit a request to do so.
-                        */
-                       request = kzalloc(sizeof(*request), GFP_KERNEL);
-                       if (request) {
-                               ret = i915_add_request(obj->ring, NULL, request);
-                               if (ret)
-                                       kfree(request);
-                       } else
-                               ret = -ENOMEM;
+               } else {
+                       ret = i915_gem_check_olr(obj->ring,
+                                                obj->last_rendering_seqno);
                }
 
                /* Update the active list for the hardware's current position.
@@ -3640,46 +3313,39 @@ int i915_gem_init_object(struct drm_gem_object *obj)
        return 0;
 }
 
-static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj)
+void i915_gem_free_object(struct drm_gem_object *gem_obj)
 {
+       struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
        struct drm_device *dev = obj->base.dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       int ret;
-
-       ret = i915_gem_object_unbind(obj);
-       if (ret == -ERESTARTSYS) {
-               list_move(&obj->mm_list,
-                         &dev_priv->mm.deferred_free_list);
-               return;
-       }
 
        trace_i915_gem_object_destroy(obj);
 
+       if (obj->phys_obj)
+               i915_gem_detach_phys_object(dev, obj);
+
+       obj->pin_count = 0;
+       if (WARN_ON(i915_gem_object_unbind(obj) == -ERESTARTSYS)) {
+               bool was_interruptible;
+
+               was_interruptible = dev_priv->mm.interruptible;
+               dev_priv->mm.interruptible = false;
+
+               WARN_ON(i915_gem_object_unbind(obj));
+
+               dev_priv->mm.interruptible = was_interruptible;
+       }
+
        if (obj->base.map_list.map)
                drm_gem_free_mmap_offset(&obj->base);
 
        drm_gem_object_release(&obj->base);
        i915_gem_info_remove_obj(dev_priv, obj->base.size);
 
-       kfree(obj->page_cpu_valid);
        kfree(obj->bit_17);
        kfree(obj);
 }
 
-void i915_gem_free_object(struct drm_gem_object *gem_obj)
-{
-       struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
-       struct drm_device *dev = obj->base.dev;
-
-       while (obj->pin_count > 0)
-               i915_gem_object_unpin(obj);
-
-       if (obj->phys_obj)
-               i915_gem_detach_phys_object(dev, obj);
-
-       i915_gem_free_object_tail(obj);
-}
-
 int
 i915_gem_idle(struct drm_device *dev)
 {
@@ -3693,20 +3359,16 @@ i915_gem_idle(struct drm_device *dev)
                return 0;
        }
 
-       ret = i915_gpu_idle(dev, true);
+       ret = i915_gpu_idle(dev);
        if (ret) {
                mutex_unlock(&dev->struct_mutex);
                return ret;
        }
+       i915_gem_retire_requests(dev);
 
        /* Under UMS, be paranoid and evict. */
-       if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = i915_gem_evict_inactive(dev, false);
-               if (ret) {
-                       mutex_unlock(&dev->struct_mutex);
-                       return ret;
-               }
-       }
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               i915_gem_evict_everything(dev, false);
 
        i915_gem_reset_fences(dev);
 
@@ -3744,9 +3406,9 @@ void i915_gem_init_swizzling(struct drm_device *dev)
 
        I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL);
        if (IS_GEN6(dev))
-               I915_WRITE(ARB_MODE, ARB_MODE_ENABLE(ARB_MODE_SWIZZLE_SNB));
+               I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB));
        else
-               I915_WRITE(ARB_MODE, ARB_MODE_ENABLE(ARB_MODE_SWIZZLE_IVB));
+               I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
 }
 
 void i915_gem_init_ppgtt(struct drm_device *dev)
@@ -3754,20 +3416,48 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        uint32_t pd_offset;
        struct intel_ring_buffer *ring;
+       struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+       uint32_t __iomem *pd_addr;
+       uint32_t pd_entry;
        int i;
 
        if (!dev_priv->mm.aliasing_ppgtt)
                return;
 
-       pd_offset = dev_priv->mm.aliasing_ppgtt->pd_offset;
+
+       pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t);
+       for (i = 0; i < ppgtt->num_pd_entries; i++) {
+               dma_addr_t pt_addr;
+
+               if (dev_priv->mm.gtt->needs_dmar)
+                       pt_addr = ppgtt->pt_dma_addr[i];
+               else
+                       pt_addr = page_to_phys(ppgtt->pt_pages[i]);
+
+               pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
+               pd_entry |= GEN6_PDE_VALID;
+
+               writel(pd_entry, pd_addr + i);
+       }
+       readl(pd_addr);
+
+       pd_offset = ppgtt->pd_offset;
        pd_offset /= 64; /* in cachelines, */
        pd_offset <<= 16;
 
        if (INTEL_INFO(dev)->gen == 6) {
-               uint32_t ecochk = I915_READ(GAM_ECOCHK);
+               uint32_t ecochk, gab_ctl, ecobits;
+
+               ecobits = I915_READ(GAC_ECO_BITS); 
+               I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
+
+               gab_ctl = I915_READ(GAB_CTL);
+               I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
+
+               ecochk = I915_READ(GAM_ECOCHK);
                I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT |
                                       ECOCHK_PPGTT_CACHE64B);
-               I915_WRITE(GFX_MODE, GFX_MODE_ENABLE(GFX_PPGTT_ENABLE));
+               I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
        } else if (INTEL_INFO(dev)->gen >= 7) {
                I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B);
                /* GFX_MODE is per-ring on gen7+ */
@@ -3778,7 +3468,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
 
                if (INTEL_INFO(dev)->gen >= 7)
                        I915_WRITE(RING_MODE_GEN7(ring),
-                                  GFX_MODE_ENABLE(GFX_PPGTT_ENABLE));
+                                  _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
 
                I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
                I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
@@ -3822,6 +3512,71 @@ cleanup_render_ring:
        return ret;
 }
 
+static bool
+intel_enable_ppgtt(struct drm_device *dev)
+{
+       if (i915_enable_ppgtt >= 0)
+               return i915_enable_ppgtt;
+
+#ifdef CONFIG_INTEL_IOMMU
+       /* Disable ppgtt on SNB if VT-d is on. */
+       if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
+               return false;
+#endif
+
+       return true;
+}
+
+int i915_gem_init(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned long gtt_size, mappable_size;
+       int ret;
+
+       gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
+       mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
+
+       mutex_lock(&dev->struct_mutex);
+       if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
+               /* PPGTT pdes are stolen from global gtt ptes, so shrink the
+                * aperture accordingly when using aliasing ppgtt. */
+               gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
+
+               i915_gem_init_global_gtt(dev, 0, mappable_size, gtt_size);
+
+               ret = i915_gem_init_aliasing_ppgtt(dev);
+               if (ret) {
+                       mutex_unlock(&dev->struct_mutex);
+                       return ret;
+               }
+       } else {
+               /* Let GEM Manage all of the aperture.
+                *
+                * However, leave one page at the end still bound to the scratch
+                * page.  There are a number of places where the hardware
+                * apparently prefetches past the end of the object, and we've
+                * seen multiple hangs with the GPU head pointer stuck in a
+                * batchbuffer bound at the last page of the aperture.  One page
+                * should be enough to keep any prefetching inside of the
+                * aperture.
+                */
+               i915_gem_init_global_gtt(dev, 0, mappable_size,
+                                        gtt_size);
+       }
+
+       ret = i915_gem_init_hw(dev);
+       mutex_unlock(&dev->struct_mutex);
+       if (ret) {
+               i915_gem_cleanup_aliasing_ppgtt(dev);
+               return ret;
+       }
+
+       /* Allow hardware batchbuffers unless told otherwise, but not for KMS. */
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               dev_priv->dri1.allow_batchbuffer = 1;
+       return 0;
+}
+
 void
 i915_gem_cleanup_ringbuffer(struct drm_device *dev)
 {
@@ -3921,9 +3676,7 @@ i915_gem_load(struct drm_device *dev)
        INIT_LIST_HEAD(&dev_priv->mm.active_list);
        INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
        INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
-       INIT_LIST_HEAD(&dev_priv->mm.pinned_list);
        INIT_LIST_HEAD(&dev_priv->mm.fence_list);
-       INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list);
        INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
        for (i = 0; i < I915_NUM_RINGS; i++)
                init_ring_lists(&dev_priv->ring[i]);
@@ -3935,12 +3688,8 @@ i915_gem_load(struct drm_device *dev)
 
        /* On GEN3 we really need to make sure the ARB C3 LP bit is set */
        if (IS_GEN3(dev)) {
-               u32 tmp = I915_READ(MI_ARB_STATE);
-               if (!(tmp & MI_ARB_C3_LP_WRITE_ENABLE)) {
-                       /* arb state is a masked write, so set bit + bit in mask */
-                       tmp = MI_ARB_C3_LP_WRITE_ENABLE | (MI_ARB_C3_LP_WRITE_ENABLE << MI_ARB_MASK_SHIFT);
-                       I915_WRITE(MI_ARB_STATE, tmp);
-               }
+               I915_WRITE(MI_ARB_STATE,
+                          _MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE));
        }
 
        dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
@@ -3955,9 +3704,7 @@ i915_gem_load(struct drm_device *dev)
                dev_priv->num_fence_regs = 8;
 
        /* Initialize fence registers to zero */
-       for (i = 0; i < dev_priv->num_fence_regs; i++) {
-               i915_gem_clear_fence_reg(dev, &dev_priv->fence_regs[i]);
-       }
+       i915_gem_reset_fences(dev);
 
        i915_gem_detect_bit_6_swizzle(dev);
        init_waitqueue_head(&dev_priv->pending_flip_queue);
@@ -4245,7 +3992,7 @@ rescan:
                 * This has a dramatic impact to reduce the number of
                 * OOM-killer events whilst running the GPU aggressively.
                 */
-               if (i915_gpu_idle(dev, true) == 0)
+               if (i915_gpu_idle(dev) == 0)
                        goto rescan;
        }
        mutex_unlock(&dev->struct_mutex);
index cc93cac242d650a595d447ecf10a95a2765a7d36..a4f6aaabca99a7d6268e5bf59a7025a6be5b6eae 100644 (file)
@@ -114,22 +114,6 @@ i915_verify_lists(struct drm_device *dev)
                }
        }
 
-       list_for_each_entry(obj, &dev_priv->mm.pinned_list, list) {
-               if (obj->base.dev != dev ||
-                   !atomic_read(&obj->base.refcount.refcount)) {
-                       DRM_ERROR("freed pinned %p\n", obj);
-                       err++;
-                       break;
-               } else if (!obj->pin_count || obj->active ||
-                          (obj->base.write_domain & I915_GEM_GPU_DOMAINS)) {
-                       DRM_ERROR("invalid pinned %p (p %d a %d w %x)\n",
-                                 obj,
-                                 obj->pin_count, obj->active,
-                                 obj->base.write_domain);
-                       err++;
-               }
-       }
-
        return warned = err;
 }
 #endif /* WATCH_INACTIVE */
index 21a82710f4b280eaf2dd48acb84cb4469cd4bec2..3bcf0451d07c45323b3be5bff25d04006a538c49 100644 (file)
@@ -35,6 +35,9 @@
 static bool
 mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind)
 {
+       if (obj->pin_count)
+               return false;
+
        list_add(&obj->exec_list, unwind);
        return drm_mm_scan_add_block(obj->gtt_space);
 }
@@ -90,7 +93,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
        /* Now merge in the soon-to-be-expired objects... */
        list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
                /* Does the object require an outstanding flush? */
-               if (obj->base.write_domain || obj->pin_count)
+               if (obj->base.write_domain)
                        continue;
 
                if (mark_free(obj, &unwind_list))
@@ -99,14 +102,11 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
 
        /* Finally add anything with a pending flush (in order of retirement) */
        list_for_each_entry(obj, &dev_priv->mm.flushing_list, mm_list) {
-               if (obj->pin_count)
-                       continue;
-
                if (mark_free(obj, &unwind_list))
                        goto found;
        }
        list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
-               if (!obj->base.write_domain || obj->pin_count)
+               if (!obj->base.write_domain)
                        continue;
 
                if (mark_free(obj, &unwind_list))
@@ -166,8 +166,9 @@ int
 i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       int ret;
+       struct drm_i915_gem_object *obj, *next;
        bool lists_empty;
+       int ret,i;
 
        lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
                       list_empty(&dev_priv->mm.flushing_list) &&
@@ -177,31 +178,30 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 
        trace_i915_gem_evict_everything(dev, purgeable_only);
 
-       /* Flush everything (on to the inactive lists) and evict */
-       ret = i915_gpu_idle(dev, true);
+       ret = i915_gpu_idle(dev);
        if (ret)
                return ret;
 
-       BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+       /* The gpu_idle will flush everything in the write domain to the
+        * active list. Then we must move everything off the active list
+        * with retire requests.
+        */
+       for (i = 0; i < I915_NUM_RINGS; i++)
+               if (WARN_ON(!list_empty(&dev_priv->ring[i].gpu_write_list)))
+                       return -EBUSY;
 
-       return i915_gem_evict_inactive(dev, purgeable_only);
-}
+       i915_gem_retire_requests(dev);
 
-/** Unbinds all inactive objects. */
-int
-i915_gem_evict_inactive(struct drm_device *dev, bool purgeable_only)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_gem_object *obj, *next;
+       BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 
+       /* Having flushed everything, unbind() should never raise an error */
        list_for_each_entry_safe(obj, next,
                                 &dev_priv->mm.inactive_list, mm_list) {
                if (!purgeable_only || obj->madv != I915_MADV_WILLNEED) {
-                       int ret = i915_gem_object_unbind(obj);
-                       if (ret)
-                               return ret;
+                       if (obj->pin_count == 0)
+                               WARN_ON(i915_gem_object_unbind(obj));
                }
        }
 
-       return 0;
+       return ret;
 }
index 81687af00893ca5c20edfe2256dd5b98da7fdf45..206b9bbe6979d9c491c7e84832f68adc317ce09a 100644 (file)
@@ -266,6 +266,12 @@ eb_destroy(struct eb_objects *eb)
        kfree(eb);
 }
 
+static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
+{
+       return (obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
+               obj->cache_level != I915_CACHE_NONE);
+}
+
 static int
 i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
                                   struct eb_objects *eb,
@@ -273,6 +279,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 {
        struct drm_device *dev = obj->base.dev;
        struct drm_gem_object *target_obj;
+       struct drm_i915_gem_object *target_i915_obj;
        uint32_t target_offset;
        int ret = -EINVAL;
 
@@ -281,7 +288,8 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
        if (unlikely(target_obj == NULL))
                return -ENOENT;
 
-       target_offset = to_intel_bo(target_obj)->gtt_offset;
+       target_i915_obj = to_intel_bo(target_obj);
+       target_offset = target_i915_obj->gtt_offset;
 
        /* The target buffer should have appeared before us in the
         * exec_object list, so it should have a GTT space bound by now.
@@ -352,11 +360,19 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
                return ret;
        }
 
+       /* We can't wait for rendering with pagefaults disabled */
+       if (obj->active && in_atomic())
+               return -EFAULT;
+
        reloc->delta += target_offset;
-       if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
+       if (use_cpu_reloc(obj)) {
                uint32_t page_offset = reloc->offset & ~PAGE_MASK;
                char *vaddr;
 
+               ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+               if (ret)
+                       return ret;
+
                vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]);
                *(uint32_t *)(vaddr + page_offset) = reloc->delta;
                kunmap_atomic(vaddr);
@@ -365,11 +381,11 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
                uint32_t __iomem *reloc_entry;
                void __iomem *reloc_page;
 
-               /* We can't wait for rendering with pagefaults disabled */
-               if (obj->active && in_atomic())
-                       return -EFAULT;
+               ret = i915_gem_object_set_to_gtt_domain(obj, true);
+               if (ret)
+                       return ret;
 
-               ret = i915_gem_object_set_to_gtt_domain(obj, 1);
+               ret = i915_gem_object_put_fence(obj);
                if (ret)
                        return ret;
 
@@ -383,6 +399,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
                io_mapping_unmap_atomic(reloc_page);
        }
 
+       /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
+        * pipe_control writes because the gpu doesn't properly redirect them
+        * through the ppgtt for non_secure batchbuffers. */
+       if (unlikely(IS_GEN6(dev) &&
+           reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
+           !target_i915_obj->has_global_gtt_mapping)) {
+               i915_gem_gtt_bind_object(target_i915_obj,
+                                        target_i915_obj->cache_level);
+       }
+
        /* and update the user's relocation entry */
        reloc->presumed_offset = target_offset;
 
@@ -393,30 +419,46 @@ static int
 i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
                                    struct eb_objects *eb)
 {
+#define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry))
+       struct drm_i915_gem_relocation_entry stack_reloc[N_RELOC(512)];
        struct drm_i915_gem_relocation_entry __user *user_relocs;
        struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
-       int i, ret;
+       int remain, ret;
 
        user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
-       for (i = 0; i < entry->relocation_count; i++) {
-               struct drm_i915_gem_relocation_entry reloc;
 
-               if (__copy_from_user_inatomic(&reloc,
-                                             user_relocs+i,
-                                             sizeof(reloc)))
+       remain = entry->relocation_count;
+       while (remain) {
+               struct drm_i915_gem_relocation_entry *r = stack_reloc;
+               int count = remain;
+               if (count > ARRAY_SIZE(stack_reloc))
+                       count = ARRAY_SIZE(stack_reloc);
+               remain -= count;
+
+               if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0])))
                        return -EFAULT;
 
-               ret = i915_gem_execbuffer_relocate_entry(obj, eb, &reloc);
-               if (ret)
-                       return ret;
+               do {
+                       u64 offset = r->presumed_offset;
 
-               if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset,
-                                           &reloc.presumed_offset,
-                                           sizeof(reloc.presumed_offset)))
-                       return -EFAULT;
+                       ret = i915_gem_execbuffer_relocate_entry(obj, eb, r);
+                       if (ret)
+                               return ret;
+
+                       if (r->presumed_offset != offset &&
+                           __copy_to_user_inatomic(&user_relocs->presumed_offset,
+                                                   &r->presumed_offset,
+                                                   sizeof(r->presumed_offset))) {
+                               return -EFAULT;
+                       }
+
+                       user_relocs++;
+                       r++;
+               } while (--count);
        }
 
        return 0;
+#undef N_RELOC
 }
 
 static int
@@ -464,6 +506,13 @@ i915_gem_execbuffer_relocate(struct drm_device *dev,
 
 #define  __EXEC_OBJECT_HAS_FENCE (1<<31)
 
+static int
+need_reloc_mappable(struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+       return entry->relocation_count && !use_cpu_reloc(obj);
+}
+
 static int
 pin_and_fence_object(struct drm_i915_gem_object *obj,
                     struct intel_ring_buffer *ring)
@@ -477,8 +526,7 @@ pin_and_fence_object(struct drm_i915_gem_object *obj,
                has_fenced_gpu_access &&
                entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
                obj->tiling_mode != I915_TILING_NONE;
-       need_mappable =
-               entry->relocation_count ? true : need_fence;
+       need_mappable = need_fence || need_reloc_mappable(obj);
 
        ret = i915_gem_object_pin(obj, entry->alignment, need_mappable);
        if (ret)
@@ -486,20 +534,15 @@ pin_and_fence_object(struct drm_i915_gem_object *obj,
 
        if (has_fenced_gpu_access) {
                if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) {
-                       if (obj->tiling_mode) {
-                               ret = i915_gem_object_get_fence(obj, ring);
-                               if (ret)
-                                       goto err_unpin;
+                       ret = i915_gem_object_get_fence(obj);
+                       if (ret)
+                               goto err_unpin;
 
+                       if (i915_gem_object_pin_fence(obj))
                                entry->flags |= __EXEC_OBJECT_HAS_FENCE;
-                               i915_gem_object_pin_fence(obj);
-                       } else {
-                               ret = i915_gem_object_put_fence(obj);
-                               if (ret)
-                                       goto err_unpin;
-                       }
+
+                       obj->pending_fenced_gpu_access = true;
                }
-               obj->pending_fenced_gpu_access = need_fence;
        }
 
        entry->offset = obj->gtt_offset;
@@ -535,8 +578,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                        has_fenced_gpu_access &&
                        entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
                        obj->tiling_mode != I915_TILING_NONE;
-               need_mappable =
-                       entry->relocation_count ? true : need_fence;
+               need_mappable = need_fence || need_reloc_mappable(obj);
 
                if (need_mappable)
                        list_move(&obj->exec_list, &ordered_objects);
@@ -576,8 +618,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                                has_fenced_gpu_access &&
                                entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
                                obj->tiling_mode != I915_TILING_NONE;
-                       need_mappable =
-                               entry->relocation_count ? true : need_fence;
+                       need_mappable = need_fence || need_reloc_mappable(obj);
 
                        if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) ||
                            (need_mappable && !obj->map_and_fenceable))
@@ -798,64 +839,6 @@ i915_gem_execbuffer_flush(struct drm_device *dev,
        return 0;
 }
 
-static bool
-intel_enable_semaphores(struct drm_device *dev)
-{
-       if (INTEL_INFO(dev)->gen < 6)
-               return 0;
-
-       if (i915_semaphores >= 0)
-               return i915_semaphores;
-
-       /* Disable semaphores on SNB */
-       if (INTEL_INFO(dev)->gen == 6)
-               return 0;
-
-       return 1;
-}
-
-static int
-i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
-                              struct intel_ring_buffer *to)
-{
-       struct intel_ring_buffer *from = obj->ring;
-       u32 seqno;
-       int ret, idx;
-
-       if (from == NULL || to == from)
-               return 0;
-
-       /* XXX gpu semaphores are implicated in various hard hangs on SNB */
-       if (!intel_enable_semaphores(obj->base.dev))
-               return i915_gem_object_wait_rendering(obj);
-
-       idx = intel_ring_sync_index(from, to);
-
-       seqno = obj->last_rendering_seqno;
-       if (seqno <= from->sync_seqno[idx])
-               return 0;
-
-       if (seqno == from->outstanding_lazy_request) {
-               struct drm_i915_gem_request *request;
-
-               request = kzalloc(sizeof(*request), GFP_KERNEL);
-               if (request == NULL)
-                       return -ENOMEM;
-
-               ret = i915_add_request(from, NULL, request);
-               if (ret) {
-                       kfree(request);
-                       return ret;
-               }
-
-               seqno = request->seqno;
-       }
-
-       from->sync_seqno[idx] = seqno;
-
-       return to->sync_to(to, from, seqno - 1);
-}
-
 static int
 i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
 {
@@ -917,7 +900,7 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
        }
 
        list_for_each_entry(obj, objects, exec_list) {
-               ret = i915_gem_execbuffer_sync_rings(obj, ring);
+               ret = i915_gem_object_sync(obj, ring);
                if (ret)
                        return ret;
        }
@@ -955,7 +938,7 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
                if (!access_ok(VERIFY_WRITE, ptr, length))
                        return -EFAULT;
 
-               if (fault_in_pages_readable(ptr, length))
+               if (fault_in_multipages_readable(ptr, length))
                        return -EFAULT;
        }
 
@@ -1133,6 +1116,17 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                        return -EINVAL;
                }
 
+               if (INTEL_INFO(dev)->gen >= 5) {
+                       DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
+                       return -EINVAL;
+               }
+
+               if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
+                       DRM_DEBUG("execbuf with %u cliprects\n",
+                                 args->num_cliprects);
+                       return -EINVAL;
+               }
+
                cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects),
                                    GFP_KERNEL);
                if (cliprects == NULL) {
@@ -1237,9 +1231,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                         * so every billion or so execbuffers, we need to stall
                         * the GPU in order to reset the counters.
                         */
-                       ret = i915_gpu_idle(dev, true);
+                       ret = i915_gpu_idle(dev);
                        if (ret)
                                goto err;
+                       i915_gem_retire_requests(dev);
 
                        BUG_ON(ring->sync_seqno[i]);
                }
@@ -1404,7 +1399,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
        struct drm_i915_gem_exec_object2 *exec2_list = NULL;
        int ret;
 
-       if (args->buffer_count < 1) {
+       if (args->buffer_count < 1 ||
+           args->buffer_count > UINT_MAX / sizeof(*exec2_list)) {
                DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count);
                return -EINVAL;
        }
index 2eacd78bb93be76fff278152f2dedeb4793b08df..29d573c27b35acad54ea603f256698c2a57f13c7 100644 (file)
@@ -65,9 +65,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_hw_ppgtt *ppgtt;
-       uint32_t pd_entry;
        unsigned first_pd_entry_in_global_pt;
-       uint32_t __iomem *pd_addr;
        int i;
        int ret = -ENOMEM;
 
@@ -98,12 +96,10 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
                                             GFP_KERNEL);
                if (!ppgtt->pt_dma_addr)
                        goto err_pt_alloc;
-       }
 
-       pd_addr = dev_priv->mm.gtt->gtt + first_pd_entry_in_global_pt;
-       for (i = 0; i < ppgtt->num_pd_entries; i++) {
-               dma_addr_t pt_addr;
-               if (dev_priv->mm.gtt->needs_dmar) {
+               for (i = 0; i < ppgtt->num_pd_entries; i++) {
+                       dma_addr_t pt_addr;
+
                        pt_addr = pci_map_page(dev->pdev, ppgtt->pt_pages[i],
                                               0, 4096,
                                               PCI_DMA_BIDIRECTIONAL);
@@ -115,15 +111,8 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
 
                        }
                        ppgtt->pt_dma_addr[i] = pt_addr;
-               } else
-                       pt_addr = page_to_phys(ppgtt->pt_pages[i]);
-
-               pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
-               pd_entry |= GEN6_PDE_VALID;
-
-               writel(pd_entry, pd_addr + i);
+               }
        }
-       readl(pd_addr);
 
        ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma;
 
@@ -328,7 +317,7 @@ static bool do_idling(struct drm_i915_private *dev_priv)
 
        if (unlikely(dev_priv->mm.gtt->do_idle_maps)) {
                dev_priv->mm.interruptible = false;
-               if (i915_gpu_idle(dev_priv->dev, false)) {
+               if (i915_gpu_idle(dev_priv->dev)) {
                        DRM_ERROR("Couldn't idle GPU\n");
                        /* Wait a bit, in hopes it avoids the hang */
                        udelay(10);
@@ -355,42 +344,28 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 
        list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
                i915_gem_clflush_object(obj);
-               i915_gem_gtt_rebind_object(obj, obj->cache_level);
+               i915_gem_gtt_bind_object(obj, obj->cache_level);
        }
 
        intel_gtt_chipset_flush();
 }
 
-int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj)
+int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
 {
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned int agp_type = cache_level_to_agp_type(dev, obj->cache_level);
-       int ret;
-
-       if (dev_priv->mm.gtt->needs_dmar) {
-               ret = intel_gtt_map_memory(obj->pages,
-                                          obj->base.size >> PAGE_SHIFT,
-                                          &obj->sg_list,
-                                          &obj->num_sg);
-               if (ret != 0)
-                       return ret;
-
-               intel_gtt_insert_sg_entries(obj->sg_list,
-                                           obj->num_sg,
-                                           obj->gtt_space->start >> PAGE_SHIFT,
-                                           agp_type);
-       } else
-               intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT,
-                                      obj->base.size >> PAGE_SHIFT,
-                                      obj->pages,
-                                      agp_type);
 
-       return 0;
+       if (dev_priv->mm.gtt->needs_dmar)
+               return intel_gtt_map_memory(obj->pages,
+                                           obj->base.size >> PAGE_SHIFT,
+                                           &obj->sg_list,
+                                           &obj->num_sg);
+       else
+               return 0;
 }
 
-void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
-                               enum i915_cache_level cache_level)
+void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
+                             enum i915_cache_level cache_level)
 {
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -408,9 +383,19 @@ void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,
                                       obj->base.size >> PAGE_SHIFT,
                                       obj->pages,
                                       agp_type);
+
+       obj->has_global_gtt_mapping = 1;
 }
 
 void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
+{
+       intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
+                             obj->base.size >> PAGE_SHIFT);
+
+       obj->has_global_gtt_mapping = 0;
+}
+
+void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
 {
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -418,9 +403,6 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 
        interruptible = do_idling(dev_priv);
 
-       intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT,
-                             obj->base.size >> PAGE_SHIFT);
-
        if (obj->sg_list) {
                intel_gtt_unmap_memory(obj->sg_list, obj->num_sg);
                obj->sg_list = NULL;
@@ -428,3 +410,23 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
 
        undo_idling(dev_priv, interruptible);
 }
+
+void i915_gem_init_global_gtt(struct drm_device *dev,
+                             unsigned long start,
+                             unsigned long mappable_end,
+                             unsigned long end)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       /* Substract the guard page ... */
+       drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE);
+
+       dev_priv->mm.gtt_start = start;
+       dev_priv->mm.gtt_mappable_end = mappable_end;
+       dev_priv->mm.gtt_end = end;
+       dev_priv->mm.gtt_total = end - start;
+       dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start;
+
+       /* ... but ensure that we clear the entire range. */
+       intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE);
+}
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
new file mode 100644 (file)
index 0000000..ada2e90
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright Â© 2008-2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *    Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/*
+ * The BIOS typically reserves some of the system's memory for the exclusive
+ * use of the integrated graphics. This memory is no longer available for
+ * use by the OS and so the user finds that his system has less memory
+ * available than he put in. We refer to this memory as stolen.
+ *
+ * The BIOS will allocate its framebuffer from the stolen memory. Our
+ * goal is try to reuse that object for our own fbcon which must always
+ * be available for panics. Anything else we can reuse the stolen memory
+ * for is a boon.
+ */
+
+#define PTE_ADDRESS_MASK               0xfffff000
+#define PTE_ADDRESS_MASK_HIGH          0x000000f0 /* i915+ */
+#define PTE_MAPPING_TYPE_UNCACHED      (0 << 1)
+#define PTE_MAPPING_TYPE_DCACHE                (1 << 1) /* i830 only */
+#define PTE_MAPPING_TYPE_CACHED                (3 << 1)
+#define PTE_MAPPING_TYPE_MASK          (3 << 1)
+#define PTE_VALID                      (1 << 0)
+
+/**
+ * i915_stolen_to_phys - take an offset into stolen memory and turn it into
+ *                       a physical one
+ * @dev: drm device
+ * @offset: address to translate
+ *
+ * Some chip functions require allocations from stolen space and need the
+ * physical address of the memory in question.
+ */
+static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct pci_dev *pdev = dev_priv->bridge_dev;
+       u32 base;
+
+#if 0
+       /* On the machines I have tested the Graphics Base of Stolen Memory
+        * is unreliable, so compute the base by subtracting the stolen memory
+        * from the Top of Low Usable DRAM which is where the BIOS places
+        * the graphics stolen memory.
+        */
+       if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
+               /* top 32bits are reserved = 0 */
+               pci_read_config_dword(pdev, 0xA4, &base);
+       } else {
+               /* XXX presume 8xx is the same as i915 */
+               pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base);
+       }
+#else
+       if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
+               u16 val;
+               pci_read_config_word(pdev, 0xb0, &val);
+               base = val >> 4 << 20;
+       } else {
+               u8 val;
+               pci_read_config_byte(pdev, 0x9c, &val);
+               base = val >> 3 << 27;
+       }
+       base -= dev_priv->mm.gtt->stolen_size;
+#endif
+
+       return base + offset;
+}
+
+static void i915_warn_stolen(struct drm_device *dev)
+{
+       DRM_INFO("not enough stolen space for compressed buffer, disabling\n");
+       DRM_INFO("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n");
+}
+
+static void i915_setup_compression(struct drm_device *dev, int size)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
+       unsigned long cfb_base;
+       unsigned long ll_base = 0;
+
+       /* Just in case the BIOS is doing something questionable. */
+       intel_disable_fbc(dev);
+
+       compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
+       if (compressed_fb)
+               compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
+       if (!compressed_fb)
+               goto err;
+
+       cfb_base = i915_stolen_to_phys(dev, compressed_fb->start);
+       if (!cfb_base)
+               goto err_fb;
+
+       if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) {
+               compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
+                                                   4096, 4096, 0);
+               if (compressed_llb)
+                       compressed_llb = drm_mm_get_block(compressed_llb,
+                                                         4096, 4096);
+               if (!compressed_llb)
+                       goto err_fb;
+
+               ll_base = i915_stolen_to_phys(dev, compressed_llb->start);
+               if (!ll_base)
+                       goto err_llb;
+       }
+
+       dev_priv->cfb_size = size;
+
+       dev_priv->compressed_fb = compressed_fb;
+       if (HAS_PCH_SPLIT(dev))
+               I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
+       else if (IS_GM45(dev)) {
+               I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
+       } else {
+               I915_WRITE(FBC_CFB_BASE, cfb_base);
+               I915_WRITE(FBC_LL_BASE, ll_base);
+               dev_priv->compressed_llb = compressed_llb;
+       }
+
+       DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n",
+                     cfb_base, ll_base, size >> 20);
+       return;
+
+err_llb:
+       drm_mm_put_block(compressed_llb);
+err_fb:
+       drm_mm_put_block(compressed_fb);
+err:
+       dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
+       i915_warn_stolen(dev);
+}
+
+static void i915_cleanup_compression(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       drm_mm_put_block(dev_priv->compressed_fb);
+       if (dev_priv->compressed_llb)
+               drm_mm_put_block(dev_priv->compressed_llb);
+}
+
+void i915_gem_cleanup_stolen(struct drm_device *dev)
+{
+       if (I915_HAS_FBC(dev) && i915_powersave)
+               i915_cleanup_compression(dev);
+}
+
+int i915_gem_init_stolen(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned long prealloc_size = dev_priv->mm.gtt->stolen_size;
+
+       /* Basic memrange allocator for stolen space */
+       drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
+
+       /* Try to set up FBC with a reasonable compressed buffer size */
+       if (I915_HAS_FBC(dev) && i915_powersave) {
+               int cfb_size;
+
+               /* Leave 1M for line length buffer & misc. */
+
+               /* Try to get a 32M buffer... */
+               if (prealloc_size > (36*1024*1024))
+                       cfb_size = 32*1024*1024;
+               else /* fall back to 7/8 of the stolen space */
+                       cfb_size = prealloc_size * 7 / 8;
+               i915_setup_compression(dev, cfb_size);
+       }
+
+       return 0;
+}
index 1a93066659871eedfcc1e50668cfd82b1c7b4b63..b964df51cec7c6d906a2865313734b0c69f6fd4c 100644 (file)
@@ -354,9 +354,15 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                /* We need to rebind the object if its current allocation
                 * no longer meets the alignment restrictions for its new
                 * tiling mode. Otherwise we can just leave it alone, but
-                * need to ensure that any fence register is cleared.
+                * need to ensure that any fence register is updated before
+                * the next fenced (either through the GTT or by the BLT unit
+                * on older GPUs) access.
+                *
+                * After updating the tiling parameters, we then flag whether
+                * we need to update an associated fence register. Note this
+                * has to also include the unfenced register the GPU uses
+                * whilst executing a fenced command for an untiled object.
                 */
-               i915_gem_release_mmap(obj);
 
                obj->map_and_fenceable =
                        obj->gtt_space == NULL ||
@@ -374,9 +380,15 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                }
 
                if (ret == 0) {
-                       obj->tiling_changed = true;
+                       obj->fence_dirty =
+                               obj->fenced_gpu_access ||
+                               obj->fence_reg != I915_FENCE_REG_NONE;
+
                        obj->tiling_mode = args->tiling_mode;
                        obj->stride = args->stride;
+
+                       /* Force the fence to be reacquired for GTT access */
+                       i915_gem_release_mmap(obj);
                }
        }
        /* we have to maintain this existing ABI... */
index 13b028994b2be7e3c2caf4eec100560ed01358fb..0e72abb9f7016005ad549ccefdf95862e4c4f87e 100644 (file)
@@ -34,6 +34,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
+#include "i915_drv.h"
 
 typedef struct _drm_i915_batchbuffer32 {
        int start;              /* agp offset */
@@ -181,7 +182,7 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd,
                         (unsigned long)request);
 }
 
-drm_ioctl_compat_t *i915_compat_ioctls[] = {
+static drm_ioctl_compat_t *i915_compat_ioctls[] = {
        [DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
        [DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
        [DRM_I915_GETPARAM] = compat_i915_getparam,
@@ -189,6 +190,7 @@ drm_ioctl_compat_t *i915_compat_ioctls[] = {
        [DRM_I915_ALLOC] = compat_i915_alloc
 };
 
+#ifdef CONFIG_COMPAT
 /**
  * Called whenever a 32-bit process running under a 64-bit kernel
  * performs an ioctl on /dev/dri/card<n>.
@@ -217,3 +219,4 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
        return ret;
 }
+#endif
index afd4e03e337e130b1d68cfa53759911768120ee1..b4999b5288e84be946c63680d28040094be3fbd5 100644 (file)
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/sysrq.h>
 #include <linux/slab.h>
 #include "drmP.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
 
-#define MAX_NOPID ((u32)~0)
-
-/**
- * Interrupts that are always left unmasked.
- *
- * Since pipe events are edge-triggered from the PIPESTAT register to IIR,
- * we leave them always unmasked in IMR and then control enabling them through
- * PIPESTAT alone.
- */
-#define I915_INTERRUPT_ENABLE_FIX                      \
-       (I915_ASLE_INTERRUPT |                          \
-        I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |          \
-        I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |          \
-        I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |  \
-        I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |  \
-        I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
-
-/** Interrupts that we mask and unmask at runtime. */
-#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT | I915_BSD_USER_INTERRUPT)
-
-#define I915_PIPE_VBLANK_STATUS        (PIPE_START_VBLANK_INTERRUPT_STATUS |\
-                                PIPE_VBLANK_INTERRUPT_STATUS)
-
-#define I915_PIPE_VBLANK_ENABLE        (PIPE_START_VBLANK_INTERRUPT_ENABLE |\
-                                PIPE_VBLANK_INTERRUPT_ENABLE)
-
-#define DRM_I915_VBLANK_PIPE_ALL       (DRM_I915_VBLANK_PIPE_A | \
-                                        DRM_I915_VBLANK_PIPE_B)
-
 /* For display hotplug interrupt */
 static void
 ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
@@ -118,6 +91,10 @@ void intel_enable_asle(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        unsigned long irqflags;
 
+       /* FIXME: opregion/asle for VLV */
+       if (IS_VALLEYVIEW(dev))
+               return;
+
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
        if (HAS_PCH_SPLIT(dev))
@@ -354,15 +331,12 @@ static void notify_ring(struct drm_device *dev,
                        struct intel_ring_buffer *ring)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 seqno;
 
        if (ring->obj == NULL)
                return;
 
-       seqno = ring->get_seqno(ring);
-       trace_i915_gem_request_complete(ring, seqno);
+       trace_i915_gem_request_complete(ring, ring->get_seqno(ring));
 
-       ring->irq_seqno = seqno;
        wake_up_all(&ring->irq_queue);
        if (i915_enable_hangcheck) {
                dev_priv->hangcheck_count = 0;
@@ -424,6 +398,141 @@ static void gen6_pm_rps_work(struct work_struct *work)
        mutex_unlock(&dev_priv->dev->struct_mutex);
 }
 
+static void snb_gt_irq_handler(struct drm_device *dev,
+                              struct drm_i915_private *dev_priv,
+                              u32 gt_iir)
+{
+
+       if (gt_iir & (GEN6_RENDER_USER_INTERRUPT |
+                     GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT))
+               notify_ring(dev, &dev_priv->ring[RCS]);
+       if (gt_iir & GEN6_BSD_USER_INTERRUPT)
+               notify_ring(dev, &dev_priv->ring[VCS]);
+       if (gt_iir & GEN6_BLITTER_USER_INTERRUPT)
+               notify_ring(dev, &dev_priv->ring[BCS]);
+
+       if (gt_iir & (GT_GEN6_BLT_CS_ERROR_INTERRUPT |
+                     GT_GEN6_BSD_CS_ERROR_INTERRUPT |
+                     GT_RENDER_CS_ERROR_INTERRUPT)) {
+               DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir);
+               i915_handle_error(dev, false);
+       }
+}
+
+static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
+                               u32 pm_iir)
+{
+       unsigned long flags;
+
+       /*
+        * IIR bits should never already be set because IMR should
+        * prevent an interrupt from being shown in IIR. The warning
+        * displays a case where we've unsafely cleared
+        * dev_priv->pm_iir. Although missing an interrupt of the same
+        * type is not a problem, it displays a problem in the logic.
+        *
+        * The mask bit in IMR is cleared by rps_work.
+        */
+
+       spin_lock_irqsave(&dev_priv->rps_lock, flags);
+       WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
+       dev_priv->pm_iir |= pm_iir;
+       I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+       POSTING_READ(GEN6_PMIMR);
+       spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
+
+       queue_work(dev_priv->wq, &dev_priv->rps_work);
+}
+
+static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 iir, gt_iir, pm_iir;
+       irqreturn_t ret = IRQ_NONE;
+       unsigned long irqflags;
+       int pipe;
+       u32 pipe_stats[I915_MAX_PIPES];
+       u32 vblank_status;
+       int vblank = 0;
+       bool blc_event;
+
+       atomic_inc(&dev_priv->irq_received);
+
+       vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS |
+               PIPE_VBLANK_INTERRUPT_STATUS;
+
+       while (true) {
+               iir = I915_READ(VLV_IIR);
+               gt_iir = I915_READ(GTIIR);
+               pm_iir = I915_READ(GEN6_PMIIR);
+
+               if (gt_iir == 0 && pm_iir == 0 && iir == 0)
+                       goto out;
+
+               ret = IRQ_HANDLED;
+
+               snb_gt_irq_handler(dev, dev_priv, gt_iir);
+
+               spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+               for_each_pipe(pipe) {
+                       int reg = PIPESTAT(pipe);
+                       pipe_stats[pipe] = I915_READ(reg);
+
+                       /*
+                        * Clear the PIPE*STAT regs before the IIR
+                        */
+                       if (pipe_stats[pipe] & 0x8000ffff) {
+                               if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+                                       DRM_DEBUG_DRIVER("pipe %c underrun\n",
+                                                        pipe_name(pipe));
+                               I915_WRITE(reg, pipe_stats[pipe]);
+                       }
+               }
+               spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+               /* Consume port.  Then clear IIR or we'll miss events */
+               if (iir & I915_DISPLAY_PORT_INTERRUPT) {
+                       u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
+
+                       DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
+                                        hotplug_status);
+                       if (hotplug_status & dev_priv->hotplug_supported_mask)
+                               queue_work(dev_priv->wq,
+                                          &dev_priv->hotplug_work);
+
+                       I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+                       I915_READ(PORT_HOTPLUG_STAT);
+               }
+
+
+               if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) {
+                       drm_handle_vblank(dev, 0);
+                       vblank++;
+                       intel_finish_page_flip(dev, 0);
+               }
+
+               if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) {
+                       drm_handle_vblank(dev, 1);
+                       vblank++;
+                       intel_finish_page_flip(dev, 0);
+               }
+
+               if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+                       blc_event = true;
+
+               if (pm_iir & GEN6_PM_DEFERRED_EVENTS)
+                       gen6_queue_rps_work(dev_priv, pm_iir);
+
+               I915_WRITE(GTIIR, gt_iir);
+               I915_WRITE(GEN6_PMIIR, pm_iir);
+               I915_WRITE(VLV_IIR, iir);
+       }
+
+out:
+       return ret;
+}
+
 static void pch_irq_handler(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -473,7 +582,6 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        int ret = IRQ_NONE;
        u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;
-       struct drm_i915_master_private *master_priv;
 
        atomic_inc(&dev_priv->irq_received);
 
@@ -492,19 +600,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
 
        ret = IRQ_HANDLED;
 
-       if (dev->primary->master) {
-               master_priv = dev->primary->master->driver_priv;
-               if (master_priv->sarea_priv)
-                       master_priv->sarea_priv->last_dispatch =
-                               READ_BREADCRUMB(dev_priv);
-       }
-
-       if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
-               notify_ring(dev, &dev_priv->ring[RCS]);
-       if (gt_iir & GT_GEN6_BSD_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[VCS]);
-       if (gt_iir & GT_BLT_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[BCS]);
+       snb_gt_irq_handler(dev, dev_priv, gt_iir);
 
        if (de_iir & DE_GSE_IVB)
                intel_opregion_gse_intr(dev);
@@ -519,12 +615,20 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
                intel_finish_page_flip_plane(dev, 1);
        }
 
+       if (de_iir & DE_PLANEC_FLIP_DONE_IVB) {
+               intel_prepare_page_flip(dev, 2);
+               intel_finish_page_flip_plane(dev, 2);
+       }
+
        if (de_iir & DE_PIPEA_VBLANK_IVB)
                drm_handle_vblank(dev, 0);
 
        if (de_iir & DE_PIPEB_VBLANK_IVB)
                drm_handle_vblank(dev, 1);
 
+       if (de_iir & DE_PIPEC_VBLANK_IVB)
+               drm_handle_vblank(dev, 2);
+
        /* check event from PCH */
        if (de_iir & DE_PCH_EVENT_IVB) {
                if (pch_iir & SDE_HOTPLUG_MASK_CPT)
@@ -532,16 +636,8 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
                pch_irq_handler(dev);
        }
 
-       if (pm_iir & GEN6_PM_DEFERRED_EVENTS) {
-               unsigned long flags;
-               spin_lock_irqsave(&dev_priv->rps_lock, flags);
-               WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
-               dev_priv->pm_iir |= pm_iir;
-               I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
-               POSTING_READ(GEN6_PMIMR);
-               spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
-               queue_work(dev_priv->wq, &dev_priv->rps_work);
-       }
+       if (pm_iir & GEN6_PM_DEFERRED_EVENTS)
+               gen6_queue_rps_work(dev_priv, pm_iir);
 
        /* should clear PCH hotplug event before clear CPU irq */
        I915_WRITE(SDEIIR, pch_iir);
@@ -556,6 +652,16 @@ done:
        return ret;
 }
 
+static void ilk_gt_irq_handler(struct drm_device *dev,
+                              struct drm_i915_private *dev_priv,
+                              u32 gt_iir)
+{
+       if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
+               notify_ring(dev, &dev_priv->ring[RCS]);
+       if (gt_iir & GT_BSD_USER_INTERRUPT)
+               notify_ring(dev, &dev_priv->ring[VCS]);
+}
+
 static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -563,14 +669,9 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
        int ret = IRQ_NONE;
        u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;
        u32 hotplug_mask;
-       struct drm_i915_master_private *master_priv;
-       u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT;
 
        atomic_inc(&dev_priv->irq_received);
 
-       if (IS_GEN6(dev))
-               bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT;
-
        /* disable master interrupt before clearing iir  */
        de_ier = I915_READ(DEIER);
        I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
@@ -592,19 +693,10 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
 
        ret = IRQ_HANDLED;
 
-       if (dev->primary->master) {
-               master_priv = dev->primary->master->driver_priv;
-               if (master_priv->sarea_priv)
-                       master_priv->sarea_priv->last_dispatch =
-                               READ_BREADCRUMB(dev_priv);
-       }
-
-       if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
-               notify_ring(dev, &dev_priv->ring[RCS]);
-       if (gt_iir & bsd_usr_interrupt)
-               notify_ring(dev, &dev_priv->ring[VCS]);
-       if (gt_iir & GT_BLT_USER_INTERRUPT)
-               notify_ring(dev, &dev_priv->ring[BCS]);
+       if (IS_GEN5(dev))
+               ilk_gt_irq_handler(dev, dev_priv, gt_iir);
+       else
+               snb_gt_irq_handler(dev, dev_priv, gt_iir);
 
        if (de_iir & DE_GSE)
                intel_opregion_gse_intr(dev);
@@ -637,25 +729,8 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
                i915_handle_rps_change(dev);
        }
 
-       if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS) {
-               /*
-                * IIR bits should never already be set because IMR should
-                * prevent an interrupt from being shown in IIR. The warning
-                * displays a case where we've unsafely cleared
-                * dev_priv->pm_iir. Although missing an interrupt of the same
-                * type is not a problem, it displays a problem in the logic.
-                *
-                * The mask bit in IMR is cleared by rps_work.
-                */
-               unsigned long flags;
-               spin_lock_irqsave(&dev_priv->rps_lock, flags);
-               WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n");
-               dev_priv->pm_iir |= pm_iir;
-               I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
-               POSTING_READ(GEN6_PMIMR);
-               spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
-               queue_work(dev_priv->wq, &dev_priv->rps_work);
-       }
+       if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS)
+               gen6_queue_rps_work(dev_priv, pm_iir);
 
        /* should clear PCH hotplug event before clear CPU irq */
        I915_WRITE(SDEIIR, pch_iir);
@@ -691,7 +766,7 @@ static void i915_error_work_func(struct work_struct *work)
        if (atomic_read(&dev_priv->mm.wedged)) {
                DRM_DEBUG_DRIVER("resetting chip\n");
                kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event);
-               if (!i915_reset(dev, GRDOM_RENDER)) {
+               if (!i915_reset(dev)) {
                        atomic_set(&dev_priv->mm.wedged, 0);
                        kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
                }
@@ -727,7 +802,8 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
                        goto unwind;
 
                local_irq_save(flags);
-               if (reloc_offset < dev_priv->mm.gtt_mappable_end) {
+               if (reloc_offset < dev_priv->mm.gtt_mappable_end &&
+                   src->has_global_gtt_mapping) {
                        void __iomem *s;
 
                        /* Simply ignore tiling or any overlapping fence.
@@ -782,10 +858,11 @@ i915_error_object_free(struct drm_i915_error_object *obj)
        kfree(obj);
 }
 
-static void
-i915_error_state_free(struct drm_device *dev,
-                     struct drm_i915_error_state *error)
+void
+i915_error_state_free(struct kref *error_ref)
 {
+       struct drm_i915_error_state *error = container_of(error_ref,
+                                                         typeof(*error), ref);
        int i;
 
        for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
@@ -798,37 +875,56 @@ i915_error_state_free(struct drm_device *dev,
        kfree(error->overlay);
        kfree(error);
 }
+static void capture_bo(struct drm_i915_error_buffer *err,
+                      struct drm_i915_gem_object *obj)
+{
+       err->size = obj->base.size;
+       err->name = obj->base.name;
+       err->seqno = obj->last_rendering_seqno;
+       err->gtt_offset = obj->gtt_offset;
+       err->read_domains = obj->base.read_domains;
+       err->write_domain = obj->base.write_domain;
+       err->fence_reg = obj->fence_reg;
+       err->pinned = 0;
+       if (obj->pin_count > 0)
+               err->pinned = 1;
+       if (obj->user_pin_count > 0)
+               err->pinned = -1;
+       err->tiling = obj->tiling_mode;
+       err->dirty = obj->dirty;
+       err->purgeable = obj->madv != I915_MADV_WILLNEED;
+       err->ring = obj->ring ? obj->ring->id : -1;
+       err->cache_level = obj->cache_level;
+}
 
-static u32 capture_bo_list(struct drm_i915_error_buffer *err,
-                          int count,
-                          struct list_head *head)
+static u32 capture_active_bo(struct drm_i915_error_buffer *err,
+                            int count, struct list_head *head)
 {
        struct drm_i915_gem_object *obj;
        int i = 0;
 
        list_for_each_entry(obj, head, mm_list) {
-               err->size = obj->base.size;
-               err->name = obj->base.name;
-               err->seqno = obj->last_rendering_seqno;
-               err->gtt_offset = obj->gtt_offset;
-               err->read_domains = obj->base.read_domains;
-               err->write_domain = obj->base.write_domain;
-               err->fence_reg = obj->fence_reg;
-               err->pinned = 0;
-               if (obj->pin_count > 0)
-                       err->pinned = 1;
-               if (obj->user_pin_count > 0)
-                       err->pinned = -1;
-               err->tiling = obj->tiling_mode;
-               err->dirty = obj->dirty;
-               err->purgeable = obj->madv != I915_MADV_WILLNEED;
-               err->ring = obj->ring ? obj->ring->id : -1;
-               err->cache_level = obj->cache_level;
-
+               capture_bo(err++, obj);
                if (++i == count)
                        break;
+       }
 
-               err++;
+       return i;
+}
+
+static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
+                            int count, struct list_head *head)
+{
+       struct drm_i915_gem_object *obj;
+       int i = 0;
+
+       list_for_each_entry(obj, head, gtt_list) {
+               if (obj->pin_count == 0)
+                       continue;
+
+               capture_bo(err++, obj);
+               if (++i == count)
+                       break;
        }
 
        return i;
@@ -901,7 +997,6 @@ static void i915_record_ring_state(struct drm_device *dev,
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (INTEL_INFO(dev)->gen >= 6) {
-               error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));
                error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
                error->semaphore_mboxes[ring->id][0]
                        = I915_READ(RING_SYNC_0(ring->mmio_base));
@@ -910,6 +1005,7 @@ static void i915_record_ring_state(struct drm_device *dev,
        }
 
        if (INTEL_INFO(dev)->gen >= 4) {
+               error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));
                error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base));
                error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
                error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
@@ -919,11 +1015,13 @@ static void i915_record_ring_state(struct drm_device *dev,
                        error->bbaddr = I915_READ64(BB_ADDR);
                }
        } else {
+               error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
                error->ipeir[ring->id] = I915_READ(IPEIR);
                error->ipehr[ring->id] = I915_READ(IPEHR);
                error->instdone[ring->id] = I915_READ(INSTDONE);
        }
 
+       error->waiting[ring->id] = waitqueue_active(&ring->irq_queue);
        error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
        error->seqno[ring->id] = ring->get_seqno(ring);
        error->acthd[ring->id] = intel_ring_get_active_head(ring);
@@ -1013,8 +1111,19 @@ static void i915_capture_error_state(struct drm_device *dev)
        DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n",
                 dev->primary->index);
 
+       kref_init(&error->ref);
        error->eir = I915_READ(EIR);
        error->pgtbl_er = I915_READ(PGTBL_ER);
+
+       if (HAS_PCH_SPLIT(dev))
+               error->ier = I915_READ(DEIER) | I915_READ(GTIER);
+       else if (IS_VALLEYVIEW(dev))
+               error->ier = I915_READ(GTIER) | I915_READ(VLV_IER);
+       else if (IS_GEN2(dev))
+               error->ier = I915_READ16(IER);
+       else
+               error->ier = I915_READ(IER);
+
        for_each_pipe(pipe)
                error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 
@@ -1034,8 +1143,9 @@ static void i915_capture_error_state(struct drm_device *dev)
        list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list)
                i++;
        error->active_bo_count = i;
-       list_for_each_entry(obj, &dev_priv->mm.pinned_list, mm_list)
-               i++;
+       list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list)
+               if (obj->pin_count)
+                       i++;
        error->pinned_bo_count = i - error->active_bo_count;
 
        error->active_bo = NULL;
@@ -1050,15 +1160,15 @@ static void i915_capture_error_state(struct drm_device *dev)
 
        if (error->active_bo)
                error->active_bo_count =
-                       capture_bo_list(error->active_bo,
-                                       error->active_bo_count,
-                                       &dev_priv->mm.active_list);
+                       capture_active_bo(error->active_bo,
+                                         error->active_bo_count,
+                                         &dev_priv->mm.active_list);
 
        if (error->pinned_bo)
                error->pinned_bo_count =
-                       capture_bo_list(error->pinned_bo,
-                                       error->pinned_bo_count,
-                                       &dev_priv->mm.pinned_list);
+                       capture_pinned_bo(error->pinned_bo,
+                                         error->pinned_bo_count,
+                                         &dev_priv->mm.gtt_list);
 
        do_gettimeofday(&error->time);
 
@@ -1073,7 +1183,7 @@ static void i915_capture_error_state(struct drm_device *dev)
        spin_unlock_irqrestore(&dev_priv->error_lock, flags);
 
        if (error)
-               i915_error_state_free(dev, error);
+               i915_error_state_free(&error->ref);
 }
 
 void i915_destroy_error_state(struct drm_device *dev)
@@ -1088,7 +1198,7 @@ void i915_destroy_error_state(struct drm_device *dev)
        spin_unlock_irqrestore(&dev_priv->error_lock, flags);
 
        if (error)
-               i915_error_state_free(dev, error);
+               kref_put(&error->ref, i915_error_state_free);
 }
 #else
 #define i915_capture_error_state(x)
@@ -1103,33 +1213,26 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
        if (!eir)
                return;
 
-       printk(KERN_ERR "render error detected, EIR: 0x%08x\n",
-              eir);
+       pr_err("render error detected, EIR: 0x%08x\n", eir);
 
        if (IS_G4X(dev)) {
                if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
                        u32 ipeir = I915_READ(IPEIR_I965);
 
-                       printk(KERN_ERR "  IPEIR: 0x%08x\n",
-                              I915_READ(IPEIR_I965));
-                       printk(KERN_ERR "  IPEHR: 0x%08x\n",
-                              I915_READ(IPEHR_I965));
-                       printk(KERN_ERR "  INSTDONE: 0x%08x\n",
+                       pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
+                       pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
+                       pr_err("  INSTDONE: 0x%08x\n",
                               I915_READ(INSTDONE_I965));
-                       printk(KERN_ERR "  INSTPS: 0x%08x\n",
-                              I915_READ(INSTPS));
-                       printk(KERN_ERR "  INSTDONE1: 0x%08x\n",
-                              I915_READ(INSTDONE1));
-                       printk(KERN_ERR "  ACTHD: 0x%08x\n",
-                              I915_READ(ACTHD_I965));
+                       pr_err("  INSTPS: 0x%08x\n", I915_READ(INSTPS));
+                       pr_err("  INSTDONE1: 0x%08x\n", I915_READ(INSTDONE1));
+                       pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
                        I915_WRITE(IPEIR_I965, ipeir);
                        POSTING_READ(IPEIR_I965);
                }
                if (eir & GM45_ERROR_PAGE_TABLE) {
                        u32 pgtbl_err = I915_READ(PGTBL_ER);
-                       printk(KERN_ERR "page table error\n");
-                       printk(KERN_ERR "  PGTBL_ER: 0x%08x\n",
-                              pgtbl_err);
+                       pr_err("page table error\n");
+                       pr_err("  PGTBL_ER: 0x%08x\n", pgtbl_err);
                        I915_WRITE(PGTBL_ER, pgtbl_err);
                        POSTING_READ(PGTBL_ER);
                }
@@ -1138,53 +1241,42 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
        if (!IS_GEN2(dev)) {
                if (eir & I915_ERROR_PAGE_TABLE) {
                        u32 pgtbl_err = I915_READ(PGTBL_ER);
-                       printk(KERN_ERR "page table error\n");
-                       printk(KERN_ERR "  PGTBL_ER: 0x%08x\n",
-                              pgtbl_err);
+                       pr_err("page table error\n");
+                       pr_err("  PGTBL_ER: 0x%08x\n", pgtbl_err);
                        I915_WRITE(PGTBL_ER, pgtbl_err);
                        POSTING_READ(PGTBL_ER);
                }
        }
 
        if (eir & I915_ERROR_MEMORY_REFRESH) {
-               printk(KERN_ERR "memory refresh error:\n");
+               pr_err("memory refresh error:\n");
                for_each_pipe(pipe)
-                       printk(KERN_ERR "pipe %c stat: 0x%08x\n",
+                       pr_err("pipe %c stat: 0x%08x\n",
                               pipe_name(pipe), I915_READ(PIPESTAT(pipe)));
                /* pipestat has already been acked */
        }
        if (eir & I915_ERROR_INSTRUCTION) {
-               printk(KERN_ERR "instruction error\n");
-               printk(KERN_ERR "  INSTPM: 0x%08x\n",
-                      I915_READ(INSTPM));
+               pr_err("instruction error\n");
+               pr_err("  INSTPM: 0x%08x\n", I915_READ(INSTPM));
                if (INTEL_INFO(dev)->gen < 4) {
                        u32 ipeir = I915_READ(IPEIR);
 
-                       printk(KERN_ERR "  IPEIR: 0x%08x\n",
-                              I915_READ(IPEIR));
-                       printk(KERN_ERR "  IPEHR: 0x%08x\n",
-                              I915_READ(IPEHR));
-                       printk(KERN_ERR "  INSTDONE: 0x%08x\n",
-                              I915_READ(INSTDONE));
-                       printk(KERN_ERR "  ACTHD: 0x%08x\n",
-                              I915_READ(ACTHD));
+                       pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR));
+                       pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR));
+                       pr_err("  INSTDONE: 0x%08x\n", I915_READ(INSTDONE));
+                       pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD));
                        I915_WRITE(IPEIR, ipeir);
                        POSTING_READ(IPEIR);
                } else {
                        u32 ipeir = I915_READ(IPEIR_I965);
 
-                       printk(KERN_ERR "  IPEIR: 0x%08x\n",
-                              I915_READ(IPEIR_I965));
-                       printk(KERN_ERR "  IPEHR: 0x%08x\n",
-                              I915_READ(IPEHR_I965));
-                       printk(KERN_ERR "  INSTDONE: 0x%08x\n",
+                       pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
+                       pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
+                       pr_err("  INSTDONE: 0x%08x\n",
                               I915_READ(INSTDONE_I965));
-                       printk(KERN_ERR "  INSTPS: 0x%08x\n",
-                              I915_READ(INSTPS));
-                       printk(KERN_ERR "  INSTDONE1: 0x%08x\n",
-                              I915_READ(INSTDONE1));
-                       printk(KERN_ERR "  ACTHD: 0x%08x\n",
-                              I915_READ(ACTHD_I965));
+                       pr_err("  INSTPS: 0x%08x\n", I915_READ(INSTPS));
+                       pr_err("  INSTDONE1: 0x%08x\n", I915_READ(INSTDONE1));
+                       pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
                        I915_WRITE(IPEIR_I965, ipeir);
                        POSTING_READ(IPEIR_I965);
                }
@@ -1265,7 +1357,8 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
        obj = work->pending_flip_obj;
        if (INTEL_INFO(dev)->gen >= 4) {
                int dspsurf = DSPSURF(intel_crtc->plane);
-               stall_detected = I915_READ(dspsurf) == obj->gtt_offset;
+               stall_detected = I915_HI_DISPBASE(I915_READ(dspsurf)) ==
+                                       obj->gtt_offset;
        } else {
                int dspaddr = DSPADDR(intel_crtc->plane);
                stall_detected = I915_READ(dspaddr) == (obj->gtt_offset +
@@ -1281,306 +1374,90 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
        }
 }
 
-static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
+/* Called from drm generic code, passed 'crtc' which
+ * we use as a pipe index
+ */
+static int i915_enable_vblank(struct drm_device *dev, int pipe)
 {
-       struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       struct drm_i915_master_private *master_priv;
-       u32 iir, new_iir;
-       u32 pipe_stats[I915_MAX_PIPES];
-       u32 vblank_status;
-       int vblank = 0;
        unsigned long irqflags;
-       int irq_received;
-       int ret = IRQ_NONE, pipe;
-       bool blc_event = false;
-
-       atomic_inc(&dev_priv->irq_received);
 
-       iir = I915_READ(IIR);
+       if (!i915_pipe_enabled(dev, pipe))
+               return -EINVAL;
 
+       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        if (INTEL_INFO(dev)->gen >= 4)
-               vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
+               i915_enable_pipestat(dev_priv, pipe,
+                                    PIPE_START_VBLANK_INTERRUPT_ENABLE);
        else
-               vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
+               i915_enable_pipestat(dev_priv, pipe,
+                                    PIPE_VBLANK_INTERRUPT_ENABLE);
 
-       for (;;) {
-               irq_received = iir != 0;
+       /* maintain vblank delivery even in deep C-states */
+       if (dev_priv->info->gen == 3)
+               I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_AGPBUSY_DIS));
+       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
-               /* Can't rely on pipestat interrupt bit in iir as it might
-                * have been cleared after the pipestat interrupt was received.
-                * It doesn't set the bit in iir again, but it still produces
-                * interrupts (for non-MSI).
-                */
-               spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-               if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
-                       i915_handle_error(dev, false);
+       return 0;
+}
 
-               for_each_pipe(pipe) {
-                       int reg = PIPESTAT(pipe);
-                       pipe_stats[pipe] = I915_READ(reg);
+static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long irqflags;
 
-                       /*
-                        * Clear the PIPE*STAT regs before the IIR
-                        */
-                       if (pipe_stats[pipe] & 0x8000ffff) {
-                               if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
-                                       DRM_DEBUG_DRIVER("pipe %c underrun\n",
-                                                        pipe_name(pipe));
-                               I915_WRITE(reg, pipe_stats[pipe]);
-                               irq_received = 1;
-                       }
-               }
-               spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+       if (!i915_pipe_enabled(dev, pipe))
+               return -EINVAL;
 
-               if (!irq_received)
-                       break;
+       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+       ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
+                                   DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
-               ret = IRQ_HANDLED;
+       return 0;
+}
 
-               /* Consume port.  Then clear IIR or we'll miss events */
-               if ((I915_HAS_HOTPLUG(dev)) &&
-                   (iir & I915_DISPLAY_PORT_INTERRUPT)) {
-                       u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
+static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long irqflags;
 
-                       DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
-                                 hotplug_status);
-                       if (hotplug_status & dev_priv->hotplug_supported_mask)
-                               queue_work(dev_priv->wq,
-                                          &dev_priv->hotplug_work);
+       if (!i915_pipe_enabled(dev, pipe))
+               return -EINVAL;
 
-                       I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-                       I915_READ(PORT_HOTPLUG_STAT);
-               }
+       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+       ironlake_enable_display_irq(dev_priv,
+                                   DE_PIPEA_VBLANK_IVB << (5 * pipe));
+       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
-               I915_WRITE(IIR, iir);
-               new_iir = I915_READ(IIR); /* Flush posted writes */
+       return 0;
+}
 
-               if (dev->primary->master) {
-                       master_priv = dev->primary->master->driver_priv;
-                       if (master_priv->sarea_priv)
-                               master_priv->sarea_priv->last_dispatch =
-                                       READ_BREADCRUMB(dev_priv);
-               }
+static int valleyview_enable_vblank(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long irqflags;
+       u32 dpfl, imr;
 
-               if (iir & I915_USER_INTERRUPT)
-                       notify_ring(dev, &dev_priv->ring[RCS]);
-               if (iir & I915_BSD_USER_INTERRUPT)
-                       notify_ring(dev, &dev_priv->ring[VCS]);
+       if (!i915_pipe_enabled(dev, pipe))
+               return -EINVAL;
 
-               if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
-                       intel_prepare_page_flip(dev, 0);
-                       if (dev_priv->flip_pending_is_done)
-                               intel_finish_page_flip_plane(dev, 0);
-               }
+       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+       dpfl = I915_READ(VLV_DPFLIPSTAT);
+       imr = I915_READ(VLV_IMR);
+       if (pipe == 0) {
+               dpfl |= PIPEA_VBLANK_INT_EN;
+               imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
+       } else {
+               dpfl |= PIPEA_VBLANK_INT_EN;
+               imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
+       }
+       I915_WRITE(VLV_DPFLIPSTAT, dpfl);
+       I915_WRITE(VLV_IMR, imr);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
-               if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
-                       intel_prepare_page_flip(dev, 1);
-                       if (dev_priv->flip_pending_is_done)
-                               intel_finish_page_flip_plane(dev, 1);
-               }
-
-               for_each_pipe(pipe) {
-                       if (pipe_stats[pipe] & vblank_status &&
-                           drm_handle_vblank(dev, pipe)) {
-                               vblank++;
-                               if (!dev_priv->flip_pending_is_done) {
-                                       i915_pageflip_stall_check(dev, pipe);
-                                       intel_finish_page_flip(dev, pipe);
-                               }
-                       }
-
-                       if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
-                               blc_event = true;
-               }
-
-
-               if (blc_event || (iir & I915_ASLE_INTERRUPT))
-                       intel_opregion_asle_intr(dev);
-
-               /* With MSI, interrupts are only generated when iir
-                * transitions from zero to nonzero.  If another bit got
-                * set while we were handling the existing iir bits, then
-                * we would never get another interrupt.
-                *
-                * This is fine on non-MSI as well, as if we hit this path
-                * we avoid exiting the interrupt handler only to generate
-                * another one.
-                *
-                * Note that for MSI this could cause a stray interrupt report
-                * if an interrupt landed in the time between writing IIR and
-                * the posting read.  This should be rare enough to never
-                * trigger the 99% of 100,000 interrupts test for disabling
-                * stray interrupts.
-                */
-               iir = new_iir;
-       }
-
-       return ret;
-}
-
-static int i915_emit_irq(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-
-       i915_kernel_lost_context(dev);
-
-       DRM_DEBUG_DRIVER("\n");
-
-       dev_priv->counter++;
-       if (dev_priv->counter > 0x7FFFFFFFUL)
-               dev_priv->counter = 1;
-       if (master_priv->sarea_priv)
-               master_priv->sarea_priv->last_enqueue = dev_priv->counter;
-
-       if (BEGIN_LP_RING(4) == 0) {
-               OUT_RING(MI_STORE_DWORD_INDEX);
-               OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-               OUT_RING(dev_priv->counter);
-               OUT_RING(MI_USER_INTERRUPT);
-               ADVANCE_LP_RING();
-       }
-
-       return dev_priv->counter;
-}
-
-static int i915_wait_irq(struct drm_device * dev, int irq_nr)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-       int ret = 0;
-       struct intel_ring_buffer *ring = LP_RING(dev_priv);
-
-       DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
-                 READ_BREADCRUMB(dev_priv));
-
-       if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
-               if (master_priv->sarea_priv)
-                       master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-               return 0;
-       }
-
-       if (master_priv->sarea_priv)
-               master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-
-       if (ring->irq_get(ring)) {
-               DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ,
-                           READ_BREADCRUMB(dev_priv) >= irq_nr);
-               ring->irq_put(ring);
-       } else if (wait_for(READ_BREADCRUMB(dev_priv) >= irq_nr, 3000))
-               ret = -EBUSY;
-
-       if (ret == -EBUSY) {
-               DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
-                         READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
-       }
-
-       return ret;
-}
-
-/* Needs the lock as it touches the ring.
- */
-int i915_irq_emit(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_irq_emit_t *emit = data;
-       int result;
-
-       if (!dev_priv || !LP_RING(dev_priv)->virtual_start) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       mutex_lock(&dev->struct_mutex);
-       result = i915_emit_irq(dev);
-       mutex_unlock(&dev->struct_mutex);
-
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-/* Doesn't need the hardware lock.
- */
-int i915_irq_wait(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_irq_wait_t *irqwait = data;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       return i915_wait_irq(dev, irqwait->irq_seq);
-}
-
-/* Called from drm generic code, passed 'crtc' which
- * we use as a pipe index
- */
-static int i915_enable_vblank(struct drm_device *dev, int pipe)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
-
-       if (!i915_pipe_enabled(dev, pipe))
-               return -EINVAL;
-
-       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       if (INTEL_INFO(dev)->gen >= 4)
-               i915_enable_pipestat(dev_priv, pipe,
-                                    PIPE_START_VBLANK_INTERRUPT_ENABLE);
-       else
-               i915_enable_pipestat(dev_priv, pipe,
-                                    PIPE_VBLANK_INTERRUPT_ENABLE);
-
-       /* maintain vblank delivery even in deep C-states */
-       if (dev_priv->info->gen == 3)
-               I915_WRITE(INSTPM, INSTPM_AGPBUSY_DIS << 16);
-       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
-       return 0;
-}
-
-static int ironlake_enable_vblank(struct drm_device *dev, int pipe)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
-
-       if (!i915_pipe_enabled(dev, pipe))
-               return -EINVAL;
-
-       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
-                                   DE_PIPEA_VBLANK : DE_PIPEB_VBLANK);
-       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
-       return 0;
-}
-
-static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
-
-       if (!i915_pipe_enabled(dev, pipe))
-               return -EINVAL;
-
-       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
-                                   DE_PIPEA_VBLANK_IVB : DE_PIPEB_VBLANK_IVB);
-       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
-
-       return 0;
-}
+       return 0;
+}
 
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
@@ -1592,8 +1469,7 @@ static void i915_disable_vblank(struct drm_device *dev, int pipe)
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        if (dev_priv->info->gen == 3)
-               I915_WRITE(INSTPM,
-                          INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS);
+               I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS));
 
        i915_disable_pipestat(dev_priv, pipe,
                              PIPE_VBLANK_INTERRUPT_ENABLE |
@@ -1618,63 +1494,30 @@ static void ivybridge_disable_vblank(struct drm_device *dev, int pipe)
        unsigned long irqflags;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-       ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
-                                    DE_PIPEA_VBLANK_IVB : DE_PIPEB_VBLANK_IVB);
+       ironlake_disable_display_irq(dev_priv,
+                                    DE_PIPEA_VBLANK_IVB << (pipe * 5));
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-/* Set the vblank monitor pipe
- */
-int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
+static void valleyview_disable_vblank(struct drm_device *dev, int pipe)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_pipe_t *pipe = data;
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long irqflags;
+       u32 dpfl, imr;
 
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
+       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+       dpfl = I915_READ(VLV_DPFLIPSTAT);
+       imr = I915_READ(VLV_IMR);
+       if (pipe == 0) {
+               dpfl &= ~PIPEA_VBLANK_INT_EN;
+               imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT;
+       } else {
+               dpfl &= ~PIPEB_VBLANK_INT_EN;
+               imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
        }
-
-       pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
-
-       return 0;
-}
-
-/**
- * Schedule buffer swap at given vertical blank.
- */
-int i915_vblank_swap(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv)
-{
-       /* The delayed swap mechanism was fundamentally racy, and has been
-        * removed.  The model was that the client requested a delayed flip/swap
-        * from the kernel, then waited for vblank before continuing to perform
-        * rendering.  The problem was that the kernel might wake the client
-        * up before it dispatched the vblank swap (since the lock has to be
-        * held while touching the ringbuffer), in which case the client would
-        * clear and start the next frame before the swap occurred, and
-        * flicker would occur in addition to likely missing the vblank.
-        *
-        * In the absence of this ioctl, userland falls back to a correct path
-        * of waiting for a vblank, then dispatching the swap on its own.
-        * Context switching to userland and back is plenty fast enough for
-        * meeting the requirements of vblank swapping.
-        */
-       return -EINVAL;
+       I915_WRITE(VLV_IMR, imr);
+       I915_WRITE(VLV_DPFLIPSTAT, dpfl);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
 static u32
@@ -1686,14 +1529,17 @@ ring_last_seqno(struct intel_ring_buffer *ring)
 
 static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
 {
+       /* We don't check whether the ring even exists before calling this
+        * function. Hence check whether it's initialized. */
+       if (ring->obj == NULL)
+               return true;
+
        if (list_empty(&ring->request_list) ||
            i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
                /* Issue a wake-up to catch stuck h/w. */
-               if (ring->waiting_seqno && waitqueue_active(&ring->irq_queue)) {
-                       DRM_ERROR("Hangcheck timer elapsed... %s idle [waiting on %d, at %d], missed IRQ?\n",
-                                 ring->name,
-                                 ring->waiting_seqno,
-                                 ring->get_seqno(ring));
+               if (waitqueue_active(&ring->irq_queue)) {
+                       DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
+                                 ring->name);
                        wake_up_all(&ring->irq_queue);
                        *err = true;
                }
@@ -1716,6 +1562,36 @@ static bool kick_ring(struct intel_ring_buffer *ring)
        return false;
 }
 
+static bool i915_hangcheck_hung(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       if (dev_priv->hangcheck_count++ > 1) {
+               DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
+               i915_handle_error(dev, true);
+
+               if (!IS_GEN2(dev)) {
+                       /* Is the chip hanging on a WAIT_FOR_EVENT?
+                        * If so we can simply poke the RB_WAIT bit
+                        * and break the hang. This should work on
+                        * all but the second generation chipsets.
+                        */
+                       if (kick_ring(&dev_priv->ring[RCS]))
+                               return false;
+
+                       if (HAS_BSD(dev) && kick_ring(&dev_priv->ring[VCS]))
+                               return false;
+
+                       if (HAS_BLT(dev) && kick_ring(&dev_priv->ring[BCS]))
+                               return false;
+               }
+
+               return true;
+       }
+
+       return false;
+}
+
 /**
  * This is called when the chip hasn't reported back with completed
  * batchbuffers in a long time. The first time this is called we simply record
@@ -1736,9 +1612,14 @@ void i915_hangcheck_elapsed(unsigned long data)
        if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
            i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
            i915_hangcheck_ring_idle(&dev_priv->ring[BCS], &err)) {
-               dev_priv->hangcheck_count = 0;
-               if (err)
+               if (err) {
+                       if (i915_hangcheck_hung(dev))
+                               return;
+
                        goto repeat;
+               }
+
+               dev_priv->hangcheck_count = 0;
                return;
        }
 
@@ -1760,30 +1641,8 @@ void i915_hangcheck_elapsed(unsigned long data)
            dev_priv->last_acthd_blt == acthd_blt &&
            dev_priv->last_instdone == instdone &&
            dev_priv->last_instdone1 == instdone1) {
-               if (dev_priv->hangcheck_count++ > 1) {
-                       DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
-                       i915_handle_error(dev, true);
-
-                       if (!IS_GEN2(dev)) {
-                               /* Is the chip hanging on a WAIT_FOR_EVENT?
-                                * If so we can simply poke the RB_WAIT bit
-                                * and break the hang. This should work on
-                                * all but the second generation chipsets.
-                                */
-                               if (kick_ring(&dev_priv->ring[RCS]))
-                                       goto repeat;
-
-                               if (HAS_BSD(dev) &&
-                                   kick_ring(&dev_priv->ring[VCS]))
-                                       goto repeat;
-
-                               if (HAS_BLT(dev) &&
-                                   kick_ring(&dev_priv->ring[BCS]))
-                                       goto repeat;
-                       }
-
+               if (i915_hangcheck_hung(dev))
                        return;
-               }
        } else {
                dev_priv->hangcheck_count = 0;
 
@@ -1808,10 +1667,6 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
 
        atomic_set(&dev_priv->irq_received, 0);
 
-       INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
-       INIT_WORK(&dev_priv->error_work, i915_error_work_func);
-       if (IS_GEN6(dev) || IS_IVYBRIDGE(dev))
-               INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
 
        I915_WRITE(HWSTAM, 0xeffe);
 
@@ -1832,6 +1687,38 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
        POSTING_READ(SDEIER);
 }
 
+static void valleyview_irq_preinstall(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe;
+
+       atomic_set(&dev_priv->irq_received, 0);
+
+       /* VLV magic */
+       I915_WRITE(VLV_IMR, 0);
+       I915_WRITE(RING_IMR(RENDER_RING_BASE), 0);
+       I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0);
+       I915_WRITE(RING_IMR(BLT_RING_BASE), 0);
+
+       /* and GT */
+       I915_WRITE(GTIIR, I915_READ(GTIIR));
+       I915_WRITE(GTIIR, I915_READ(GTIIR));
+       I915_WRITE(GTIMR, 0xffffffff);
+       I915_WRITE(GTIER, 0x0);
+       POSTING_READ(GTIER);
+
+       I915_WRITE(DPINVGTT, 0xff);
+
+       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+       for_each_pipe(pipe)
+               I915_WRITE(PIPESTAT(pipe), 0xffff);
+       I915_WRITE(VLV_IIR, 0xffffffff);
+       I915_WRITE(VLV_IMR, 0xffffffff);
+       I915_WRITE(VLV_IER, 0x0);
+       POSTING_READ(VLV_IER);
+}
+
 /*
  * Enable digital hotplug on the PCH, and configure the DP short pulse
  * duration to 2ms (which is the minimum in the Display Port spec)
@@ -1861,13 +1748,6 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
        u32 render_irqs;
        u32 hotplug_mask;
 
-       DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue);
-       if (HAS_BSD(dev))
-               DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue);
-       if (HAS_BLT(dev))
-               DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue);
-
-       dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
        dev_priv->irq_mask = ~display_mask;
 
        /* should always can generate irq */
@@ -1884,8 +1764,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
        if (IS_GEN6(dev))
                render_irqs =
                        GT_USER_INTERRUPT |
-                       GT_GEN6_BSD_USER_INTERRUPT |
-                       GT_BLT_USER_INTERRUPT;
+                       GEN6_BSD_USER_INTERRUPT |
+                       GEN6_BLITTER_USER_INTERRUPT;
        else
                render_irqs =
                        GT_USER_INTERRUPT |
@@ -1930,26 +1810,24 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        /* enable kind of interrupts always enabled */
-       u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
-               DE_PCH_EVENT_IVB | DE_PLANEA_FLIP_DONE_IVB |
-               DE_PLANEB_FLIP_DONE_IVB;
+       u32 display_mask =
+               DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | DE_PCH_EVENT_IVB |
+               DE_PLANEC_FLIP_DONE_IVB |
+               DE_PLANEB_FLIP_DONE_IVB |
+               DE_PLANEA_FLIP_DONE_IVB;
        u32 render_irqs;
        u32 hotplug_mask;
 
-       DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue);
-       if (HAS_BSD(dev))
-               DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue);
-       if (HAS_BLT(dev))
-               DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue);
-
-       dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
        dev_priv->irq_mask = ~display_mask;
 
        /* should always can generate irq */
        I915_WRITE(DEIIR, I915_READ(DEIIR));
        I915_WRITE(DEIMR, dev_priv->irq_mask);
-       I915_WRITE(DEIER, display_mask | DE_PIPEA_VBLANK_IVB |
-                  DE_PIPEB_VBLANK_IVB);
+       I915_WRITE(DEIER,
+                  display_mask |
+                  DE_PIPEC_VBLANK_IVB |
+                  DE_PIPEB_VBLANK_IVB |
+                  DE_PIPEA_VBLANK_IVB);
        POSTING_READ(DEIER);
 
        dev_priv->gt_irq_mask = ~0;
@@ -1957,8 +1835,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
        I915_WRITE(GTIIR, I915_READ(GTIIR));
        I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 
-       render_irqs = GT_USER_INTERRUPT | GT_GEN6_BSD_USER_INTERRUPT |
-               GT_BLT_USER_INTERRUPT;
+       render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT |
+               GEN6_BLITTER_USER_INTERRUPT;
        I915_WRITE(GTIER, render_irqs);
        POSTING_READ(GTIER);
 
@@ -1978,46 +1856,532 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
        return 0;
 }
 
-static void i915_driver_irq_preinstall(struct drm_device * dev)
+static int valleyview_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       int pipe;
+       u32 render_irqs;
+       u32 enable_mask;
+       u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+       u16 msid;
 
-       atomic_set(&dev_priv->irq_received, 0);
+       enable_mask = I915_DISPLAY_PORT_INTERRUPT;
+       enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
+               I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
 
-       INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
-       INIT_WORK(&dev_priv->error_work, i915_error_work_func);
+       dev_priv->irq_mask = ~enable_mask;
 
-       if (I915_HAS_HOTPLUG(dev)) {
-               I915_WRITE(PORT_HOTPLUG_EN, 0);
-               I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+       dev_priv->pipestat[0] = 0;
+       dev_priv->pipestat[1] = 0;
+
+       /* Hack for broken MSIs on VLV */
+       pci_write_config_dword(dev_priv->dev->pdev, 0x94, 0xfee00000);
+       pci_read_config_word(dev->pdev, 0x98, &msid);
+       msid &= 0xff; /* mask out delivery bits */
+       msid |= (1<<14);
+       pci_write_config_word(dev_priv->dev->pdev, 0x98, msid);
+
+       I915_WRITE(VLV_IMR, dev_priv->irq_mask);
+       I915_WRITE(VLV_IER, enable_mask);
+       I915_WRITE(VLV_IIR, 0xffffffff);
+       I915_WRITE(PIPESTAT(0), 0xffff);
+       I915_WRITE(PIPESTAT(1), 0xffff);
+       POSTING_READ(VLV_IER);
+
+       I915_WRITE(VLV_IIR, 0xffffffff);
+       I915_WRITE(VLV_IIR, 0xffffffff);
+
+       render_irqs = GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT |
+               GT_GEN6_BLT_CS_ERROR_INTERRUPT |
+               GT_GEN6_BLT_USER_INTERRUPT |
+               GT_GEN6_BSD_USER_INTERRUPT |
+               GT_GEN6_BSD_CS_ERROR_INTERRUPT |
+               GT_GEN7_L3_PARITY_ERROR_INTERRUPT |
+               GT_PIPE_NOTIFY |
+               GT_RENDER_CS_ERROR_INTERRUPT |
+               GT_SYNC_STATUS |
+               GT_USER_INTERRUPT;
+
+       dev_priv->gt_irq_mask = ~render_irqs;
+
+       I915_WRITE(GTIIR, I915_READ(GTIIR));
+       I915_WRITE(GTIIR, I915_READ(GTIIR));
+       I915_WRITE(GTIMR, 0);
+       I915_WRITE(GTIER, render_irqs);
+       POSTING_READ(GTIER);
+
+       /* ack & enable invalid PTE error interrupts */
+#if 0 /* FIXME: add support to irq handler for checking these bits */
+       I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK);
+       I915_WRITE(DPINVGTT, DPINVGTT_EN_MASK);
+#endif
+
+       I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
+#if 0 /* FIXME: check register definitions; some have moved */
+       /* Note HDMI and DP share bits */
+       if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+               hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+       if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+               hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+       if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+               hotplug_en |= HDMID_HOTPLUG_INT_EN;
+       if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+               hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+       if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+               hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+       if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+               hotplug_en |= CRT_HOTPLUG_INT_EN;
+               hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
        }
+#endif
 
-       I915_WRITE(HWSTAM, 0xeffe);
-       for_each_pipe(pipe)
-               I915_WRITE(PIPESTAT(pipe), 0);
-       I915_WRITE(IMR, 0xffffffff);
-       I915_WRITE(IER, 0x0);
-       POSTING_READ(IER);
+       I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+
+       return 0;
 }
 
-/*
- * Must be called after intel_modeset_init or hotplug interrupts won't be
- * enabled correctly.
- */
-static int i915_driver_irq_postinstall(struct drm_device *dev)
+static void valleyview_irq_uninstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
-       u32 error_mask;
+       int pipe;
 
-       dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
+       if (!dev_priv)
+               return;
 
-       /* Unmask the interrupts that we always want on. */
-       dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX;
+       for_each_pipe(pipe)
+               I915_WRITE(PIPESTAT(pipe), 0xffff);
 
-       dev_priv->pipestat[0] = 0;
-       dev_priv->pipestat[1] = 0;
+       I915_WRITE(HWSTAM, 0xffffffff);
+       I915_WRITE(PORT_HOTPLUG_EN, 0);
+       I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+       for_each_pipe(pipe)
+               I915_WRITE(PIPESTAT(pipe), 0xffff);
+       I915_WRITE(VLV_IIR, 0xffffffff);
+       I915_WRITE(VLV_IMR, 0xffffffff);
+       I915_WRITE(VLV_IER, 0x0);
+       POSTING_READ(VLV_IER);
+}
+
+static void ironlake_irq_uninstall(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       if (!dev_priv)
+               return;
+
+       I915_WRITE(HWSTAM, 0xffffffff);
+
+       I915_WRITE(DEIMR, 0xffffffff);
+       I915_WRITE(DEIER, 0x0);
+       I915_WRITE(DEIIR, I915_READ(DEIIR));
+
+       I915_WRITE(GTIMR, 0xffffffff);
+       I915_WRITE(GTIER, 0x0);
+       I915_WRITE(GTIIR, I915_READ(GTIIR));
+
+       I915_WRITE(SDEIMR, 0xffffffff);
+       I915_WRITE(SDEIER, 0x0);
+       I915_WRITE(SDEIIR, I915_READ(SDEIIR));
+}
+
+static void i8xx_irq_preinstall(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe;
+
+       atomic_set(&dev_priv->irq_received, 0);
+
+       for_each_pipe(pipe)
+               I915_WRITE(PIPESTAT(pipe), 0);
+       I915_WRITE16(IMR, 0xffff);
+       I915_WRITE16(IER, 0x0);
+       POSTING_READ16(IER);
+}
+
+static int i8xx_irq_postinstall(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       dev_priv->pipestat[0] = 0;
+       dev_priv->pipestat[1] = 0;
+
+       I915_WRITE16(EMR,
+                    ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
+
+       /* Unmask the interrupts that we always want on. */
+       dev_priv->irq_mask =
+               ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+                 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+                 I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+                 I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
+                 I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+       I915_WRITE16(IMR, dev_priv->irq_mask);
+
+       I915_WRITE16(IER,
+                    I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+                    I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+                    I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |
+                    I915_USER_INTERRUPT);
+       POSTING_READ16(IER);
+
+       return 0;
+}
+
+static irqreturn_t i8xx_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u16 iir, new_iir;
+       u32 pipe_stats[2];
+       unsigned long irqflags;
+       int irq_received;
+       int pipe;
+       u16 flip_mask =
+               I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+               I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+
+       atomic_inc(&dev_priv->irq_received);
+
+       iir = I915_READ16(IIR);
+       if (iir == 0)
+               return IRQ_NONE;
+
+       while (iir & ~flip_mask) {
+               /* Can't rely on pipestat interrupt bit in iir as it might
+                * have been cleared after the pipestat interrupt was received.
+                * It doesn't set the bit in iir again, but it still produces
+                * interrupts (for non-MSI).
+                */
+               spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+               if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
+                       i915_handle_error(dev, false);
+
+               for_each_pipe(pipe) {
+                       int reg = PIPESTAT(pipe);
+                       pipe_stats[pipe] = I915_READ(reg);
+
+                       /*
+                        * Clear the PIPE*STAT regs before the IIR
+                        */
+                       if (pipe_stats[pipe] & 0x8000ffff) {
+                               if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+                                       DRM_DEBUG_DRIVER("pipe %c underrun\n",
+                                                        pipe_name(pipe));
+                               I915_WRITE(reg, pipe_stats[pipe]);
+                               irq_received = 1;
+                       }
+               }
+               spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+               I915_WRITE16(IIR, iir & ~flip_mask);
+               new_iir = I915_READ16(IIR); /* Flush posted writes */
+
+               i915_update_dri1_breadcrumb(dev);
+
+               if (iir & I915_USER_INTERRUPT)
+                       notify_ring(dev, &dev_priv->ring[RCS]);
+
+               if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS &&
+                   drm_handle_vblank(dev, 0)) {
+                       if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
+                               intel_prepare_page_flip(dev, 0);
+                               intel_finish_page_flip(dev, 0);
+                               flip_mask &= ~I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
+                       }
+               }
+
+               if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS &&
+                   drm_handle_vblank(dev, 1)) {
+                       if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
+                               intel_prepare_page_flip(dev, 1);
+                               intel_finish_page_flip(dev, 1);
+                               flip_mask &= ~I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+                       }
+               }
+
+               iir = new_iir;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void i8xx_irq_uninstall(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe;
+
+       for_each_pipe(pipe) {
+               /* Clear enable bits; then clear status bits */
+               I915_WRITE(PIPESTAT(pipe), 0);
+               I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
+       }
+       I915_WRITE16(IMR, 0xffff);
+       I915_WRITE16(IER, 0x0);
+       I915_WRITE16(IIR, I915_READ16(IIR));
+}
+
+static void i915_irq_preinstall(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe;
+
+       atomic_set(&dev_priv->irq_received, 0);
+
+       if (I915_HAS_HOTPLUG(dev)) {
+               I915_WRITE(PORT_HOTPLUG_EN, 0);
+               I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+       }
+
+       I915_WRITE16(HWSTAM, 0xeffe);
+       for_each_pipe(pipe)
+               I915_WRITE(PIPESTAT(pipe), 0);
+       I915_WRITE(IMR, 0xffffffff);
+       I915_WRITE(IER, 0x0);
+       POSTING_READ(IER);
+}
+
+static int i915_irq_postinstall(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 enable_mask;
+
+       dev_priv->pipestat[0] = 0;
+       dev_priv->pipestat[1] = 0;
+
+       I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH));
+
+       /* Unmask the interrupts that we always want on. */
+       dev_priv->irq_mask =
+               ~(I915_ASLE_INTERRUPT |
+                 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+                 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+                 I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+                 I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
+                 I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+
+       enable_mask =
+               I915_ASLE_INTERRUPT |
+               I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+               I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+               I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |
+               I915_USER_INTERRUPT;
+
+       if (I915_HAS_HOTPLUG(dev)) {
+               /* Enable in IER... */
+               enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
+               /* and unmask in IMR */
+               dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT;
+       }
+
+       I915_WRITE(IMR, dev_priv->irq_mask);
+       I915_WRITE(IER, enable_mask);
+       POSTING_READ(IER);
+
+       if (I915_HAS_HOTPLUG(dev)) {
+               u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+
+               if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+                       hotplug_en |= HDMID_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+                       hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+               if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) {
+                       hotplug_en |= CRT_HOTPLUG_INT_EN;
+                       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+               }
+
+               /* Ignore TV since it's buggy */
+
+               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+       }
+
+       intel_opregion_enable_asle(dev);
+
+       return 0;
+}
+
+static irqreturn_t i915_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 iir, new_iir, pipe_stats[I915_MAX_PIPES];
+       unsigned long irqflags;
+       u32 flip_mask =
+               I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+               I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+       u32 flip[2] = {
+               I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT,
+               I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT
+       };
+       int pipe, ret = IRQ_NONE;
+
+       atomic_inc(&dev_priv->irq_received);
+
+       iir = I915_READ(IIR);
+       do {
+               bool irq_received = (iir & ~flip_mask) != 0;
+               bool blc_event = false;
+
+               /* Can't rely on pipestat interrupt bit in iir as it might
+                * have been cleared after the pipestat interrupt was received.
+                * It doesn't set the bit in iir again, but it still produces
+                * interrupts (for non-MSI).
+                */
+               spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+               if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
+                       i915_handle_error(dev, false);
+
+               for_each_pipe(pipe) {
+                       int reg = PIPESTAT(pipe);
+                       pipe_stats[pipe] = I915_READ(reg);
+
+                       /* Clear the PIPE*STAT regs before the IIR */
+                       if (pipe_stats[pipe] & 0x8000ffff) {
+                               if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+                                       DRM_DEBUG_DRIVER("pipe %c underrun\n",
+                                                        pipe_name(pipe));
+                               I915_WRITE(reg, pipe_stats[pipe]);
+                               irq_received = true;
+                       }
+               }
+               spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+               if (!irq_received)
+                       break;
+
+               /* Consume port.  Then clear IIR or we'll miss events */
+               if ((I915_HAS_HOTPLUG(dev)) &&
+                   (iir & I915_DISPLAY_PORT_INTERRUPT)) {
+                       u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
+
+                       DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
+                                 hotplug_status);
+                       if (hotplug_status & dev_priv->hotplug_supported_mask)
+                               queue_work(dev_priv->wq,
+                                          &dev_priv->hotplug_work);
+
+                       I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+                       POSTING_READ(PORT_HOTPLUG_STAT);
+               }
+
+               I915_WRITE(IIR, iir & ~flip_mask);
+               new_iir = I915_READ(IIR); /* Flush posted writes */
+
+               if (iir & I915_USER_INTERRUPT)
+                       notify_ring(dev, &dev_priv->ring[RCS]);
+
+               for_each_pipe(pipe) {
+                       int plane = pipe;
+                       if (IS_MOBILE(dev))
+                               plane = !plane;
+                       if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
+                           drm_handle_vblank(dev, pipe)) {
+                               if (iir & flip[plane]) {
+                                       intel_prepare_page_flip(dev, plane);
+                                       intel_finish_page_flip(dev, pipe);
+                                       flip_mask &= ~flip[plane];
+                               }
+                       }
+
+                       if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+                               blc_event = true;
+               }
+
+               if (blc_event || (iir & I915_ASLE_INTERRUPT))
+                       intel_opregion_asle_intr(dev);
+
+               /* With MSI, interrupts are only generated when iir
+                * transitions from zero to nonzero.  If another bit got
+                * set while we were handling the existing iir bits, then
+                * we would never get another interrupt.
+                *
+                * This is fine on non-MSI as well, as if we hit this path
+                * we avoid exiting the interrupt handler only to generate
+                * another one.
+                *
+                * Note that for MSI this could cause a stray interrupt report
+                * if an interrupt landed in the time between writing IIR and
+                * the posting read.  This should be rare enough to never
+                * trigger the 99% of 100,000 interrupts test for disabling
+                * stray interrupts.
+                */
+               ret = IRQ_HANDLED;
+               iir = new_iir;
+       } while (iir & ~flip_mask);
+
+       i915_update_dri1_breadcrumb(dev);
+
+       return ret;
+}
+
+static void i915_irq_uninstall(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe;
+
+       if (I915_HAS_HOTPLUG(dev)) {
+               I915_WRITE(PORT_HOTPLUG_EN, 0);
+               I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+       }
+
+       I915_WRITE16(HWSTAM, 0xffff);
+       for_each_pipe(pipe) {
+               /* Clear enable bits; then clear status bits */
+               I915_WRITE(PIPESTAT(pipe), 0);
+               I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
+       }
+       I915_WRITE(IMR, 0xffffffff);
+       I915_WRITE(IER, 0x0);
+
+       I915_WRITE(IIR, I915_READ(IIR));
+}
+
+static void i965_irq_preinstall(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int pipe;
+
+       atomic_set(&dev_priv->irq_received, 0);
+
+       if (I915_HAS_HOTPLUG(dev)) {
+               I915_WRITE(PORT_HOTPLUG_EN, 0);
+               I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+       }
+
+       I915_WRITE(HWSTAM, 0xeffe);
+       for_each_pipe(pipe)
+               I915_WRITE(PIPESTAT(pipe), 0);
+       I915_WRITE(IMR, 0xffffffff);
+       I915_WRITE(IER, 0x0);
+       POSTING_READ(IER);
+}
+
+static int i965_irq_postinstall(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 enable_mask;
+       u32 error_mask;
+
+       /* Unmask the interrupts that we always want on. */
+       dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT |
+                              I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+                              I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+                              I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
+                              I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |
+                              I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+
+       enable_mask = ~dev_priv->irq_mask;
+       enable_mask |= I915_USER_INTERRUPT;
+
+       if (IS_G4X(dev))
+               enable_mask |= I915_BSD_USER_INTERRUPT;
+
+       dev_priv->pipestat[0] = 0;
+       dev_priv->pipestat[1] = 0;
 
        if (I915_HAS_HOTPLUG(dev)) {
                /* Enable in IER... */
@@ -2081,31 +2445,124 @@ static int i915_driver_irq_postinstall(struct drm_device *dev)
        return 0;
 }
 
-static void ironlake_irq_uninstall(struct drm_device *dev)
+static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS)
 {
+       struct drm_device *dev = (struct drm_device *) arg;
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 iir, new_iir;
+       u32 pipe_stats[I915_MAX_PIPES];
+       unsigned long irqflags;
+       int irq_received;
+       int ret = IRQ_NONE, pipe;
 
-       if (!dev_priv)
-               return;
+       atomic_inc(&dev_priv->irq_received);
 
-       dev_priv->vblank_pipe = 0;
+       iir = I915_READ(IIR);
 
-       I915_WRITE(HWSTAM, 0xffffffff);
+       for (;;) {
+               bool blc_event = false;
 
-       I915_WRITE(DEIMR, 0xffffffff);
-       I915_WRITE(DEIER, 0x0);
-       I915_WRITE(DEIIR, I915_READ(DEIIR));
+               irq_received = iir != 0;
 
-       I915_WRITE(GTIMR, 0xffffffff);
-       I915_WRITE(GTIER, 0x0);
-       I915_WRITE(GTIIR, I915_READ(GTIIR));
+               /* Can't rely on pipestat interrupt bit in iir as it might
+                * have been cleared after the pipestat interrupt was received.
+                * It doesn't set the bit in iir again, but it still produces
+                * interrupts (for non-MSI).
+                */
+               spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+               if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
+                       i915_handle_error(dev, false);
 
-       I915_WRITE(SDEIMR, 0xffffffff);
-       I915_WRITE(SDEIER, 0x0);
-       I915_WRITE(SDEIIR, I915_READ(SDEIIR));
+               for_each_pipe(pipe) {
+                       int reg = PIPESTAT(pipe);
+                       pipe_stats[pipe] = I915_READ(reg);
+
+                       /*
+                        * Clear the PIPE*STAT regs before the IIR
+                        */
+                       if (pipe_stats[pipe] & 0x8000ffff) {
+                               if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+                                       DRM_DEBUG_DRIVER("pipe %c underrun\n",
+                                                        pipe_name(pipe));
+                               I915_WRITE(reg, pipe_stats[pipe]);
+                               irq_received = 1;
+                       }
+               }
+               spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+               if (!irq_received)
+                       break;
+
+               ret = IRQ_HANDLED;
+
+               /* Consume port.  Then clear IIR or we'll miss events */
+               if ((I915_HAS_HOTPLUG(dev)) &&
+                   (iir & I915_DISPLAY_PORT_INTERRUPT)) {
+                       u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
+
+                       DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
+                                 hotplug_status);
+                       if (hotplug_status & dev_priv->hotplug_supported_mask)
+                               queue_work(dev_priv->wq,
+                                          &dev_priv->hotplug_work);
+
+                       I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
+                       I915_READ(PORT_HOTPLUG_STAT);
+               }
+
+               I915_WRITE(IIR, iir);
+               new_iir = I915_READ(IIR); /* Flush posted writes */
+
+               if (iir & I915_USER_INTERRUPT)
+                       notify_ring(dev, &dev_priv->ring[RCS]);
+               if (iir & I915_BSD_USER_INTERRUPT)
+                       notify_ring(dev, &dev_priv->ring[VCS]);
+
+               if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT)
+                       intel_prepare_page_flip(dev, 0);
+
+               if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT)
+                       intel_prepare_page_flip(dev, 1);
+
+               for_each_pipe(pipe) {
+                       if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
+                           drm_handle_vblank(dev, pipe)) {
+                               i915_pageflip_stall_check(dev, pipe);
+                               intel_finish_page_flip(dev, pipe);
+                       }
+
+                       if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+                               blc_event = true;
+               }
+
+
+               if (blc_event || (iir & I915_ASLE_INTERRUPT))
+                       intel_opregion_asle_intr(dev);
+
+               /* With MSI, interrupts are only generated when iir
+                * transitions from zero to nonzero.  If another bit got
+                * set while we were handling the existing iir bits, then
+                * we would never get another interrupt.
+                *
+                * This is fine on non-MSI as well, as if we hit this path
+                * we avoid exiting the interrupt handler only to generate
+                * another one.
+                *
+                * Note that for MSI this could cause a stray interrupt report
+                * if an interrupt landed in the time between writing IIR and
+                * the posting read.  This should be rare enough to never
+                * trigger the 99% of 100,000 interrupts test for disabling
+                * stray interrupts.
+                */
+               iir = new_iir;
+       }
+
+       i915_update_dri1_breadcrumb(dev);
+
+       return ret;
 }
 
-static void i915_driver_irq_uninstall(struct drm_device * dev)
+static void i965_irq_uninstall(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        int pipe;
@@ -2113,8 +2570,6 @@ static void i915_driver_irq_uninstall(struct drm_device * dev)
        if (!dev_priv)
                return;
 
-       dev_priv->vblank_pipe = 0;
-
        if (I915_HAS_HOTPLUG(dev)) {
                I915_WRITE(PORT_HOTPLUG_EN, 0);
                I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@ -2134,9 +2589,16 @@ static void i915_driver_irq_uninstall(struct drm_device * dev)
 
 void intel_irq_init(struct drm_device *dev)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+       INIT_WORK(&dev_priv->error_work, i915_error_work_func);
+       INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
+
        dev->driver->get_vblank_counter = i915_get_vblank_counter;
        dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-       if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
+       if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev) ||
+           IS_VALLEYVIEW(dev)) {
                dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
                dev->driver->get_vblank_counter = gm45_get_vblank_counter;
        }
@@ -2147,7 +2609,14 @@ void intel_irq_init(struct drm_device *dev)
                dev->driver->get_vblank_timestamp = NULL;
        dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
 
-       if (IS_IVYBRIDGE(dev)) {
+       if (IS_VALLEYVIEW(dev)) {
+               dev->driver->irq_handler = valleyview_irq_handler;
+               dev->driver->irq_preinstall = valleyview_irq_preinstall;
+               dev->driver->irq_postinstall = valleyview_irq_postinstall;
+               dev->driver->irq_uninstall = valleyview_irq_uninstall;
+               dev->driver->enable_vblank = valleyview_enable_vblank;
+               dev->driver->disable_vblank = valleyview_disable_vblank;
+       } else if (IS_IVYBRIDGE(dev)) {
                /* Share pre & uninstall handlers with ILK/SNB */
                dev->driver->irq_handler = ivybridge_irq_handler;
                dev->driver->irq_preinstall = ironlake_irq_preinstall;
@@ -2163,10 +2632,25 @@ void intel_irq_init(struct drm_device *dev)
                dev->driver->enable_vblank = ironlake_enable_vblank;
                dev->driver->disable_vblank = ironlake_disable_vblank;
        } else {
-               dev->driver->irq_preinstall = i915_driver_irq_preinstall;
-               dev->driver->irq_postinstall = i915_driver_irq_postinstall;
-               dev->driver->irq_uninstall = i915_driver_irq_uninstall;
-               dev->driver->irq_handler = i915_driver_irq_handler;
+               if (INTEL_INFO(dev)->gen == 2) {
+                       dev->driver->irq_preinstall = i8xx_irq_preinstall;
+                       dev->driver->irq_postinstall = i8xx_irq_postinstall;
+                       dev->driver->irq_handler = i8xx_irq_handler;
+                       dev->driver->irq_uninstall = i8xx_irq_uninstall;
+               } else if (INTEL_INFO(dev)->gen == 3) {
+                       /* IIR "flip pending" means done if this bit is set */
+                       I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));
+
+                       dev->driver->irq_preinstall = i915_irq_preinstall;
+                       dev->driver->irq_postinstall = i915_irq_postinstall;
+                       dev->driver->irq_uninstall = i915_irq_uninstall;
+                       dev->driver->irq_handler = i915_irq_handler;
+               } else {
+                       dev->driver->irq_preinstall = i965_irq_preinstall;
+                       dev->driver->irq_postinstall = i965_irq_postinstall;
+                       dev->driver->irq_uninstall = i965_irq_uninstall;
+                       dev->driver->irq_handler = i965_irq_handler;
+               }
                dev->driver->enable_vblank = i915_enable_vblank;
                dev->driver->disable_vblank = i915_disable_vblank;
        }
index 3886cf051bac24cf276d16afacd5201b2d159ec0..10e71a9f8bd9de612119c5d71f2df3d3ac8ec264 100644 (file)
 
 #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
 
+#define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
+
+#define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a))
+#define _MASKED_BIT_DISABLE(a) ((a) << 16)
+
 /*
  * The Bridge device's PCI config space has information about the
  * fb aperture size and the amount of pre-reserved memory.
@@ -77,6 +82,7 @@
 #define  GRDOM_FULL    (0<<2)
 #define  GRDOM_RENDER  (1<<2)
 #define  GRDOM_MEDIA   (3<<2)
+#define  GRDOM_RESET_ENABLE (1<<0)
 
 #define GEN6_MBCUNIT_SNPCR     0x900c /* for LLC config */
 #define   GEN6_MBC_SNPCR_SHIFT 21
 #define   ECOCHK_PPGTT_CACHE64B                (0x3<<3)
 #define   ECOCHK_PPGTT_CACHE4B         (0x0<<3)
 
+#define GAC_ECO_BITS                   0x14090
+#define   ECOBITS_PPGTT_CACHE64B       (3<<8)
+#define   ECOBITS_PPGTT_CACHE4B                (0<<8)
+
+#define GAB_CTL                                0x24000
+#define   GAB_CTL_CONT_AFTER_PAGEFAULT (1<<8)
+
 /* VGA stuff */
 
 #define VGA_ST01_MDA 0x3ba
 #define   MI_BATCH_NON_SECURE  (1)
 #define   MI_BATCH_NON_SECURE_I965 (1<<8)
 #define MI_BATCH_BUFFER_START  MI_INSTR(0x31, 0)
+#define   MI_BATCH_GTT             (2<<6) /* aliased with (1<<7) on gen4 */
 #define MI_SEMAPHORE_MBOX      MI_INSTR(0x16, 1) /* gen6+ */
 #define  MI_SEMAPHORE_GLOBAL_GTT    (1<<22)
 #define  MI_SEMAPHORE_UPDATE       (1<<21)
 #define  DEBUG_RESET_RENDER            (1<<8)
 #define  DEBUG_RESET_DISPLAY           (1<<9)
 
+/*
+ * DPIO - a special bus for various display related registers to hide behind:
+ *  0x800c: m1, m2, n, p1, p2, k dividers
+ *  0x8014: REF and SFR select
+ *  0x8014: N divider, VCO select
+ *  0x801c/3c: core clock bits
+ *  0x8048/68: low pass filter coefficients
+ *  0x8100: fast clock controls
+ */
+#define DPIO_PKT                       0x2100
+#define  DPIO_RID                      (0<<24)
+#define  DPIO_OP_WRITE                 (1<<16)
+#define  DPIO_OP_READ                  (0<<16)
+#define  DPIO_PORTID                   (0x12<<8)
+#define  DPIO_BYTE                     (0xf<<4)
+#define  DPIO_BUSY                     (1<<0) /* status only */
+#define DPIO_DATA                      0x2104
+#define DPIO_REG                       0x2108
+#define DPIO_CTL                       0x2110
+#define  DPIO_MODSEL1                  (1<<3) /* if ref clk b == 27 */
+#define  DPIO_MODSEL0                  (1<<2) /* if ref clk a == 27 */
+#define  DPIO_SFR_BYPASS               (1<<1)
+#define  DPIO_RESET                    (1<<0)
+
+#define _DPIO_DIV_A                    0x800c
+#define   DPIO_POST_DIV_SHIFT          (28) /* 3 bits */
+#define   DPIO_K_SHIFT                 (24) /* 4 bits */
+#define   DPIO_P1_SHIFT                        (21) /* 3 bits */
+#define   DPIO_P2_SHIFT                        (16) /* 5 bits */
+#define   DPIO_N_SHIFT                 (12) /* 4 bits */
+#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 _DPIO_REFSFR_A                 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_SHIFT    16 /* 2 bits */
+#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 _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 _DPIO_LFP_COEFF_A              0x8048
+#define _DPIO_LFP_COEFF_B              0x8068
+#define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B)
+
+#define DPIO_FASTCLK_DISABLE           0x8100
 
 /*
  * Fence registers
 #define ARB_MODE               0x04030
 #define   ARB_MODE_SWIZZLE_SNB (1<<4)
 #define   ARB_MODE_SWIZZLE_IVB (1<<5)
-#define   ARB_MODE_ENABLE(x)   GFX_MODE_ENABLE(x)
-#define   ARB_MODE_DISABLE(x)  GFX_MODE_DISABLE(x)
 #define RENDER_HWS_PGA_GEN7    (0x04080)
 #define RING_FAULT_REG(ring)   (0x4094 + 0x100*(ring)->id)
 #define DONE_REG               0x40b0
 #define INSTDONE       0x02090
 #define NOPID          0x02094
 #define HWSTAM         0x02098
+#define DMA_FADD_I8XX  0x020d0
 
 #define ERROR_GEN6     0x040a0
 
  */
 # define _3D_CHICKEN2_WM_READ_PIPELINED                        (1 << 14)
 #define _3D_CHICKEN3   0x02090
+#define  _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL          (1 << 5)
 
 #define MI_MODE                0x0209c
 # define VS_TIMER_DISPATCH                             (1 << 6)
 #define   GFX_PSMI_GRANULARITY         (1<<10)
 #define   GFX_PPGTT_ENABLE             (1<<9)
 
-#define GFX_MODE_ENABLE(bit) (((bit) << 16) | (bit))
-#define GFX_MODE_DISABLE(bit) (((bit) << 16) | (0))
-
 #define SCPD0          0x0209c /* 915+ only */
 #define IER            0x020a0
 #define IIR            0x020a4
 #define IMR            0x020a8
 #define ISR            0x020ac
+#define VLV_IIR_RW     0x182084
+#define VLV_IER                0x1820a0
+#define VLV_IIR                0x1820a4
+#define VLV_IMR                0x1820a8
+#define VLV_ISR                0x1820ac
 #define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT           (1<<18)
 #define   I915_DISPLAY_PORT_INTERRUPT                  (1<<17)
 #define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT   (1<<15)
 #define LM_BURST_LENGTH     0x00000700
 #define LM_FIFO_WATERMARK   0x0000001F
 #define MI_ARB_STATE   0x020e4 /* 915+ only */
-#define   MI_ARB_MASK_SHIFT      16    /* shift for enable bits */
 
 /* Make render/texture TLB fetches lower priorty than associated data
  *   fetches. This is not turned on by default
 #define   MI_ARB_DISPLAY_PRIORITY_B_A          (1 << 0)        /* display B > display A */
 
 #define CACHE_MODE_0   0x02120 /* 915+ only */
-#define   CM0_MASK_SHIFT          16
 #define   CM0_IZ_OPT_DISABLE      (1<<6)
 #define   CM0_ZR_OPT_DISABLE      (1<<5)
+#define          CM0_STC_EVICT_DISABLE_LRA_SNB (1<<5)
 #define   CM0_DEPTH_EVICT_DISABLE (1<<4)
 #define   CM0_COLOR_EVICT_DISABLE (1<<3)
 #define   CM0_DEPTH_WRITE_DISABLE (1<<1)
 #define   ECO_GATING_CX_ONLY   (1<<3)
 #define   ECO_FLIP_DONE                (1<<0)
 
-/* GEN6 interrupt control */
+#define CACHE_MODE_1           0x7004 /* IVB+ */
+#define   PIXEL_SUBSPAN_COLLECT_OPT_DISABLE (1<<6)
+
+/* GEN6 interrupt control
+ * Note that the per-ring interrupt bits do alias with the global interrupt bits
+ * in GTIMR. */
 #define GEN6_RENDER_HWSTAM     0x2098
 #define GEN6_RENDER_IMR                0x20a8
 #define   GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT         (1 << 8)
 
 #define GEN6_BSD_RNCID                 0x12198
 
+#define GEN7_FF_THREAD_MODE            0x20a0
+#define   GEN7_FF_SCHED_MASK           0x0077070
+#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   GEN7_FF_TS_SCHED_HW          (0x0<<16) /* Default */
+#define   GEN7_FF_VS_SCHED_HS1         (0x5<<12)
+#define   GEN7_FF_VS_SCHED_HS0         (0x3<<12)
+#define   GEN7_FF_VS_SCHED_LOAD_BALANCE        (0x1<<12) /* Default */
+#define   GEN7_FF_VS_SCHED_HW          (0x0<<12)
+#define   GEN7_FF_DS_SCHED_HS1         (0x5<<4)
+#define   GEN7_FF_DS_SCHED_HS0         (0x3<<4)
+#define   GEN7_FF_DS_SCHED_LOAD_BALANCE        (0x1<<4)  /* Default */
+#define   GEN7_FF_DS_SCHED_HW          (0x0<<4)
+
 /*
  * Framebuffer compression (915+ only)
  */
 #define   GMBUS_PORT_PANEL     3
 #define   GMBUS_PORT_DPC       4 /* HDMIC */
 #define   GMBUS_PORT_DPB       5 /* SDVO, HDMIB */
-                                 /* 6 reserved */
-#define   GMBUS_PORT_DPD       7 /* HDMID */
-#define   GMBUS_NUM_PORTS       8
+#define   GMBUS_PORT_DPD       6 /* HDMID */
+#define   GMBUS_PORT_RESERVED  7 /* 7 reserved */
+#define   GMBUS_NUM_PORTS      (GMBUS_PORT_DPD - GMBUS_PORT_SSC + 1)
 #define GMBUS1                 0x5104 /* command/status */
 #define   GMBUS_SW_CLR_INT     (1<<31)
 #define   GMBUS_SW_RDY         (1<<30)
 #define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B)
 #define   DPLL_VCO_ENABLE              (1 << 31)
 #define   DPLL_DVO_HIGH_SPEED          (1 << 30)
+#define   DPLL_EXT_BUFFER_ENABLE_VLV   (1 << 30)
 #define   DPLL_SYNCLOCK_ENABLE         (1 << 29)
+#define   DPLL_REFA_CLK_ENABLE_VLV     (1 << 29)
 #define   DPLL_VGA_MODE_DIS            (1 << 28)
 #define   DPLLB_MODE_DAC_SERIAL                (1 << 26) /* i915 */
 #define   DPLLB_MODE_LVDS              (2 << 26) /* i915 */
 #define   DPLL_P2_CLOCK_DIV_MASK       0x03000000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK  0x00ff0000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */
+#define   DPLL_INTEGRATED_CLOCK_VLV    (1<<13)
 
 #define SRX_INDEX              0x3c4
 #define SRX_DATA               0x3c5
 #define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT     0
 #define _DPLL_B_MD 0x06020 /* 965+ only */
 #define DPLL_MD(pipe) _PIPE(pipe, _DPLL_A_MD, _DPLL_B_MD)
+
 #define _FPA0  0x06040
 #define _FPA1  0x06044
 #define _FPB0  0x06048
 #define RAMCLK_GATE_D          0x6210          /* CRL only */
 #define DEUC                   0x6214          /* CRL only */
 
+#define FW_BLC_SELF_VLV                0x6500
+#define  FW_CSPWRDWNEN         (1<<15)
+
 /*
  * Palette regs
  */
 #define   PIPECONF_DISABLE     0
 #define   PIPECONF_DOUBLE_WIDE (1<<30)
 #define   I965_PIPECONF_ACTIVE (1<<30)
+#define   PIPECONF_FRAME_START_DELAY_MASK (3<<27)
 #define   PIPECONF_SINGLE_WIDE 0
 #define   PIPECONF_PIPE_UNLOCKED 0
 #define   PIPECONF_PIPE_LOCKED (1<<25)
 #define   PIPECONF_DITHER_TYPE_TEMP (3<<2)
 #define _PIPEASTAT             0x70024
 #define   PIPE_FIFO_UNDERRUN_STATUS            (1UL<<31)
+#define   SPRITE1_FLIPDONE_INT_EN_VLV          (1UL<<30)
 #define   PIPE_CRC_ERROR_ENABLE                        (1UL<<29)
 #define   PIPE_CRC_DONE_ENABLE                 (1UL<<28)
 #define   PIPE_GMBUS_EVENT_ENABLE              (1UL<<27)
+#define   PLANE_FLIP_DONE_INT_EN_VLV           (1UL<<26)
 #define   PIPE_HOTPLUG_INTERRUPT_ENABLE                (1UL<<26)
 #define   PIPE_VSYNC_INTERRUPT_ENABLE          (1UL<<25)
 #define   PIPE_DISPLAY_LINE_COMPARE_ENABLE     (1UL<<24)
 #define   PIPE_DPST_EVENT_ENABLE               (1UL<<23)
+#define   SPRITE0_FLIP_DONE_INT_EN_VLV         (1UL<<26)
 #define   PIPE_LEGACY_BLC_EVENT_ENABLE         (1UL<<22)
 #define   PIPE_ODD_FIELD_INTERRUPT_ENABLE      (1UL<<21)
 #define   PIPE_EVEN_FIELD_INTERRUPT_ENABLE     (1UL<<20)
 #define   PIPE_HOTPLUG_TV_INTERRUPT_ENABLE     (1UL<<18) /* pre-965 */
 #define   PIPE_START_VBLANK_INTERRUPT_ENABLE   (1UL<<18) /* 965 or later */
 #define   PIPE_VBLANK_INTERRUPT_ENABLE         (1UL<<17)
+#define   PIPEA_HBLANK_INT_EN_VLV              (1UL<<16)
 #define   PIPE_OVERLAY_UPDATED_ENABLE          (1UL<<16)
+#define   SPRITE1_FLIPDONE_INT_STATUS_VLV      (1UL<<15)
+#define   SPRITE0_FLIPDONE_INT_STATUS_VLV      (1UL<<15)
 #define   PIPE_CRC_ERROR_INTERRUPT_STATUS      (1UL<<13)
 #define   PIPE_CRC_DONE_INTERRUPT_STATUS       (1UL<<12)
 #define   PIPE_GMBUS_INTERRUPT_STATUS          (1UL<<11)
+#define   PLANE_FLIPDONE_INT_STATUS_VLV                (1UL<<10)
 #define   PIPE_HOTPLUG_INTERRUPT_STATUS                (1UL<<10)
 #define   PIPE_VSYNC_INTERRUPT_STATUS          (1UL<<9)
 #define   PIPE_DISPLAY_LINE_COMPARE_STATUS     (1UL<<8)
 #define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL)
 #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT)
 
+#define VLV_DPFLIPSTAT                         0x70028
+#define   PIPEB_LINE_COMPARE_STATUS            (1<<29)
+#define   PIPEB_HLINE_INT_EN                   (1<<28)
+#define   PIPEB_VBLANK_INT_EN                  (1<<27)
+#define   SPRITED_FLIPDONE_INT_EN              (1<<26)
+#define   SPRITEC_FLIPDONE_INT_EN              (1<<25)
+#define   PLANEB_FLIPDONE_INT_EN               (1<<24)
+#define   PIPEA_LINE_COMPARE_STATUS            (1<<21)
+#define   PIPEA_HLINE_INT_EN                   (1<<20)
+#define   PIPEA_VBLANK_INT_EN                  (1<<19)
+#define   SPRITEB_FLIPDONE_INT_EN              (1<<18)
+#define   SPRITEA_FLIPDONE_INT_EN              (1<<17)
+#define   PLANEA_FLIPDONE_INT_EN               (1<<16)
+
+#define DPINVGTT                               0x7002c /* VLV only */
+#define   CURSORB_INVALID_GTT_INT_EN           (1<<23)
+#define   CURSORA_INVALID_GTT_INT_EN           (1<<22)
+#define   SPRITED_INVALID_GTT_INT_EN           (1<<21)
+#define   SPRITEC_INVALID_GTT_INT_EN           (1<<20)
+#define   PLANEB_INVALID_GTT_INT_EN            (1<<19)
+#define   SPRITEB_INVALID_GTT_INT_EN           (1<<18)
+#define   SPRITEA_INVALID_GTT_INT_EN           (1<<17)
+#define   PLANEA_INVALID_GTT_INT_EN            (1<<16)
+#define   DPINVGTT_EN_MASK                     0xff0000
+#define   CURSORB_INVALID_GTT_STATUS           (1<<7)
+#define   CURSORA_INVALID_GTT_STATUS           (1<<6)
+#define   SPRITED_INVALID_GTT_STATUS           (1<<5)
+#define   SPRITEC_INVALID_GTT_STATUS           (1<<4)
+#define   PLANEB_INVALID_GTT_STATUS            (1<<3)
+#define   SPRITEB_INVALID_GTT_STATUS           (1<<2)
+#define   SPRITEA_INVALID_GTT_STATUS           (1<<1)
+#define   PLANEA_INVALID_GTT_STATUS            (1<<0)
+#define   DPINVGTT_STATUS_MASK                 0xff
+
 #define DSPARB                 0x70030
 #define   DSPARB_CSTART_MASK   (0x7f << 7)
 #define   DSPARB_CSTART_SHIFT  7
 #define   DSPFW_HPLL_CURSOR_MASK       (0x3f<<16)
 #define   DSPFW_HPLL_SR_MASK           (0x1ff)
 
+/* drain latency register values*/
+#define DRAIN_LATENCY_PRECISION_32     32
+#define DRAIN_LATENCY_PRECISION_16     16
+#define VLV_DDL1                       0x70050
+#define DDL_CURSORA_PRECISION_32       (1<<31)
+#define DDL_CURSORA_PRECISION_16       (0<<31)
+#define DDL_CURSORA_SHIFT              24
+#define DDL_PLANEA_PRECISION_32                (1<<7)
+#define DDL_PLANEA_PRECISION_16                (0<<7)
+#define VLV_DDL2                       0x70054
+#define DDL_CURSORB_PRECISION_32       (1<<31)
+#define DDL_CURSORB_PRECISION_16       (0<<31)
+#define DDL_CURSORB_SHIFT              24
+#define DDL_PLANEB_PRECISION_32                (1<<7)
+#define DDL_PLANEB_PRECISION_16                (0<<7)
+
 /* FIFO watermark sizes etc */
 #define G4X_FIFO_LINE_SIZE     64
 #define I915_FIFO_LINE_SIZE    64
 #define I830_FIFO_LINE_SIZE    32
 
+#define VALLEYVIEW_FIFO_SIZE   255
 #define G4X_FIFO_SIZE          127
 #define I965_FIFO_SIZE         512
 #define I945_FIFO_SIZE         127
 #define I855GM_FIFO_SIZE       127 /* In cachelines */
 #define I830_FIFO_SIZE         95
 
+#define VALLEYVIEW_MAX_WM      0xff
 #define G4X_MAX_WM             0x3f
 #define I915_MAX_WM            0x3f
 
 #define PINEVIEW_CURSOR_DFT_WM 0
 #define PINEVIEW_CURSOR_GUARD_WM       5
 
+#define VALLEYVIEW_CURSOR_MAX_WM 64
 #define I965_CURSOR_FIFO       64
 #define I965_CURSOR_MAX_WM     32
 #define I965_CURSOR_DFT_WM     8
 #define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF)
 #define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF)
 
+/* Display/Sprite base address macros */
+#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                  0x71410
 #define SWF01                  0x71414
 #define DE_PCH_EVENT_IVB               (1<<28)
 #define DE_DP_A_HOTPLUG_IVB            (1<<27)
 #define DE_AUX_CHANNEL_A_IVB           (1<<26)
+#define DE_SPRITEC_FLIP_DONE_IVB       (1<<14)
+#define DE_PLANEC_FLIP_DONE_IVB                (1<<13)
+#define DE_PIPEC_VBLANK_IVB            (1<<10)
 #define DE_SPRITEB_FLIP_DONE_IVB       (1<<9)
-#define DE_SPRITEA_FLIP_DONE_IVB       (1<<4)
 #define DE_PLANEB_FLIP_DONE_IVB                (1<<8)
-#define DE_PLANEA_FLIP_DONE_IVB                (1<<3)
 #define DE_PIPEB_VBLANK_IVB            (1<<5)
+#define DE_SPRITEA_FLIP_DONE_IVB       (1<<4)
+#define DE_PLANEA_FLIP_DONE_IVB                (1<<3)
 #define DE_PIPEA_VBLANK_IVB            (1<<0)
 
+#define VLV_MASTER_IER                 0x4400c /* Gunit master IER */
+#define   MASTER_INTERRUPT_ENABLE      (1<<31)
+
 #define DEISR   0x44000
 #define DEIMR   0x44004
 #define DEIIR   0x44008
 #define DEIER   0x4400c
 
-/* GT interrupt */
-#define GT_PIPE_NOTIFY         (1 << 4)
-#define GT_SYNC_STATUS          (1 << 2)
-#define GT_USER_INTERRUPT       (1 << 0)
-#define GT_BSD_USER_INTERRUPT   (1 << 5)
-#define GT_GEN6_BSD_USER_INTERRUPT     (1 << 12)
-#define GT_BLT_USER_INTERRUPT  (1 << 22)
+/* GT interrupt.
+ * Note that for gen6+ the ring-specific interrupt bits do alias with the
+ * corresponding bits in the per-ring interrupt control registers. */
+#define GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT   (1 << 26)
+#define GT_GEN6_BLT_CS_ERROR_INTERRUPT         (1 << 25)
+#define GT_GEN6_BLT_USER_INTERRUPT             (1 << 22)
+#define GT_GEN6_BSD_CS_ERROR_INTERRUPT         (1 << 15)
+#define GT_GEN6_BSD_USER_INTERRUPT             (1 << 12)
+#define GT_BSD_USER_INTERRUPT                  (1 << 5) /* ilk only */
+#define GT_GEN7_L3_PARITY_ERROR_INTERRUPT      (1 << 5)
+#define GT_PIPE_NOTIFY                         (1 << 4)
+#define GT_RENDER_CS_ERROR_INTERRUPT           (1 << 3)
+#define GT_SYNC_STATUS                         (1 << 2)
+#define GT_USER_INTERRUPT                      (1 << 0)
 
 #define GTISR   0x44010
 #define GTIMR   0x44014
 
 #define _PCH_DPLL_A              0xc6014
 #define _PCH_DPLL_B              0xc6018
-#define PCH_DPLL(pipe) (pipe == 0 ?  _PCH_DPLL_A : _PCH_DPLL_B)
+#define _PCH_DPLL(pll) (pll == 0 ? _PCH_DPLL_A : _PCH_DPLL_B)
 
 #define _PCH_FPA0                0xc6040
 #define  FP_CB_TUNE            (0x3<<22)
 #define _PCH_FPA1                0xc6044
 #define _PCH_FPB0                0xc6048
 #define _PCH_FPB1                0xc604c
-#define PCH_FP0(pipe) (pipe == 0 ? _PCH_FPA0 : _PCH_FPB0)
-#define PCH_FP1(pipe) (pipe == 0 ? _PCH_FPA1 : _PCH_FPB1)
+#define _PCH_FP0(pll) (pll == 0 ? _PCH_FPA0 : _PCH_FPB0)
+#define _PCH_FP1(pll) (pll == 0 ? _PCH_FPA1 : _PCH_FPB1)
 
 #define PCH_DPLL_TEST           0xc606c
 
 #define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B)
 #define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B)
 
+#define VLV_VIDEO_DIP_CTL_A            0x60220
+#define VLV_VIDEO_DIP_DATA_A           0x60208
+#define VLV_VIDEO_DIP_GDCP_PAYLOAD_A   0x60210
+
+#define VLV_VIDEO_DIP_CTL_B            0x61170
+#define VLV_VIDEO_DIP_DATA_B           0x61174
+#define VLV_VIDEO_DIP_GDCP_PAYLOAD_B   0x61178
+
+#define VLV_TVIDEO_DIP_CTL(pipe) \
+        _PIPE(pipe, VLV_VIDEO_DIP_CTL_A, VLV_VIDEO_DIP_CTL_B)
+#define VLV_TVIDEO_DIP_DATA(pipe) \
+        _PIPE(pipe, VLV_VIDEO_DIP_DATA_A, VLV_VIDEO_DIP_DATA_B)
+#define VLV_TVIDEO_DIP_GCP(pipe) \
+       _PIPE(pipe, VLV_VIDEO_DIP_GDCP_PAYLOAD_A, VLV_VIDEO_DIP_GDCP_PAYLOAD_B)
+
 #define _TRANS_HTOTAL_B          0xe1000
 #define _TRANS_HBLANK_B          0xe1004
 #define _TRANS_HSYNC_B           0xe1008
 #define  FDI_LINK_TRAIN_PATTERN_IDLE_CPT       (2<<8)
 #define  FDI_LINK_TRAIN_NORMAL_CPT             (3<<8)
 #define  FDI_LINK_TRAIN_PATTERN_MASK_CPT       (3<<8)
+/* LPT */
+#define  FDI_PORT_WIDTH_2X_LPT                 (1<<19)
+#define  FDI_PORT_WIDTH_1X_LPT                 (0<<19)
 
 #define _FDI_RXA_MISC            0xf0010
 #define _FDI_RXB_MISC            0xf1010
 #define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 
 /* or SDVOB */
+#define VLV_HDMIB 0x61140
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
 #define  TRANSCODER(pipe)       ((pipe) << 30)
 #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB       (0x3f<<22)
 
 #define  FORCEWAKE                             0xA18C
+#define  FORCEWAKE_VLV                         0x1300b0
+#define  FORCEWAKE_ACK_VLV                     0x1300b4
 #define  FORCEWAKE_ACK                         0x130090
 #define  FORCEWAKE_MT                          0xa188 /* multi-threaded */
 #define  FORCEWAKE_MT_ACK                      0x130040
 #define  GT_FIFO_FREE_ENTRIES                  0x120008
 #define    GT_FIFO_NUM_RESERVED_ENTRIES                20
 
+#define GEN6_UCGCTL1                           0x9400
+# define GEN6_BLBUNIT_CLOCK_GATE_DISABLE               (1 << 5)
+# define GEN6_CSUNIT_CLOCK_GATE_DISABLE                        (1 << 7)
+
 #define GEN6_UCGCTL2                           0x9404
 # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE               (1 << 13)
 # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE              (1 << 12)
                                                 GEN6_PM_RP_DOWN_THRESHOLD | \
                                                 GEN6_PM_RP_DOWN_TIMEOUT)
 
+#define GEN6_GT_GFX_RC6_LOCKED                 0x138104
+#define GEN6_GT_GFX_RC6                                0x138108
+#define GEN6_GT_GFX_RC6p                       0x13810C
+#define GEN6_GT_GFX_RC6pp                      0x138110
+
 #define GEN6_PCODE_MAILBOX                     0x138124
 #define   GEN6_PCODE_READY                     (1<<31)
 #define   GEN6_READ_OC_PARAMS                  0xc
 #define   AUD_CONFIG_PIXEL_CLOCK_HDMI          (0xf << 16)
 #define   AUD_CONFIG_DISABLE_NCTS              (1 << 3)
 
+/* HSW Power Wells */
+#define HSW_PWR_WELL_CTL1              0x45400         /* BIOS */
+#define HSW_PWR_WELL_CTL2              0x45404         /* Driver */
+#define HSW_PWR_WELL_CTL3              0x45408         /* KVMR */
+#define HSW_PWR_WELL_CTL4              0x4540C         /* Debug */
+#define   HSW_PWR_WELL_ENABLE                          (1<<31)
+#define   HSW_PWR_WELL_STATE                           (1<<30)
+#define HSW_PWR_WELL_CTL5              0x45410
+#define   HSW_PWR_WELL_ENABLE_SINGLE_STEP      (1<<31)
+#define   HSW_PWR_WELL_PWR_GATE_OVERRIDE       (1<<20)
+#define   HSW_PWR_WELL_FORCE_ON                                (1<<19)
+#define HSW_PWR_WELL_CTL6              0x45414
+
+/* Per-pipe DDI Function Control */
+#define PIPE_DDI_FUNC_CTL_A                    0x60400
+#define PIPE_DDI_FUNC_CTL_B                    0x61400
+#define PIPE_DDI_FUNC_CTL_C                    0x62400
+#define PIPE_DDI_FUNC_CTL_EDP          0x6F400
+#define DDI_FUNC_CTL(pipe) _PIPE(pipe, \
+                                       PIPE_DDI_FUNC_CTL_A, \
+                                       PIPE_DDI_FUNC_CTL_B)
+#define  PIPE_DDI_FUNC_ENABLE          (1<<31)
+/* Those bits are ignored by pipe EDP since it can only connect to DDI A */
+#define  PIPE_DDI_PORT_MASK                            (0xf<<28)
+#define  PIPE_DDI_SELECT_PORT(x)               ((x)<<28)
+#define  PIPE_DDI_MODE_SELECT_HDMI             (0<<24)
+#define  PIPE_DDI_MODE_SELECT_DVI              (1<<24)
+#define  PIPE_DDI_MODE_SELECT_DP_SST   (2<<24)
+#define  PIPE_DDI_MODE_SELECT_DP_MST   (3<<24)
+#define  PIPE_DDI_MODE_SELECT_FDI              (4<<24)
+#define  PIPE_DDI_BPC_8                                        (0<<20)
+#define  PIPE_DDI_BPC_10                               (1<<20)
+#define  PIPE_DDI_BPC_6                                        (2<<20)
+#define  PIPE_DDI_BPC_12                               (3<<20)
+#define  PIPE_DDI_BFI_ENABLE                   (1<<4)
+#define  PIPE_DDI_PORT_WIDTH_X1                        (0<<1)
+#define  PIPE_DDI_PORT_WIDTH_X2                        (1<<1)
+#define  PIPE_DDI_PORT_WIDTH_X4                        (3<<1)
+
+/* DisplayPort Transport Control */
+#define DP_TP_CTL_A                    0x64040
+#define DP_TP_CTL_B                    0x64140
+#define DP_TP_CTL(port) _PORT(port, \
+                                       DP_TP_CTL_A, \
+                                       DP_TP_CTL_B)
+#define  DP_TP_CTL_ENABLE              (1<<31)
+#define  DP_TP_CTL_MODE_SST    (0<<27)
+#define  DP_TP_CTL_MODE_MST    (1<<27)
+#define  DP_TP_CTL_ENHANCED_FRAME_ENABLE       (1<<18)
+#define  DP_TP_CTL_FDI_AUTOTRAIN       (1<<15)
+#define  DP_TP_CTL_LINK_TRAIN_MASK             (7<<8)
+#define  DP_TP_CTL_LINK_TRAIN_PAT1             (0<<8)
+#define  DP_TP_CTL_LINK_TRAIN_PAT2             (1<<8)
+#define  DP_TP_CTL_LINK_TRAIN_NORMAL   (3<<8)
+
+/* DisplayPort Transport Status */
+#define DP_TP_STATUS_A                 0x64044
+#define DP_TP_STATUS_B                 0x64144
+#define DP_TP_STATUS(port) _PORT(port, \
+                                       DP_TP_STATUS_A, \
+                                       DP_TP_STATUS_B)
+#define  DP_TP_STATUS_AUTOTRAIN_DONE   (1<<12)
+
+/* DDI Buffer Control */
+#define DDI_BUF_CTL_A                          0x64000
+#define DDI_BUF_CTL_B                          0x64100
+#define DDI_BUF_CTL(port) _PORT(port, \
+                                       DDI_BUF_CTL_A, \
+                                       DDI_BUF_CTL_B)
+#define  DDI_BUF_CTL_ENABLE                            (1<<31)
+#define  DDI_BUF_EMP_400MV_0DB_HSW             (0<<24)   /* Sel0 */
+#define  DDI_BUF_EMP_400MV_3_5DB_HSW   (1<<24)   /* Sel1 */
+#define  DDI_BUF_EMP_400MV_6DB_HSW             (2<<24)   /* Sel2 */
+#define  DDI_BUF_EMP_400MV_9_5DB_HSW   (3<<24)   /* Sel3 */
+#define  DDI_BUF_EMP_600MV_0DB_HSW             (4<<24)   /* Sel4 */
+#define  DDI_BUF_EMP_600MV_3_5DB_HSW   (5<<24)   /* Sel5 */
+#define  DDI_BUF_EMP_600MV_6DB_HSW             (6<<24)   /* Sel6 */
+#define  DDI_BUF_EMP_800MV_0DB_HSW             (7<<24)   /* Sel7 */
+#define  DDI_BUF_EMP_800MV_3_5DB_HSW   (8<<24)   /* Sel8 */
+#define  DDI_BUF_EMP_MASK                              (0xf<<24)
+#define  DDI_BUF_IS_IDLE                               (1<<7)
+#define  DDI_PORT_WIDTH_X1                             (0<<1)
+#define  DDI_PORT_WIDTH_X2                             (1<<1)
+#define  DDI_PORT_WIDTH_X4                             (3<<1)
+#define  DDI_INIT_DISPLAY_DETECTED             (1<<0)
+
+/* DDI Buffer Translations */
+#define DDI_BUF_TRANS_A                                0x64E00
+#define DDI_BUF_TRANS_B                                0x64E60
+#define DDI_BUF_TRANS(port) _PORT(port, \
+                                       DDI_BUF_TRANS_A, \
+                                       DDI_BUF_TRANS_B)
+
+/* Sideband Interface (SBI) is programmed indirectly, via
+ * SBI_ADDR, which contains the register offset; and SBI_DATA,
+ * which contains the payload */
+#define SBI_ADDR                               0xC6000
+#define SBI_DATA                               0xC6004
+#define SBI_CTL_STAT                   0xC6008
+#define  SBI_CTL_OP_CRRD               (0x6<<8)
+#define  SBI_CTL_OP_CRWR               (0x7<<8)
+#define  SBI_RESPONSE_FAIL             (0x1<<1)
+#define  SBI_RESPONSE_SUCCESS  (0x0<<1)
+#define  SBI_BUSY                              (0x1<<0)
+#define  SBI_READY                             (0x0<<0)
+
+/* SBI offsets */
+#define  SBI_SSCDIVINTPHASE6           0x0600
+#define   SBI_SSCDIVINTPHASE_DIVSEL_MASK       ((0x7f)<<1)
+#define   SBI_SSCDIVINTPHASE_DIVSEL(x)         ((x)<<1)
+#define   SBI_SSCDIVINTPHASE_INCVAL_MASK       ((0x7f)<<8)
+#define   SBI_SSCDIVINTPHASE_INCVAL(x)         ((x)<<8)
+#define   SBI_SSCDIVINTPHASE_DIR(x)                    ((x)<<15)
+#define   SBI_SSCDIVINTPHASE_PROPAGATE         (1<<0)
+#define  SBI_SSCCTL                                    0x020c
+#define  SBI_SSCCTL6                           0x060C
+#define   SBI_SSCCTL_DISABLE           (1<<0)
+#define  SBI_SSCAUXDIV6                                0x0610
+#define   SBI_SSCAUXDIV_FINALDIV2SEL(x)                ((x)<<4)
+#define  SBI_DBUFF0                                    0x2a00
+
+/* LPT PIXCLK_GATE */
+#define PIXCLK_GATE                            0xC6020
+#define  PIXCLK_GATE_UNGATE            1<<0
+#define  PIXCLK_GATE_GATE              0<<0
+
+/* SPLL */
+#define SPLL_CTL                               0x46020
+#define  SPLL_PLL_ENABLE               (1<<31)
+#define  SPLL_PLL_SCC                  (1<<28)
+#define  SPLL_PLL_NON_SCC              (2<<28)
+#define  SPLL_PLL_FREQ_810MHz  (0<<26)
+#define  SPLL_PLL_FREQ_1350MHz (1<<26)
+
+/* WRPLL */
+#define WRPLL_CTL1                             0x46040
+#define WRPLL_CTL2                             0x46060
+#define  WRPLL_PLL_ENABLE                              (1<<31)
+#define  WRPLL_PLL_SELECT_SSC                  (0x01<<28)
+#define  WRPLL_PLL_SELECT_NON_SCC              (0x02<<28)
+#define  WRPLL_PLL_SELECT_LCPLL_2700   (0x03<<28)
+/* WRPLL divider programming */
+#define  WRPLL_DIVIDER_REFERENCE(x)            ((x)<<0)
+#define  WRPLL_DIVIDER_POST(x)                 ((x)<<8)
+#define  WRPLL_DIVIDER_FEEDBACK(x)             ((x)<<16)
+
+/* Port clock selection */
+#define PORT_CLK_SEL_A                 0x46100
+#define PORT_CLK_SEL_B                 0x46104
+#define PORT_CLK_SEL(port) _PORT(port, \
+                                       PORT_CLK_SEL_A, \
+                                       PORT_CLK_SEL_B)
+#define  PORT_CLK_SEL_LCPLL_2700       (0<<29)
+#define  PORT_CLK_SEL_LCPLL_1350       (1<<29)
+#define  PORT_CLK_SEL_LCPLL_810                (2<<29)
+#define  PORT_CLK_SEL_SPLL                     (3<<29)
+#define  PORT_CLK_SEL_WRPLL1           (4<<29)
+#define  PORT_CLK_SEL_WRPLL2           (5<<29)
+
+/* Pipe clock selection */
+#define PIPE_CLK_SEL_A                 0x46140
+#define PIPE_CLK_SEL_B                 0x46144
+#define PIPE_CLK_SEL(pipe) _PIPE(pipe, \
+                                       PIPE_CLK_SEL_A, \
+                                       PIPE_CLK_SEL_B)
+/* For each pipe, we need to select the corresponding port clock */
+#define  PIPE_CLK_SEL_DISABLED (0x0<<29)
+#define  PIPE_CLK_SEL_PORT(x)  ((x+1)<<29)
+
+/* LCPLL Control */
+#define LCPLL_CTL                              0x130040
+#define  LCPLL_PLL_DISABLE             (1<<31)
+#define  LCPLL_PLL_LOCK                        (1<<30)
+#define  LCPLL_CD_CLOCK_DISABLE        (1<<25)
+#define  LCPLL_CD2X_CLOCK_DISABLE      (1<<23)
+
+/* Pipe WM_LINETIME - watermark line time */
+#define PIPE_WM_LINETIME_A             0x45270
+#define PIPE_WM_LINETIME_B             0x45274
+#define PIPE_WM_LINETIME(pipe) _PIPE(pipe, \
+                                       PIPE_WM_LINETIME_A, \
+                                       PIPE_WM_LINETIME_A)
+#define   PIPE_WM_LINETIME_MASK                (0x1ff)
+#define   PIPE_WM_LINETIME_TIME(x)                     ((x))
+#define   PIPE_WM_LINETIME_IPS_LINETIME_MASK   (0x1ff<<16)
+#define   PIPE_WM_LINETIME_IPS_LINETIME(x)             ((x)<<16)
+
+/* SFUSE_STRAP */
+#define SFUSE_STRAP                            0xc2014
+#define  SFUSE_STRAP_DDIB_DETECTED     (1<<2)
+#define  SFUSE_STRAP_DDIC_DETECTED     (1<<1)
+#define  SFUSE_STRAP_DDID_DETECTED     (1<<0)
+
 #endif /* _I915_REG_H_ */
index 2b5eb229ff2cc1c443d7f01039a4cc308201d211..73a5c3c12fe0dbc04c4988c3f6d5d56fe67ec655 100644 (file)
@@ -40,7 +40,7 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
                return false;
 
        if (HAS_PCH_SPLIT(dev))
-               dpll_reg = PCH_DPLL(pipe);
+               dpll_reg = _PCH_DPLL(pipe);
        else
                dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
 
@@ -879,17 +879,7 @@ int i915_restore_state(struct drm_device *dev)
        mutex_unlock(&dev->struct_mutex);
 
        if (drm_core_check_feature(dev, DRIVER_MODESET))
-               intel_init_clock_gating(dev);
-
-       if (IS_IRONLAKE_M(dev)) {
-               ironlake_enable_drps(dev);
-               intel_init_emon(dev);
-       }
-
-       if (INTEL_INFO(dev)->gen >= 6) {
-               gen6_enable_rps(dev_priv);
-               gen6_update_ring_freq(dev_priv);
-       }
+               intel_modeset_init_hw(dev);
 
        mutex_lock(&dev->struct_mutex);
 
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
new file mode 100644 (file)
index 0000000..79f8344
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright Â© 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/stat.h>
+#include <linux/sysfs.h>
+#include "i915_drv.h"
+
+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 */
+
+       if (!intel_enable_rc6(dev))
+               return 0;
+
+       raw_time = I915_READ(reg) * 128ULL;
+       return DIV_ROUND_UP_ULL(raw_time, 100000);
+}
+
+static ssize_t
+show_rc6_mask(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+       return snprintf(buf, PAGE_SIZE, "%x", intel_enable_rc6(dminor->dev));
+}
+
+static ssize_t
+show_rc6_ms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+       u32 rc6_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6);
+       return snprintf(buf, PAGE_SIZE, "%u", rc6_residency);
+}
+
+static ssize_t
+show_rc6p_ms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+       u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p);
+       return snprintf(buf, PAGE_SIZE, "%u", rc6p_residency);
+}
+
+static ssize_t
+show_rc6pp_ms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+       u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp);
+       return snprintf(buf, PAGE_SIZE, "%u", rc6pp_residency);
+}
+
+static DEVICE_ATTR(rc6_enable, S_IRUGO, show_rc6_mask, NULL);
+static DEVICE_ATTR(rc6_residency_ms, S_IRUGO, show_rc6_ms, NULL);
+static DEVICE_ATTR(rc6p_residency_ms, S_IRUGO, show_rc6p_ms, NULL);
+static DEVICE_ATTR(rc6pp_residency_ms, S_IRUGO, show_rc6pp_ms, NULL);
+
+static struct attribute *rc6_attrs[] = {
+       &dev_attr_rc6_enable.attr,
+       &dev_attr_rc6_residency_ms.attr,
+       &dev_attr_rc6p_residency_ms.attr,
+       &dev_attr_rc6pp_residency_ms.attr,
+       NULL
+};
+
+static struct attribute_group rc6_attr_group = {
+       .name = power_group_name,
+       .attrs =  rc6_attrs
+};
+
+void i915_setup_sysfs(struct drm_device *dev)
+{
+       int ret;
+
+       /* ILK doesn't have any residency information */
+       if (INTEL_INFO(dev)->gen < 6)
+               return;
+
+       ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
+       if (ret)
+               DRM_ERROR("sysfs setup failed\n");
+}
+
+void i915_teardown_sysfs(struct drm_device *dev)
+{
+       sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
+}
index ead876eb6ea050767f2f2e53d770fb8d19d279ab..f1df2bd4ecf4cc37010ccb990614dcacde0936e9 100644 (file)
@@ -7,5 +7,7 @@
 
 #include "i915_drv.h"
 
+#ifndef __CHECKER__
 #define CREATE_TRACE_POINTS
 #include "i915_trace.h"
+#endif
index bae3edf956a444f1e39e30e39867db75ef33303d..f413899475e94b388526f8a036cc9c378a2ddcd4 100644 (file)
@@ -9,6 +9,7 @@
 #include <acpi/acpi_drivers.h>
 
 #include "drmP.h"
+#include "i915_drv.h"
 
 #define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */
 
@@ -182,8 +183,6 @@ static void intel_dsm_platform_mux_info(void)
                        DRM_DEBUG_DRIVER("  hpd mux info: %s\n",
                               intel_dsm_mux_type(info->buffer.pointer[3]));
                }
-       } else {
-               DRM_ERROR("MUX INFO call failed\n");
        }
 
 out:
index 8168d8f8a634ed8ccf8644f2039ee02c21b7d480..353459362f6f68eeb08a2c263366274b53c114b6 100644 (file)
@@ -24,6 +24,7 @@
  *    Eric Anholt <eric@anholt.net>
  *
  */
+#include <linux/dmi.h>
 #include <drm/drm_dp_helper.h>
 #include "drmP.h"
 #include "drm.h"
@@ -173,6 +174,28 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
        return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
 }
 
+/* get lvds_fp_timing entry
+ * this function may return NULL if the corresponding entry is invalid
+ */
+static const struct lvds_fp_timing *
+get_lvds_fp_timing(const struct bdb_header *bdb,
+                  const struct bdb_lvds_lfp_data *data,
+                  const struct bdb_lvds_lfp_data_ptrs *ptrs,
+                  int index)
+{
+       size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
+       u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
+       size_t ofs;
+
+       if (index >= ARRAY_SIZE(ptrs->ptr))
+               return NULL;
+       ofs = ptrs->ptr[index].fp_timing_offset;
+       if (ofs < data_ofs ||
+           ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
+               return NULL;
+       return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
+}
+
 /* Try to find integrated panel data */
 static void
 parse_lfp_panel_data(struct drm_i915_private *dev_priv,
@@ -182,6 +205,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
        const struct bdb_lvds_lfp_data *lvds_lfp_data;
        const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
        const struct lvds_dvo_timing *panel_dvo_timing;
+       const struct lvds_fp_timing *fp_timing;
        struct drm_display_mode *panel_fixed_mode;
        int i, downclock;
 
@@ -243,6 +267,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
                              "Normal Clock %dKHz, downclock %dKHz\n",
                              panel_fixed_mode->clock, 10*downclock);
        }
+
+       fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
+                                      lvds_lfp_data_ptrs,
+                                      lvds_options->panel_type);
+       if (fp_timing) {
+               /* check the resolution, just to be sure */
+               if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
+                   fp_timing->y_res == panel_fixed_mode->vdisplay) {
+                       dev_priv->bios_lvds_val = fp_timing->lvds_reg_val;
+                       DRM_DEBUG_KMS("VBT initial LVDS value %x\n",
+                                     dev_priv->bios_lvds_val);
+               }
+       }
 }
 
 /* Try to find sdvo panel data */
@@ -255,6 +292,11 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
        int index;
 
        index = i915_vbt_sdvo_panel_type;
+       if (index == -2) {
+               DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n");
+               return;
+       }
+
        if (index == -1) {
                struct bdb_sdvo_lvds_options *sdvo_lvds_options;
 
@@ -331,11 +373,11 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
                if (block_size >= sizeof(*general)) {
                        int bus_pin = general->crt_ddc_gmbus_pin;
                        DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
-                       if (bus_pin >= 1 && bus_pin <= 6)
+                       if (intel_gmbus_is_port_valid(bus_pin))
                                dev_priv->crt_ddc_pin = bus_pin;
                } else {
                        DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
-                                 block_size);
+                                     block_size);
                }
        }
 }
@@ -621,6 +663,26 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
        dev_priv->edp.bpp = 18;
 }
 
+static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+{
+       DRM_DEBUG_KMS("Falling back to manually reading VBT from "
+                     "VBIOS ROM for %s\n",
+                     id->ident);
+       return 1;
+}
+
+static const struct dmi_system_id intel_no_opregion_vbt[] = {
+       {
+               .callback = intel_no_opregion_vbt_callback,
+               .ident = "ThinkCentre A57",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
+               },
+       },
+       { }
+};
+
 /**
  * intel_parse_bios - find VBT and initialize settings from the BIOS
  * @dev: DRM device
@@ -641,7 +703,7 @@ intel_parse_bios(struct drm_device *dev)
        init_vbt_defaults(dev_priv);
 
        /* XXX Should this validation be moved to intel_opregion.c? */
-       if (dev_priv->opregion.vbt) {
+       if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) {
                struct vbt_header *vbt = dev_priv->opregion.vbt;
                if (memcmp(vbt->signature, "$VBT", 4) == 0) {
                        DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
index 4d3d736a4f56a9c65b315162dac4dc1b2b372c28..417ca99e697d8c842d150d9252157e2503f4a229 100644 (file)
@@ -55,18 +55,36 @@ static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
                            struct intel_crt, base);
 }
 
-static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
+static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 temp, reg;
+       u32 temp;
 
-       if (HAS_PCH_SPLIT(dev))
-               reg = PCH_ADPA;
-       else
-               reg = ADPA;
+       temp = I915_READ(PCH_ADPA);
+       temp &= ~ADPA_DAC_ENABLE;
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               temp |= ADPA_DAC_ENABLE;
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               /* Just leave port enable cleared */
+               break;
+       }
+
+       I915_WRITE(PCH_ADPA, temp);
+}
 
-       temp = I915_READ(reg);
+static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 temp;
+
+       temp = I915_READ(ADPA);
        temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
        temp &= ~ADPA_DAC_ENABLE;
 
@@ -85,7 +103,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
                break;
        }
 
-       I915_WRITE(reg, temp);
+       I915_WRITE(ADPA, temp);
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -278,9 +296,10 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
        if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
                struct edid *edid;
                bool is_digital = false;
+               struct i2c_adapter *i2c;
 
-               edid = drm_get_edid(connector,
-                       &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
+               i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
+               edid = drm_get_edid(connector, i2c);
                /*
                 * This may be a DVI-I connector with a shared DDC
                 * link between analog and digital outputs, so we
@@ -430,8 +449,8 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 {
        struct drm_device *dev = connector->dev;
        struct intel_crt *crt = intel_attached_crt(connector);
-       struct drm_crtc *crtc;
        enum drm_connector_status status;
+       struct intel_load_detect_pipe tmp;
 
        if (I915_HAS_HOTPLUG(dev)) {
                if (intel_crt_detect_hotplug(connector)) {
@@ -450,23 +469,16 @@ intel_crt_detect(struct drm_connector *connector, bool force)
                return connector->status;
 
        /* for pre-945g platforms use load detect */
-       crtc = crt->base.base.crtc;
-       if (crtc && crtc->enabled) {
-               status = intel_crt_load_detect(crt);
-       } else {
-               struct intel_load_detect_pipe tmp;
-
-               if (intel_get_load_detect_pipe(&crt->base, connector, NULL,
-                                              &tmp)) {
-                       if (intel_crt_detect_ddc(connector))
-                               status = connector_status_connected;
-                       else
-                               status = intel_crt_load_detect(crt);
-                       intel_release_load_detect_pipe(&crt->base, connector,
-                                                      &tmp);
-               } else
-                       status = connector_status_unknown;
-       }
+       if (intel_get_load_detect_pipe(&crt->base, connector, NULL,
+                                      &tmp)) {
+               if (intel_crt_detect_ddc(connector))
+                       status = connector_status_connected;
+               else
+                       status = intel_crt_load_detect(crt);
+               intel_release_load_detect_pipe(&crt->base, connector,
+                                              &tmp);
+       } else
+               status = connector_status_unknown;
 
        return status;
 }
@@ -483,15 +495,16 @@ static int intel_crt_get_modes(struct drm_connector *connector)
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
+       struct i2c_adapter *i2c;
 
-       ret = intel_ddc_get_modes(connector,
-                                &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
+       i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
+       ret = intel_ddc_get_modes(connector, i2c);
        if (ret || !IS_G4X(dev))
                return ret;
 
        /* Try to probe digital port for output in DVI-I -> VGA mode. */
-       return intel_ddc_get_modes(connector,
-                                  &dev_priv->gmbus[GMBUS_PORT_DPB].adapter);
+       i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
+       return intel_ddc_get_modes(connector, i2c);
 }
 
 static int intel_crt_set_property(struct drm_connector *connector,
@@ -514,12 +527,20 @@ static void intel_crt_reset(struct drm_connector *connector)
  * Routines for controlling stuff on the analog port
  */
 
-static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = {
-       .dpms = intel_crt_dpms,
+static const struct drm_encoder_helper_funcs pch_encoder_funcs = {
        .mode_fixup = intel_crt_mode_fixup,
        .prepare = intel_encoder_prepare,
        .commit = intel_encoder_commit,
        .mode_set = intel_crt_mode_set,
+       .dpms = pch_crt_dpms,
+};
+
+static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
+       .mode_fixup = intel_crt_mode_fixup,
+       .prepare = intel_encoder_prepare,
+       .commit = intel_encoder_commit,
+       .mode_set = intel_crt_mode_set,
+       .dpms = gmch_crt_dpms,
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
@@ -543,7 +564,7 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
 
 static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
 {
-       DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident);
+       DRM_INFO("Skipping CRT initialization for %s\n", id->ident);
        return 1;
 }
 
@@ -565,6 +586,7 @@ void intel_crt_init(struct drm_device *dev)
        struct intel_crt *crt;
        struct intel_connector *intel_connector;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       const struct drm_encoder_helper_funcs *encoder_helper_funcs;
 
        /* Skip machines without VGA that falsely report hotplug events */
        if (dmi_check_system(intel_no_crt))
@@ -600,7 +622,12 @@ void intel_crt_init(struct drm_device *dev)
                connector->interlace_allowed = 1;
        connector->doublescan_allowed = 0;
 
-       drm_encoder_helper_add(&crt->base.base, &intel_crt_helper_funcs);
+       if (HAS_PCH_SPLIT(dev))
+               encoder_helper_funcs = &pch_encoder_funcs;
+       else
+               encoder_helper_funcs = &gmch_encoder_funcs;
+
+       drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
        drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
        drm_sysfs_connector_add(connector);
index d514719f65e26516a823577a8ef3e5c161ffb5a8..6b4139064f9c48d0de9b8e799553347b8c581417 100644 (file)
@@ -24,7 +24,7 @@
  *     Eric Anholt <eric@anholt.net>
  */
 
-#include <linux/cpufreq.h>
+#include <linux/dmi.h>
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/i2c.h>
@@ -44,7 +44,6 @@
 #define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
 
 bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
-static void intel_update_watermarks(struct drm_device *dev);
 static void intel_increase_pllclock(struct drm_crtc *crtc);
 static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
 
@@ -360,6 +359,88 @@ static const intel_limit_t intel_limits_ironlake_display_port = {
        .find_pll = intel_find_pll_ironlake_dp,
 };
 
+u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
+{
+       unsigned long flags;
+       u32 val = 0;
+
+       spin_lock_irqsave(&dev_priv->dpio_lock, flags);
+       if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
+               DRM_ERROR("DPIO idle wait timed out\n");
+               goto out_unlock;
+       }
+
+       I915_WRITE(DPIO_REG, reg);
+       I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_READ | DPIO_PORTID |
+                  DPIO_BYTE);
+       if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
+               DRM_ERROR("DPIO read wait timed out\n");
+               goto out_unlock;
+       }
+       val = I915_READ(DPIO_DATA);
+
+out_unlock:
+       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
+       return val;
+}
+
+static void vlv_init_dpio(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       /* Reset the DPIO config */
+       I915_WRITE(DPIO_CTL, 0);
+       POSTING_READ(DPIO_CTL);
+       I915_WRITE(DPIO_CTL, 1);
+       POSTING_READ(DPIO_CTL);
+}
+
+static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
+{
+       DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
+       return 1;
+}
+
+static const struct dmi_system_id intel_dual_link_lvds[] = {
+       {
+               .callback = intel_dual_link_lvds_callback,
+               .ident = "Apple MacBook Pro (Core i5/i7 Series)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
+               },
+       },
+       { }     /* terminating entry */
+};
+
+static bool is_dual_link_lvds(struct drm_i915_private *dev_priv,
+                             unsigned int reg)
+{
+       unsigned int val;
+
+       /* use the module option value if specified */
+       if (i915_lvds_channel_mode > 0)
+               return i915_lvds_channel_mode == 2;
+
+       if (dmi_check_system(intel_dual_link_lvds))
+               return true;
+
+       if (dev_priv->lvds_val)
+               val = dev_priv->lvds_val;
+       else {
+               /* BIOS should set the proper LVDS register value at boot, but
+                * in reality, it doesn't set the value when the lid is closed;
+                * we need to check "the value to be set" in VBT when LVDS
+                * register is uninitialized.
+                */
+               val = I915_READ(reg);
+               if (!(val & ~LVDS_DETECTED))
+                       val = dev_priv->bios_lvds_val;
+               dev_priv->lvds_val = val;
+       }
+       return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
+}
+
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
                                                int refclk)
 {
@@ -368,8 +449,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
        const intel_limit_t *limit;
 
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
-                   LVDS_CLKB_POWER_UP) {
+               if (is_dual_link_lvds(dev_priv, PCH_LVDS)) {
                        /* LVDS dual channel */
                        if (refclk == 100000)
                                limit = &intel_limits_ironlake_dual_lvds_100m;
@@ -397,8 +477,7 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
        const intel_limit_t *limit;
 
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
-                   LVDS_CLKB_POWER_UP)
+               if (is_dual_link_lvds(dev_priv, LVDS))
                        /* LVDS with dual channel */
                        limit = &intel_limits_g4x_dual_channel_lvds;
                else
@@ -536,8 +615,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                 * reliably set up different single/dual channel state, if we
                 * even can.
                 */
-               if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
-                   LVDS_CLKB_POWER_UP)
+               if (is_dual_link_lvds(dev_priv, LVDS))
                        clock.p2 = limit->p2.p2_fast;
                else
                        clock.p2 = limit->p2.p2_slow;
@@ -811,26 +889,28 @@ static void assert_pll(struct drm_i915_private *dev_priv,
 
 /* For ILK+ */
 static void assert_pch_pll(struct drm_i915_private *dev_priv,
-                          enum pipe pipe, bool state)
+                          struct intel_crtc *intel_crtc, bool state)
 {
        int reg;
        u32 val;
        bool cur_state;
 
+       if (!intel_crtc->pch_pll) {
+               WARN(1, "asserting PCH PLL enabled with no PLL\n");
+               return;
+       }
+
        if (HAS_PCH_CPT(dev_priv->dev)) {
                u32 pch_dpll;
 
                pch_dpll = I915_READ(PCH_DPLL_SEL);
 
                /* Make sure the selected PLL is enabled to the transcoder */
-               WARN(!((pch_dpll >> (4 * pipe)) & 8),
-                    "transcoder %d PLL not enabled\n", pipe);
-
-               /* Convert the transcoder pipe number to a pll pipe number */
-               pipe = (pch_dpll >> (4 * pipe)) & 1;
+               WARN(!((pch_dpll >> (4 * intel_crtc->pipe)) & 8),
+                    "transcoder %d PLL not enabled\n", intel_crtc->pipe);
        }
 
-       reg = PCH_DPLL(pipe);
+       reg = intel_crtc->pch_pll->pll_reg;
        val = I915_READ(reg);
        cur_state = !!(val & DPLL_VCO_ENABLE);
        WARN(cur_state != state,
@@ -1206,60 +1286,79 @@ static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
  * The PCH PLL needs to be enabled before the PCH transcoder, since it
  * drives the transcoder clock.
  */
-static void intel_enable_pch_pll(struct drm_i915_private *dev_priv,
-                                enum pipe pipe)
+static void intel_enable_pch_pll(struct intel_crtc *intel_crtc)
 {
+       struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
+       struct intel_pch_pll *pll = intel_crtc->pch_pll;
        int reg;
        u32 val;
 
-       if (pipe > 1)
-               return;
-
        /* PCH only available on ILK+ */
        BUG_ON(dev_priv->info->gen < 5);
+       BUG_ON(pll == NULL);
+       BUG_ON(pll->refcount == 0);
+
+       DRM_DEBUG_KMS("enable PCH PLL %x (active %d, on? %d)for crtc %d\n",
+                     pll->pll_reg, pll->active, pll->on,
+                     intel_crtc->base.base.id);
 
        /* PCH refclock must be enabled first */
        assert_pch_refclk_enabled(dev_priv);
 
-       reg = PCH_DPLL(pipe);
+       if (pll->active++ && pll->on) {
+               assert_pch_pll_enabled(dev_priv, intel_crtc);
+               return;
+       }
+
+       DRM_DEBUG_KMS("enabling PCH PLL %x\n", pll->pll_reg);
+
+       reg = pll->pll_reg;
        val = I915_READ(reg);
        val |= DPLL_VCO_ENABLE;
        I915_WRITE(reg, val);
        POSTING_READ(reg);
        udelay(200);
+
+       pll->on = true;
 }
 
-static void intel_disable_pch_pll(struct drm_i915_private *dev_priv,
-                                 enum pipe pipe)
+static void intel_disable_pch_pll(struct intel_crtc *intel_crtc)
 {
+       struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
+       struct intel_pch_pll *pll = intel_crtc->pch_pll;
        int reg;
-       u32 val, pll_mask = TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL,
-               pll_sel = TRANSC_DPLL_ENABLE;
-
-       if (pipe > 1)
-               return;
+       u32 val;
 
        /* PCH only available on ILK+ */
        BUG_ON(dev_priv->info->gen < 5);
+       if (pll == NULL)
+              return;
 
-       /* Make sure transcoder isn't still depending on us */
-       assert_transcoder_disabled(dev_priv, pipe);
-
-       if (pipe == 0)
-               pll_sel |= TRANSC_DPLLA_SEL;
-       else if (pipe == 1)
-               pll_sel |= TRANSC_DPLLB_SEL;
+       BUG_ON(pll->refcount == 0);
 
+       DRM_DEBUG_KMS("disable PCH PLL %x (active %d, on? %d) for crtc %d\n",
+                     pll->pll_reg, pll->active, pll->on,
+                     intel_crtc->base.base.id);
 
-       if ((I915_READ(PCH_DPLL_SEL) & pll_mask) == pll_sel)
+       BUG_ON(pll->active == 0);
+       if (--pll->active) {
+               assert_pch_pll_enabled(dev_priv, intel_crtc);
                return;
+       }
+
+       DRM_DEBUG_KMS("disabling PCH PLL %x\n", pll->pll_reg);
+
+       /* Make sure transcoder isn't still depending on us */
+       assert_transcoder_disabled(dev_priv, intel_crtc->pipe);
 
-       reg = PCH_DPLL(pipe);
+       reg = pll->pll_reg;
        val = I915_READ(reg);
        val &= ~DPLL_VCO_ENABLE;
        I915_WRITE(reg, val);
        POSTING_READ(reg);
        udelay(200);
+
+       pll->on = false;
 }
 
 static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
@@ -1273,7 +1372,7 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
        BUG_ON(dev_priv->info->gen < 5);
 
        /* Make sure PCH DPLL is enabled */
-       assert_pch_pll_enabled(dev_priv, pipe);
+       assert_pch_pll_enabled(dev_priv, to_intel_crtc(crtc));
 
        /* FDI must be feeding us bits for PCH ports */
        assert_fdi_tx_enabled(dev_priv, pipe);
@@ -1415,7 +1514,7 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
  * Plane regs are double buffered, going from enabled->disabled needs a
  * trigger in order to latch.  The display address reg provides this.
  */
-static void intel_flush_display_plane(struct drm_i915_private *dev_priv,
+void intel_flush_display_plane(struct drm_i915_private *dev_priv,
                                      enum plane plane)
 {
        I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane)));
@@ -1526,490 +1625,6 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
        disable_pch_hdmi(dev_priv, pipe, HDMID);
 }
 
-static void i8xx_disable_fbc(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 fbc_ctl;
-
-       /* Disable compression */
-       fbc_ctl = I915_READ(FBC_CONTROL);
-       if ((fbc_ctl & FBC_CTL_EN) == 0)
-               return;
-
-       fbc_ctl &= ~FBC_CTL_EN;
-       I915_WRITE(FBC_CONTROL, fbc_ctl);
-
-       /* Wait for compressing bit to clear */
-       if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
-               DRM_DEBUG_KMS("FBC idle timed out\n");
-               return;
-       }
-
-       DRM_DEBUG_KMS("disabled FBC\n");
-}
-
-static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *fb = crtc->fb;
-       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-       struct drm_i915_gem_object *obj = intel_fb->obj;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int cfb_pitch;
-       int plane, i;
-       u32 fbc_ctl, fbc_ctl2;
-
-       cfb_pitch = dev_priv->cfb_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;
-       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);
-
-       /* enable it... */
-       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);
-
-       DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ",
-                     cfb_pitch, crtc->y, intel_crtc->plane);
-}
-
-static bool i8xx_fbc_enabled(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
-}
-
-static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *fb = crtc->fb;
-       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-       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... */
-       I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN);
-
-       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
-}
-
-static void g4x_disable_fbc(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 dpfc_ctl;
-
-       /* Disable compression */
-       dpfc_ctl = I915_READ(DPFC_CONTROL);
-       if (dpfc_ctl & DPFC_CTL_EN) {
-               dpfc_ctl &= ~DPFC_CTL_EN;
-               I915_WRITE(DPFC_CONTROL, dpfc_ctl);
-
-               DRM_DEBUG_KMS("disabled FBC\n");
-       }
-}
-
-static bool g4x_fbc_enabled(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
-}
-
-static void sandybridge_blit_fbc_update(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 blt_ecoskpd;
-
-       /* Make sure blitter notifies FBC of writes */
-       gen6_gt_force_wake_get(dev_priv);
-       blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
-       blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
-               GEN6_BLITTER_LOCK_SHIFT;
-       I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
-       blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY;
-       I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
-       blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY <<
-                        GEN6_BLITTER_LOCK_SHIFT);
-       I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
-       POSTING_READ(GEN6_BLITTER_ECOSKPD);
-       gen6_gt_force_wake_put(dev_priv);
-}
-
-static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_framebuffer *fb = crtc->fb;
-       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-       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);
-       dpfc_ctl &= DPFC_RESERVED;
-       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);
-       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, obj->gtt_offset | ILK_FBC_RT_VALID);
-       /* enable it... */
-       I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
-
-       if (IS_GEN6(dev)) {
-               I915_WRITE(SNB_DPFC_CTL_SA,
-                          SNB_CPU_FENCE_ENABLE | obj->fence_reg);
-               I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
-               sandybridge_blit_fbc_update(dev);
-       }
-
-       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
-}
-
-static void ironlake_disable_fbc(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 dpfc_ctl;
-
-       /* Disable compression */
-       dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
-       if (dpfc_ctl & DPFC_CTL_EN) {
-               dpfc_ctl &= ~DPFC_CTL_EN;
-               I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
-
-               DRM_DEBUG_KMS("disabled FBC\n");
-       }
-}
-
-static bool ironlake_fbc_enabled(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
-}
-
-bool intel_fbc_enabled(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (!dev_priv->display.fbc_enabled)
-               return false;
-
-       return dev_priv->display.fbc_enabled(dev);
-}
-
-static void intel_fbc_work_fn(struct work_struct *__work)
-{
-       struct intel_fbc_work *work =
-               container_of(to_delayed_work(__work),
-                            struct intel_fbc_work, work);
-       struct drm_device *dev = work->crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       mutex_lock(&dev->struct_mutex);
-       if (work == dev_priv->fbc_work) {
-               /* Double check that we haven't switched fb without cancelling
-                * the prior work.
-                */
-               if (work->crtc->fb == work->fb) {
-                       dev_priv->display.enable_fbc(work->crtc,
-                                                    work->interval);
-
-                       dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane;
-                       dev_priv->cfb_fb = work->crtc->fb->base.id;
-                       dev_priv->cfb_y = work->crtc->y;
-               }
-
-               dev_priv->fbc_work = NULL;
-       }
-       mutex_unlock(&dev->struct_mutex);
-
-       kfree(work);
-}
-
-static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
-{
-       if (dev_priv->fbc_work == NULL)
-               return;
-
-       DRM_DEBUG_KMS("cancelling pending FBC enable\n");
-
-       /* Synchronisation is provided by struct_mutex and checking of
-        * dev_priv->fbc_work, so we can perform the cancellation
-        * entirely asynchronously.
-        */
-       if (cancel_delayed_work(&dev_priv->fbc_work->work))
-               /* tasklet was killed before being run, clean up */
-               kfree(dev_priv->fbc_work);
-
-       /* Mark the work as no longer wanted so that if it does
-        * wake-up (because the work was already running and waiting
-        * for our mutex), it will discover that is no longer
-        * necessary to run.
-        */
-       dev_priv->fbc_work = NULL;
-}
-
-static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
-{
-       struct intel_fbc_work *work;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (!dev_priv->display.enable_fbc)
-               return;
-
-       intel_cancel_fbc_work(dev_priv);
-
-       work = kzalloc(sizeof *work, GFP_KERNEL);
-       if (work == NULL) {
-               dev_priv->display.enable_fbc(crtc, interval);
-               return;
-       }
-
-       work->crtc = crtc;
-       work->fb = crtc->fb;
-       work->interval = interval;
-       INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
-
-       dev_priv->fbc_work = work;
-
-       DRM_DEBUG_KMS("scheduling delayed FBC enable\n");
-
-       /* Delay the actual enabling to let pageflipping cease and the
-        * display to settle before starting the compression. Note that
-        * this delay also serves a second purpose: it allows for a
-        * vblank to pass after disabling the FBC before we attempt
-        * to modify the control registers.
-        *
-        * A more complicated solution would involve tracking vblanks
-        * following the termination of the page-flipping sequence
-        * and indeed performing the enable as a co-routine and not
-        * waiting synchronously upon the vblank.
-        */
-       schedule_delayed_work(&work->work, msecs_to_jiffies(50));
-}
-
-void intel_disable_fbc(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       intel_cancel_fbc_work(dev_priv);
-
-       if (!dev_priv->display.disable_fbc)
-               return;
-
-       dev_priv->display.disable_fbc(dev);
-       dev_priv->cfb_plane = -1;
-}
-
-/**
- * intel_update_fbc - enable/disable FBC as needed
- * @dev: the drm_device
- *
- * Set up the framebuffer compression hardware at mode set time.  We
- * enable it if possible:
- *   - plane A only (on pre-965)
- *   - no pixel mulitply/line duplication
- *   - no alpha buffer discard
- *   - no dual wide
- *   - framebuffer <= 2048 in width, 1536 in height
- *
- * We can't assume that any compression will take place (worst case),
- * so the compressed buffer has to be the same size as the uncompressed
- * one.  It also must reside (along with the line length buffer) in
- * stolen memory.
- *
- * We need to enable/disable FBC on a global basis.
- */
-static void intel_update_fbc(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = NULL, *tmp_crtc;
-       struct intel_crtc *intel_crtc;
-       struct drm_framebuffer *fb;
-       struct intel_framebuffer *intel_fb;
-       struct drm_i915_gem_object *obj;
-       int enable_fbc;
-
-       DRM_DEBUG_KMS("\n");
-
-       if (!i915_powersave)
-               return;
-
-       if (!I915_HAS_FBC(dev))
-               return;
-
-       /*
-        * If FBC is already on, we just have to verify that we can
-        * keep it that way...
-        * Need to disable if:
-        *   - more than one pipe is active
-        *   - changing FBC params (stride, fence, mode)
-        *   - new fb is too large to fit in compressed buffer
-        *   - going to an unsupported config (interlace, pixel multiply, etc.)
-        */
-       list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
-               if (tmp_crtc->enabled && tmp_crtc->fb) {
-                       if (crtc) {
-                               DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
-                               dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
-                               goto out_disable;
-                       }
-                       crtc = tmp_crtc;
-               }
-       }
-
-       if (!crtc || crtc->fb == NULL) {
-               DRM_DEBUG_KMS("no output, disabling\n");
-               dev_priv->no_fbc_reason = FBC_NO_OUTPUT;
-               goto out_disable;
-       }
-
-       intel_crtc = to_intel_crtc(crtc);
-       fb = crtc->fb;
-       intel_fb = to_intel_framebuffer(fb);
-       obj = intel_fb->obj;
-
-       enable_fbc = i915_enable_fbc;
-       if (enable_fbc < 0) {
-               DRM_DEBUG_KMS("fbc set to per-chip default\n");
-               enable_fbc = 1;
-               if (INTEL_INFO(dev)->gen <= 6)
-                       enable_fbc = 0;
-       }
-       if (!enable_fbc) {
-               DRM_DEBUG_KMS("fbc disabled per module param\n");
-               dev_priv->no_fbc_reason = FBC_MODULE_PARAM;
-               goto out_disable;
-       }
-       if (intel_fb->obj->base.size > dev_priv->cfb_size) {
-               DRM_DEBUG_KMS("framebuffer too large, disabling "
-                             "compression\n");
-               dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
-               goto out_disable;
-       }
-       if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) ||
-           (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) {
-               DRM_DEBUG_KMS("mode incompatible with compression, "
-                             "disabling\n");
-               dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
-               goto out_disable;
-       }
-       if ((crtc->mode.hdisplay > 2048) ||
-           (crtc->mode.vdisplay > 1536)) {
-               DRM_DEBUG_KMS("mode too large for compression, disabling\n");
-               dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
-               goto out_disable;
-       }
-       if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) {
-               DRM_DEBUG_KMS("plane not 0, disabling compression\n");
-               dev_priv->no_fbc_reason = FBC_BAD_PLANE;
-               goto out_disable;
-       }
-
-       /* The use of a CPU fence is mandatory in order to detect writes
-        * by the CPU to the scanout and trigger updates to the FBC.
-        */
-       if (obj->tiling_mode != I915_TILING_X ||
-           obj->fence_reg == I915_FENCE_REG_NONE) {
-               DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n");
-               dev_priv->no_fbc_reason = FBC_NOT_TILED;
-               goto out_disable;
-       }
-
-       /* If the kernel debugger is active, always disable compression */
-       if (in_dbg_master())
-               goto out_disable;
-
-       /* If the scanout has not changed, don't modify the FBC settings.
-        * Note that we make the fundamental assumption that the fb->obj
-        * cannot be unpinned (and have its GTT offset and fence revoked)
-        * without first being decoupled from the scanout and FBC disabled.
-        */
-       if (dev_priv->cfb_plane == intel_crtc->plane &&
-           dev_priv->cfb_fb == fb->base.id &&
-           dev_priv->cfb_y == crtc->y)
-               return;
-
-       if (intel_fbc_enabled(dev)) {
-               /* We update FBC along two paths, after changing fb/crtc
-                * configuration (modeswitching) and after page-flipping
-                * finishes. For the latter, we know that not only did
-                * we disable the FBC at the start of the page-flip
-                * sequence, but also more than one vblank has passed.
-                *
-                * For the former case of modeswitching, it is possible
-                * to switch between two FBC valid configurations
-                * instantaneously so we do need to disable the FBC
-                * before we can modify its control registers. We also
-                * have to wait for the next vblank for that to take
-                * effect. However, since we delay enabling FBC we can
-                * assume that a vblank has passed since disabling and
-                * that we can safely alter the registers in the deferred
-                * callback.
-                *
-                * In the scenario that we go from a valid to invalid
-                * and then back to valid FBC configuration we have
-                * no strict enforcement that a vblank occurred since
-                * disabling the FBC. However, along all current pipe
-                * disabling paths we do need to wait for a vblank at
-                * some point. And we wait before enabling FBC anyway.
-                */
-               DRM_DEBUG_KMS("disabling active FBC for update\n");
-               intel_disable_fbc(dev);
-       }
-
-       intel_enable_fbc(crtc, 500);
-       return;
-
-out_disable:
-       /* Multiple disables should be harmless */
-       if (intel_fbc_enabled(dev)) {
-               DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
-               intel_disable_fbc(dev);
-       }
-}
-
 int
 intel_pin_and_fence_fb_obj(struct drm_device *dev,
                           struct drm_i915_gem_object *obj,
@@ -2050,13 +1665,11 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
         * framebuffer compression.  For simplicity, we always install
         * a fence as the cost is not that onerous.
         */
-       if (obj->tiling_mode != I915_TILING_NONE) {
-               ret = i915_gem_object_get_fence(obj, pipelined);
-               if (ret)
-                       goto err_unpin;
+       ret = i915_gem_object_get_fence(obj);
+       if (ret)
+               goto err_unpin;
 
-               i915_gem_object_pin_fence(obj);
-       }
+       i915_gem_object_pin_fence(obj);
 
        dev_priv->mm.interruptible = true;
        return 0;
@@ -2137,7 +1750,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                      Start, Offset, x, y, fb->pitches[0]);
        I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
        if (INTEL_INFO(dev)->gen >= 4) {
-               I915_WRITE(DSPSURF(plane), Start);
+               I915_MODIFY_DISPBASE(DSPSURF(plane), Start);
                I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
                I915_WRITE(DSPADDR(plane), Offset);
        } else
@@ -2217,7 +1830,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc,
        DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
                      Start, Offset, x, y, fb->pitches[0]);
        I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
-       I915_WRITE(DSPSURF(plane), Start);
+       I915_MODIFY_DISPBASE(DSPSURF(plane), Start);
        I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
        I915_WRITE(DSPADDR(plane), Offset);
        POSTING_READ(reg);
@@ -2232,23 +1845,47 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int ret;
-
-       ret = dev_priv->display.update_plane(crtc, fb, x, y);
-       if (ret)
-               return ret;
 
-       intel_update_fbc(dev);
+       if (dev_priv->display.disable_fbc)
+               dev_priv->display.disable_fbc(dev);
        intel_increase_pllclock(crtc);
 
-       return 0;
+       return dev_priv->display.update_plane(crtc, fb, x, y);
 }
 
 static int
-intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
+intel_finish_fb(struct drm_framebuffer *old_fb)
+{
+       struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
+       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+       bool was_interruptible = dev_priv->mm.interruptible;
+       int ret;
+
+       wait_event(dev_priv->pending_flip_queue,
+                  atomic_read(&dev_priv->mm.wedged) ||
+                  atomic_read(&obj->pending_flip) == 0);
+
+       /* Big Hammer, we also need to ensure that any pending
+        * MI_WAIT_FOR_EVENT inside a user batch buffer on the
+        * current scanout is retired before unpinning the old
+        * framebuffer.
+        *
+        * This should only fail upon a hung GPU, in which case we
+        * can safely continue.
+        */
+       dev_priv->mm.interruptible = false;
+       ret = i915_gem_object_finish_gpu(obj);
+       dev_priv->mm.interruptible = was_interruptible;
+
+       return ret;
+}
+
+static int
+intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                    struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int ret;
@@ -2282,28 +1919,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                return ret;
        }
 
-       if (old_fb) {
-               struct drm_i915_private *dev_priv = dev->dev_private;
-               struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
-
-               wait_event(dev_priv->pending_flip_queue,
-                          atomic_read(&dev_priv->mm.wedged) ||
-                          atomic_read(&obj->pending_flip) == 0);
-
-               /* Big Hammer, we also need to ensure that any pending
-                * MI_WAIT_FOR_EVENT inside a user batch buffer on the
-                * current scanout is retired before unpinning the old
-                * framebuffer.
-                *
-                * This should only fail upon a hung GPU, in which case we
-                * can safely continue.
-                */
-               ret = i915_gem_object_finish_gpu(obj);
-               (void) ret;
-       }
+       if (old_fb)
+               intel_finish_fb(old_fb);
 
-       ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
-                                        LEAVE_ATOMIC_MODE_SET);
+       ret = dev_priv->display.update_plane(crtc, crtc->fb, x, y);
        if (ret) {
                intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
                mutex_unlock(&dev->struct_mutex);
@@ -2316,6 +1935,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
        }
 
+       intel_update_fbc(dev);
        mutex_unlock(&dev->struct_mutex);
 
        if (!dev->primary->master)
@@ -2537,7 +2157,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp, i;
+       u32 reg, temp, i, retry;
 
        /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
           for train result */
@@ -2589,15 +2209,19 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
                POSTING_READ(reg);
                udelay(500);
 
-               reg = FDI_RX_IIR(pipe);
-               temp = I915_READ(reg);
-               DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
-
-               if (temp & FDI_RX_BIT_LOCK) {
-                       I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
-                       DRM_DEBUG_KMS("FDI train 1 done.\n");
-                       break;
+               for (retry = 0; retry < 5; retry++) {
+                       reg = FDI_RX_IIR(pipe);
+                       temp = I915_READ(reg);
+                       DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
+                       if (temp & FDI_RX_BIT_LOCK) {
+                               I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
+                               DRM_DEBUG_KMS("FDI train 1 done.\n");
+                               break;
+                       }
+                       udelay(50);
                }
+               if (retry < 5)
+                       break;
        }
        if (i == 4)
                DRM_ERROR("FDI train 1 fail!\n");
@@ -2638,15 +2262,19 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
                POSTING_READ(reg);
                udelay(500);
 
-               reg = FDI_RX_IIR(pipe);
-               temp = I915_READ(reg);
-               DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
-
-               if (temp & FDI_RX_SYMBOL_LOCK) {
-                       I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
-                       DRM_DEBUG_KMS("FDI train 2 done.\n");
-                       break;
+               for (retry = 0; retry < 5; retry++) {
+                       reg = FDI_RX_IIR(pipe);
+                       temp = I915_READ(reg);
+                       DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
+                       if (temp & FDI_RX_SYMBOL_LOCK) {
+                               I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
+                               DRM_DEBUG_KMS("FDI train 2 done.\n");
+                               break;
+                       }
+                       udelay(50);
                }
+               if (retry < 5)
+                       break;
        }
        if (i == 4)
                DRM_ERROR("FDI train 2 fail!\n");
@@ -2878,38 +2506,16 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
        udelay(100);
 }
 
-/*
- * When we disable a pipe, we need to clear any pending scanline wait events
- * to avoid hanging the ring, which we assume we are waiting on.
- */
-static void intel_clear_scanline_wait(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_ring_buffer *ring;
-       u32 tmp;
-
-       if (IS_GEN2(dev))
-               /* Can't break the hang on i8xx */
-               return;
-
-       ring = LP_RING(dev_priv);
-       tmp = I915_READ_CTL(ring);
-       if (tmp & RING_WAIT)
-               I915_WRITE_CTL(ring, tmp);
-}
-
 static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 {
-       struct drm_i915_gem_object *obj;
-       struct drm_i915_private *dev_priv;
+       struct drm_device *dev = crtc->dev;
 
        if (crtc->fb == NULL)
                return;
 
-       obj = to_intel_framebuffer(crtc->fb)->obj;
-       dev_priv = crtc->dev->dev_private;
-       wait_event(dev_priv->pending_flip_queue,
-                  atomic_read(&obj->pending_flip) == 0);
+       mutex_lock(&dev->struct_mutex);
+       intel_finish_fb(crtc->fb);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
@@ -2951,29 +2557,36 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp, transc_sel;
+       u32 reg, temp;
 
        /* For PCH output, training FDI link */
        dev_priv->display.fdi_link_train(crtc);
 
-       intel_enable_pch_pll(dev_priv, pipe);
+       intel_enable_pch_pll(intel_crtc);
 
        if (HAS_PCH_CPT(dev)) {
-               transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL :
-                       TRANSC_DPLLB_SEL;
+               u32 sel;
 
-               /* Be sure PCH DPLL SEL is set */
                temp = I915_READ(PCH_DPLL_SEL);
-               if (pipe == 0) {
-                       temp &= ~(TRANSA_DPLLB_SEL);
-                       temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
-               } else if (pipe == 1) {
-                       temp &= ~(TRANSB_DPLLB_SEL);
-                       temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
-               } else if (pipe == 2) {
-                       temp &= ~(TRANSC_DPLLB_SEL);
-                       temp |= (TRANSC_DPLL_ENABLE | transc_sel);
+               switch (pipe) {
+               default:
+               case 0:
+                       temp |= TRANSA_DPLL_ENABLE;
+                       sel = TRANSA_DPLLB_SEL;
+                       break;
+               case 1:
+                       temp |= TRANSB_DPLL_ENABLE;
+                       sel = TRANSB_DPLLB_SEL;
+                       break;
+               case 2:
+                       temp |= TRANSC_DPLL_ENABLE;
+                       sel = TRANSC_DPLLB_SEL;
+                       break;
                }
+               if (intel_crtc->pch_pll->pll_reg == _PCH_DPLL_B)
+                       temp |= sel;
+               else
+                       temp &= ~sel;
                I915_WRITE(PCH_DPLL_SEL, temp);
        }
 
@@ -3031,6 +2644,82 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        intel_enable_transcoder(dev_priv, pipe);
 }
 
+static void intel_put_pch_pll(struct intel_crtc *intel_crtc)
+{
+       struct intel_pch_pll *pll = intel_crtc->pch_pll;
+
+       if (pll == NULL)
+               return;
+
+       if (pll->refcount == 0) {
+               WARN(1, "bad PCH PLL refcount\n");
+               return;
+       }
+
+       --pll->refcount;
+       intel_crtc->pch_pll = NULL;
+}
+
+static struct intel_pch_pll *intel_get_pch_pll(struct intel_crtc *intel_crtc, u32 dpll, u32 fp)
+{
+       struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
+       struct intel_pch_pll *pll;
+       int i;
+
+       pll = intel_crtc->pch_pll;
+       if (pll) {
+               DRM_DEBUG_KMS("CRTC:%d reusing existing PCH PLL %x\n",
+                             intel_crtc->base.base.id, pll->pll_reg);
+               goto prepare;
+       }
+
+       for (i = 0; i < dev_priv->num_pch_pll; i++) {
+               pll = &dev_priv->pch_plls[i];
+
+               /* Only want to check enabled timings first */
+               if (pll->refcount == 0)
+                       continue;
+
+               if (dpll == (I915_READ(pll->pll_reg) & 0x7fffffff) &&
+                   fp == I915_READ(pll->fp0_reg)) {
+                       DRM_DEBUG_KMS("CRTC:%d sharing existing PCH PLL %x (refcount %d, ative %d)\n",
+                                     intel_crtc->base.base.id,
+                                     pll->pll_reg, pll->refcount, pll->active);
+
+                       goto found;
+               }
+       }
+
+       /* Ok no matching timings, maybe there's a free one? */
+       for (i = 0; i < dev_priv->num_pch_pll; i++) {
+               pll = &dev_priv->pch_plls[i];
+               if (pll->refcount == 0) {
+                       DRM_DEBUG_KMS("CRTC:%d allocated PCH PLL %x\n",
+                                     intel_crtc->base.base.id, pll->pll_reg);
+                       goto found;
+               }
+       }
+
+       return NULL;
+
+found:
+       intel_crtc->pch_pll = pll;
+       pll->refcount++;
+       DRM_DEBUG_DRIVER("using pll %d for pipe %d\n", i, intel_crtc->pipe);
+prepare: /* separate function? */
+       DRM_DEBUG_DRIVER("switching PLL %x off\n", pll->pll_reg);
+
+       /* Wait for the clocks to stabilize before rewriting the regs */
+       I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
+       POSTING_READ(pll->pll_reg);
+       udelay(150);
+
+       I915_WRITE(pll->fp0_reg, fp);
+       I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE);
+       pll->on = false;
+       return pll;
+}
+
 void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3175,8 +2864,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
        }
 
        /* disable PCH DPLL */
-       if (!intel_crtc->no_pll)
-               intel_disable_pch_pll(dev_priv, pipe);
+       intel_disable_pch_pll(intel_crtc);
 
        /* Switch from PCDclk to Rawclk */
        reg = FDI_RX_CTL(pipe);
@@ -3204,7 +2892,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
        mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
-       intel_clear_scanline_wait(dev);
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -3232,6 +2919,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
        }
 }
 
+static void ironlake_crtc_off(struct drm_crtc *crtc)
+{
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       intel_put_pch_pll(intel_crtc);
+}
+
 static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
 {
        if (!enable && intel_crtc->overlay) {
@@ -3303,7 +2996,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
        intel_crtc->active = false;
        intel_update_fbc(dev);
        intel_update_watermarks(dev);
-       intel_clear_scanline_wait(dev);
 }
 
 static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
@@ -3323,6 +3015,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
        }
 }
 
+static void i9xx_crtc_off(struct drm_crtc *crtc)
+{
+}
+
 /**
  * Sets the power management mode of the pipe and plane.
  */
@@ -3370,8 +3066,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
 {
        struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
        struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
        crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+       dev_priv->display.off(crtc);
+
        assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
        assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
 
@@ -3451,12 +3150,20 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
                        return false;
        }
 
-       /* All interlaced capable intel hw wants timings in frames. */
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
+       /* All interlaced capable intel hw wants timings in frames. Note though
+        * that intel_lvds_mode_fixup does some funny tricks with the crtc
+        * timings, so we need to be careful not to clobber these.*/
+       if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET))
+               drm_mode_set_crtcinfo(adjusted_mode, 0);
 
        return true;
 }
 
+static int valleyview_get_display_clock_speed(struct drm_device *dev)
+{
+       return 400000; /* FIXME */
+}
+
 static int i945_get_display_clock_speed(struct drm_device *dev)
 {
        return 400000;
@@ -3554,1780 +3261,1087 @@ ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
        fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
 }
 
-
-struct intel_watermark_params {
-       unsigned long fifo_size;
-       unsigned long max_wm;
-       unsigned long default_wm;
-       unsigned long guard_size;
-       unsigned long cacheline_size;
-};
-
-/* Pineview has different values for various configs */
-static const struct intel_watermark_params pineview_display_wm = {
-       PINEVIEW_DISPLAY_FIFO,
-       PINEVIEW_MAX_WM,
-       PINEVIEW_DFT_WM,
-       PINEVIEW_GUARD_WM,
-       PINEVIEW_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params pineview_display_hplloff_wm = {
-       PINEVIEW_DISPLAY_FIFO,
-       PINEVIEW_MAX_WM,
-       PINEVIEW_DFT_HPLLOFF_WM,
-       PINEVIEW_GUARD_WM,
-       PINEVIEW_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params pineview_cursor_wm = {
-       PINEVIEW_CURSOR_FIFO,
-       PINEVIEW_CURSOR_MAX_WM,
-       PINEVIEW_CURSOR_DFT_WM,
-       PINEVIEW_CURSOR_GUARD_WM,
-       PINEVIEW_FIFO_LINE_SIZE,
-};
-static const struct intel_watermark_params pineview_cursor_hplloff_wm = {
-       PINEVIEW_CURSOR_FIFO,
-       PINEVIEW_CURSOR_MAX_WM,
-       PINEVIEW_CURSOR_DFT_WM,
-       PINEVIEW_CURSOR_GUARD_WM,
-       PINEVIEW_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params g4x_wm_info = {
-       G4X_FIFO_SIZE,
-       G4X_MAX_WM,
-       G4X_MAX_WM,
-       2,
-       G4X_FIFO_LINE_SIZE,
-};
-static const struct intel_watermark_params g4x_cursor_wm_info = {
-       I965_CURSOR_FIFO,
-       I965_CURSOR_MAX_WM,
-       I965_CURSOR_DFT_WM,
-       2,
-       G4X_FIFO_LINE_SIZE,
-};
-static const struct intel_watermark_params i965_cursor_wm_info = {
-       I965_CURSOR_FIFO,
-       I965_CURSOR_MAX_WM,
-       I965_CURSOR_DFT_WM,
-       2,
-       I915_FIFO_LINE_SIZE,
-};
-static const struct intel_watermark_params i945_wm_info = {
-       I945_FIFO_SIZE,
-       I915_MAX_WM,
-       1,
-       2,
-       I915_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params i915_wm_info = {
-       I915_FIFO_SIZE,
-       I915_MAX_WM,
-       1,
-       2,
-       I915_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params i855_wm_info = {
-       I855GM_FIFO_SIZE,
-       I915_MAX_WM,
-       1,
-       2,
-       I830_FIFO_LINE_SIZE
-};
-static const struct intel_watermark_params i830_wm_info = {
-       I830_FIFO_SIZE,
-       I915_MAX_WM,
-       1,
-       2,
-       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
-};
-
+static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
+{
+       if (i915_panel_use_ssc >= 0)
+               return i915_panel_use_ssc != 0;
+       return dev_priv->lvds_use_ssc
+               && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
+}
 
 /**
- * intel_calculate_wm - calculate watermark level
- * @clock_in_khz: pixel clock
- * @wm: chip FIFO params
- * @pixel_size: display pixel size
- * @latency_ns: memory latency for the platform
+ * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
+ * @crtc: CRTC structure
+ * @mode: requested mode
+ *
+ * A pipe may be connected to one or more outputs.  Based on the depth of the
+ * attached framebuffer, choose a good color depth to use on the pipe.
  *
- * Calculate the watermark level (the level at which the display plane will
- * start fetching from memory again).  Each chip has a different display
- * FIFO size and allocation, so the caller needs to figure that out and pass
- * in the correct intel_watermark_params structure.
+ * If possible, match the pipe depth to the fb depth.  In some cases, this
+ * isn't ideal, because the connected output supports a lesser or restricted
+ * set of depths.  Resolve that here:
+ *    LVDS typically supports only 6bpc, so clamp down in that case
+ *    HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
+ *    Displays may support a restricted set as well, check EDID and clamp as
+ *      appropriate.
+ *    DP may want to dither down to 6bpc to fit larger modes
  *
- * As the pixel clock runs, the FIFO will be drained at a rate that depends
- * on the pixel size.  When it reaches the watermark level, it'll start
- * fetching FIFO line sized based chunks from memory until the FIFO fills
- * past the watermark point.  If the FIFO drains completely, a FIFO underrun
- * will occur, and a display engine hang could result.
+ * RETURNS:
+ * Dithering requirement (i.e. false if display bpc and pipe bpc match,
+ * true if they don't match).
  */
-static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
-                                       const struct intel_watermark_params *wm,
-                                       int fifo_size,
-                                       int pixel_size,
-                                       unsigned long latency_ns)
+static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
+                                        unsigned int *pipe_bpp,
+                                        struct drm_display_mode *mode)
 {
-       long entries_required, wm_size;
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_encoder *encoder;
+       struct drm_connector *connector;
+       unsigned int display_bpc = UINT_MAX, bpc;
 
-       /*
-        * Note: we need to make sure we don't overflow for various clock &
-        * latency values.
-        * clocks go from a few thousand to several hundred thousand.
-        * latency is usually a few thousand
-        */
-       entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) /
-               1000;
-       entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size);
+       /* Walk the encoders & connectors on this crtc, get min bpc */
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
 
-       DRM_DEBUG_KMS("FIFO entries required for mode: %ld\n", entries_required);
+               if (encoder->crtc != crtc)
+                       continue;
 
-       wm_size = fifo_size - (entries_required + wm->guard_size);
+               if (intel_encoder->type == INTEL_OUTPUT_LVDS) {
+                       unsigned int lvds_bpc;
 
-       DRM_DEBUG_KMS("FIFO watermark level: %ld\n", wm_size);
+                       if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) ==
+                           LVDS_A3_POWER_UP)
+                               lvds_bpc = 8;
+                       else
+                               lvds_bpc = 6;
 
-       /* Don't promote wm_size to unsigned... */
-       if (wm_size > (long)wm->max_wm)
-               wm_size = wm->max_wm;
-       if (wm_size <= 0)
-               wm_size = wm->default_wm;
-       return wm_size;
-}
+                       if (lvds_bpc < display_bpc) {
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+                               display_bpc = lvds_bpc;
+                       }
+                       continue;
+               }
 
-struct cxsr_latency {
-       int is_desktop;
-       int is_ddr3;
-       unsigned long fsb_freq;
-       unsigned long mem_freq;
-       unsigned long display_sr;
-       unsigned long display_hpll_disable;
-       unsigned long cursor_sr;
-       unsigned long cursor_hpll_disable;
-};
+               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+                       /* Use VBT settings if we have an eDP panel */
+                       unsigned int edp_bpc = dev_priv->edp.bpp / 3;
 
-static const struct cxsr_latency cxsr_latency_table[] = {
-       {1, 0, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
-       {1, 0, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
-       {1, 0, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
-       {1, 1, 800, 667, 6420, 36420, 6873, 36873},    /* DDR3-667 SC */
-       {1, 1, 800, 800, 5902, 35902, 6318, 36318},    /* DDR3-800 SC */
-
-       {1, 0, 667, 400, 3400, 33400, 4021, 34021},    /* DDR2-400 SC */
-       {1, 0, 667, 667, 3372, 33372, 3845, 33845},    /* DDR2-667 SC */
-       {1, 0, 667, 800, 3386, 33386, 3822, 33822},    /* DDR2-800 SC */
-       {1, 1, 667, 667, 6438, 36438, 6911, 36911},    /* DDR3-667 SC */
-       {1, 1, 667, 800, 5941, 35941, 6377, 36377},    /* DDR3-800 SC */
-
-       {1, 0, 400, 400, 3472, 33472, 4173, 34173},    /* DDR2-400 SC */
-       {1, 0, 400, 667, 3443, 33443, 3996, 33996},    /* DDR2-667 SC */
-       {1, 0, 400, 800, 3430, 33430, 3946, 33946},    /* DDR2-800 SC */
-       {1, 1, 400, 667, 6509, 36509, 7062, 37062},    /* DDR3-667 SC */
-       {1, 1, 400, 800, 5985, 35985, 6501, 36501},    /* DDR3-800 SC */
-
-       {0, 0, 800, 400, 3438, 33438, 4065, 34065},    /* DDR2-400 SC */
-       {0, 0, 800, 667, 3410, 33410, 3889, 33889},    /* DDR2-667 SC */
-       {0, 0, 800, 800, 3403, 33403, 3845, 33845},    /* DDR2-800 SC */
-       {0, 1, 800, 667, 6476, 36476, 6955, 36955},    /* DDR3-667 SC */
-       {0, 1, 800, 800, 5958, 35958, 6400, 36400},    /* DDR3-800 SC */
-
-       {0, 0, 667, 400, 3456, 33456, 4103, 34106},    /* DDR2-400 SC */
-       {0, 0, 667, 667, 3428, 33428, 3927, 33927},    /* DDR2-667 SC */
-       {0, 0, 667, 800, 3443, 33443, 3905, 33905},    /* DDR2-800 SC */
-       {0, 1, 667, 667, 6494, 36494, 6993, 36993},    /* DDR3-667 SC */
-       {0, 1, 667, 800, 5998, 35998, 6460, 36460},    /* DDR3-800 SC */
-
-       {0, 0, 400, 400, 3528, 33528, 4255, 34255},    /* DDR2-400 SC */
-       {0, 0, 400, 667, 3500, 33500, 4079, 34079},    /* DDR2-667 SC */
-       {0, 0, 400, 800, 3487, 33487, 4029, 34029},    /* DDR2-800 SC */
-       {0, 1, 400, 667, 6566, 36566, 7145, 37145},    /* DDR3-667 SC */
-       {0, 1, 400, 800, 6042, 36042, 6584, 36584},    /* DDR3-800 SC */
-};
+                       if (edp_bpc < display_bpc) {
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               display_bpc = edp_bpc;
+                       }
+                       continue;
+               }
 
-static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop,
-                                                        int is_ddr3,
-                                                        int fsb,
-                                                        int mem)
-{
-       const struct cxsr_latency *latency;
-       int i;
+               /* Not one of the known troublemakers, check the EDID */
+               list_for_each_entry(connector, &dev->mode_config.connector_list,
+                                   head) {
+                       if (connector->encoder != encoder)
+                               continue;
 
-       if (fsb == 0 || mem == 0)
-               return NULL;
+                       /* Don't use an invalid EDID bpc value */
+                       if (connector->display_info.bpc &&
+                           connector->display_info.bpc < display_bpc) {
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+                               display_bpc = connector->display_info.bpc;
+                       }
+               }
 
-       for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
-               latency = &cxsr_latency_table[i];
-               if (is_desktop == latency->is_desktop &&
-                   is_ddr3 == latency->is_ddr3 &&
-                   fsb == latency->fsb_freq && mem == latency->mem_freq)
-                       return latency;
+               /*
+                * HDMI is either 12 or 8, so if the display lets 10bpc sneak
+                * through, clamp it down.  (Note: >12bpc will be caught below.)
+                */
+               if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+                       if (display_bpc > 8 && display_bpc < 12) {
+                               DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
+                               display_bpc = 12;
+                       } else {
+                               DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
+                               display_bpc = 8;
+                       }
+               }
        }
 
-       DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
-
-       return NULL;
-}
-
-static void pineview_disable_cxsr(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       /* deactivate cxsr */
-       I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN);
-}
-
-/*
- * Latency for FIFO fetches is dependent on several factors:
- *   - memory configuration (speed, channels)
- *   - chipset
- *   - current MCH state
- * It can be fairly high in some situations, so here we assume a fairly
- * pessimal value.  It's a tradeoff between extra memory fetches (if we
- * set this value too high, the FIFO will fetch frequently to stay full)
- * and power consumption (set it too low to save power and we might see
- * FIFO underruns and display "flicker").
- *
- * A value of 5us seems to be a good balance; safe for very low end
- * platforms but not overly aggressive on lower latency configs.
- */
-static const int latency_ns = 5000;
+       if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+               DRM_DEBUG_KMS("Dithering DP to 6bpc\n");
+               display_bpc = 6;
+       }
 
-static int i9xx_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;
+       /*
+        * We could just drive the pipe at the highest bpc all the time and
+        * enable dithering as needed, but that costs bandwidth.  So choose
+        * the minimum value that expresses the full color range of the fb but
+        * also stays within the max display bpc discovered above.
+        */
 
-       size = dsparb & 0x7f;
-       if (plane)
-               size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size;
-
-       DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
-                     plane ? "B" : "A", size);
-
-       return size;
-}
+       switch (crtc->fb->depth) {
+       case 8:
+               bpc = 8; /* since we go through a colormap */
+               break;
+       case 15:
+       case 16:
+               bpc = 6; /* min is 18bpp */
+               break;
+       case 24:
+               bpc = 8;
+               break;
+       case 30:
+               bpc = 10;
+               break;
+       case 48:
+               bpc = 12;
+               break;
+       default:
+               DRM_DEBUG("unsupported depth, assuming 24 bits\n");
+               bpc = min((unsigned int)8, display_bpc);
+               break;
+       }
 
-static int i85x_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;
+       display_bpc = min(display_bpc, bpc);
 
-       size = dsparb & 0x1ff;
-       if (plane)
-               size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) - size;
-       size >>= 1; /* Convert to cachelines */
+       DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
+                     bpc, display_bpc);
 
-       DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
-                     plane ? "B" : "A", size);
+       *pipe_bpp = display_bpc * 3;
 
-       return size;
+       return display_bpc != bpc;
 }
 
-static int i845_get_fifo_size(struct drm_device *dev, int plane)
+static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
 {
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t dsparb = I915_READ(DSPARB);
-       int size;
-
-       size = dsparb & 0x7f;
-       size >>= 2; /* Convert to cachelines */
+       int refclk;
 
-       DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
-                     plane ? "B" : "A",
-                     size);
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+           intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
+               refclk = dev_priv->lvds_ssc_freq * 1000;
+               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+                             refclk / 1000);
+       } else if (!IS_GEN2(dev)) {
+               refclk = 96000;
+       } else {
+               refclk = 48000;
+       }
 
-       return size;
+       return refclk;
 }
 
-static int i830_get_fifo_size(struct drm_device *dev, int plane)
+static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode,
+                                     intel_clock_t *clock)
 {
-       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;
+       /* SDVO TV has fixed PLL values depend on its clock range,
+          this mirrors vbios setting. */
+       if (adjusted_mode->clock >= 100000
+           && adjusted_mode->clock < 140500) {
+               clock->p1 = 2;
+               clock->p2 = 10;
+               clock->n = 3;
+               clock->m1 = 16;
+               clock->m2 = 8;
+       } else if (adjusted_mode->clock >= 140500
+                  && adjusted_mode->clock <= 200000) {
+               clock->p1 = 1;
+               clock->p2 = 10;
+               clock->n = 6;
+               clock->m1 = 12;
+               clock->m2 = 8;
+       }
 }
 
-static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
+static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
+                                    intel_clock_t *clock,
+                                    intel_clock_t *reduced_clock)
 {
-       struct drm_crtc *crtc, *enabled = NULL;
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       u32 fp, fp2 = 0;
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (crtc->enabled && crtc->fb) {
-                       if (enabled)
-                               return NULL;
-                       enabled = crtc;
-               }
+       if (IS_PINEVIEW(dev)) {
+               fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2;
+               if (reduced_clock)
+                       fp2 = (1 << reduced_clock->n) << 16 |
+                               reduced_clock->m1 << 8 | reduced_clock->m2;
+       } else {
+               fp = clock->n << 16 | clock->m1 << 8 | clock->m2;
+               if (reduced_clock)
+                       fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 |
+                               reduced_clock->m2;
        }
 
-       return enabled;
+       I915_WRITE(FP0(pipe), fp);
+
+       intel_crtc->lowfreq_avail = false;
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+           reduced_clock && i915_powersave) {
+               I915_WRITE(FP1(pipe), fp2);
+               intel_crtc->lowfreq_avail = true;
+       } else {
+               I915_WRITE(FP1(pipe), fp);
+       }
 }
 
-static void pineview_update_wm(struct drm_device *dev)
+static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock,
+                             struct drm_display_mode *adjusted_mode)
 {
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc;
-       const struct cxsr_latency *latency;
-       u32 reg;
-       unsigned long wm;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       u32 temp;
 
-       latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
-                                        dev_priv->fsb_freq, dev_priv->mem_freq);
-       if (!latency) {
-               DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
-               pineview_disable_cxsr(dev);
-               return;
+       temp = I915_READ(LVDS);
+       temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+       if (pipe == 1) {
+               temp |= LVDS_PIPEB_SELECT;
+       } else {
+               temp &= ~LVDS_PIPEB_SELECT;
        }
+       /* set the corresponsding LVDS_BORDER bit */
+       temp |= dev_priv->lvds_border_bits;
+       /* Set the B0-B3 data pairs corresponding to whether we're going to
+        * set the DPLLs for dual-channel mode or not.
+        */
+       if (clock->p2 == 7)
+               temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+       else
+               temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
 
-       crtc = single_enabled_crtc(dev);
-       if (crtc) {
-               int clock = crtc->mode.clock;
-               int pixel_size = crtc->fb->bits_per_pixel / 8;
-
-               /* Display SR */
-               wm = intel_calculate_wm(clock, &pineview_display_wm,
-                                       pineview_display_wm.fifo_size,
-                                       pixel_size, latency->display_sr);
-               reg = I915_READ(DSPFW1);
-               reg &= ~DSPFW_SR_MASK;
-               reg |= wm << DSPFW_SR_SHIFT;
-               I915_WRITE(DSPFW1, reg);
-               DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg);
-
-               /* cursor SR */
-               wm = intel_calculate_wm(clock, &pineview_cursor_wm,
-                                       pineview_display_wm.fifo_size,
-                                       pixel_size, latency->cursor_sr);
-               reg = I915_READ(DSPFW3);
-               reg &= ~DSPFW_CURSOR_SR_MASK;
-               reg |= (wm & 0x3f) << DSPFW_CURSOR_SR_SHIFT;
-               I915_WRITE(DSPFW3, reg);
-
-               /* Display HPLL off SR */
-               wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm,
-                                       pineview_display_hplloff_wm.fifo_size,
-                                       pixel_size, latency->display_hpll_disable);
-               reg = I915_READ(DSPFW3);
-               reg &= ~DSPFW_HPLL_SR_MASK;
-               reg |= wm & DSPFW_HPLL_SR_MASK;
-               I915_WRITE(DSPFW3, reg);
-
-               /* cursor HPLL off SR */
-               wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm,
-                                       pineview_display_hplloff_wm.fifo_size,
-                                       pixel_size, latency->cursor_hpll_disable);
-               reg = I915_READ(DSPFW3);
-               reg &= ~DSPFW_HPLL_CURSOR_MASK;
-               reg |= (wm & 0x3f) << DSPFW_HPLL_CURSOR_SHIFT;
-               I915_WRITE(DSPFW3, reg);
-               DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg);
-
-               /* activate cxsr */
-               I915_WRITE(DSPFW3,
-                          I915_READ(DSPFW3) | PINEVIEW_SELF_REFRESH_EN);
-               DRM_DEBUG_KMS("Self-refresh is enabled\n");
-       } else {
-               pineview_disable_cxsr(dev);
-               DRM_DEBUG_KMS("Self-refresh is disabled\n");
+       /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+        * appropriately here, but we need to look more thoroughly into how
+        * panels behave in the two modes.
+        */
+       /* set the dithering flag on LVDS as needed */
+       if (INTEL_INFO(dev)->gen >= 4) {
+               if (dev_priv->lvds_dither)
+                       temp |= LVDS_ENABLE_DITHER;
+               else
+                       temp &= ~LVDS_ENABLE_DITHER;
        }
+       temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+       if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+               temp |= LVDS_HSYNC_POLARITY;
+       if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+               temp |= LVDS_VSYNC_POLARITY;
+       I915_WRITE(LVDS, temp);
 }
 
-static bool g4x_compute_wm0(struct drm_device *dev,
-                           int plane,
-                           const struct intel_watermark_params *display,
-                           int display_latency_ns,
-                           const struct intel_watermark_params *cursor,
-                           int cursor_latency_ns,
-                           int *plane_wm,
-                           int *cursor_wm)
+static void i9xx_update_pll(struct drm_crtc *crtc,
+                           struct drm_display_mode *mode,
+                           struct drm_display_mode *adjusted_mode,
+                           intel_clock_t *clock, intel_clock_t *reduced_clock,
+                           int num_connectors)
 {
-       struct drm_crtc *crtc;
-       int htotal, hdisplay, clock, pixel_size;
-       int line_time_us, line_count;
-       int entries, tlb_miss;
-
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       if (crtc->fb == NULL || !crtc->enabled) {
-               *cursor_wm = cursor->guard_size;
-               *plane_wm = display->guard_size;
-               return false;
-       }
-
-       htotal = crtc->mode.htotal;
-       hdisplay = crtc->mode.hdisplay;
-       clock = crtc->mode.clock;
-       pixel_size = crtc->fb->bits_per_pixel / 8;
-
-       /* Use the small buffer method to calculate plane watermark */
-       entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
-       tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
-       if (tlb_miss > 0)
-               entries += tlb_miss;
-       entries = DIV_ROUND_UP(entries, display->cacheline_size);
-       *plane_wm = entries + display->guard_size;
-       if (*plane_wm > (int)display->max_wm)
-               *plane_wm = display->max_wm;
-
-       /* Use the large buffer method to calculate cursor watermark */
-       line_time_us = ((htotal * 1000) / clock);
-       line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
-       entries = line_count * 64 * pixel_size;
-       tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
-       if (tlb_miss > 0)
-               entries += tlb_miss;
-       entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
-       *cursor_wm = entries + cursor->guard_size;
-       if (*cursor_wm > (int)cursor->max_wm)
-               *cursor_wm = (int)cursor->max_wm;
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       u32 dpll;
+       bool is_sdvo;
 
-       return true;
-}
+       is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
+               intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
 
-/*
- * 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 g4x_check_srwm(struct drm_device *dev,
-                          int display_wm, int cursor_wm,
-                          const struct intel_watermark_params *display,
-                          const struct intel_watermark_params *cursor)
-{
-       DRM_DEBUG_KMS("SR watermark: display plane %d, cursor %d\n",
-                     display_wm, cursor_wm);
+       dpll = DPLL_VGA_MODE_DIS;
 
-       if (display_wm > display->max_wm) {
-               DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n",
-                             display_wm, display->max_wm);
-               return false;
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+               dpll |= DPLLB_MODE_LVDS;
+       else
+               dpll |= DPLLB_MODE_DAC_SERIAL;
+       if (is_sdvo) {
+               int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
+               if (pixel_multiplier > 1) {
+                       if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+                               dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+               }
+               dpll |= DPLL_DVO_HIGH_SPEED;
        }
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+               dpll |= DPLL_DVO_HIGH_SPEED;
 
-       if (cursor_wm > cursor->max_wm) {
-               DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n",
-                             cursor_wm, cursor->max_wm);
-               return false;
+       /* compute bitmask from p1 value */
+       if (IS_PINEVIEW(dev))
+               dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
+       else {
+               dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+               if (IS_G4X(dev) && reduced_clock)
+                       dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
        }
-
-       if (!(display_wm || cursor_wm)) {
-               DRM_DEBUG_KMS("SR latency is 0, disabling\n");
-               return false;
+       switch (clock->p2) {
+       case 5:
+               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+               break;
+       case 7:
+               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+               break;
+       case 10:
+               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+               break;
+       case 14:
+               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+               break;
        }
+       if (INTEL_INFO(dev)->gen >= 4)
+               dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
 
-       return true;
-}
-
-static bool g4x_compute_srwm(struct drm_device *dev,
-                            int plane,
-                            int latency_ns,
-                            const struct intel_watermark_params *display,
-                            const struct intel_watermark_params *cursor,
-                            int *display_wm, int *cursor_wm)
-{
-       struct drm_crtc *crtc;
-       int hdisplay, htotal, pixel_size, clock;
-       unsigned long line_time_us;
-       int line_count, line_size;
-       int small, large;
-       int entries;
-
-       if (!latency_ns) {
-               *display_wm = *cursor_wm = 0;
-               return false;
-       }
+       if (is_sdvo && intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT))
+               dpll |= PLL_REF_INPUT_TVCLKINBC;
+       else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT))
+               /* XXX: just matching BIOS for now */
+               /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
+               dpll |= 3;
+       else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+                intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+               dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+       else
+               dpll |= PLL_REF_INPUT_DREFCLK;
 
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       hdisplay = crtc->mode.hdisplay;
-       htotal = crtc->mode.htotal;
-       clock = crtc->mode.clock;
-       pixel_size = crtc->fb->bits_per_pixel / 8;
+       dpll |= DPLL_VCO_ENABLE;
+       I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
+       POSTING_READ(DPLL(pipe));
+       udelay(150);
 
-       line_time_us = (htotal * 1000) / clock;
-       line_count = (latency_ns / line_time_us + 1000) / 1000;
-       line_size = hdisplay * pixel_size;
+       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
+        * This is an exception to the general rule that mode_set doesn't turn
+        * things on.
+        */
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+               intel_update_lvds(crtc, clock, adjusted_mode);
 
-       /* 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;
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+               intel_dp_set_m_n(crtc, mode, adjusted_mode);
 
-       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-       *display_wm = entries + display->guard_size;
+       I915_WRITE(DPLL(pipe), dpll);
 
-       /* 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;
+       /* Wait for the clocks to stabilize. */
+       POSTING_READ(DPLL(pipe));
+       udelay(150);
 
-       return g4x_check_srwm(dev,
-                             *display_wm, *cursor_wm,
-                             display, cursor);
+       if (INTEL_INFO(dev)->gen >= 4) {
+               u32 temp = 0;
+               if (is_sdvo) {
+                       temp = intel_mode_get_pixel_multiplier(adjusted_mode);
+                       if (temp > 1)
+                               temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
+                       else
+                               temp = 0;
+               }
+               I915_WRITE(DPLL_MD(pipe), temp);
+       } else {
+               /* The pixel multiplier can only be updated once the
+                * DPLL is enabled and the clocks are stable.
+                *
+                * So write it again.
+                */
+               I915_WRITE(DPLL(pipe), dpll);
+       }
 }
 
-#define single_plane_enabled(mask) is_power_of_2(mask)
-
-static void g4x_update_wm(struct drm_device *dev)
-{
-       static const int sr_latency_ns = 12000;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
-       int plane_sr, cursor_sr;
-       unsigned int enabled = 0;
-
-       if (g4x_compute_wm0(dev, 0,
-                           &g4x_wm_info, latency_ns,
-                           &g4x_cursor_wm_info, latency_ns,
-                           &planea_wm, &cursora_wm))
-               enabled |= 1;
-
-       if (g4x_compute_wm0(dev, 1,
-                           &g4x_wm_info, latency_ns,
-                           &g4x_cursor_wm_info, latency_ns,
-                           &planeb_wm, &cursorb_wm))
-               enabled |= 2;
-
-       plane_sr = cursor_sr = 0;
-       if (single_plane_enabled(enabled) &&
-           g4x_compute_srwm(dev, ffs(enabled) - 1,
-                            sr_latency_ns,
-                            &g4x_wm_info,
-                            &g4x_cursor_wm_info,
-                            &plane_sr, &cursor_sr))
-               I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
-       else
-               I915_WRITE(FW_BLC_SELF,
-                          I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN);
-
-       DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
-                     planea_wm, cursora_wm,
-                     planeb_wm, cursorb_wm,
-                     plane_sr, cursor_sr);
-
-       I915_WRITE(DSPFW1,
-                  (plane_sr << DSPFW_SR_SHIFT) |
-                  (cursorb_wm << DSPFW_CURSORB_SHIFT) |
-                  (planeb_wm << DSPFW_PLANEB_SHIFT) |
-                  planea_wm);
-       I915_WRITE(DSPFW2,
-                  (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) |
-                  (cursora_wm << DSPFW_CURSORA_SHIFT));
-       /* HPLL off in SR has some issues on G4x... disable it */
-       I915_WRITE(DSPFW3,
-                  (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) |
-                  (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
-}
-
-static void i965_update_wm(struct drm_device *dev)
+static void i8xx_update_pll(struct drm_crtc *crtc,
+                           struct drm_display_mode *adjusted_mode,
+                           intel_clock_t *clock,
+                           int num_connectors)
 {
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc;
-       int srwm = 1;
-       int cursor_sr = 16;
-
-       /* Calc sr entries for one plane configs */
-       crtc = single_enabled_crtc(dev);
-       if (crtc) {
-               /* self-refresh has much higher latency */
-               static const int sr_latency_ns = 12000;
-               int clock = crtc->mode.clock;
-               int htotal = crtc->mode.htotal;
-               int hdisplay = crtc->mode.hdisplay;
-               int pixel_size = crtc->fb->bits_per_pixel / 8;
-               unsigned long line_time_us;
-               int entries;
-
-               line_time_us = ((htotal * 1000) / clock);
-
-               /* Use ns/us then divide to preserve precision */
-               entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-                       pixel_size * hdisplay;
-               entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE);
-               srwm = I965_FIFO_SIZE - entries;
-               if (srwm < 0)
-                       srwm = 1;
-               srwm &= 0x1ff;
-               DRM_DEBUG_KMS("self-refresh entries: %d, wm: %d\n",
-                             entries, srwm);
-
-               entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-                       pixel_size * 64;
-               entries = DIV_ROUND_UP(entries,
-                                         i965_cursor_wm_info.cacheline_size);
-               cursor_sr = i965_cursor_wm_info.fifo_size -
-                       (entries + i965_cursor_wm_info.guard_size);
-
-               if (cursor_sr > i965_cursor_wm_info.max_wm)
-                       cursor_sr = i965_cursor_wm_info.max_wm;
-
-               DRM_DEBUG_KMS("self-refresh watermark: display plane %d "
-                             "cursor %d\n", srwm, cursor_sr);
-
-               if (IS_CRESTLINE(dev))
-                       I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       u32 dpll;
+
+       dpll = DPLL_VGA_MODE_DIS;
+
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+               dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
        } else {
-               /* Turn off self refresh if both pipes are enabled */
-               if (IS_CRESTLINE(dev))
-                       I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-                                  & ~FW_BLC_SELF_EN);
+               if (clock->p1 == 2)
+                       dpll |= PLL_P1_DIVIDE_BY_TWO;
+               else
+                       dpll |= (clock->p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+               if (clock->p2 == 4)
+                       dpll |= PLL_P2_DIVIDE_BY_4;
        }
 
-       DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
-                     srwm);
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT))
+               /* XXX: just matching BIOS for now */
+               /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
+               dpll |= 3;
+       else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+                intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+               dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+       else
+               dpll |= PLL_REF_INPUT_DREFCLK;
 
-       /* 965 has limitations... */
-       I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) |
-                  (8 << 16) | (8 << 8) | (8 << 0));
-       I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
-       /* update cursor SR watermark */
-       I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
-}
+       dpll |= DPLL_VCO_ENABLE;
+       I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
+       POSTING_READ(DPLL(pipe));
+       udelay(150);
 
-static void i9xx_update_wm(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       const struct intel_watermark_params *wm_info;
-       uint32_t fwater_lo;
-       uint32_t fwater_hi;
-       int cwm, srwm = 1;
-       int fifo_size;
-       int planea_wm, planeb_wm;
-       struct drm_crtc *crtc, *enabled = NULL;
-
-       if (IS_I945GM(dev))
-               wm_info = &i945_wm_info;
-       else if (!IS_GEN2(dev))
-               wm_info = &i915_wm_info;
-       else
-               wm_info = &i855_wm_info;
-
-       fifo_size = dev_priv->display.get_fifo_size(dev, 0);
-       crtc = intel_get_crtc_for_plane(dev, 0);
-       if (crtc->enabled && crtc->fb) {
-               planea_wm = intel_calculate_wm(crtc->mode.clock,
-                                              wm_info, fifo_size,
-                                              crtc->fb->bits_per_pixel / 8,
-                                              latency_ns);
-               enabled = crtc;
-       } else
-               planea_wm = fifo_size - wm_info->guard_size;
-
-       fifo_size = dev_priv->display.get_fifo_size(dev, 1);
-       crtc = intel_get_crtc_for_plane(dev, 1);
-       if (crtc->enabled && crtc->fb) {
-               planeb_wm = intel_calculate_wm(crtc->mode.clock,
-                                              wm_info, fifo_size,
-                                              crtc->fb->bits_per_pixel / 8,
-                                              latency_ns);
-               if (enabled == NULL)
-                       enabled = crtc;
-               else
-                       enabled = NULL;
-       } else
-               planeb_wm = fifo_size - wm_info->guard_size;
+       I915_WRITE(DPLL(pipe), dpll);
 
-       DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+       /* Wait for the clocks to stabilize. */
+       POSTING_READ(DPLL(pipe));
+       udelay(150);
 
-       /*
-        * Overlay gets an aggressive default since video jitter is bad.
+       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
+        * This is an exception to the general rule that mode_set doesn't turn
+        * things on.
         */
-       cwm = 2;
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+               intel_update_lvds(crtc, clock, adjusted_mode);
 
-       /* Play safe and disable self-refresh before adjusting watermarks. */
-       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);
-
-       /* Calc sr entries for one plane configs */
-       if (HAS_FW_BLC(dev) && enabled) {
-               /* self-refresh has much higher latency */
-               static const int sr_latency_ns = 6000;
-               int clock = enabled->mode.clock;
-               int htotal = enabled->mode.htotal;
-               int hdisplay = enabled->mode.hdisplay;
-               int pixel_size = enabled->fb->bits_per_pixel / 8;
-               unsigned long line_time_us;
-               int entries;
-
-               line_time_us = (htotal * 1000) / clock;
-
-               /* Use ns/us then divide to preserve precision */
-               entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-                       pixel_size * hdisplay;
-               entries = DIV_ROUND_UP(entries, wm_info->cacheline_size);
-               DRM_DEBUG_KMS("self-refresh entries: %d\n", entries);
-               srwm = wm_info->fifo_size - entries;
-               if (srwm < 0)
-                       srwm = 1;
-
-               if (IS_I945G(dev) || IS_I945GM(dev))
-                       I915_WRITE(FW_BLC_SELF,
-                                  FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
-               else if (IS_I915GM(dev))
-                       I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
-       }
-
-       DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
-                     planea_wm, planeb_wm, cwm, srwm);
-
-       fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f);
-       fwater_hi = (cwm & 0x1f);
-
-       /* Set request length to 8 cachelines per fetch */
-       fwater_lo = fwater_lo | (1 << 24) | (1 << 8);
-       fwater_hi = fwater_hi | (1 << 8);
-
-       I915_WRITE(FW_BLC, fwater_lo);
-       I915_WRITE(FW_BLC2, fwater_hi);
-
-       if (HAS_FW_BLC(dev)) {
-               if (enabled) {
-                       if (IS_I945G(dev) || IS_I945GM(dev))
-                               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);
-                       DRM_DEBUG_KMS("memory self refresh enabled\n");
-               } else
-                       DRM_DEBUG_KMS("memory self refresh disabled\n");
-       }
+       /* The pixel multiplier can only be updated once the
+        * DPLL is enabled and the clocks are stable.
+        *
+        * So write it again.
+        */
+       I915_WRITE(DPLL(pipe), dpll);
 }
 
-static void i830_update_wm(struct drm_device *dev)
+static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
+                             struct drm_display_mode *mode,
+                             struct drm_display_mode *adjusted_mode,
+                             int x, int y,
+                             struct drm_framebuffer *old_fb)
 {
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc;
-       uint32_t fwater_lo;
-       int planea_wm;
-
-       crtc = single_enabled_crtc(dev);
-       if (crtc == NULL)
-               return;
-
-       planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info,
-                                      dev_priv->display.get_fifo_size(dev, 0),
-                                      crtc->fb->bits_per_pixel / 8,
-                                      latency_ns);
-       fwater_lo = I915_READ(FW_BLC) & ~0xfff;
-       fwater_lo |= (3<<8) | planea_wm;
-
-       DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm);
-
-       I915_WRITE(FW_BLC, fwater_lo);
-}
-
-#define ILK_LP0_PLANE_LATENCY          700
-#define ILK_LP0_CURSOR_LATENCY         1300
-
-/*
- * 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);
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       int plane = intel_crtc->plane;
+       int refclk, num_connectors = 0;
+       intel_clock_t clock, reduced_clock;
+       u32 dspcntr, pipeconf, vsyncshift;
+       bool ok, has_reduced_clock = false, is_sdvo = false;
+       bool is_lvds = false, is_tv = false, is_dp = false;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct intel_encoder *encoder;
+       const intel_limit_t *limit;
+       int ret;
 
-       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);
+       list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+               if (encoder->base.crtc != crtc)
+                       continue;
 
-               /* 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;
-       }
+               switch (encoder->type) {
+               case INTEL_OUTPUT_LVDS:
+                       is_lvds = true;
+                       break;
+               case INTEL_OUTPUT_SDVO:
+               case INTEL_OUTPUT_HDMI:
+                       is_sdvo = true;
+                       if (encoder->needs_tv_clock)
+                               is_tv = true;
+                       break;
+               case INTEL_OUTPUT_TVOUT:
+                       is_tv = true;
+                       break;
+               case INTEL_OUTPUT_DISPLAYPORT:
+                       is_dp = true;
+                       break;
+               }
 
-       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;
+               num_connectors++;
        }
 
-       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;
-       }
+       refclk = i9xx_get_refclk(crtc, num_connectors);
 
-       if (!(fbc_wm || display_wm || cursor_wm)) {
-               DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level);
-               return false;
+       /*
+        * Returns a set of divisors for the desired target clock with the given
+        * refclk, or FALSE.  The returned values represent the clock equation:
+        * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+        */
+       limit = intel_limit(crtc, refclk);
+       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
+                            &clock);
+       if (!ok) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
        }
 
-       return true;
-}
+       /* Ensure that the cursor is valid for the new mode before changing... */
+       intel_crtc_update_cursor(crtc, 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;
-       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;
+       if (is_lvds && dev_priv->lvds_downclock_avail) {
+               /*
+                * Ensure we match the reduced clock's P to the target clock.
+                * If the clocks don't match, we can't switch the display clock
+                * by using the FP0/FP1. In such case we will disable the LVDS
+                * downclock feature.
+               */
+               has_reduced_clock = limit->find_pll(limit, crtc,
+                                                   dev_priv->lvds_downclock,
+                                                   refclk,
+                                                   &clock,
+                                                   &reduced_clock);
        }
 
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       hdisplay = crtc->mode.hdisplay;
-       htotal = crtc->mode.htotal;
-       clock = crtc->mode.clock;
-       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;
+       if (is_sdvo && is_tv)
+               i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock);
 
-       /* 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;
+       i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ?
+                                &reduced_clock : NULL);
 
-       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-       *display_wm = entries + display->guard_size;
+       if (IS_GEN2(dev))
+               i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors);
+       else
+               i9xx_update_pll(crtc, mode, adjusted_mode, &clock,
+                               has_reduced_clock ? &reduced_clock : NULL,
+                               num_connectors);
 
-       /*
-        * 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;
+       /* setup pipeconf */
+       pipeconf = I915_READ(PIPECONF(pipe));
 
-       /* 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;
+       /* Set up the display plane register */
+       dspcntr = DISPPLANE_GAMMA_ENABLE;
 
-       return ironlake_check_srwm(dev, level,
-                                  *fbc_wm, *display_wm, *cursor_wm,
-                                  display, cursor);
-}
+       if (pipe == 0)
+               dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
+       else
+               dspcntr |= DISPPLANE_SEL_PIPE_B;
 
-static void ironlake_update_wm(struct drm_device *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, 0,
-                           &ironlake_display_wm_info,
-                           ILK_LP0_PLANE_LATENCY,
-                           &ironlake_cursor_wm_info,
-                           ILK_LP0_CURSOR_LATENCY,
-                           &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;
-       }
-
-       if (g4x_compute_wm0(dev, 1,
-                           &ironlake_display_wm_info,
-                           ILK_LP0_PLANE_LATENCY,
-                           &ironlake_cursor_wm_info,
-                           ILK_LP0_CURSOR_LATENCY,
-                           &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 |= 2;
+       if (pipe == 0 && INTEL_INFO(dev)->gen < 4) {
+               /* Enable pixel doubling when the dot clock is > 90% of the (display)
+                * core speed.
+                *
+                * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
+                * pipe == 0 check?
+                */
+               if (mode->clock >
+                   dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
+                       pipeconf |= PIPECONF_DOUBLE_WIDE;
+               else
+                       pipeconf &= ~PIPECONF_DOUBLE_WIDE;
        }
 
-       /*
-        * 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,
-                                  ILK_READ_WM1_LATENCY() * 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 |
-                  (ILK_READ_WM1_LATENCY() << 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,
-                                  ILK_READ_WM2_LATENCY() * 500,
-                                  &ironlake_display_srwm_info,
-                                  &ironlake_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
+       /* default to 8bpc */
+       pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
+       if (is_dp) {
+               if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
+                       pipeconf |= PIPECONF_BPP_6 |
+                                   PIPECONF_DITHER_EN |
+                                   PIPECONF_DITHER_TYPE_SP;
+               }
+       }
 
-       I915_WRITE(WM2_LP_ILK,
-                  WM2_LP_EN |
-                  (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
+       DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+       drm_mode_debug_printmodeline(mode);
 
-       /*
-        * WM3 is unsupported on ILK, probably because we don't have latency
-        * data for that power state
-        */
-}
+       if (HAS_PIPE_CXSR(dev)) {
+               if (intel_crtc->lowfreq_avail) {
+                       DRM_DEBUG_KMS("enabling CxSR downclocking\n");
+                       pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+               } else {
+                       DRM_DEBUG_KMS("disabling CxSR downclocking\n");
+                       pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+               }
+       }
 
-void sandybridge_update_wm(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
-       u32 val;
-       int fbc_wm, plane_wm, cursor_wm;
-       unsigned int enabled;
-
-       enabled = 0;
-       if (g4x_compute_wm0(dev, 0,
-                           &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;
-       }
-
-       if (g4x_compute_wm0(dev, 1,
-                           &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 |= 2;
-       }
-
-       /* IVB has 3 pipes */
-       if (IS_IVYBRIDGE(dev) &&
-           g4x_compute_wm0(dev, 2,
-                           &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 |= 3;
+       pipeconf &= ~PIPECONF_INTERLACE_MASK;
+       if (!IS_GEN2(dev) &&
+           adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+               /* the chip adds 2 halflines automatically */
+               adjusted_mode->crtc_vtotal -= 1;
+               adjusted_mode->crtc_vblank_end -= 1;
+               vsyncshift = adjusted_mode->crtc_hsync_start
+                            - adjusted_mode->crtc_htotal/2;
+       } else {
+               pipeconf |= PIPECONF_PROGRESSIVE;
+               vsyncshift = 0;
        }
 
-       /*
-        * 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 (!IS_GEN3(dev))
+               I915_WRITE(VSYNCSHIFT(pipe), vsyncshift);
 
-       if (!single_plane_enabled(enabled) ||
-           dev_priv->sprite_scaling_enabled)
-               return;
-       enabled = ffs(enabled) - 1;
-
-       /* WM1 */
-       if (!ironlake_compute_srwm(dev, 1, enabled,
-                                  SNB_READ_WM1_LATENCY() * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
+       I915_WRITE(HTOTAL(pipe),
+                  (adjusted_mode->crtc_hdisplay - 1) |
+                  ((adjusted_mode->crtc_htotal - 1) << 16));
+       I915_WRITE(HBLANK(pipe),
+                  (adjusted_mode->crtc_hblank_start - 1) |
+                  ((adjusted_mode->crtc_hblank_end - 1) << 16));
+       I915_WRITE(HSYNC(pipe),
+                  (adjusted_mode->crtc_hsync_start - 1) |
+                  ((adjusted_mode->crtc_hsync_end - 1) << 16));
 
-       I915_WRITE(WM1_LP_ILK,
-                  WM1_LP_SR_EN |
-                  (SNB_READ_WM1_LATENCY() << 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,
-                                  SNB_READ_WM2_LATENCY() * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
+       I915_WRITE(VTOTAL(pipe),
+                  (adjusted_mode->crtc_vdisplay - 1) |
+                  ((adjusted_mode->crtc_vtotal - 1) << 16));
+       I915_WRITE(VBLANK(pipe),
+                  (adjusted_mode->crtc_vblank_start - 1) |
+                  ((adjusted_mode->crtc_vblank_end - 1) << 16));
+       I915_WRITE(VSYNC(pipe),
+                  (adjusted_mode->crtc_vsync_start - 1) |
+                  ((adjusted_mode->crtc_vsync_end - 1) << 16));
 
-       I915_WRITE(WM2_LP_ILK,
-                  WM2_LP_EN |
-                  (SNB_READ_WM2_LATENCY() << 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,
-                                  SNB_READ_WM3_LATENCY() * 500,
-                                  &sandybridge_display_srwm_info,
-                                  &sandybridge_cursor_srwm_info,
-                                  &fbc_wm, &plane_wm, &cursor_wm))
-               return;
+       /* pipesrc and dspsize control the size that is scaled from,
+        * which should always be the user's requested size.
+        */
+       I915_WRITE(DSPSIZE(plane),
+                  ((mode->vdisplay - 1) << 16) |
+                  (mode->hdisplay - 1));
+       I915_WRITE(DSPPOS(plane), 0);
+       I915_WRITE(PIPESRC(pipe),
+                  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 
-       I915_WRITE(WM3_LP_ILK,
-                  WM3_LP_EN |
-                  (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
-                  (fbc_wm << WM1_LP_FBC_SHIFT) |
-                  (plane_wm << WM1_LP_SR_SHIFT) |
-                  cursor_wm);
-}
+       I915_WRITE(PIPECONF(pipe), pipeconf);
+       POSTING_READ(PIPECONF(pipe));
+       intel_enable_pipe(dev_priv, pipe, false);
 
-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;
+       intel_wait_for_vblank(dev, pipe);
 
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       if (crtc->fb == NULL || !crtc->enabled) {
-               *sprite_wm = display->guard_size;
-               return false;
-       }
+       I915_WRITE(DSPCNTR(plane), dspcntr);
+       POSTING_READ(DSPCNTR(plane));
 
-       clock = crtc->mode.clock;
+       ret = intel_pipe_set_base(crtc, x, y, old_fb);
 
-       /* 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;
+       intel_update_watermarks(dev);
 
-       return true;
+       return ret;
 }
 
-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)
+/*
+ * Initialize reference clocks when the driver loads
+ */
+void ironlake_init_pch_refclk(struct drm_device *dev)
 {
-       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;
-       }
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct intel_encoder *encoder;
+       u32 temp;
+       bool has_lvds = false;
+       bool has_cpu_edp = false;
+       bool has_pch_edp = false;
+       bool has_panel = false;
+       bool has_ck505 = false;
+       bool can_ssc = false;
 
-       crtc = intel_get_crtc_for_plane(dev, plane);
-       clock = crtc->mode.clock;
-       if (!clock) {
-               *sprite_wm = 0;
-               return false;
+       /* We need to take the global config into account */
+       list_for_each_entry(encoder, &mode_config->encoder_list,
+                           base.head) {
+               switch (encoder->type) {
+               case INTEL_OUTPUT_LVDS:
+                       has_panel = true;
+                       has_lvds = true;
+                       break;
+               case INTEL_OUTPUT_EDP:
+                       has_panel = true;
+                       if (intel_encoder_is_pch_edp(&encoder->base))
+                               has_pch_edp = true;
+                       else
+                               has_cpu_edp = true;
+                       break;
+               }
        }
 
-       line_time_us = (sprite_width * 1000) / clock;
-       if (!line_time_us) {
-               *sprite_wm = 0;
-               return false;
+       if (HAS_PCH_IBX(dev)) {
+               has_ck505 = dev_priv->display_clock_mode;
+               can_ssc = has_ck505;
+       } else {
+               has_ck505 = false;
+               can_ssc = true;
        }
 
-       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;
+       DRM_DEBUG_KMS("has_panel %d has_lvds %d has_pch_edp %d has_cpu_edp %d has_ck505 %d\n",
+                     has_panel, has_lvds, has_pch_edp, has_cpu_edp,
+                     has_ck505);
 
-       entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
-       *sprite_wm = entries + display->guard_size;
+       /* Ironlake: try to setup display ref clock before DPLL
+        * enabling. This is only under driver's control after
+        * PCH B stepping, previous chipset stepping should be
+        * ignoring this setting.
+        */
+       temp = I915_READ(PCH_DREF_CONTROL);
+       /* Always enable nonspread source */
+       temp &= ~DREF_NONSPREAD_SOURCE_MASK;
 
-       return *sprite_wm > 0x3ff ? false : true;
-}
+       if (has_ck505)
+               temp |= DREF_NONSPREAD_CK505_ENABLE;
+       else
+               temp |= DREF_NONSPREAD_SOURCE_ENABLE;
 
-static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,
-                                        uint32_t sprite_width, int pixel_size)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
-       u32 val;
-       int sprite_wm, reg;
-       int ret;
+       if (has_panel) {
+               temp &= ~DREF_SSC_SOURCE_MASK;
+               temp |= DREF_SSC_SOURCE_ENABLE;
 
-       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 */
-       }
+               /* SSC must be turned on before enabling the CPU output  */
+               if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+                       DRM_DEBUG_KMS("Using SSC on panel\n");
+                       temp |= DREF_SSC1_ENABLE;
+               } else
+                       temp &= ~DREF_SSC1_ENABLE;
 
-       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 %d\n",
-                             pipe);
-               return;
-       }
+               /* Get SSC going before enabling the outputs */
+               I915_WRITE(PCH_DREF_CONTROL, temp);
+               POSTING_READ(PCH_DREF_CONTROL);
+               udelay(200);
 
-       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 %d - %d\n", pipe, sprite_wm);
-
-
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             SNB_READ_WM1_LATENCY() * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %d\n",
-                             pipe);
-               return;
-       }
-       I915_WRITE(WM1S_LP_ILK, sprite_wm);
+               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
-       /* Only IVB has two more LP watermarks for sprite */
-       if (!IS_IVYBRIDGE(dev))
-               return;
+               /* Enable CPU source on CPU attached eDP */
+               if (has_cpu_edp) {
+                       if (intel_panel_use_ssc(dev_priv) && can_ssc) {
+                               DRM_DEBUG_KMS("Using SSC on eDP\n");
+                               temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+                       }
+                       else
+                               temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+               } else
+                       temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
 
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             SNB_READ_WM2_LATENCY() * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %d\n",
-                             pipe);
-               return;
-       }
-       I915_WRITE(WM2S_LP_IVB, sprite_wm);
+               I915_WRITE(PCH_DREF_CONTROL, temp);
+               POSTING_READ(PCH_DREF_CONTROL);
+               udelay(200);
+       } else {
+               DRM_DEBUG_KMS("Disabling SSC entirely\n");
 
-       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
-                                             pixel_size,
-                                             &sandybridge_display_srwm_info,
-                                             SNB_READ_WM3_LATENCY() * 500,
-                                             &sprite_wm);
-       if (!ret) {
-               DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %d\n",
-                             pipe);
-               return;
+               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+
+               /* Turn off CPU output */
+               temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+
+               I915_WRITE(PCH_DREF_CONTROL, temp);
+               POSTING_READ(PCH_DREF_CONTROL);
+               udelay(200);
+
+               /* Turn off the SSC source */
+               temp &= ~DREF_SSC_SOURCE_MASK;
+               temp |= DREF_SSC_SOURCE_DISABLE;
+
+               /* Turn off SSC1 */
+               temp &= ~ DREF_SSC1_ENABLE;
+
+               I915_WRITE(PCH_DREF_CONTROL, temp);
+               POSTING_READ(PCH_DREF_CONTROL);
+               udelay(200);
        }
-       I915_WRITE(WM3S_LP_IVB, sprite_wm);
 }
 
-/**
- * intel_update_watermarks - update FIFO watermark values based on current modes
- *
- * Calculate watermark values for the various WM regs based on current mode
- * and plane configuration.
- *
- * There are several cases to deal with here:
- *   - normal (i.e. non-self-refresh)
- *   - self-refresh (SR) mode
- *   - lines are large relative to FIFO size (buffer can hold up to 2)
- *   - lines are small relative to FIFO size (buffer can hold more than 2
- *     lines), so need to account for TLB latency
- *
- *   The normal calculation is:
- *     watermark = dotclock * bytes per pixel * latency
- *   where latency is platform & configuration dependent (we assume pessimal
- *   values here).
- *
- *   The SR calculation is:
- *     watermark = (trunc(latency/line time)+1) * surface width *
- *       bytes per pixel
- *   where
- *     line time = htotal / dotclock
- *     surface width = hdisplay for normal plane and 64 for cursor
- *   and latency is assumed to be high, as above.
- *
- * The final value programmed to the register should always be rounded up,
- * and include an extra 2 entries to account for clock crossings.
- *
- * We don't use the sprite, so we can ignore that.  And on Crestline we have
- * to set the non-SR watermarks to 8.
- */
-static void intel_update_watermarks(struct drm_device *dev)
+static int ironlake_get_refclk(struct drm_crtc *crtc)
 {
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_encoder *encoder;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct intel_encoder *edp_encoder = NULL;
+       int num_connectors = 0;
+       bool is_lvds = false;
 
-       if (dev_priv->display.update_wm)
-               dev_priv->display.update_wm(dev);
-}
+       list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+               if (encoder->base.crtc != crtc)
+                       continue;
 
-void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
-                                   uint32_t sprite_width, int pixel_size)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
+               switch (encoder->type) {
+               case INTEL_OUTPUT_LVDS:
+                       is_lvds = true;
+                       break;
+               case INTEL_OUTPUT_EDP:
+                       edp_encoder = encoder;
+                       break;
+               }
+               num_connectors++;
+       }
 
-       if (dev_priv->display.update_sprite_wm)
-               dev_priv->display.update_sprite_wm(dev, pipe, sprite_width,
-                                                  pixel_size);
-}
+       if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
+               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+                             dev_priv->lvds_ssc_freq);
+               return dev_priv->lvds_ssc_freq * 1000;
+       }
 
-static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
-{
-       if (i915_panel_use_ssc >= 0)
-               return i915_panel_use_ssc != 0;
-       return dev_priv->lvds_use_ssc
-               && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
+       return 120000;
 }
 
-/**
- * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
- * @crtc: CRTC structure
- * @mode: requested mode
- *
- * A pipe may be connected to one or more outputs.  Based on the depth of the
- * attached framebuffer, choose a good color depth to use on the pipe.
- *
- * If possible, match the pipe depth to the fb depth.  In some cases, this
- * isn't ideal, because the connected output supports a lesser or restricted
- * set of depths.  Resolve that here:
- *    LVDS typically supports only 6bpc, so clamp down in that case
- *    HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
- *    Displays may support a restricted set as well, check EDID and clamp as
- *      appropriate.
- *    DP may want to dither down to 6bpc to fit larger modes
- *
- * RETURNS:
- * Dithering requirement (i.e. false if display bpc and pipe bpc match,
- * true if they don't match).
- */
-static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
-                                        unsigned int *pipe_bpp,
-                                        struct drm_display_mode *mode)
+static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
+                                 struct drm_display_mode *mode,
+                                 struct drm_display_mode *adjusted_mode,
+                                 int x, int y,
+                                 struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_encoder *encoder;
-       struct drm_connector *connector;
-       unsigned int display_bpc = UINT_MAX, bpc;
-
-       /* Walk the encoders & connectors on this crtc, get min bpc */
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       int plane = intel_crtc->plane;
+       int refclk, num_connectors = 0;
+       intel_clock_t clock, reduced_clock;
+       u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf;
+       bool ok, has_reduced_clock = false, is_sdvo = false;
+       bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct intel_encoder *encoder, *edp_encoder = NULL;
+       const intel_limit_t *limit;
+       int ret;
+       struct fdi_m_n m_n = {0};
+       u32 temp;
+       int target_clock, pixel_multiplier, lane, link_bw, factor;
+       unsigned int pipe_bpp;
+       bool dither;
+       bool is_cpu_edp = false, is_pch_edp = false;
 
-               if (encoder->crtc != crtc)
+       list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
+               if (encoder->base.crtc != crtc)
                        continue;
 
-               if (intel_encoder->type == INTEL_OUTPUT_LVDS) {
-                       unsigned int lvds_bpc;
-
-                       if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) ==
-                           LVDS_A3_POWER_UP)
-                               lvds_bpc = 8;
+               switch (encoder->type) {
+               case INTEL_OUTPUT_LVDS:
+                       is_lvds = true;
+                       break;
+               case INTEL_OUTPUT_SDVO:
+               case INTEL_OUTPUT_HDMI:
+                       is_sdvo = true;
+                       if (encoder->needs_tv_clock)
+                               is_tv = true;
+                       break;
+               case INTEL_OUTPUT_TVOUT:
+                       is_tv = true;
+                       break;
+               case INTEL_OUTPUT_ANALOG:
+                       is_crt = true;
+                       break;
+               case INTEL_OUTPUT_DISPLAYPORT:
+                       is_dp = true;
+                       break;
+               case INTEL_OUTPUT_EDP:
+                       is_dp = true;
+                       if (intel_encoder_is_pch_edp(&encoder->base))
+                               is_pch_edp = true;
                        else
-                               lvds_bpc = 6;
-
-                       if (lvds_bpc < display_bpc) {
-                               DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
-                               display_bpc = lvds_bpc;
-                       }
-                       continue;
+                               is_cpu_edp = true;
+                       edp_encoder = encoder;
+                       break;
                }
 
-               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
-                       /* Use VBT settings if we have an eDP panel */
-                       unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+               num_connectors++;
+       }
 
-                       if (edp_bpc < display_bpc) {
-                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
-                               display_bpc = edp_bpc;
-                       }
-                       continue;
-               }
+       refclk = ironlake_get_refclk(crtc);
 
-               /* Not one of the known troublemakers, check the EDID */
-               list_for_each_entry(connector, &dev->mode_config.connector_list,
-                                   head) {
-                       if (connector->encoder != encoder)
-                               continue;
+       /*
+        * Returns a set of divisors for the desired target clock with the given
+        * refclk, or FALSE.  The returned values represent the clock equation:
+        * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+        */
+       limit = intel_limit(crtc, refclk);
+       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
+                            &clock);
+       if (!ok) {
+               DRM_ERROR("Couldn't find PLL settings for mode!\n");
+               return -EINVAL;
+       }
 
-                       /* Don't use an invalid EDID bpc value */
-                       if (connector->display_info.bpc &&
-                           connector->display_info.bpc < display_bpc) {
-                               DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
-                               display_bpc = connector->display_info.bpc;
-                       }
-               }
+       /* Ensure that the cursor is valid for the new mode before changing... */
+       intel_crtc_update_cursor(crtc, true);
 
+       if (is_lvds && dev_priv->lvds_downclock_avail) {
                /*
-                * HDMI is either 12 or 8, so if the display lets 10bpc sneak
-                * through, clamp it down.  (Note: >12bpc will be caught below.)
-                */
-               if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-                       if (display_bpc > 8 && display_bpc < 12) {
-                               DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
-                               display_bpc = 12;
-                       } else {
-                               DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
-                               display_bpc = 8;
-                       }
+                * Ensure we match the reduced clock's P to the target clock.
+                * If the clocks don't match, we can't switch the display clock
+                * by using the FP0/FP1. In such case we will disable the LVDS
+                * downclock feature.
+               */
+               has_reduced_clock = limit->find_pll(limit, crtc,
+                                                   dev_priv->lvds_downclock,
+                                                   refclk,
+                                                   &clock,
+                                                   &reduced_clock);
+       }
+       /* SDVO TV has fixed PLL values depend on its clock range,
+          this mirrors vbios setting. */
+       if (is_sdvo && is_tv) {
+               if (adjusted_mode->clock >= 100000
+                   && adjusted_mode->clock < 140500) {
+                       clock.p1 = 2;
+                       clock.p2 = 10;
+                       clock.n = 3;
+                       clock.m1 = 16;
+                       clock.m2 = 8;
+               } else if (adjusted_mode->clock >= 140500
+                          && adjusted_mode->clock <= 200000) {
+                       clock.p1 = 1;
+                       clock.p2 = 10;
+                       clock.n = 6;
+                       clock.m1 = 12;
+                       clock.m2 = 8;
                }
        }
 
-       if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
-               DRM_DEBUG_KMS("Dithering DP to 6bpc\n");
-               display_bpc = 6;
-       }
+       /* FDI link */
+       pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
+       lane = 0;
+       /* CPU eDP doesn't require FDI link, so just set DP M/N
+          according to current link config */
+       if (is_cpu_edp) {
+               target_clock = mode->clock;
+               intel_edp_link_config(edp_encoder, &lane, &link_bw);
+       } else {
+               /* [e]DP over FDI requires target mode clock
+                  instead of link clock */
+               if (is_dp)
+                       target_clock = mode->clock;
+               else
+                       target_clock = adjusted_mode->clock;
 
-       /*
-        * We could just drive the pipe at the highest bpc all the time and
-        * enable dithering as needed, but that costs bandwidth.  So choose
-        * the minimum value that expresses the full color range of the fb but
-        * also stays within the max display bpc discovered above.
-        */
+               /* FDI is a binary signal running at ~2.7GHz, encoding
+                * each output octet as 10 bits. The actual frequency
+                * is stored as a divider into a 100MHz clock, and the
+                * mode pixel clock is stored in units of 1KHz.
+                * Hence the bw of each lane in terms of the mode signal
+                * is:
+                */
+               link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
+       }
 
-       switch (crtc->fb->depth) {
-       case 8:
-               bpc = 8; /* since we go through a colormap */
-               break;
-       case 15:
-       case 16:
-               bpc = 6; /* min is 18bpp */
+       /* determine panel color depth */
+       temp = I915_READ(PIPECONF(pipe));
+       temp &= ~PIPE_BPC_MASK;
+       dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
+       switch (pipe_bpp) {
+       case 18:
+               temp |= PIPE_6BPC;
                break;
        case 24:
-               bpc = 8;
+               temp |= PIPE_8BPC;
                break;
        case 30:
-               bpc = 10;
+               temp |= PIPE_10BPC;
                break;
-       case 48:
-               bpc = 12;
+       case 36:
+               temp |= PIPE_12BPC;
                break;
        default:
-               DRM_DEBUG("unsupported depth, assuming 24 bits\n");
-               bpc = min((unsigned int)8, display_bpc);
+               WARN(1, "intel_choose_pipe_bpp returned invalid value %d\n",
+                       pipe_bpp);
+               temp |= PIPE_8BPC;
+               pipe_bpp = 24;
                break;
        }
 
-       display_bpc = min(display_bpc, bpc);
+       intel_crtc->bpp = pipe_bpp;
+       I915_WRITE(PIPECONF(pipe), temp);
 
-       DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
-                     bpc, display_bpc);
+       if (!lane) {
+               /*
+                * Account for spread spectrum to avoid
+                * oversubscribing the link. Max center spread
+                * is 2.5%; use 5% for safety's sake.
+                */
+               u32 bps = target_clock * intel_crtc->bpp * 21 / 20;
+               lane = bps / (link_bw * 8) + 1;
+       }
 
-       *pipe_bpp = display_bpc * 3;
+       intel_crtc->fdi_lanes = lane;
 
-       return display_bpc != bpc;
-}
+       if (pixel_multiplier > 1)
+               link_bw *= pixel_multiplier;
+       ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
+                            &m_n);
 
-static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int refclk;
+       fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+       if (has_reduced_clock)
+               fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+                       reduced_clock.m2;
 
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
-           intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               refclk = dev_priv->lvds_ssc_freq * 1000;
-               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
-                             refclk / 1000);
-       } else if (!IS_GEN2(dev)) {
-               refclk = 96000;
-       } else {
-               refclk = 48000;
-       }
+       /* Enable autotuning of the PLL clock (if permissible) */
+       factor = 21;
+       if (is_lvds) {
+               if ((intel_panel_use_ssc(dev_priv) &&
+                    dev_priv->lvds_ssc_freq == 100) ||
+                   (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+                       factor = 25;
+       } else if (is_sdvo && is_tv)
+               factor = 20;
 
-       return refclk;
-}
+       if (clock.m < factor * clock.n)
+               fp |= FP_CB_TUNE;
 
-static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode,
-                                     intel_clock_t *clock)
-{
-       /* SDVO TV has fixed PLL values depend on its clock range,
-          this mirrors vbios setting. */
-       if (adjusted_mode->clock >= 100000
-           && adjusted_mode->clock < 140500) {
-               clock->p1 = 2;
-               clock->p2 = 10;
-               clock->n = 3;
-               clock->m1 = 16;
-               clock->m2 = 8;
-       } else if (adjusted_mode->clock >= 140500
-                  && adjusted_mode->clock <= 200000) {
-               clock->p1 = 1;
-               clock->p2 = 10;
-               clock->n = 6;
-               clock->m1 = 12;
-               clock->m2 = 8;
+       dpll = 0;
+
+       if (is_lvds)
+               dpll |= DPLLB_MODE_LVDS;
+       else
+               dpll |= DPLLB_MODE_DAC_SERIAL;
+       if (is_sdvo) {
+               int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
+               if (pixel_multiplier > 1) {
+                       dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
+               }
+               dpll |= DPLL_DVO_HIGH_SPEED;
        }
-}
+       if (is_dp && !is_cpu_edp)
+               dpll |= DPLL_DVO_HIGH_SPEED;
 
-static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
-                                    intel_clock_t *clock,
-                                    intel_clock_t *reduced_clock)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       u32 fp, fp2 = 0;
+       /* compute bitmask from p1 value */
+       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
+       /* also FPA1 */
+       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
 
-       if (IS_PINEVIEW(dev)) {
-               fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2;
-               if (reduced_clock)
-                       fp2 = (1 << reduced_clock->n) << 16 |
-                               reduced_clock->m1 << 8 | reduced_clock->m2;
-       } else {
-               fp = clock->n << 16 | clock->m1 << 8 | clock->m2;
-               if (reduced_clock)
-                       fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 |
-                               reduced_clock->m2;
+       switch (clock.p2) {
+       case 5:
+               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+               break;
+       case 7:
+               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+               break;
+       case 10:
+               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+               break;
+       case 14:
+               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+               break;
        }
 
-       I915_WRITE(FP0(pipe), fp);
+       if (is_sdvo && is_tv)
+               dpll |= PLL_REF_INPUT_TVCLKINBC;
+       else if (is_tv)
+               /* XXX: just matching BIOS for now */
+               /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
+               dpll |= 3;
+       else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+               dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
+       else
+               dpll |= PLL_REF_INPUT_DREFCLK;
 
-       intel_crtc->lowfreq_avail = false;
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
-           reduced_clock && i915_powersave) {
-               I915_WRITE(FP1(pipe), fp2);
-               intel_crtc->lowfreq_avail = true;
-       } else {
-               I915_WRITE(FP1(pipe), fp);
-       }
-}
-
-static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
-                             struct drm_display_mode *mode,
-                             struct drm_display_mode *adjusted_mode,
-                             int x, int y,
-                             struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
-       int refclk, num_connectors = 0;
-       intel_clock_t clock, reduced_clock;
-       u32 dpll, dspcntr, pipeconf, vsyncshift;
-       bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
-       bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct intel_encoder *encoder;
-       const intel_limit_t *limit;
-       int ret;
-       u32 temp;
-       u32 lvds_sync = 0;
-
-       list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
-               if (encoder->base.crtc != crtc)
-                       continue;
-
-               switch (encoder->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
-               case INTEL_OUTPUT_SDVO:
-               case INTEL_OUTPUT_HDMI:
-                       is_sdvo = true;
-                       if (encoder->needs_tv_clock)
-                               is_tv = true;
-                       break;
-               case INTEL_OUTPUT_DVO:
-                       is_dvo = true;
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       is_tv = true;
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       is_crt = true;
-                       break;
-               case INTEL_OUTPUT_DISPLAYPORT:
-                       is_dp = true;
-                       break;
-               }
-
-               num_connectors++;
-       }
-
-       refclk = i9xx_get_refclk(crtc, num_connectors);
-
-       /*
-        * Returns a set of divisors for the desired target clock with the given
-        * refclk, or FALSE.  The returned values represent the clock equation:
-        * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
-        */
-       limit = intel_limit(crtc, refclk);
-       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
-                            &clock);
-       if (!ok) {
-               DRM_ERROR("Couldn't find PLL settings for mode!\n");
-               return -EINVAL;
-       }
-
-       /* Ensure that the cursor is valid for the new mode before changing... */
-       intel_crtc_update_cursor(crtc, true);
-
-       if (is_lvds && dev_priv->lvds_downclock_avail) {
-               /*
-                * Ensure we match the reduced clock's P to the target clock.
-                * If the clocks don't match, we can't switch the display clock
-                * by using the FP0/FP1. In such case we will disable the LVDS
-                * downclock feature.
-               */
-               has_reduced_clock = limit->find_pll(limit, crtc,
-                                                   dev_priv->lvds_downclock,
-                                                   refclk,
-                                                   &clock,
-                                                   &reduced_clock);
-       }
-
-       if (is_sdvo && is_tv)
-               i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock);
-
-       i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ?
-                                &reduced_clock : NULL);
-
-       dpll = DPLL_VGA_MODE_DIS;
-
-       if (!IS_GEN2(dev)) {
-               if (is_lvds)
-                       dpll |= DPLLB_MODE_LVDS;
-               else
-                       dpll |= DPLLB_MODE_DAC_SERIAL;
-               if (is_sdvo) {
-                       int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
-                       if (pixel_multiplier > 1) {
-                               if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
-                                       dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-                       }
-                       dpll |= DPLL_DVO_HIGH_SPEED;
-               }
-               if (is_dp)
-                       dpll |= DPLL_DVO_HIGH_SPEED;
-
-               /* compute bitmask from p1 value */
-               if (IS_PINEVIEW(dev))
-                       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
-               else {
-                       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-                       if (IS_G4X(dev) && has_reduced_clock)
-                               dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
-               }
-               switch (clock.p2) {
-               case 5:
-                       dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
-                       break;
-               case 7:
-                       dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
-                       break;
-               case 10:
-                       dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
-                       break;
-               case 14:
-                       dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
-                       break;
-               }
-               if (INTEL_INFO(dev)->gen >= 4)
-                       dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
-       } else {
-               if (is_lvds) {
-                       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-               } else {
-                       if (clock.p1 == 2)
-                               dpll |= PLL_P1_DIVIDE_BY_TWO;
-                       else
-                               dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-                       if (clock.p2 == 4)
-                               dpll |= PLL_P2_DIVIDE_BY_4;
-               }
-       }
-
-       if (is_sdvo && is_tv)
-               dpll |= PLL_REF_INPUT_TVCLKINBC;
-       else if (is_tv)
-               /* XXX: just matching BIOS for now */
-               /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
-               dpll |= 3;
-       else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
-               dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
-       else
-               dpll |= PLL_REF_INPUT_DREFCLK;
-
-       /* setup pipeconf */
-       pipeconf = I915_READ(PIPECONF(pipe));
+       /* setup pipeconf */
+       pipeconf = I915_READ(PIPECONF(pipe));
 
        /* Set up the display plane register */
        dspcntr = DISPPLANE_GAMMA_ENABLE;
 
-       if (pipe == 0)
-               dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
-       else
-               dspcntr |= DISPPLANE_SEL_PIPE_B;
-
-       if (pipe == 0 && INTEL_INFO(dev)->gen < 4) {
-               /* Enable pixel doubling when the dot clock is > 90% of the (display)
-                * core speed.
-                *
-                * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
-                * pipe == 0 check?
-                */
-               if (mode->clock >
-                   dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
-                       pipeconf |= PIPECONF_DOUBLE_WIDE;
-               else
-                       pipeconf &= ~PIPECONF_DOUBLE_WIDE;
-       }
-
-       /* default to 8bpc */
-       pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
-       if (is_dp) {
-               if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
-                       pipeconf |= PIPECONF_BPP_6 |
-                                   PIPECONF_DITHER_EN |
-                                   PIPECONF_DITHER_TYPE_SP;
-               }
-       }
-
-       dpll |= DPLL_VCO_ENABLE;
-
-       DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+       DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
        drm_mode_debug_printmodeline(mode);
 
-       I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
+       /* CPU eDP is the only output that doesn't need a PCH PLL of its own */
+       if (!is_cpu_edp) {
+               struct intel_pch_pll *pll;
 
-       POSTING_READ(DPLL(pipe));
-       udelay(150);
+               pll = intel_get_pch_pll(intel_crtc, dpll, fp);
+               if (pll == NULL) {
+                       DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
+                                        pipe);
+                       return -EINVAL;
+               }
+       } else
+               intel_put_pch_pll(intel_crtc);
 
        /* The LVDS pin pair needs to be on before the DPLLs are enabled.
         * This is an exception to the general rule that mode_set doesn't turn
         * things on.
         */
        if (is_lvds) {
-               temp = I915_READ(LVDS);
+               temp = I915_READ(PCH_LVDS);
                temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-               if (pipe == 1) {
-                       temp |= LVDS_PIPEB_SELECT;
+               if (HAS_PCH_CPT(dev)) {
+                       temp &= ~PORT_TRANS_SEL_MASK;
+                       temp |= PORT_TRANS_SEL_CPT(pipe);
                } else {
-                       temp &= ~LVDS_PIPEB_SELECT;
+                       if (pipe == 1)
+                               temp |= LVDS_PIPEB_SELECT;
+                       else
+                               temp &= ~LVDS_PIPEB_SELECT;
                }
+
                /* set the corresponsding LVDS_BORDER bit */
                temp |= dev_priv->lvds_border_bits;
                /* Set the B0-B3 data pairs corresponding to whether we're going to
@@ -5342,88 +4356,77 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                 * appropriately here, but we need to look more thoroughly into how
                 * panels behave in the two modes.
                 */
-               /* set the dithering flag on LVDS as needed */
-               if (INTEL_INFO(dev)->gen >= 4) {
-                       if (dev_priv->lvds_dither)
-                               temp |= LVDS_ENABLE_DITHER;
-                       else
-                               temp &= ~LVDS_ENABLE_DITHER;
-               }
+               temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
                if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-                       lvds_sync |= LVDS_HSYNC_POLARITY;
+                       temp |= LVDS_HSYNC_POLARITY;
                if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-                       lvds_sync |= LVDS_VSYNC_POLARITY;
-               if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY))
-                   != lvds_sync) {
-                       char flags[2] = "-+";
-                       DRM_INFO("Changing LVDS panel from "
-                                "(%chsync, %cvsync) to (%chsync, %cvsync)\n",
-                                flags[!(temp & LVDS_HSYNC_POLARITY)],
-                                flags[!(temp & LVDS_VSYNC_POLARITY)],
-                                flags[!(lvds_sync & LVDS_HSYNC_POLARITY)],
-                                flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]);
-                       temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
-                       temp |= lvds_sync;
-               }
-               I915_WRITE(LVDS, temp);
+                       temp |= LVDS_VSYNC_POLARITY;
+               I915_WRITE(PCH_LVDS, temp);
        }
 
-       if (is_dp) {
+       pipeconf &= ~PIPECONF_DITHER_EN;
+       pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
+       if ((is_lvds && dev_priv->lvds_dither) || dither) {
+               pipeconf |= PIPECONF_DITHER_EN;
+               pipeconf |= PIPECONF_DITHER_TYPE_SP;
+       }
+       if (is_dp && !is_cpu_edp) {
                intel_dp_set_m_n(crtc, mode, adjusted_mode);
+       } else {
+               /* For non-DP output, clear any trans DP clock recovery setting.*/
+               I915_WRITE(TRANSDATA_M1(pipe), 0);
+               I915_WRITE(TRANSDATA_N1(pipe), 0);
+               I915_WRITE(TRANSDPLINK_M1(pipe), 0);
+               I915_WRITE(TRANSDPLINK_N1(pipe), 0);
        }
 
-       I915_WRITE(DPLL(pipe), dpll);
+       if (intel_crtc->pch_pll) {
+               I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
 
-       /* Wait for the clocks to stabilize. */
-       POSTING_READ(DPLL(pipe));
-       udelay(150);
+               /* Wait for the clocks to stabilize. */
+               POSTING_READ(intel_crtc->pch_pll->pll_reg);
+               udelay(150);
 
-       if (INTEL_INFO(dev)->gen >= 4) {
-               temp = 0;
-               if (is_sdvo) {
-                       temp = intel_mode_get_pixel_multiplier(adjusted_mode);
-                       if (temp > 1)
-                               temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-                       else
-                               temp = 0;
-               }
-               I915_WRITE(DPLL_MD(pipe), temp);
-       } else {
                /* The pixel multiplier can only be updated once the
                 * DPLL is enabled and the clocks are stable.
                 *
                 * So write it again.
                 */
-               I915_WRITE(DPLL(pipe), dpll);
+               I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
        }
 
-       if (HAS_PIPE_CXSR(dev)) {
-               if (intel_crtc->lowfreq_avail) {
-                       DRM_DEBUG_KMS("enabling CxSR downclocking\n");
-                       pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+       intel_crtc->lowfreq_avail = false;
+       if (intel_crtc->pch_pll) {
+               if (is_lvds && has_reduced_clock && i915_powersave) {
+                       I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
+                       intel_crtc->lowfreq_avail = true;
+                       if (HAS_PIPE_CXSR(dev)) {
+                               DRM_DEBUG_KMS("enabling CxSR downclocking\n");
+                               pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
+                       }
                } else {
-                       DRM_DEBUG_KMS("disabling CxSR downclocking\n");
-                       pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+                       I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
+                       if (HAS_PIPE_CXSR(dev)) {
+                               DRM_DEBUG_KMS("disabling CxSR downclocking\n");
+                               pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
+                       }
                }
        }
 
        pipeconf &= ~PIPECONF_INTERLACE_MASK;
-       if (!IS_GEN2(dev) &&
-           adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
-               pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               pipeconf |= PIPECONF_INTERLACED_ILK;
                /* the chip adds 2 halflines automatically */
                adjusted_mode->crtc_vtotal -= 1;
                adjusted_mode->crtc_vblank_end -= 1;
-               vsyncshift = adjusted_mode->crtc_hsync_start
-                            - adjusted_mode->crtc_htotal/2;
+               I915_WRITE(VSYNCSHIFT(pipe),
+                          adjusted_mode->crtc_hsync_start
+                          - adjusted_mode->crtc_htotal/2);
        } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
-               vsyncshift = 0;
+               I915_WRITE(VSYNCSHIFT(pipe), 0);
        }
 
-       if (!IS_GEN3(dev))
-               I915_WRITE(VSYNCSHIFT(pipe), vsyncshift);
-
        I915_WRITE(HTOTAL(pipe),
                   (adjusted_mode->crtc_hdisplay - 1) |
                   ((adjusted_mode->crtc_htotal - 1) << 16));
@@ -5444,25 +4447,27 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                   (adjusted_mode->crtc_vsync_start - 1) |
                   ((adjusted_mode->crtc_vsync_end - 1) << 16));
 
-       /* pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
+       /* pipesrc controls the size that is scaled from, which should
+        * always be the user's requested size.
         */
-       I915_WRITE(DSPSIZE(plane),
-                  ((mode->vdisplay - 1) << 16) |
-                  (mode->hdisplay - 1));
-       I915_WRITE(DSPPOS(plane), 0);
        I915_WRITE(PIPESRC(pipe),
                   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 
+       I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
+       I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
+       I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
+       I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
+
+       if (is_cpu_edp)
+               ironlake_set_pll_edp(crtc, adjusted_mode->clock);
+
        I915_WRITE(PIPECONF(pipe), pipeconf);
        POSTING_READ(PIPECONF(pipe));
-       intel_enable_pipe(dev_priv, pipe, false);
 
        intel_wait_for_vblank(dev, pipe);
 
        I915_WRITE(DSPCNTR(plane), dspcntr);
        POSTING_READ(DSPCNTR(plane));
-       intel_enable_plane(dev_priv, plane, pipe);
 
        ret = intel_pipe_set_base(crtc, x, y, old_fb);
 
@@ -5471,3353 +4476,1942 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        return ret;
 }
 
-/*
- * Initialize reference clocks when the driver loads
- */
-void ironlake_init_pch_refclk(struct drm_device *dev)
+static int intel_crtc_mode_set(struct drm_crtc *crtc,
+                              struct drm_display_mode *mode,
+                              struct drm_display_mode *adjusted_mode,
+                              int x, int y,
+                              struct drm_framebuffer *old_fb)
 {
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct intel_encoder *encoder;
-       u32 temp;
-       bool has_lvds = false;
-       bool has_cpu_edp = false;
-       bool has_pch_edp = false;
-       bool has_panel = false;
-       bool has_ck505 = false;
-       bool can_ssc = false;
-
-       /* We need to take the global config into account */
-       list_for_each_entry(encoder, &mode_config->encoder_list,
-                           base.head) {
-               switch (encoder->type) {
-               case INTEL_OUTPUT_LVDS:
-                       has_panel = true;
-                       has_lvds = true;
-                       break;
-               case INTEL_OUTPUT_EDP:
-                       has_panel = true;
-                       if (intel_encoder_is_pch_edp(&encoder->base))
-                               has_pch_edp = true;
-                       else
-                               has_cpu_edp = true;
-                       break;
-               }
-       }
-
-       if (HAS_PCH_IBX(dev)) {
-               has_ck505 = dev_priv->display_clock_mode;
-               can_ssc = has_ck505;
-       } else {
-               has_ck505 = false;
-               can_ssc = true;
-       }
-
-       DRM_DEBUG_KMS("has_panel %d has_lvds %d has_pch_edp %d has_cpu_edp %d has_ck505 %d\n",
-                     has_panel, has_lvds, has_pch_edp, has_cpu_edp,
-                     has_ck505);
-
-       /* Ironlake: try to setup display ref clock before DPLL
-        * enabling. This is only under driver's control after
-        * PCH B stepping, previous chipset stepping should be
-        * ignoring this setting.
-        */
-       temp = I915_READ(PCH_DREF_CONTROL);
-       /* Always enable nonspread source */
-       temp &= ~DREF_NONSPREAD_SOURCE_MASK;
-
-       if (has_ck505)
-               temp |= DREF_NONSPREAD_CK505_ENABLE;
-       else
-               temp |= DREF_NONSPREAD_SOURCE_ENABLE;
-
-       if (has_panel) {
-               temp &= ~DREF_SSC_SOURCE_MASK;
-               temp |= DREF_SSC_SOURCE_ENABLE;
-
-               /* SSC must be turned on before enabling the CPU output  */
-               if (intel_panel_use_ssc(dev_priv) && can_ssc) {
-                       DRM_DEBUG_KMS("Using SSC on panel\n");
-                       temp |= DREF_SSC1_ENABLE;
-               }
-
-               /* Get SSC going before enabling the outputs */
-               I915_WRITE(PCH_DREF_CONTROL, temp);
-               POSTING_READ(PCH_DREF_CONTROL);
-               udelay(200);
-
-               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-
-               /* Enable CPU source on CPU attached eDP */
-               if (has_cpu_edp) {
-                       if (intel_panel_use_ssc(dev_priv) && can_ssc) {
-                               DRM_DEBUG_KMS("Using SSC on eDP\n");
-                               temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
-                       }
-                       else
-                               temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
-               } else
-                       temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
-
-               I915_WRITE(PCH_DREF_CONTROL, temp);
-               POSTING_READ(PCH_DREF_CONTROL);
-               udelay(200);
-       } else {
-               DRM_DEBUG_KMS("Disabling SSC entirely\n");
-
-               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-
-               /* Turn off CPU output */
-               temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
-
-               I915_WRITE(PCH_DREF_CONTROL, temp);
-               POSTING_READ(PCH_DREF_CONTROL);
-               udelay(200);
-
-               /* Turn off the SSC source */
-               temp &= ~DREF_SSC_SOURCE_MASK;
-               temp |= DREF_SSC_SOURCE_DISABLE;
-
-               /* Turn off SSC1 */
-               temp &= ~ DREF_SSC1_ENABLE;
-
-               I915_WRITE(PCH_DREF_CONTROL, temp);
-               POSTING_READ(PCH_DREF_CONTROL);
-               udelay(200);
-       }
-}
-
-static int ironlake_get_refclk(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_encoder *encoder;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct intel_encoder *edp_encoder = NULL;
-       int num_connectors = 0;
-       bool is_lvds = false;
-
-       list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
-               if (encoder->base.crtc != crtc)
-                       continue;
-
-               switch (encoder->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
-               case INTEL_OUTPUT_EDP:
-                       edp_encoder = encoder;
-                       break;
-               }
-               num_connectors++;
-       }
-
-       if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
-                             dev_priv->lvds_ssc_freq);
-               return dev_priv->lvds_ssc_freq * 1000;
-       }
-
-       return 120000;
-}
-
-static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
-                                 struct drm_display_mode *mode,
-                                 struct drm_display_mode *adjusted_mode,
-                                 int x, int y,
-                                 struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
-       int refclk, num_connectors = 0;
-       intel_clock_t clock, reduced_clock;
-       u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf;
-       bool ok, has_reduced_clock = false, is_sdvo = false;
-       bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
-       struct intel_encoder *has_edp_encoder = NULL;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct intel_encoder *encoder;
-       const intel_limit_t *limit;
-       int ret;
-       struct fdi_m_n m_n = {0};
-       u32 temp;
-       u32 lvds_sync = 0;
-       int target_clock, pixel_multiplier, lane, link_bw, factor;
-       unsigned int pipe_bpp;
-       bool dither;
-
-       list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
-               if (encoder->base.crtc != crtc)
-                       continue;
-
-               switch (encoder->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
-               case INTEL_OUTPUT_SDVO:
-               case INTEL_OUTPUT_HDMI:
-                       is_sdvo = true;
-                       if (encoder->needs_tv_clock)
-                               is_tv = true;
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       is_tv = true;
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       is_crt = true;
-                       break;
-               case INTEL_OUTPUT_DISPLAYPORT:
-                       is_dp = true;
-                       break;
-               case INTEL_OUTPUT_EDP:
-                       has_edp_encoder = encoder;
-                       break;
-               }
-
-               num_connectors++;
-       }
-
-       refclk = ironlake_get_refclk(crtc);
-
-       /*
-        * Returns a set of divisors for the desired target clock with the given
-        * refclk, or FALSE.  The returned values represent the clock equation:
-        * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
-        */
-       limit = intel_limit(crtc, refclk);
-       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
-                            &clock);
-       if (!ok) {
-               DRM_ERROR("Couldn't find PLL settings for mode!\n");
-               return -EINVAL;
-       }
-
-       /* Ensure that the cursor is valid for the new mode before changing... */
-       intel_crtc_update_cursor(crtc, true);
-
-       if (is_lvds && dev_priv->lvds_downclock_avail) {
-               /*
-                * Ensure we match the reduced clock's P to the target clock.
-                * If the clocks don't match, we can't switch the display clock
-                * by using the FP0/FP1. In such case we will disable the LVDS
-                * downclock feature.
-               */
-               has_reduced_clock = limit->find_pll(limit, crtc,
-                                                   dev_priv->lvds_downclock,
-                                                   refclk,
-                                                   &clock,
-                                                   &reduced_clock);
-       }
-       /* SDVO TV has fixed PLL values depend on its clock range,
-          this mirrors vbios setting. */
-       if (is_sdvo && is_tv) {
-               if (adjusted_mode->clock >= 100000
-                   && adjusted_mode->clock < 140500) {
-                       clock.p1 = 2;
-                       clock.p2 = 10;
-                       clock.n = 3;
-                       clock.m1 = 16;
-                       clock.m2 = 8;
-               } else if (adjusted_mode->clock >= 140500
-                          && adjusted_mode->clock <= 200000) {
-                       clock.p1 = 1;
-                       clock.p2 = 10;
-                       clock.n = 6;
-                       clock.m1 = 12;
-                       clock.m2 = 8;
-               }
-       }
-
-       /* FDI link */
-       pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
-       lane = 0;
-       /* CPU eDP doesn't require FDI link, so just set DP M/N
-          according to current link config */
-       if (has_edp_encoder &&
-           !intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-               target_clock = mode->clock;
-               intel_edp_link_config(has_edp_encoder,
-                                     &lane, &link_bw);
-       } else {
-               /* [e]DP over FDI requires target mode clock
-                  instead of link clock */
-               if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base))
-                       target_clock = mode->clock;
-               else
-                       target_clock = adjusted_mode->clock;
-
-               /* FDI is a binary signal running at ~2.7GHz, encoding
-                * each output octet as 10 bits. The actual frequency
-                * is stored as a divider into a 100MHz clock, and the
-                * mode pixel clock is stored in units of 1KHz.
-                * Hence the bw of each lane in terms of the mode signal
-                * is:
-                */
-               link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
-       }
-
-       /* determine panel color depth */
-       temp = I915_READ(PIPECONF(pipe));
-       temp &= ~PIPE_BPC_MASK;
-       dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
-       switch (pipe_bpp) {
-       case 18:
-               temp |= PIPE_6BPC;
-               break;
-       case 24:
-               temp |= PIPE_8BPC;
-               break;
-       case 30:
-               temp |= PIPE_10BPC;
-               break;
-       case 36:
-               temp |= PIPE_12BPC;
-               break;
-       default:
-               WARN(1, "intel_choose_pipe_bpp returned invalid value %d\n",
-                       pipe_bpp);
-               temp |= PIPE_8BPC;
-               pipe_bpp = 24;
-               break;
-       }
-
-       intel_crtc->bpp = pipe_bpp;
-       I915_WRITE(PIPECONF(pipe), temp);
-
-       if (!lane) {
-               /*
-                * Account for spread spectrum to avoid
-                * oversubscribing the link. Max center spread
-                * is 2.5%; use 5% for safety's sake.
-                */
-               u32 bps = target_clock * intel_crtc->bpp * 21 / 20;
-               lane = bps / (link_bw * 8) + 1;
-       }
-
-       intel_crtc->fdi_lanes = lane;
-
-       if (pixel_multiplier > 1)
-               link_bw *= pixel_multiplier;
-       ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
-                            &m_n);
-
-       fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
-       if (has_reduced_clock)
-               fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
-                       reduced_clock.m2;
-
-       /* Enable autotuning of the PLL clock (if permissible) */
-       factor = 21;
-       if (is_lvds) {
-               if ((intel_panel_use_ssc(dev_priv) &&
-                    dev_priv->lvds_ssc_freq == 100) ||
-                   (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
-                       factor = 25;
-       } else if (is_sdvo && is_tv)
-               factor = 20;
-
-       if (clock.m < factor * clock.n)
-               fp |= FP_CB_TUNE;
-
-       dpll = 0;
-
-       if (is_lvds)
-               dpll |= DPLLB_MODE_LVDS;
-       else
-               dpll |= DPLLB_MODE_DAC_SERIAL;
-       if (is_sdvo) {
-               int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
-               if (pixel_multiplier > 1) {
-                       dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
-               }
-               dpll |= DPLL_DVO_HIGH_SPEED;
-       }
-       if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base))
-               dpll |= DPLL_DVO_HIGH_SPEED;
-
-       /* compute bitmask from p1 value */
-       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-       /* also FPA1 */
-       dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
-
-       switch (clock.p2) {
-       case 5:
-               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
-               break;
-       case 7:
-               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
-               break;
-       case 10:
-               dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
-               break;
-       case 14:
-               dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
-               break;
-       }
-
-       if (is_sdvo && is_tv)
-               dpll |= PLL_REF_INPUT_TVCLKINBC;
-       else if (is_tv)
-               /* XXX: just matching BIOS for now */
-               /*      dpll |= PLL_REF_INPUT_TVCLKINBC; */
-               dpll |= 3;
-       else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
-               dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
-       else
-               dpll |= PLL_REF_INPUT_DREFCLK;
-
-       /* setup pipeconf */
-       pipeconf = I915_READ(PIPECONF(pipe));
-
-       /* Set up the display plane register */
-       dspcntr = DISPPLANE_GAMMA_ENABLE;
-
-       DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
-       drm_mode_debug_printmodeline(mode);
-
-       /* PCH eDP needs FDI, but CPU eDP does not */
-       if (!intel_crtc->no_pll) {
-               if (!has_edp_encoder ||
-                   intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-                       I915_WRITE(PCH_FP0(pipe), fp);
-                       I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);
-
-                       POSTING_READ(PCH_DPLL(pipe));
-                       udelay(150);
-               }
-       } else {
-               if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) &&
-                   fp == I915_READ(PCH_FP0(0))) {
-                       intel_crtc->use_pll_a = true;
-                       DRM_DEBUG_KMS("using pipe a dpll\n");
-               } else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) &&
-                          fp == I915_READ(PCH_FP0(1))) {
-                       intel_crtc->use_pll_a = false;
-                       DRM_DEBUG_KMS("using pipe b dpll\n");
-               } else {
-                       DRM_DEBUG_KMS("no matching PLL configuration for pipe 2\n");
-                       return -EINVAL;
-               }
-       }
-
-       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
-        * This is an exception to the general rule that mode_set doesn't turn
-        * things on.
-        */
-       if (is_lvds) {
-               temp = I915_READ(PCH_LVDS);
-               temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-               if (HAS_PCH_CPT(dev)) {
-                       temp &= ~PORT_TRANS_SEL_MASK;
-                       temp |= PORT_TRANS_SEL_CPT(pipe);
-               } else {
-                       if (pipe == 1)
-                               temp |= LVDS_PIPEB_SELECT;
-                       else
-                               temp &= ~LVDS_PIPEB_SELECT;
-               }
-
-               /* set the corresponsding LVDS_BORDER bit */
-               temp |= dev_priv->lvds_border_bits;
-               /* Set the B0-B3 data pairs corresponding to whether we're going to
-                * set the DPLLs for dual-channel mode or not.
-                */
-               if (clock.p2 == 7)
-                       temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-               else
-                       temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
-
-               /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
-                * appropriately here, but we need to look more thoroughly into how
-                * panels behave in the two modes.
-                */
-               if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-                       lvds_sync |= LVDS_HSYNC_POLARITY;
-               if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-                       lvds_sync |= LVDS_VSYNC_POLARITY;
-               if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY))
-                   != lvds_sync) {
-                       char flags[2] = "-+";
-                       DRM_INFO("Changing LVDS panel from "
-                                "(%chsync, %cvsync) to (%chsync, %cvsync)\n",
-                                flags[!(temp & LVDS_HSYNC_POLARITY)],
-                                flags[!(temp & LVDS_VSYNC_POLARITY)],
-                                flags[!(lvds_sync & LVDS_HSYNC_POLARITY)],
-                                flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]);
-                       temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
-                       temp |= lvds_sync;
-               }
-               I915_WRITE(PCH_LVDS, temp);
-       }
-
-       pipeconf &= ~PIPECONF_DITHER_EN;
-       pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
-       if ((is_lvds && dev_priv->lvds_dither) || dither) {
-               pipeconf |= PIPECONF_DITHER_EN;
-               pipeconf |= PIPECONF_DITHER_TYPE_SP;
-       }
-       if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-               intel_dp_set_m_n(crtc, mode, adjusted_mode);
-       } else {
-               /* For non-DP output, clear any trans DP clock recovery setting.*/
-               I915_WRITE(TRANSDATA_M1(pipe), 0);
-               I915_WRITE(TRANSDATA_N1(pipe), 0);
-               I915_WRITE(TRANSDPLINK_M1(pipe), 0);
-               I915_WRITE(TRANSDPLINK_N1(pipe), 0);
-       }
-
-       if (!intel_crtc->no_pll &&
-           (!has_edp_encoder ||
-            intel_encoder_is_pch_edp(&has_edp_encoder->base))) {
-               I915_WRITE(PCH_DPLL(pipe), dpll);
-
-               /* Wait for the clocks to stabilize. */
-               POSTING_READ(PCH_DPLL(pipe));
-               udelay(150);
-
-               /* The pixel multiplier can only be updated once the
-                * DPLL is enabled and the clocks are stable.
-                *
-                * So write it again.
-                */
-               I915_WRITE(PCH_DPLL(pipe), dpll);
-       }
-
-       intel_crtc->lowfreq_avail = false;
-       if (!intel_crtc->no_pll) {
-               if (is_lvds && has_reduced_clock && i915_powersave) {
-                       I915_WRITE(PCH_FP1(pipe), fp2);
-                       intel_crtc->lowfreq_avail = true;
-                       if (HAS_PIPE_CXSR(dev)) {
-                               DRM_DEBUG_KMS("enabling CxSR downclocking\n");
-                               pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
-                       }
-               } else {
-                       I915_WRITE(PCH_FP1(pipe), fp);
-                       if (HAS_PIPE_CXSR(dev)) {
-                               DRM_DEBUG_KMS("disabling CxSR downclocking\n");
-                               pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
-                       }
-               }
-       }
-
-       pipeconf &= ~PIPECONF_INTERLACE_MASK;
-       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
-               pipeconf |= PIPECONF_INTERLACED_ILK;
-               /* the chip adds 2 halflines automatically */
-               adjusted_mode->crtc_vtotal -= 1;
-               adjusted_mode->crtc_vblank_end -= 1;
-               I915_WRITE(VSYNCSHIFT(pipe),
-                          adjusted_mode->crtc_hsync_start
-                          - adjusted_mode->crtc_htotal/2);
-       } else {
-               pipeconf |= PIPECONF_PROGRESSIVE;
-               I915_WRITE(VSYNCSHIFT(pipe), 0);
-       }
-
-       I915_WRITE(HTOTAL(pipe),
-                  (adjusted_mode->crtc_hdisplay - 1) |
-                  ((adjusted_mode->crtc_htotal - 1) << 16));
-       I915_WRITE(HBLANK(pipe),
-                  (adjusted_mode->crtc_hblank_start - 1) |
-                  ((adjusted_mode->crtc_hblank_end - 1) << 16));
-       I915_WRITE(HSYNC(pipe),
-                  (adjusted_mode->crtc_hsync_start - 1) |
-                  ((adjusted_mode->crtc_hsync_end - 1) << 16));
-
-       I915_WRITE(VTOTAL(pipe),
-                  (adjusted_mode->crtc_vdisplay - 1) |
-                  ((adjusted_mode->crtc_vtotal - 1) << 16));
-       I915_WRITE(VBLANK(pipe),
-                  (adjusted_mode->crtc_vblank_start - 1) |
-                  ((adjusted_mode->crtc_vblank_end - 1) << 16));
-       I915_WRITE(VSYNC(pipe),
-                  (adjusted_mode->crtc_vsync_start - 1) |
-                  ((adjusted_mode->crtc_vsync_end - 1) << 16));
-
-       /* pipesrc controls the size that is scaled from, which should
-        * always be the user's requested size.
-        */
-       I915_WRITE(PIPESRC(pipe),
-                  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
-
-       I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
-       I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
-       I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
-       I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
-
-       if (has_edp_encoder &&
-           !intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
-               ironlake_set_pll_edp(crtc, adjusted_mode->clock);
-       }
-
-       I915_WRITE(PIPECONF(pipe), pipeconf);
-       POSTING_READ(PIPECONF(pipe));
-
-       intel_wait_for_vblank(dev, pipe);
-
-       I915_WRITE(DSPCNTR(plane), dspcntr);
-       POSTING_READ(DSPCNTR(plane));
-
-       ret = intel_pipe_set_base(crtc, x, y, old_fb);
-
-       intel_update_watermarks(dev);
-
-       return ret;
-}
-
-static int intel_crtc_mode_set(struct drm_crtc *crtc,
-                              struct drm_display_mode *mode,
-                              struct drm_display_mode *adjusted_mode,
-                              int x, int y,
-                              struct drm_framebuffer *old_fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       int ret;
-
-       drm_vblank_pre_modeset(dev, pipe);
-
-       ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
-                                             x, y, old_fb);
-       drm_vblank_post_modeset(dev, pipe);
-
-       if (ret)
-               intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
-       else
-               intel_crtc->dpms_mode = DRM_MODE_DPMS_ON;
-
-       return ret;
-}
-
-static bool intel_eld_uptodate(struct drm_connector *connector,
-                              int reg_eldv, uint32_t bits_eldv,
-                              int reg_elda, uint32_t bits_elda,
-                              int reg_edid)
-{
-       struct drm_i915_private *dev_priv = connector->dev->dev_private;
-       uint8_t *eld = connector->eld;
-       uint32_t i;
-
-       i = I915_READ(reg_eldv);
-       i &= bits_eldv;
-
-       if (!eld[0])
-               return !i;
-
-       if (!i)
-               return false;
-
-       i = I915_READ(reg_elda);
-       i &= ~bits_elda;
-       I915_WRITE(reg_elda, i);
-
-       for (i = 0; i < eld[2]; i++)
-               if (I915_READ(reg_edid) != *((uint32_t *)eld + i))
-                       return false;
-
-       return true;
-}
-
-static void g4x_write_eld(struct drm_connector *connector,
-                         struct drm_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = connector->dev->dev_private;
-       uint8_t *eld = connector->eld;
-       uint32_t eldv;
-       uint32_t len;
-       uint32_t i;
-
-       i = I915_READ(G4X_AUD_VID_DID);
-
-       if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL)
-               eldv = G4X_ELDV_DEVCL_DEVBLC;
-       else
-               eldv = G4X_ELDV_DEVCTG;
-
-       if (intel_eld_uptodate(connector,
-                              G4X_AUD_CNTL_ST, eldv,
-                              G4X_AUD_CNTL_ST, G4X_ELD_ADDR,
-                              G4X_HDMIW_HDMIEDID))
-               return;
-
-       i = I915_READ(G4X_AUD_CNTL_ST);
-       i &= ~(eldv | G4X_ELD_ADDR);
-       len = (i >> 9) & 0x1f;          /* ELD buffer size */
-       I915_WRITE(G4X_AUD_CNTL_ST, i);
-
-       if (!eld[0])
-               return;
-
-       len = min_t(uint8_t, eld[2], len);
-       DRM_DEBUG_DRIVER("ELD size %d\n", len);
-       for (i = 0; i < len; i++)
-               I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i));
-
-       i = I915_READ(G4X_AUD_CNTL_ST);
-       i |= eldv;
-       I915_WRITE(G4X_AUD_CNTL_ST, i);
-}
-
-static void ironlake_write_eld(struct drm_connector *connector,
-                                    struct drm_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = connector->dev->dev_private;
-       uint8_t *eld = connector->eld;
-       uint32_t eldv;
-       uint32_t i;
-       int len;
-       int hdmiw_hdmiedid;
-       int aud_config;
-       int aud_cntl_st;
-       int aud_cntrl_st2;
-
-       if (HAS_PCH_IBX(connector->dev)) {
-               hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A;
-               aud_config = IBX_AUD_CONFIG_A;
-               aud_cntl_st = IBX_AUD_CNTL_ST_A;
-               aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
-       } else {
-               hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A;
-               aud_config = CPT_AUD_CONFIG_A;
-               aud_cntl_st = CPT_AUD_CNTL_ST_A;
-               aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
-       }
-
-       i = to_intel_crtc(crtc)->pipe;
-       hdmiw_hdmiedid += i * 0x100;
-       aud_cntl_st += i * 0x100;
-       aud_config += i * 0x100;
-
-       DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
-
-       i = I915_READ(aud_cntl_st);
-       i = (i >> 29) & 0x3;            /* DIP_Port_Select, 0x1 = PortB */
-       if (!i) {
-               DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
-               /* operate blindly on all ports */
-               eldv = IBX_ELD_VALIDB;
-               eldv |= IBX_ELD_VALIDB << 4;
-               eldv |= IBX_ELD_VALIDB << 8;
-       } else {
-               DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i);
-               eldv = IBX_ELD_VALIDB << ((i - 1) * 4);
-       }
-
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
-               DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
-               eld[5] |= (1 << 2);     /* Conn_Type, 0x1 = DisplayPort */
-               I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
-       } else
-               I915_WRITE(aud_config, 0);
-
-       if (intel_eld_uptodate(connector,
-                              aud_cntrl_st2, eldv,
-                              aud_cntl_st, IBX_ELD_ADDRESS,
-                              hdmiw_hdmiedid))
-               return;
-
-       i = I915_READ(aud_cntrl_st2);
-       i &= ~eldv;
-       I915_WRITE(aud_cntrl_st2, i);
-
-       if (!eld[0])
-               return;
-
-       i = I915_READ(aud_cntl_st);
-       i &= ~IBX_ELD_ADDRESS;
-       I915_WRITE(aud_cntl_st, i);
-
-       len = min_t(uint8_t, eld[2], 21);       /* 84 bytes of hw ELD buffer */
-       DRM_DEBUG_DRIVER("ELD size %d\n", len);
-       for (i = 0; i < len; i++)
-               I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
-
-       i = I915_READ(aud_cntrl_st2);
-       i |= eldv;
-       I915_WRITE(aud_cntrl_st2, i);
-}
-
-void intel_write_eld(struct drm_encoder *encoder,
-                    struct drm_display_mode *mode)
-{
-       struct drm_crtc *crtc = encoder->crtc;
-       struct drm_connector *connector;
-       struct drm_device *dev = encoder->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       connector = drm_select_eld(encoder, mode);
-       if (!connector)
-               return;
-
-       DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
-                        connector->base.id,
-                        drm_get_connector_name(connector),
-                        connector->encoder->base.id,
-                        drm_get_encoder_name(connector->encoder));
-
-       connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
-
-       if (dev_priv->display.write_eld)
-               dev_priv->display.write_eld(connector, crtc);
-}
-
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-void intel_crtc_load_lut(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int palreg = PALETTE(intel_crtc->pipe);
-       int i;
-
-       /* The clocks have to be on to load the palette. */
-       if (!crtc->enabled || !intel_crtc->active)
-               return;
-
-       /* use legacy palette for Ironlake */
-       if (HAS_PCH_SPLIT(dev))
-               palreg = LGC_PALETTE(intel_crtc->pipe);
-
-       for (i = 0; i < 256; i++) {
-               I915_WRITE(palreg + 4 * i,
-                          (intel_crtc->lut_r[i] << 16) |
-                          (intel_crtc->lut_g[i] << 8) |
-                          intel_crtc->lut_b[i]);
-       }
-}
-
-static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       bool visible = base != 0;
-       u32 cntl;
-
-       if (intel_crtc->cursor_visible == visible)
-               return;
-
-       cntl = I915_READ(_CURACNTR);
-       if (visible) {
-               /* On these chipsets we can only modify the base whilst
-                * the cursor is disabled.
-                */
-               I915_WRITE(_CURABASE, base);
-
-               cntl &= ~(CURSOR_FORMAT_MASK);
-               /* XXX width must be 64, stride 256 => 0x00 << 28 */
-               cntl |= CURSOR_ENABLE |
-                       CURSOR_GAMMA_ENABLE |
-                       CURSOR_FORMAT_ARGB;
-       } else
-               cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
-       I915_WRITE(_CURACNTR, cntl);
-
-       intel_crtc->cursor_visible = visible;
-}
-
-static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       bool visible = base != 0;
-
-       if (intel_crtc->cursor_visible != visible) {
-               uint32_t cntl = I915_READ(CURCNTR(pipe));
-               if (base) {
-                       cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
-                       cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-                       cntl |= pipe << 28; /* Connect to correct pipe */
-               } else {
-                       cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
-                       cntl |= CURSOR_MODE_DISABLE;
-               }
-               I915_WRITE(CURCNTR(pipe), cntl);
-
-               intel_crtc->cursor_visible = visible;
-       }
-       /* and commit changes on next vblank */
-       I915_WRITE(CURBASE(pipe), base);
-}
-
-static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       bool visible = base != 0;
-
-       if (intel_crtc->cursor_visible != visible) {
-               uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
-               if (base) {
-                       cntl &= ~CURSOR_MODE;
-                       cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-               } else {
-                       cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
-                       cntl |= CURSOR_MODE_DISABLE;
-               }
-               I915_WRITE(CURCNTR_IVB(pipe), cntl);
-
-               intel_crtc->cursor_visible = visible;
-       }
-       /* and commit changes on next vblank */
-       I915_WRITE(CURBASE_IVB(pipe), base);
-}
-
-/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
-static void intel_crtc_update_cursor(struct drm_crtc *crtc,
-                                    bool on)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       int x = intel_crtc->cursor_x;
-       int y = intel_crtc->cursor_y;
-       u32 base, pos;
-       bool visible;
-
-       pos = 0;
-
-       if (on && crtc->enabled && crtc->fb) {
-               base = intel_crtc->cursor_addr;
-               if (x > (int) crtc->fb->width)
-                       base = 0;
-
-               if (y > (int) crtc->fb->height)
-                       base = 0;
-       } else
-               base = 0;
-
-       if (x < 0) {
-               if (x + intel_crtc->cursor_width < 0)
-                       base = 0;
-
-               pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
-               x = -x;
-       }
-       pos |= x << CURSOR_X_SHIFT;
-
-       if (y < 0) {
-               if (y + intel_crtc->cursor_height < 0)
-                       base = 0;
-
-               pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
-               y = -y;
-       }
-       pos |= y << CURSOR_Y_SHIFT;
-
-       visible = base != 0;
-       if (!visible && !intel_crtc->cursor_visible)
-               return;
-
-       if (IS_IVYBRIDGE(dev)) {
-               I915_WRITE(CURPOS_IVB(pipe), pos);
-               ivb_update_cursor(crtc, base);
-       } else {
-               I915_WRITE(CURPOS(pipe), pos);
-               if (IS_845G(dev) || IS_I865G(dev))
-                       i845_update_cursor(crtc, base);
-               else
-                       i9xx_update_cursor(crtc, base);
-       }
-
-       if (visible)
-               intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
-}
-
-static int intel_crtc_cursor_set(struct drm_crtc *crtc,
-                                struct drm_file *file,
-                                uint32_t handle,
-                                uint32_t width, uint32_t height)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_i915_gem_object *obj;
-       uint32_t addr;
-       int ret;
-
-       DRM_DEBUG_KMS("\n");
-
-       /* if we want to turn off the cursor ignore width and height */
-       if (!handle) {
-               DRM_DEBUG_KMS("cursor off\n");
-               addr = 0;
-               obj = NULL;
-               mutex_lock(&dev->struct_mutex);
-               goto finish;
-       }
-
-       /* Currently we only support 64x64 cursors */
-       if (width != 64 || height != 64) {
-               DRM_ERROR("we currently only support 64x64 cursors\n");
-               return -EINVAL;
-       }
-
-       obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
-       if (&obj->base == NULL)
-               return -ENOENT;
-
-       if (obj->base.size < width * height * 4) {
-               DRM_ERROR("buffer is to small\n");
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       /* we only need to pin inside GTT if cursor is non-phy */
-       mutex_lock(&dev->struct_mutex);
-       if (!dev_priv->info->cursor_needs_physical) {
-               if (obj->tiling_mode) {
-                       DRM_ERROR("cursor cannot be tiled\n");
-                       ret = -EINVAL;
-                       goto fail_locked;
-               }
-
-               ret = i915_gem_object_pin_to_display_plane(obj, 0, NULL);
-               if (ret) {
-                       DRM_ERROR("failed to move cursor bo into the GTT\n");
-                       goto fail_locked;
-               }
-
-               ret = i915_gem_object_put_fence(obj);
-               if (ret) {
-                       DRM_ERROR("failed to release fence for cursor");
-                       goto fail_unpin;
-               }
-
-               addr = obj->gtt_offset;
-       } else {
-               int align = IS_I830(dev) ? 16 * 1024 : 256;
-               ret = i915_gem_attach_phys_object(dev, obj,
-                                                 (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1,
-                                                 align);
-               if (ret) {
-                       DRM_ERROR("failed to attach phys object\n");
-                       goto fail_locked;
-               }
-               addr = obj->phys_obj->handle->busaddr;
-       }
-
-       if (IS_GEN2(dev))
-               I915_WRITE(CURSIZE, (height << 12) | width);
-
- finish:
-       if (intel_crtc->cursor_bo) {
-               if (dev_priv->info->cursor_needs_physical) {
-                       if (intel_crtc->cursor_bo != obj)
-                               i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
-               } else
-                       i915_gem_object_unpin(intel_crtc->cursor_bo);
-               drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
-       }
-
-       mutex_unlock(&dev->struct_mutex);
-
-       intel_crtc->cursor_addr = addr;
-       intel_crtc->cursor_bo = obj;
-       intel_crtc->cursor_width = width;
-       intel_crtc->cursor_height = height;
-
-       intel_crtc_update_cursor(crtc, true);
-
-       return 0;
-fail_unpin:
-       i915_gem_object_unpin(obj);
-fail_locked:
-       mutex_unlock(&dev->struct_mutex);
-fail:
-       drm_gem_object_unreference_unlocked(&obj->base);
-       return ret;
-}
-
-static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       intel_crtc->cursor_x = x;
-       intel_crtc->cursor_y = y;
-
-       intel_crtc_update_cursor(crtc, true);
-
-       return 0;
-}
-
-/** Sets the color ramps on behalf of RandR */
-void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
-                                u16 blue, int regno)
-{
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       intel_crtc->lut_r[regno] = red >> 8;
-       intel_crtc->lut_g[regno] = green >> 8;
-       intel_crtc->lut_b[regno] = blue >> 8;
-}
-
-void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
-                            u16 *blue, int regno)
-{
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       *red = intel_crtc->lut_r[regno] << 8;
-       *green = intel_crtc->lut_g[regno] << 8;
-       *blue = intel_crtc->lut_b[regno] << 8;
-}
-
-static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-                                u16 *blue, uint32_t start, uint32_t size)
-{
-       int end = (start + size > 256) ? 256 : start + size, i;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       for (i = start; i < end; i++) {
-               intel_crtc->lut_r[i] = red[i] >> 8;
-               intel_crtc->lut_g[i] = green[i] >> 8;
-               intel_crtc->lut_b[i] = blue[i] >> 8;
-       }
-
-       intel_crtc_load_lut(crtc);
-}
-
-/**
- * Get a pipe with a simple mode set on it for doing load-based monitor
- * detection.
- *
- * It will be up to the load-detect code to adjust the pipe as appropriate for
- * its requirements.  The pipe will be connected to no other encoders.
- *
- * Currently this code will only succeed if there is a pipe with no encoders
- * configured for it.  In the future, it could choose to temporarily disable
- * some outputs to free up a pipe for its use.
- *
- * \return crtc, or NULL if no pipes are available.
- */
-
-/* VESA 640x480x72Hz mode to set on the pipe */
-static struct drm_display_mode load_detect_mode = {
-       DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
-                704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
-};
-
-static struct drm_framebuffer *
-intel_framebuffer_create(struct drm_device *dev,
-                        struct drm_mode_fb_cmd2 *mode_cmd,
-                        struct drm_i915_gem_object *obj)
-{
-       struct intel_framebuffer *intel_fb;
-       int ret;
-
-       intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-       if (!intel_fb) {
-               drm_gem_object_unreference_unlocked(&obj->base);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
-       if (ret) {
-               drm_gem_object_unreference_unlocked(&obj->base);
-               kfree(intel_fb);
-               return ERR_PTR(ret);
-       }
-
-       return &intel_fb->base;
-}
-
-static u32
-intel_framebuffer_pitch_for_width(int width, int bpp)
-{
-       u32 pitch = DIV_ROUND_UP(width * bpp, 8);
-       return ALIGN(pitch, 64);
-}
-
-static u32
-intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
-{
-       u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
-       return ALIGN(pitch * mode->vdisplay, PAGE_SIZE);
-}
-
-static struct drm_framebuffer *
-intel_framebuffer_create_for_mode(struct drm_device *dev,
-                                 struct drm_display_mode *mode,
-                                 int depth, int bpp)
-{
-       struct drm_i915_gem_object *obj;
-       struct drm_mode_fb_cmd2 mode_cmd;
-
-       obj = i915_gem_alloc_object(dev,
-                                   intel_framebuffer_size_for_mode(mode, bpp));
-       if (obj == NULL)
-               return ERR_PTR(-ENOMEM);
-
-       mode_cmd.width = mode->hdisplay;
-       mode_cmd.height = mode->vdisplay;
-       mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
-                                                               bpp);
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
-
-       return intel_framebuffer_create(dev, &mode_cmd, obj);
-}
-
-static struct drm_framebuffer *
-mode_fits_in_fbdev(struct drm_device *dev,
-                  struct drm_display_mode *mode)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_gem_object *obj;
-       struct drm_framebuffer *fb;
-
-       if (dev_priv->fbdev == NULL)
-               return NULL;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       int ret;
 
-       obj = dev_priv->fbdev->ifb.obj;
-       if (obj == NULL)
-               return NULL;
+       drm_vblank_pre_modeset(dev, pipe);
 
-       fb = &dev_priv->fbdev->ifb.base;
-       if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
-                                                              fb->bits_per_pixel))
-               return NULL;
+       ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
+                                             x, y, old_fb);
+       drm_vblank_post_modeset(dev, pipe);
 
-       if (obj->base.size < mode->vdisplay * fb->pitches[0])
-               return NULL;
+       if (ret)
+               intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
+       else
+               intel_crtc->dpms_mode = DRM_MODE_DPMS_ON;
 
-       return fb;
+       return ret;
 }
 
-bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
-                               struct drm_connector *connector,
-                               struct drm_display_mode *mode,
-                               struct intel_load_detect_pipe *old)
+static bool intel_eld_uptodate(struct drm_connector *connector,
+                              int reg_eldv, uint32_t bits_eldv,
+                              int reg_elda, uint32_t bits_elda,
+                              int reg_edid)
 {
-       struct intel_crtc *intel_crtc;
-       struct drm_crtc *possible_crtc;
-       struct drm_encoder *encoder = &intel_encoder->base;
-       struct drm_crtc *crtc = NULL;
-       struct drm_device *dev = encoder->dev;
-       struct drm_framebuffer *old_fb;
-       int i = -1;
-
-       DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
-                     connector->base.id, drm_get_connector_name(connector),
-                     encoder->base.id, drm_get_encoder_name(encoder));
-
-       /*
-        * Algorithm gets a little messy:
-        *
-        *   - if the connector already has an assigned crtc, use it (but make
-        *     sure it's on first)
-        *
-        *   - try to find the first unused crtc that can drive this connector,
-        *     and use that if we find one
-        */
-
-       /* See if we already have a CRTC for this connector */
-       if (encoder->crtc) {
-               crtc = encoder->crtc;
-
-               intel_crtc = to_intel_crtc(crtc);
-               old->dpms_mode = intel_crtc->dpms_mode;
-               old->load_detect_temp = false;
-
-               /* Make sure the crtc and connector are running */
-               if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
-                       struct drm_encoder_helper_funcs *encoder_funcs;
-                       struct drm_crtc_helper_funcs *crtc_funcs;
-
-                       crtc_funcs = crtc->helper_private;
-                       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-
-                       encoder_funcs = encoder->helper_private;
-                       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-               }
-
-               return true;
-       }
-
-       /* Find an unused one (if possible) */
-       list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) {
-               i++;
-               if (!(encoder->possible_crtcs & (1 << i)))
-                       continue;
-               if (!possible_crtc->enabled) {
-                       crtc = possible_crtc;
-                       break;
-               }
-       }
-
-       /*
-        * If we didn't find an unused CRTC, don't use any.
-        */
-       if (!crtc) {
-               DRM_DEBUG_KMS("no pipe available for load-detect\n");
-               return false;
-       }
-
-       encoder->crtc = crtc;
-       connector->encoder = encoder;
-
-       intel_crtc = to_intel_crtc(crtc);
-       old->dpms_mode = intel_crtc->dpms_mode;
-       old->load_detect_temp = true;
-       old->release_fb = NULL;
+       struct drm_i915_private *dev_priv = connector->dev->dev_private;
+       uint8_t *eld = connector->eld;
+       uint32_t i;
 
-       if (!mode)
-               mode = &load_detect_mode;
+       i = I915_READ(reg_eldv);
+       i &= bits_eldv;
 
-       old_fb = crtc->fb;
+       if (!eld[0])
+               return !i;
 
-       /* We need a framebuffer large enough to accommodate all accesses
-        * that the plane may generate whilst we perform load detection.
-        * We can not rely on the fbcon either being present (we get called
-        * during its initialisation to detect all boot displays, or it may
-        * not even exist) or that it is large enough to satisfy the
-        * requested mode.
-        */
-       crtc->fb = mode_fits_in_fbdev(dev, mode);
-       if (crtc->fb == NULL) {
-               DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
-               crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
-               old->release_fb = crtc->fb;
-       } else
-               DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
-       if (IS_ERR(crtc->fb)) {
-               DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
-               crtc->fb = old_fb;
+       if (!i)
                return false;
-       }
 
-       if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
-               DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
-               if (old->release_fb)
-                       old->release_fb->funcs->destroy(old->release_fb);
-               crtc->fb = old_fb;
-               return false;
-       }
+       i = I915_READ(reg_elda);
+       i &= ~bits_elda;
+       I915_WRITE(reg_elda, i);
 
-       /* let the connector get through one full cycle before testing */
-       intel_wait_for_vblank(dev, intel_crtc->pipe);
+       for (i = 0; i < eld[2]; i++)
+               if (I915_READ(reg_edid) != *((uint32_t *)eld + i))
+                       return false;
 
        return true;
 }
 
-void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
-                                   struct drm_connector *connector,
-                                   struct intel_load_detect_pipe *old)
+static void g4x_write_eld(struct drm_connector *connector,
+                         struct drm_crtc *crtc)
 {
-       struct drm_encoder *encoder = &intel_encoder->base;
-       struct drm_device *dev = encoder->dev;
-       struct drm_crtc *crtc = encoder->crtc;
-       struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+       struct drm_i915_private *dev_priv = connector->dev->dev_private;
+       uint8_t *eld = connector->eld;
+       uint32_t eldv;
+       uint32_t len;
+       uint32_t i;
 
-       DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
-                     connector->base.id, drm_get_connector_name(connector),
-                     encoder->base.id, drm_get_encoder_name(encoder));
+       i = I915_READ(G4X_AUD_VID_DID);
 
-       if (old->load_detect_temp) {
-               connector->encoder = NULL;
-               drm_helper_disable_unused_functions(dev);
+       if (i == INTEL_AUDIO_DEVBLC || i == INTEL_AUDIO_DEVCL)
+               eldv = G4X_ELDV_DEVCL_DEVBLC;
+       else
+               eldv = G4X_ELDV_DEVCTG;
 
-               if (old->release_fb)
-                       old->release_fb->funcs->destroy(old->release_fb);
+       if (intel_eld_uptodate(connector,
+                              G4X_AUD_CNTL_ST, eldv,
+                              G4X_AUD_CNTL_ST, G4X_ELD_ADDR,
+                              G4X_HDMIW_HDMIEDID))
+               return;
+
+       i = I915_READ(G4X_AUD_CNTL_ST);
+       i &= ~(eldv | G4X_ELD_ADDR);
+       len = (i >> 9) & 0x1f;          /* ELD buffer size */
+       I915_WRITE(G4X_AUD_CNTL_ST, i);
 
+       if (!eld[0])
                return;
-       }
 
-       /* Switch crtc and encoder back off if necessary */
-       if (old->dpms_mode != DRM_MODE_DPMS_ON) {
-               encoder_funcs->dpms(encoder, old->dpms_mode);
-               crtc_funcs->dpms(crtc, old->dpms_mode);
-       }
+       len = min_t(uint8_t, eld[2], len);
+       DRM_DEBUG_DRIVER("ELD size %d\n", len);
+       for (i = 0; i < len; i++)
+               I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i));
+
+       i = I915_READ(G4X_AUD_CNTL_ST);
+       i |= eldv;
+       I915_WRITE(G4X_AUD_CNTL_ST, i);
 }
 
-/* Returns the clock of the currently programmed mode of the given pipe. */
-static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
+static void ironlake_write_eld(struct drm_connector *connector,
+                                    struct drm_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       u32 dpll = I915_READ(DPLL(pipe));
-       u32 fp;
-       intel_clock_t clock;
-
-       if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-               fp = I915_READ(FP0(pipe));
-       else
-               fp = I915_READ(FP1(pipe));
+       struct drm_i915_private *dev_priv = connector->dev->dev_private;
+       uint8_t *eld = connector->eld;
+       uint32_t eldv;
+       uint32_t i;
+       int len;
+       int hdmiw_hdmiedid;
+       int aud_config;
+       int aud_cntl_st;
+       int aud_cntrl_st2;
 
-       clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
-       if (IS_PINEVIEW(dev)) {
-               clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
-               clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT;
+       if (HAS_PCH_IBX(connector->dev)) {
+               hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A;
+               aud_config = IBX_AUD_CONFIG_A;
+               aud_cntl_st = IBX_AUD_CNTL_ST_A;
+               aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
        } else {
-               clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
-               clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
+               hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A;
+               aud_config = CPT_AUD_CONFIG_A;
+               aud_cntl_st = CPT_AUD_CNTL_ST_A;
+               aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
        }
 
-       if (!IS_GEN2(dev)) {
-               if (IS_PINEVIEW(dev))
-                       clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >>
-                               DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW);
-               else
-                       clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
-                              DPLL_FPA01_P1_POST_DIV_SHIFT);
+       i = to_intel_crtc(crtc)->pipe;
+       hdmiw_hdmiedid += i * 0x100;
+       aud_cntl_st += i * 0x100;
+       aud_config += i * 0x100;
 
-               switch (dpll & DPLL_MODE_MASK) {
-               case DPLLB_MODE_DAC_SERIAL:
-                       clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ?
-                               5 : 10;
-                       break;
-               case DPLLB_MODE_LVDS:
-                       clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ?
-                               7 : 14;
-                       break;
-               default:
-                       DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed "
-                                 "mode\n", (int)(dpll & DPLL_MODE_MASK));
-                       return 0;
-               }
+       DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
 
-               /* XXX: Handle the 100Mhz refclk */
-               intel_clock(dev, 96000, &clock);
+       i = I915_READ(aud_cntl_st);
+       i = (i >> 29) & 0x3;            /* DIP_Port_Select, 0x1 = PortB */
+       if (!i) {
+               DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
+               /* operate blindly on all ports */
+               eldv = IBX_ELD_VALIDB;
+               eldv |= IBX_ELD_VALIDB << 4;
+               eldv |= IBX_ELD_VALIDB << 8;
        } else {
-               bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
+               DRM_DEBUG_DRIVER("ELD on port %c\n", 'A' + i);
+               eldv = IBX_ELD_VALIDB << ((i - 1) * 4);
+       }
 
-               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 (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+               DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
+               eld[5] |= (1 << 2);     /* Conn_Type, 0x1 = DisplayPort */
+               I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
+       } else
+               I915_WRITE(aud_config, 0);
 
-                       if ((dpll & PLL_REF_INPUT_MASK) ==
-                           PLLB_REF_INPUT_SPREADSPECTRUMIN) {
-                               /* XXX: might not be 66MHz */
-                               intel_clock(dev, 66000, &clock);
-                       } else
-                               intel_clock(dev, 48000, &clock);
-               } else {
-                       if (dpll & PLL_P1_DIVIDE_BY_TWO)
-                               clock.p1 = 2;
-                       else {
-                               clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
-                                           DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
-                       }
-                       if (dpll & PLL_P2_DIVIDE_BY_4)
-                               clock.p2 = 4;
-                       else
-                               clock.p2 = 2;
+       if (intel_eld_uptodate(connector,
+                              aud_cntrl_st2, eldv,
+                              aud_cntl_st, IBX_ELD_ADDRESS,
+                              hdmiw_hdmiedid))
+               return;
 
-                       intel_clock(dev, 48000, &clock);
-               }
-       }
+       i = I915_READ(aud_cntrl_st2);
+       i &= ~eldv;
+       I915_WRITE(aud_cntrl_st2, i);
 
-       /* XXX: It would be nice to validate the clocks, but we can't reuse
-        * i830PllIsValid() because it relies on the xf86_config connector
-        * configuration being accurate, which it isn't necessarily.
-        */
+       if (!eld[0])
+               return;
 
-       return clock.dot;
+       i = I915_READ(aud_cntl_st);
+       i &= ~IBX_ELD_ADDRESS;
+       I915_WRITE(aud_cntl_st, i);
+
+       len = min_t(uint8_t, eld[2], 21);       /* 84 bytes of hw ELD buffer */
+       DRM_DEBUG_DRIVER("ELD size %d\n", len);
+       for (i = 0; i < len; i++)
+               I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
+
+       i = I915_READ(aud_cntrl_st2);
+       i |= eldv;
+       I915_WRITE(aud_cntrl_st2, i);
 }
 
-/** Returns the currently programmed mode of the given pipe. */
-struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
-                                            struct drm_crtc *crtc)
+void intel_write_eld(struct drm_encoder *encoder,
+                    struct drm_display_mode *mode)
 {
+       struct drm_crtc *crtc = encoder->crtc;
+       struct drm_connector *connector;
+       struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       struct drm_display_mode *mode;
-       int htot = I915_READ(HTOTAL(pipe));
-       int hsync = I915_READ(HSYNC(pipe));
-       int vtot = I915_READ(VTOTAL(pipe));
-       int vsync = I915_READ(VSYNC(pipe));
 
-       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
-       if (!mode)
-               return NULL;
+       connector = drm_select_eld(encoder, mode);
+       if (!connector)
+               return;
 
-       mode->clock = intel_crtc_clock_get(dev, crtc);
-       mode->hdisplay = (htot & 0xffff) + 1;
-       mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
-       mode->hsync_start = (hsync & 0xffff) + 1;
-       mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
-       mode->vdisplay = (vtot & 0xffff) + 1;
-       mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
-       mode->vsync_start = (vsync & 0xffff) + 1;
-       mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
+       DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+                        connector->base.id,
+                        drm_get_connector_name(connector),
+                        connector->encoder->base.id,
+                        drm_get_encoder_name(connector->encoder));
 
-       drm_mode_set_name(mode);
-       drm_mode_set_crtcinfo(mode, 0);
+       connector->eld[6] = drm_av_sync_delay(connector, mode) / 2;
 
-       return mode;
+       if (dev_priv->display.write_eld)
+               dev_priv->display.write_eld(connector, crtc);
 }
 
-#define GPU_IDLE_TIMEOUT 500 /* ms */
-
-/* When this timer fires, we've been idle for awhile */
-static void intel_gpu_idle_timer(unsigned long arg)
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void intel_crtc_load_lut(struct drm_crtc *crtc)
 {
-       struct drm_device *dev = (struct drm_device *)arg;
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int palreg = PALETTE(intel_crtc->pipe);
+       int i;
 
-       if (!list_empty(&dev_priv->mm.active_list)) {
-               /* Still processing requests, so just re-arm the timer. */
-               mod_timer(&dev_priv->idle_timer, jiffies +
-                         msecs_to_jiffies(GPU_IDLE_TIMEOUT));
+       /* The clocks have to be on to load the palette. */
+       if (!crtc->enabled || !intel_crtc->active)
                return;
-       }
 
-       dev_priv->busy = false;
-       queue_work(dev_priv->wq, &dev_priv->idle_work);
-}
+       /* use legacy palette for Ironlake */
+       if (HAS_PCH_SPLIT(dev))
+               palreg = LGC_PALETTE(intel_crtc->pipe);
 
-#define CRTC_IDLE_TIMEOUT 1000 /* ms */
+       for (i = 0; i < 256; i++) {
+               I915_WRITE(palreg + 4 * i,
+                          (intel_crtc->lut_r[i] << 16) |
+                          (intel_crtc->lut_g[i] << 8) |
+                          intel_crtc->lut_b[i]);
+       }
+}
 
-static void intel_crtc_idle_timer(unsigned long arg)
+static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
 {
-       struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
-       struct drm_crtc *crtc = &intel_crtc->base;
-       drm_i915_private_t *dev_priv = crtc->dev->dev_private;
-       struct intel_framebuffer *intel_fb;
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       bool visible = base != 0;
+       u32 cntl;
 
-       intel_fb = to_intel_framebuffer(crtc->fb);
-       if (intel_fb && intel_fb->obj->active) {
-               /* The framebuffer is still being accessed by the GPU. */
-               mod_timer(&intel_crtc->idle_timer, jiffies +
-                         msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
+       if (intel_crtc->cursor_visible == visible)
                return;
-       }
 
-       intel_crtc->busy = false;
-       queue_work(dev_priv->wq, &dev_priv->idle_work);
+       cntl = I915_READ(_CURACNTR);
+       if (visible) {
+               /* On these chipsets we can only modify the base whilst
+                * the cursor is disabled.
+                */
+               I915_WRITE(_CURABASE, base);
+
+               cntl &= ~(CURSOR_FORMAT_MASK);
+               /* XXX width must be 64, stride 256 => 0x00 << 28 */
+               cntl |= CURSOR_ENABLE |
+                       CURSOR_GAMMA_ENABLE |
+                       CURSOR_FORMAT_ARGB;
+       } else
+               cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
+       I915_WRITE(_CURACNTR, cntl);
+
+       intel_crtc->cursor_visible = visible;
 }
 
-static void intel_increase_pllclock(struct drm_crtc *crtc)
+static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
 {
        struct drm_device *dev = crtc->dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       int dpll_reg = DPLL(pipe);
-       int dpll;
-
-       if (HAS_PCH_SPLIT(dev))
-               return;
+       bool visible = base != 0;
 
-       if (!dev_priv->lvds_downclock_avail)
-               return;
+       if (intel_crtc->cursor_visible != visible) {
+               uint32_t cntl = I915_READ(CURCNTR(pipe));
+               if (base) {
+                       cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
+                       cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+                       cntl |= pipe << 28; /* Connect to correct pipe */
+               } else {
+                       cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+                       cntl |= CURSOR_MODE_DISABLE;
+               }
+               I915_WRITE(CURCNTR(pipe), cntl);
 
-       dpll = I915_READ(dpll_reg);
-       if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
-               DRM_DEBUG_DRIVER("upclocking LVDS\n");
+               intel_crtc->cursor_visible = visible;
+       }
+       /* and commit changes on next vblank */
+       I915_WRITE(CURBASE(pipe), base);
+}
 
-               assert_panel_unlocked(dev_priv, pipe);
+static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       bool visible = base != 0;
 
-               dpll &= ~DISPLAY_RATE_SELECT_FPA1;
-               I915_WRITE(dpll_reg, dpll);
-               intel_wait_for_vblank(dev, pipe);
+       if (intel_crtc->cursor_visible != visible) {
+               uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
+               if (base) {
+                       cntl &= ~CURSOR_MODE;
+                       cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+               } else {
+                       cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+                       cntl |= CURSOR_MODE_DISABLE;
+               }
+               I915_WRITE(CURCNTR_IVB(pipe), cntl);
 
-               dpll = I915_READ(dpll_reg);
-               if (dpll & DISPLAY_RATE_SELECT_FPA1)
-                       DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
+               intel_crtc->cursor_visible = visible;
        }
-
-       /* Schedule downclock */
-       mod_timer(&intel_crtc->idle_timer, jiffies +
-                 msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
+       /* and commit changes on next vblank */
+       I915_WRITE(CURBASE_IVB(pipe), base);
 }
 
-static void intel_decrease_pllclock(struct drm_crtc *crtc)
+/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
+static void intel_crtc_update_cursor(struct drm_crtc *crtc,
+                                    bool on)
 {
        struct drm_device *dev = crtc->dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       int dpll_reg = DPLL(pipe);
-       int dpll = I915_READ(dpll_reg);
+       int x = intel_crtc->cursor_x;
+       int y = intel_crtc->cursor_y;
+       u32 base, pos;
+       bool visible;
 
-       if (HAS_PCH_SPLIT(dev))
-               return;
+       pos = 0;
 
-       if (!dev_priv->lvds_downclock_avail)
-               return;
+       if (on && crtc->enabled && crtc->fb) {
+               base = intel_crtc->cursor_addr;
+               if (x > (int) crtc->fb->width)
+                       base = 0;
 
-       /*
-        * Since this is called by a timer, we should never get here in
-        * the manual case.
-        */
-       if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
-               DRM_DEBUG_DRIVER("downclocking LVDS\n");
+               if (y > (int) crtc->fb->height)
+                       base = 0;
+       } else
+               base = 0;
 
-               assert_panel_unlocked(dev_priv, pipe);
+       if (x < 0) {
+               if (x + intel_crtc->cursor_width < 0)
+                       base = 0;
 
-               dpll |= DISPLAY_RATE_SELECT_FPA1;
-               I915_WRITE(dpll_reg, dpll);
-               intel_wait_for_vblank(dev, pipe);
-               dpll = I915_READ(dpll_reg);
-               if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
-                       DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
+               pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
+               x = -x;
        }
+       pos |= x << CURSOR_X_SHIFT;
 
-}
+       if (y < 0) {
+               if (y + intel_crtc->cursor_height < 0)
+                       base = 0;
 
-/**
- * intel_idle_update - adjust clocks for idleness
- * @work: work struct
- *
- * Either the GPU or display (or both) went idle.  Check the busy status
- * here and adjust the CRTC and GPU clocks as necessary.
- */
-static void intel_idle_update(struct work_struct *work)
-{
-       drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
-                                                   idle_work);
-       struct drm_device *dev = dev_priv->dev;
-       struct drm_crtc *crtc;
-       struct intel_crtc *intel_crtc;
+               pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
+               y = -y;
+       }
+       pos |= y << CURSOR_Y_SHIFT;
 
-       if (!i915_powersave)
+       visible = base != 0;
+       if (!visible && !intel_crtc->cursor_visible)
                return;
 
-       mutex_lock(&dev->struct_mutex);
+       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
+               I915_WRITE(CURPOS_IVB(pipe), pos);
+               ivb_update_cursor(crtc, base);
+       } else {
+               I915_WRITE(CURPOS(pipe), pos);
+               if (IS_845G(dev) || IS_I865G(dev))
+                       i845_update_cursor(crtc, base);
+               else
+                       i9xx_update_cursor(crtc, base);
+       }
+}
 
-       i915_update_gfx_val(dev_priv);
+static int intel_crtc_cursor_set(struct drm_crtc *crtc,
+                                struct drm_file *file,
+                                uint32_t handle,
+                                uint32_t width, uint32_t height)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_i915_gem_object *obj;
+       uint32_t addr;
+       int ret;
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               /* Skip inactive CRTCs */
-               if (!crtc->fb)
-                       continue;
+       DRM_DEBUG_KMS("\n");
 
-               intel_crtc = to_intel_crtc(crtc);
-               if (!intel_crtc->busy)
-                       intel_decrease_pllclock(crtc);
+       /* if we want to turn off the cursor ignore width and height */
+       if (!handle) {
+               DRM_DEBUG_KMS("cursor off\n");
+               addr = 0;
+               obj = NULL;
+               mutex_lock(&dev->struct_mutex);
+               goto finish;
        }
 
+       /* Currently we only support 64x64 cursors */
+       if (width != 64 || height != 64) {
+               DRM_ERROR("we currently only support 64x64 cursors\n");
+               return -EINVAL;
+       }
 
-       mutex_unlock(&dev->struct_mutex);
-}
+       obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
+       if (&obj->base == NULL)
+               return -ENOENT;
 
-/**
- * intel_mark_busy - mark the GPU and possibly the display busy
- * @dev: drm device
- * @obj: object we're operating on
- *
- * Callers can use this function to indicate that the GPU is busy processing
- * commands.  If @obj matches one of the CRTC objects (i.e. it's a scanout
- * buffer), we'll also mark the display as busy, so we know to increase its
- * clock frequency.
- */
-void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = NULL;
-       struct intel_framebuffer *intel_fb;
-       struct intel_crtc *intel_crtc;
+       if (obj->base.size < width * height * 4) {
+               DRM_ERROR("buffer is to small\n");
+               ret = -ENOMEM;
+               goto fail;
+       }
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return;
+       /* we only need to pin inside GTT if cursor is non-phy */
+       mutex_lock(&dev->struct_mutex);
+       if (!dev_priv->info->cursor_needs_physical) {
+               if (obj->tiling_mode) {
+                       DRM_ERROR("cursor cannot be tiled\n");
+                       ret = -EINVAL;
+                       goto fail_locked;
+               }
 
-       if (!dev_priv->busy)
-               dev_priv->busy = true;
-       else
-               mod_timer(&dev_priv->idle_timer, jiffies +
-                         msecs_to_jiffies(GPU_IDLE_TIMEOUT));
+               ret = i915_gem_object_pin_to_display_plane(obj, 0, NULL);
+               if (ret) {
+                       DRM_ERROR("failed to move cursor bo into the GTT\n");
+                       goto fail_locked;
+               }
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (!crtc->fb)
-                       continue;
+               ret = i915_gem_object_put_fence(obj);
+               if (ret) {
+                       DRM_ERROR("failed to release fence for cursor");
+                       goto fail_unpin;
+               }
 
-               intel_crtc = to_intel_crtc(crtc);
-               intel_fb = to_intel_framebuffer(crtc->fb);
-               if (intel_fb->obj == obj) {
-                       if (!intel_crtc->busy) {
-                               /* Non-busy -> busy, upclock */
-                               intel_increase_pllclock(crtc);
-                               intel_crtc->busy = true;
-                       } else {
-                               /* Busy -> busy, put off timer */
-                               mod_timer(&intel_crtc->idle_timer, jiffies +
-                                         msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
-                       }
+               addr = obj->gtt_offset;
+       } else {
+               int align = IS_I830(dev) ? 16 * 1024 : 256;
+               ret = i915_gem_attach_phys_object(dev, obj,
+                                                 (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1,
+                                                 align);
+               if (ret) {
+                       DRM_ERROR("failed to attach phys object\n");
+                       goto fail_locked;
                }
+               addr = obj->phys_obj->handle->busaddr;
        }
-}
-
-static void intel_crtc_destroy(struct drm_crtc *crtc)
-{
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct intel_unpin_work *work;
-       unsigned long flags;
 
-       spin_lock_irqsave(&dev->event_lock, flags);
-       work = intel_crtc->unpin_work;
-       intel_crtc->unpin_work = NULL;
-       spin_unlock_irqrestore(&dev->event_lock, flags);
+       if (IS_GEN2(dev))
+               I915_WRITE(CURSIZE, (height << 12) | width);
 
-       if (work) {
-               cancel_work_sync(&work->work);
-               kfree(work);
+ finish:
+       if (intel_crtc->cursor_bo) {
+               if (dev_priv->info->cursor_needs_physical) {
+                       if (intel_crtc->cursor_bo != obj)
+                               i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
+               } else
+                       i915_gem_object_unpin(intel_crtc->cursor_bo);
+               drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
        }
 
-       drm_crtc_cleanup(crtc);
-
-       kfree(intel_crtc);
-}
+       mutex_unlock(&dev->struct_mutex);
 
-static void intel_unpin_work_fn(struct work_struct *__work)
-{
-       struct intel_unpin_work *work =
-               container_of(__work, struct intel_unpin_work, work);
+       intel_crtc->cursor_addr = addr;
+       intel_crtc->cursor_bo = obj;
+       intel_crtc->cursor_width = width;
+       intel_crtc->cursor_height = height;
 
-       mutex_lock(&work->dev->struct_mutex);
-       intel_unpin_fb_obj(work->old_fb_obj);
-       drm_gem_object_unreference(&work->pending_flip_obj->base);
-       drm_gem_object_unreference(&work->old_fb_obj->base);
+       intel_crtc_update_cursor(crtc, true);
 
-       intel_update_fbc(work->dev);
-       mutex_unlock(&work->dev->struct_mutex);
-       kfree(work);
+       return 0;
+fail_unpin:
+       i915_gem_object_unpin(obj);
+fail_locked:
+       mutex_unlock(&dev->struct_mutex);
+fail:
+       drm_gem_object_unreference_unlocked(&obj->base);
+       return ret;
 }
 
-static void do_intel_finish_page_flip(struct drm_device *dev,
-                                     struct drm_crtc *crtc)
+static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_unpin_work *work;
-       struct drm_i915_gem_object *obj;
-       struct drm_pending_vblank_event *e;
-       struct timeval tnow, tvbl;
-       unsigned long flags;
 
-       /* Ignore early vblank irqs */
-       if (intel_crtc == NULL)
-               return;
+       intel_crtc->cursor_x = x;
+       intel_crtc->cursor_y = y;
 
-       do_gettimeofday(&tnow);
+       intel_crtc_update_cursor(crtc, true);
 
-       spin_lock_irqsave(&dev->event_lock, flags);
-       work = intel_crtc->unpin_work;
-       if (work == NULL || !work->pending) {
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               return;
-       }
+       return 0;
+}
 
-       intel_crtc->unpin_work = NULL;
+/** Sets the color ramps on behalf of RandR */
+void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+                                u16 blue, int regno)
+{
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       if (work->event) {
-               e = work->event;
-               e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl);
+       intel_crtc->lut_r[regno] = red >> 8;
+       intel_crtc->lut_g[regno] = green >> 8;
+       intel_crtc->lut_b[regno] = blue >> 8;
+}
 
-               /* Called before vblank count and timestamps have
-                * been updated for the vblank interval of flip
-                * completion? Need to increment vblank count and
-                * add one videorefresh duration to returned timestamp
-                * to account for this. We assume this happened if we
-                * get called over 0.9 frame durations after the last
-                * timestamped vblank.
-                *
-                * This calculation can not be used with vrefresh rates
-                * below 5Hz (10Hz to be on the safe side) without
-                * promoting to 64 integers.
-                */
-               if (10 * (timeval_to_ns(&tnow) - timeval_to_ns(&tvbl)) >
-                   9 * crtc->framedur_ns) {
-                       e->event.sequence++;
-                       tvbl = ns_to_timeval(timeval_to_ns(&tvbl) +
-                                            crtc->framedur_ns);
-               }
+void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                            u16 *blue, int regno)
+{
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-               e->event.tv_sec = tvbl.tv_sec;
-               e->event.tv_usec = tvbl.tv_usec;
+       *red = intel_crtc->lut_r[regno] << 8;
+       *green = intel_crtc->lut_g[regno] << 8;
+       *blue = intel_crtc->lut_b[regno] << 8;
+}
 
-               list_add_tail(&e->base.link,
-                             &e->base.file_priv->event_list);
-               wake_up_interruptible(&e->base.file_priv->event_wait);
+static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
+                                u16 *blue, uint32_t start, uint32_t size)
+{
+       int end = (start + size > 256) ? 256 : start + size, i;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       for (i = start; i < end; i++) {
+               intel_crtc->lut_r[i] = red[i] >> 8;
+               intel_crtc->lut_g[i] = green[i] >> 8;
+               intel_crtc->lut_b[i] = blue[i] >> 8;
        }
 
-       drm_vblank_put(dev, intel_crtc->pipe);
+       intel_crtc_load_lut(crtc);
+}
 
-       spin_unlock_irqrestore(&dev->event_lock, flags);
+/**
+ * Get a pipe with a simple mode set on it for doing load-based monitor
+ * detection.
+ *
+ * It will be up to the load-detect code to adjust the pipe as appropriate for
+ * its requirements.  The pipe will be connected to no other encoders.
+ *
+ * Currently this code will only succeed if there is a pipe with no encoders
+ * configured for it.  In the future, it could choose to temporarily disable
+ * some outputs to free up a pipe for its use.
+ *
+ * \return crtc, or NULL if no pipes are available.
+ */
 
-       obj = work->old_fb_obj;
+/* VESA 640x480x72Hz mode to set on the pipe */
+static struct drm_display_mode load_detect_mode = {
+       DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
+                704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
+};
 
-       atomic_clear_mask(1 << intel_crtc->plane,
-                         &obj->pending_flip.counter);
-       if (atomic_read(&obj->pending_flip) == 0)
-               wake_up(&dev_priv->pending_flip_queue);
+static struct drm_framebuffer *
+intel_framebuffer_create(struct drm_device *dev,
+                        struct drm_mode_fb_cmd2 *mode_cmd,
+                        struct drm_i915_gem_object *obj)
+{
+       struct intel_framebuffer *intel_fb;
+       int ret;
 
-       schedule_work(&work->work);
+       intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
+       if (!intel_fb) {
+               drm_gem_object_unreference_unlocked(&obj->base);
+               return ERR_PTR(-ENOMEM);
+       }
 
-       trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
+       ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
+       if (ret) {
+               drm_gem_object_unreference_unlocked(&obj->base);
+               kfree(intel_fb);
+               return ERR_PTR(ret);
+       }
+
+       return &intel_fb->base;
 }
 
-void intel_finish_page_flip(struct drm_device *dev, int pipe)
+static u32
+intel_framebuffer_pitch_for_width(int width, int bpp)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-
-       do_intel_finish_page_flip(dev, crtc);
+       u32 pitch = DIV_ROUND_UP(width * bpp, 8);
+       return ALIGN(pitch, 64);
 }
 
-void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
+static u32
+intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
-
-       do_intel_finish_page_flip(dev, crtc);
+       u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
+       return ALIGN(pitch * mode->vdisplay, PAGE_SIZE);
 }
 
-void intel_prepare_page_flip(struct drm_device *dev, int plane)
+static struct drm_framebuffer *
+intel_framebuffer_create_for_mode(struct drm_device *dev,
+                                 struct drm_display_mode *mode,
+                                 int depth, int bpp)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc =
-               to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
-       unsigned long flags;
+       struct drm_i915_gem_object *obj;
+       struct drm_mode_fb_cmd2 mode_cmd;
 
-       spin_lock_irqsave(&dev->event_lock, flags);
-       if (intel_crtc->unpin_work) {
-               if ((++intel_crtc->unpin_work->pending) > 1)
-                       DRM_ERROR("Prepared flip multiple times\n");
-       } else {
-               DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
-       }
-       spin_unlock_irqrestore(&dev->event_lock, flags);
+       obj = i915_gem_alloc_object(dev,
+                                   intel_framebuffer_size_for_mode(mode, bpp));
+       if (obj == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       mode_cmd.width = mode->hdisplay;
+       mode_cmd.height = mode->vdisplay;
+       mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
+                                                               bpp);
+       mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
+
+       return intel_framebuffer_create(dev, &mode_cmd, obj);
 }
 
-static int intel_gen2_queue_flip(struct drm_device *dev,
-                                struct drm_crtc *crtc,
-                                struct drm_framebuffer *fb,
-                                struct drm_i915_gem_object *obj)
+static struct drm_framebuffer *
+mode_fits_in_fbdev(struct drm_device *dev,
+                  struct drm_display_mode *mode)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       unsigned long offset;
-       u32 flip_mask;
-       int ret;
+       struct drm_i915_gem_object *obj;
+       struct drm_framebuffer *fb;
 
-       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
-       if (ret)
-               goto out;
+       if (dev_priv->fbdev == NULL)
+               return NULL;
 
-       /* Offset into the new buffer for cases of shared fbs between CRTCs */
-       offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
+       obj = dev_priv->fbdev->ifb.obj;
+       if (obj == NULL)
+               return NULL;
 
-       ret = BEGIN_LP_RING(6);
-       if (ret)
-               goto out;
+       fb = &dev_priv->fbdev->ifb.base;
+       if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
+                                                              fb->bits_per_pixel))
+               return NULL;
 
-       /* Can't queue multiple flips, so wait for the previous
-        * one to finish before executing the next.
-        */
-       if (intel_crtc->plane)
-               flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
-       else
-               flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-       OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
-       OUT_RING(MI_NOOP);
-       OUT_RING(MI_DISPLAY_FLIP |
-                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       OUT_RING(fb->pitches[0]);
-       OUT_RING(obj->gtt_offset + offset);
-       OUT_RING(0); /* aux display base address, unused */
-       ADVANCE_LP_RING();
-out:
-       return ret;
+       if (obj->base.size < mode->vdisplay * fb->pitches[0])
+               return NULL;
+
+       return fb;
 }
 
-static int intel_gen3_queue_flip(struct drm_device *dev,
-                                struct drm_crtc *crtc,
-                                struct drm_framebuffer *fb,
-                                struct drm_i915_gem_object *obj)
+bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
+                               struct drm_connector *connector,
+                               struct drm_display_mode *mode,
+                               struct intel_load_detect_pipe *old)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       unsigned long offset;
-       u32 flip_mask;
-       int ret;
+       struct intel_crtc *intel_crtc;
+       struct drm_crtc *possible_crtc;
+       struct drm_encoder *encoder = &intel_encoder->base;
+       struct drm_crtc *crtc = NULL;
+       struct drm_device *dev = encoder->dev;
+       struct drm_framebuffer *old_fb;
+       int i = -1;
 
-       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
-       if (ret)
-               goto out;
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+                     connector->base.id, drm_get_connector_name(connector),
+                     encoder->base.id, drm_get_encoder_name(encoder));
 
-       /* Offset into the new buffer for cases of shared fbs between CRTCs */
-       offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
+       /*
+        * Algorithm gets a little messy:
+        *
+        *   - if the connector already has an assigned crtc, use it (but make
+        *     sure it's on first)
+        *
+        *   - try to find the first unused crtc that can drive this connector,
+        *     and use that if we find one
+        */
+
+       /* See if we already have a CRTC for this connector */
+       if (encoder->crtc) {
+               crtc = encoder->crtc;
+
+               intel_crtc = to_intel_crtc(crtc);
+               old->dpms_mode = intel_crtc->dpms_mode;
+               old->load_detect_temp = false;
 
-       ret = BEGIN_LP_RING(6);
-       if (ret)
-               goto out;
+               /* Make sure the crtc and connector are running */
+               if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
+                       struct drm_encoder_helper_funcs *encoder_funcs;
+                       struct drm_crtc_helper_funcs *crtc_funcs;
 
-       if (intel_crtc->plane)
-               flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
-       else
-               flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-       OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
-       OUT_RING(MI_NOOP);
-       OUT_RING(MI_DISPLAY_FLIP_I915 |
-                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       OUT_RING(fb->pitches[0]);
-       OUT_RING(obj->gtt_offset + offset);
-       OUT_RING(MI_NOOP);
-
-       ADVANCE_LP_RING();
-out:
-       return ret;
-}
+                       crtc_funcs = crtc->helper_private;
+                       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
 
-static int intel_gen4_queue_flip(struct drm_device *dev,
-                                struct drm_crtc *crtc,
-                                struct drm_framebuffer *fb,
-                                struct drm_i915_gem_object *obj)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       uint32_t pf, pipesrc;
-       int ret;
+                       encoder_funcs = encoder->helper_private;
+                       encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+               }
 
-       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
-       if (ret)
-               goto out;
+               return true;
+       }
 
-       ret = BEGIN_LP_RING(4);
-       if (ret)
-               goto out;
+       /* Find an unused one (if possible) */
+       list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) {
+               i++;
+               if (!(encoder->possible_crtcs & (1 << i)))
+                       continue;
+               if (!possible_crtc->enabled) {
+                       crtc = possible_crtc;
+                       break;
+               }
+       }
 
-       /* i965+ uses the linear or tiled offsets from the
-        * Display Registers (which do not change across a page-flip)
-        * so we need only reprogram the base address.
+       /*
+        * If we didn't find an unused CRTC, don't use any.
         */
-       OUT_RING(MI_DISPLAY_FLIP |
-                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       OUT_RING(fb->pitches[0]);
-       OUT_RING(obj->gtt_offset | obj->tiling_mode);
+       if (!crtc) {
+               DRM_DEBUG_KMS("no pipe available for load-detect\n");
+               return false;
+       }
 
-       /* XXX Enabling the panel-fitter across page-flip is so far
-        * untested on non-native modes, so ignore it for now.
-        * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
-        */
-       pf = 0;
-       pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
-       OUT_RING(pf | pipesrc);
-       ADVANCE_LP_RING();
-out:
-       return ret;
-}
+       encoder->crtc = crtc;
+       connector->encoder = encoder;
 
-static int intel_gen6_queue_flip(struct drm_device *dev,
-                                struct drm_crtc *crtc,
-                                struct drm_framebuffer *fb,
-                                struct drm_i915_gem_object *obj)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       uint32_t pf, pipesrc;
-       int ret;
+       intel_crtc = to_intel_crtc(crtc);
+       old->dpms_mode = intel_crtc->dpms_mode;
+       old->load_detect_temp = true;
+       old->release_fb = NULL;
 
-       ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv));
-       if (ret)
-               goto out;
+       if (!mode)
+               mode = &load_detect_mode;
 
-       ret = BEGIN_LP_RING(4);
-       if (ret)
-               goto out;
+       old_fb = crtc->fb;
+
+       /* We need a framebuffer large enough to accommodate all accesses
+        * that the plane may generate whilst we perform load detection.
+        * We can not rely on the fbcon either being present (we get called
+        * during its initialisation to detect all boot displays, or it may
+        * not even exist) or that it is large enough to satisfy the
+        * requested mode.
+        */
+       crtc->fb = mode_fits_in_fbdev(dev, mode);
+       if (crtc->fb == NULL) {
+               DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
+               crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
+               old->release_fb = crtc->fb;
+       } else
+               DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
+       if (IS_ERR(crtc->fb)) {
+               DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
+               crtc->fb = old_fb;
+               return false;
+       }
+
+       if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
+               DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
+               if (old->release_fb)
+                       old->release_fb->funcs->destroy(old->release_fb);
+               crtc->fb = old_fb;
+               return false;
+       }
 
-       OUT_RING(MI_DISPLAY_FLIP |
-                MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-       OUT_RING(fb->pitches[0] | obj->tiling_mode);
-       OUT_RING(obj->gtt_offset);
+       /* let the connector get through one full cycle before testing */
+       intel_wait_for_vblank(dev, intel_crtc->pipe);
 
-       pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
-       pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
-       OUT_RING(pf | pipesrc);
-       ADVANCE_LP_RING();
-out:
-       return ret;
+       return true;
 }
 
-/*
- * On gen7 we currently use the blit ring because (in early silicon at least)
- * the render ring doesn't give us interrpts for page flip completion, which
- * means clients will hang after the first flip is queued.  Fortunately the
- * blit ring generates interrupts properly, so use it instead.
- */
-static int intel_gen7_queue_flip(struct drm_device *dev,
-                                struct drm_crtc *crtc,
-                                struct drm_framebuffer *fb,
-                                struct drm_i915_gem_object *obj)
+void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
+                                   struct drm_connector *connector,
+                                   struct intel_load_detect_pipe *old)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
-       int ret;
+       struct drm_encoder *encoder = &intel_encoder->base;
+       struct drm_device *dev = encoder->dev;
+       struct drm_crtc *crtc = encoder->crtc;
+       struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 
-       ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
-       if (ret)
-               goto out;
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
+                     connector->base.id, drm_get_connector_name(connector),
+                     encoder->base.id, drm_get_encoder_name(encoder));
 
-       ret = intel_ring_begin(ring, 4);
-       if (ret)
-               goto out;
+       if (old->load_detect_temp) {
+               connector->encoder = NULL;
+               drm_helper_disable_unused_functions(dev);
 
-       intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19));
-       intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
-       intel_ring_emit(ring, (obj->gtt_offset));
-       intel_ring_emit(ring, (MI_NOOP));
-       intel_ring_advance(ring);
-out:
-       return ret;
-}
+               if (old->release_fb)
+                       old->release_fb->funcs->destroy(old->release_fb);
 
-static int intel_default_queue_flip(struct drm_device *dev,
-                                   struct drm_crtc *crtc,
-                                   struct drm_framebuffer *fb,
-                                   struct drm_i915_gem_object *obj)
-{
-       return -ENODEV;
+               return;
+       }
+
+       /* Switch crtc and encoder back off if necessary */
+       if (old->dpms_mode != DRM_MODE_DPMS_ON) {
+               encoder_funcs->dpms(encoder, old->dpms_mode);
+               crtc_funcs->dpms(crtc, old->dpms_mode);
+       }
 }
 
-static int intel_crtc_page_flip(struct drm_crtc *crtc,
-                               struct drm_framebuffer *fb,
-                               struct drm_pending_vblank_event *event)
+/* Returns the clock of the currently programmed mode of the given pipe. */
+static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
 {
-       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_framebuffer *intel_fb;
-       struct drm_i915_gem_object *obj;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_unpin_work *work;
-       unsigned long flags;
-       int ret;
+       int pipe = intel_crtc->pipe;
+       u32 dpll = I915_READ(DPLL(pipe));
+       u32 fp;
+       intel_clock_t clock;
 
-       work = kzalloc(sizeof *work, GFP_KERNEL);
-       if (work == NULL)
-               return -ENOMEM;
+       if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+               fp = I915_READ(FP0(pipe));
+       else
+               fp = I915_READ(FP1(pipe));
 
-       work->event = event;
-       work->dev = crtc->dev;
-       intel_fb = to_intel_framebuffer(crtc->fb);
-       work->old_fb_obj = intel_fb->obj;
-       INIT_WORK(&work->work, intel_unpin_work_fn);
+       clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
+       if (IS_PINEVIEW(dev)) {
+               clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
+               clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT;
+       } else {
+               clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
+               clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
+       }
 
-       ret = drm_vblank_get(dev, intel_crtc->pipe);
-       if (ret)
-               goto free_work;
+       if (!IS_GEN2(dev)) {
+               if (IS_PINEVIEW(dev))
+                       clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >>
+                               DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW);
+               else
+                       clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
+                              DPLL_FPA01_P1_POST_DIV_SHIFT);
 
-       /* We borrow the event spin lock for protecting unpin_work */
-       spin_lock_irqsave(&dev->event_lock, flags);
-       if (intel_crtc->unpin_work) {
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               kfree(work);
-               drm_vblank_put(dev, intel_crtc->pipe);
+               switch (dpll & DPLL_MODE_MASK) {
+               case DPLLB_MODE_DAC_SERIAL:
+                       clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ?
+                               5 : 10;
+                       break;
+               case DPLLB_MODE_LVDS:
+                       clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ?
+                               7 : 14;
+                       break;
+               default:
+                       DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed "
+                                 "mode\n", (int)(dpll & DPLL_MODE_MASK));
+                       return 0;
+               }
+
+               /* XXX: Handle the 100Mhz refclk */
+               intel_clock(dev, 96000, &clock);
+       } else {
+               bool is_lvds = (pipe == 1) && (I915_READ(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 ((dpll & PLL_REF_INPUT_MASK) ==
+                           PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+                               /* XXX: might not be 66MHz */
+                               intel_clock(dev, 66000, &clock);
+                       } else
+                               intel_clock(dev, 48000, &clock);
+               } else {
+                       if (dpll & PLL_P1_DIVIDE_BY_TWO)
+                               clock.p1 = 2;
+                       else {
+                               clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+                                           DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+                       }
+                       if (dpll & PLL_P2_DIVIDE_BY_4)
+                               clock.p2 = 4;
+                       else
+                               clock.p2 = 2;
 
-               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
-               return -EBUSY;
+                       intel_clock(dev, 48000, &clock);
+               }
        }
-       intel_crtc->unpin_work = work;
-       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       intel_fb = to_intel_framebuffer(fb);
-       obj = intel_fb->obj;
+       /* XXX: It would be nice to validate the clocks, but we can't reuse
+        * i830PllIsValid() because it relies on the xf86_config connector
+        * configuration being accurate, which it isn't necessarily.
+        */
 
-       mutex_lock(&dev->struct_mutex);
+       return clock.dot;
+}
 
-       /* Reference the objects for the scheduled work. */
-       drm_gem_object_reference(&work->old_fb_obj->base);
-       drm_gem_object_reference(&obj->base);
+/** Returns the currently programmed mode of the given pipe. */
+struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
+                                            struct drm_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       struct drm_display_mode *mode;
+       int htot = I915_READ(HTOTAL(pipe));
+       int hsync = I915_READ(HSYNC(pipe));
+       int vtot = I915_READ(VTOTAL(pipe));
+       int vsync = I915_READ(VSYNC(pipe));
 
-       crtc->fb = fb;
+       mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+       if (!mode)
+               return NULL;
 
-       work->pending_flip_obj = obj;
+       mode->clock = intel_crtc_clock_get(dev, crtc);
+       mode->hdisplay = (htot & 0xffff) + 1;
+       mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
+       mode->hsync_start = (hsync & 0xffff) + 1;
+       mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
+       mode->vdisplay = (vtot & 0xffff) + 1;
+       mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
+       mode->vsync_start = (vsync & 0xffff) + 1;
+       mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
 
-       work->enable_stall_check = true;
+       drm_mode_set_name(mode);
 
-       /* Block clients from rendering to the new back buffer until
-        * the flip occurs and the object is no longer visible.
-        */
-       atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
+       return mode;
+}
 
-       ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
-       if (ret)
-               goto cleanup_pending;
+#define GPU_IDLE_TIMEOUT 500 /* ms */
 
-       intel_disable_fbc(dev);
-       mutex_unlock(&dev->struct_mutex);
+/* When this timer fires, we've been idle for awhile */
+static void intel_gpu_idle_timer(unsigned long arg)
+{
+       struct drm_device *dev = (struct drm_device *)arg;
+       drm_i915_private_t *dev_priv = dev->dev_private;
 
-       trace_i915_flip_request(intel_crtc->plane, obj);
+       if (!list_empty(&dev_priv->mm.active_list)) {
+               /* Still processing requests, so just re-arm the timer. */
+               mod_timer(&dev_priv->idle_timer, jiffies +
+                         msecs_to_jiffies(GPU_IDLE_TIMEOUT));
+               return;
+       }
 
-       return 0;
+       dev_priv->busy = false;
+       queue_work(dev_priv->wq, &dev_priv->idle_work);
+}
 
-cleanup_pending:
-       atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
-       drm_gem_object_unreference(&work->old_fb_obj->base);
-       drm_gem_object_unreference(&obj->base);
-       mutex_unlock(&dev->struct_mutex);
+#define CRTC_IDLE_TIMEOUT 1000 /* ms */
 
-       spin_lock_irqsave(&dev->event_lock, flags);
-       intel_crtc->unpin_work = NULL;
-       spin_unlock_irqrestore(&dev->event_lock, flags);
+static void intel_crtc_idle_timer(unsigned long arg)
+{
+       struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
+       struct drm_crtc *crtc = &intel_crtc->base;
+       drm_i915_private_t *dev_priv = crtc->dev->dev_private;
+       struct intel_framebuffer *intel_fb;
 
-       drm_vblank_put(dev, intel_crtc->pipe);
-free_work:
-       kfree(work);
+       intel_fb = to_intel_framebuffer(crtc->fb);
+       if (intel_fb && intel_fb->obj->active) {
+               /* The framebuffer is still being accessed by the GPU. */
+               mod_timer(&intel_crtc->idle_timer, jiffies +
+                         msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
+               return;
+       }
 
-       return ret;
+       intel_crtc->busy = false;
+       queue_work(dev_priv->wq, &dev_priv->idle_work);
 }
 
-static void intel_sanitize_modesetting(struct drm_device *dev,
-                                      int pipe, int plane)
+static void intel_increase_pllclock(struct drm_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 reg, val;
+       struct drm_device *dev = crtc->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int pipe = intel_crtc->pipe;
+       int dpll_reg = DPLL(pipe);
+       int dpll;
 
        if (HAS_PCH_SPLIT(dev))
                return;
 
-       /* Who knows what state these registers were left in by the BIOS or
-        * grub?
-        *
-        * If we leave the registers in a conflicting state (e.g. with the
-        * display plane reading from the other pipe than the one we intend
-        * to use) then when we attempt to teardown the active mode, we will
-        * not disable the pipes and planes in the correct order -- leaving
-        * a plane reading from a disabled pipe and possibly leading to
-        * undefined behaviour.
-        */
+       if (!dev_priv->lvds_downclock_avail)
+               return;
 
-       reg = DSPCNTR(plane);
-       val = I915_READ(reg);
+       dpll = I915_READ(dpll_reg);
+       if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
+               DRM_DEBUG_DRIVER("upclocking LVDS\n");
 
-       if ((val & DISPLAY_PLANE_ENABLE) == 0)
-               return;
-       if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
-               return;
+               assert_panel_unlocked(dev_priv, pipe);
 
-       /* This display plane is active and attached to the other CPU pipe. */
-       pipe = !pipe;
+               dpll &= ~DISPLAY_RATE_SELECT_FPA1;
+               I915_WRITE(dpll_reg, dpll);
+               intel_wait_for_vblank(dev, pipe);
 
-       /* Disable the plane and wait for it to stop reading from the pipe. */
-       intel_disable_plane(dev_priv, plane, pipe);
-       intel_disable_pipe(dev_priv, pipe);
+               dpll = I915_READ(dpll_reg);
+               if (dpll & DISPLAY_RATE_SELECT_FPA1)
+                       DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
+       }
+
+       /* Schedule downclock */
+       mod_timer(&intel_crtc->idle_timer, jiffies +
+                 msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
 }
 
-static void intel_crtc_reset(struct drm_crtc *crtc)
+static void intel_decrease_pllclock(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       /* Reset flags back to the 'unknown' status so that they
-        * will be correctly set on the initial modeset.
-        */
-       intel_crtc->dpms_mode = -1;
+       if (HAS_PCH_SPLIT(dev))
+               return;
 
-       /* We need to fix up any BIOS configuration that conflicts with
-        * our expectations.
+       if (!dev_priv->lvds_downclock_avail)
+               return;
+
+       /*
+        * Since this is called by a timer, we should never get here in
+        * the manual case.
         */
-       intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
-}
+       if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
+               int pipe = intel_crtc->pipe;
+               int dpll_reg = DPLL(pipe);
+               int dpll;
 
-static struct drm_crtc_helper_funcs intel_helper_funcs = {
-       .dpms = intel_crtc_dpms,
-       .mode_fixup = intel_crtc_mode_fixup,
-       .mode_set = intel_crtc_mode_set,
-       .mode_set_base = intel_pipe_set_base,
-       .mode_set_base_atomic = intel_pipe_set_base_atomic,
-       .load_lut = intel_crtc_load_lut,
-       .disable = intel_crtc_disable,
-};
+               DRM_DEBUG_DRIVER("downclocking LVDS\n");
 
-static const struct drm_crtc_funcs intel_crtc_funcs = {
-       .reset = intel_crtc_reset,
-       .cursor_set = intel_crtc_cursor_set,
-       .cursor_move = intel_crtc_cursor_move,
-       .gamma_set = intel_crtc_gamma_set,
-       .set_config = drm_crtc_helper_set_config,
-       .destroy = intel_crtc_destroy,
-       .page_flip = intel_crtc_page_flip,
-};
+               assert_panel_unlocked(dev_priv, pipe);
 
-static void intel_crtc_init(struct drm_device *dev, int pipe)
+               dpll = I915_READ(dpll_reg);
+               dpll |= DISPLAY_RATE_SELECT_FPA1;
+               I915_WRITE(dpll_reg, dpll);
+               intel_wait_for_vblank(dev, pipe);
+               dpll = I915_READ(dpll_reg);
+               if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
+                       DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
+       }
+
+}
+
+/**
+ * intel_idle_update - adjust clocks for idleness
+ * @work: work struct
+ *
+ * Either the GPU or display (or both) went idle.  Check the busy status
+ * here and adjust the CRTC and GPU clocks as necessary.
+ */
+static void intel_idle_update(struct work_struct *work)
 {
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
+                                                   idle_work);
+       struct drm_device *dev = dev_priv->dev;
+       struct drm_crtc *crtc;
        struct intel_crtc *intel_crtc;
-       int i;
 
-       intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
-       if (intel_crtc == NULL)
+       if (!i915_powersave)
                return;
 
-       drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
-
-       drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
-       for (i = 0; i < 256; i++) {
-               intel_crtc->lut_r[i] = i;
-               intel_crtc->lut_g[i] = i;
-               intel_crtc->lut_b[i] = i;
-       }
-
-       /* Swap pipes & planes for FBC on pre-965 */
-       intel_crtc->pipe = pipe;
-       intel_crtc->plane = pipe;
-       if (IS_MOBILE(dev) && IS_GEN3(dev)) {
-               DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
-               intel_crtc->plane = !pipe;
-       }
-
-       BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
-              dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
-       dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
-       dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
+       mutex_lock(&dev->struct_mutex);
 
-       intel_crtc_reset(&intel_crtc->base);
-       intel_crtc->active = true; /* force the pipe off on setup_init_config */
-       intel_crtc->bpp = 24; /* default for pre-Ironlake */
+       i915_update_gfx_val(dev_priv);
 
-       if (HAS_PCH_SPLIT(dev)) {
-               if (pipe == 2 && IS_IVYBRIDGE(dev))
-                       intel_crtc->no_pll = true;
-               intel_helper_funcs.prepare = ironlake_crtc_prepare;
-               intel_helper_funcs.commit = ironlake_crtc_commit;
-       } else {
-               intel_helper_funcs.prepare = i9xx_crtc_prepare;
-               intel_helper_funcs.commit = i9xx_crtc_commit;
-       }
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               /* Skip inactive CRTCs */
+               if (!crtc->fb)
+                       continue;
 
-       drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
+               intel_crtc = to_intel_crtc(crtc);
+               if (!intel_crtc->busy)
+                       intel_decrease_pllclock(crtc);
+       }
 
-       intel_crtc->busy = false;
 
-       setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
-                   (unsigned long)intel_crtc);
+       mutex_unlock(&dev->struct_mutex);
 }
 
-int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
-                               struct drm_file *file)
+/**
+ * intel_mark_busy - mark the GPU and possibly the display busy
+ * @dev: drm device
+ * @obj: object we're operating on
+ *
+ * Callers can use this function to indicate that the GPU is busy processing
+ * commands.  If @obj matches one of the CRTC objects (i.e. it's a scanout
+ * buffer), we'll also mark the display as busy, so we know to increase its
+ * clock frequency.
+ */
+void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
-       struct drm_mode_object *drmmode_obj;
-       struct intel_crtc *crtc;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
+       struct drm_crtc *crtc = NULL;
+       struct intel_framebuffer *intel_fb;
+       struct intel_crtc *intel_crtc;
 
-       drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
-                       DRM_MODE_OBJECT_CRTC);
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
 
-       if (!drmmode_obj) {
-               DRM_ERROR("no such CRTC id\n");
-               return -EINVAL;
-       }
+       if (!dev_priv->busy) {
+               intel_sanitize_pm(dev);
+               dev_priv->busy = true;
+       } else
+               mod_timer(&dev_priv->idle_timer, jiffies +
+                         msecs_to_jiffies(GPU_IDLE_TIMEOUT));
 
-       crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
-       pipe_from_crtc_id->pipe = crtc->pipe;
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               if (!crtc->fb)
+                       continue;
 
-       return 0;
+               intel_crtc = to_intel_crtc(crtc);
+               intel_fb = to_intel_framebuffer(crtc->fb);
+               if (intel_fb->obj == obj) {
+                       if (!intel_crtc->busy) {
+                               /* Non-busy -> busy, upclock */
+                               intel_increase_pllclock(crtc);
+                               intel_crtc->busy = true;
+                       } else {
+                               /* Busy -> busy, put off timer */
+                               mod_timer(&intel_crtc->idle_timer, jiffies +
+                                         msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
+                       }
+               }
+       }
 }
 
-static int intel_encoder_clones(struct drm_device *dev, int type_mask)
+static void intel_crtc_destroy(struct drm_crtc *crtc)
 {
-       struct intel_encoder *encoder;
-       int index_mask = 0;
-       int entry = 0;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct intel_unpin_work *work;
+       unsigned long flags;
 
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-               if (type_mask & encoder->clone_mask)
-                       index_mask |= (1 << entry);
-               entry++;
+       spin_lock_irqsave(&dev->event_lock, flags);
+       work = intel_crtc->unpin_work;
+       intel_crtc->unpin_work = NULL;
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+
+       if (work) {
+               cancel_work_sync(&work->work);
+               kfree(work);
        }
 
-       return index_mask;
+       drm_crtc_cleanup(crtc);
+
+       kfree(intel_crtc);
 }
 
-static bool has_edp_a(struct drm_device *dev)
+static void intel_unpin_work_fn(struct work_struct *__work)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (!IS_MOBILE(dev))
-               return false;
-
-       if ((I915_READ(DP_A) & DP_DETECTED) == 0)
-               return false;
+       struct intel_unpin_work *work =
+               container_of(__work, struct intel_unpin_work, work);
 
-       if (IS_GEN5(dev) &&
-           (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
-               return false;
+       mutex_lock(&work->dev->struct_mutex);
+       intel_unpin_fb_obj(work->old_fb_obj);
+       drm_gem_object_unreference(&work->pending_flip_obj->base);
+       drm_gem_object_unreference(&work->old_fb_obj->base);
 
-       return true;
+       intel_update_fbc(work->dev);
+       mutex_unlock(&work->dev->struct_mutex);
+       kfree(work);
 }
 
-static void intel_setup_outputs(struct drm_device *dev)
+static void do_intel_finish_page_flip(struct drm_device *dev,
+                                     struct drm_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_encoder *encoder;
-       bool dpd_is_edp = false;
-       bool has_lvds;
-
-       has_lvds = intel_lvds_init(dev);
-       if (!has_lvds && !HAS_PCH_SPLIT(dev)) {
-               /* disable the panel fitter on everything but LVDS */
-               I915_WRITE(PFIT_CONTROL, 0);
-       }
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_unpin_work *work;
+       struct drm_i915_gem_object *obj;
+       struct drm_pending_vblank_event *e;
+       struct timeval tnow, tvbl;
+       unsigned long flags;
 
-       if (HAS_PCH_SPLIT(dev)) {
-               dpd_is_edp = intel_dpd_is_edp(dev);
+       /* Ignore early vblank irqs */
+       if (intel_crtc == NULL)
+               return;
 
-               if (has_edp_a(dev))
-                       intel_dp_init(dev, DP_A);
+       do_gettimeofday(&tnow);
 
-               if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
-                       intel_dp_init(dev, PCH_DP_D);
+       spin_lock_irqsave(&dev->event_lock, flags);
+       work = intel_crtc->unpin_work;
+       if (work == NULL || !work->pending) {
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+               return;
        }
 
-       intel_crt_init(dev);
+       intel_crtc->unpin_work = NULL;
 
-       if (HAS_PCH_SPLIT(dev)) {
-               int found;
+       if (work->event) {
+               e = work->event;
+               e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl);
 
-               if (I915_READ(HDMIB) & PORT_DETECTED) {
-                       /* PCH SDVOB multiplex with HDMIB */
-                       found = intel_sdvo_init(dev, PCH_SDVOB);
-                       if (!found)
-                               intel_hdmi_init(dev, HDMIB);
-                       if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
-                               intel_dp_init(dev, PCH_DP_B);
+               /* Called before vblank count and timestamps have
+                * been updated for the vblank interval of flip
+                * completion? Need to increment vblank count and
+                * add one videorefresh duration to returned timestamp
+                * to account for this. We assume this happened if we
+                * get called over 0.9 frame durations after the last
+                * timestamped vblank.
+                *
+                * This calculation can not be used with vrefresh rates
+                * below 5Hz (10Hz to be on the safe side) without
+                * promoting to 64 integers.
+                */
+               if (10 * (timeval_to_ns(&tnow) - timeval_to_ns(&tvbl)) >
+                   9 * crtc->framedur_ns) {
+                       e->event.sequence++;
+                       tvbl = ns_to_timeval(timeval_to_ns(&tvbl) +
+                                            crtc->framedur_ns);
                }
 
-               if (I915_READ(HDMIC) & PORT_DETECTED)
-                       intel_hdmi_init(dev, HDMIC);
+               e->event.tv_sec = tvbl.tv_sec;
+               e->event.tv_usec = tvbl.tv_usec;
 
-               if (I915_READ(HDMID) & PORT_DETECTED)
-                       intel_hdmi_init(dev, HDMID);
+               list_add_tail(&e->base.link,
+                             &e->base.file_priv->event_list);
+               wake_up_interruptible(&e->base.file_priv->event_wait);
+       }
 
-               if (I915_READ(PCH_DP_C) & DP_DETECTED)
-                       intel_dp_init(dev, PCH_DP_C);
+       drm_vblank_put(dev, intel_crtc->pipe);
 
-               if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
-                       intel_dp_init(dev, PCH_DP_D);
+       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
-               bool found = false;
+       obj = work->old_fb_obj;
 
-               if (I915_READ(SDVOB) & SDVO_DETECTED) {
-                       DRM_DEBUG_KMS("probing SDVOB\n");
-                       found = intel_sdvo_init(dev, SDVOB);
-                       if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
-                               DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
-                               intel_hdmi_init(dev, SDVOB);
-                       }
+       atomic_clear_mask(1 << intel_crtc->plane,
+                         &obj->pending_flip.counter);
+       if (atomic_read(&obj->pending_flip) == 0)
+               wake_up(&dev_priv->pending_flip_queue);
 
-                       if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
-                               DRM_DEBUG_KMS("probing DP_B\n");
-                               intel_dp_init(dev, DP_B);
-                       }
-               }
+       schedule_work(&work->work);
 
-               /* Before G4X SDVOC doesn't have its own detect register */
+       trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
+}
 
-               if (I915_READ(SDVOB) & SDVO_DETECTED) {
-                       DRM_DEBUG_KMS("probing SDVOC\n");
-                       found = intel_sdvo_init(dev, SDVOC);
-               }
+void intel_finish_page_flip(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
 
-               if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
+       do_intel_finish_page_flip(dev, crtc);
+}
 
-                       if (SUPPORTS_INTEGRATED_HDMI(dev)) {
-                               DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
-                               intel_hdmi_init(dev, SDVOC);
-                       }
-                       if (SUPPORTS_INTEGRATED_DP(dev)) {
-                               DRM_DEBUG_KMS("probing DP_C\n");
-                               intel_dp_init(dev, DP_C);
-                       }
-               }
+void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
 
-               if (SUPPORTS_INTEGRATED_DP(dev) &&
-                   (I915_READ(DP_D) & DP_DETECTED)) {
-                       DRM_DEBUG_KMS("probing DP_D\n");
-                       intel_dp_init(dev, DP_D);
-               }
-       } else if (IS_GEN2(dev))
-               intel_dvo_init(dev);
+       do_intel_finish_page_flip(dev, crtc);
+}
 
-       if (SUPPORTS_TV(dev))
-               intel_tv_init(dev);
+void intel_prepare_page_flip(struct drm_device *dev, int plane)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc =
+               to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
+       unsigned long flags;
 
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-               encoder->base.possible_crtcs = encoder->crtc_mask;
-               encoder->base.possible_clones =
-                       intel_encoder_clones(dev, encoder->clone_mask);
+       spin_lock_irqsave(&dev->event_lock, flags);
+       if (intel_crtc->unpin_work) {
+               if ((++intel_crtc->unpin_work->pending) > 1)
+                       DRM_ERROR("Prepared flip multiple times\n");
+       } else {
+               DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
        }
-
-       /* disable all the possible outputs/crtcs before entering KMS mode */
-       drm_helper_disable_unused_functions(dev);
-
-       if (HAS_PCH_SPLIT(dev))
-               ironlake_init_pch_refclk(dev);
+       spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
+static int intel_gen2_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
 {
-       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       unsigned long offset;
+       u32 flip_mask;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+       int ret;
 
-       drm_framebuffer_cleanup(fb);
-       drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
+       ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
+       if (ret)
+               goto err;
 
-       kfree(intel_fb);
-}
+       /* Offset into the new buffer for cases of shared fbs between CRTCs */
+       offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
 
-static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-                                               struct drm_file *file,
-                                               unsigned int *handle)
-{
-       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-       struct drm_i915_gem_object *obj = intel_fb->obj;
+       ret = intel_ring_begin(ring, 6);
+       if (ret)
+               goto err_unpin;
 
-       return drm_gem_handle_create(file, &obj->base, handle);
-}
+       /* Can't queue multiple flips, so wait for the previous
+        * one to finish before executing the next.
+        */
+       if (intel_crtc->plane)
+               flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+       else
+               flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
+       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_emit(ring, MI_DISPLAY_FLIP |
+                       MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+       intel_ring_emit(ring, fb->pitches[0]);
+       intel_ring_emit(ring, obj->gtt_offset + offset);
+       intel_ring_emit(ring, 0); /* aux display base address, unused */
+       intel_ring_advance(ring);
+       return 0;
 
-static const struct drm_framebuffer_funcs intel_fb_funcs = {
-       .destroy = intel_user_framebuffer_destroy,
-       .create_handle = intel_user_framebuffer_create_handle,
-};
+err_unpin:
+       intel_unpin_fb_obj(obj);
+err:
+       return ret;
+}
 
-int intel_framebuffer_init(struct drm_device *dev,
-                          struct intel_framebuffer *intel_fb,
-                          struct drm_mode_fb_cmd2 *mode_cmd,
-                          struct drm_i915_gem_object *obj)
+static int intel_gen3_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       unsigned long offset;
+       u32 flip_mask;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        int ret;
 
-       if (obj->tiling_mode == I915_TILING_Y)
-               return -EINVAL;
+       ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
+       if (ret)
+               goto err;
 
-       if (mode_cmd->pitches[0] & 63)
-               return -EINVAL;
+       /* Offset into the new buffer for cases of shared fbs between CRTCs */
+       offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8;
 
-       switch (mode_cmd->pixel_format) {
-       case DRM_FORMAT_RGB332:
-       case DRM_FORMAT_RGB565:
-       case DRM_FORMAT_XRGB8888:
-       case DRM_FORMAT_XBGR8888:
-       case DRM_FORMAT_ARGB8888:
-       case DRM_FORMAT_XRGB2101010:
-       case DRM_FORMAT_ARGB2101010:
-               /* RGB formats are common across chipsets */
-               break;
-       case DRM_FORMAT_YUYV:
-       case DRM_FORMAT_UYVY:
-       case DRM_FORMAT_YVYU:
-       case DRM_FORMAT_VYUY:
-               break;
-       default:
-               DRM_DEBUG_KMS("unsupported pixel format %u\n",
-                               mode_cmd->pixel_format);
-               return -EINVAL;
-       }
+       ret = intel_ring_begin(ring, 6);
+       if (ret)
+               goto err_unpin;
 
-       ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
-       if (ret) {
-               DRM_ERROR("framebuffer init failed %d\n", ret);
-               return ret;
-       }
+       if (intel_crtc->plane)
+               flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+       else
+               flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
+       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 |
+                       MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+       intel_ring_emit(ring, fb->pitches[0]);
+       intel_ring_emit(ring, obj->gtt_offset + offset);
+       intel_ring_emit(ring, MI_NOOP);
 
-       drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
-       intel_fb->obj = obj;
+       intel_ring_advance(ring);
        return 0;
+
+err_unpin:
+       intel_unpin_fb_obj(obj);
+err:
+       return ret;
 }
 
-static struct drm_framebuffer *
-intel_user_framebuffer_create(struct drm_device *dev,
-                             struct drm_file *filp,
-                             struct drm_mode_fb_cmd2 *mode_cmd)
+static int intel_gen4_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
 {
-       struct drm_i915_gem_object *obj;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       uint32_t pf, pipesrc;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+       int ret;
 
-       obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
-                                               mode_cmd->handles[0]));
-       if (&obj->base == NULL)
-               return ERR_PTR(-ENOENT);
+       ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
+       if (ret)
+               goto err;
 
-       return intel_framebuffer_create(dev, mode_cmd, obj);
-}
+       ret = intel_ring_begin(ring, 4);
+       if (ret)
+               goto err_unpin;
 
-static const struct drm_mode_config_funcs intel_mode_funcs = {
-       .fb_create = intel_user_framebuffer_create,
-       .output_poll_changed = intel_fb_output_poll_changed,
-};
+       /* i965+ uses the linear or tiled offsets from the
+        * Display Registers (which do not change across a page-flip)
+        * so we need only reprogram the base address.
+        */
+       intel_ring_emit(ring, MI_DISPLAY_FLIP |
+                       MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+       intel_ring_emit(ring, fb->pitches[0]);
+       intel_ring_emit(ring, obj->gtt_offset | obj->tiling_mode);
 
-static struct drm_i915_gem_object *
-intel_alloc_context_page(struct drm_device *dev)
-{
-       struct drm_i915_gem_object *ctx;
-       int ret;
+       /* XXX Enabling the panel-fitter across page-flip is so far
+        * untested on non-native modes, so ignore it for now.
+        * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
+        */
+       pf = 0;
+       pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
+       intel_ring_emit(ring, pf | pipesrc);
+       intel_ring_advance(ring);
+       return 0;
 
-       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+err_unpin:
+       intel_unpin_fb_obj(obj);
+err:
+       return ret;
+}
 
-       ctx = i915_gem_alloc_object(dev, 4096);
-       if (!ctx) {
-               DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
-               return NULL;
-       }
+static int intel_gen6_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+       uint32_t pf, pipesrc;
+       int ret;
 
-       ret = i915_gem_object_pin(ctx, 4096, true);
-       if (ret) {
-               DRM_ERROR("failed to pin power context: %d\n", ret);
-               goto err_unref;
-       }
+       ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
+       if (ret)
+               goto err;
 
-       ret = i915_gem_object_set_to_gtt_domain(ctx, 1);
-       if (ret) {
-               DRM_ERROR("failed to set-domain on power context: %d\n", ret);
+       ret = intel_ring_begin(ring, 4);
+       if (ret)
                goto err_unpin;
-       }
 
-       return ctx;
+       intel_ring_emit(ring, MI_DISPLAY_FLIP |
+                       MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+       intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
+       intel_ring_emit(ring, obj->gtt_offset);
+
+       /* Contrary to the suggestions in the documentation,
+        * "Enable Panel Fitter" does not seem to be required when page
+        * flipping with a non-native mode, and worse causes a normal
+        * modeset to fail.
+        * pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
+        */
+       pf = 0;
+       pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
+       intel_ring_emit(ring, pf | pipesrc);
+       intel_ring_advance(ring);
+       return 0;
 
 err_unpin:
-       i915_gem_object_unpin(ctx);
-err_unref:
-       drm_gem_object_unreference(&ctx->base);
-       mutex_unlock(&dev->struct_mutex);
-       return NULL;
+       intel_unpin_fb_obj(obj);
+err:
+       return ret;
 }
 
-bool ironlake_set_drps(struct drm_device *dev, u8 val)
+/*
+ * On gen7 we currently use the blit ring because (in early silicon at least)
+ * the render ring doesn't give us interrpts for page flip completion, which
+ * means clients will hang after the first flip is queued.  Fortunately the
+ * blit ring generates interrupts properly, so use it instead.
+ */
+static int intel_gen7_queue_flip(struct drm_device *dev,
+                                struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_i915_gem_object *obj)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u16 rgvswctl;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
+       int ret;
 
-       rgvswctl = I915_READ16(MEMSWCTL);
-       if (rgvswctl & MEMCTL_CMD_STS) {
-               DRM_DEBUG("gpu busy, RCS change rejected\n");
-               return false; /* still busy with another command */
-       }
+       ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
+       if (ret)
+               goto err;
 
-       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
-               (val << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
-       I915_WRITE16(MEMSWCTL, rgvswctl);
-       POSTING_READ16(MEMSWCTL);
+       ret = intel_ring_begin(ring, 4);
+       if (ret)
+               goto err_unpin;
+
+       intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19));
+       intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
+       intel_ring_emit(ring, (obj->gtt_offset));
+       intel_ring_emit(ring, (MI_NOOP));
+       intel_ring_advance(ring);
+       return 0;
 
-       rgvswctl |= MEMCTL_CMD_STS;
-       I915_WRITE16(MEMSWCTL, rgvswctl);
+err_unpin:
+       intel_unpin_fb_obj(obj);
+err:
+       return ret;
+}
 
-       return true;
+static int intel_default_queue_flip(struct drm_device *dev,
+                                   struct drm_crtc *crtc,
+                                   struct drm_framebuffer *fb,
+                                   struct drm_i915_gem_object *obj)
+{
+       return -ENODEV;
 }
 
-void ironlake_enable_drps(struct drm_device *dev)
+static int intel_crtc_page_flip(struct drm_crtc *crtc,
+                               struct drm_framebuffer *fb,
+                               struct drm_pending_vblank_event *event)
 {
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 rgvmodectl = I915_READ(MEMMODECTL);
-       u8 fmax, fmin, fstart, vstart;
+       struct intel_framebuffer *intel_fb;
+       struct drm_i915_gem_object *obj;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_unpin_work *work;
+       unsigned long flags;
+       int ret;
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (work == NULL)
+               return -ENOMEM;
+
+       work->event = event;
+       work->dev = crtc->dev;
+       intel_fb = to_intel_framebuffer(crtc->fb);
+       work->old_fb_obj = intel_fb->obj;
+       INIT_WORK(&work->work, intel_unpin_work_fn);
+
+       ret = drm_vblank_get(dev, intel_crtc->pipe);
+       if (ret)
+               goto free_work;
+
+       /* We borrow the event spin lock for protecting unpin_work */
+       spin_lock_irqsave(&dev->event_lock, flags);
+       if (intel_crtc->unpin_work) {
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+               kfree(work);
+               drm_vblank_put(dev, intel_crtc->pipe);
 
-       /* Enable temp reporting */
-       I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN);
-       I915_WRITE16(TSC1, I915_READ(TSC1) | TSE);
+               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
+               return -EBUSY;
+       }
+       intel_crtc->unpin_work = work;
+       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       /* 100ms RC evaluation intervals */
-       I915_WRITE(RCUPEI, 100000);
-       I915_WRITE(RCDNEI, 100000);
+       intel_fb = to_intel_framebuffer(fb);
+       obj = intel_fb->obj;
 
-       /* Set max/min thresholds to 90ms and 80ms respectively */
-       I915_WRITE(RCBMAXAVG, 90000);
-       I915_WRITE(RCBMINAVG, 80000);
+       mutex_lock(&dev->struct_mutex);
 
-       I915_WRITE(MEMIHYST, 1);
+       /* Reference the objects for the scheduled work. */
+       drm_gem_object_reference(&work->old_fb_obj->base);
+       drm_gem_object_reference(&obj->base);
 
-       /* Set up min, max, and cur for interrupt handling */
-       fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT;
-       fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
-       fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
-               MEMMODE_FSTART_SHIFT;
+       crtc->fb = fb;
 
-       vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
-               PXVFREQ_PX_SHIFT;
+       work->pending_flip_obj = obj;
 
-       dev_priv->fmax = fmax; /* IPS callback will increase this */
-       dev_priv->fstart = fstart;
+       work->enable_stall_check = true;
 
-       dev_priv->max_delay = fstart;
-       dev_priv->min_delay = fmin;
-       dev_priv->cur_delay = fstart;
+       /* Block clients from rendering to the new back buffer until
+        * the flip occurs and the object is no longer visible.
+        */
+       atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
 
-       DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n",
-                        fmax, fmin, fstart);
+       ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
+       if (ret)
+               goto cleanup_pending;
 
-       I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
+       intel_disable_fbc(dev);
+       mutex_unlock(&dev->struct_mutex);
 
-       /*
-        * Interrupts will be enabled in ironlake_irq_postinstall
-        */
+       trace_i915_flip_request(intel_crtc->plane, obj);
 
-       I915_WRITE(VIDSTART, vstart);
-       POSTING_READ(VIDSTART);
+       return 0;
 
-       rgvmodectl |= MEMMODE_SWMODE_EN;
-       I915_WRITE(MEMMODECTL, rgvmodectl);
+cleanup_pending:
+       atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
+       drm_gem_object_unreference(&work->old_fb_obj->base);
+       drm_gem_object_unreference(&obj->base);
+       mutex_unlock(&dev->struct_mutex);
 
-       if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10))
-               DRM_ERROR("stuck trying to change perf mode\n");
-       msleep(1);
+       spin_lock_irqsave(&dev->event_lock, flags);
+       intel_crtc->unpin_work = NULL;
+       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       ironlake_set_drps(dev, fstart);
+       drm_vblank_put(dev, intel_crtc->pipe);
+free_work:
+       kfree(work);
 
-       dev_priv->last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
-               I915_READ(0x112e0);
-       dev_priv->last_time1 = jiffies_to_msecs(jiffies);
-       dev_priv->last_count2 = I915_READ(0x112f4);
-       getrawmonotonic(&dev_priv->last_time2);
+       return ret;
 }
 
-void ironlake_disable_drps(struct drm_device *dev)
+static void intel_sanitize_modesetting(struct drm_device *dev,
+                                      int pipe, int plane)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u16 rgvswctl = I915_READ16(MEMSWCTL);
+       u32 reg, val;
 
-       /* Ack interrupts, disable EFC interrupt */
-       I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
-       I915_WRITE(MEMINTRSTS, MEMINT_EVAL_CHG);
-       I915_WRITE(DEIER, I915_READ(DEIER) & ~DE_PCU_EVENT);
-       I915_WRITE(DEIIR, DE_PCU_EVENT);
-       I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
+       /* Clear any frame start delays used for debugging left by the BIOS */
+       for_each_pipe(pipe) {
+               reg = PIPECONF(pipe);
+               I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+       }
 
-       /* Go back to the starting frequency */
-       ironlake_set_drps(dev, dev_priv->fstart);
-       msleep(1);
-       rgvswctl |= MEMCTL_CMD_STS;
-       I915_WRITE(MEMSWCTL, rgvswctl);
-       msleep(1);
+       if (HAS_PCH_SPLIT(dev))
+               return;
 
-}
+       /* Who knows what state these registers were left in by the BIOS or
+        * grub?
+        *
+        * If we leave the registers in a conflicting state (e.g. with the
+        * display plane reading from the other pipe than the one we intend
+        * to use) then when we attempt to teardown the active mode, we will
+        * not disable the pipes and planes in the correct order -- leaving
+        * a plane reading from a disabled pipe and possibly leading to
+        * undefined behaviour.
+        */
 
-void gen6_set_rps(struct drm_device *dev, u8 val)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 swreq;
+       reg = DSPCNTR(plane);
+       val = I915_READ(reg);
 
-       swreq = (val & 0x3ff) << 25;
-       I915_WRITE(GEN6_RPNSWREQ, swreq);
+       if ((val & DISPLAY_PLANE_ENABLE) == 0)
+               return;
+       if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
+               return;
+
+       /* This display plane is active and attached to the other CPU pipe. */
+       pipe = !pipe;
+
+       /* Disable the plane and wait for it to stop reading from the pipe. */
+       intel_disable_plane(dev_priv, plane, pipe);
+       intel_disable_pipe(dev_priv, pipe);
 }
 
-void gen6_disable_rps(struct drm_device *dev)
+static void intel_crtc_reset(struct drm_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
-       I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
-       I915_WRITE(GEN6_PMIER, 0);
-       /* Complete PM interrupt masking here doesn't race with the rps work
-        * item again unmasking PM interrupts because that is using a different
-        * register (PMIMR) to mask PM interrupts. The only risk is in leaving
-        * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
+       struct drm_device *dev = crtc->dev;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       spin_lock_irq(&dev_priv->rps_lock);
-       dev_priv->pm_iir = 0;
-       spin_unlock_irq(&dev_priv->rps_lock);
+       /* Reset flags back to the 'unknown' status so that they
+        * will be correctly set on the initial modeset.
+        */
+       intel_crtc->dpms_mode = -1;
 
-       I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
+       /* We need to fix up any BIOS configuration that conflicts with
+        * our expectations.
+        */
+       intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
 }
 
-static unsigned long intel_pxfreq(u32 vidfreq)
-{
-       unsigned long freq;
-       int div = (vidfreq & 0x3f0000) >> 16;
-       int post = (vidfreq & 0x3000) >> 12;
-       int pre = (vidfreq & 0x7);
+static struct drm_crtc_helper_funcs intel_helper_funcs = {
+       .dpms = intel_crtc_dpms,
+       .mode_fixup = intel_crtc_mode_fixup,
+       .mode_set = intel_crtc_mode_set,
+       .mode_set_base = intel_pipe_set_base,
+       .mode_set_base_atomic = intel_pipe_set_base_atomic,
+       .load_lut = intel_crtc_load_lut,
+       .disable = intel_crtc_disable,
+};
 
-       if (!pre)
-               return 0;
+static const struct drm_crtc_funcs intel_crtc_funcs = {
+       .reset = intel_crtc_reset,
+       .cursor_set = intel_crtc_cursor_set,
+       .cursor_move = intel_crtc_cursor_move,
+       .gamma_set = intel_crtc_gamma_set,
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = intel_crtc_destroy,
+       .page_flip = intel_crtc_page_flip,
+};
+
+static void intel_pch_pll_init(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int i;
 
-       freq = ((div * 133333) / ((1<<post) * pre));
+       if (dev_priv->num_pch_pll == 0) {
+               DRM_DEBUG_KMS("No PCH PLLs on this hardware, skipping initialisation\n");
+               return;
+       }
 
-       return freq;
+       for (i = 0; i < dev_priv->num_pch_pll; i++) {
+               dev_priv->pch_plls[i].pll_reg = _PCH_DPLL(i);
+               dev_priv->pch_plls[i].fp0_reg = _PCH_FP0(i);
+               dev_priv->pch_plls[i].fp1_reg = _PCH_FP1(i);
+       }
 }
 
-void intel_init_emon(struct drm_device *dev)
+static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 lcfuse;
-       u8 pxw[16];
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc;
        int i;
 
-       /* Disable to program */
-       I915_WRITE(ECR, 0);
-       POSTING_READ(ECR);
-
-       /* Program energy weights for various events */
-       I915_WRITE(SDEW, 0x15040d00);
-       I915_WRITE(CSIEW0, 0x007f0000);
-       I915_WRITE(CSIEW1, 0x1e220004);
-       I915_WRITE(CSIEW2, 0x04000004);
-
-       for (i = 0; i < 5; i++)
-               I915_WRITE(PEW + (i * 4), 0);
-       for (i = 0; i < 3; i++)
-               I915_WRITE(DEW + (i * 4), 0);
-
-       /* Program P-state weights to account for frequency power adjustment */
-       for (i = 0; i < 16; i++) {
-               u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4));
-               unsigned long freq = intel_pxfreq(pxvidfreq);
-               unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >>
-                       PXVFREQ_PX_SHIFT;
-               unsigned long val;
-
-               val = vid * vid;
-               val *= (freq / 1000);
-               val *= 255;
-               val /= (127*127*900);
-               if (val > 0xff)
-                       DRM_ERROR("bad pxval: %ld\n", val);
-               pxw[i] = val;
-       }
-       /* Render standby states get 0 weight */
-       pxw[14] = 0;
-       pxw[15] = 0;
+       intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
+       if (intel_crtc == NULL)
+               return;
 
-       for (i = 0; i < 4; i++) {
-               u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) |
-                       (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]);
-               I915_WRITE(PXW + (i * 4), val);
-       }
+       drm_crtc_init(dev, &intel_crtc->base, &intel_crtc_funcs);
 
-       /* Adjust magic regs to magic values (more experimental results) */
-       I915_WRITE(OGW0, 0);
-       I915_WRITE(OGW1, 0);
-       I915_WRITE(EG0, 0x00007f00);
-       I915_WRITE(EG1, 0x0000000e);
-       I915_WRITE(EG2, 0x000e0000);
-       I915_WRITE(EG3, 0x68000300);
-       I915_WRITE(EG4, 0x42000000);
-       I915_WRITE(EG5, 0x00140031);
-       I915_WRITE(EG6, 0);
-       I915_WRITE(EG7, 0);
+       drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
+       for (i = 0; i < 256; i++) {
+               intel_crtc->lut_r[i] = i;
+               intel_crtc->lut_g[i] = i;
+               intel_crtc->lut_b[i] = i;
+       }
 
-       for (i = 0; i < 8; i++)
-               I915_WRITE(PXWL + (i * 4), 0);
+       /* Swap pipes & planes for FBC on pre-965 */
+       intel_crtc->pipe = pipe;
+       intel_crtc->plane = pipe;
+       if (IS_MOBILE(dev) && IS_GEN3(dev)) {
+               DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
+               intel_crtc->plane = !pipe;
+       }
 
-       /* Enable PMON + select events */
-       I915_WRITE(ECR, 0x80000019);
+       BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
+              dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
+       dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
+       dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
 
-       lcfuse = I915_READ(LCFUSE02);
+       intel_crtc_reset(&intel_crtc->base);
+       intel_crtc->active = true; /* force the pipe off on setup_init_config */
+       intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
-       dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
-}
+       if (HAS_PCH_SPLIT(dev)) {
+               intel_helper_funcs.prepare = ironlake_crtc_prepare;
+               intel_helper_funcs.commit = ironlake_crtc_commit;
+       } else {
+               intel_helper_funcs.prepare = i9xx_crtc_prepare;
+               intel_helper_funcs.commit = i9xx_crtc_commit;
+       }
 
-static bool intel_enable_rc6(struct drm_device *dev)
-{
-       /*
-        * Respect the kernel parameter if it is set
-        */
-       if (i915_enable_rc6 >= 0)
-               return i915_enable_rc6;
+       drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
-       /*
-        * Disable RC6 on Ironlake
-        */
-       if (INTEL_INFO(dev)->gen == 5)
-               return 0;
+       intel_crtc->busy = false;
 
-       /*
-        * Disable rc6 on Sandybridge
-        */
-       if (INTEL_INFO(dev)->gen == 6) {
-               DRM_DEBUG_DRIVER("Sandybridge: RC6 disabled\n");
-               return 0;
-       }
-       DRM_DEBUG_DRIVER("RC6 enabled\n");
-       return 1;
+       setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
+                   (unsigned long)intel_crtc);
 }
 
-void gen6_enable_rps(struct drm_i915_private *dev_priv)
+int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+                               struct drm_file *file)
 {
-       u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-       u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
-       u32 pcu_mbox, rc6_mask = 0;
-       u32 gtfifodbg;
-       int cur_freq, min_freq, max_freq;
-       int i;
-
-       /* Here begins a magic sequence of register writes to enable
-        * auto-downclocking.
-        *
-        * Perhaps there might be some value in exposing these to
-        * userspace...
-        */
-       I915_WRITE(GEN6_RC_STATE, 0);
-       mutex_lock(&dev_priv->dev->struct_mutex);
-
-       /* Clear the DBG now so we don't confuse earlier errors */
-       if ((gtfifodbg = I915_READ(GTFIFODBG))) {
-               DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg);
-               I915_WRITE(GTFIFODBG, gtfifodbg);
-       }
-
-       gen6_gt_force_wake_get(dev_priv);
-
-       /* disable the counters and set deterministic thresholds */
-       I915_WRITE(GEN6_RC_CONTROL, 0);
-
-       I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16);
-       I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30);
-       I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30);
-       I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
-       I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
-
-       for (i = 0; i < I915_NUM_RINGS; i++)
-               I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10);
-
-       I915_WRITE(GEN6_RC_SLEEP, 0);
-       I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
-       I915_WRITE(GEN6_RC6_THRESHOLD, 50000);
-       I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
-       I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
-
-       if (intel_enable_rc6(dev_priv->dev))
-               rc6_mask = GEN6_RC_CTL_RC6_ENABLE |
-                       ((IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0);
-
-       I915_WRITE(GEN6_RC_CONTROL,
-                  rc6_mask |
-                  GEN6_RC_CTL_EI_MODE(1) |
-                  GEN6_RC_CTL_HW_ENABLE);
-
-       I915_WRITE(GEN6_RPNSWREQ,
-                  GEN6_FREQUENCY(10) |
-                  GEN6_OFFSET(0) |
-                  GEN6_AGGRESSIVE_TURBO);
-       I915_WRITE(GEN6_RC_VIDEO_FREQ,
-                  GEN6_FREQUENCY(12));
-
-       I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000);
-       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
-                  18 << 24 |
-                  6 << 16);
-       I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000);
-       I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000);
-       I915_WRITE(GEN6_RP_UP_EI, 100000);
-       I915_WRITE(GEN6_RP_DOWN_EI, 5000000);
-       I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
-       I915_WRITE(GEN6_RP_CONTROL,
-                  GEN6_RP_MEDIA_TURBO |
-                  GEN6_RP_MEDIA_HW_MODE |
-                  GEN6_RP_MEDIA_IS_GFX |
-                  GEN6_RP_ENABLE |
-                  GEN6_RP_UP_BUSY_AVG |
-                  GEN6_RP_DOWN_IDLE_CONT);
-
-       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
-                    500))
-               DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
-
-       I915_WRITE(GEN6_PCODE_DATA, 0);
-       I915_WRITE(GEN6_PCODE_MAILBOX,
-                  GEN6_PCODE_READY |
-                  GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
-       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
-                    500))
-               DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
-
-       min_freq = (rp_state_cap & 0xff0000) >> 16;
-       max_freq = rp_state_cap & 0xff;
-       cur_freq = (gt_perf_status & 0xff00) >> 8;
-
-       /* Check for overclock support */
-       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
-                    500))
-               DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
-       I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_READ_OC_PARAMS);
-       pcu_mbox = I915_READ(GEN6_PCODE_DATA);
-       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
-                    500))
-               DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
-       if (pcu_mbox & (1<<31)) { /* OC supported */
-               max_freq = pcu_mbox & 0xff;
-               DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
-       }
-
-       /* In units of 100MHz */
-       dev_priv->max_delay = max_freq;
-       dev_priv->min_delay = min_freq;
-       dev_priv->cur_delay = cur_freq;
-
-       /* requires MSI enabled */
-       I915_WRITE(GEN6_PMIER,
-                  GEN6_PM_MBOX_EVENT |
-                  GEN6_PM_THERMAL_EVENT |
-                  GEN6_PM_RP_DOWN_TIMEOUT |
-                  GEN6_PM_RP_UP_THRESHOLD |
-                  GEN6_PM_RP_DOWN_THRESHOLD |
-                  GEN6_PM_RP_UP_EI_EXPIRED |
-                  GEN6_PM_RP_DOWN_EI_EXPIRED);
-       spin_lock_irq(&dev_priv->rps_lock);
-       WARN_ON(dev_priv->pm_iir != 0);
-       I915_WRITE(GEN6_PMIMR, 0);
-       spin_unlock_irq(&dev_priv->rps_lock);
-       /* enable all PM interrupts */
-       I915_WRITE(GEN6_PMINTRMSK, 0);
-
-       gen6_gt_force_wake_put(dev_priv);
-       mutex_unlock(&dev_priv->dev->struct_mutex);
-}
-
-void gen6_update_ring_freq(struct drm_i915_private *dev_priv)
-{
-       int min_freq = 15;
-       int gpu_freq, ia_freq, max_ia_freq;
-       int scaling_factor = 180;
-
-       max_ia_freq = cpufreq_quick_get_max(0);
-       /*
-        * Default to measured freq if none found, PCU will ensure we don't go
-        * over
-        */
-       if (!max_ia_freq)
-               max_ia_freq = tsc_khz;
-
-       /* Convert from kHz to MHz */
-       max_ia_freq /= 1000;
+       struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
+       struct drm_mode_object *drmmode_obj;
+       struct intel_crtc *crtc;
 
-       mutex_lock(&dev_priv->dev->struct_mutex);
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
 
-       /*
-        * For each potential GPU frequency, load a ring frequency we'd like
-        * to use for memory access.  We do this by specifying the IA frequency
-        * the PCU should use as a reference to determine the ring frequency.
-        */
-       for (gpu_freq = dev_priv->max_delay; gpu_freq >= dev_priv->min_delay;
-            gpu_freq--) {
-               int diff = dev_priv->max_delay - gpu_freq;
+       drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
+                       DRM_MODE_OBJECT_CRTC);
 
-               /*
-                * For GPU frequencies less than 750MHz, just use the lowest
-                * ring freq.
-                */
-               if (gpu_freq < min_freq)
-                       ia_freq = 800;
-               else
-                       ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
-               ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
-
-               I915_WRITE(GEN6_PCODE_DATA,
-                          (ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT) |
-                          gpu_freq);
-               I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
-                          GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
-               if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
-                             GEN6_PCODE_READY) == 0, 10)) {
-                       DRM_ERROR("pcode write of freq table timed out\n");
-                       continue;
-               }
+       if (!drmmode_obj) {
+               DRM_ERROR("no such CRTC id\n");
+               return -EINVAL;
        }
 
-       mutex_unlock(&dev_priv->dev->struct_mutex);
+       crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
+       pipe_from_crtc_id->pipe = crtc->pipe;
+
+       return 0;
 }
 
-static void ironlake_init_clock_gating(struct drm_device *dev)
+static int intel_encoder_clones(struct drm_device *dev, int type_mask)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
-
-       /* Required for FBC */
-       dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE |
-               DPFCRUNIT_CLOCK_GATE_DISABLE |
-               DPFDUNIT_CLOCK_GATE_DISABLE;
-       /* Required for CxSR */
-       dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE;
-
-       I915_WRITE(PCH_3DCGDIS0,
-                  MARIUNIT_CLOCK_GATE_DISABLE |
-                  SVSMUNIT_CLOCK_GATE_DISABLE);
-       I915_WRITE(PCH_3DCGDIS1,
-                  VFMUNIT_CLOCK_GATE_DISABLE);
-
-       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
-
-       /*
-        * According to the spec the following bits should be set in
-        * order to enable memory self-refresh
-        * The bit 22/21 of 0x42004
-        * The bit 5 of 0x42020
-        * The bit 15 of 0x45000
-        */
-       I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                  (I915_READ(ILK_DISPLAY_CHICKEN2) |
-                   ILK_DPARB_GATE | ILK_VSDPFD_FULL));
-       I915_WRITE(ILK_DSPCLK_GATE,
-                  (I915_READ(ILK_DSPCLK_GATE) |
-                   ILK_DPARB_CLK_GATE));
-       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);
+       struct intel_encoder *encoder;
+       int index_mask = 0;
+       int entry = 0;
 
-       /*
-        * Based on the document from hardware guys the following bits
-        * should be set unconditionally in order to enable FBC.
-        * The bit 22 of 0x42000
-        * The bit 22 of 0x42004
-        * The bit 7,8,9 of 0x42020.
-        */
-       if (IS_IRONLAKE_M(dev)) {
-               I915_WRITE(ILK_DISPLAY_CHICKEN1,
-                          I915_READ(ILK_DISPLAY_CHICKEN1) |
-                          ILK_FBCQ_DIS);
-               I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                          I915_READ(ILK_DISPLAY_CHICKEN2) |
-                          ILK_DPARB_GATE);
-               I915_WRITE(ILK_DSPCLK_GATE,
-                          I915_READ(ILK_DSPCLK_GATE) |
-                          ILK_DPFC_DIS1 |
-                          ILK_DPFC_DIS2 |
-                          ILK_CLK_FBC);
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+               if (type_mask & encoder->clone_mask)
+                       index_mask |= (1 << entry);
+               entry++;
        }
 
-       I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                  I915_READ(ILK_DISPLAY_CHICKEN2) |
-                  ILK_ELPIN_409_SELECT);
-       I915_WRITE(_3D_CHICKEN2,
-                  _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
-                  _3D_CHICKEN2_WM_READ_PIPELINED);
+       return index_mask;
 }
 
-static void gen6_init_clock_gating(struct drm_device *dev)
+static bool has_edp_a(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
-       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
-
-       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
 
-       I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                  I915_READ(ILK_DISPLAY_CHICKEN2) |
-                  ILK_ELPIN_409_SELECT);
-
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
+       if (!IS_MOBILE(dev))
+               return false;
 
-       /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
-        * gating disable must be set.  Failure to set it results in
-        * flickering pixels due to Z write ordering failures after
-        * some amount of runtime in the Mesa "fire" demo, and Unigine
-        * Sanctuary and Tropics, and apparently anything else with
-        * alpha test or pixel discard.
-        *
-        * According to the spec, bit 11 (RCCUNIT) must also be set,
-        * but we didn't debug actual testcases to find it out.
-        */
-       I915_WRITE(GEN6_UCGCTL2,
-                  GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
-                  GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+       if ((I915_READ(DP_A) & DP_DETECTED) == 0)
+               return false;
 
-       /*
-        * According to the spec the following bits should be
-        * set in order to enable memory self-refresh and fbc:
-        * The bit21 and bit22 of 0x42000
-        * The bit21 and bit22 of 0x42004
-        * The bit5 and bit7 of 0x42020
-        * The bit14 of 0x70180
-        * The bit14 of 0x71180
-        */
-       I915_WRITE(ILK_DISPLAY_CHICKEN1,
-                  I915_READ(ILK_DISPLAY_CHICKEN1) |
-                  ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS);
-       I915_WRITE(ILK_DISPLAY_CHICKEN2,
-                  I915_READ(ILK_DISPLAY_CHICKEN2) |
-                  ILK_DPARB_GATE | ILK_VSDPFD_FULL);
-       I915_WRITE(ILK_DSPCLK_GATE,
-                  I915_READ(ILK_DSPCLK_GATE) |
-                  ILK_DPARB_CLK_GATE  |
-                  ILK_DPFD_CLK_GATE);
+       if (IS_GEN5(dev) &&
+           (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
+               return false;
 
-       for_each_pipe(pipe) {
-               I915_WRITE(DSPCNTR(pipe),
-                          I915_READ(DSPCNTR(pipe)) |
-                          DISPPLANE_TRICKLE_FEED_DISABLE);
-               intel_flush_display_plane(dev_priv, pipe);
-       }
+       return true;
 }
 
-static void ivybridge_init_clock_gating(struct drm_device *dev)
+static void intel_setup_outputs(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
-       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
-
-       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
-
-       I915_WRITE(WM3_LP_ILK, 0);
-       I915_WRITE(WM2_LP_ILK, 0);
-       I915_WRITE(WM1_LP_ILK, 0);
-
-       /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
-        * This implements the WaDisableRCZUnitClockGating workaround.
-        */
-       I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
-
-       I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
-
-       I915_WRITE(IVB_CHICKEN3,
-                  CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
-                  CHICKEN3_DGMG_DONE_FIX_DISABLE);
-
-       /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
-       I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
-                  GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+       struct intel_encoder *encoder;
+       bool dpd_is_edp = false;
+       bool has_lvds;
 
-       /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
-       I915_WRITE(GEN7_L3CNTLREG1,
-                       GEN7_WA_FOR_GEN7_L3_CONTROL);
-       I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
-                       GEN7_WA_L3_CHICKEN_MODE);
+       has_lvds = intel_lvds_init(dev);
+       if (!has_lvds && !HAS_PCH_SPLIT(dev)) {
+               /* disable the panel fitter on everything but LVDS */
+               I915_WRITE(PFIT_CONTROL, 0);
+       }
 
-       /* This is required by WaCatErrorRejectionIssue */
-       I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
-                       I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
-                       GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+       if (HAS_PCH_SPLIT(dev)) {
+               dpd_is_edp = intel_dpd_is_edp(dev);
 
-       for_each_pipe(pipe) {
-               I915_WRITE(DSPCNTR(pipe),
-                          I915_READ(DSPCNTR(pipe)) |
-                          DISPPLANE_TRICKLE_FEED_DISABLE);
-               intel_flush_display_plane(dev_priv, pipe);
-       }
-}
+               if (has_edp_a(dev))
+                       intel_dp_init(dev, DP_A);
 
-static void g4x_init_clock_gating(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t dspclk_gate;
+               if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
+                       intel_dp_init(dev, PCH_DP_D);
+       }
 
-       I915_WRITE(RENCLK_GATE_D1, 0);
-       I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
-                  GS_UNIT_CLOCK_GATE_DISABLE |
-                  CL_UNIT_CLOCK_GATE_DISABLE);
-       I915_WRITE(RAMCLK_GATE_D, 0);
-       dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
-               OVRUNIT_CLOCK_GATE_DISABLE |
-               OVCUNIT_CLOCK_GATE_DISABLE;
-       if (IS_GM45(dev))
-               dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
-       I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
-}
+       intel_crt_init(dev);
 
-static void crestline_init_clock_gating(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (HAS_PCH_SPLIT(dev)) {
+               int found;
 
-       I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
-       I915_WRITE(RENCLK_GATE_D2, 0);
-       I915_WRITE(DSPCLK_GATE_D, 0);
-       I915_WRITE(RAMCLK_GATE_D, 0);
-       I915_WRITE16(DEUC, 0);
-}
+               if (I915_READ(HDMIB) & PORT_DETECTED) {
+                       /* PCH SDVOB multiplex with HDMIB */
+                       found = intel_sdvo_init(dev, PCH_SDVOB, true);
+                       if (!found)
+                               intel_hdmi_init(dev, HDMIB);
+                       if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
+                               intel_dp_init(dev, PCH_DP_B);
+               }
 
-static void broadwater_init_clock_gating(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
+               if (I915_READ(HDMIC) & PORT_DETECTED)
+                       intel_hdmi_init(dev, HDMIC);
 
-       I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
-                  I965_RCC_CLOCK_GATE_DISABLE |
-                  I965_RCPB_CLOCK_GATE_DISABLE |
-                  I965_ISC_CLOCK_GATE_DISABLE |
-                  I965_FBC_CLOCK_GATE_DISABLE);
-       I915_WRITE(RENCLK_GATE_D2, 0);
-}
+               if (I915_READ(HDMID) & PORT_DETECTED)
+                       intel_hdmi_init(dev, HDMID);
 
-static void gen3_init_clock_gating(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 dstate = I915_READ(D_STATE);
+               if (I915_READ(PCH_DP_C) & DP_DETECTED)
+                       intel_dp_init(dev, PCH_DP_C);
 
-       dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
-               DSTATE_DOT_CLOCK_GATING;
-       I915_WRITE(D_STATE, dstate);
-}
+               if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
+                       intel_dp_init(dev, PCH_DP_D);
 
-static void i85x_init_clock_gating(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
+               bool found = false;
 
-       I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
-}
+               if (I915_READ(SDVOB) & SDVO_DETECTED) {
+                       DRM_DEBUG_KMS("probing SDVOB\n");
+                       found = intel_sdvo_init(dev, SDVOB, true);
+                       if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
+                               DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
+                               intel_hdmi_init(dev, SDVOB);
+                       }
 
-static void i830_init_clock_gating(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
+                       if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
+                               DRM_DEBUG_KMS("probing DP_B\n");
+                               intel_dp_init(dev, DP_B);
+                       }
+               }
 
-       I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
-}
+               /* Before G4X SDVOC doesn't have its own detect register */
 
-static void ibx_init_clock_gating(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
+               if (I915_READ(SDVOB) & SDVO_DETECTED) {
+                       DRM_DEBUG_KMS("probing SDVOC\n");
+                       found = intel_sdvo_init(dev, SDVOC, false);
+               }
 
-       /*
-        * On Ibex Peak and Cougar Point, we need to disable clock
-        * gating for the panel power sequencer or it will fail to
-        * start up when no ports are active.
-        */
-       I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
-}
+               if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
 
-static void cpt_init_clock_gating(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe;
+                       if (SUPPORTS_INTEGRATED_HDMI(dev)) {
+                               DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
+                               intel_hdmi_init(dev, SDVOC);
+                       }
+                       if (SUPPORTS_INTEGRATED_DP(dev)) {
+                               DRM_DEBUG_KMS("probing DP_C\n");
+                               intel_dp_init(dev, DP_C);
+                       }
+               }
 
-       /*
-        * On Ibex Peak and Cougar Point, we need to disable clock
-        * gating for the panel power sequencer or it will fail to
-        * start up when no ports are active.
-        */
-       I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
-       I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
-                  DPLS_EDP_PPS_FIX_DIS);
-       /* Without this, mode sets may fail silently on FDI */
-       for_each_pipe(pipe)
-               I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_AUTOTRAIN_GEN_STALL_DIS);
-}
+               if (SUPPORTS_INTEGRATED_DP(dev) &&
+                   (I915_READ(DP_D) & DP_DETECTED)) {
+                       DRM_DEBUG_KMS("probing DP_D\n");
+                       intel_dp_init(dev, DP_D);
+               }
+       } else if (IS_GEN2(dev))
+               intel_dvo_init(dev);
 
-static void ironlake_teardown_rc6(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (SUPPORTS_TV(dev))
+               intel_tv_init(dev);
 
-       if (dev_priv->renderctx) {
-               i915_gem_object_unpin(dev_priv->renderctx);
-               drm_gem_object_unreference(&dev_priv->renderctx->base);
-               dev_priv->renderctx = NULL;
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+               encoder->base.possible_crtcs = encoder->crtc_mask;
+               encoder->base.possible_clones =
+                       intel_encoder_clones(dev, encoder->clone_mask);
        }
 
-       if (dev_priv->pwrctx) {
-               i915_gem_object_unpin(dev_priv->pwrctx);
-               drm_gem_object_unreference(&dev_priv->pwrctx->base);
-               dev_priv->pwrctx = NULL;
-       }
+       /* disable all the possible outputs/crtcs before entering KMS mode */
+       drm_helper_disable_unused_functions(dev);
+
+       if (HAS_PCH_SPLIT(dev))
+               ironlake_init_pch_refclk(dev);
 }
 
-static void ironlake_disable_rc6(struct drm_device *dev)
+static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (I915_READ(PWRCTXA)) {
-               /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */
-               I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT);
-               wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON),
-                        50);
-
-               I915_WRITE(PWRCTXA, 0);
-               POSTING_READ(PWRCTXA);
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 
-               I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
-               POSTING_READ(RSTDBYCTL);
-       }
+       drm_framebuffer_cleanup(fb);
+       drm_gem_object_unreference_unlocked(&intel_fb->obj->base);
 
-       ironlake_teardown_rc6(dev);
+       kfree(intel_fb);
 }
 
-static int ironlake_setup_rc6(struct drm_device *dev)
+static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+                                               struct drm_file *file,
+                                               unsigned int *handle)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (dev_priv->renderctx == NULL)
-               dev_priv->renderctx = intel_alloc_context_page(dev);
-       if (!dev_priv->renderctx)
-               return -ENOMEM;
-
-       if (dev_priv->pwrctx == NULL)
-               dev_priv->pwrctx = intel_alloc_context_page(dev);
-       if (!dev_priv->pwrctx) {
-               ironlake_teardown_rc6(dev);
-               return -ENOMEM;
-       }
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       struct drm_i915_gem_object *obj = intel_fb->obj;
 
-       return 0;
+       return drm_gem_handle_create(file, &obj->base, handle);
 }
 
-void ironlake_enable_rc6(struct drm_device *dev)
+static const struct drm_framebuffer_funcs intel_fb_funcs = {
+       .destroy = intel_user_framebuffer_destroy,
+       .create_handle = intel_user_framebuffer_create_handle,
+};
+
+int intel_framebuffer_init(struct drm_device *dev,
+                          struct intel_framebuffer *intel_fb,
+                          struct drm_mode_fb_cmd2 *mode_cmd,
+                          struct drm_i915_gem_object *obj)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
-       /* rc6 disabled by default due to repeated reports of hanging during
-        * boot and resume.
-        */
-       if (!intel_enable_rc6(dev))
-               return;
+       if (obj->tiling_mode == I915_TILING_Y)
+               return -EINVAL;
 
-       mutex_lock(&dev->struct_mutex);
-       ret = ironlake_setup_rc6(dev);
-       if (ret) {
-               mutex_unlock(&dev->struct_mutex);
-               return;
-       }
+       if (mode_cmd->pitches[0] & 63)
+               return -EINVAL;
 
-       /*
-        * GPU can automatically power down the render unit if given a page
-        * to save state.
-        */
-       ret = BEGIN_LP_RING(6);
-       if (ret) {
-               ironlake_teardown_rc6(dev);
-               mutex_unlock(&dev->struct_mutex);
-               return;
+       switch (mode_cmd->pixel_format) {
+       case DRM_FORMAT_RGB332:
+       case DRM_FORMAT_RGB565:
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_XBGR8888:
+       case DRM_FORMAT_ARGB8888:
+       case DRM_FORMAT_XRGB2101010:
+       case DRM_FORMAT_ARGB2101010:
+               /* RGB formats are common across chipsets */
+               break;
+       case DRM_FORMAT_YUYV:
+       case DRM_FORMAT_UYVY:
+       case DRM_FORMAT_YVYU:
+       case DRM_FORMAT_VYUY:
+               break;
+       default:
+               DRM_DEBUG_KMS("unsupported pixel format %u\n",
+                               mode_cmd->pixel_format);
+               return -EINVAL;
        }
 
-       OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
-       OUT_RING(MI_SET_CONTEXT);
-       OUT_RING(dev_priv->renderctx->gtt_offset |
-                MI_MM_SPACE_GTT |
-                MI_SAVE_EXT_STATE_EN |
-                MI_RESTORE_EXT_STATE_EN |
-                MI_RESTORE_INHIBIT);
-       OUT_RING(MI_SUSPEND_FLUSH);
-       OUT_RING(MI_NOOP);
-       OUT_RING(MI_FLUSH);
-       ADVANCE_LP_RING();
-
-       /*
-        * Wait for the command parser to advance past MI_SET_CONTEXT. The HW
-        * does an implicit flush, combined with MI_FLUSH above, it should be
-        * safe to assume that renderctx is valid
-        */
-       ret = intel_wait_ring_idle(LP_RING(dev_priv));
+       ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
        if (ret) {
-               DRM_ERROR("failed to enable ironlake power power savings\n");
-               ironlake_teardown_rc6(dev);
-               mutex_unlock(&dev->struct_mutex);
-               return;
+               DRM_ERROR("framebuffer init failed %d\n", ret);
+               return ret;
        }
 
-       I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN);
-       I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
-       mutex_unlock(&dev->struct_mutex);
+       drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
+       intel_fb->obj = obj;
+       return 0;
 }
 
-void intel_init_clock_gating(struct drm_device *dev)
+static struct drm_framebuffer *
+intel_user_framebuffer_create(struct drm_device *dev,
+                             struct drm_file *filp,
+                             struct drm_mode_fb_cmd2 *mode_cmd)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_gem_object *obj;
 
-       dev_priv->display.init_clock_gating(dev);
+       obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
+                                               mode_cmd->handles[0]));
+       if (&obj->base == NULL)
+               return ERR_PTR(-ENOENT);
 
-       if (dev_priv->display.init_pch_clock_gating)
-               dev_priv->display.init_pch_clock_gating(dev);
+       return intel_framebuffer_create(dev, mode_cmd, obj);
 }
 
+static const struct drm_mode_config_funcs intel_mode_funcs = {
+       .fb_create = intel_user_framebuffer_create,
+       .output_poll_changed = intel_fb_output_poll_changed,
+};
+
 /* Set up chip specific display functions */
 static void intel_init_display(struct drm_device *dev)
 {
@@ -8827,32 +6421,20 @@ static void intel_init_display(struct drm_device *dev)
        if (HAS_PCH_SPLIT(dev)) {
                dev_priv->display.dpms = ironlake_crtc_dpms;
                dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
+               dev_priv->display.off = ironlake_crtc_off;
                dev_priv->display.update_plane = ironlake_update_plane;
        } else {
                dev_priv->display.dpms = i9xx_crtc_dpms;
                dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
+               dev_priv->display.off = i9xx_crtc_off;
                dev_priv->display.update_plane = i9xx_update_plane;
        }
 
-       if (I915_HAS_FBC(dev)) {
-               if (HAS_PCH_SPLIT(dev)) {
-                       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)) {
-                       dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
-                       dev_priv->display.enable_fbc = i8xx_enable_fbc;
-                       dev_priv->display.disable_fbc = i8xx_disable_fbc;
-               }
-               /* 855GM needs testing */
-       }
-
        /* Returns the core display clock speed */
-       if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev)))
+       if (IS_VALLEYVIEW(dev))
+               dev_priv->display.get_display_clock_speed =
+                       valleyview_get_display_clock_speed;
+       else if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev)))
                dev_priv->display.get_display_clock_speed =
                        i945_get_display_clock_speed;
        else if (IS_I915G(dev))
@@ -8874,124 +6456,24 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.get_display_clock_speed =
                        i830_get_display_clock_speed;
 
-       /* For FIFO watermark updates */
        if (HAS_PCH_SPLIT(dev)) {
-               dev_priv->display.force_wake_get = __gen6_gt_force_wake_get;
-               dev_priv->display.force_wake_put = __gen6_gt_force_wake_put;
-
-               /* IVB configs may use multi-threaded forcewake */
-               if (IS_IVYBRIDGE(dev)) {
-                       u32     ecobus;
-
-                       /* A small trick here - if the bios hasn't configured MT forcewake,
-                        * and if the device is in RC6, then force_wake_mt_get will not wake
-                        * the device and the ECOBUS read will return zero. Which will be
-                        * (correctly) interpreted by the test below as MT forcewake being
-                        * disabled.
-                        */
-                       mutex_lock(&dev->struct_mutex);
-                       __gen6_gt_force_wake_mt_get(dev_priv);
-                       ecobus = I915_READ_NOTRACE(ECOBUS);
-                       __gen6_gt_force_wake_mt_put(dev_priv);
-                       mutex_unlock(&dev->struct_mutex);
-
-                       if (ecobus & FORCEWAKE_MT_ENABLE) {
-                               DRM_DEBUG_KMS("Using MT version of forcewake\n");
-                               dev_priv->display.force_wake_get =
-                                       __gen6_gt_force_wake_mt_get;
-                               dev_priv->display.force_wake_put =
-                                       __gen6_gt_force_wake_mt_put;
-                       }
-               }
-
-               if (HAS_PCH_IBX(dev))
-                       dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating;
-               else if (HAS_PCH_CPT(dev))
-                       dev_priv->display.init_pch_clock_gating = cpt_init_clock_gating;
-
                if (IS_GEN5(dev)) {
-                       if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
-                               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;
-                       }
                        dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
-                       dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
                        dev_priv->display.write_eld = ironlake_write_eld;
                } else if (IS_GEN6(dev)) {
-                       if (SNB_READ_WM0_LATENCY()) {
-                               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;
-                       }
                        dev_priv->display.fdi_link_train = gen6_fdi_link_train;
-                       dev_priv->display.init_clock_gating = gen6_init_clock_gating;
                        dev_priv->display.write_eld = ironlake_write_eld;
                } else if (IS_IVYBRIDGE(dev)) {
                        /* FIXME: detect B0+ stepping and use auto training */
                        dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
-                       if (SNB_READ_WM0_LATENCY()) {
-                               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;
-                       }
-                       dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
                        dev_priv->display.write_eld = ironlake_write_eld;
                } else
                        dev_priv->display.update_wm = NULL;
-       } else if (IS_PINEVIEW(dev)) {
-               if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
-                                           dev_priv->is_ddr3,
-                                           dev_priv->fsb_freq,
-                                           dev_priv->mem_freq)) {
-                       DRM_INFO("failed to find known CxSR latency "
-                                "(found ddr%s fsb freq %d, mem freq %d), "
-                                "disabling CxSR\n",
-                                (dev_priv->is_ddr3 == 1) ? "3" : "2",
-                                dev_priv->fsb_freq, dev_priv->mem_freq);
-                       /* Disable CxSR and never update its watermark again */
-                       pineview_disable_cxsr(dev);
-                       dev_priv->display.update_wm = NULL;
-               } else
-                       dev_priv->display.update_wm = pineview_update_wm;
-               dev_priv->display.init_clock_gating = gen3_init_clock_gating;
+       } else if (IS_VALLEYVIEW(dev)) {
+               dev_priv->display.force_wake_get = vlv_force_wake_get;
+               dev_priv->display.force_wake_put = vlv_force_wake_put;
        } else if (IS_G4X(dev)) {
                dev_priv->display.write_eld = g4x_write_eld;
-               dev_priv->display.update_wm = g4x_update_wm;
-               dev_priv->display.init_clock_gating = g4x_init_clock_gating;
-       } else if (IS_GEN4(dev)) {
-               dev_priv->display.update_wm = i965_update_wm;
-               if (IS_CRESTLINE(dev))
-                       dev_priv->display.init_clock_gating = crestline_init_clock_gating;
-               else if (IS_BROADWATER(dev))
-                       dev_priv->display.init_clock_gating = broadwater_init_clock_gating;
-       } else if (IS_GEN3(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))
-                       dev_priv->display.get_fifo_size = i845_get_fifo_size;
-               else
-                       dev_priv->display.get_fifo_size = i830_get_fifo_size;
        }
 
        /* Default just returns -ENODEV to indicate unsupported */
@@ -9030,7 +6512,7 @@ static void quirk_pipea_force(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        dev_priv->quirks |= QUIRK_PIPEA_FORCE;
-       DRM_DEBUG_DRIVER("applying pipe a force quirk\n");
+       DRM_INFO("applying pipe a force quirk\n");
 }
 
 /*
@@ -9040,6 +6522,18 @@ static void quirk_ssc_force_disable(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        dev_priv->quirks |= QUIRK_LVDS_SSC_DISABLE;
+       DRM_INFO("applying lvds SSC disable quirk\n");
+}
+
+/*
+ * A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight
+ * brightness value
+ */
+static void quirk_invert_brightness(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       dev_priv->quirks |= QUIRK_INVERT_BRIGHTNESS;
+       DRM_INFO("applying inverted panel brightness quirk\n");
 }
 
 struct intel_quirk {
@@ -9049,7 +6543,7 @@ struct intel_quirk {
        void (*hook)(struct drm_device *dev);
 };
 
-struct intel_quirk intel_quirks[] = {
+static struct intel_quirk intel_quirks[] = {
        /* HP Mini needs pipe A force quirk (LP: #322104) */
        { 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
 
@@ -9074,6 +6568,9 @@ struct intel_quirk intel_quirks[] = {
 
        /* Sony Vaio Y cannot use SSC on LVDS */
        { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
+
+       /* Acer Aspire 5734Z must invert backlight brightness */
+       { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
@@ -9106,7 +6603,7 @@ static void i915_disable_vga(struct drm_device *dev)
                vga_reg = VGACNTRL;
 
        vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
-       outb(1, VGA_SR_INDEX);
+       outb(SR01, VGA_SR_INDEX);
        sr1 = inb(VGA_SR_DATA);
        outb(sr1 | 1<<5, VGA_SR_DATA);
        vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
@@ -9116,6 +6613,39 @@ static void i915_disable_vga(struct drm_device *dev)
        POSTING_READ(vga_reg);
 }
 
+static void ivb_pch_pwm_override(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       /*
+        * IVB has CPU eDP backlight regs too, set things up to let the
+        * PCH regs control the backlight
+        */
+       I915_WRITE(BLC_PWM_CPU_CTL2, PWM_ENABLE);
+       I915_WRITE(BLC_PWM_CPU_CTL, 0);
+       I915_WRITE(BLC_PWM_PCH_CTL1, PWM_ENABLE | (1<<30));
+}
+
+void intel_modeset_init_hw(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       intel_init_clock_gating(dev);
+
+       if (IS_IRONLAKE_M(dev)) {
+               ironlake_enable_drps(dev);
+               intel_init_emon(dev);
+       }
+
+       if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
+               gen6_enable_rps(dev_priv);
+               gen6_update_ring_freq(dev_priv);
+       }
+
+       if (IS_IVYBRIDGE(dev))
+               ivb_pch_pwm_override(dev);
+}
+
 void intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -9133,6 +6663,8 @@ void intel_modeset_init(struct drm_device *dev)
 
        intel_init_quirks(dev);
 
+       intel_init_pm(dev);
+
        intel_init_display(dev);
 
        if (IS_GEN2(dev)) {
@@ -9157,21 +6689,13 @@ void intel_modeset_init(struct drm_device *dev)
                        DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
        }
 
+       intel_pch_pll_init(dev);
+
        /* Just disable it once at startup */
        i915_disable_vga(dev);
        intel_setup_outputs(dev);
 
-       intel_init_clock_gating(dev);
-
-       if (IS_IRONLAKE_M(dev)) {
-               ironlake_enable_drps(dev);
-               intel_init_emon(dev);
-       }
-
-       if (IS_GEN6(dev) || IS_GEN7(dev)) {
-               gen6_enable_rps(dev_priv);
-               gen6_update_ring_freq(dev_priv);
-       }
+       intel_modeset_init_hw(dev);
 
        INIT_WORK(&dev_priv->idle_work, intel_idle_update);
        setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
@@ -9211,12 +6735,15 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        if (IS_IRONLAKE_M(dev))
                ironlake_disable_drps(dev);
-       if (IS_GEN6(dev) || IS_GEN7(dev))
+       if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev))
                gen6_disable_rps(dev);
 
        if (IS_IRONLAKE_M(dev))
                ironlake_disable_rc6(dev);
 
+       if (IS_VALLEYVIEW(dev))
+               vlv_init_dpio(dev);
+
        mutex_unlock(&dev->struct_mutex);
 
        /* Disable the irq before mode object teardown, for the irq might
index 110552ff302c1dea71360dfc84da622d1cec1785..a1a5ce71558a5d7d288f288f11c051873957175f 100644 (file)
@@ -219,14 +219,38 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
        return (max_link_clock * max_lanes * 8) / 10;
 }
 
+static bool
+intel_dp_adjust_dithering(struct intel_dp *intel_dp,
+                         struct drm_display_mode *mode,
+                         struct drm_display_mode *adjusted_mode)
+{
+       int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
+       int max_lanes = intel_dp_max_lane_count(intel_dp);
+       int max_rate, mode_rate;
+
+       mode_rate = intel_dp_link_required(mode->clock, 24);
+       max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
+
+       if (mode_rate > max_rate) {
+               mode_rate = intel_dp_link_required(mode->clock, 18);
+               if (mode_rate > max_rate)
+                       return false;
+
+               if (adjusted_mode)
+                       adjusted_mode->private_flags
+                               |= INTEL_MODE_DP_FORCE_6BPC;
+
+               return true;
+       }
+
+       return true;
+}
+
 static int
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
 {
        struct intel_dp *intel_dp = intel_attached_dp(connector);
-       int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
-       int max_lanes = intel_dp_max_lane_count(intel_dp);
-       int max_rate, mode_rate;
 
        if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
                if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
@@ -236,16 +260,8 @@ intel_dp_mode_valid(struct drm_connector *connector,
                        return MODE_PANEL;
        }
 
-       mode_rate = intel_dp_link_required(mode->clock, 24);
-       max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
-
-       if (mode_rate > max_rate) {
-                       mode_rate = intel_dp_link_required(mode->clock, 18);
-                       if (mode_rate > max_rate)
-                               return MODE_CLOCK_HIGH;
-                       else
-                               mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC;
-       }
+       if (!intel_dp_adjust_dithering(intel_dp, mode, NULL))
+               return MODE_CLOCK_HIGH;
 
        if (mode->clock < 10000)
                return MODE_CLOCK_LOW;
@@ -672,7 +688,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
        int lane_count, clock;
        int max_lane_count = intel_dp_max_lane_count(intel_dp);
        int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
-       int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
+       int bpp, mode_rate;
        static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 
        if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
@@ -686,19 +702,30 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
                mode->clock = intel_dp->panel_fixed_mode->clock;
        }
 
+       DRM_DEBUG_KMS("DP link computation with max lane count %i "
+                     "max bw %02x pixel clock %iKHz\n",
+                     max_lane_count, bws[max_clock], mode->clock);
+
+       if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode))
+               return false;
+
+       bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
+       mode_rate = intel_dp_link_required(mode->clock, bpp);
+
        for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
                for (clock = 0; clock <= max_clock; clock++) {
                        int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
-                       if (intel_dp_link_required(mode->clock, bpp)
-                                       <= link_avail) {
+                       if (mode_rate <= link_avail) {
                                intel_dp->link_bw = bws[clock];
                                intel_dp->lane_count = lane_count;
                                adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
-                               DRM_DEBUG_KMS("Display port link bw %02x lane "
-                                               "count %d clock %d\n",
+                               DRM_DEBUG_KMS("DP link bw %02x lane "
+                                               "count %d clock %d bpp %d\n",
                                       intel_dp->link_bw, intel_dp->lane_count,
-                                      adjusted_mode->clock);
+                                      adjusted_mode->clock, bpp);
+                               DRM_DEBUG_KMS("DP link bw required %i available %i\n",
+                                             mode_rate, link_avail);
                                return true;
                        }
                }
@@ -1128,6 +1155,7 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
        DRM_DEBUG_KMS("Turn eDP power off\n");
 
        WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n");
+       ironlake_panel_vdd_off_sync(intel_dp); /* finish any pending work */
 
        pp = ironlake_get_pp_control(dev_priv);
        pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
@@ -2417,6 +2445,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
        }
 
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+
        connector->interlace_allowed = true;
        connector->doublescan_allowed = 0;
 
@@ -2462,6 +2491,13 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                pp_off = I915_READ(PCH_PP_OFF_DELAYS);
                pp_div = I915_READ(PCH_PP_DIVISOR);
 
+               if (!pp_on || !pp_off || !pp_div) {
+                       DRM_INFO("bad panel power sequencing delays, disabling panel\n");
+                       intel_dp_encoder_destroy(&intel_dp->base.base);
+                       intel_dp_destroy(&intel_connector->base);
+                       return;
+               }
+
                /* Pull timing values out of registers */
                cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
                        PANEL_POWER_UP_DELAY_SHIFT;
index 5a14149b3794237ad26ee24bce00b5938e157b93..e5ee166e2faf82ada74d7e7559fe0a6aa5f4006b 100644 (file)
        ret__;                                                          \
 })
 
+#define wait_for_atomic_us(COND, US) ({ \
+       int i, ret__ = -ETIMEDOUT;      \
+       for (i = 0; i < (US); i++) {    \
+               if ((COND)) {           \
+                       ret__ = 0;      \
+                       break;          \
+               }                       \
+               udelay(1);              \
+       }                               \
+       ret__;                          \
+})
+
 #define wait_for(COND, MS) _wait_for(COND, MS, 1)
 #define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0)
 
 #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
 #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
 #define INTEL_MODE_DP_FORCE_6BPC (0x10)
+/* This flag must be set by the encoder's mode_fixup if it changes the crtc
+ * timings in the mode to prevent the crtc fixup from overwriting them.
+ * Currently only lvds needs that. */
+#define INTEL_MODE_CRTC_TIMINGS_SET (0x20)
 
 static inline void
 intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
@@ -167,8 +183,8 @@ struct intel_crtc {
        bool cursor_visible;
        unsigned int bpp;
 
-       bool no_pll; /* tertiary pipe for IVB */
-       bool use_pll_a;
+       /* We can share PLLs across outputs if the timings match */
+       struct intel_pch_pll *pch_pll;
 };
 
 struct intel_plane {
@@ -192,6 +208,25 @@ struct intel_plane {
                             struct drm_intel_sprite_colorkey *key);
 };
 
+struct intel_watermark_params {
+       unsigned long fifo_size;
+       unsigned long max_wm;
+       unsigned long default_wm;
+       unsigned long guard_size;
+       unsigned long cacheline_size;
+};
+
+struct cxsr_latency {
+       int is_desktop;
+       int is_ddr3;
+       unsigned long fsb_freq;
+       unsigned long mem_freq;
+       unsigned long display_sr;
+       unsigned long display_hpll_disable;
+       unsigned long cursor_sr;
+       unsigned long cursor_hpll_disable;
+};
+
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 #define to_intel_connector(x) container_of(x, struct intel_connector, base)
 #define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
@@ -203,6 +238,8 @@ struct intel_plane {
 #define DIP_TYPE_AVI    0x82
 #define DIP_VERSION_AVI 0x2
 #define DIP_LEN_AVI     13
+#define DIP_AVI_PR_1    0
+#define DIP_AVI_PR_2    1
 
 #define DIP_TYPE_SPD   0x83
 #define DIP_VERSION_SPD        0x1
@@ -236,8 +273,8 @@ struct dip_infoframe {
                        uint8_t ITC_EC_Q_SC;
                        /* PB4 - VIC 6:0 */
                        uint8_t VIC;
-                       /* PB5 - PR 3:0 */
-                       uint8_t PR;
+                       /* PB5 - YQ 7:6, CN 5:4, PR 3:0 */
+                       uint8_t YQ_CN_PR;
                        /* PB6 to PB13 */
                        uint16_t top_bar_end;
                        uint16_t bottom_bar_start;
@@ -293,7 +330,8 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector)
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
 void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
-extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
+extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
+                           bool is_sdvob);
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
 extern void intel_mark_busy(struct drm_device *dev,
@@ -307,6 +345,10 @@ extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
 extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
+extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
+                                     enum plane plane);
+
+void intel_sanitize_pm(struct drm_device *dev);
 
 /* intel_panel.c */
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
@@ -364,12 +406,9 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
 extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
                                    u16 *blue, int regno);
 extern void intel_enable_clock_gating(struct drm_device *dev);
+extern void ironlake_disable_rc6(struct drm_device *dev);
 extern void ironlake_enable_drps(struct drm_device *dev);
 extern void ironlake_disable_drps(struct drm_device *dev);
-extern void gen6_enable_rps(struct drm_i915_private *dev_priv);
-extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv);
-extern void gen6_disable_rps(struct drm_device *dev);
-extern void intel_init_emon(struct drm_device *dev);
 
 extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
                                      struct drm_i915_gem_object *obj,
@@ -409,7 +448,7 @@ extern void intel_write_eld(struct drm_encoder *encoder,
 extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
 
 /* For use by IVB LP watermark workaround in intel_sprite.c */
-extern void sandybridge_update_wm(struct drm_device *dev);
+extern void intel_update_watermarks(struct drm_device *dev);
 extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
                                           uint32_t sprite_width,
                                           int pixel_size);
@@ -419,4 +458,21 @@ extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
                                     struct drm_file *file_priv);
 
+extern u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg);
+
+/* Power-related functions, located in intel_pm.c */
+extern void intel_init_pm(struct drm_device *dev);
+/* FBC */
+extern bool intel_fbc_enabled(struct drm_device *dev);
+extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
+extern void intel_update_fbc(struct drm_device *dev);
+/* IPS */
+extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
+extern void intel_gpu_ips_teardown(void);
+
+extern void gen6_enable_rps(struct drm_i915_private *dev_priv);
+extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv);
+extern void gen6_disable_rps(struct drm_device *dev);
+extern void intel_init_emon(struct drm_device *dev);
+
 #endif /* __INTEL_DRV_H__ */
index 020a7d7f744dcc9608d9a652d2b0d0d4b1035ea7..60ba50b956f22c9478318d4fa3a54e20de86b179 100644 (file)
@@ -243,7 +243,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
         * that's not the case.
         */
        intel_ddc_get_modes(connector,
-                           &dev_priv->gmbus[GMBUS_PORT_DPC].adapter);
+                           intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPC));
        if (!list_empty(&connector->probed_modes))
                return 1;
 
@@ -375,7 +375,7 @@ void intel_dvo_init(struct drm_device *dev)
                 * special cases, but otherwise default to what's defined
                 * in the spec.
                 */
-               if (dvo->gpio != 0)
+               if (intel_gmbus_is_port_valid(dvo->gpio))
                        gpio = dvo->gpio;
                else if (dvo->type == INTEL_DVO_CHIP_LVDS)
                        gpio = GMBUS_PORT_SSC;
@@ -386,7 +386,7 @@ void intel_dvo_init(struct drm_device *dev)
                 * It appears that everything is on GPIOE except for panels
                 * on i830 laptops, which are on GPIOB (DVOA).
                 */
-               i2c = &dev_priv->gmbus[gpio].adapter;
+               i2c = intel_gmbus_get_adapter(dev_priv, gpio);
 
                intel_dvo->dev = *dvo;
                if (!dvo->dev_ops->init(&intel_dvo->dev, i2c))
index 19ecd78b8a2ce572c98b1407122e1d97d94c4781..bf8690720a0cb882b5d99f6edee38b46d7ff48ec 100644 (file)
@@ -94,7 +94,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
        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, false);
+       ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
        if (ret) {
                DRM_ERROR("failed to pin fb: %d\n", ret);
                goto out_unref;
@@ -279,6 +279,8 @@ void intel_fb_restore_mode(struct drm_device *dev)
        struct drm_mode_config *config = &dev->mode_config;
        struct drm_plane *plane;
 
+       mutex_lock(&dev->mode_config.mutex);
+
        ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
        if (ret)
                DRM_DEBUG("failed to restore crtc mode\n");
@@ -286,4 +288,6 @@ void intel_fb_restore_mode(struct drm_device *dev)
        /* Be sure to shut off any planes that may be active */
        list_for_each_entry(plane, &config->plane_list, head)
                plane->funcs->disable_plane(plane);
+
+       mutex_unlock(&dev->mode_config.mutex);
 }
index cae3e5f17a49d8b767a371710935dcf89146121a..bf218753cbaf818086704aa9217c81bf713407f5 100644 (file)
@@ -136,7 +136,7 @@ static void i9xx_write_infoframe(struct drm_encoder *encoder,
 
        val &= ~VIDEO_DIP_SELECT_MASK;
 
-       I915_WRITE(VIDEO_DIP_CTL, val | port | flags);
+       I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags);
 
        for (i = 0; i < len; i += 4) {
                I915_WRITE(VIDEO_DIP_DATA, *data);
@@ -177,6 +177,37 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder,
 
        I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
 }
+
+static void vlv_write_infoframe(struct drm_encoder *encoder,
+                                    struct dip_infoframe *frame)
+{
+       uint32_t *data = (uint32_t *)frame;
+       struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = encoder->crtc;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
+       unsigned i, len = DIP_HEADER_SIZE + frame->len;
+       u32 flags, val = I915_READ(reg);
+
+       intel_wait_for_vblank(dev, intel_crtc->pipe);
+
+       flags = intel_infoframe_index(frame);
+
+       val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
+
+       I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
+
+       for (i = 0; i < len; i += 4) {
+               I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
+               data++;
+       }
+
+       flags |= intel_infoframe_flags(frame);
+
+       I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
+}
+
 static void intel_set_infoframe(struct drm_encoder *encoder,
                                struct dip_infoframe *frame)
 {
@@ -189,7 +220,8 @@ static void intel_set_infoframe(struct drm_encoder *encoder,
        intel_hdmi->write_infoframe(encoder, frame);
 }
 
-static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
+static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
+                                        struct drm_display_mode *adjusted_mode)
 {
        struct dip_infoframe avi_if = {
                .type = DIP_TYPE_AVI,
@@ -197,6 +229,9 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
                .len = DIP_LEN_AVI,
        };
 
+       if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
+               avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2;
+
        intel_set_infoframe(encoder, &avi_if);
 }
 
@@ -259,7 +294,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
        I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
        POSTING_READ(intel_hdmi->sdvox_reg);
 
-       intel_hdmi_set_avi_infoframe(encoder);
+       intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
        intel_hdmi_set_spd_infoframe(encoder);
 }
 
@@ -334,7 +369,8 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
        intel_hdmi->has_hdmi_sink = false;
        intel_hdmi->has_audio = false;
        edid = drm_get_edid(connector,
-                           &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
+                           intel_gmbus_get_adapter(dev_priv,
+                                                   intel_hdmi->ddc_bus));
 
        if (edid) {
                if (edid->input & DRM_EDID_INPUT_DIGITAL) {
@@ -367,7 +403,8 @@ static int intel_hdmi_get_modes(struct drm_connector *connector)
         */
 
        return intel_ddc_get_modes(connector,
-                                  &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
+                                  intel_gmbus_get_adapter(dev_priv,
+                                                          intel_hdmi->ddc_bus));
 }
 
 static bool
@@ -379,7 +416,8 @@ intel_hdmi_detect_audio(struct drm_connector *connector)
        bool has_audio = false;
 
        edid = drm_get_edid(connector,
-                           &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
+                           intel_gmbus_get_adapter(dev_priv,
+                                                   intel_hdmi->ddc_bus));
        if (edid) {
                if (edid->input & DRM_EDID_INPUT_DIGITAL)
                        has_audio = drm_detect_monitor_audio(edid);
@@ -549,7 +587,11 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
        if (!HAS_PCH_SPLIT(dev)) {
                intel_hdmi->write_infoframe = i9xx_write_infoframe;
                I915_WRITE(VIDEO_DIP_CTL, 0);
-       } else {
+       } else if (IS_VALLEYVIEW(dev)) {
+               intel_hdmi->write_infoframe = vlv_write_infoframe;
+               for_each_pipe(i)
+                       I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0);
+       }  else {
                intel_hdmi->write_infoframe = ironlake_write_infoframe;
                for_each_pipe(i)
                        I915_WRITE(TVIDEO_DIP_CTL(i), 0);
index 601c86e664afd237875aefc43fe65a0671930cb5..e04255edc8010beddc22c5b9f07f0423293b6108 100644 (file)
 #include "i915_drm.h"
 #include "i915_drv.h"
 
+struct gmbus_port {
+       const char *name;
+       int reg;
+};
+
+static const struct gmbus_port gmbus_ports[] = {
+       { "ssc", GPIOB },
+       { "vga", GPIOA },
+       { "panel", GPIOC },
+       { "dpc", GPIOD },
+       { "dpb", GPIOE },
+       { "dpd", GPIOF },
+};
+
 /* Intel GPIO access functions */
 
 #define I2C_RISEFALL_TIME 10
@@ -49,10 +63,7 @@ void
 intel_i2c_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       if (HAS_PCH_SPLIT(dev))
-               I915_WRITE(PCH_GMBUS0, 0);
-       else
-               I915_WRITE(GMBUS0, 0);
+       I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);
 }
 
 static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
@@ -140,63 +151,173 @@ static void set_data(void *data, int state_high)
        POSTING_READ(bus->gpio_reg);
 }
 
-static bool
+static int
+intel_gpio_pre_xfer(struct i2c_adapter *adapter)
+{
+       struct intel_gmbus *bus = container_of(adapter,
+                                              struct intel_gmbus,
+                                              adapter);
+       struct drm_i915_private *dev_priv = bus->dev_priv;
+
+       intel_i2c_reset(dev_priv->dev);
+       intel_i2c_quirk_set(dev_priv, true);
+       set_data(bus, 1);
+       set_clock(bus, 1);
+       udelay(I2C_RISEFALL_TIME);
+       return 0;
+}
+
+static void
+intel_gpio_post_xfer(struct i2c_adapter *adapter)
+{
+       struct intel_gmbus *bus = container_of(adapter,
+                                              struct intel_gmbus,
+                                              adapter);
+       struct drm_i915_private *dev_priv = bus->dev_priv;
+
+       set_data(bus, 1);
+       set_clock(bus, 1);
+       intel_i2c_quirk_set(dev_priv, false);
+}
+
+static void
 intel_gpio_setup(struct intel_gmbus *bus, u32 pin)
 {
        struct drm_i915_private *dev_priv = bus->dev_priv;
-       static const int map_pin_to_reg[] = {
-               0,
-               GPIOB,
-               GPIOA,
-               GPIOC,
-               GPIOD,
-               GPIOE,
-               0,
-               GPIOF,
-       };
        struct i2c_algo_bit_data *algo;
 
-       if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin])
-               return false;
-
        algo = &bus->bit_algo;
 
-       bus->gpio_reg = map_pin_to_reg[pin];
-       if (HAS_PCH_SPLIT(dev_priv->dev))
-               bus->gpio_reg += PCH_GPIOA - GPIOA;
+       /* -1 to map pin pair to gmbus index */
+       bus->gpio_reg = dev_priv->gpio_mmio_base + gmbus_ports[pin - 1].reg;
 
        bus->adapter.algo_data = algo;
        algo->setsda = set_data;
        algo->setscl = set_clock;
        algo->getsda = get_data;
        algo->getscl = get_clock;
+       algo->pre_xfer = intel_gpio_pre_xfer;
+       algo->post_xfer = intel_gpio_post_xfer;
        algo->udelay = I2C_RISEFALL_TIME;
        algo->timeout = usecs_to_jiffies(2200);
        algo->data = bus;
+}
+
+static int
+gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
+               u32 gmbus1_index)
+{
+       int reg_offset = dev_priv->gpio_mmio_base;
+       u16 len = msg->len;
+       u8 *buf = msg->buf;
+
+       I915_WRITE(GMBUS1 + reg_offset,
+                  gmbus1_index |
+                  GMBUS_CYCLE_WAIT |
+                  (len << GMBUS_BYTE_COUNT_SHIFT) |
+                  (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                  GMBUS_SLAVE_READ | GMBUS_SW_RDY);
+       while (len) {
+               int ret;
+               u32 val, loop = 0;
+               u32 gmbus2;
+
+               ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) &
+                              (GMBUS_SATOER | GMBUS_HW_RDY),
+                              50);
+               if (ret)
+                       return -ETIMEDOUT;
+               if (gmbus2 & GMBUS_SATOER)
+                       return -ENXIO;
+
+               val = I915_READ(GMBUS3 + reg_offset);
+               do {
+                       *buf++ = val & 0xff;
+                       val >>= 8;
+               } while (--len && ++loop < 4);
+       }
 
-       return true;
+       return 0;
 }
 
 static int
-intel_i2c_quirk_xfer(struct intel_gmbus *bus,
-                    struct i2c_msg *msgs,
-                    int num)
+gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
 {
-       struct drm_i915_private *dev_priv = bus->dev_priv;
+       int reg_offset = dev_priv->gpio_mmio_base;
+       u16 len = msg->len;
+       u8 *buf = msg->buf;
+       u32 val, loop;
+
+       val = loop = 0;
+       while (len && loop < 4) {
+               val |= *buf++ << (8 * loop++);
+               len -= 1;
+       }
+
+       I915_WRITE(GMBUS3 + reg_offset, val);
+       I915_WRITE(GMBUS1 + reg_offset,
+                  GMBUS_CYCLE_WAIT |
+                  (msg->len << GMBUS_BYTE_COUNT_SHIFT) |
+                  (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                  GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
+       while (len) {
+               int ret;
+               u32 gmbus2;
+
+               val = loop = 0;
+               do {
+                       val |= *buf++ << (8 * loop);
+               } while (--len && ++loop < 4);
+
+               I915_WRITE(GMBUS3 + reg_offset, val);
+
+               ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) &
+                              (GMBUS_SATOER | GMBUS_HW_RDY),
+                              50);
+               if (ret)
+                       return -ETIMEDOUT;
+               if (gmbus2 & GMBUS_SATOER)
+                       return -ENXIO;
+       }
+       return 0;
+}
+
+/*
+ * The gmbus controller can combine a 1 or 2 byte write with a read that
+ * immediately follows it by using an "INDEX" cycle.
+ */
+static bool
+gmbus_is_index_read(struct i2c_msg *msgs, int i, int num)
+{
+       return (i + 1 < num &&
+               !(msgs[i].flags & I2C_M_RD) && msgs[i].len <= 2 &&
+               (msgs[i + 1].flags & I2C_M_RD));
+}
+
+static int
+gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
+{
+       int reg_offset = dev_priv->gpio_mmio_base;
+       u32 gmbus1_index = 0;
+       u32 gmbus5 = 0;
        int ret;
 
-       intel_i2c_reset(dev_priv->dev);
+       if (msgs[0].len == 2)
+               gmbus5 = GMBUS_2BYTE_INDEX_EN |
+                        msgs[0].buf[1] | (msgs[0].buf[0] << 8);
+       if (msgs[0].len == 1)
+               gmbus1_index = GMBUS_CYCLE_INDEX |
+                              (msgs[0].buf[0] << GMBUS_SLAVE_INDEX_SHIFT);
 
-       intel_i2c_quirk_set(dev_priv, true);
-       set_data(bus, 1);
-       set_clock(bus, 1);
-       udelay(I2C_RISEFALL_TIME);
+       /* GMBUS5 holds 16-bit index */
+       if (gmbus5)
+               I915_WRITE(GMBUS5 + reg_offset, gmbus5);
 
-       ret = i2c_bit_algo.master_xfer(&bus->adapter, msgs, num);
+       ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
 
-       set_data(bus, 1);
-       set_clock(bus, 1);
-       intel_i2c_quirk_set(dev_priv, false);
+       /* Clear GMBUS5 after each index transfer */
+       if (gmbus5)
+               I915_WRITE(GMBUS5 + reg_offset, 0);
 
        return ret;
 }
@@ -210,117 +331,108 @@ gmbus_xfer(struct i2c_adapter *adapter,
                                               struct intel_gmbus,
                                               adapter);
        struct drm_i915_private *dev_priv = bus->dev_priv;
-       int i, reg_offset, ret;
+       int i, reg_offset;
+       int ret = 0;
 
        mutex_lock(&dev_priv->gmbus_mutex);
 
        if (bus->force_bit) {
-               ret = intel_i2c_quirk_xfer(bus, msgs, num);
+               ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
                goto out;
        }
 
-       reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0;
+       reg_offset = dev_priv->gpio_mmio_base;
 
        I915_WRITE(GMBUS0 + reg_offset, bus->reg0);
 
        for (i = 0; i < num; i++) {
-               u16 len = msgs[i].len;
-               u8 *buf = msgs[i].buf;
-
-               if (msgs[i].flags & I2C_M_RD) {
-                       I915_WRITE(GMBUS1 + reg_offset,
-                                  GMBUS_CYCLE_WAIT |
-                                  (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
-                                  (len << GMBUS_BYTE_COUNT_SHIFT) |
-                                  (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
-                                  GMBUS_SLAVE_READ | GMBUS_SW_RDY);
-                       POSTING_READ(GMBUS2+reg_offset);
-                       do {
-                               u32 val, loop = 0;
-
-                               if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
-                                       goto timeout;
-                               if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
-                                       goto clear_err;
-
-                               val = I915_READ(GMBUS3 + reg_offset);
-                               do {
-                                       *buf++ = val & 0xff;
-                                       val >>= 8;
-                               } while (--len && ++loop < 4);
-                       } while (len);
+               u32 gmbus2;
+
+               if (gmbus_is_index_read(msgs, i, num)) {
+                       ret = gmbus_xfer_index_read(dev_priv, &msgs[i]);
+                       i += 1;  /* set i to the index of the read xfer */
+               } else if (msgs[i].flags & I2C_M_RD) {
+                       ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
                } else {
-                       u32 val, loop;
-
-                       val = loop = 0;
-                       do {
-                               val |= *buf++ << (8 * loop);
-                       } while (--len && ++loop < 4);
-
-                       I915_WRITE(GMBUS3 + reg_offset, val);
-                       I915_WRITE(GMBUS1 + reg_offset,
-                                  GMBUS_CYCLE_WAIT |
-                                  (i + 1 == num ? GMBUS_CYCLE_STOP : 0) |
-                                  (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) |
-                                  (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) |
-                                  GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
-                       POSTING_READ(GMBUS2+reg_offset);
-
-                       while (len) {
-                               if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
-                                       goto timeout;
-                               if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
-                                       goto clear_err;
-
-                               val = loop = 0;
-                               do {
-                                       val |= *buf++ << (8 * loop);
-                               } while (--len && ++loop < 4);
-
-                               I915_WRITE(GMBUS3 + reg_offset, val);
-                               POSTING_READ(GMBUS2+reg_offset);
-                       }
+                       ret = gmbus_xfer_write(dev_priv, &msgs[i]);
                }
 
-               if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50))
+               if (ret == -ETIMEDOUT)
                        goto timeout;
-               if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
+               if (ret == -ENXIO)
+                       goto clear_err;
+
+               ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) &
+                              (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE),
+                              50);
+               if (ret)
+                       goto timeout;
+               if (gmbus2 & GMBUS_SATOER)
                        goto clear_err;
        }
 
-       goto done;
+       /* Generate a STOP condition on the bus. Note that gmbus can't generata
+        * a STOP on the very first cycle. To simplify the code we
+        * unconditionally generate the STOP condition with an additional gmbus
+        * cycle. */
+       I915_WRITE(GMBUS1 + reg_offset, GMBUS_CYCLE_STOP | GMBUS_SW_RDY);
+
+       /* Mark the GMBUS interface as disabled after waiting for idle.
+        * We will re-enable it at the start of the next xfer,
+        * till then let it sleep.
+        */
+       if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0,
+                    10)) {
+               DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n",
+                        adapter->name);
+               ret = -ETIMEDOUT;
+       }
+       I915_WRITE(GMBUS0 + reg_offset, 0);
+       ret = ret ?: i;
+       goto out;
 
 clear_err:
+       /*
+        * Wait for bus to IDLE before clearing NAK.
+        * If we clear the NAK while bus is still active, then it will stay
+        * active and the next transaction may fail.
+        */
+       if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0,
+                    10))
+               DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n",
+                             adapter->name);
+
        /* Toggle the Software Clear Interrupt bit. This has the effect
         * of resetting the GMBUS controller and so clearing the
         * BUS_ERROR raised by the slave's NAK.
         */
        I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT);
        I915_WRITE(GMBUS1 + reg_offset, 0);
+       I915_WRITE(GMBUS0 + reg_offset, 0);
 
-done:
-       /* Mark the GMBUS interface as disabled after waiting for idle.
-        * We will re-enable it at the start of the next xfer,
-        * till then let it sleep.
+       DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n",
+                        adapter->name, msgs[i].addr,
+                        (msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
+
+       /*
+        * If no ACK is received during the address phase of a transaction,
+        * the adapter must report -ENXIO.
+        * It is not clear what to return if no ACK is received at other times.
+        * So, we always return -ENXIO in all NAK cases, to ensure we send
+        * it at least during the one case that is specified.
         */
-       if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10))
-               DRM_INFO("GMBUS timed out waiting for idle\n");
-       I915_WRITE(GMBUS0 + reg_offset, 0);
-       ret = i;
+       ret = -ENXIO;
        goto out;
 
 timeout:
-       DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n",
-                bus->reg0 & 0xff, bus->adapter.name);
+       DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
+                bus->adapter.name, bus->reg0 & 0xff);
        I915_WRITE(GMBUS0 + reg_offset, 0);
 
        /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
-       if (!bus->has_gpio) {
-               ret = -EIO;
-       } else {
-               bus->force_bit = true;
-               ret = intel_i2c_quirk_xfer(bus, msgs, num);
-       }
+       bus->force_bit = true;
+       ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
+
 out:
        mutex_unlock(&dev_priv->gmbus_mutex);
        return ret;
@@ -346,35 +458,26 @@ static const struct i2c_algorithm gmbus_algorithm = {
  */
 int intel_setup_gmbus(struct drm_device *dev)
 {
-       static const char *names[GMBUS_NUM_PORTS] = {
-               "disabled",
-               "ssc",
-               "vga",
-               "panel",
-               "dpc",
-               "dpb",
-               "reserved",
-               "dpd",
-       };
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret, i;
 
-       dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus),
-                                 GFP_KERNEL);
-       if (dev_priv->gmbus == NULL)
-               return -ENOMEM;
+       if (HAS_PCH_SPLIT(dev))
+               dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA;
+       else
+               dev_priv->gpio_mmio_base = 0;
 
        mutex_init(&dev_priv->gmbus_mutex);
 
        for (i = 0; i < GMBUS_NUM_PORTS; i++) {
                struct intel_gmbus *bus = &dev_priv->gmbus[i];
+               u32 port = i + 1; /* +1 to map gmbus index to pin pair */
 
                bus->adapter.owner = THIS_MODULE;
                bus->adapter.class = I2C_CLASS_DDC;
                snprintf(bus->adapter.name,
                         sizeof(bus->adapter.name),
                         "i915 gmbus %s",
-                        names[i]);
+                        gmbus_ports[i].name);
 
                bus->adapter.dev.parent = &dev->pdev->dev;
                bus->dev_priv = dev_priv;
@@ -385,13 +488,9 @@ int intel_setup_gmbus(struct drm_device *dev)
                        goto err;
 
                /* By default use a conservative clock rate */
-               bus->reg0 = i | GMBUS_RATE_100KHZ;
-
-               bus->has_gpio = intel_gpio_setup(bus, i);
+               bus->reg0 = port | GMBUS_RATE_100KHZ;
 
-               /* XXX force bit banging until GMBUS is fully debugged */
-               if (bus->has_gpio && IS_GEN2(dev))
-                       bus->force_bit = true;
+               intel_gpio_setup(bus, port);
        }
 
        intel_i2c_reset(dev_priv->dev);
@@ -403,11 +502,18 @@ err:
                struct intel_gmbus *bus = &dev_priv->gmbus[i];
                i2c_del_adapter(&bus->adapter);
        }
-       kfree(dev_priv->gmbus);
-       dev_priv->gmbus = NULL;
        return ret;
 }
 
+struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv,
+                                           unsigned port)
+{
+       WARN_ON(!intel_gmbus_is_port_valid(port));
+       /* -1 to map pin pair to gmbus index */
+       return (intel_gmbus_is_port_valid(port)) ?
+               &dev_priv->gmbus[port - 1].adapter : NULL;
+}
+
 void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed)
 {
        struct intel_gmbus *bus = to_intel_gmbus(adapter);
@@ -419,8 +525,7 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
 {
        struct intel_gmbus *bus = to_intel_gmbus(adapter);
 
-       if (bus->has_gpio)
-               bus->force_bit = force_bit;
+       bus->force_bit = force_bit;
 }
 
 void intel_teardown_gmbus(struct drm_device *dev)
@@ -435,7 +540,4 @@ void intel_teardown_gmbus(struct drm_device *dev)
                struct intel_gmbus *bus = &dev_priv->gmbus[i];
                i2c_del_adapter(&bus->adapter);
        }
-
-       kfree(dev_priv->gmbus);
-       dev_priv->gmbus = NULL;
 }
index c5c0973af8a112073d5f50896560ade0c407b91b..9dee82350defb0590ecc16326a4cdd712d15b0e4 100644 (file)
@@ -187,6 +187,8 @@ centre_horizontally(struct drm_display_mode *mode,
 
        mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
        mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
+
+       mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
 }
 
 static void
@@ -208,6 +210,8 @@ centre_vertically(struct drm_display_mode *mode,
 
        mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
        mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
+
+       mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
 }
 
 static inline u32 panel_fitter_scaling(u32 source, u32 target)
@@ -283,6 +287,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
        for_each_pipe(pipe)
                I915_WRITE(BCLRPAT(pipe), 0);
 
+       drm_mode_set_crtcinfo(adjusted_mode, 0);
+
        switch (intel_lvds->fitting_mode) {
        case DRM_MODE_SCALE_CENTER:
                /*
@@ -474,7 +480,7 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
 
 static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
 {
-       DRM_DEBUG_KMS("Skipping forced modeset for %s\n", id->ident);
+       DRM_INFO("Skipping forced modeset for %s\n", id->ident);
        return 1;
 }
 
@@ -622,7 +628,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
 
 static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
 {
-       DRM_DEBUG_KMS("Skipping LVDS initialization for %s\n", id->ident);
+       DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
        return 1;
 }
 
@@ -744,7 +750,7 @@ static const struct dmi_system_id intel_no_lvds[] = {
                .ident = "Hewlett-Packard t5745",
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_BOARD_NAME, "hp t5745"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
                },
        },
        {
@@ -752,7 +758,15 @@ static const struct dmi_system_id intel_no_lvds[] = {
                .ident = "Hewlett-Packard st5747",
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_BOARD_NAME, "hp st5747"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
+               },
+       },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "MSI Wind Box DC500",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+                       DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
                },
        },
 
@@ -837,8 +851,8 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
                    child->device_type != DEVICE_TYPE_LFP)
                        continue;
 
-               if (child->i2c_pin)
-                   *i2c_pin = child->i2c_pin;
+               if (intel_gmbus_is_port_valid(child->i2c_pin))
+                       *i2c_pin = child->i2c_pin;
 
                /* However, we cannot trust the BIOS writers to populate
                 * the VBT correctly.  Since LVDS requires additional
@@ -979,7 +993,8 @@ bool intel_lvds_init(struct drm_device *dev)
         * preferred mode is the right one.
         */
        intel_lvds->edid = drm_get_edid(connector,
-                                       &dev_priv->gmbus[pin].adapter);
+                                       intel_gmbus_get_adapter(dev_priv,
+                                                               pin));
        if (intel_lvds->edid) {
                if (drm_add_edid_modes(connector,
                                       intel_lvds->edid)) {
index d1928e79d9b6786de31af6b67cce9ec9962b99a3..d67ec3a51e429cac9eace0a417cb70461ebead2a 100644 (file)
@@ -56,7 +56,8 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus)
                }
        };
 
-       return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2;
+       return i2c_transfer(intel_gmbus_get_adapter(dev_priv, ddc_bus),
+                           msgs, 2) == 2;
 }
 
 /**
index 289140bc83cbd5c5bf5b86bb3f7daa398795d440..18bd0af855dc5605585f09a7edfb98637f6c98e6 100644 (file)
@@ -25,6 +25,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/acpi.h>
 #include <linux/acpi_io.h>
 #include <acpi/video.h>
@@ -149,7 +151,7 @@ struct opregion_asle {
 static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
+       struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
        u32 max;
 
        if (!(bclp & ASLE_BCLP_VALID))
@@ -161,7 +163,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 
        max = intel_panel_get_max_backlight(dev);
        intel_panel_set_backlight(dev, bclp * max / 255);
-       asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
+       iowrite32((bclp*0x64)/0xff | ASLE_CBLV_VALID, &asle->cblv);
 
        return 0;
 }
@@ -198,14 +200,14 @@ static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
 void intel_opregion_asle_intr(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
+       struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
        u32 asle_stat = 0;
        u32 asle_req;
 
        if (!asle)
                return;
 
-       asle_req = asle->aslc & ASLE_REQ_MSK;
+       asle_req = ioread32(&asle->aslc) & ASLE_REQ_MSK;
 
        if (!asle_req) {
                DRM_DEBUG_DRIVER("non asle set request??\n");
@@ -213,31 +215,31 @@ void intel_opregion_asle_intr(struct drm_device *dev)
        }
 
        if (asle_req & ASLE_SET_ALS_ILLUM)
-               asle_stat |= asle_set_als_illum(dev, asle->alsi);
+               asle_stat |= asle_set_als_illum(dev, ioread32(&asle->alsi));
 
        if (asle_req & ASLE_SET_BACKLIGHT)
-               asle_stat |= asle_set_backlight(dev, asle->bclp);
+               asle_stat |= asle_set_backlight(dev, ioread32(&asle->bclp));
 
        if (asle_req & ASLE_SET_PFIT)
-               asle_stat |= asle_set_pfit(dev, asle->pfit);
+               asle_stat |= asle_set_pfit(dev, ioread32(&asle->pfit));
 
        if (asle_req & ASLE_SET_PWM_FREQ)
-               asle_stat |= asle_set_pwm_freq(dev, asle->pfmb);
+               asle_stat |= asle_set_pwm_freq(dev, ioread32(&asle->pfmb));
 
-       asle->aslc = asle_stat;
+       iowrite32(asle_stat, &asle->aslc);
 }
 
 void intel_opregion_gse_intr(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
+       struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
        u32 asle_stat = 0;
        u32 asle_req;
 
        if (!asle)
                return;
 
-       asle_req = asle->aslc & ASLE_REQ_MSK;
+       asle_req = ioread32(&asle->aslc) & ASLE_REQ_MSK;
 
        if (!asle_req) {
                DRM_DEBUG_DRIVER("non asle set request??\n");
@@ -250,7 +252,7 @@ void intel_opregion_gse_intr(struct drm_device *dev)
        }
 
        if (asle_req & ASLE_SET_BACKLIGHT)
-               asle_stat |= asle_set_backlight(dev, asle->bclp);
+               asle_stat |= asle_set_backlight(dev, ioread32(&asle->bclp));
 
        if (asle_req & ASLE_SET_PFIT) {
                DRM_DEBUG_DRIVER("Pfit is not supported\n");
@@ -262,7 +264,7 @@ void intel_opregion_gse_intr(struct drm_device *dev)
                asle_stat |= ASLE_PWM_FREQ_FAILED;
        }
 
-       asle->aslc = asle_stat;
+       iowrite32(asle_stat, &asle->aslc);
 }
 #define ASLE_ALS_EN    (1<<0)
 #define ASLE_BLC_EN    (1<<1)
@@ -272,15 +274,16 @@ void intel_opregion_gse_intr(struct drm_device *dev)
 void intel_opregion_enable_asle(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct opregion_asle *asle = dev_priv->opregion.asle;
+       struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
 
        if (asle) {
                if (IS_MOBILE(dev))
                        intel_enable_asle(dev);
 
-               asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
-                       ASLE_PFMB_EN;
-               asle->ardy = 1;
+               iowrite32(ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN |
+                         ASLE_PFMB_EN,
+                         &asle->tche);
+               iowrite32(1, &asle->ardy);
        }
 }
 
@@ -298,7 +301,7 @@ static int intel_opregion_video_event(struct notifier_block *nb,
           Linux, these are handled by the dock, button and video drivers.
        */
 
-       struct opregion_acpi *acpi;
+       struct opregion_acpi __iomem *acpi;
        struct acpi_bus_event *event = data;
        int ret = NOTIFY_OK;
 
@@ -310,10 +313,11 @@ static int intel_opregion_video_event(struct notifier_block *nb,
 
        acpi = system_opregion->acpi;
 
-       if (event->type == 0x80 && !(acpi->cevt & 0x1))
+       if (event->type == 0x80 &&
+           (ioread32(&acpi->cevt) & 1) == 0)
                ret = NOTIFY_BAD;
 
-       acpi->csts = 0;
+       iowrite32(0, &acpi->csts);
 
        return ret;
 }
@@ -337,6 +341,7 @@ static void intel_didl_outputs(struct drm_device *dev)
        struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
        unsigned long long device_id;
        acpi_status status;
+       u32 temp;
        int i = 0;
 
        handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
@@ -355,7 +360,7 @@ static void intel_didl_outputs(struct drm_device *dev)
        }
 
        if (!acpi_video_bus) {
-               printk(KERN_WARNING "No ACPI video bus found\n");
+               pr_warn("No ACPI video bus found\n");
                return;
        }
 
@@ -371,7 +376,8 @@ static void intel_didl_outputs(struct drm_device *dev)
                if (ACPI_SUCCESS(status)) {
                        if (!device_id)
                                goto blind_set;
-                       opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f);
+                       iowrite32((u32)(device_id & 0x0f0f),
+                                 &opregion->acpi->didl[i]);
                        i++;
                }
        }
@@ -379,7 +385,7 @@ static void intel_didl_outputs(struct drm_device *dev)
 end:
        /* If fewer than 8 outputs, the list must be null terminated */
        if (i < 8)
-               opregion->acpi->didl[i] = 0;
+               iowrite32(0, &opregion->acpi->didl[i]);
        return;
 
 blind_set:
@@ -413,7 +419,9 @@ blind_set:
                        output_type = ACPI_LVDS_OUTPUT;
                        break;
                }
-               opregion->acpi->didl[i] |= (1<<31) | output_type | i;
+               temp = ioread32(&opregion->acpi->didl[i]);
+               iowrite32(temp | (1<<31) | output_type | i,
+                         &opregion->acpi->didl[i]);
                i++;
        }
        goto end;
@@ -434,8 +442,8 @@ void intel_opregion_init(struct drm_device *dev)
                /* Notify BIOS we are ready to handle ACPI video ext notifs.
                 * Right now, all the events are handled by the ACPI video module.
                 * We don't actually need to do anything with them. */
-               opregion->acpi->csts = 0;
-               opregion->acpi->drdy = 1;
+               iowrite32(0, &opregion->acpi->csts);
+               iowrite32(1, &opregion->acpi->drdy);
 
                system_opregion = opregion;
                register_acpi_notifier(&intel_opregion_notifier);
@@ -454,7 +462,7 @@ void intel_opregion_fini(struct drm_device *dev)
                return;
 
        if (opregion->acpi) {
-               opregion->acpi->drdy = 0;
+               iowrite32(0, &opregion->acpi->drdy);
 
                system_opregion = NULL;
                unregister_acpi_notifier(&intel_opregion_notifier);
@@ -474,8 +482,9 @@ int intel_opregion_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_opregion *opregion = &dev_priv->opregion;
-       void *base;
+       void __iomem *base;
        u32 asls, mboxes;
+       char buf[sizeof(OPREGION_SIGNATURE)];
        int err = 0;
 
        pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
@@ -489,7 +498,9 @@ int intel_opregion_setup(struct drm_device *dev)
        if (!base)
                return -ENOMEM;
 
-       if (memcmp(base, OPREGION_SIGNATURE, 16)) {
+       memcpy_fromio(buf, base, sizeof(buf));
+
+       if (memcmp(buf, OPREGION_SIGNATURE, 16)) {
                DRM_DEBUG_DRIVER("opregion signature mismatch\n");
                err = -EINVAL;
                goto err_out;
@@ -499,7 +510,7 @@ int intel_opregion_setup(struct drm_device *dev)
 
        opregion->lid_state = base + ACPI_CLID;
 
-       mboxes = opregion->header->mboxes;
+       mboxes = ioread32(&opregion->header->mboxes);
        if (mboxes & MBOX_ACPI) {
                DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
                opregion->acpi = base + OPREGION_ACPI_OFFSET;
index 80b331c322fb57832732d078a4492fe20075d78e..458743da37743e702a8ccea57f7c37ae01cbfc07 100644 (file)
@@ -187,14 +187,14 @@ struct intel_overlay {
        void (*flip_tail)(struct intel_overlay *);
 };
 
-static struct overlay_registers *
+static struct overlay_registers __iomem *
 intel_overlay_map_regs(struct intel_overlay *overlay)
 {
        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
-       struct overlay_registers *regs;
+       struct overlay_registers __iomem *regs;
 
        if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
-               regs = overlay->reg_bo->phys_obj->handle->vaddr;
+               regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_obj->handle->vaddr;
        else
                regs = io_mapping_map_wc(dev_priv->mm.gtt_mapping,
                                         overlay->reg_bo->gtt_offset);
@@ -203,7 +203,7 @@ intel_overlay_map_regs(struct intel_overlay *overlay)
 }
 
 static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
-                                    struct overlay_registers *regs)
+                                    struct overlay_registers __iomem *regs)
 {
        if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
                io_mapping_unmap(regs);
@@ -215,20 +215,21 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
 {
        struct drm_device *dev = overlay->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        int ret;
 
        BUG_ON(overlay->last_flip_req);
-       ret = i915_add_request(LP_RING(dev_priv), NULL, request);
+       ret = i915_add_request(ring, NULL, request);
        if (ret) {
            kfree(request);
            return ret;
        }
        overlay->last_flip_req = request->seqno;
        overlay->flip_tail = tail;
-       ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req,
-                               true);
+       ret = i915_wait_request(ring, overlay->last_flip_req);
        if (ret)
                return ret;
+       i915_gem_retire_requests(dev);
 
        overlay->last_flip_req = 0;
        return 0;
@@ -262,7 +263,7 @@ i830_activate_pipe_a(struct drm_device *dev)
        DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
 
        mode = drm_mode_duplicate(dev, &vesa_640x480);
-       drm_mode_set_crtcinfo(mode, 0);
+
        if (!drm_crtc_helper_set_mode(&crtc->base, mode,
                                       crtc->base.x, crtc->base.y,
                                       crtc->base.fb))
@@ -287,6 +288,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        struct drm_i915_gem_request *request;
        int pipe_a_quirk = 0;
        int ret;
@@ -306,17 +308,17 @@ static int intel_overlay_on(struct intel_overlay *overlay)
                goto out;
        }
 
-       ret = BEGIN_LP_RING(4);
+       ret = intel_ring_begin(ring, 4);
        if (ret) {
                kfree(request);
                goto out;
        }
 
-       OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
-       OUT_RING(overlay->flip_addr | OFC_UPDATE);
-       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
-       OUT_RING(MI_NOOP);
-       ADVANCE_LP_RING();
+       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
+       intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
+       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_advance(ring);
 
        ret = intel_overlay_do_wait_request(overlay, request, NULL);
 out:
@@ -332,6 +334,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
 {
        struct drm_device *dev = overlay->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        struct drm_i915_gem_request *request;
        u32 flip_addr = overlay->flip_addr;
        u32 tmp;
@@ -351,16 +354,16 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
        if (tmp & (1 << 17))
                DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
-       ret = BEGIN_LP_RING(2);
+       ret = intel_ring_begin(ring, 2);
        if (ret) {
                kfree(request);
                return ret;
        }
-       OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
-       OUT_RING(flip_addr);
-       ADVANCE_LP_RING();
+       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
+       intel_ring_emit(ring, flip_addr);
+       intel_ring_advance(ring);
 
-       ret = i915_add_request(LP_RING(dev_priv), NULL, request);
+       ret = i915_add_request(ring, NULL, request);
        if (ret) {
                kfree(request);
                return ret;
@@ -401,6 +404,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        u32 flip_addr = overlay->flip_addr;
        struct drm_i915_gem_request *request;
        int ret;
@@ -417,20 +421,20 @@ static int intel_overlay_off(struct intel_overlay *overlay)
         * of the hw. Do it in both cases */
        flip_addr |= OFC_UPDATE;
 
-       ret = BEGIN_LP_RING(6);
+       ret = intel_ring_begin(ring, 6);
        if (ret) {
                kfree(request);
                return ret;
        }
        /* wait for overlay to go idle */
-       OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
-       OUT_RING(flip_addr);
-       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
+       intel_ring_emit(ring, flip_addr);
+       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
        /* turn overlay off */
-       OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
-       OUT_RING(flip_addr);
-       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
-       ADVANCE_LP_RING();
+       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+       intel_ring_emit(ring, flip_addr);
+       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       intel_ring_advance(ring);
 
        return intel_overlay_do_wait_request(overlay, request,
                                             intel_overlay_off_tail);
@@ -442,15 +446,16 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        int ret;
 
        if (overlay->last_flip_req == 0)
                return 0;
 
-       ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req,
-                               true);
+       ret = i915_wait_request(ring, overlay->last_flip_req);
        if (ret)
                return ret;
+       i915_gem_retire_requests(dev);
 
        if (overlay->flip_tail)
                overlay->flip_tail(overlay);
@@ -467,6 +472,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        int ret;
 
        /* Only wait if there is actually an old frame to release to
@@ -483,15 +489,15 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
                if (request == NULL)
                        return -ENOMEM;
 
-               ret = BEGIN_LP_RING(2);
+               ret = intel_ring_begin(ring, 2);
                if (ret) {
                        kfree(request);
                        return ret;
                }
 
-               OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
-               OUT_RING(MI_NOOP);
-               ADVANCE_LP_RING();
+               intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_advance(ring);
 
                ret = intel_overlay_do_wait_request(overlay, request,
                                                    intel_overlay_release_old_vid_tail);
@@ -619,14 +625,15 @@ static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
        0x3000, 0x0800, 0x3000
 };
 
-static void update_polyphase_filter(struct overlay_registers *regs)
+static void update_polyphase_filter(struct overlay_registers __iomem *regs)
 {
-       memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
-       memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
+       memcpy_toio(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
+       memcpy_toio(regs->UV_HCOEFS, uv_static_hcoeffs,
+                   sizeof(uv_static_hcoeffs));
 }
 
 static bool update_scaling_factors(struct intel_overlay *overlay,
-                                  struct overlay_registers *regs,
+                                  struct overlay_registers __iomem *regs,
                                   struct put_image_params *params)
 {
        /* fixed point with a 12 bit shift */
@@ -665,16 +672,19 @@ static bool update_scaling_factors(struct intel_overlay *overlay,
        overlay->old_xscale = xscale;
        overlay->old_yscale = yscale;
 
-       regs->YRGBSCALE = (((yscale & FRACT_MASK) << 20) |
-                          ((xscale >> FP_SHIFT)  << 16) |
-                          ((xscale & FRACT_MASK) << 3));
+       iowrite32(((yscale & FRACT_MASK) << 20) |
+                 ((xscale >> FP_SHIFT)  << 16) |
+                 ((xscale & FRACT_MASK) << 3),
+                &regs->YRGBSCALE);
 
-       regs->UVSCALE = (((yscale_UV & FRACT_MASK) << 20) |
-                        ((xscale_UV >> FP_SHIFT)  << 16) |
-                        ((xscale_UV & FRACT_MASK) << 3));
+       iowrite32(((yscale_UV & FRACT_MASK) << 20) |
+                 ((xscale_UV >> FP_SHIFT)  << 16) |
+                 ((xscale_UV & FRACT_MASK) << 3),
+                &regs->UVSCALE);
 
-       regs->UVSCALEV = ((((yscale    >> FP_SHIFT) << 16) |
-                          ((yscale_UV >> FP_SHIFT) << 0)));
+       iowrite32((((yscale    >> FP_SHIFT) << 16) |
+                  ((yscale_UV >> FP_SHIFT) << 0)),
+                &regs->UVSCALEV);
 
        if (scale_changed)
                update_polyphase_filter(regs);
@@ -683,30 +693,32 @@ static bool update_scaling_factors(struct intel_overlay *overlay,
 }
 
 static void update_colorkey(struct intel_overlay *overlay,
-                           struct overlay_registers *regs)
+                           struct overlay_registers __iomem *regs)
 {
        u32 key = overlay->color_key;
 
        switch (overlay->crtc->base.fb->bits_per_pixel) {
        case 8:
-               regs->DCLRKV = 0;
-               regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
+               iowrite32(0, &regs->DCLRKV);
+               iowrite32(CLK_RGB8I_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
                break;
 
        case 16:
                if (overlay->crtc->base.fb->depth == 15) {
-                       regs->DCLRKV = RGB15_TO_COLORKEY(key);
-                       regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
+                       iowrite32(RGB15_TO_COLORKEY(key), &regs->DCLRKV);
+                       iowrite32(CLK_RGB15_MASK | DST_KEY_ENABLE,
+                                 &regs->DCLRKM);
                } else {
-                       regs->DCLRKV = RGB16_TO_COLORKEY(key);
-                       regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
+                       iowrite32(RGB16_TO_COLORKEY(key), &regs->DCLRKV);
+                       iowrite32(CLK_RGB16_MASK | DST_KEY_ENABLE,
+                                 &regs->DCLRKM);
                }
                break;
 
        case 24:
        case 32:
-               regs->DCLRKV = key;
-               regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
+               iowrite32(key, &regs->DCLRKV);
+               iowrite32(CLK_RGB24_MASK | DST_KEY_ENABLE, &regs->DCLRKM);
                break;
        }
 }
@@ -761,9 +773,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
                                      struct put_image_params *params)
 {
        int ret, tmp_width;
-       struct overlay_registers *regs;
+       struct overlay_registers __iomem *regs;
        bool scale_changed = false;
        struct drm_device *dev = overlay->dev;
+       u32 swidth, swidthsw, sheight, ostride;
 
        BUG_ON(!mutex_is_locked(&dev->struct_mutex));
        BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
@@ -782,16 +795,18 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
                goto out_unpin;
 
        if (!overlay->active) {
+               u32 oconfig;
                regs = intel_overlay_map_regs(overlay);
                if (!regs) {
                        ret = -ENOMEM;
                        goto out_unpin;
                }
-               regs->OCONFIG = OCONF_CC_OUT_8BIT;
+               oconfig = OCONF_CC_OUT_8BIT;
                if (IS_GEN4(overlay->dev))
-                       regs->OCONFIG |= OCONF_CSC_MODE_BT709;
-               regs->OCONFIG |= overlay->crtc->pipe == 0 ?
+                       oconfig |= OCONF_CSC_MODE_BT709;
+               oconfig |= overlay->crtc->pipe == 0 ?
                        OCONF_PIPE_A : OCONF_PIPE_B;
+               iowrite32(oconfig, &regs->OCONFIG);
                intel_overlay_unmap_regs(overlay, regs);
 
                ret = intel_overlay_on(overlay);
@@ -805,42 +820,46 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
                goto out_unpin;
        }
 
-       regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
-       regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
+       iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS);
+       iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ);
 
        if (params->format & I915_OVERLAY_YUV_PACKED)
                tmp_width = packed_width_bytes(params->format, params->src_w);
        else
                tmp_width = params->src_w;
 
-       regs->SWIDTH = params->src_w;
-       regs->SWIDTHSW = calc_swidthsw(overlay->dev,
-                                      params->offset_Y, tmp_width);
-       regs->SHEIGHT = params->src_h;
-       regs->OBUF_0Y = new_bo->gtt_offset + params->offset_Y;
-       regs->OSTRIDE = params->stride_Y;
+       swidth = params->src_w;
+       swidthsw = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width);
+       sheight = params->src_h;
+       iowrite32(new_bo->gtt_offset + params->offset_Y, &regs->OBUF_0Y);
+       ostride = params->stride_Y;
 
        if (params->format & I915_OVERLAY_YUV_PLANAR) {
                int uv_hscale = uv_hsubsampling(params->format);
                int uv_vscale = uv_vsubsampling(params->format);
                u32 tmp_U, tmp_V;
-               regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
+               swidth |= (params->src_w/uv_hscale) << 16;
                tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
                                      params->src_w/uv_hscale);
                tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
                                      params->src_w/uv_hscale);
-               regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
-               regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
-               regs->OBUF_0U = new_bo->gtt_offset + params->offset_U;
-               regs->OBUF_0V = new_bo->gtt_offset + params->offset_V;
-               regs->OSTRIDE |= params->stride_UV << 16;
+               swidthsw |= max_t(u32, tmp_U, tmp_V) << 16;
+               sheight |= (params->src_h/uv_vscale) << 16;
+               iowrite32(new_bo->gtt_offset + params->offset_U, &regs->OBUF_0U);
+               iowrite32(new_bo->gtt_offset + params->offset_V, &regs->OBUF_0V);
+               ostride |= params->stride_UV << 16;
        }
 
+       iowrite32(swidth, &regs->SWIDTH);
+       iowrite32(swidthsw, &regs->SWIDTHSW);
+       iowrite32(sheight, &regs->SHEIGHT);
+       iowrite32(ostride, &regs->OSTRIDE);
+
        scale_changed = update_scaling_factors(overlay, regs, params);
 
        update_colorkey(overlay, regs);
 
-       regs->OCMD = overlay_cmd_reg(params);
+       iowrite32(overlay_cmd_reg(params), &regs->OCMD);
 
        intel_overlay_unmap_regs(overlay, regs);
 
@@ -860,7 +879,7 @@ out_unpin:
 
 int intel_overlay_switch_off(struct intel_overlay *overlay)
 {
-       struct overlay_registers *regs;
+       struct overlay_registers __iomem *regs;
        struct drm_device *dev = overlay->dev;
        int ret;
 
@@ -879,7 +898,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
                return ret;
 
        regs = intel_overlay_map_regs(overlay);
-       regs->OCMD = 0;
+       iowrite32(0, &regs->OCMD);
        intel_overlay_unmap_regs(overlay, regs);
 
        ret = intel_overlay_off(overlay);
@@ -1109,11 +1128,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
        struct put_image_params *params;
        int ret;
 
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
+       /* No need to check for DRIVER_MODESET - we don't set it up then. */
        overlay = dev_priv->overlay;
        if (!overlay) {
                DRM_DEBUG("userspace bug: no overlay\n");
@@ -1250,10 +1265,11 @@ out_free:
 }
 
 static void update_reg_attrs(struct intel_overlay *overlay,
-                            struct overlay_registers *regs)
+                            struct overlay_registers __iomem *regs)
 {
-       regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
-       regs->OCLRC1 = overlay->saturation;
+       iowrite32((overlay->contrast << 18) | (overlay->brightness & 0xff),
+                 &regs->OCLRC0);
+       iowrite32(overlay->saturation, &regs->OCLRC1);
 }
 
 static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
@@ -1306,14 +1322,10 @@ int intel_overlay_attrs(struct drm_device *dev, void *data,
        struct drm_intel_overlay_attrs *attrs = data;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_overlay *overlay;
-       struct overlay_registers *regs;
+       struct overlay_registers __iomem *regs;
        int ret;
 
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
+       /* No need to check for DRIVER_MODESET - we don't set it up then. */
        overlay = dev_priv->overlay;
        if (!overlay) {
                DRM_DEBUG("userspace bug: no overlay\n");
@@ -1396,7 +1408,7 @@ void intel_setup_overlay(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_overlay *overlay;
        struct drm_i915_gem_object *reg_bo;
-       struct overlay_registers *regs;
+       struct overlay_registers __iomem *regs;
        int ret;
 
        if (!HAS_OVERLAY(dev))
@@ -1451,7 +1463,7 @@ void intel_setup_overlay(struct drm_device *dev)
        if (!regs)
                goto out_unpin_bo;
 
-       memset(regs, 0, sizeof(struct overlay_registers));
+       memset_io(regs, 0, sizeof(struct overlay_registers));
        update_polyphase_filter(regs);
        update_reg_attrs(overlay, regs);
 
@@ -1499,14 +1511,17 @@ struct intel_overlay_error_state {
        u32 isr;
 };
 
-static struct overlay_registers *
+static struct overlay_registers __iomem *
 intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
 {
        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
-       struct overlay_registers *regs;
+       struct overlay_registers __iomem *regs;
 
        if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
-               regs = overlay->reg_bo->phys_obj->handle->vaddr;
+               /* Cast to make sparse happy, but it's wc memory anyway, so
+                * equivalent to the wc io mapping on X86. */
+               regs = (struct overlay_registers __iomem *)
+                       overlay->reg_bo->phys_obj->handle->vaddr;
        else
                regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
                                                overlay->reg_bo->gtt_offset);
@@ -1515,7 +1530,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
 }
 
 static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
-                                           struct overlay_registers *regs)
+                                       struct overlay_registers __iomem *regs)
 {
        if (!OVERLAY_NEEDS_PHYSICAL(overlay->dev))
                io_mapping_unmap_atomic(regs);
@@ -1540,9 +1555,9 @@ intel_overlay_capture_error_state(struct drm_device *dev)
        error->dovsta = I915_READ(DOVSTA);
        error->isr = I915_READ(ISR);
        if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
-               error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
+               error->base = (__force long)overlay->reg_bo->phys_obj->handle->vaddr;
        else
-               error->base = (long) overlay->reg_bo->gtt_offset;
+               error->base = overlay->reg_bo->gtt_offset;
 
        regs = intel_overlay_map_regs_atomic(overlay);
        if (!regs)
index 230a141dbea34da3feff3e4fc043d780a6975fdd..2b2e011e9055f7f9b9bdb9fc066410caaed4d68e 100644 (file)
@@ -28,6 +28,9 @@
  *      Chris Wilson <chris@chris-wilson.co.uk>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/moduleparam.h>
 #include "intel_drv.h"
 
 #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
@@ -47,8 +50,6 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
        adjusted_mode->vtotal = fixed_mode->vtotal;
 
        adjusted_mode->clock = fixed_mode->clock;
-
-       drm_mode_set_crtcinfo(adjusted_mode, 0);
 }
 
 /* adjusted_mode has been preset to be the panel's fixed mode */
@@ -171,7 +172,7 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)
                /* XXX add code here to query mode clock or hardware clock
                 * and program max PWM appropriately.
                 */
-               printk_once(KERN_WARNING "fixme: max PWM is zero.\n");
+               pr_warn_once("fixme: max PWM is zero\n");
                return 1;
        }
 
@@ -191,6 +192,27 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)
        return max;
 }
 
+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, u32 val)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (i915_panel_invert_brightness < 0)
+               return val;
+
+       if (i915_panel_invert_brightness > 0 ||
+           dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS)
+               return intel_panel_get_max_backlight(dev) - val;
+
+       return val;
+}
+
 u32 intel_panel_get_backlight(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -211,6 +233,7 @@ u32 intel_panel_get_backlight(struct drm_device *dev)
                }
        }
 
+       val = intel_panel_compute_brightness(dev, val);
        DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
        return val;
 }
@@ -228,6 +251,7 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level
        u32 tmp;
 
        DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
+       level = intel_panel_compute_brightness(dev, level);
 
        if (HAS_PCH_SPLIT(dev))
                return intel_pch_panel_set_backlight(dev, level);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
new file mode 100644 (file)
index 0000000..4389234
--- /dev/null
@@ -0,0 +1,3712 @@
+/*
+ * Copyright Â© 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eugeni Dodonov <eugeni.dodonov@intel.com>
+ *
+ */
+
+#include <linux/cpufreq.h>
+#include "i915_drv.h"
+#include "intel_drv.h"
+#include "../../../platform/x86/intel_ips.h"
+#include <linux/module.h>
+
+/* FBC, or Frame Buffer Compression, is a technique employed to compress the
+ * framebuffer contents in-memory, aiming at reducing the required bandwidth
+ * during in-memory transfers and, therefore, reduce the power packet.
+ *
+ * The benefits of FBC are mostly visible with solid backgrounds and
+ * variation-less patterns.
+ *
+ * FBC-related functionality can be enabled by the means of the
+ * i915.i915_enable_fbc parameter
+ */
+
+static void i8xx_disable_fbc(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 fbc_ctl;
+
+       /* Disable compression */
+       fbc_ctl = I915_READ(FBC_CONTROL);
+       if ((fbc_ctl & FBC_CTL_EN) == 0)
+               return;
+
+       fbc_ctl &= ~FBC_CTL_EN;
+       I915_WRITE(FBC_CONTROL, fbc_ctl);
+
+       /* Wait for compressing bit to clear */
+       if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) {
+               DRM_DEBUG_KMS("FBC idle timed out\n");
+               return;
+       }
+
+       DRM_DEBUG_KMS("disabled FBC\n");
+}
+
+static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_framebuffer *fb = crtc->fb;
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       struct drm_i915_gem_object *obj = intel_fb->obj;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int cfb_pitch;
+       int plane, i;
+       u32 fbc_ctl, fbc_ctl2;
+
+       cfb_pitch = dev_priv->cfb_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;
+       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);
+
+       /* enable it... */
+       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);
+
+       DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ",
+                     cfb_pitch, crtc->y, intel_crtc->plane);
+}
+
+static bool i8xx_fbc_enabled(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
+}
+
+static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_framebuffer *fb = crtc->fb;
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       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... */
+       I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN);
+
+       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
+}
+
+static void g4x_disable_fbc(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dpfc_ctl;
+
+       /* Disable compression */
+       dpfc_ctl = I915_READ(DPFC_CONTROL);
+       if (dpfc_ctl & DPFC_CTL_EN) {
+               dpfc_ctl &= ~DPFC_CTL_EN;
+               I915_WRITE(DPFC_CONTROL, dpfc_ctl);
+
+               DRM_DEBUG_KMS("disabled FBC\n");
+       }
+}
+
+static bool g4x_fbc_enabled(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
+}
+
+static void sandybridge_blit_fbc_update(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 blt_ecoskpd;
+
+       /* Make sure blitter notifies FBC of writes */
+       gen6_gt_force_wake_get(dev_priv);
+       blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
+       blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
+               GEN6_BLITTER_LOCK_SHIFT;
+       I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
+       blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY;
+       I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
+       blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY <<
+                        GEN6_BLITTER_LOCK_SHIFT);
+       I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
+       POSTING_READ(GEN6_BLITTER_ECOSKPD);
+       gen6_gt_force_wake_put(dev_priv);
+}
+
+static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_framebuffer *fb = crtc->fb;
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       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);
+       dpfc_ctl &= DPFC_RESERVED;
+       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);
+       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, obj->gtt_offset | ILK_FBC_RT_VALID);
+       /* enable it... */
+       I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
+
+       if (IS_GEN6(dev)) {
+               I915_WRITE(SNB_DPFC_CTL_SA,
+                          SNB_CPU_FENCE_ENABLE | obj->fence_reg);
+               I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
+               sandybridge_blit_fbc_update(dev);
+       }
+
+       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
+}
+
+static void ironlake_disable_fbc(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dpfc_ctl;
+
+       /* Disable compression */
+       dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
+       if (dpfc_ctl & DPFC_CTL_EN) {
+               dpfc_ctl &= ~DPFC_CTL_EN;
+               I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
+
+               DRM_DEBUG_KMS("disabled FBC\n");
+       }
+}
+
+static bool ironlake_fbc_enabled(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
+}
+
+bool intel_fbc_enabled(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!dev_priv->display.fbc_enabled)
+               return false;
+
+       return dev_priv->display.fbc_enabled(dev);
+}
+
+static void intel_fbc_work_fn(struct work_struct *__work)
+{
+       struct intel_fbc_work *work =
+               container_of(to_delayed_work(__work),
+                            struct intel_fbc_work, work);
+       struct drm_device *dev = work->crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       mutex_lock(&dev->struct_mutex);
+       if (work == dev_priv->fbc_work) {
+               /* Double check that we haven't switched fb without cancelling
+                * the prior work.
+                */
+               if (work->crtc->fb == work->fb) {
+                       dev_priv->display.enable_fbc(work->crtc,
+                                                    work->interval);
+
+                       dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane;
+                       dev_priv->cfb_fb = work->crtc->fb->base.id;
+                       dev_priv->cfb_y = work->crtc->y;
+               }
+
+               dev_priv->fbc_work = NULL;
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       kfree(work);
+}
+
+static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
+{
+       if (dev_priv->fbc_work == NULL)
+               return;
+
+       DRM_DEBUG_KMS("cancelling pending FBC enable\n");
+
+       /* Synchronisation is provided by struct_mutex and checking of
+        * dev_priv->fbc_work, so we can perform the cancellation
+        * entirely asynchronously.
+        */
+       if (cancel_delayed_work(&dev_priv->fbc_work->work))
+               /* tasklet was killed before being run, clean up */
+               kfree(dev_priv->fbc_work);
+
+       /* Mark the work as no longer wanted so that if it does
+        * wake-up (because the work was already running and waiting
+        * for our mutex), it will discover that is no longer
+        * necessary to run.
+        */
+       dev_priv->fbc_work = NULL;
+}
+
+void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+       struct intel_fbc_work *work;
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!dev_priv->display.enable_fbc)
+               return;
+
+       intel_cancel_fbc_work(dev_priv);
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (work == NULL) {
+               dev_priv->display.enable_fbc(crtc, interval);
+               return;
+       }
+
+       work->crtc = crtc;
+       work->fb = crtc->fb;
+       work->interval = interval;
+       INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
+
+       dev_priv->fbc_work = work;
+
+       DRM_DEBUG_KMS("scheduling delayed FBC enable\n");
+
+       /* Delay the actual enabling to let pageflipping cease and the
+        * display to settle before starting the compression. Note that
+        * this delay also serves a second purpose: it allows for a
+        * vblank to pass after disabling the FBC before we attempt
+        * to modify the control registers.
+        *
+        * A more complicated solution would involve tracking vblanks
+        * following the termination of the page-flipping sequence
+        * and indeed performing the enable as a co-routine and not
+        * waiting synchronously upon the vblank.
+        */
+       schedule_delayed_work(&work->work, msecs_to_jiffies(50));
+}
+
+void intel_disable_fbc(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       intel_cancel_fbc_work(dev_priv);
+
+       if (!dev_priv->display.disable_fbc)
+               return;
+
+       dev_priv->display.disable_fbc(dev);
+       dev_priv->cfb_plane = -1;
+}
+
+/**
+ * intel_update_fbc - enable/disable FBC as needed
+ * @dev: the drm_device
+ *
+ * Set up the framebuffer compression hardware at mode set time.  We
+ * enable it if possible:
+ *   - plane A only (on pre-965)
+ *   - no pixel mulitply/line duplication
+ *   - no alpha buffer discard
+ *   - no dual wide
+ *   - framebuffer <= 2048 in width, 1536 in height
+ *
+ * We can't assume that any compression will take place (worst case),
+ * so the compressed buffer has to be the same size as the uncompressed
+ * one.  It also must reside (along with the line length buffer) in
+ * stolen memory.
+ *
+ * We need to enable/disable FBC on a global basis.
+ */
+void intel_update_fbc(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = NULL, *tmp_crtc;
+       struct intel_crtc *intel_crtc;
+       struct drm_framebuffer *fb;
+       struct intel_framebuffer *intel_fb;
+       struct drm_i915_gem_object *obj;
+       int enable_fbc;
+
+       DRM_DEBUG_KMS("\n");
+
+       if (!i915_powersave)
+               return;
+
+       if (!I915_HAS_FBC(dev))
+               return;
+
+       /*
+        * If FBC is already on, we just have to verify that we can
+        * keep it that way...
+        * Need to disable if:
+        *   - more than one pipe is active
+        *   - changing FBC params (stride, fence, mode)
+        *   - new fb is too large to fit in compressed buffer
+        *   - going to an unsupported config (interlace, pixel multiply, etc.)
+        */
+       list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+               if (tmp_crtc->enabled && tmp_crtc->fb) {
+                       if (crtc) {
+                               DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
+                               dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
+                               goto out_disable;
+                       }
+                       crtc = tmp_crtc;
+               }
+       }
+
+       if (!crtc || crtc->fb == NULL) {
+               DRM_DEBUG_KMS("no output, disabling\n");
+               dev_priv->no_fbc_reason = FBC_NO_OUTPUT;
+               goto out_disable;
+       }
+
+       intel_crtc = to_intel_crtc(crtc);
+       fb = crtc->fb;
+       intel_fb = to_intel_framebuffer(fb);
+       obj = intel_fb->obj;
+
+       enable_fbc = i915_enable_fbc;
+       if (enable_fbc < 0) {
+               DRM_DEBUG_KMS("fbc set to per-chip default\n");
+               enable_fbc = 1;
+               if (INTEL_INFO(dev)->gen <= 6)
+                       enable_fbc = 0;
+       }
+       if (!enable_fbc) {
+               DRM_DEBUG_KMS("fbc disabled per module param\n");
+               dev_priv->no_fbc_reason = FBC_MODULE_PARAM;
+               goto out_disable;
+       }
+       if (intel_fb->obj->base.size > dev_priv->cfb_size) {
+               DRM_DEBUG_KMS("framebuffer too large, disabling "
+                             "compression\n");
+               dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
+               goto out_disable;
+       }
+       if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) ||
+           (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) {
+               DRM_DEBUG_KMS("mode incompatible with compression, "
+                             "disabling\n");
+               dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
+               goto out_disable;
+       }
+       if ((crtc->mode.hdisplay > 2048) ||
+           (crtc->mode.vdisplay > 1536)) {
+               DRM_DEBUG_KMS("mode too large for compression, disabling\n");
+               dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
+               goto out_disable;
+       }
+       if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) {
+               DRM_DEBUG_KMS("plane not 0, disabling compression\n");
+               dev_priv->no_fbc_reason = FBC_BAD_PLANE;
+               goto out_disable;
+       }
+
+       /* The use of a CPU fence is mandatory in order to detect writes
+        * by the CPU to the scanout and trigger updates to the FBC.
+        */
+       if (obj->tiling_mode != I915_TILING_X ||
+           obj->fence_reg == I915_FENCE_REG_NONE) {
+               DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n");
+               dev_priv->no_fbc_reason = FBC_NOT_TILED;
+               goto out_disable;
+       }
+
+       /* If the kernel debugger is active, always disable compression */
+       if (in_dbg_master())
+               goto out_disable;
+
+       /* If the scanout has not changed, don't modify the FBC settings.
+        * Note that we make the fundamental assumption that the fb->obj
+        * cannot be unpinned (and have its GTT offset and fence revoked)
+        * without first being decoupled from the scanout and FBC disabled.
+        */
+       if (dev_priv->cfb_plane == intel_crtc->plane &&
+           dev_priv->cfb_fb == fb->base.id &&
+           dev_priv->cfb_y == crtc->y)
+               return;
+
+       if (intel_fbc_enabled(dev)) {
+               /* We update FBC along two paths, after changing fb/crtc
+                * configuration (modeswitching) and after page-flipping
+                * finishes. For the latter, we know that not only did
+                * we disable the FBC at the start of the page-flip
+                * sequence, but also more than one vblank has passed.
+                *
+                * For the former case of modeswitching, it is possible
+                * to switch between two FBC valid configurations
+                * instantaneously so we do need to disable the FBC
+                * before we can modify its control registers. We also
+                * have to wait for the next vblank for that to take
+                * effect. However, since we delay enabling FBC we can
+                * assume that a vblank has passed since disabling and
+                * that we can safely alter the registers in the deferred
+                * callback.
+                *
+                * In the scenario that we go from a valid to invalid
+                * and then back to valid FBC configuration we have
+                * no strict enforcement that a vblank occurred since
+                * disabling the FBC. However, along all current pipe
+                * disabling paths we do need to wait for a vblank at
+                * some point. And we wait before enabling FBC anyway.
+                */
+               DRM_DEBUG_KMS("disabling active FBC for update\n");
+               intel_disable_fbc(dev);
+       }
+
+       intel_enable_fbc(crtc, 500);
+       return;
+
+out_disable:
+       /* Multiple disables should be harmless */
+       if (intel_fbc_enabled(dev)) {
+               DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
+               intel_disable_fbc(dev);
+       }
+}
+
+static void i915_pineview_get_mem_freq(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       u32 tmp;
+
+       tmp = I915_READ(CLKCFG);
+
+       switch (tmp & CLKCFG_FSB_MASK) {
+       case CLKCFG_FSB_533:
+               dev_priv->fsb_freq = 533; /* 133*4 */
+               break;
+       case CLKCFG_FSB_800:
+               dev_priv->fsb_freq = 800; /* 200*4 */
+               break;
+       case CLKCFG_FSB_667:
+               dev_priv->fsb_freq =  667; /* 167*4 */
+               break;
+       case CLKCFG_FSB_400:
+               dev_priv->fsb_freq = 400; /* 100*4 */
+               break;
+       }
+
+       switch (tmp & CLKCFG_MEM_MASK) {
+       case CLKCFG_MEM_533:
+               dev_priv->mem_freq = 533;
+               break;
+       case CLKCFG_MEM_667:
+               dev_priv->mem_freq = 667;
+               break;
+       case CLKCFG_MEM_800:
+               dev_priv->mem_freq = 800;
+               break;
+       }
+
+       /* detect pineview DDR3 setting */
+       tmp = I915_READ(CSHRDDR3CTL);
+       dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
+}
+
+static void i915_ironlake_get_mem_freq(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       u16 ddrpll, csipll;
+
+       ddrpll = I915_READ16(DDRMPLL1);
+       csipll = I915_READ16(CSIPLL0);
+
+       switch (ddrpll & 0xff) {
+       case 0xc:
+               dev_priv->mem_freq = 800;
+               break;
+       case 0x10:
+               dev_priv->mem_freq = 1066;
+               break;
+       case 0x14:
+               dev_priv->mem_freq = 1333;
+               break;
+       case 0x18:
+               dev_priv->mem_freq = 1600;
+               break;
+       default:
+               DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n",
+                                ddrpll & 0xff);
+               dev_priv->mem_freq = 0;
+               break;
+       }
+
+       dev_priv->r_t = dev_priv->mem_freq;
+
+       switch (csipll & 0x3ff) {
+       case 0x00c:
+               dev_priv->fsb_freq = 3200;
+               break;
+       case 0x00e:
+               dev_priv->fsb_freq = 3733;
+               break;
+       case 0x010:
+               dev_priv->fsb_freq = 4266;
+               break;
+       case 0x012:
+               dev_priv->fsb_freq = 4800;
+               break;
+       case 0x014:
+               dev_priv->fsb_freq = 5333;
+               break;
+       case 0x016:
+               dev_priv->fsb_freq = 5866;
+               break;
+       case 0x018:
+               dev_priv->fsb_freq = 6400;
+               break;
+       default:
+               DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n",
+                                csipll & 0x3ff);
+               dev_priv->fsb_freq = 0;
+               break;
+       }
+
+       if (dev_priv->fsb_freq == 3200) {
+               dev_priv->c_m = 0;
+       } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) {
+               dev_priv->c_m = 1;
+       } else {
+               dev_priv->c_m = 2;
+       }
+}
+
+static const struct cxsr_latency cxsr_latency_table[] = {
+       {1, 0, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
+       {1, 0, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
+       {1, 0, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
+       {1, 1, 800, 667, 6420, 36420, 6873, 36873},    /* DDR3-667 SC */
+       {1, 1, 800, 800, 5902, 35902, 6318, 36318},    /* DDR3-800 SC */
+
+       {1, 0, 667, 400, 3400, 33400, 4021, 34021},    /* DDR2-400 SC */
+       {1, 0, 667, 667, 3372, 33372, 3845, 33845},    /* DDR2-667 SC */
+       {1, 0, 667, 800, 3386, 33386, 3822, 33822},    /* DDR2-800 SC */
+       {1, 1, 667, 667, 6438, 36438, 6911, 36911},    /* DDR3-667 SC */
+       {1, 1, 667, 800, 5941, 35941, 6377, 36377},    /* DDR3-800 SC */
+
+       {1, 0, 400, 400, 3472, 33472, 4173, 34173},    /* DDR2-400 SC */
+       {1, 0, 400, 667, 3443, 33443, 3996, 33996},    /* DDR2-667 SC */
+       {1, 0, 400, 800, 3430, 33430, 3946, 33946},    /* DDR2-800 SC */
+       {1, 1, 400, 667, 6509, 36509, 7062, 37062},    /* DDR3-667 SC */
+       {1, 1, 400, 800, 5985, 35985, 6501, 36501},    /* DDR3-800 SC */
+
+       {0, 0, 800, 400, 3438, 33438, 4065, 34065},    /* DDR2-400 SC */
+       {0, 0, 800, 667, 3410, 33410, 3889, 33889},    /* DDR2-667 SC */
+       {0, 0, 800, 800, 3403, 33403, 3845, 33845},    /* DDR2-800 SC */
+       {0, 1, 800, 667, 6476, 36476, 6955, 36955},    /* DDR3-667 SC */
+       {0, 1, 800, 800, 5958, 35958, 6400, 36400},    /* DDR3-800 SC */
+
+       {0, 0, 667, 400, 3456, 33456, 4103, 34106},    /* DDR2-400 SC */
+       {0, 0, 667, 667, 3428, 33428, 3927, 33927},    /* DDR2-667 SC */
+       {0, 0, 667, 800, 3443, 33443, 3905, 33905},    /* DDR2-800 SC */
+       {0, 1, 667, 667, 6494, 36494, 6993, 36993},    /* DDR3-667 SC */
+       {0, 1, 667, 800, 5998, 35998, 6460, 36460},    /* DDR3-800 SC */
+
+       {0, 0, 400, 400, 3528, 33528, 4255, 34255},    /* DDR2-400 SC */
+       {0, 0, 400, 667, 3500, 33500, 4079, 34079},    /* DDR2-667 SC */
+       {0, 0, 400, 800, 3487, 33487, 4029, 34029},    /* DDR2-800 SC */
+       {0, 1, 400, 667, 6566, 36566, 7145, 37145},    /* DDR3-667 SC */
+       {0, 1, 400, 800, 6042, 36042, 6584, 36584},    /* DDR3-800 SC */
+};
+
+static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop,
+                                                        int is_ddr3,
+                                                        int fsb,
+                                                        int mem)
+{
+       const struct cxsr_latency *latency;
+       int i;
+
+       if (fsb == 0 || mem == 0)
+               return NULL;
+
+       for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
+               latency = &cxsr_latency_table[i];
+               if (is_desktop == latency->is_desktop &&
+                   is_ddr3 == latency->is_ddr3 &&
+                   fsb == latency->fsb_freq && mem == latency->mem_freq)
+                       return latency;
+       }
+
+       DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
+
+       return NULL;
+}
+
+static void pineview_disable_cxsr(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       /* deactivate cxsr */
+       I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN);
+}
+
+/*
+ * Latency for FIFO fetches is dependent on several factors:
+ *   - memory configuration (speed, channels)
+ *   - chipset
+ *   - current MCH state
+ * It can be fairly high in some situations, so here we assume a fairly
+ * pessimal value.  It's a tradeoff between extra memory fetches (if we
+ * set this value too high, the FIFO will fetch frequently to stay full)
+ * and power consumption (set it too low to save power and we might see
+ * FIFO underruns and display "flicker").
+ *
+ * A value of 5us seems to be a good balance; safe for very low end
+ * platforms but not overly aggressive on lower latency configs.
+ */
+static const int latency_ns = 5000;
+
+static int i9xx_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;
+       if (plane)
+               size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size;
+
+       DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
+                     plane ? "B" : "A", size);
+
+       return size;
+}
+
+static int i85x_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 & 0x1ff;
+       if (plane)
+               size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) - size;
+       size >>= 1; /* Convert to cachelines */
+
+       DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
+                     plane ? "B" : "A", size);
+
+       return size;
+}
+
+static int i845_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 >>= 2; /* Convert to cachelines */
+
+       DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
+                     plane ? "B" : "A",
+                     size);
+
+       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,
+       PINEVIEW_MAX_WM,
+       PINEVIEW_DFT_WM,
+       PINEVIEW_GUARD_WM,
+       PINEVIEW_FIFO_LINE_SIZE
+};
+static const struct intel_watermark_params pineview_display_hplloff_wm = {
+       PINEVIEW_DISPLAY_FIFO,
+       PINEVIEW_MAX_WM,
+       PINEVIEW_DFT_HPLLOFF_WM,
+       PINEVIEW_GUARD_WM,
+       PINEVIEW_FIFO_LINE_SIZE
+};
+static const struct intel_watermark_params pineview_cursor_wm = {
+       PINEVIEW_CURSOR_FIFO,
+       PINEVIEW_CURSOR_MAX_WM,
+       PINEVIEW_CURSOR_DFT_WM,
+       PINEVIEW_CURSOR_GUARD_WM,
+       PINEVIEW_FIFO_LINE_SIZE,
+};
+static const struct intel_watermark_params pineview_cursor_hplloff_wm = {
+       PINEVIEW_CURSOR_FIFO,
+       PINEVIEW_CURSOR_MAX_WM,
+       PINEVIEW_CURSOR_DFT_WM,
+       PINEVIEW_CURSOR_GUARD_WM,
+       PINEVIEW_FIFO_LINE_SIZE
+};
+static const struct intel_watermark_params g4x_wm_info = {
+       G4X_FIFO_SIZE,
+       G4X_MAX_WM,
+       G4X_MAX_WM,
+       2,
+       G4X_FIFO_LINE_SIZE,
+};
+static const struct intel_watermark_params g4x_cursor_wm_info = {
+       I965_CURSOR_FIFO,
+       I965_CURSOR_MAX_WM,
+       I965_CURSOR_DFT_WM,
+       2,
+       G4X_FIFO_LINE_SIZE,
+};
+static const struct intel_watermark_params valleyview_wm_info = {
+       VALLEYVIEW_FIFO_SIZE,
+       VALLEYVIEW_MAX_WM,
+       VALLEYVIEW_MAX_WM,
+       2,
+       G4X_FIFO_LINE_SIZE,
+};
+static const struct intel_watermark_params valleyview_cursor_wm_info = {
+       I965_CURSOR_FIFO,
+       VALLEYVIEW_CURSOR_MAX_WM,
+       I965_CURSOR_DFT_WM,
+       2,
+       G4X_FIFO_LINE_SIZE,
+};
+static const struct intel_watermark_params i965_cursor_wm_info = {
+       I965_CURSOR_FIFO,
+       I965_CURSOR_MAX_WM,
+       I965_CURSOR_DFT_WM,
+       2,
+       I915_FIFO_LINE_SIZE,
+};
+static const struct intel_watermark_params i945_wm_info = {
+       I945_FIFO_SIZE,
+       I915_MAX_WM,
+       1,
+       2,
+       I915_FIFO_LINE_SIZE
+};
+static const struct intel_watermark_params i915_wm_info = {
+       I915_FIFO_SIZE,
+       I915_MAX_WM,
+       1,
+       2,
+       I915_FIFO_LINE_SIZE
+};
+static const struct intel_watermark_params i855_wm_info = {
+       I855GM_FIFO_SIZE,
+       I915_MAX_WM,
+       1,
+       2,
+       I830_FIFO_LINE_SIZE
+};
+static const struct intel_watermark_params i830_wm_info = {
+       I830_FIFO_SIZE,
+       I915_MAX_WM,
+       1,
+       2,
+       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
+ * @wm: chip FIFO params
+ * @pixel_size: display pixel size
+ * @latency_ns: memory latency for the platform
+ *
+ * Calculate the watermark level (the level at which the display plane will
+ * start fetching from memory again).  Each chip has a different display
+ * FIFO size and allocation, so the caller needs to figure that out and pass
+ * in the correct intel_watermark_params structure.
+ *
+ * As the pixel clock runs, the FIFO will be drained at a rate that depends
+ * on the pixel size.  When it reaches the watermark level, it'll start
+ * fetching FIFO line sized based chunks from memory until the FIFO fills
+ * past the watermark point.  If the FIFO drains completely, a FIFO underrun
+ * will occur, and a display engine hang could result.
+ */
+static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
+                                       const struct intel_watermark_params *wm,
+                                       int fifo_size,
+                                       int pixel_size,
+                                       unsigned long latency_ns)
+{
+       long entries_required, wm_size;
+
+       /*
+        * Note: we need to make sure we don't overflow for various clock &
+        * latency values.
+        * clocks go from a few thousand to several hundred thousand.
+        * latency is usually a few thousand
+        */
+       entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) /
+               1000;
+       entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size);
+
+       DRM_DEBUG_KMS("FIFO entries required for mode: %ld\n", entries_required);
+
+       wm_size = fifo_size - (entries_required + wm->guard_size);
+
+       DRM_DEBUG_KMS("FIFO watermark level: %ld\n", wm_size);
+
+       /* Don't promote wm_size to unsigned... */
+       if (wm_size > (long)wm->max_wm)
+               wm_size = wm->max_wm;
+       if (wm_size <= 0)
+               wm_size = wm->default_wm;
+       return wm_size;
+}
+
+static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
+{
+       struct drm_crtc *crtc, *enabled = NULL;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               if (crtc->enabled && crtc->fb) {
+                       if (enabled)
+                               return NULL;
+                       enabled = crtc;
+               }
+       }
+
+       return enabled;
+}
+
+static void pineview_update_wm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
+       const struct cxsr_latency *latency;
+       u32 reg;
+       unsigned long wm;
+
+       latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
+                                        dev_priv->fsb_freq, dev_priv->mem_freq);
+       if (!latency) {
+               DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
+               pineview_disable_cxsr(dev);
+               return;
+       }
+
+       crtc = single_enabled_crtc(dev);
+       if (crtc) {
+               int clock = crtc->mode.clock;
+               int pixel_size = crtc->fb->bits_per_pixel / 8;
+
+               /* Display SR */
+               wm = intel_calculate_wm(clock, &pineview_display_wm,
+                                       pineview_display_wm.fifo_size,
+                                       pixel_size, latency->display_sr);
+               reg = I915_READ(DSPFW1);
+               reg &= ~DSPFW_SR_MASK;
+               reg |= wm << DSPFW_SR_SHIFT;
+               I915_WRITE(DSPFW1, reg);
+               DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg);
+
+               /* cursor SR */
+               wm = intel_calculate_wm(clock, &pineview_cursor_wm,
+                                       pineview_display_wm.fifo_size,
+                                       pixel_size, latency->cursor_sr);
+               reg = I915_READ(DSPFW3);
+               reg &= ~DSPFW_CURSOR_SR_MASK;
+               reg |= (wm & 0x3f) << DSPFW_CURSOR_SR_SHIFT;
+               I915_WRITE(DSPFW3, reg);
+
+               /* Display HPLL off SR */
+               wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm,
+                                       pineview_display_hplloff_wm.fifo_size,
+                                       pixel_size, latency->display_hpll_disable);
+               reg = I915_READ(DSPFW3);
+               reg &= ~DSPFW_HPLL_SR_MASK;
+               reg |= wm & DSPFW_HPLL_SR_MASK;
+               I915_WRITE(DSPFW3, reg);
+
+               /* cursor HPLL off SR */
+               wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm,
+                                       pineview_display_hplloff_wm.fifo_size,
+                                       pixel_size, latency->cursor_hpll_disable);
+               reg = I915_READ(DSPFW3);
+               reg &= ~DSPFW_HPLL_CURSOR_MASK;
+               reg |= (wm & 0x3f) << DSPFW_HPLL_CURSOR_SHIFT;
+               I915_WRITE(DSPFW3, reg);
+               DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg);
+
+               /* activate cxsr */
+               I915_WRITE(DSPFW3,
+                          I915_READ(DSPFW3) | PINEVIEW_SELF_REFRESH_EN);
+               DRM_DEBUG_KMS("Self-refresh is enabled\n");
+       } else {
+               pineview_disable_cxsr(dev);
+               DRM_DEBUG_KMS("Self-refresh is disabled\n");
+       }
+}
+
+static bool g4x_compute_wm0(struct drm_device *dev,
+                           int plane,
+                           const struct intel_watermark_params *display,
+                           int display_latency_ns,
+                           const struct intel_watermark_params *cursor,
+                           int cursor_latency_ns,
+                           int *plane_wm,
+                           int *cursor_wm)
+{
+       struct drm_crtc *crtc;
+       int htotal, hdisplay, clock, pixel_size;
+       int line_time_us, line_count;
+       int entries, tlb_miss;
+
+       crtc = intel_get_crtc_for_plane(dev, plane);
+       if (crtc->fb == NULL || !crtc->enabled) {
+               *cursor_wm = cursor->guard_size;
+               *plane_wm = display->guard_size;
+               return false;
+       }
+
+       htotal = crtc->mode.htotal;
+       hdisplay = crtc->mode.hdisplay;
+       clock = crtc->mode.clock;
+       pixel_size = crtc->fb->bits_per_pixel / 8;
+
+       /* Use the small buffer method to calculate plane watermark */
+       entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
+       tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
+       if (tlb_miss > 0)
+               entries += tlb_miss;
+       entries = DIV_ROUND_UP(entries, display->cacheline_size);
+       *plane_wm = entries + display->guard_size;
+       if (*plane_wm > (int)display->max_wm)
+               *plane_wm = display->max_wm;
+
+       /* Use the large buffer method to calculate cursor watermark */
+       line_time_us = ((htotal * 1000) / clock);
+       line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
+       entries = line_count * 64 * pixel_size;
+       tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
+       if (tlb_miss > 0)
+               entries += tlb_miss;
+       entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
+       *cursor_wm = entries + cursor->guard_size;
+       if (*cursor_wm > (int)cursor->max_wm)
+               *cursor_wm = (int)cursor->max_wm;
+
+       return true;
+}
+
+/*
+ * 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 g4x_check_srwm(struct drm_device *dev,
+                          int display_wm, int cursor_wm,
+                          const struct intel_watermark_params *display,
+                          const struct intel_watermark_params *cursor)
+{
+       DRM_DEBUG_KMS("SR watermark: display plane %d, cursor %d\n",
+                     display_wm, cursor_wm);
+
+       if (display_wm > display->max_wm) {
+               DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n",
+                             display_wm, display->max_wm);
+               return false;
+       }
+
+       if (cursor_wm > cursor->max_wm) {
+               DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n",
+                             cursor_wm, cursor->max_wm);
+               return false;
+       }
+
+       if (!(display_wm || cursor_wm)) {
+               DRM_DEBUG_KMS("SR latency is 0, disabling\n");
+               return false;
+       }
+
+       return true;
+}
+
+static bool g4x_compute_srwm(struct drm_device *dev,
+                            int plane,
+                            int latency_ns,
+                            const struct intel_watermark_params *display,
+                            const struct intel_watermark_params *cursor,
+                            int *display_wm, int *cursor_wm)
+{
+       struct drm_crtc *crtc;
+       int hdisplay, htotal, pixel_size, clock;
+       unsigned long line_time_us;
+       int line_count, line_size;
+       int small, large;
+       int entries;
+
+       if (!latency_ns) {
+               *display_wm = *cursor_wm = 0;
+               return false;
+       }
+
+       crtc = intel_get_crtc_for_plane(dev, plane);
+       hdisplay = crtc->mode.hdisplay;
+       htotal = crtc->mode.htotal;
+       clock = crtc->mode.clock;
+       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;
+
+       /* 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 g4x_check_srwm(dev,
+                             *display_wm, *cursor_wm,
+                             display, cursor);
+}
+
+static bool vlv_compute_drain_latency(struct drm_device *dev,
+                                    int plane,
+                                    int *plane_prec_mult,
+                                    int *plane_dl,
+                                    int *cursor_prec_mult,
+                                    int *cursor_dl)
+{
+       struct drm_crtc *crtc;
+       int clock, pixel_size;
+       int entries;
+
+       crtc = intel_get_crtc_for_plane(dev, plane);
+       if (crtc->fb == NULL || !crtc->enabled)
+               return false;
+
+       clock = crtc->mode.clock;       /* VESA DOT Clock */
+       pixel_size = crtc->fb->bits_per_pixel / 8;      /* BPP */
+
+       entries = (clock / 1000) * pixel_size;
+       *plane_prec_mult = (entries > 256) ?
+               DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16;
+       *plane_dl = (64 * (*plane_prec_mult) * 4) / ((clock / 1000) *
+                                                    pixel_size);
+
+       entries = (clock / 1000) * 4;   /* BPP is always 4 for cursor */
+       *cursor_prec_mult = (entries > 256) ?
+               DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16;
+       *cursor_dl = (64 * (*cursor_prec_mult) * 4) / ((clock / 1000) * 4);
+
+       return true;
+}
+
+/*
+ * Update drain latency registers of memory arbiter
+ *
+ * Valleyview SoC has a new memory arbiter and needs drain latency registers
+ * to be programmed. Each plane has a drain latency multiplier and a drain
+ * latency value.
+ */
+
+static void vlv_update_drain_latency(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int planea_prec, planea_dl, planeb_prec, planeb_dl;
+       int cursora_prec, cursora_dl, cursorb_prec, cursorb_dl;
+       int plane_prec_mult, cursor_prec_mult; /* Precision multiplier is
+                                                       either 16 or 32 */
+
+       /* For plane A, Cursor A */
+       if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl,
+                                     &cursor_prec_mult, &cursora_dl)) {
+               cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
+                       DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_16;
+               planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
+                       DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_16;
+
+               I915_WRITE(VLV_DDL1, cursora_prec |
+                               (cursora_dl << DDL_CURSORA_SHIFT) |
+                               planea_prec | planea_dl);
+       }
+
+       /* For plane B, Cursor B */
+       if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl,
+                                     &cursor_prec_mult, &cursorb_dl)) {
+               cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
+                       DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_16;
+               planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ?
+                       DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_16;
+
+               I915_WRITE(VLV_DDL2, cursorb_prec |
+                               (cursorb_dl << DDL_CURSORB_SHIFT) |
+                               planeb_prec | planeb_dl);
+       }
+}
+
+#define single_plane_enabled(mask) is_power_of_2(mask)
+
+static void valleyview_update_wm(struct drm_device *dev)
+{
+       static const int sr_latency_ns = 12000;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
+       int plane_sr, cursor_sr;
+       unsigned int enabled = 0;
+
+       vlv_update_drain_latency(dev);
+
+       if (g4x_compute_wm0(dev, 0,
+                           &valleyview_wm_info, latency_ns,
+                           &valleyview_cursor_wm_info, latency_ns,
+                           &planea_wm, &cursora_wm))
+               enabled |= 1;
+
+       if (g4x_compute_wm0(dev, 1,
+                           &valleyview_wm_info, latency_ns,
+                           &valleyview_cursor_wm_info, latency_ns,
+                           &planeb_wm, &cursorb_wm))
+               enabled |= 2;
+
+       plane_sr = cursor_sr = 0;
+       if (single_plane_enabled(enabled) &&
+           g4x_compute_srwm(dev, ffs(enabled) - 1,
+                            sr_latency_ns,
+                            &valleyview_wm_info,
+                            &valleyview_cursor_wm_info,
+                            &plane_sr, &cursor_sr))
+               I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN);
+       else
+               I915_WRITE(FW_BLC_SELF_VLV,
+                          I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN);
+
+       DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
+                     planea_wm, cursora_wm,
+                     planeb_wm, cursorb_wm,
+                     plane_sr, cursor_sr);
+
+       I915_WRITE(DSPFW1,
+                  (plane_sr << DSPFW_SR_SHIFT) |
+                  (cursorb_wm << DSPFW_CURSORB_SHIFT) |
+                  (planeb_wm << DSPFW_PLANEB_SHIFT) |
+                  planea_wm);
+       I915_WRITE(DSPFW2,
+                  (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) |
+                  (cursora_wm << DSPFW_CURSORA_SHIFT));
+       I915_WRITE(DSPFW3,
+                  (I915_READ(DSPFW3) | (cursor_sr << DSPFW_CURSOR_SR_SHIFT)));
+}
+
+static void g4x_update_wm(struct drm_device *dev)
+{
+       static const int sr_latency_ns = 12000;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
+       int plane_sr, cursor_sr;
+       unsigned int enabled = 0;
+
+       if (g4x_compute_wm0(dev, 0,
+                           &g4x_wm_info, latency_ns,
+                           &g4x_cursor_wm_info, latency_ns,
+                           &planea_wm, &cursora_wm))
+               enabled |= 1;
+
+       if (g4x_compute_wm0(dev, 1,
+                           &g4x_wm_info, latency_ns,
+                           &g4x_cursor_wm_info, latency_ns,
+                           &planeb_wm, &cursorb_wm))
+               enabled |= 2;
+
+       plane_sr = cursor_sr = 0;
+       if (single_plane_enabled(enabled) &&
+           g4x_compute_srwm(dev, ffs(enabled) - 1,
+                            sr_latency_ns,
+                            &g4x_wm_info,
+                            &g4x_cursor_wm_info,
+                            &plane_sr, &cursor_sr))
+               I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+       else
+               I915_WRITE(FW_BLC_SELF,
+                          I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN);
+
+       DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
+                     planea_wm, cursora_wm,
+                     planeb_wm, cursorb_wm,
+                     plane_sr, cursor_sr);
+
+       I915_WRITE(DSPFW1,
+                  (plane_sr << DSPFW_SR_SHIFT) |
+                  (cursorb_wm << DSPFW_CURSORB_SHIFT) |
+                  (planeb_wm << DSPFW_PLANEB_SHIFT) |
+                  planea_wm);
+       I915_WRITE(DSPFW2,
+                  (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) |
+                  (cursora_wm << DSPFW_CURSORA_SHIFT));
+       /* HPLL off in SR has some issues on G4x... disable it */
+       I915_WRITE(DSPFW3,
+                  (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) |
+                  (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
+}
+
+static void i965_update_wm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
+       int srwm = 1;
+       int cursor_sr = 16;
+
+       /* Calc sr entries for one plane configs */
+       crtc = single_enabled_crtc(dev);
+       if (crtc) {
+               /* self-refresh has much higher latency */
+               static const int sr_latency_ns = 12000;
+               int clock = crtc->mode.clock;
+               int htotal = crtc->mode.htotal;
+               int hdisplay = crtc->mode.hdisplay;
+               int pixel_size = crtc->fb->bits_per_pixel / 8;
+               unsigned long line_time_us;
+               int entries;
+
+               line_time_us = ((htotal * 1000) / clock);
+
+               /* Use ns/us then divide to preserve precision */
+               entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+                       pixel_size * hdisplay;
+               entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE);
+               srwm = I965_FIFO_SIZE - entries;
+               if (srwm < 0)
+                       srwm = 1;
+               srwm &= 0x1ff;
+               DRM_DEBUG_KMS("self-refresh entries: %d, wm: %d\n",
+                             entries, srwm);
+
+               entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+                       pixel_size * 64;
+               entries = DIV_ROUND_UP(entries,
+                                         i965_cursor_wm_info.cacheline_size);
+               cursor_sr = i965_cursor_wm_info.fifo_size -
+                       (entries + i965_cursor_wm_info.guard_size);
+
+               if (cursor_sr > i965_cursor_wm_info.max_wm)
+                       cursor_sr = i965_cursor_wm_info.max_wm;
+
+               DRM_DEBUG_KMS("self-refresh watermark: display plane %d "
+                             "cursor %d\n", srwm, cursor_sr);
+
+               if (IS_CRESTLINE(dev))
+                       I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+       } else {
+               /* Turn off self refresh if both pipes are enabled */
+               if (IS_CRESTLINE(dev))
+                       I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+                                  & ~FW_BLC_SELF_EN);
+       }
+
+       DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
+                     srwm);
+
+       /* 965 has limitations... */
+       I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) |
+                  (8 << 16) | (8 << 8) | (8 << 0));
+       I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
+       /* update cursor SR watermark */
+       I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
+}
+
+static void i9xx_update_wm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       const struct intel_watermark_params *wm_info;
+       uint32_t fwater_lo;
+       uint32_t fwater_hi;
+       int cwm, srwm = 1;
+       int fifo_size;
+       int planea_wm, planeb_wm;
+       struct drm_crtc *crtc, *enabled = NULL;
+
+       if (IS_I945GM(dev))
+               wm_info = &i945_wm_info;
+       else if (!IS_GEN2(dev))
+               wm_info = &i915_wm_info;
+       else
+               wm_info = &i855_wm_info;
+
+       fifo_size = dev_priv->display.get_fifo_size(dev, 0);
+       crtc = intel_get_crtc_for_plane(dev, 0);
+       if (crtc->enabled && crtc->fb) {
+               planea_wm = intel_calculate_wm(crtc->mode.clock,
+                                              wm_info, fifo_size,
+                                              crtc->fb->bits_per_pixel / 8,
+                                              latency_ns);
+               enabled = crtc;
+       } else
+               planea_wm = fifo_size - wm_info->guard_size;
+
+       fifo_size = dev_priv->display.get_fifo_size(dev, 1);
+       crtc = intel_get_crtc_for_plane(dev, 1);
+       if (crtc->enabled && crtc->fb) {
+               planeb_wm = intel_calculate_wm(crtc->mode.clock,
+                                              wm_info, fifo_size,
+                                              crtc->fb->bits_per_pixel / 8,
+                                              latency_ns);
+               if (enabled == NULL)
+                       enabled = crtc;
+               else
+                       enabled = NULL;
+       } else
+               planeb_wm = fifo_size - wm_info->guard_size;
+
+       DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+
+       /*
+        * Overlay gets an aggressive default since video jitter is bad.
+        */
+       cwm = 2;
+
+       /* Play safe and disable self-refresh before adjusting watermarks. */
+       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);
+
+       /* Calc sr entries for one plane configs */
+       if (HAS_FW_BLC(dev) && enabled) {
+               /* self-refresh has much higher latency */
+               static const int sr_latency_ns = 6000;
+               int clock = enabled->mode.clock;
+               int htotal = enabled->mode.htotal;
+               int hdisplay = enabled->mode.hdisplay;
+               int pixel_size = enabled->fb->bits_per_pixel / 8;
+               unsigned long line_time_us;
+               int entries;
+
+               line_time_us = (htotal * 1000) / clock;
+
+               /* Use ns/us then divide to preserve precision */
+               entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+                       pixel_size * hdisplay;
+               entries = DIV_ROUND_UP(entries, wm_info->cacheline_size);
+               DRM_DEBUG_KMS("self-refresh entries: %d\n", entries);
+               srwm = wm_info->fifo_size - entries;
+               if (srwm < 0)
+                       srwm = 1;
+
+               if (IS_I945G(dev) || IS_I945GM(dev))
+                       I915_WRITE(FW_BLC_SELF,
+                                  FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
+               else if (IS_I915GM(dev))
+                       I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
+       }
+
+       DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
+                     planea_wm, planeb_wm, cwm, srwm);
+
+       fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f);
+       fwater_hi = (cwm & 0x1f);
+
+       /* Set request length to 8 cachelines per fetch */
+       fwater_lo = fwater_lo | (1 << 24) | (1 << 8);
+       fwater_hi = fwater_hi | (1 << 8);
+
+       I915_WRITE(FW_BLC, fwater_lo);
+       I915_WRITE(FW_BLC2, fwater_hi);
+
+       if (HAS_FW_BLC(dev)) {
+               if (enabled) {
+                       if (IS_I945G(dev) || IS_I945GM(dev))
+                               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);
+                       DRM_DEBUG_KMS("memory self refresh enabled\n");
+               } else
+                       DRM_DEBUG_KMS("memory self refresh disabled\n");
+       }
+}
+
+static void i830_update_wm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
+       uint32_t fwater_lo;
+       int planea_wm;
+
+       crtc = single_enabled_crtc(dev);
+       if (crtc == NULL)
+               return;
+
+       planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info,
+                                      dev_priv->display.get_fifo_size(dev, 0),
+                                      crtc->fb->bits_per_pixel / 8,
+                                      latency_ns);
+       fwater_lo = I915_READ(FW_BLC) & ~0xfff;
+       fwater_lo |= (3<<8) | planea_wm;
+
+       DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm);
+
+       I915_WRITE(FW_BLC, fwater_lo);
+}
+
+#define ILK_LP0_PLANE_LATENCY          700
+#define ILK_LP0_CURSOR_LATENCY         1300
+
+/*
+ * 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;
+       }
+
+       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;
+       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);
+       hdisplay = crtc->mode.hdisplay;
+       htotal = crtc->mode.htotal;
+       clock = crtc->mode.clock;
+       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_device *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, 0,
+                           &ironlake_display_wm_info,
+                           ILK_LP0_PLANE_LATENCY,
+                           &ironlake_cursor_wm_info,
+                           ILK_LP0_CURSOR_LATENCY,
+                           &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;
+       }
+
+       if (g4x_compute_wm0(dev, 1,
+                           &ironlake_display_wm_info,
+                           ILK_LP0_PLANE_LATENCY,
+                           &ironlake_cursor_wm_info,
+                           ILK_LP0_CURSOR_LATENCY,
+                           &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 |= 2;
+       }
+
+       /*
+        * 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,
+                                  ILK_READ_WM1_LATENCY() * 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 |
+                  (ILK_READ_WM1_LATENCY() << 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,
+                                  ILK_READ_WM2_LATENCY() * 500,
+                                  &ironlake_display_srwm_info,
+                                  &ironlake_cursor_srwm_info,
+                                  &fbc_wm, &plane_wm, &cursor_wm))
+               return;
+
+       I915_WRITE(WM2_LP_ILK,
+                  WM2_LP_EN |
+                  (ILK_READ_WM2_LATENCY() << 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_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
+       u32 val;
+       int fbc_wm, plane_wm, cursor_wm;
+       unsigned int enabled;
+
+       enabled = 0;
+       if (g4x_compute_wm0(dev, 0,
+                           &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;
+       }
+
+       if (g4x_compute_wm0(dev, 1,
+                           &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 |= 2;
+       }
+
+       /* IVB has 3 pipes */
+       if (IS_IVYBRIDGE(dev) &&
+           g4x_compute_wm0(dev, 2,
+                           &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 |= 3;
+       }
+
+       /*
+        * 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,
+                                  SNB_READ_WM1_LATENCY() * 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 |
+                  (SNB_READ_WM1_LATENCY() << 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,
+                                  SNB_READ_WM2_LATENCY() * 500,
+                                  &sandybridge_display_srwm_info,
+                                  &sandybridge_cursor_srwm_info,
+                                  &fbc_wm, &plane_wm, &cursor_wm))
+               return;
+
+       I915_WRITE(WM2_LP_ILK,
+                  WM2_LP_EN |
+                  (SNB_READ_WM2_LATENCY() << 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,
+                                  SNB_READ_WM3_LATENCY() * 500,
+                                  &sandybridge_display_srwm_info,
+                                  &sandybridge_cursor_srwm_info,
+                                  &fbc_wm, &plane_wm, &cursor_wm))
+               return;
+
+       I915_WRITE(WM3_LP_ILK,
+                  WM3_LP_EN |
+                  (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+                  (fbc_wm << WM1_LP_FBC_SHIFT) |
+                  (plane_wm << WM1_LP_SR_SHIFT) |
+                  cursor_wm);
+}
+
+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 (crtc->fb == NULL || !crtc->enabled) {
+               *sprite_wm = display->guard_size;
+               return false;
+       }
+
+       clock = crtc->mode.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 = crtc->mode.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_device *dev, int pipe,
+                                        uint32_t sprite_width, int pixel_size)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int latency = SNB_READ_WM0_LATENCY() * 100;     /* In unit 0.1us */
+       u32 val;
+       int sprite_wm, reg;
+       int ret;
+
+       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 %d\n",
+                             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 %d - %d\n", pipe, sprite_wm);
+
+
+       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
+                                             pixel_size,
+                                             &sandybridge_display_srwm_info,
+                                             SNB_READ_WM1_LATENCY() * 500,
+                                             &sprite_wm);
+       if (!ret) {
+               DRM_DEBUG_KMS("failed to compute sprite lp1 wm on pipe %d\n",
+                             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,
+                                             SNB_READ_WM2_LATENCY() * 500,
+                                             &sprite_wm);
+       if (!ret) {
+               DRM_DEBUG_KMS("failed to compute sprite lp2 wm on pipe %d\n",
+                             pipe);
+               return;
+       }
+       I915_WRITE(WM2S_LP_IVB, sprite_wm);
+
+       ret = sandybridge_compute_sprite_srwm(dev, pipe, sprite_width,
+                                             pixel_size,
+                                             &sandybridge_display_srwm_info,
+                                             SNB_READ_WM3_LATENCY() * 500,
+                                             &sprite_wm);
+       if (!ret) {
+               DRM_DEBUG_KMS("failed to compute sprite lp3 wm on pipe %d\n",
+                             pipe);
+               return;
+       }
+       I915_WRITE(WM3S_LP_IVB, sprite_wm);
+}
+
+/**
+ * intel_update_watermarks - update FIFO watermark values based on current modes
+ *
+ * Calculate watermark values for the various WM regs based on current mode
+ * and plane configuration.
+ *
+ * There are several cases to deal with here:
+ *   - normal (i.e. non-self-refresh)
+ *   - self-refresh (SR) mode
+ *   - lines are large relative to FIFO size (buffer can hold up to 2)
+ *   - lines are small relative to FIFO size (buffer can hold more than 2
+ *     lines), so need to account for TLB latency
+ *
+ *   The normal calculation is:
+ *     watermark = dotclock * bytes per pixel * latency
+ *   where latency is platform & configuration dependent (we assume pessimal
+ *   values here).
+ *
+ *   The SR calculation is:
+ *     watermark = (trunc(latency/line time)+1) * surface width *
+ *       bytes per pixel
+ *   where
+ *     line time = htotal / dotclock
+ *     surface width = hdisplay for normal plane and 64 for cursor
+ *   and latency is assumed to be high, as above.
+ *
+ * The final value programmed to the register should always be rounded up,
+ * and include an extra 2 entries to account for clock crossings.
+ *
+ * We don't use the sprite, so we can ignore that.  And on Crestline we have
+ * to set the non-SR watermarks to 8.
+ */
+void intel_update_watermarks(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->display.update_wm)
+               dev_priv->display.update_wm(dev);
+}
+
+void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
+                                   uint32_t sprite_width, int pixel_size)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->display.update_sprite_wm)
+               dev_priv->display.update_sprite_wm(dev, pipe, sprite_width,
+                                                  pixel_size);
+}
+
+static struct drm_i915_gem_object *
+intel_alloc_context_page(struct drm_device *dev)
+{
+       struct drm_i915_gem_object *ctx;
+       int ret;
+
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+       ctx = i915_gem_alloc_object(dev, 4096);
+       if (!ctx) {
+               DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
+               return NULL;
+       }
+
+       ret = i915_gem_object_pin(ctx, 4096, true);
+       if (ret) {
+               DRM_ERROR("failed to pin power context: %d\n", ret);
+               goto err_unref;
+       }
+
+       ret = i915_gem_object_set_to_gtt_domain(ctx, 1);
+       if (ret) {
+               DRM_ERROR("failed to set-domain on power context: %d\n", ret);
+               goto err_unpin;
+       }
+
+       return ctx;
+
+err_unpin:
+       i915_gem_object_unpin(ctx);
+err_unref:
+       drm_gem_object_unreference(&ctx->base);
+       mutex_unlock(&dev->struct_mutex);
+       return NULL;
+}
+
+bool ironlake_set_drps(struct drm_device *dev, u8 val)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u16 rgvswctl;
+
+       rgvswctl = I915_READ16(MEMSWCTL);
+       if (rgvswctl & MEMCTL_CMD_STS) {
+               DRM_DEBUG("gpu busy, RCS change rejected\n");
+               return false; /* still busy with another command */
+       }
+
+       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
+               (val << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
+       I915_WRITE16(MEMSWCTL, rgvswctl);
+       POSTING_READ16(MEMSWCTL);
+
+       rgvswctl |= MEMCTL_CMD_STS;
+       I915_WRITE16(MEMSWCTL, rgvswctl);
+
+       return true;
+}
+
+void ironlake_enable_drps(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 rgvmodectl = I915_READ(MEMMODECTL);
+       u8 fmax, fmin, fstart, vstart;
+
+       /* Enable temp reporting */
+       I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN);
+       I915_WRITE16(TSC1, I915_READ(TSC1) | TSE);
+
+       /* 100ms RC evaluation intervals */
+       I915_WRITE(RCUPEI, 100000);
+       I915_WRITE(RCDNEI, 100000);
+
+       /* Set max/min thresholds to 90ms and 80ms respectively */
+       I915_WRITE(RCBMAXAVG, 90000);
+       I915_WRITE(RCBMINAVG, 80000);
+
+       I915_WRITE(MEMIHYST, 1);
+
+       /* Set up min, max, and cur for interrupt handling */
+       fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT;
+       fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
+       fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
+               MEMMODE_FSTART_SHIFT;
+
+       vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
+               PXVFREQ_PX_SHIFT;
+
+       dev_priv->fmax = fmax; /* IPS callback will increase this */
+       dev_priv->fstart = fstart;
+
+       dev_priv->max_delay = fstart;
+       dev_priv->min_delay = fmin;
+       dev_priv->cur_delay = fstart;
+
+       DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n",
+                        fmax, fmin, fstart);
+
+       I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
+
+       /*
+        * Interrupts will be enabled in ironlake_irq_postinstall
+        */
+
+       I915_WRITE(VIDSTART, vstart);
+       POSTING_READ(VIDSTART);
+
+       rgvmodectl |= MEMMODE_SWMODE_EN;
+       I915_WRITE(MEMMODECTL, rgvmodectl);
+
+       if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10))
+               DRM_ERROR("stuck trying to change perf mode\n");
+       msleep(1);
+
+       ironlake_set_drps(dev, fstart);
+
+       dev_priv->last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
+               I915_READ(0x112e0);
+       dev_priv->last_time1 = jiffies_to_msecs(jiffies);
+       dev_priv->last_count2 = I915_READ(0x112f4);
+       getrawmonotonic(&dev_priv->last_time2);
+}
+
+void ironlake_disable_drps(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u16 rgvswctl = I915_READ16(MEMSWCTL);
+
+       /* Ack interrupts, disable EFC interrupt */
+       I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
+       I915_WRITE(MEMINTRSTS, MEMINT_EVAL_CHG);
+       I915_WRITE(DEIER, I915_READ(DEIER) & ~DE_PCU_EVENT);
+       I915_WRITE(DEIIR, DE_PCU_EVENT);
+       I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
+
+       /* Go back to the starting frequency */
+       ironlake_set_drps(dev, dev_priv->fstart);
+       msleep(1);
+       rgvswctl |= MEMCTL_CMD_STS;
+       I915_WRITE(MEMSWCTL, rgvswctl);
+       msleep(1);
+
+}
+
+void gen6_set_rps(struct drm_device *dev, u8 val)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 swreq;
+
+       swreq = (val & 0x3ff) << 25;
+       I915_WRITE(GEN6_RPNSWREQ, swreq);
+}
+
+void gen6_disable_rps(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
+       I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+       I915_WRITE(GEN6_PMIER, 0);
+       /* Complete PM interrupt masking here doesn't race with the rps work
+        * item again unmasking PM interrupts because that is using a different
+        * register (PMIMR) to mask PM interrupts. The only risk is in leaving
+        * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
+
+       spin_lock_irq(&dev_priv->rps_lock);
+       dev_priv->pm_iir = 0;
+       spin_unlock_irq(&dev_priv->rps_lock);
+
+       I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
+}
+
+int intel_enable_rc6(const struct drm_device *dev)
+{
+       /*
+        * Respect the kernel parameter if it is set
+        */
+       if (i915_enable_rc6 >= 0)
+               return i915_enable_rc6;
+
+       /*
+        * Disable RC6 on Ironlake
+        */
+       if (INTEL_INFO(dev)->gen == 5)
+               return 0;
+
+       /* Sorry Haswell, no RC6 for you for now. */
+       if (IS_HASWELL(dev))
+               return 0;
+
+       /*
+        * Disable rc6 on Sandybridge
+        */
+       if (INTEL_INFO(dev)->gen == 6) {
+               DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
+               return INTEL_RC6_ENABLE;
+       }
+       DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n");
+       return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
+}
+
+void gen6_enable_rps(struct drm_i915_private *dev_priv)
+{
+       u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+       u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
+       u32 pcu_mbox, rc6_mask = 0;
+       u32 gtfifodbg;
+       int cur_freq, min_freq, max_freq;
+       int rc6_mode;
+       int i;
+
+       /* Here begins a magic sequence of register writes to enable
+        * auto-downclocking.
+        *
+        * Perhaps there might be some value in exposing these to
+        * userspace...
+        */
+       I915_WRITE(GEN6_RC_STATE, 0);
+       mutex_lock(&dev_priv->dev->struct_mutex);
+
+       /* Clear the DBG now so we don't confuse earlier errors */
+       if ((gtfifodbg = I915_READ(GTFIFODBG))) {
+               DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg);
+               I915_WRITE(GTFIFODBG, gtfifodbg);
+       }
+
+       gen6_gt_force_wake_get(dev_priv);
+
+       /* disable the counters and set deterministic thresholds */
+       I915_WRITE(GEN6_RC_CONTROL, 0);
+
+       I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16);
+       I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30);
+       I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30);
+       I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
+       I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
+
+       for (i = 0; i < I915_NUM_RINGS; i++)
+               I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10);
+
+       I915_WRITE(GEN6_RC_SLEEP, 0);
+       I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
+       I915_WRITE(GEN6_RC6_THRESHOLD, 50000);
+       I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
+       I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
+
+       rc6_mode = intel_enable_rc6(dev_priv->dev);
+       if (rc6_mode & INTEL_RC6_ENABLE)
+               rc6_mask |= GEN6_RC_CTL_RC6_ENABLE;
+
+       if (rc6_mode & INTEL_RC6p_ENABLE)
+               rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE;
+
+       if (rc6_mode & INTEL_RC6pp_ENABLE)
+               rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE;
+
+       DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
+                       (rc6_mode & INTEL_RC6_ENABLE) ? "on" : "off",
+                       (rc6_mode & INTEL_RC6p_ENABLE) ? "on" : "off",
+                       (rc6_mode & INTEL_RC6pp_ENABLE) ? "on" : "off");
+
+       I915_WRITE(GEN6_RC_CONTROL,
+                  rc6_mask |
+                  GEN6_RC_CTL_EI_MODE(1) |
+                  GEN6_RC_CTL_HW_ENABLE);
+
+       I915_WRITE(GEN6_RPNSWREQ,
+                  GEN6_FREQUENCY(10) |
+                  GEN6_OFFSET(0) |
+                  GEN6_AGGRESSIVE_TURBO);
+       I915_WRITE(GEN6_RC_VIDEO_FREQ,
+                  GEN6_FREQUENCY(12));
+
+       I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000);
+       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+                  18 << 24 |
+                  6 << 16);
+       I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000);
+       I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000);
+       I915_WRITE(GEN6_RP_UP_EI, 100000);
+       I915_WRITE(GEN6_RP_DOWN_EI, 5000000);
+       I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
+       I915_WRITE(GEN6_RP_CONTROL,
+                  GEN6_RP_MEDIA_TURBO |
+                  GEN6_RP_MEDIA_HW_MODE |
+                  GEN6_RP_MEDIA_IS_GFX |
+                  GEN6_RP_ENABLE |
+                  GEN6_RP_UP_BUSY_AVG |
+                  GEN6_RP_DOWN_IDLE_CONT);
+
+       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+                    500))
+               DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
+
+       I915_WRITE(GEN6_PCODE_DATA, 0);
+       I915_WRITE(GEN6_PCODE_MAILBOX,
+                  GEN6_PCODE_READY |
+                  GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
+       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+                    500))
+               DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
+
+       min_freq = (rp_state_cap & 0xff0000) >> 16;
+       max_freq = rp_state_cap & 0xff;
+       cur_freq = (gt_perf_status & 0xff00) >> 8;
+
+       /* Check for overclock support */
+       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+                    500))
+               DRM_ERROR("timeout waiting for pcode mailbox to become idle\n");
+       I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_READ_OC_PARAMS);
+       pcu_mbox = I915_READ(GEN6_PCODE_DATA);
+       if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
+                    500))
+               DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
+       if (pcu_mbox & (1<<31)) { /* OC supported */
+               max_freq = pcu_mbox & 0xff;
+               DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
+       }
+
+       /* In units of 100MHz */
+       dev_priv->max_delay = max_freq;
+       dev_priv->min_delay = min_freq;
+       dev_priv->cur_delay = cur_freq;
+
+       /* requires MSI enabled */
+       I915_WRITE(GEN6_PMIER,
+                  GEN6_PM_MBOX_EVENT |
+                  GEN6_PM_THERMAL_EVENT |
+                  GEN6_PM_RP_DOWN_TIMEOUT |
+                  GEN6_PM_RP_UP_THRESHOLD |
+                  GEN6_PM_RP_DOWN_THRESHOLD |
+                  GEN6_PM_RP_UP_EI_EXPIRED |
+                  GEN6_PM_RP_DOWN_EI_EXPIRED);
+       spin_lock_irq(&dev_priv->rps_lock);
+       WARN_ON(dev_priv->pm_iir != 0);
+       I915_WRITE(GEN6_PMIMR, 0);
+       spin_unlock_irq(&dev_priv->rps_lock);
+       /* enable all PM interrupts */
+       I915_WRITE(GEN6_PMINTRMSK, 0);
+
+       gen6_gt_force_wake_put(dev_priv);
+       mutex_unlock(&dev_priv->dev->struct_mutex);
+}
+
+void gen6_update_ring_freq(struct drm_i915_private *dev_priv)
+{
+       int min_freq = 15;
+       int gpu_freq, ia_freq, max_ia_freq;
+       int scaling_factor = 180;
+
+       max_ia_freq = cpufreq_quick_get_max(0);
+       /*
+        * Default to measured freq if none found, PCU will ensure we don't go
+        * over
+        */
+       if (!max_ia_freq)
+               max_ia_freq = tsc_khz;
+
+       /* Convert from kHz to MHz */
+       max_ia_freq /= 1000;
+
+       mutex_lock(&dev_priv->dev->struct_mutex);
+
+       /*
+        * For each potential GPU frequency, load a ring frequency we'd like
+        * to use for memory access.  We do this by specifying the IA frequency
+        * the PCU should use as a reference to determine the ring frequency.
+        */
+       for (gpu_freq = dev_priv->max_delay; gpu_freq >= dev_priv->min_delay;
+            gpu_freq--) {
+               int diff = dev_priv->max_delay - gpu_freq;
+
+               /*
+                * For GPU frequencies less than 750MHz, just use the lowest
+                * ring freq.
+                */
+               if (gpu_freq < min_freq)
+                       ia_freq = 800;
+               else
+                       ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
+               ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
+
+               I915_WRITE(GEN6_PCODE_DATA,
+                          (ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT) |
+                          gpu_freq);
+               I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
+                          GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
+               if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) &
+                             GEN6_PCODE_READY) == 0, 10)) {
+                       DRM_ERROR("pcode write of freq table timed out\n");
+                       continue;
+               }
+       }
+
+       mutex_unlock(&dev_priv->dev->struct_mutex);
+}
+
+static void ironlake_teardown_rc6(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->renderctx) {
+               i915_gem_object_unpin(dev_priv->renderctx);
+               drm_gem_object_unreference(&dev_priv->renderctx->base);
+               dev_priv->renderctx = NULL;
+       }
+
+       if (dev_priv->pwrctx) {
+               i915_gem_object_unpin(dev_priv->pwrctx);
+               drm_gem_object_unreference(&dev_priv->pwrctx->base);
+               dev_priv->pwrctx = NULL;
+       }
+}
+
+void ironlake_disable_rc6(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (I915_READ(PWRCTXA)) {
+               /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */
+               I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT);
+               wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON),
+                        50);
+
+               I915_WRITE(PWRCTXA, 0);
+               POSTING_READ(PWRCTXA);
+
+               I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
+               POSTING_READ(RSTDBYCTL);
+       }
+
+       ironlake_teardown_rc6(dev);
+}
+
+static int ironlake_setup_rc6(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->renderctx == NULL)
+               dev_priv->renderctx = intel_alloc_context_page(dev);
+       if (!dev_priv->renderctx)
+               return -ENOMEM;
+
+       if (dev_priv->pwrctx == NULL)
+               dev_priv->pwrctx = intel_alloc_context_page(dev);
+       if (!dev_priv->pwrctx) {
+               ironlake_teardown_rc6(dev);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+void ironlake_enable_rc6(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+       int ret;
+
+       /* rc6 disabled by default due to repeated reports of hanging during
+        * boot and resume.
+        */
+       if (!intel_enable_rc6(dev))
+               return;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = ironlake_setup_rc6(dev);
+       if (ret) {
+               mutex_unlock(&dev->struct_mutex);
+               return;
+       }
+
+       /*
+        * GPU can automatically power down the render unit if given a page
+        * to save state.
+        */
+       ret = intel_ring_begin(ring, 6);
+       if (ret) {
+               ironlake_teardown_rc6(dev);
+               mutex_unlock(&dev->struct_mutex);
+               return;
+       }
+
+       intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
+       intel_ring_emit(ring, MI_SET_CONTEXT);
+       intel_ring_emit(ring, dev_priv->renderctx->gtt_offset |
+                       MI_MM_SPACE_GTT |
+                       MI_SAVE_EXT_STATE_EN |
+                       MI_RESTORE_EXT_STATE_EN |
+                       MI_RESTORE_INHIBIT);
+       intel_ring_emit(ring, MI_SUSPEND_FLUSH);
+       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_emit(ring, MI_FLUSH);
+       intel_ring_advance(ring);
+
+       /*
+        * Wait for the command parser to advance past MI_SET_CONTEXT. The HW
+        * does an implicit flush, combined with MI_FLUSH above, it should be
+        * safe to assume that renderctx is valid
+        */
+       ret = intel_wait_ring_idle(ring);
+       if (ret) {
+               DRM_ERROR("failed to enable ironlake power power savings\n");
+               ironlake_teardown_rc6(dev);
+               mutex_unlock(&dev->struct_mutex);
+               return;
+       }
+
+       I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN);
+       I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
+       mutex_unlock(&dev->struct_mutex);
+}
+
+static unsigned long intel_pxfreq(u32 vidfreq)
+{
+       unsigned long freq;
+       int div = (vidfreq & 0x3f0000) >> 16;
+       int post = (vidfreq & 0x3000) >> 12;
+       int pre = (vidfreq & 0x7);
+
+       if (!pre)
+               return 0;
+
+       freq = ((div * 133333) / ((1<<post) * pre));
+
+       return freq;
+}
+
+static const struct cparams {
+       u16 i;
+       u16 t;
+       u16 m;
+       u16 c;
+} cparams[] = {
+       { 1, 1333, 301, 28664 },
+       { 1, 1066, 294, 24460 },
+       { 1, 800, 294, 25192 },
+       { 0, 1333, 276, 27605 },
+       { 0, 1066, 276, 27605 },
+       { 0, 800, 231, 23784 },
+};
+
+unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
+{
+       u64 total_count, diff, ret;
+       u32 count1, count2, count3, m = 0, c = 0;
+       unsigned long now = jiffies_to_msecs(jiffies), diff1;
+       int i;
+
+       diff1 = now - dev_priv->last_time1;
+
+       /* Prevent division-by-zero if we are asking too fast.
+        * Also, we don't get interesting results if we are polling
+        * faster than once in 10ms, so just return the saved value
+        * in such cases.
+        */
+       if (diff1 <= 10)
+               return dev_priv->chipset_power;
+
+       count1 = I915_READ(DMIEC);
+       count2 = I915_READ(DDREC);
+       count3 = I915_READ(CSIEC);
+
+       total_count = count1 + count2 + count3;
+
+       /* FIXME: handle per-counter overflow */
+       if (total_count < dev_priv->last_count1) {
+               diff = ~0UL - dev_priv->last_count1;
+               diff += total_count;
+       } else {
+               diff = total_count - dev_priv->last_count1;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(cparams); i++) {
+               if (cparams[i].i == dev_priv->c_m &&
+                   cparams[i].t == dev_priv->r_t) {
+                       m = cparams[i].m;
+                       c = cparams[i].c;
+                       break;
+               }
+       }
+
+       diff = div_u64(diff, diff1);
+       ret = ((m * diff) + c);
+       ret = div_u64(ret, 10);
+
+       dev_priv->last_count1 = total_count;
+       dev_priv->last_time1 = now;
+
+       dev_priv->chipset_power = ret;
+
+       return ret;
+}
+
+unsigned long i915_mch_val(struct drm_i915_private *dev_priv)
+{
+       unsigned long m, x, b;
+       u32 tsfs;
+
+       tsfs = I915_READ(TSFS);
+
+       m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT);
+       x = I915_READ8(TR1);
+
+       b = tsfs & TSFS_INTR_MASK;
+
+       return ((m * x) / 127) - b;
+}
+
+static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
+{
+       static const struct v_table {
+               u16 vd; /* in .1 mil */
+               u16 vm; /* in .1 mil */
+       } v_table[] = {
+               { 0, 0, },
+               { 375, 0, },
+               { 500, 0, },
+               { 625, 0, },
+               { 750, 0, },
+               { 875, 0, },
+               { 1000, 0, },
+               { 1125, 0, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4125, 3000, },
+               { 4250, 3125, },
+               { 4375, 3250, },
+               { 4500, 3375, },
+               { 4625, 3500, },
+               { 4750, 3625, },
+               { 4875, 3750, },
+               { 5000, 3875, },
+               { 5125, 4000, },
+               { 5250, 4125, },
+               { 5375, 4250, },
+               { 5500, 4375, },
+               { 5625, 4500, },
+               { 5750, 4625, },
+               { 5875, 4750, },
+               { 6000, 4875, },
+               { 6125, 5000, },
+               { 6250, 5125, },
+               { 6375, 5250, },
+               { 6500, 5375, },
+               { 6625, 5500, },
+               { 6750, 5625, },
+               { 6875, 5750, },
+               { 7000, 5875, },
+               { 7125, 6000, },
+               { 7250, 6125, },
+               { 7375, 6250, },
+               { 7500, 6375, },
+               { 7625, 6500, },
+               { 7750, 6625, },
+               { 7875, 6750, },
+               { 8000, 6875, },
+               { 8125, 7000, },
+               { 8250, 7125, },
+               { 8375, 7250, },
+               { 8500, 7375, },
+               { 8625, 7500, },
+               { 8750, 7625, },
+               { 8875, 7750, },
+               { 9000, 7875, },
+               { 9125, 8000, },
+               { 9250, 8125, },
+               { 9375, 8250, },
+               { 9500, 8375, },
+               { 9625, 8500, },
+               { 9750, 8625, },
+               { 9875, 8750, },
+               { 10000, 8875, },
+               { 10125, 9000, },
+               { 10250, 9125, },
+               { 10375, 9250, },
+               { 10500, 9375, },
+               { 10625, 9500, },
+               { 10750, 9625, },
+               { 10875, 9750, },
+               { 11000, 9875, },
+               { 11125, 10000, },
+               { 11250, 10125, },
+               { 11375, 10250, },
+               { 11500, 10375, },
+               { 11625, 10500, },
+               { 11750, 10625, },
+               { 11875, 10750, },
+               { 12000, 10875, },
+               { 12125, 11000, },
+               { 12250, 11125, },
+               { 12375, 11250, },
+               { 12500, 11375, },
+               { 12625, 11500, },
+               { 12750, 11625, },
+               { 12875, 11750, },
+               { 13000, 11875, },
+               { 13125, 12000, },
+               { 13250, 12125, },
+               { 13375, 12250, },
+               { 13500, 12375, },
+               { 13625, 12500, },
+               { 13750, 12625, },
+               { 13875, 12750, },
+               { 14000, 12875, },
+               { 14125, 13000, },
+               { 14250, 13125, },
+               { 14375, 13250, },
+               { 14500, 13375, },
+               { 14625, 13500, },
+               { 14750, 13625, },
+               { 14875, 13750, },
+               { 15000, 13875, },
+               { 15125, 14000, },
+               { 15250, 14125, },
+               { 15375, 14250, },
+               { 15500, 14375, },
+               { 15625, 14500, },
+               { 15750, 14625, },
+               { 15875, 14750, },
+               { 16000, 14875, },
+               { 16125, 15000, },
+       };
+       if (dev_priv->info->is_mobile)
+               return v_table[pxvid].vm;
+       else
+               return v_table[pxvid].vd;
+}
+
+void i915_update_gfx_val(struct drm_i915_private *dev_priv)
+{
+       struct timespec now, diff1;
+       u64 diff;
+       unsigned long diffms;
+       u32 count;
+
+       if (dev_priv->info->gen != 5)
+               return;
+
+       getrawmonotonic(&now);
+       diff1 = timespec_sub(now, dev_priv->last_time2);
+
+       /* Don't divide by 0 */
+       diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
+       if (!diffms)
+               return;
+
+       count = I915_READ(GFXEC);
+
+       if (count < dev_priv->last_count2) {
+               diff = ~0UL - dev_priv->last_count2;
+               diff += count;
+       } else {
+               diff = count - dev_priv->last_count2;
+       }
+
+       dev_priv->last_count2 = count;
+       dev_priv->last_time2 = now;
+
+       /* More magic constants... */
+       diff = diff * 1181;
+       diff = div_u64(diff, diffms * 10);
+       dev_priv->gfx_power = diff;
+}
+
+unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
+{
+       unsigned long t, corr, state1, corr2, state2;
+       u32 pxvid, ext_v;
+
+       pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
+       pxvid = (pxvid >> 24) & 0x7f;
+       ext_v = pvid_to_extvid(dev_priv, pxvid);
+
+       state1 = ext_v;
+
+       t = i915_mch_val(dev_priv);
+
+       /* Revel in the empirically derived constants */
+
+       /* Correction factor in 1/100000 units */
+       if (t > 80)
+               corr = ((t * 2349) + 135940);
+       else if (t >= 50)
+               corr = ((t * 964) + 29317);
+       else /* < 50 */
+               corr = ((t * 301) + 1004);
+
+       corr = corr * ((150142 * state1) / 10000 - 78642);
+       corr /= 100000;
+       corr2 = (corr * dev_priv->corr);
+
+       state2 = (corr2 * state1) / 10000;
+       state2 /= 100; /* convert to mW */
+
+       i915_update_gfx_val(dev_priv);
+
+       return dev_priv->gfx_power + state2;
+}
+
+/* Global for IPS driver to get at the current i915 device */
+static struct drm_i915_private *i915_mch_dev;
+/*
+ * Lock protecting IPS related data structures
+ *   - i915_mch_dev
+ *   - dev_priv->max_delay
+ *   - dev_priv->min_delay
+ *   - dev_priv->fmax
+ *   - dev_priv->gpu_busy
+ */
+static DEFINE_SPINLOCK(mchdev_lock);
+
+/**
+ * i915_read_mch_val - return value for IPS use
+ *
+ * Calculate and return a value for the IPS driver to use when deciding whether
+ * we have thermal and power headroom to increase CPU or GPU power budget.
+ */
+unsigned long i915_read_mch_val(void)
+{
+       struct drm_i915_private *dev_priv;
+       unsigned long chipset_val, graphics_val, ret = 0;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev)
+               goto out_unlock;
+       dev_priv = i915_mch_dev;
+
+       chipset_val = i915_chipset_val(dev_priv);
+       graphics_val = i915_gfx_val(dev_priv);
+
+       ret = chipset_val + graphics_val;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_read_mch_val);
+
+/**
+ * i915_gpu_raise - raise GPU frequency limit
+ *
+ * Raise the limit; IPS indicates we have thermal headroom.
+ */
+bool i915_gpu_raise(void)
+{
+       struct drm_i915_private *dev_priv;
+       bool ret = true;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev) {
+               ret = false;
+               goto out_unlock;
+       }
+       dev_priv = i915_mch_dev;
+
+       if (dev_priv->max_delay > dev_priv->fmax)
+               dev_priv->max_delay--;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_raise);
+
+/**
+ * i915_gpu_lower - lower GPU frequency limit
+ *
+ * IPS indicates we're close to a thermal limit, so throttle back the GPU
+ * frequency maximum.
+ */
+bool i915_gpu_lower(void)
+{
+       struct drm_i915_private *dev_priv;
+       bool ret = true;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev) {
+               ret = false;
+               goto out_unlock;
+       }
+       dev_priv = i915_mch_dev;
+
+       if (dev_priv->max_delay < dev_priv->min_delay)
+               dev_priv->max_delay++;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_lower);
+
+/**
+ * i915_gpu_busy - indicate GPU business to IPS
+ *
+ * Tell the IPS driver whether or not the GPU is busy.
+ */
+bool i915_gpu_busy(void)
+{
+       struct drm_i915_private *dev_priv;
+       bool ret = false;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev)
+               goto out_unlock;
+       dev_priv = i915_mch_dev;
+
+       ret = dev_priv->busy;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_busy);
+
+/**
+ * i915_gpu_turbo_disable - disable graphics turbo
+ *
+ * Disable graphics turbo by resetting the max frequency and setting the
+ * current frequency to the default.
+ */
+bool i915_gpu_turbo_disable(void)
+{
+       struct drm_i915_private *dev_priv;
+       bool ret = true;
+
+       spin_lock(&mchdev_lock);
+       if (!i915_mch_dev) {
+               ret = false;
+               goto out_unlock;
+       }
+       dev_priv = i915_mch_dev;
+
+       dev_priv->max_delay = dev_priv->fstart;
+
+       if (!ironlake_set_drps(dev_priv->dev, dev_priv->fstart))
+               ret = false;
+
+out_unlock:
+       spin_unlock(&mchdev_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
+
+/**
+ * Tells the intel_ips driver that the i915 driver is now loaded, if
+ * IPS got loaded first.
+ *
+ * This awkward dance is so that neither module has to depend on the
+ * other in order for IPS to do the appropriate communication of
+ * GPU turbo limits to i915.
+ */
+static void
+ips_ping_for_i915_load(void)
+{
+       void (*link)(void);
+
+       link = symbol_get(ips_link_to_i915_driver);
+       if (link) {
+               link();
+               symbol_put(ips_link_to_i915_driver);
+       }
+}
+
+void intel_gpu_ips_init(struct drm_i915_private *dev_priv)
+{
+       spin_lock(&mchdev_lock);
+       i915_mch_dev = dev_priv;
+       dev_priv->mchdev_lock = &mchdev_lock;
+       spin_unlock(&mchdev_lock);
+
+       ips_ping_for_i915_load();
+}
+
+void intel_gpu_ips_teardown(void)
+{
+       spin_lock(&mchdev_lock);
+       i915_mch_dev = NULL;
+       spin_unlock(&mchdev_lock);
+}
+
+void intel_init_emon(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 lcfuse;
+       u8 pxw[16];
+       int i;
+
+       /* Disable to program */
+       I915_WRITE(ECR, 0);
+       POSTING_READ(ECR);
+
+       /* Program energy weights for various events */
+       I915_WRITE(SDEW, 0x15040d00);
+       I915_WRITE(CSIEW0, 0x007f0000);
+       I915_WRITE(CSIEW1, 0x1e220004);
+       I915_WRITE(CSIEW2, 0x04000004);
+
+       for (i = 0; i < 5; i++)
+               I915_WRITE(PEW + (i * 4), 0);
+       for (i = 0; i < 3; i++)
+               I915_WRITE(DEW + (i * 4), 0);
+
+       /* Program P-state weights to account for frequency power adjustment */
+       for (i = 0; i < 16; i++) {
+               u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4));
+               unsigned long freq = intel_pxfreq(pxvidfreq);
+               unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >>
+                       PXVFREQ_PX_SHIFT;
+               unsigned long val;
+
+               val = vid * vid;
+               val *= (freq / 1000);
+               val *= 255;
+               val /= (127*127*900);
+               if (val > 0xff)
+                       DRM_ERROR("bad pxval: %ld\n", val);
+               pxw[i] = val;
+       }
+       /* Render standby states get 0 weight */
+       pxw[14] = 0;
+       pxw[15] = 0;
+
+       for (i = 0; i < 4; i++) {
+               u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) |
+                       (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]);
+               I915_WRITE(PXW + (i * 4), val);
+       }
+
+       /* Adjust magic regs to magic values (more experimental results) */
+       I915_WRITE(OGW0, 0);
+       I915_WRITE(OGW1, 0);
+       I915_WRITE(EG0, 0x00007f00);
+       I915_WRITE(EG1, 0x0000000e);
+       I915_WRITE(EG2, 0x000e0000);
+       I915_WRITE(EG3, 0x68000300);
+       I915_WRITE(EG4, 0x42000000);
+       I915_WRITE(EG5, 0x00140031);
+       I915_WRITE(EG6, 0);
+       I915_WRITE(EG7, 0);
+
+       for (i = 0; i < 8; i++)
+               I915_WRITE(PXWL + (i * 4), 0);
+
+       /* Enable PMON + select events */
+       I915_WRITE(ECR, 0x80000019);
+
+       lcfuse = I915_READ(LCFUSE02);
+
+       dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
+}
+
+static void ironlake_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+
+       /* Required for FBC */
+       dspclk_gate |= DPFCUNIT_CLOCK_GATE_DISABLE |
+               DPFCRUNIT_CLOCK_GATE_DISABLE |
+               DPFDUNIT_CLOCK_GATE_DISABLE;
+       /* Required for CxSR */
+       dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE;
+
+       I915_WRITE(PCH_3DCGDIS0,
+                  MARIUNIT_CLOCK_GATE_DISABLE |
+                  SVSMUNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(PCH_3DCGDIS1,
+                  VFMUNIT_CLOCK_GATE_DISABLE);
+
+       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+
+       /*
+        * According to the spec the following bits should be set in
+        * order to enable memory self-refresh
+        * The bit 22/21 of 0x42004
+        * The bit 5 of 0x42020
+        * The bit 15 of 0x45000
+        */
+       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                  (I915_READ(ILK_DISPLAY_CHICKEN2) |
+                   ILK_DPARB_GATE | ILK_VSDPFD_FULL));
+       I915_WRITE(ILK_DSPCLK_GATE,
+                  (I915_READ(ILK_DSPCLK_GATE) |
+                   ILK_DPARB_CLK_GATE));
+       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);
+
+       /*
+        * Based on the document from hardware guys the following bits
+        * should be set unconditionally in order to enable FBC.
+        * The bit 22 of 0x42000
+        * The bit 22 of 0x42004
+        * The bit 7,8,9 of 0x42020.
+        */
+       if (IS_IRONLAKE_M(dev)) {
+               I915_WRITE(ILK_DISPLAY_CHICKEN1,
+                          I915_READ(ILK_DISPLAY_CHICKEN1) |
+                          ILK_FBCQ_DIS);
+               I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                          I915_READ(ILK_DISPLAY_CHICKEN2) |
+                          ILK_DPARB_GATE);
+               I915_WRITE(ILK_DSPCLK_GATE,
+                          I915_READ(ILK_DSPCLK_GATE) |
+                          ILK_DPFC_DIS1 |
+                          ILK_DPFC_DIS2 |
+                          ILK_CLK_FBC);
+       }
+
+       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                  I915_READ(ILK_DISPLAY_CHICKEN2) |
+                  ILK_ELPIN_409_SELECT);
+       I915_WRITE(_3D_CHICKEN2,
+                  _3D_CHICKEN2_WM_READ_PIPELINED << 16 |
+                  _3D_CHICKEN2_WM_READ_PIPELINED);
+}
+
+static void gen6_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe;
+       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+
+       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+
+       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                  I915_READ(ILK_DISPLAY_CHICKEN2) |
+                  ILK_ELPIN_409_SELECT);
+
+       I915_WRITE(WM3_LP_ILK, 0);
+       I915_WRITE(WM2_LP_ILK, 0);
+       I915_WRITE(WM1_LP_ILK, 0);
+
+       I915_WRITE(CACHE_MODE_0,
+                  _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
+
+       I915_WRITE(GEN6_UCGCTL1,
+                  I915_READ(GEN6_UCGCTL1) |
+                  GEN6_BLBUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_CSUNIT_CLOCK_GATE_DISABLE);
+
+       /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+        * gating disable must be set.  Failure to set it results in
+        * flickering pixels due to Z write ordering failures after
+        * some amount of runtime in the Mesa "fire" demo, and Unigine
+        * Sanctuary and Tropics, and apparently anything else with
+        * alpha test or pixel discard.
+        *
+        * According to the spec, bit 11 (RCCUNIT) must also be set,
+        * but we didn't debug actual testcases to find it out.
+        */
+       I915_WRITE(GEN6_UCGCTL2,
+                  GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+
+       /* Bspec says we need to always set all mask bits. */
+       I915_WRITE(_3D_CHICKEN, (0xFFFF << 16) |
+                  _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL);
+
+       /*
+        * According to the spec the following bits should be
+        * set in order to enable memory self-refresh and fbc:
+        * The bit21 and bit22 of 0x42000
+        * The bit21 and bit22 of 0x42004
+        * The bit5 and bit7 of 0x42020
+        * The bit14 of 0x70180
+        * The bit14 of 0x71180
+        */
+       I915_WRITE(ILK_DISPLAY_CHICKEN1,
+                  I915_READ(ILK_DISPLAY_CHICKEN1) |
+                  ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS);
+       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                  I915_READ(ILK_DISPLAY_CHICKEN2) |
+                  ILK_DPARB_GATE | ILK_VSDPFD_FULL);
+       I915_WRITE(ILK_DSPCLK_GATE,
+                  I915_READ(ILK_DSPCLK_GATE) |
+                  ILK_DPARB_CLK_GATE  |
+                  ILK_DPFD_CLK_GATE);
+
+       for_each_pipe(pipe) {
+               I915_WRITE(DSPCNTR(pipe),
+                          I915_READ(DSPCNTR(pipe)) |
+                          DISPPLANE_TRICKLE_FEED_DISABLE);
+               intel_flush_display_plane(dev_priv, pipe);
+       }
+}
+
+static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
+{
+       uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE);
+
+       reg &= ~GEN7_FF_SCHED_MASK;
+       reg |= GEN7_FF_TS_SCHED_HW;
+       reg |= GEN7_FF_VS_SCHED_HW;
+       reg |= GEN7_FF_DS_SCHED_HW;
+
+       I915_WRITE(GEN7_FF_THREAD_MODE, reg);
+}
+
+static void ivybridge_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe;
+       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+
+       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+
+       I915_WRITE(WM3_LP_ILK, 0);
+       I915_WRITE(WM2_LP_ILK, 0);
+       I915_WRITE(WM1_LP_ILK, 0);
+
+       /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
+        * This implements the WaDisableRCZUnitClockGating workaround.
+        */
+       I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
+
+       I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
+
+       I915_WRITE(IVB_CHICKEN3,
+                  CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
+                  CHICKEN3_DGMG_DONE_FIX_DISABLE);
+
+       /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
+       I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
+                  GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+
+       /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
+       I915_WRITE(GEN7_L3CNTLREG1,
+                       GEN7_WA_FOR_GEN7_L3_CONTROL);
+       I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
+                       GEN7_WA_L3_CHICKEN_MODE);
+
+       /* This is required by WaCatErrorRejectionIssue */
+       I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+                       I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
+                       GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+
+       for_each_pipe(pipe) {
+               I915_WRITE(DSPCNTR(pipe),
+                          I915_READ(DSPCNTR(pipe)) |
+                          DISPPLANE_TRICKLE_FEED_DISABLE);
+               intel_flush_display_plane(dev_priv, pipe);
+       }
+
+       gen7_setup_fixed_func_scheduler(dev_priv);
+
+       /* WaDisable4x2SubspanOptimization */
+       I915_WRITE(CACHE_MODE_1,
+                  _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
+}
+
+static void valleyview_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe;
+       uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
+
+       I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+
+       I915_WRITE(WM3_LP_ILK, 0);
+       I915_WRITE(WM2_LP_ILK, 0);
+       I915_WRITE(WM1_LP_ILK, 0);
+
+       /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
+        * This implements the WaDisableRCZUnitClockGating workaround.
+        */
+       I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
+
+       I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
+
+       I915_WRITE(IVB_CHICKEN3,
+                  CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE |
+                  CHICKEN3_DGMG_DONE_FIX_DISABLE);
+
+       /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
+       I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
+                  GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+
+       /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
+       I915_WRITE(GEN7_L3CNTLREG1, GEN7_WA_FOR_GEN7_L3_CONTROL);
+       I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE);
+
+       /* This is required by WaCatErrorRejectionIssue */
+       I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+                  I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
+                  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+
+       for_each_pipe(pipe) {
+               I915_WRITE(DSPCNTR(pipe),
+                          I915_READ(DSPCNTR(pipe)) |
+                          DISPPLANE_TRICKLE_FEED_DISABLE);
+               intel_flush_display_plane(dev_priv, pipe);
+       }
+
+       I915_WRITE(CACHE_MODE_1,
+                  _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
+}
+
+static void g4x_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dspclk_gate;
+
+       I915_WRITE(RENCLK_GATE_D1, 0);
+       I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
+                  GS_UNIT_CLOCK_GATE_DISABLE |
+                  CL_UNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(RAMCLK_GATE_D, 0);
+       dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
+               OVRUNIT_CLOCK_GATE_DISABLE |
+               OVCUNIT_CLOCK_GATE_DISABLE;
+       if (IS_GM45(dev))
+               dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
+       I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
+}
+
+static void crestline_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
+       I915_WRITE(RENCLK_GATE_D2, 0);
+       I915_WRITE(DSPCLK_GATE_D, 0);
+       I915_WRITE(RAMCLK_GATE_D, 0);
+       I915_WRITE16(DEUC, 0);
+}
+
+static void broadwater_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
+                  I965_RCC_CLOCK_GATE_DISABLE |
+                  I965_RCPB_CLOCK_GATE_DISABLE |
+                  I965_ISC_CLOCK_GATE_DISABLE |
+                  I965_FBC_CLOCK_GATE_DISABLE);
+       I915_WRITE(RENCLK_GATE_D2, 0);
+}
+
+static void gen3_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dstate = I915_READ(D_STATE);
+
+       dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
+               DSTATE_DOT_CLOCK_GATING;
+       I915_WRITE(D_STATE, dstate);
+
+       if (IS_PINEVIEW(dev))
+               I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY));
+}
+
+static void i85x_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
+}
+
+static void i830_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
+}
+
+static void ibx_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       /*
+        * On Ibex Peak and Cougar Point, we need to disable clock
+        * gating for the panel power sequencer or it will fail to
+        * start up when no ports are active.
+        */
+       I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
+}
+
+static void cpt_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe;
+
+       /*
+        * On Ibex Peak and Cougar Point, we need to disable clock
+        * gating for the panel power sequencer or it will fail to
+        * start up when no ports are active.
+        */
+       I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
+       I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
+                  DPLS_EDP_PPS_FIX_DIS);
+       /* Without this, mode sets may fail silently on FDI */
+       for_each_pipe(pipe)
+               I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_AUTOTRAIN_GEN_STALL_DIS);
+}
+
+void intel_init_clock_gating(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       dev_priv->display.init_clock_gating(dev);
+
+       if (dev_priv->display.init_pch_clock_gating)
+               dev_priv->display.init_pch_clock_gating(dev);
+}
+
+static void gen6_sanitize_pm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 limits, delay, old;
+
+       gen6_gt_force_wake_get(dev_priv);
+
+       old = limits = I915_READ(GEN6_RP_INTERRUPT_LIMITS);
+       /* Make sure we continue to get interrupts
+        * until we hit the minimum or maximum frequencies.
+        */
+       limits &= ~(0x3f << 16 | 0x3f << 24);
+       delay = dev_priv->cur_delay;
+       if (delay < dev_priv->max_delay)
+               limits |= (dev_priv->max_delay & 0x3f) << 24;
+       if (delay > dev_priv->min_delay)
+               limits |= (dev_priv->min_delay & 0x3f) << 16;
+
+       if (old != limits) {
+               DRM_ERROR("Power management discrepancy: GEN6_RP_INTERRUPT_LIMITS expected %08x, was %08x\n",
+                         limits, old);
+               I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
+       }
+
+       gen6_gt_force_wake_put(dev_priv);
+}
+
+void intel_sanitize_pm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->display.sanitize_pm)
+               dev_priv->display.sanitize_pm(dev);
+}
+
+/* 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)) {
+                       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)) {
+                       dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
+                       dev_priv->display.enable_fbc = i8xx_enable_fbc;
+                       dev_priv->display.disable_fbc = i8xx_disable_fbc;
+               }
+               /* 855GM needs testing */
+       }
+
+       /* For cxsr */
+       if (IS_PINEVIEW(dev))
+               i915_pineview_get_mem_freq(dev);
+       else if (IS_GEN5(dev))
+               i915_ironlake_get_mem_freq(dev);
+
+       /* For FIFO watermark updates */
+       if (HAS_PCH_SPLIT(dev)) {
+               dev_priv->display.force_wake_get = __gen6_gt_force_wake_get;
+               dev_priv->display.force_wake_put = __gen6_gt_force_wake_put;
+
+               /* IVB configs may use multi-threaded forcewake */
+               if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
+                       u32     ecobus;
+
+                       /* A small trick here - if the bios hasn't configured MT forcewake,
+                        * and if the device is in RC6, then force_wake_mt_get will not wake
+                        * the device and the ECOBUS read will return zero. Which will be
+                        * (correctly) interpreted by the test below as MT forcewake being
+                        * disabled.
+                        */
+                       mutex_lock(&dev->struct_mutex);
+                       __gen6_gt_force_wake_mt_get(dev_priv);
+                       ecobus = I915_READ_NOTRACE(ECOBUS);
+                       __gen6_gt_force_wake_mt_put(dev_priv);
+                       mutex_unlock(&dev->struct_mutex);
+
+                       if (ecobus & FORCEWAKE_MT_ENABLE) {
+                               DRM_DEBUG_KMS("Using MT version of forcewake\n");
+                               dev_priv->display.force_wake_get =
+                                       __gen6_gt_force_wake_mt_get;
+                               dev_priv->display.force_wake_put =
+                                       __gen6_gt_force_wake_mt_put;
+                       }
+               }
+
+               if (HAS_PCH_IBX(dev))
+                       dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating;
+               else if (HAS_PCH_CPT(dev))
+                       dev_priv->display.init_pch_clock_gating = cpt_init_clock_gating;
+
+               if (IS_GEN5(dev)) {
+                       if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
+                               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;
+                       }
+                       dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
+               } else if (IS_GEN6(dev)) {
+                       if (SNB_READ_WM0_LATENCY()) {
+                               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;
+                       }
+                       dev_priv->display.init_clock_gating = gen6_init_clock_gating;
+                       dev_priv->display.sanitize_pm = gen6_sanitize_pm;
+               } else if (IS_IVYBRIDGE(dev)) {
+                       /* FIXME: detect B0+ stepping and use auto training */
+                       if (SNB_READ_WM0_LATENCY()) {
+                               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;
+                       }
+                       dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
+                       dev_priv->display.sanitize_pm = gen6_sanitize_pm;
+               } 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 =
+                       valleyview_init_clock_gating;
+               dev_priv->display.force_wake_get = vlv_force_wake_get;
+               dev_priv->display.force_wake_put = vlv_force_wake_put;
+       } else if (IS_PINEVIEW(dev)) {
+               if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
+                                           dev_priv->is_ddr3,
+                                           dev_priv->fsb_freq,
+                                           dev_priv->mem_freq)) {
+                       DRM_INFO("failed to find known CxSR latency "
+                                "(found ddr%s fsb freq %d, mem freq %d), "
+                                "disabling CxSR\n",
+                                (dev_priv->is_ddr3 == 1) ? "3" : "2",
+                                dev_priv->fsb_freq, dev_priv->mem_freq);
+                       /* Disable CxSR and never update its watermark again */
+                       pineview_disable_cxsr(dev);
+                       dev_priv->display.update_wm = NULL;
+               } else
+                       dev_priv->display.update_wm = pineview_update_wm;
+               dev_priv->display.init_clock_gating = gen3_init_clock_gating;
+       } else if (IS_G4X(dev)) {
+               dev_priv->display.update_wm = g4x_update_wm;
+               dev_priv->display.init_clock_gating = g4x_init_clock_gating;
+       } else if (IS_GEN4(dev)) {
+               dev_priv->display.update_wm = i965_update_wm;
+               if (IS_CRESTLINE(dev))
+                       dev_priv->display.init_clock_gating = crestline_init_clock_gating;
+               else if (IS_BROADWATER(dev))
+                       dev_priv->display.init_clock_gating = broadwater_init_clock_gating;
+       } else if (IS_GEN3(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))
+                       dev_priv->display.get_fifo_size = i845_get_fifo_size;
+               else
+                       dev_priv->display.get_fifo_size = i830_get_fifo_size;
+       }
+}
+
index fc66af6a9448e0dc8013194ab032d793012dd1bd..b59b6d5b75833e37e204da899c4dda2f65a9bf2d 100644 (file)
@@ -53,9 +53,35 @@ static inline int ring_space(struct intel_ring_buffer *ring)
 }
 
 static int
-render_ring_flush(struct intel_ring_buffer *ring,
-                 u32   invalidate_domains,
-                 u32   flush_domains)
+gen2_render_ring_flush(struct intel_ring_buffer *ring,
+                      u32      invalidate_domains,
+                      u32      flush_domains)
+{
+       u32 cmd;
+       int ret;
+
+       cmd = MI_FLUSH;
+       if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0)
+               cmd |= MI_NO_WRITE_FLUSH;
+
+       if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
+               cmd |= MI_READ_FLUSH;
+
+       ret = intel_ring_begin(ring, 2);
+       if (ret)
+               return ret;
+
+       intel_ring_emit(ring, cmd);
+       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_advance(ring);
+
+       return 0;
+}
+
+static int
+gen4_render_ring_flush(struct intel_ring_buffer *ring,
+                      u32      invalidate_domains,
+                      u32      flush_domains)
 {
        struct drm_device *dev = ring->dev;
        u32 cmd;
@@ -90,17 +116,8 @@ render_ring_flush(struct intel_ring_buffer *ring,
         */
 
        cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
-       if ((invalidate_domains|flush_domains) &
-           I915_GEM_DOMAIN_RENDER)
+       if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER)
                cmd &= ~MI_NO_WRITE_FLUSH;
-       if (INTEL_INFO(dev)->gen < 4) {
-               /*
-                * On the 965, the sampler cache always gets flushed
-                * and this bit is reserved.
-                */
-               if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
-                       cmd |= MI_READ_FLUSH;
-       }
        if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
                cmd |= MI_EXE_FLUSH;
 
@@ -290,9 +307,9 @@ static int init_ring_common(struct intel_ring_buffer *ring)
                        | RING_VALID);
 
        /* If the head is still not zero, the ring is dead */
-       if ((I915_READ_CTL(ring) & RING_VALID) == 0 ||
-           I915_READ_START(ring) != obj->gtt_offset ||
-           (I915_READ_HEAD(ring) & HEAD_ADDR) != 0) {
+       if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 &&
+                    I915_READ_START(ring) == obj->gtt_offset &&
+                    (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {
                DRM_ERROR("%s initialization failed "
                                "ctl %08x head %08x tail %08x start %08x\n",
                                ring->name,
@@ -384,12 +401,11 @@ static int init_render_ring(struct intel_ring_buffer *ring)
        int ret = init_ring_common(ring);
 
        if (INTEL_INFO(dev)->gen > 3) {
-               int mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
-               I915_WRITE(MI_MODE, mode);
+               I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
                if (IS_GEN7(dev))
                        I915_WRITE(GFX_MODE_GEN7,
-                                  GFX_MODE_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
-                                  GFX_MODE_ENABLE(GFX_REPLAY_MODE));
+                                  _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
+                                  _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
        }
 
        if (INTEL_INFO(dev)->gen >= 5) {
@@ -398,11 +414,19 @@ static int init_render_ring(struct intel_ring_buffer *ring)
                        return ret;
        }
 
-       if (INTEL_INFO(dev)->gen >= 6) {
-               I915_WRITE(INSTPM,
-                          INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING);
+       if (IS_GEN6(dev)) {
+               /* From the Sandybridge PRM, volume 1 part 3, page 24:
+                * "If this bit is set, STCunit will have LRA as replacement
+                *  policy. [...] This bit must be reset.  LRA replacement
+                *  policy is not supported."
+                */
+               I915_WRITE(CACHE_MODE_0,
+                          _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
        }
 
+       if (INTEL_INFO(dev)->gen >= 6)
+               I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
+
        return ret;
 }
 
@@ -472,21 +496,30 @@ gen6_add_request(struct intel_ring_buffer *ring,
  * @seqno - seqno which the waiter will block on
  */
 static int
-intel_ring_sync(struct intel_ring_buffer *waiter,
-               struct intel_ring_buffer *signaller,
-               int ring,
-               u32 seqno)
+gen6_ring_sync(struct intel_ring_buffer *waiter,
+              struct intel_ring_buffer *signaller,
+              u32 seqno)
 {
        int ret;
        u32 dw1 = MI_SEMAPHORE_MBOX |
                  MI_SEMAPHORE_COMPARE |
                  MI_SEMAPHORE_REGISTER;
 
+       /* Throughout all of the GEM code, seqno passed implies our current
+        * seqno is >= the last seqno executed. However for hardware the
+        * comparison is strictly greater than.
+        */
+       seqno -= 1;
+
+       WARN_ON(signaller->semaphore_register[waiter->id] ==
+               MI_SEMAPHORE_SYNC_INVALID);
+
        ret = intel_ring_begin(waiter, 4);
        if (ret)
                return ret;
 
-       intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]);
+       intel_ring_emit(waiter,
+                       dw1 | signaller->semaphore_register[waiter->id]);
        intel_ring_emit(waiter, seqno);
        intel_ring_emit(waiter, 0);
        intel_ring_emit(waiter, MI_NOOP);
@@ -495,47 +528,6 @@ intel_ring_sync(struct intel_ring_buffer *waiter,
        return 0;
 }
 
-/* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */
-int
-render_ring_sync_to(struct intel_ring_buffer *waiter,
-                   struct intel_ring_buffer *signaller,
-                   u32 seqno)
-{
-       WARN_ON(signaller->semaphore_register[RCS] == MI_SEMAPHORE_SYNC_INVALID);
-       return intel_ring_sync(waiter,
-                              signaller,
-                              RCS,
-                              seqno);
-}
-
-/* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */
-int
-gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter,
-                     struct intel_ring_buffer *signaller,
-                     u32 seqno)
-{
-       WARN_ON(signaller->semaphore_register[VCS] == MI_SEMAPHORE_SYNC_INVALID);
-       return intel_ring_sync(waiter,
-                              signaller,
-                              VCS,
-                              seqno);
-}
-
-/* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */
-int
-gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
-                     struct intel_ring_buffer *signaller,
-                     u32 seqno)
-{
-       WARN_ON(signaller->semaphore_register[BCS] == MI_SEMAPHORE_SYNC_INVALID);
-       return intel_ring_sync(waiter,
-                              signaller,
-                              BCS,
-                              seqno);
-}
-
-
-
 #define PIPE_CONTROL_FLUSH(ring__, addr__)                                     \
 do {                                                                   \
        intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |                \
@@ -597,27 +589,6 @@ pc_render_add_request(struct intel_ring_buffer *ring,
        return 0;
 }
 
-static int
-render_ring_add_request(struct intel_ring_buffer *ring,
-                       u32 *result)
-{
-       u32 seqno = i915_gem_next_request_seqno(ring);
-       int ret;
-
-       ret = intel_ring_begin(ring, 4);
-       if (ret)
-               return ret;
-
-       intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
-       intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-       intel_ring_emit(ring, seqno);
-       intel_ring_emit(ring, MI_USER_INTERRUPT);
-       intel_ring_advance(ring);
-
-       *result = seqno;
-       return 0;
-}
-
 static u32
 gen6_ring_get_seqno(struct intel_ring_buffer *ring)
 {
@@ -626,7 +597,7 @@ gen6_ring_get_seqno(struct intel_ring_buffer *ring)
        /* Workaround to force correct ordering between irq and seqno writes on
         * ivb (and maybe also on snb) by reading from a CS register (like
         * ACTHD) before reading the status page. */
-       if (IS_GEN7(dev))
+       if (IS_GEN6(dev) || IS_GEN7(dev))
                intel_ring_get_active_head(ring);
        return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
 }
@@ -644,76 +615,115 @@ pc_render_get_seqno(struct intel_ring_buffer *ring)
        return pc->cpu_page[0];
 }
 
-static void
-ironlake_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
+static bool
+gen5_ring_get_irq(struct intel_ring_buffer *ring)
 {
-       dev_priv->gt_irq_mask &= ~mask;
-       I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-       POSTING_READ(GTIMR);
+       struct drm_device *dev = ring->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long flags;
+
+       if (!dev->irq_enabled)
+               return false;
+
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
+       if (ring->irq_refcount++ == 0) {
+               dev_priv->gt_irq_mask &= ~ring->irq_enable_mask;
+               I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+               POSTING_READ(GTIMR);
+       }
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
+
+       return true;
 }
 
 static void
-ironlake_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
+gen5_ring_put_irq(struct intel_ring_buffer *ring)
 {
-       dev_priv->gt_irq_mask |= mask;
-       I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-       POSTING_READ(GTIMR);
+       struct drm_device *dev = ring->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
+       if (--ring->irq_refcount == 0) {
+               dev_priv->gt_irq_mask |= ring->irq_enable_mask;
+               I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+               POSTING_READ(GTIMR);
+       }
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
-static void
-i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
+static bool
+i9xx_ring_get_irq(struct intel_ring_buffer *ring)
 {
-       dev_priv->irq_mask &= ~mask;
-       I915_WRITE(IMR, dev_priv->irq_mask);
-       POSTING_READ(IMR);
+       struct drm_device *dev = ring->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long flags;
+
+       if (!dev->irq_enabled)
+               return false;
+
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
+       if (ring->irq_refcount++ == 0) {
+               dev_priv->irq_mask &= ~ring->irq_enable_mask;
+               I915_WRITE(IMR, dev_priv->irq_mask);
+               POSTING_READ(IMR);
+       }
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
+
+       return true;
 }
 
 static void
-i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
+i9xx_ring_put_irq(struct intel_ring_buffer *ring)
 {
-       dev_priv->irq_mask |= mask;
-       I915_WRITE(IMR, dev_priv->irq_mask);
-       POSTING_READ(IMR);
+       struct drm_device *dev = ring->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
+       if (--ring->irq_refcount == 0) {
+               dev_priv->irq_mask |= ring->irq_enable_mask;
+               I915_WRITE(IMR, dev_priv->irq_mask);
+               POSTING_READ(IMR);
+       }
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 static bool
-render_ring_get_irq(struct intel_ring_buffer *ring)
+i8xx_ring_get_irq(struct intel_ring_buffer *ring)
 {
        struct drm_device *dev = ring->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long flags;
 
        if (!dev->irq_enabled)
                return false;
 
-       spin_lock(&ring->irq_lock);
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (ring->irq_refcount++ == 0) {
-               if (HAS_PCH_SPLIT(dev))
-                       ironlake_enable_irq(dev_priv,
-                                           GT_PIPE_NOTIFY | GT_USER_INTERRUPT);
-               else
-                       i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
+               dev_priv->irq_mask &= ~ring->irq_enable_mask;
+               I915_WRITE16(IMR, dev_priv->irq_mask);
+               POSTING_READ16(IMR);
        }
-       spin_unlock(&ring->irq_lock);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
        return true;
 }
 
 static void
-render_ring_put_irq(struct intel_ring_buffer *ring)
+i8xx_ring_put_irq(struct intel_ring_buffer *ring)
 {
        struct drm_device *dev = ring->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long flags;
 
-       spin_lock(&ring->irq_lock);
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (--ring->irq_refcount == 0) {
-               if (HAS_PCH_SPLIT(dev))
-                       ironlake_disable_irq(dev_priv,
-                                            GT_USER_INTERRUPT |
-                                            GT_PIPE_NOTIFY);
-               else
-                       i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+               dev_priv->irq_mask |= ring->irq_enable_mask;
+               I915_WRITE16(IMR, dev_priv->irq_mask);
+               POSTING_READ16(IMR);
        }
-       spin_unlock(&ring->irq_lock);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
@@ -765,7 +775,7 @@ bsd_ring_flush(struct intel_ring_buffer *ring,
 }
 
 static int
-ring_add_request(struct intel_ring_buffer *ring,
+i9xx_add_request(struct intel_ring_buffer *ring,
                 u32 *result)
 {
        u32 seqno;
@@ -788,10 +798,11 @@ ring_add_request(struct intel_ring_buffer *ring,
 }
 
 static bool
-gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
+gen6_ring_get_irq(struct intel_ring_buffer *ring)
 {
        struct drm_device *dev = ring->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long flags;
 
        if (!dev->irq_enabled)
               return false;
@@ -801,120 +812,87 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
         * blt/bsd rings on ivb. */
        gen6_gt_force_wake_get(dev_priv);
 
-       spin_lock(&ring->irq_lock);
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (ring->irq_refcount++ == 0) {
-               ring->irq_mask &= ~rflag;
-               I915_WRITE_IMR(ring, ring->irq_mask);
-               ironlake_enable_irq(dev_priv, gflag);
+               I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
+               dev_priv->gt_irq_mask &= ~ring->irq_enable_mask;
+               I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+               POSTING_READ(GTIMR);
        }
-       spin_unlock(&ring->irq_lock);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
        return true;
 }
 
 static void
-gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
+gen6_ring_put_irq(struct intel_ring_buffer *ring)
 {
        struct drm_device *dev = ring->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned long flags;
 
-       spin_lock(&ring->irq_lock);
+       spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (--ring->irq_refcount == 0) {
-               ring->irq_mask |= rflag;
-               I915_WRITE_IMR(ring, ring->irq_mask);
-               ironlake_disable_irq(dev_priv, gflag);
+               I915_WRITE_IMR(ring, ~0);
+               dev_priv->gt_irq_mask |= ring->irq_enable_mask;
+               I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
+               POSTING_READ(GTIMR);
        }
-       spin_unlock(&ring->irq_lock);
+       spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
        gen6_gt_force_wake_put(dev_priv);
 }
 
-static bool
-bsd_ring_get_irq(struct intel_ring_buffer *ring)
+static int
+i965_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
 {
-       struct drm_device *dev = ring->dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       if (!dev->irq_enabled)
-               return false;
+       int ret;
 
-       spin_lock(&ring->irq_lock);
-       if (ring->irq_refcount++ == 0) {
-               if (IS_G4X(dev))
-                       i915_enable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
-               else
-                       ironlake_enable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
-       }
-       spin_unlock(&ring->irq_lock);
+       ret = intel_ring_begin(ring, 2);
+       if (ret)
+               return ret;
 
-       return true;
-}
-static void
-bsd_ring_put_irq(struct intel_ring_buffer *ring)
-{
-       struct drm_device *dev = ring->dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
+       intel_ring_emit(ring,
+                       MI_BATCH_BUFFER_START |
+                       MI_BATCH_GTT |
+                       MI_BATCH_NON_SECURE_I965);
+       intel_ring_emit(ring, offset);
+       intel_ring_advance(ring);
 
-       spin_lock(&ring->irq_lock);
-       if (--ring->irq_refcount == 0) {
-               if (IS_G4X(dev))
-                       i915_disable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
-               else
-                       ironlake_disable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
-       }
-       spin_unlock(&ring->irq_lock);
+       return 0;
 }
 
 static int
-ring_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
+i830_dispatch_execbuffer(struct intel_ring_buffer *ring,
+                               u32 offset, u32 len)
 {
        int ret;
 
-       ret = intel_ring_begin(ring, 2);
+       ret = intel_ring_begin(ring, 4);
        if (ret)
                return ret;
 
-       intel_ring_emit(ring,
-                       MI_BATCH_BUFFER_START | (2 << 6) |
-                       MI_BATCH_NON_SECURE_I965);
-       intel_ring_emit(ring, offset);
+       intel_ring_emit(ring, MI_BATCH_BUFFER);
+       intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
+       intel_ring_emit(ring, offset + len - 8);
+       intel_ring_emit(ring, 0);
        intel_ring_advance(ring);
 
        return 0;
 }
 
 static int
-render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
+i915_dispatch_execbuffer(struct intel_ring_buffer *ring,
                                u32 offset, u32 len)
 {
-       struct drm_device *dev = ring->dev;
        int ret;
 
-       if (IS_I830(dev) || IS_845G(dev)) {
-               ret = intel_ring_begin(ring, 4);
-               if (ret)
-                       return ret;
-
-               intel_ring_emit(ring, MI_BATCH_BUFFER);
-               intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
-               intel_ring_emit(ring, offset + len - 8);
-               intel_ring_emit(ring, 0);
-       } else {
-               ret = intel_ring_begin(ring, 2);
-               if (ret)
-                       return ret;
+       ret = intel_ring_begin(ring, 2);
+       if (ret)
+               return ret;
 
-               if (INTEL_INFO(dev)->gen >= 4) {
-                       intel_ring_emit(ring,
-                                       MI_BATCH_BUFFER_START | (2 << 6) |
-                                       MI_BATCH_NON_SECURE_I965);
-                       intel_ring_emit(ring, offset);
-               } else {
-                       intel_ring_emit(ring,
-                                       MI_BATCH_BUFFER_START | (2 << 6));
-                       intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
-               }
-       }
+       intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
+       intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
        intel_ring_advance(ring);
 
        return 0;
@@ -922,7 +900,6 @@ render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
 
 static void cleanup_status_page(struct intel_ring_buffer *ring)
 {
-       drm_i915_private_t *dev_priv = ring->dev->dev_private;
        struct drm_i915_gem_object *obj;
 
        obj = ring->status_page.obj;
@@ -933,14 +910,11 @@ static void cleanup_status_page(struct intel_ring_buffer *ring)
        i915_gem_object_unpin(obj);
        drm_gem_object_unreference(&obj->base);
        ring->status_page.obj = NULL;
-
-       memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
 }
 
 static int init_status_page(struct intel_ring_buffer *ring)
 {
        struct drm_device *dev = ring->dev;
-       drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
        int ret;
 
@@ -961,7 +935,6 @@ static int init_status_page(struct intel_ring_buffer *ring)
        ring->status_page.gfx_addr = obj->gtt_offset;
        ring->status_page.page_addr = kmap(obj->pages[0]);
        if (ring->status_page.page_addr == NULL) {
-               memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
                goto err_unpin;
        }
        ring->status_page.obj = obj;
@@ -981,8 +954,8 @@ err:
        return ret;
 }
 
-int intel_init_ring_buffer(struct drm_device *dev,
-                          struct intel_ring_buffer *ring)
+static int intel_init_ring_buffer(struct drm_device *dev,
+                                 struct intel_ring_buffer *ring)
 {
        struct drm_i915_gem_object *obj;
        int ret;
@@ -991,10 +964,9 @@ int intel_init_ring_buffer(struct drm_device *dev,
        INIT_LIST_HEAD(&ring->active_list);
        INIT_LIST_HEAD(&ring->request_list);
        INIT_LIST_HEAD(&ring->gpu_write_list);
+       ring->size = 32 * PAGE_SIZE;
 
        init_waitqueue_head(&ring->irq_queue);
-       spin_lock_init(&ring->irq_lock);
-       ring->irq_mask = ~0;
 
        if (I915_NEED_GFX_HWS(dev)) {
                ret = init_status_page(ring);
@@ -1015,20 +987,14 @@ int intel_init_ring_buffer(struct drm_device *dev,
        if (ret)
                goto err_unref;
 
-       ring->map.size = ring->size;
-       ring->map.offset = dev->agp->base + obj->gtt_offset;
-       ring->map.type = 0;
-       ring->map.flags = 0;
-       ring->map.mtrr = 0;
-
-       drm_core_ioremap_wc(&ring->map, dev);
-       if (ring->map.handle == NULL) {
+       ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset,
+                                        ring->size);
+       if (ring->virtual_start == NULL) {
                DRM_ERROR("Failed to map ringbuffer.\n");
                ret = -EINVAL;
                goto err_unpin;
        }
 
-       ring->virtual_start = ring->map.handle;
        ret = ring->init(ring);
        if (ret)
                goto err_unmap;
@@ -1038,13 +1004,13 @@ int intel_init_ring_buffer(struct drm_device *dev,
         * of the buffer.
         */
        ring->effective_size = ring->size;
-       if (IS_I830(ring->dev))
+       if (IS_I830(ring->dev) || IS_845G(ring->dev))
                ring->effective_size -= 128;
 
        return 0;
 
 err_unmap:
-       drm_core_ioremapfree(&ring->map, dev);
+       iounmap(ring->virtual_start);
 err_unpin:
        i915_gem_object_unpin(obj);
 err_unref:
@@ -1072,7 +1038,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
 
        I915_WRITE_CTL(ring, 0);
 
-       drm_core_ioremapfree(&ring->map, ring->dev);
+       iounmap(ring->virtual_start);
 
        i915_gem_object_unpin(ring->obj);
        drm_gem_object_unreference(&ring->obj->base);
@@ -1086,7 +1052,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
 
 static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
 {
-       unsigned int *virt;
+       uint32_t __iomem *virt;
        int rem = ring->size - ring->tail;
 
        if (ring->space < rem) {
@@ -1095,12 +1061,10 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
                        return ret;
        }
 
-       virt = (unsigned int *)(ring->virtual_start + ring->tail);
-       rem /= 8;
-       while (rem--) {
-               *virt++ = MI_NOOP;
-               *virt++ = MI_NOOP;
-       }
+       virt = ring->virtual_start + ring->tail;
+       rem /= 4;
+       while (rem--)
+               iowrite32(MI_NOOP, virt++);
 
        ring->tail = 0;
        ring->space = ring_space(ring);
@@ -1121,9 +1085,11 @@ static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
        was_interruptible = dev_priv->mm.interruptible;
        dev_priv->mm.interruptible = false;
 
-       ret = i915_wait_request(ring, seqno, true);
+       ret = i915_wait_request(ring, seqno);
 
        dev_priv->mm.interruptible = was_interruptible;
+       if (!ret)
+               i915_gem_retire_requests_ring(ring);
 
        return ret;
 }
@@ -1197,15 +1163,12 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
                return ret;
 
        trace_i915_ring_wait_begin(ring);
-       if (drm_core_check_feature(dev, DRIVER_GEM))
-               /* With GEM the hangcheck timer should kick us out of the loop,
-                * leaving it early runs the risk of corrupting GEM state (due
-                * to running on almost untested codepaths). But on resume
-                * timers don't work yet, so prevent a complete hang in that
-                * case by choosing an insanely large timeout. */
-               end = jiffies + 60 * HZ;
-       else
-               end = jiffies + 3 * HZ;
+       /* With GEM the hangcheck timer should kick us out of the loop,
+        * leaving it early runs the risk of corrupting GEM state (due
+        * to running on almost untested codepaths). But on resume
+        * timers don't work yet, so prevent a complete hang in that
+        * case by choosing an insanely large timeout. */
+       end = jiffies + 60 * HZ;
 
        do {
                ring->head = I915_READ_HEAD(ring);
@@ -1257,48 +1220,14 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
 
 void intel_ring_advance(struct intel_ring_buffer *ring)
 {
+       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+
        ring->tail &= ring->size - 1;
+       if (dev_priv->stop_rings & intel_ring_flag(ring))
+               return;
        ring->write_tail(ring, ring->tail);
 }
 
-static const struct intel_ring_buffer render_ring = {
-       .name                   = "render ring",
-       .id                     = RCS,
-       .mmio_base              = RENDER_RING_BASE,
-       .size                   = 32 * PAGE_SIZE,
-       .init                   = init_render_ring,
-       .write_tail             = ring_write_tail,
-       .flush                  = render_ring_flush,
-       .add_request            = render_ring_add_request,
-       .get_seqno              = ring_get_seqno,
-       .irq_get                = render_ring_get_irq,
-       .irq_put                = render_ring_put_irq,
-       .dispatch_execbuffer    = render_ring_dispatch_execbuffer,
-       .cleanup                = render_ring_cleanup,
-       .sync_to                = render_ring_sync_to,
-       .semaphore_register     = {MI_SEMAPHORE_SYNC_INVALID,
-                                  MI_SEMAPHORE_SYNC_RV,
-                                  MI_SEMAPHORE_SYNC_RB},
-       .signal_mbox            = {GEN6_VRSYNC, GEN6_BRSYNC},
-};
-
-/* ring buffer for bit-stream decoder */
-
-static const struct intel_ring_buffer bsd_ring = {
-       .name                   = "bsd ring",
-       .id                     = VCS,
-       .mmio_base              = BSD_RING_BASE,
-       .size                   = 32 * PAGE_SIZE,
-       .init                   = init_ring_common,
-       .write_tail             = ring_write_tail,
-       .flush                  = bsd_ring_flush,
-       .add_request            = ring_add_request,
-       .get_seqno              = ring_get_seqno,
-       .irq_get                = bsd_ring_get_irq,
-       .irq_put                = bsd_ring_put_irq,
-       .dispatch_execbuffer    = ring_dispatch_execbuffer,
-};
-
 
 static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
                                     u32 value)
@@ -1361,77 +1290,8 @@ gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
        return 0;
 }
 
-static bool
-gen6_render_ring_get_irq(struct intel_ring_buffer *ring)
-{
-       return gen6_ring_get_irq(ring,
-                                GT_USER_INTERRUPT,
-                                GEN6_RENDER_USER_INTERRUPT);
-}
-
-static void
-gen6_render_ring_put_irq(struct intel_ring_buffer *ring)
-{
-       return gen6_ring_put_irq(ring,
-                                GT_USER_INTERRUPT,
-                                GEN6_RENDER_USER_INTERRUPT);
-}
-
-static bool
-gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring)
-{
-       return gen6_ring_get_irq(ring,
-                                GT_GEN6_BSD_USER_INTERRUPT,
-                                GEN6_BSD_USER_INTERRUPT);
-}
-
-static void
-gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring)
-{
-       return gen6_ring_put_irq(ring,
-                                GT_GEN6_BSD_USER_INTERRUPT,
-                                GEN6_BSD_USER_INTERRUPT);
-}
-
-/* ring buffer for Video Codec for Gen6+ */
-static const struct intel_ring_buffer gen6_bsd_ring = {
-       .name                   = "gen6 bsd ring",
-       .id                     = VCS,
-       .mmio_base              = GEN6_BSD_RING_BASE,
-       .size                   = 32 * PAGE_SIZE,
-       .init                   = init_ring_common,
-       .write_tail             = gen6_bsd_ring_write_tail,
-       .flush                  = gen6_ring_flush,
-       .add_request            = gen6_add_request,
-       .get_seqno              = gen6_ring_get_seqno,
-       .irq_get                = gen6_bsd_ring_get_irq,
-       .irq_put                = gen6_bsd_ring_put_irq,
-       .dispatch_execbuffer    = gen6_ring_dispatch_execbuffer,
-       .sync_to                = gen6_bsd_ring_sync_to,
-       .semaphore_register     = {MI_SEMAPHORE_SYNC_VR,
-                                  MI_SEMAPHORE_SYNC_INVALID,
-                                  MI_SEMAPHORE_SYNC_VB},
-       .signal_mbox            = {GEN6_RVSYNC, GEN6_BVSYNC},
-};
-
 /* Blitter support (SandyBridge+) */
 
-static bool
-blt_ring_get_irq(struct intel_ring_buffer *ring)
-{
-       return gen6_ring_get_irq(ring,
-                                GT_BLT_USER_INTERRUPT,
-                                GEN6_BLITTER_USER_INTERRUPT);
-}
-
-static void
-blt_ring_put_irq(struct intel_ring_buffer *ring)
-{
-       gen6_ring_put_irq(ring,
-                         GT_BLT_USER_INTERRUPT,
-                         GEN6_BLITTER_USER_INTERRUPT);
-}
-
 static int blt_ring_flush(struct intel_ring_buffer *ring,
                          u32 invalidate, u32 flush)
 {
@@ -1453,42 +1313,63 @@ static int blt_ring_flush(struct intel_ring_buffer *ring,
        return 0;
 }
 
-static const struct intel_ring_buffer gen6_blt_ring = {
-       .name                   = "blt ring",
-       .id                     = BCS,
-       .mmio_base              = BLT_RING_BASE,
-       .size                   = 32 * PAGE_SIZE,
-       .init                   = init_ring_common,
-       .write_tail             = ring_write_tail,
-       .flush                  = blt_ring_flush,
-       .add_request            = gen6_add_request,
-       .get_seqno              = gen6_ring_get_seqno,
-       .irq_get                = blt_ring_get_irq,
-       .irq_put                = blt_ring_put_irq,
-       .dispatch_execbuffer    = gen6_ring_dispatch_execbuffer,
-       .sync_to                = gen6_blt_ring_sync_to,
-       .semaphore_register     = {MI_SEMAPHORE_SYNC_BR,
-                                  MI_SEMAPHORE_SYNC_BV,
-                                  MI_SEMAPHORE_SYNC_INVALID},
-       .signal_mbox            = {GEN6_RBSYNC, GEN6_VBSYNC},
-};
-
 int intel_init_render_ring_buffer(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
 
-       *ring = render_ring;
+       ring->name = "render ring";
+       ring->id = RCS;
+       ring->mmio_base = RENDER_RING_BASE;
+
        if (INTEL_INFO(dev)->gen >= 6) {
                ring->add_request = gen6_add_request;
                ring->flush = gen6_render_ring_flush;
-               ring->irq_get = gen6_render_ring_get_irq;
-               ring->irq_put = gen6_render_ring_put_irq;
+               ring->irq_get = gen6_ring_get_irq;
+               ring->irq_put = gen6_ring_put_irq;
+               ring->irq_enable_mask = GT_USER_INTERRUPT;
                ring->get_seqno = gen6_ring_get_seqno;
+               ring->sync_to = gen6_ring_sync;
+               ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID;
+               ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV;
+               ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_RB;
+               ring->signal_mbox[0] = GEN6_VRSYNC;
+               ring->signal_mbox[1] = GEN6_BRSYNC;
        } else if (IS_GEN5(dev)) {
                ring->add_request = pc_render_add_request;
+               ring->flush = gen4_render_ring_flush;
                ring->get_seqno = pc_render_get_seqno;
+               ring->irq_get = gen5_ring_get_irq;
+               ring->irq_put = gen5_ring_put_irq;
+               ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY;
+       } else {
+               ring->add_request = i9xx_add_request;
+               if (INTEL_INFO(dev)->gen < 4)
+                       ring->flush = gen2_render_ring_flush;
+               else
+                       ring->flush = gen4_render_ring_flush;
+               ring->get_seqno = ring_get_seqno;
+               if (IS_GEN2(dev)) {
+                       ring->irq_get = i8xx_ring_get_irq;
+                       ring->irq_put = i8xx_ring_put_irq;
+               } else {
+                       ring->irq_get = i9xx_ring_get_irq;
+                       ring->irq_put = i9xx_ring_put_irq;
+               }
+               ring->irq_enable_mask = I915_USER_INTERRUPT;
        }
+       ring->write_tail = ring_write_tail;
+       if (INTEL_INFO(dev)->gen >= 6)
+               ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+       else if (INTEL_INFO(dev)->gen >= 4)
+               ring->dispatch_execbuffer = i965_dispatch_execbuffer;
+       else if (IS_I830(dev) || IS_845G(dev))
+               ring->dispatch_execbuffer = i830_dispatch_execbuffer;
+       else
+               ring->dispatch_execbuffer = i915_dispatch_execbuffer;
+       ring->init = init_render_ring;
+       ring->cleanup = render_ring_cleanup;
+
 
        if (!I915_NEED_GFX_HWS(dev)) {
                ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
@@ -1503,15 +1384,41 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
 
-       *ring = render_ring;
+       ring->name = "render ring";
+       ring->id = RCS;
+       ring->mmio_base = RENDER_RING_BASE;
+
        if (INTEL_INFO(dev)->gen >= 6) {
-               ring->add_request = gen6_add_request;
-               ring->irq_get = gen6_render_ring_get_irq;
-               ring->irq_put = gen6_render_ring_put_irq;
-       } else if (IS_GEN5(dev)) {
-               ring->add_request = pc_render_add_request;
-               ring->get_seqno = pc_render_get_seqno;
+               /* non-kms not supported on gen6+ */
+               return -ENODEV;
+       }
+
+       /* Note: gem is not supported on gen5/ilk without kms (the corresponding
+        * gem_init ioctl returns with -ENODEV). Hence we do not need to set up
+        * the special gen5 functions. */
+       ring->add_request = i9xx_add_request;
+       if (INTEL_INFO(dev)->gen < 4)
+               ring->flush = gen2_render_ring_flush;
+       else
+               ring->flush = gen4_render_ring_flush;
+       ring->get_seqno = ring_get_seqno;
+       if (IS_GEN2(dev)) {
+               ring->irq_get = i8xx_ring_get_irq;
+               ring->irq_put = i8xx_ring_put_irq;
+       } else {
+               ring->irq_get = i9xx_ring_get_irq;
+               ring->irq_put = i9xx_ring_put_irq;
        }
+       ring->irq_enable_mask = I915_USER_INTERRUPT;
+       ring->write_tail = ring_write_tail;
+       if (INTEL_INFO(dev)->gen >= 4)
+               ring->dispatch_execbuffer = i965_dispatch_execbuffer;
+       else if (IS_I830(dev) || IS_845G(dev))
+               ring->dispatch_execbuffer = i830_dispatch_execbuffer;
+       else
+               ring->dispatch_execbuffer = i915_dispatch_execbuffer;
+       ring->init = init_render_ring;
+       ring->cleanup = render_ring_cleanup;
 
        if (!I915_NEED_GFX_HWS(dev))
                ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
@@ -1526,20 +1433,13 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
        if (IS_I830(ring->dev))
                ring->effective_size -= 128;
 
-       ring->map.offset = start;
-       ring->map.size = size;
-       ring->map.type = 0;
-       ring->map.flags = 0;
-       ring->map.mtrr = 0;
-
-       drm_core_ioremap_wc(&ring->map, dev);
-       if (ring->map.handle == NULL) {
+       ring->virtual_start = ioremap_wc(start, size);
+       if (ring->virtual_start == NULL) {
                DRM_ERROR("can not ioremap virtual address for"
                          " ring buffer\n");
                return -ENOMEM;
        }
 
-       ring->virtual_start = (void __force __iomem *)ring->map.handle;
        return 0;
 }
 
@@ -1548,10 +1448,46 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[VCS];
 
-       if (IS_GEN6(dev) || IS_GEN7(dev))
-               *ring = gen6_bsd_ring;
-       else
-               *ring = bsd_ring;
+       ring->name = "bsd ring";
+       ring->id = VCS;
+
+       ring->write_tail = ring_write_tail;
+       if (IS_GEN6(dev) || IS_GEN7(dev)) {
+               ring->mmio_base = GEN6_BSD_RING_BASE;
+               /* gen6 bsd needs a special wa for tail updates */
+               if (IS_GEN6(dev))
+                       ring->write_tail = gen6_bsd_ring_write_tail;
+               ring->flush = gen6_ring_flush;
+               ring->add_request = gen6_add_request;
+               ring->get_seqno = gen6_ring_get_seqno;
+               ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT;
+               ring->irq_get = gen6_ring_get_irq;
+               ring->irq_put = gen6_ring_put_irq;
+               ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+               ring->sync_to = gen6_ring_sync;
+               ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_VR;
+               ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_INVALID;
+               ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_VB;
+               ring->signal_mbox[0] = GEN6_RVSYNC;
+               ring->signal_mbox[1] = GEN6_BVSYNC;
+       } else {
+               ring->mmio_base = BSD_RING_BASE;
+               ring->flush = bsd_ring_flush;
+               ring->add_request = i9xx_add_request;
+               ring->get_seqno = ring_get_seqno;
+               if (IS_GEN5(dev)) {
+                       ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
+                       ring->irq_get = gen5_ring_get_irq;
+                       ring->irq_put = gen5_ring_put_irq;
+               } else {
+                       ring->irq_enable_mask = I915_BSD_USER_INTERRUPT;
+                       ring->irq_get = i9xx_ring_get_irq;
+                       ring->irq_put = i9xx_ring_put_irq;
+               }
+               ring->dispatch_execbuffer = i965_dispatch_execbuffer;
+       }
+       ring->init = init_ring_common;
+
 
        return intel_init_ring_buffer(dev, ring);
 }
@@ -1561,7 +1497,25 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
 
-       *ring = gen6_blt_ring;
+       ring->name = "blitter ring";
+       ring->id = BCS;
+
+       ring->mmio_base = BLT_RING_BASE;
+       ring->write_tail = ring_write_tail;
+       ring->flush = blt_ring_flush;
+       ring->add_request = gen6_add_request;
+       ring->get_seqno = gen6_ring_get_seqno;
+       ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT;
+       ring->irq_get = gen6_ring_get_irq;
+       ring->irq_put = gen6_ring_put_irq;
+       ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+       ring->sync_to = gen6_ring_sync;
+       ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_BR;
+       ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_BV;
+       ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_INVALID;
+       ring->signal_mbox[0] = GEN6_RBSYNC;
+       ring->signal_mbox[1] = GEN6_VBSYNC;
+       ring->init = init_ring_common;
 
        return intel_init_ring_buffer(dev, ring);
 }
index bc0365b8fa4d26983899f221d1f0e96ae593f7a5..baba75714578a340bb4bde915a501f7524a1c419 100644 (file)
@@ -2,7 +2,7 @@
 #define _INTEL_RINGBUFFER_H_
 
 struct  intel_hw_status_page {
-       u32     __iomem *page_addr;
+       u32             *page_addr;
        unsigned int    gfx_addr;
        struct          drm_i915_gem_object *obj;
 };
@@ -56,12 +56,9 @@ struct  intel_ring_buffer {
         */
        u32             last_retired_head;
 
-       spinlock_t      irq_lock;
-       u32             irq_refcount;
-       u32             irq_mask;
-       u32             irq_seqno;              /* last seq seem at irq time */
+       u32             irq_refcount;           /* protected by dev_priv->irq_lock */
+       u32             irq_enable_mask;        /* bitmask to enable ring interrupt */
        u32             trace_irq_seqno;
-       u32             waiting_seqno;
        u32             sync_seqno[I915_NUM_RINGS-1];
        bool __must_check (*irq_get)(struct intel_ring_buffer *ring);
        void            (*irq_put)(struct intel_ring_buffer *ring);
@@ -118,7 +115,6 @@ struct  intel_ring_buffer {
        u32 outstanding_lazy_request;
 
        wait_queue_head_t irq_queue;
-       drm_local_map_t map;
 
        void *private;
 };
@@ -152,7 +148,9 @@ static inline u32
 intel_read_status_page(struct intel_ring_buffer *ring,
                       int reg)
 {
-       return ioread32(ring->status_page.page_addr + reg);
+       /* Ensure that the compiler doesn't optimize away the load. */
+       barrier();
+       return ring->status_page.page_addr[reg];
 }
 
 /**
@@ -170,10 +168,7 @@ intel_read_status_page(struct intel_ring_buffer *ring,
  *
  * The area from dword 0x20 to 0x3ff is available for driver usage.
  */
-#define READ_HWSP(dev_priv, reg) intel_read_status_page(LP_RING(dev_priv), reg)
-#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
 #define I915_GEM_HWS_INDEX             0x20
-#define I915_BREADCRUMB_INDEX          0x21
 
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
 
index e36b171c1e7d5ff2b7a95b0dc6dd5db741f6e2fc..7d3f238e826562050c6fcb1771d765f7f1ad0e55 100644 (file)
@@ -41,7 +41,7 @@
 #define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)
 #define SDVO_RGB_MASK  (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)
 #define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1)
-#define SDVO_TV_MASK   (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0)
+#define SDVO_TV_MASK   (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_YPRPB0)
 
 #define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\
                        SDVO_TV_MASK)
@@ -74,7 +74,7 @@ struct intel_sdvo {
        struct i2c_adapter ddc;
 
        /* Register for the SDVO device: SDVOB or SDVOC */
-       int sdvo_reg;
+       uint32_t sdvo_reg;
 
        /* Active outputs controlled by this SDVO output */
        uint16_t controlled_output;
@@ -114,6 +114,9 @@ struct intel_sdvo {
         */
        bool is_tv;
 
+       /* On different gens SDVOB is at different places. */
+       bool is_sdvob;
+
        /* This is for current tv format name */
        int tv_format_index;
 
@@ -403,8 +406,7 @@ static const struct _sdvo_cmd_name {
        SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
 };
 
-#define IS_SDVOB(reg)  (reg == SDVOB || reg == PCH_SDVOB)
-#define SDVO_NAME(svdo) (IS_SDVOB((svdo)->sdvo_reg) ? "SDVOB" : "SDVOC")
+#define SDVO_NAME(svdo) ((svdo)->is_sdvob ? "SDVOB" : "SDVOC")
 
 static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
                                   const void *args, int args_len)
@@ -441,9 +443,17 @@ static const char *cmd_status_names[] = {
 static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd,
                                 const void *args, int args_len)
 {
-       u8 buf[args_len*2 + 2], status;
-       struct i2c_msg msgs[args_len + 3];
-       int i, ret;
+       u8 *buf, status;
+       struct i2c_msg *msgs;
+       int i, ret = true;
+
+       buf = (u8 *)kzalloc(args_len * 2 + 2, GFP_KERNEL);
+       if (!buf)
+               return false;
+
+       msgs = kcalloc(args_len + 3, sizeof(*msgs), GFP_KERNEL);
+       if (!msgs)
+               return false;
 
        intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len);
 
@@ -477,15 +487,19 @@ static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd,
        ret = i2c_transfer(intel_sdvo->i2c, msgs, i+3);
        if (ret < 0) {
                DRM_DEBUG_KMS("I2c transfer returned %d\n", ret);
-               return false;
+               ret = false;
+               goto out;
        }
        if (ret != i+3) {
                /* failure in I2C transfer */
                DRM_DEBUG_KMS("I2c transfer returned %d/%d\n", ret, i+3);
-               return false;
+               ret = false;
        }
 
-       return true;
+out:
+       kfree(msgs);
+       kfree(buf);
+       return ret;
 }
 
 static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
@@ -731,21 +745,26 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
        uint16_t width, height;
        uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
        uint16_t h_sync_offset, v_sync_offset;
+       int mode_clock;
 
-       width = mode->crtc_hdisplay;
-       height = mode->crtc_vdisplay;
+       width = mode->hdisplay;
+       height = mode->vdisplay;
 
        /* do some mode translations */
-       h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start;
-       h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+       h_blank_len = mode->htotal - mode->hdisplay;
+       h_sync_len = mode->hsync_end - mode->hsync_start;
+
+       v_blank_len = mode->vtotal - mode->vdisplay;
+       v_sync_len = mode->vsync_end - mode->vsync_start;
 
-       v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start;
-       v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+       h_sync_offset = mode->hsync_start - mode->hdisplay;
+       v_sync_offset = mode->vsync_start - mode->vdisplay;
 
-       h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
-       v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
+       mode_clock = mode->clock;
+       mode_clock /= intel_mode_get_pixel_multiplier(mode) ?: 1;
+       mode_clock /= 10;
+       dtd->part1.clock = mode_clock;
 
-       dtd->part1.clock = mode->clock / 10;
        dtd->part1.h_active = width & 0xff;
        dtd->part1.h_blank = h_blank_len & 0xff;
        dtd->part1.h_high = (((width >> 8) & 0xf) << 4) |
@@ -996,7 +1015,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
        struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
        u32 sdvox;
        struct intel_sdvo_in_out_map in_out;
-       struct intel_sdvo_dtd input_dtd;
+       struct intel_sdvo_dtd input_dtd, output_dtd;
        int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
        int rate;
 
@@ -1021,20 +1040,13 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
                                          intel_sdvo->attached_output))
                return;
 
-       /* We have tried to get input timing in mode_fixup, and filled into
-        * adjusted_mode.
-        */
-       if (intel_sdvo->is_tv || intel_sdvo->is_lvds) {
-               input_dtd = intel_sdvo->input_dtd;
-       } else {
-               /* Set the output timing to the screen */
-               if (!intel_sdvo_set_target_output(intel_sdvo,
-                                                 intel_sdvo->attached_output))
-                       return;
-
-               intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
-               (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd);
-       }
+       /* lvds has a special fixed output timing. */
+       if (intel_sdvo->is_lvds)
+               intel_sdvo_get_dtd_from_mode(&output_dtd,
+                                            intel_sdvo->sdvo_lvds_fixed_mode);
+       else
+               intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
+       (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd);
 
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
@@ -1052,6 +1064,10 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
            !intel_sdvo_set_tv_format(intel_sdvo))
                return;
 
+       /* We have tried to get input timing in mode_fixup, and filled into
+        * adjusted_mode.
+        */
+       intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
        (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd);
 
        switch (pixel_multiplier) {
@@ -1252,10 +1268,11 @@ intel_sdvo_get_analog_edid(struct drm_connector *connector)
        struct drm_i915_private *dev_priv = connector->dev->dev_private;
 
        return drm_get_edid(connector,
-                           &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
+                           intel_gmbus_get_adapter(dev_priv,
+                                                   dev_priv->crt_ddc_pin));
 }
 
-enum drm_connector_status
+static enum drm_connector_status
 intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
 {
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
@@ -1341,8 +1358,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
                return connector_status_unknown;
 
        /* add 30ms delay when the output type might be TV */
-       if (intel_sdvo->caps.output_flags &
-           (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0))
+       if (intel_sdvo->caps.output_flags & SDVO_TV_MASK)
                mdelay(30);
 
        if (!intel_sdvo_read_response(intel_sdvo, &response, 2))
@@ -1562,9 +1578,6 @@ end:
                        intel_sdvo->sdvo_lvds_fixed_mode =
                                drm_mode_duplicate(connector->dev, newmode);
 
-                       drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode,
-                                             0);
-
                        intel_sdvo->is_lvds = true;
                        break;
                }
@@ -1893,7 +1906,7 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
 {
        struct sdvo_device_mapping *mapping;
 
-       if (IS_SDVOB(reg))
+       if (sdvo->is_sdvob)
                mapping = &(dev_priv->sdvo_mappings[0]);
        else
                mapping = &(dev_priv->sdvo_mappings[1]);
@@ -1911,7 +1924,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
        struct sdvo_device_mapping *mapping;
        u8 pin;
 
-       if (IS_SDVOB(reg))
+       if (sdvo->is_sdvob)
                mapping = &dev_priv->sdvo_mappings[0];
        else
                mapping = &dev_priv->sdvo_mappings[1];
@@ -1920,12 +1933,12 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
        if (mapping->initialized)
                pin = mapping->i2c_pin;
 
-       if (pin < GMBUS_NUM_PORTS) {
-               sdvo->i2c = &dev_priv->gmbus[pin].adapter;
+       if (intel_gmbus_is_port_valid(pin)) {
+               sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin);
                intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);
                intel_gmbus_force_bit(sdvo->i2c, true);
        } else {
-               sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
+               sdvo->i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
        }
 }
 
@@ -1936,12 +1949,12 @@ intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device)
 }
 
 static u8
-intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg)
+intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct sdvo_device_mapping *my_mapping, *other_mapping;
 
-       if (IS_SDVOB(sdvo_reg)) {
+       if (sdvo->is_sdvob) {
                my_mapping = &dev_priv->sdvo_mappings[0];
                other_mapping = &dev_priv->sdvo_mappings[1];
        } else {
@@ -1966,7 +1979,7 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg)
        /* No SDVO device info is found for another DVO port,
         * so use mapping assumption we had before BIOS parsing.
         */
-       if (IS_SDVOB(sdvo_reg))
+       if (sdvo->is_sdvob)
                return 0x70;
        else
                return 0x72;
@@ -2191,6 +2204,10 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
                if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_CVBS0))
                        return false;
 
+       if (flags & SDVO_OUTPUT_YPRPB0)
+               if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_YPRPB0))
+                       return false;
+
        if (flags & SDVO_OUTPUT_RGB0)
                if (!intel_sdvo_analog_init(intel_sdvo, 0))
                        return false;
@@ -2482,7 +2499,7 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo,
        return i2c_add_adapter(&sdvo->ddc) == 0;
 }
 
-bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
+bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *intel_encoder;
@@ -2494,7 +2511,8 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
                return false;
 
        intel_sdvo->sdvo_reg = sdvo_reg;
-       intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg) >> 1;
+       intel_sdvo->is_sdvob = is_sdvob;
+       intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1;
        intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg);
        if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) {
                kfree(intel_sdvo);
@@ -2511,13 +2529,13 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
                u8 byte;
 
                if (!intel_sdvo_read_byte(intel_sdvo, i, &byte)) {
-                       DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n",
-                                     IS_SDVOB(sdvo_reg) ? 'B' : 'C');
+                       DRM_DEBUG_KMS("No SDVO device found on %s\n",
+                                     SDVO_NAME(intel_sdvo));
                        goto err;
                }
        }
 
-       if (IS_SDVOB(sdvo_reg))
+       if (intel_sdvo->is_sdvob)
                dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
        else
                dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
@@ -2538,8 +2556,8 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
 
        if (intel_sdvo_output_setup(intel_sdvo,
                                    intel_sdvo->caps.output_flags) != true) {
-               DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",
-                             IS_SDVOB(sdvo_reg) ? 'B' : 'C');
+               DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
+                             SDVO_NAME(intel_sdvo));
                goto err;
        }
 
index 7aa0450399a1e9b44379479de41ffac0757f2821..2a20fb0781d7591018fdb7202d96ee7685e9cbba 100644 (file)
@@ -95,7 +95,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        /* must disable */
        sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
        sprctl |= SPRITE_ENABLE;
-       sprctl |= SPRITE_DEST_KEY;
 
        /* Sizes are 0 based */
        src_w--;
@@ -111,14 +110,18 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
         * when scaling is disabled.
         */
        if (crtc_w != src_w || crtc_h != src_h) {
-               dev_priv->sprite_scaling_enabled = true;
-               sandybridge_update_wm(dev);
-               intel_wait_for_vblank(dev, pipe);
+               if (!dev_priv->sprite_scaling_enabled) {
+                       dev_priv->sprite_scaling_enabled = true;
+                       intel_update_watermarks(dev);
+                       intel_wait_for_vblank(dev, pipe);
+               }
                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
        } else {
-               dev_priv->sprite_scaling_enabled = false;
-               /* potentially re-enable LP watermarks */
-               sandybridge_update_wm(dev);
+               if (dev_priv->sprite_scaling_enabled) {
+                       dev_priv->sprite_scaling_enabled = false;
+                       /* potentially re-enable LP watermarks */
+                       intel_update_watermarks(dev);
+               }
        }
 
        I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
@@ -134,7 +137,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
        I915_WRITE(SPRSCALE(pipe), sprscale);
        I915_WRITE(SPRCTL(pipe), sprctl);
-       I915_WRITE(SPRSURF(pipe), obj->gtt_offset);
+       I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset);
        POSTING_READ(SPRSURF(pipe));
 }
 
@@ -150,8 +153,11 @@ ivb_disable_plane(struct drm_plane *plane)
        /* Can't leave the scaler enabled... */
        I915_WRITE(SPRSCALE(pipe), 0);
        /* Activate double buffered register update */
-       I915_WRITE(SPRSURF(pipe), 0);
+       I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
        POSTING_READ(SPRSURF(pipe));
+
+       dev_priv->sprite_scaling_enabled = false;
+       intel_update_watermarks(dev);
 }
 
 static int
@@ -209,7 +215,7 @@ ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 }
 
 static void
-snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
                 unsigned int crtc_w, unsigned int crtc_h,
                 uint32_t x, uint32_t y,
@@ -219,7 +225,7 @@ snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_plane *intel_plane = to_intel_plane(plane);
        int pipe = intel_plane->pipe, pixel_size;
-       u32 dvscntr, dvsscale = 0;
+       u32 dvscntr, dvsscale;
 
        dvscntr = I915_READ(DVSCNTR(pipe));
 
@@ -263,8 +269,8 @@ snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        if (obj->tiling_mode != I915_TILING_NONE)
                dvscntr |= DVS_TILED;
 
-       /* must disable */
-       dvscntr |= DVS_TRICKLE_FEED_DISABLE;
+       if (IS_GEN6(dev))
+               dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
        dvscntr |= DVS_ENABLE;
 
        /* Sizes are 0 based */
@@ -275,7 +281,8 @@ snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 
        intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
 
-       if (crtc_w != src_w || crtc_h != src_h)
+       dvsscale = 0;
+       if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
        I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
@@ -291,12 +298,12 @@ snb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
        I915_WRITE(DVSSCALE(pipe), dvsscale);
        I915_WRITE(DVSCNTR(pipe), dvscntr);
-       I915_WRITE(DVSSURF(pipe), obj->gtt_offset);
+       I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset);
        POSTING_READ(DVSSURF(pipe));
 }
 
 static void
-snb_disable_plane(struct drm_plane *plane)
+ilk_disable_plane(struct drm_plane *plane)
 {
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -307,7 +314,7 @@ snb_disable_plane(struct drm_plane *plane)
        /* Disable the scaler */
        I915_WRITE(DVSSCALE(pipe), 0);
        /* Flush double buffered register updates */
-       I915_WRITE(DVSSURF(pipe), 0);
+       I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
        POSTING_READ(DVSSURF(pipe));
 }
 
@@ -334,7 +341,7 @@ intel_disable_primary(struct drm_crtc *crtc)
 }
 
 static int
-snb_update_colorkey(struct drm_plane *plane,
+ilk_update_colorkey(struct drm_plane *plane,
                    struct drm_intel_sprite_colorkey *key)
 {
        struct drm_device *dev = plane->dev;
@@ -363,7 +370,7 @@ snb_update_colorkey(struct drm_plane *plane,
 }
 
 static void
-snb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
+ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 {
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -411,6 +418,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
        old_obj = intel_plane->obj;
 
+       src_w = src_w >> 16;
+       src_h = src_h >> 16;
+
        /* Pipe must be running... */
        if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
                return -EINVAL;
@@ -548,14 +558,13 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
                              struct drm_file *file_priv)
 {
        struct drm_intel_sprite_colorkey *set = data;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_mode_object *obj;
        struct drm_plane *plane;
        struct intel_plane *intel_plane;
        int ret = 0;
 
-       if (!dev_priv)
-               return -EINVAL;
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
 
        /* Make sure we don't try to enable both src & dest simultaneously */
        if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
@@ -582,14 +591,13 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
                              struct drm_file *file_priv)
 {
        struct drm_intel_sprite_colorkey *get = data;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_mode_object *obj;
        struct drm_plane *plane;
        struct intel_plane *intel_plane;
        int ret = 0;
 
-       if (!dev_priv)
-               return -EINVAL;
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -ENODEV;
 
        mutex_lock(&dev->mode_config.mutex);
 
@@ -614,6 +622,14 @@ static const struct drm_plane_funcs intel_plane_funcs = {
        .destroy = intel_destroy_plane,
 };
 
+static uint32_t ilk_plane_formats[] = {
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_YUYV,
+       DRM_FORMAT_YVYU,
+       DRM_FORMAT_UYVY,
+       DRM_FORMAT_VYUY,
+};
+
 static uint32_t snb_plane_formats[] = {
        DRM_FORMAT_XBGR8888,
        DRM_FORMAT_XRGB8888,
@@ -628,34 +644,56 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe)
 {
        struct intel_plane *intel_plane;
        unsigned long possible_crtcs;
+       const uint32_t *plane_formats;
+       int num_plane_formats;
        int ret;
 
-       if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+       if (INTEL_INFO(dev)->gen < 5)
                return -ENODEV;
 
        intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
        if (!intel_plane)
                return -ENOMEM;
 
-       if (IS_GEN6(dev)) {
+       switch (INTEL_INFO(dev)->gen) {
+       case 5:
+       case 6:
                intel_plane->max_downscale = 16;
-               intel_plane->update_plane = snb_update_plane;
-               intel_plane->disable_plane = snb_disable_plane;
-               intel_plane->update_colorkey = snb_update_colorkey;
-               intel_plane->get_colorkey = snb_get_colorkey;
-       } else if (IS_GEN7(dev)) {
+               intel_plane->update_plane = ilk_update_plane;
+               intel_plane->disable_plane = ilk_disable_plane;
+               intel_plane->update_colorkey = ilk_update_colorkey;
+               intel_plane->get_colorkey = ilk_get_colorkey;
+
+               if (IS_GEN6(dev)) {
+                       plane_formats = snb_plane_formats;
+                       num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+               } else {
+                       plane_formats = ilk_plane_formats;
+                       num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
+               }
+               break;
+
+       case 7:
                intel_plane->max_downscale = 2;
                intel_plane->update_plane = ivb_update_plane;
                intel_plane->disable_plane = ivb_disable_plane;
                intel_plane->update_colorkey = ivb_update_colorkey;
                intel_plane->get_colorkey = ivb_get_colorkey;
+
+               plane_formats = snb_plane_formats;
+               num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+               break;
+
+       default:
+               return -ENODEV;
        }
 
        intel_plane->pipe = pipe;
        possible_crtcs = (1 << pipe);
        ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
-                            &intel_plane_funcs, snb_plane_formats,
-                            ARRAY_SIZE(snb_plane_formats), false);
+                            &intel_plane_funcs,
+                            plane_formats, num_plane_formats,
+                            false);
        if (ret)
                kfree(intel_plane);
 
index 05f765ef546450efcc56844ff29e589c4c23d028..3346612d2953eff35c3e9025b044d33e75e28206 100644 (file)
@@ -811,7 +811,7 @@ intel_tv_mode_lookup(const char *tv_format)
 {
        int i;
 
-       for (i = 0; i < sizeof(tv_modes) / sizeof(tv_modes[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
                const struct tv_mode *tv_mode = &tv_modes[i];
 
                if (!strcmp(tv_format, tv_mode->name))
@@ -1153,6 +1153,15 @@ intel_tv_detect_type(struct intel_tv *intel_tv,
                   DAC_B_0_7_V |
                   DAC_C_0_7_V);
 
+
+       /*
+        * The TV sense state should be cleared to zero on cantiga platform. Otherwise
+        * the TV is misdetected. This is hardware requirement.
+        */
+       if (IS_GM45(dev))
+               tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
+                           TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
+
        I915_WRITE(TV_CTL, tv_ctl);
        I915_WRITE(TV_DAC, tv_dac);
        POSTING_READ(TV_DAC);
@@ -1240,11 +1249,8 @@ intel_tv_detect(struct drm_connector *connector, bool force)
        int type;
 
        mode = reported_modes[0];
-       drm_mode_set_crtcinfo(&mode, 0);
 
-       if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) {
-               type = intel_tv_detect_type(intel_tv, connector);
-       } else if (force) {
+       if (force) {
                struct intel_load_detect_pipe tmp;
 
                if (intel_get_load_detect_pipe(&intel_tv->base, connector,
index ca1639918f57976b852bdcaab751d18402a882ad..97a81260485a15fb360a4fa6dfc37ac910fca303 100644 (file)
@@ -13,6 +13,7 @@ config DRM_NOUVEAU
        select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT
        select ACPI_WMI if ACPI
        select MXM_WMI if ACPI
+       select POWER_SUPPLY
        help
          Choose this option for open-source nVidia support.
 
index 7814a760c16439e8d6a0c74da474b4a978ce9793..284bd25d5d2127a3d44f9d8efae7449b77edcfbd 100644 (file)
@@ -270,7 +270,7 @@ static bool nouveau_dsm_detect(void)
        struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
        struct pci_dev *pdev = NULL;
        int has_dsm = 0;
-       int has_optimus;
+       int has_optimus = 0;
        int vga_count = 0;
        bool guid_valid;
        int retval;
index 637afe71de5645108110fc73b37a0ba9b2a4255b..0be4a815e706cadd4e2bd4b0734f640c807f86ec 100644 (file)
@@ -177,14 +177,15 @@ bios_shadow_pci(struct nvbios *bios)
 
        if (!pci_enable_rom(pdev)) {
                void __iomem *rom = pci_map_rom(pdev, &length);
-               if (rom) {
+               if (rom && length) {
                        bios->data = kmalloc(length, GFP_KERNEL);
                        if (bios->data) {
                                memcpy_fromio(bios->data, rom, length);
                                bios->length = length;
                        }
-                       pci_unmap_rom(pdev, rom);
                }
+               if (rom)
+                       pci_unmap_rom(pdev, rom);
 
                pci_disable_rom(pdev);
        }
@@ -6155,10 +6156,14 @@ dcb_fake_connectors(struct nvbios *bios)
 
        /* heuristic: if we ever get a non-zero connector field, assume
         * that all the indices are valid and we don't need fake them.
+        *
+        * and, as usual, a blacklist of boards with bad bios data..
         */
-       for (i = 0; i < dcbt->entries; i++) {
-               if (dcbt->entry[i].connector)
-                       return;
+       if (!nv_match_device(bios->dev, 0x0392, 0x107d, 0x20a2)) {
+               for (i = 0; i < dcbt->entries; i++) {
+                       if (dcbt->entry[i].connector)
+                               return;
+               }
        }
 
        /* no useful connector info available, we need to make it up
index 44e6416d4a336054409a24e05bfe20c66c4c7d1a..846afb0bfef4b5dff1ce87f06f6bd985a8fc1650 100644 (file)
@@ -436,11 +436,11 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
        }
 
        if (dev_priv->card_type < NV_C0) {
-               init->subchan[0].handle = NvSw;
-               init->subchan[0].grclass = NV_SW;
-               init->nr_subchan = 1;
-       } else {
-               init->nr_subchan = 0;
+               init->subchan[0].handle = 0x00000000;
+               init->subchan[0].grclass = 0x0000;
+               init->subchan[1].handle = NvSw;
+               init->subchan[1].grclass = NV_SW;
+               init->nr_subchan = 2;
        }
 
        /* Named memory object area */
index bcf0fd9e313eb6fdc2db1e158cdecfb77cf1310d..23d4edf992b7d20440eb53ce8273231ccfe487e1 100644 (file)
@@ -48,8 +48,8 @@ void nv50_dma_push(struct nouveau_channel *, struct nouveau_bo *,
 
 /* Hardcoded object assignments to subchannels (subchannel id). */
 enum {
-       NvSubSw         = 0,
-       NvSubM2MF       = 1,
+       NvSubM2MF       = 0,
+       NvSubSw         = 1,
        NvSub2D         = 2,
        NvSubCtxSurf2D  = 2,
        NvSubGdiRect    = 3,
index 59ea1c14eca0363b7f132abc4c86242e68b82e0f..c3de36384522f9668a99e6aa26fb2da39dc01dd8 100644 (file)
@@ -32,7 +32,9 @@ static bool
 hdmi_sor(struct drm_encoder *encoder)
 {
        struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
-       if (dev_priv->chipset < 0xa3)
+       if (dev_priv->chipset <  0xa3 ||
+           dev_priv->chipset == 0xaa ||
+           dev_priv->chipset == 0xac)
                return false;
        return true;
 }
index 34d591b7d4efe91d1221d0ae11131157efcdcca9..da3e7c3abab7090a3770413c02bd0cbbaa6134a3 100644 (file)
@@ -235,6 +235,7 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile)
                return -EPERM;
 
        strncpy(string, profile, sizeof(string));
+       string[sizeof(string) - 1] = 0;
        if ((ptr = strchr(string, '\n')))
                *ptr = '\0';
 
index a4886b36d0faf771d6abc7d8aaa0983aca465850..298c09b755697f791c530fc541d559ad0465ca69 100644 (file)
@@ -642,7 +642,7 @@ nouveau_card_channel_init(struct drm_device *dev)
                OUT_RING  (chan, chan->vram_handle);
                OUT_RING  (chan, chan->gart_handle);
        } else
-       if (dev_priv->card_type <= NV_C0) {
+       if (dev_priv->card_type <= NV_D0) {
                ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039);
                if (ret)
                        goto error;
@@ -662,6 +662,12 @@ error:
        return ret;
 }
 
+static const struct vga_switcheroo_client_ops nouveau_switcheroo_ops = {
+       .set_gpu_state = nouveau_switcheroo_set_state,
+       .reprobe = nouveau_switcheroo_reprobe,
+       .can_switch = nouveau_switcheroo_can_switch,
+};
+
 int
 nouveau_card_init(struct drm_device *dev)
 {
@@ -670,9 +676,7 @@ nouveau_card_init(struct drm_device *dev)
        int ret, e = 0;
 
        vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
-       vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
-                                      nouveau_switcheroo_reprobe,
-                                      nouveau_switcheroo_can_switch);
+       vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops);
 
        /* Initialise internal driver API hooks */
        ret = nouveau_init_engine_ptrs(dev);
index 550ad3fcf0afa691153f293f7e36f64e181105f7..9d79180069df2cdb93b6e8b7ea45cb0508fed38c 100644 (file)
@@ -65,7 +65,7 @@ nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out)
        if (line < 10) {
                line = (line - 2) * 4;
                reg  = NV_PCRTC_GPIO_EXT;
-               mask = 0x00000003 << ((line - 2) * 4);
+               mask = 0x00000003;
                data = (dir << 1) | out;
        } else
        if (line < 14) {
index a7844ab6a50cd5603b351eb026a62e763cb6a554..27464021247583a87fd5dfc1c6c79441da9e703c 100644 (file)
@@ -42,7 +42,7 @@ nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */
        static const u8 nv50[] = { 16, 8, 0, 24 };
-       if (dev_priv->card_type == 0xaf)
+       if (dev_priv->chipset == 0xaf)
                return nvaf[lane];
        return nv50[lane];
 }
index 5bf55038fd9238a4ec582f0d72b505dc3b804bd2..f704e942372e75b291cc505536a197c4c464a537 100644 (file)
@@ -54,6 +54,11 @@ nvc0_mfb_isr(struct drm_device *dev)
                        nvc0_mfb_subp_isr(dev, unit, subp);
                units &= ~(1 << unit);
        }
+
+       /* we do something horribly wrong and upset PMFB a lot, so mask off
+        * interrupts from it after the first one until it's fixed
+        */
+       nv_mask(dev, 0x000640, 0x02000000, 0x00000000);
 }
 
 static void
index d1bd239cd9e9eef5f88ef06e4964f158a7490986..5ce9bf51a8de680c1658e0dd26491e16f8f77511 100644 (file)
@@ -1306,8 +1306,11 @@ struct atom_context *atom_parse(struct card_info *card, void *bios)
 
 int atom_asic_init(struct atom_context *ctx)
 {
+       struct radeon_device *rdev = ctx->card->dev->dev_private;
        int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
        uint32_t ps[16];
+       int ret;
+
        memset(ps, 0, 64);
 
        ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR));
@@ -1317,7 +1320,17 @@ int atom_asic_init(struct atom_context *ctx)
 
        if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
                return 1;
-       return atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+       ret = atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+       if (ret)
+               return ret;
+
+       memset(ps, 0, 64);
+
+       if (rdev->family < CHIP_R600) {
+               if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL))
+                       atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL, ps);
+       }
+       return ret;
 }
 
 void atom_destroy(struct atom_context *ctx)
index 93cfe2086ba023b82b4271b136730a2d3a4cd25d..25fea631dad2d2ae03bee413b7d9254045a5f9d3 100644 (file)
@@ -44,6 +44,7 @@
 #define ATOM_CMD_SETSCLK       0x0A
 #define ATOM_CMD_SETMCLK       0x0B
 #define ATOM_CMD_SETPCLK       0x0C
+#define ATOM_CMD_SPDFANCNTL    0x39
 
 #define ATOM_DATA_FWI_PTR      0xC
 #define ATOM_DATA_IIO_PTR      0x32
index b5ff1f7b6f7ee4f3917d6d83e137ec02998a6d78..01d77d1554f4258899da5e14eb0044e3d529cc02 100644 (file)
@@ -575,6 +575,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
 
                if (rdev->family < CHIP_RV770)
                        pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
+               /* use frac fb div on APUs */
+               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
+                       pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
        } else {
                pll->flags |= RADEON_PLL_LEGACY;
 
@@ -588,8 +591,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                if (encoder->crtc == crtc) {
                        radeon_encoder = to_radeon_encoder(encoder);
                        connector = radeon_get_connector_for_encoder(encoder);
-                       /* if (connector && connector->display_info.bpc)
-                               bpc = connector->display_info.bpc; */
+                       bpc = radeon_get_monitor_bpc(connector);
                        encoder_mode = atombios_get_encoder_mode(encoder);
                        is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
                        if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
@@ -955,8 +957,8 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                break;
        }
 
-       if (radeon_encoder->active_device &
-           (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) {
+       if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
+           (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
                struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
                struct drm_connector *connector =
                        radeon_get_connector_for_encoder(encoder);
@@ -965,9 +967,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                struct radeon_connector_atom_dig *dig_connector =
                        radeon_connector->con_priv;
                int dp_clock;
-
-               /* if (connector->display_info.bpc)
-                       bpc = connector->display_info.bpc; */
+               bpc = radeon_get_monitor_bpc(connector);
 
                switch (encoder_mode) {
                case ATOM_ENCODER_MODE_DP_MST:
index c57d85664e77991e6af217de06ea7c6493e9a6e6..cadbb107c80377b1804613375d1269c2d89bb770 100644 (file)
@@ -405,13 +405,10 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
 /* get bpc from the EDID */
 static int convert_bpc_to_bpp(int bpc)
 {
-#if 0
        if (bpc == 0)
                return 24;
        else
                return bpc * 3;
-#endif
-       return 24;
 }
 
 /* get the max pix clock supported by the link rate and lane num */
@@ -463,7 +460,7 @@ static int radeon_dp_get_dp_lane_number(struct drm_connector *connector,
                                        u8 dpcd[DP_DPCD_SIZE],
                                        int pix_clock)
 {
-       int bpp = convert_bpc_to_bpp(connector->display_info.bpc);
+       int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
        int max_link_rate = dp_get_max_link_rate(dpcd);
        int max_lane_num = dp_get_max_lane_number(dpcd);
        int lane_num;
@@ -482,7 +479,7 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
                                       u8 dpcd[DP_DPCD_SIZE],
                                       int pix_clock)
 {
-       int bpp = convert_bpc_to_bpp(connector->display_info.bpc);
+       int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
        int lane_num, max_pix_clock;
 
        if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
index e607c4d7dd98bbccd9a709ab908b0c2c5b26a4b9..b92a694caa0d8f6efdd3cb233411bf5fff9ae11e 100644 (file)
@@ -230,6 +230,10 @@ atombios_dvo_setup(struct drm_encoder *encoder, int action)
        if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
                return;
 
+       /* some R4xx chips have the wrong frev */
+       if (rdev->family <= CHIP_RV410)
+               frev = 1;
+
        switch (frev) {
        case 1:
                switch (crev) {
@@ -541,7 +545,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
                dp_clock = dig_connector->dp_clock;
                dp_lane_count = dig_connector->dp_lane_count;
                hpd_id = radeon_connector->hpd.hpd;
-               /* bpc = connector->display_info.bpc; */
+               bpc = radeon_get_monitor_bpc(connector);
        }
 
        /* no dig encoder assigned */
@@ -1159,7 +1163,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
                dp_lane_count = dig_connector->dp_lane_count;
                connector_object_id =
                        (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-               /* bpc = connector->display_info.bpc; */
+               bpc = radeon_get_monitor_bpc(connector);
        }
 
        memset(&args, 0, sizeof(args));
index cfa372cb1cb379a069179c65632e3b35cd4039f1..7e7ac3d6e76e072a67fe0c6900f459e2a748e67d 100644 (file)
@@ -2424,27 +2424,18 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin
        u32 srbm_status;
        u32 grbm_status;
        u32 grbm_status_se0, grbm_status_se1;
-       struct r100_gpu_lockup *lockup = &rdev->config.evergreen.lockup;
-       int r;
 
        srbm_status = RREG32(SRBM_STATUS);
        grbm_status = RREG32(GRBM_STATUS);
        grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
        grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
        if (!(grbm_status & GUI_ACTIVE)) {
-               r100_gpu_lockup_update(lockup, ring);
+               radeon_ring_lockup_update(ring);
                return false;
        }
        /* force CP activities */
-       r = radeon_ring_lock(rdev, ring, 2);
-       if (!r) {
-               /* PACKET2 NOP */
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_unlock_commit(rdev, ring);
-       }
-       ring->rptr = RREG32(CP_RB_RPTR);
-       return r100_gpu_cp_is_lockup(rdev, lockup, ring);
+       radeon_ring_force_activity(rdev, ring);
+       return radeon_ring_test_lockup(rdev, ring);
 }
 
 static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
@@ -2594,6 +2585,7 @@ int evergreen_irq_set(struct radeon_device *rdev)
        u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;
        u32 grbm_int_cntl = 0;
        u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0;
+       u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0;
 
        if (!rdev->irq.installed) {
                WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@@ -2614,6 +2606,13 @@ int evergreen_irq_set(struct radeon_device *rdev)
        hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
        hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
 
+       afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
+       afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
+       afmt3 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
+       afmt4 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
+       afmt5 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
+       afmt6 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
+
        if (rdev->family >= CHIP_CAYMAN) {
                /* enable CP interrupts on all rings */
                if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) {
@@ -2690,6 +2689,30 @@ int evergreen_irq_set(struct radeon_device *rdev)
                DRM_DEBUG("evergreen_irq_set: hpd 6\n");
                hpd6 |= DC_HPDx_INT_EN;
        }
+       if (rdev->irq.afmt[0]) {
+               DRM_DEBUG("evergreen_irq_set: hdmi 0\n");
+               afmt1 |= AFMT_AZ_FORMAT_WTRIG_MASK;
+       }
+       if (rdev->irq.afmt[1]) {
+               DRM_DEBUG("evergreen_irq_set: hdmi 1\n");
+               afmt2 |= AFMT_AZ_FORMAT_WTRIG_MASK;
+       }
+       if (rdev->irq.afmt[2]) {
+               DRM_DEBUG("evergreen_irq_set: hdmi 2\n");
+               afmt3 |= AFMT_AZ_FORMAT_WTRIG_MASK;
+       }
+       if (rdev->irq.afmt[3]) {
+               DRM_DEBUG("evergreen_irq_set: hdmi 3\n");
+               afmt4 |= AFMT_AZ_FORMAT_WTRIG_MASK;
+       }
+       if (rdev->irq.afmt[4]) {
+               DRM_DEBUG("evergreen_irq_set: hdmi 4\n");
+               afmt5 |= AFMT_AZ_FORMAT_WTRIG_MASK;
+       }
+       if (rdev->irq.afmt[5]) {
+               DRM_DEBUG("evergreen_irq_set: hdmi 5\n");
+               afmt6 |= AFMT_AZ_FORMAT_WTRIG_MASK;
+       }
        if (rdev->irq.gui_idle) {
                DRM_DEBUG("gui idle\n");
                grbm_int_cntl |= GUI_IDLE_INT_ENABLE;
@@ -2732,6 +2755,13 @@ int evergreen_irq_set(struct radeon_device *rdev)
        WREG32(DC_HPD5_INT_CONTROL, hpd5);
        WREG32(DC_HPD6_INT_CONTROL, hpd6);
 
+       WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1);
+       WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2);
+       WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, afmt3);
+       WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, afmt4);
+       WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5);
+       WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6);
+
        return 0;
 }
 
@@ -2756,6 +2786,13 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
                rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
        }
 
+       rdev->irq.stat_regs.evergreen.afmt_status1 = RREG32(AFMT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.afmt_status2 = RREG32(AFMT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.afmt_status3 = RREG32(AFMT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.afmt_status4 = RREG32(AFMT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
+       rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
+
        if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
                WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
        if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
@@ -2829,6 +2866,36 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
        }
+       if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) {
+               tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
+               tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
+               WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) {
+               tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
+               tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
+               WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) {
+               tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
+               tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
+               WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) {
+               tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
+               tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
+               WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) {
+               tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
+               tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
+               WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, tmp);
+       }
+       if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) {
+               tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+               tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
+               WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, tmp);
+       }
 }
 
 void evergreen_irq_disable(struct radeon_device *rdev)
@@ -2878,6 +2945,7 @@ int evergreen_irq_process(struct radeon_device *rdev)
        u32 ring_index;
        unsigned long flags;
        bool queue_hotplug = false;
+       bool queue_hdmi = false;
 
        if (!rdev->ih.enabled || rdev->shutdown)
                return IRQ_NONE;
@@ -3111,6 +3179,55 @@ restart_ih:
                                break;
                        }
                        break;
+               case 44: /* hdmi */
+                       switch (src_data) {
+                       case 0:
+                               if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) {
+                                       rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG;
+                                       queue_hdmi = true;
+                                       DRM_DEBUG("IH: HDMI0\n");
+                               }
+                               break;
+                       case 1:
+                               if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) {
+                                       rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG;
+                                       queue_hdmi = true;
+                                       DRM_DEBUG("IH: HDMI1\n");
+                               }
+                               break;
+                       case 2:
+                               if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) {
+                                       rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG;
+                                       queue_hdmi = true;
+                                       DRM_DEBUG("IH: HDMI2\n");
+                               }
+                               break;
+                       case 3:
+                               if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) {
+                                       rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG;
+                                       queue_hdmi = true;
+                                       DRM_DEBUG("IH: HDMI3\n");
+                               }
+                               break;
+                       case 4:
+                               if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) {
+                                       rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG;
+                                       queue_hdmi = true;
+                                       DRM_DEBUG("IH: HDMI4\n");
+                               }
+                               break;
+                       case 5:
+                               if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) {
+                                       rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG;
+                                       queue_hdmi = true;
+                                       DRM_DEBUG("IH: HDMI5\n");
+                               }
+                               break;
+                       default:
+                               DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
+                               break;
+                       }
+                       break;
                case 176: /* CP_INT in ring buffer */
                case 177: /* CP_INT in IB1 */
                case 178: /* CP_INT in IB2 */
@@ -3154,6 +3271,8 @@ restart_ih:
                goto restart_ih;
        if (queue_hotplug)
                schedule_work(&rdev->hotplug_work);
+       if (queue_hdmi)
+               schedule_work(&rdev->audio_work);
        rdev->ih.rptr = rptr;
        WREG32(IH_RB_RPTR, rdev->ih.rptr);
        spin_unlock_irqrestore(&rdev->ih.lock, flags);
@@ -3248,12 +3367,9 @@ static int evergreen_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        r = r600_audio_init(rdev);
        if (r) {
@@ -3434,7 +3550,6 @@ void evergreen_fini(struct radeon_device *rdev)
        evergreen_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
-       radeon_semaphore_driver_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_agp_fini(rdev);
        radeon_bo_fini(rdev);
index 222acd2d33df782ce5b29d42272df0514f011b0f..30f04800b38ba06abfce0a33fa23b97eb85343a8 100644 (file)
@@ -637,7 +637,6 @@ int evergreen_blit_init(struct radeon_device *rdev)
        if (rdev->r600_blit.shader_obj)
                goto done;
 
-       mutex_init(&rdev->r600_blit.mutex);
        rdev->r600_blit.state_offset = 0;
 
        if (rdev->family < CHIP_CAYMAN)
index 70089d32b80feb7a4777f80b63c7b5c9c0c5901a..4e7dd2b4843d94b0b88c778aca8fa08c7f089c61 100644 (file)
@@ -1057,7 +1057,7 @@ static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
        uint32_t header, h_idx, reg, wait_reg_mem_info;
        volatile uint32_t *ib;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
 
        /* parse the WAIT_REG_MEM */
        r = evergreen_cs_packet_parse(p, &wait_reg_mem, p->idx);
@@ -1215,7 +1215,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                if (!(evergreen_reg_safe_bm[i] & m))
                        return 0;
        }
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        switch (reg) {
        /* force following reg to 0 in an attempt to disable out buffer
         * which will need us to better understand how it works to perform
@@ -1896,7 +1896,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
        u32 idx_value;
 
        track = (struct evergreen_cs_track *)p->track;
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        idx = pkt->idx + 1;
        idx_value = radeon_get_ib_value(p, idx);
 
@@ -2610,8 +2610,8 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)
                }
        } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
 #if 0
-       for (r = 0; r < p->ib->length_dw; r++) {
-               printk(KERN_INFO "%05d  0x%08X\n", r, p->ib->ptr[r]);
+       for (r = 0; r < p->ib.length_dw; r++) {
+               printk(KERN_INFO "%05d  0x%08X\n", r, p->ib.ptr[r]);
                mdelay(1);
        }
 #endif
index 96c10b3991aade56f69ec9eef3258dc867670022..8beac1065025c17dd7d1ef33d916527c38737bf2 100644 (file)
 /* HDMI blocks at 0x7030, 0x7c30, 0x10830, 0x11430, 0x12030, 0x12c30 */
 #define EVERGREEN_HDMI_BASE                            0x7030
 
-#define EVERGREEN_HDMI_CONFIG_OFFSET                   0xf0
-
 #endif
index b4eefc355f16d1c0628e5007038a2af4e0a4f5f1..79130bfd1d6f058750b16a4c8f09eaf85ec992bf 100644 (file)
 #define        CP_SEM_INCOMPLETE_TIMER_CNTL                    0x85C8
 #define        CP_DEBUG                                        0xC1FC
 
+/* Audio clocks */
+#define DCCG_AUDIO_DTO_SOURCE             0x05ac
+#       define DCCG_AUDIO_DTO0_SOURCE_SEL(x) ((x) << 0) /* crtc0 - crtc5 */
+#       define DCCG_AUDIO_DTO_SEL         (1 << 4) /* 0=dto0 1=dto1 */
+
+#define DCCG_AUDIO_DTO0_PHASE             0x05b0
+#define DCCG_AUDIO_DTO0_MODULE            0x05b4
+#define DCCG_AUDIO_DTO0_LOAD              0x05b8
+#define DCCG_AUDIO_DTO0_CNTL              0x05bc
+
+#define DCCG_AUDIO_DTO1_PHASE             0x05c0
+#define DCCG_AUDIO_DTO1_MODULE            0x05c4
+#define DCCG_AUDIO_DTO1_LOAD              0x05c8
+#define DCCG_AUDIO_DTO1_CNTL              0x05cc
+
+/* DCE 4.0 AFMT */
+#define HDMI_CONTROL                         0x7030
+#       define HDMI_KEEPOUT_MODE             (1 << 0)
+#       define HDMI_PACKET_GEN_VERSION       (1 << 4) /* 0 = r6xx compat */
+#       define HDMI_ERROR_ACK                (1 << 8)
+#       define HDMI_ERROR_MASK               (1 << 9)
+#       define HDMI_DEEP_COLOR_ENABLE        (1 << 24)
+#       define HDMI_DEEP_COLOR_DEPTH         (((x) & 3) << 28)
+#       define HDMI_24BIT_DEEP_COLOR         0
+#       define HDMI_30BIT_DEEP_COLOR         1
+#       define HDMI_36BIT_DEEP_COLOR         2
+#define HDMI_STATUS                          0x7034
+#       define HDMI_ACTIVE_AVMUTE            (1 << 0)
+#       define HDMI_AUDIO_PACKET_ERROR       (1 << 16)
+#       define HDMI_VBI_PACKET_ERROR         (1 << 20)
+#define HDMI_AUDIO_PACKET_CONTROL            0x7038
+#       define HDMI_AUDIO_DELAY_EN(x)        (((x) & 3) << 4)
+#       define HDMI_AUDIO_PACKETS_PER_LINE(x)  (((x) & 0x1f) << 16)
+#define HDMI_ACR_PACKET_CONTROL              0x703c
+#       define HDMI_ACR_SEND                 (1 << 0)
+#       define HDMI_ACR_CONT                 (1 << 1)
+#       define HDMI_ACR_SELECT(x)            (((x) & 3) << 4)
+#       define HDMI_ACR_HW                   0
+#       define HDMI_ACR_32                   1
+#       define HDMI_ACR_44                   2
+#       define HDMI_ACR_48                   3
+#       define HDMI_ACR_SOURCE               (1 << 8) /* 0 - hw; 1 - cts value */
+#       define HDMI_ACR_AUTO_SEND            (1 << 12)
+#       define HDMI_ACR_N_MULTIPLE(x)        (((x) & 7) << 16)
+#       define HDMI_ACR_X1                   1
+#       define HDMI_ACR_X2                   2
+#       define HDMI_ACR_X4                   4
+#       define HDMI_ACR_AUDIO_PRIORITY       (1 << 31)
+#define HDMI_VBI_PACKET_CONTROL              0x7040
+#       define HDMI_NULL_SEND                (1 << 0)
+#       define HDMI_GC_SEND                  (1 << 4)
+#       define HDMI_GC_CONT                  (1 << 5) /* 0 - once; 1 - every frame */
+#define HDMI_INFOFRAME_CONTROL0              0x7044
+#       define HDMI_AVI_INFO_SEND            (1 << 0)
+#       define HDMI_AVI_INFO_CONT            (1 << 1)
+#       define HDMI_AUDIO_INFO_SEND          (1 << 4)
+#       define HDMI_AUDIO_INFO_CONT          (1 << 5)
+#       define HDMI_MPEG_INFO_SEND           (1 << 8)
+#       define HDMI_MPEG_INFO_CONT           (1 << 9)
+#define HDMI_INFOFRAME_CONTROL1              0x7048
+#       define HDMI_AVI_INFO_LINE(x)         (((x) & 0x3f) << 0)
+#       define HDMI_AUDIO_INFO_LINE(x)       (((x) & 0x3f) << 8)
+#       define HDMI_MPEG_INFO_LINE(x)        (((x) & 0x3f) << 16)
+#define HDMI_GENERIC_PACKET_CONTROL          0x704c
+#       define HDMI_GENERIC0_SEND            (1 << 0)
+#       define HDMI_GENERIC0_CONT            (1 << 1)
+#       define HDMI_GENERIC1_SEND            (1 << 4)
+#       define HDMI_GENERIC1_CONT            (1 << 5)
+#       define HDMI_GENERIC0_LINE(x)         (((x) & 0x3f) << 16)
+#       define HDMI_GENERIC1_LINE(x)         (((x) & 0x3f) << 24)
+#define HDMI_GC                              0x7058
+#       define HDMI_GC_AVMUTE                (1 << 0)
+#       define HDMI_GC_AVMUTE_CONT           (1 << 2)
+#define AFMT_AUDIO_PACKET_CONTROL2           0x705c
+#       define AFMT_AUDIO_LAYOUT_OVRD        (1 << 0)
+#       define AFMT_AUDIO_LAYOUT_SELECT      (1 << 1)
+#       define AFMT_60958_CS_SOURCE          (1 << 4)
+#       define AFMT_AUDIO_CHANNEL_ENABLE(x)  (((x) & 0xff) << 8)
+#       define AFMT_DP_AUDIO_STREAM_ID(x)    (((x) & 0xff) << 16)
+#define AFMT_AVI_INFO0                       0x7084
+#       define AFMT_AVI_INFO_CHECKSUM(x)     (((x) & 0xff) << 0)
+#       define AFMT_AVI_INFO_S(x)            (((x) & 3) << 8)
+#       define AFMT_AVI_INFO_B(x)            (((x) & 3) << 10)
+#       define AFMT_AVI_INFO_A(x)            (((x) & 1) << 12)
+#       define AFMT_AVI_INFO_Y(x)            (((x) & 3) << 13)
+#       define AFMT_AVI_INFO_Y_RGB           0
+#       define AFMT_AVI_INFO_Y_YCBCR422      1
+#       define AFMT_AVI_INFO_Y_YCBCR444      2
+#       define AFMT_AVI_INFO_Y_A_B_S(x)      (((x) & 0xff) << 8)
+#       define AFMT_AVI_INFO_R(x)            (((x) & 0xf) << 16)
+#       define AFMT_AVI_INFO_M(x)            (((x) & 0x3) << 20)
+#       define AFMT_AVI_INFO_C(x)            (((x) & 0x3) << 22)
+#       define AFMT_AVI_INFO_C_M_R(x)        (((x) & 0xff) << 16)
+#       define AFMT_AVI_INFO_SC(x)           (((x) & 0x3) << 24)
+#       define AFMT_AVI_INFO_Q(x)            (((x) & 0x3) << 26)
+#       define AFMT_AVI_INFO_EC(x)           (((x) & 0x3) << 28)
+#       define AFMT_AVI_INFO_ITC(x)          (((x) & 0x1) << 31)
+#       define AFMT_AVI_INFO_ITC_EC_Q_SC(x)  (((x) & 0xff) << 24)
+#define AFMT_AVI_INFO1                       0x7088
+#       define AFMT_AVI_INFO_VIC(x)          (((x) & 0x7f) << 0) /* don't use avi infoframe v1 */
+#       define AFMT_AVI_INFO_PR(x)           (((x) & 0xf) << 8) /* don't use avi infoframe v1 */
+#       define AFMT_AVI_INFO_CN(x)           (((x) & 0x3) << 12)
+#       define AFMT_AVI_INFO_YQ(x)           (((x) & 0x3) << 14)
+#       define AFMT_AVI_INFO_TOP(x)          (((x) & 0xffff) << 16)
+#define AFMT_AVI_INFO2                       0x708c
+#       define AFMT_AVI_INFO_BOTTOM(x)       (((x) & 0xffff) << 0)
+#       define AFMT_AVI_INFO_LEFT(x)         (((x) & 0xffff) << 16)
+#define AFMT_AVI_INFO3                       0x7090
+#       define AFMT_AVI_INFO_RIGHT(x)        (((x) & 0xffff) << 0)
+#       define AFMT_AVI_INFO_VERSION(x)      (((x) & 3) << 24)
+#define AFMT_MPEG_INFO0                      0x7094
+#       define AFMT_MPEG_INFO_CHECKSUM(x)    (((x) & 0xff) << 0)
+#       define AFMT_MPEG_INFO_MB0(x)         (((x) & 0xff) << 8)
+#       define AFMT_MPEG_INFO_MB1(x)         (((x) & 0xff) << 16)
+#       define AFMT_MPEG_INFO_MB2(x)         (((x) & 0xff) << 24)
+#define AFMT_MPEG_INFO1                      0x7098
+#       define AFMT_MPEG_INFO_MB3(x)         (((x) & 0xff) << 0)
+#       define AFMT_MPEG_INFO_MF(x)          (((x) & 3) << 8)
+#       define AFMT_MPEG_INFO_FR(x)          (((x) & 1) << 12)
+#define AFMT_GENERIC0_HDR                    0x709c
+#define AFMT_GENERIC0_0                      0x70a0
+#define AFMT_GENERIC0_1                      0x70a4
+#define AFMT_GENERIC0_2                      0x70a8
+#define AFMT_GENERIC0_3                      0x70ac
+#define AFMT_GENERIC0_4                      0x70b0
+#define AFMT_GENERIC0_5                      0x70b4
+#define AFMT_GENERIC0_6                      0x70b8
+#define AFMT_GENERIC1_HDR                    0x70bc
+#define AFMT_GENERIC1_0                      0x70c0
+#define AFMT_GENERIC1_1                      0x70c4
+#define AFMT_GENERIC1_2                      0x70c8
+#define AFMT_GENERIC1_3                      0x70cc
+#define AFMT_GENERIC1_4                      0x70d0
+#define AFMT_GENERIC1_5                      0x70d4
+#define AFMT_GENERIC1_6                      0x70d8
+#define HDMI_ACR_32_0                        0x70dc
+#       define HDMI_ACR_CTS_32(x)            (((x) & 0xfffff) << 12)
+#define HDMI_ACR_32_1                        0x70e0
+#       define HDMI_ACR_N_32(x)              (((x) & 0xfffff) << 0)
+#define HDMI_ACR_44_0                        0x70e4
+#       define HDMI_ACR_CTS_44(x)            (((x) & 0xfffff) << 12)
+#define HDMI_ACR_44_1                        0x70e8
+#       define HDMI_ACR_N_44(x)              (((x) & 0xfffff) << 0)
+#define HDMI_ACR_48_0                        0x70ec
+#       define HDMI_ACR_CTS_48(x)            (((x) & 0xfffff) << 12)
+#define HDMI_ACR_48_1                        0x70f0
+#       define HDMI_ACR_N_48(x)              (((x) & 0xfffff) << 0)
+#define HDMI_ACR_STATUS_0                    0x70f4
+#define HDMI_ACR_STATUS_1                    0x70f8
+#define AFMT_AUDIO_INFO0                     0x70fc
+#       define AFMT_AUDIO_INFO_CHECKSUM(x)   (((x) & 0xff) << 0)
+#       define AFMT_AUDIO_INFO_CC(x)         (((x) & 7) << 8)
+#       define AFMT_AUDIO_INFO_CT(x)         (((x) & 0xf) << 11)
+#       define AFMT_AUDIO_INFO_CHECKSUM_OFFSET(x)   (((x) & 0xff) << 16)
+#       define AFMT_AUDIO_INFO_CXT(x)        (((x) & 0x1f) << 24)
+#define AFMT_AUDIO_INFO1                     0x7100
+#       define AFMT_AUDIO_INFO_CA(x)         (((x) & 0xff) << 0)
+#       define AFMT_AUDIO_INFO_LSV(x)        (((x) & 0xf) << 11)
+#       define AFMT_AUDIO_INFO_DM_INH(x)     (((x) & 1) << 15)
+#       define AFMT_AUDIO_INFO_DM_INH_LSV(x) (((x) & 0xff) << 8)
+#       define AFMT_AUDIO_INFO_LFEBPL(x)     (((x) & 3) << 16)
+#define AFMT_60958_0                         0x7104
+#       define AFMT_60958_CS_A(x)            (((x) & 1) << 0)
+#       define AFMT_60958_CS_B(x)            (((x) & 1) << 1)
+#       define AFMT_60958_CS_C(x)            (((x) & 1) << 2)
+#       define AFMT_60958_CS_D(x)            (((x) & 3) << 3)
+#       define AFMT_60958_CS_MODE(x)         (((x) & 3) << 6)
+#       define AFMT_60958_CS_CATEGORY_CODE(x)      (((x) & 0xff) << 8)
+#       define AFMT_60958_CS_SOURCE_NUMBER(x)      (((x) & 0xf) << 16)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_L(x)   (((x) & 0xf) << 20)
+#       define AFMT_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24)
+#       define AFMT_60958_CS_CLOCK_ACCURACY(x)     (((x) & 3) << 28)
+#define AFMT_60958_1                         0x7108
+#       define AFMT_60958_CS_WORD_LENGTH(x)  (((x) & 0xf) << 0)
+#       define AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY(x)   (((x) & 0xf) << 4)
+#       define AFMT_60958_CS_VALID_L(x)      (((x) & 1) << 16)
+#       define AFMT_60958_CS_VALID_R(x)      (((x) & 1) << 18)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_R(x)   (((x) & 0xf) << 20)
+#define AFMT_AUDIO_CRC_CONTROL               0x710c
+#       define AFMT_AUDIO_CRC_EN             (1 << 0)
+#define AFMT_RAMP_CONTROL0                   0x7110
+#       define AFMT_RAMP_MAX_COUNT(x)        (((x) & 0xffffff) << 0)
+#       define AFMT_RAMP_DATA_SIGN           (1 << 31)
+#define AFMT_RAMP_CONTROL1                   0x7114
+#       define AFMT_RAMP_MIN_COUNT(x)        (((x) & 0xffffff) << 0)
+#       define AFMT_AUDIO_TEST_CH_DISABLE(x) (((x) & 0xff) << 24)
+#define AFMT_RAMP_CONTROL2                   0x7118
+#       define AFMT_RAMP_INC_COUNT(x)        (((x) & 0xffffff) << 0)
+#define AFMT_RAMP_CONTROL3                   0x711c
+#       define AFMT_RAMP_DEC_COUNT(x)        (((x) & 0xffffff) << 0)
+#define AFMT_60958_2                         0x7120
+#       define AFMT_60958_CS_CHANNEL_NUMBER_2(x)   (((x) & 0xf) << 0)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_3(x)   (((x) & 0xf) << 4)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_4(x)   (((x) & 0xf) << 8)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_5(x)   (((x) & 0xf) << 12)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_6(x)   (((x) & 0xf) << 16)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_7(x)   (((x) & 0xf) << 20)
+#define AFMT_STATUS                          0x7128
+#       define AFMT_AUDIO_ENABLE             (1 << 4)
+#       define AFMT_AUDIO_HBR_ENABLE         (1 << 8)
+#       define AFMT_AZ_FORMAT_WTRIG          (1 << 28)
+#       define AFMT_AZ_FORMAT_WTRIG_INT      (1 << 29)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG      (1 << 30)
+#define AFMT_AUDIO_PACKET_CONTROL            0x712c
+#       define AFMT_AUDIO_SAMPLE_SEND        (1 << 0)
+#       define AFMT_RESET_FIFO_WHEN_AUDIO_DIS (1 << 11) /* set to 1 */
+#       define AFMT_AUDIO_TEST_EN            (1 << 12)
+#       define AFMT_AUDIO_CHANNEL_SWAP       (1 << 24)
+#       define AFMT_60958_CS_UPDATE          (1 << 26)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG_MASK (1 << 27)
+#       define AFMT_AZ_FORMAT_WTRIG_MASK     (1 << 28)
+#       define AFMT_AZ_FORMAT_WTRIG_ACK      (1 << 29)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG_ACK  (1 << 30)
+#define AFMT_VBI_PACKET_CONTROL              0x7130
+#       define AFMT_GENERIC0_UPDATE          (1 << 2)
+#define AFMT_INFOFRAME_CONTROL0              0x7134
+#       define AFMT_AUDIO_INFO_SOURCE        (1 << 6) /* 0 - sound block; 1 - afmt regs */
+#       define AFMT_AUDIO_INFO_UPDATE        (1 << 7)
+#       define AFMT_MPEG_INFO_UPDATE         (1 << 10)
+#define AFMT_GENERIC0_7                      0x7138
 
 #define        GC_USER_SHADER_PIPE_CONFIG                      0x8954
 #define                INACTIVE_QD_PIPES(x)                            ((x) << 8)
index a48ca53fcd6ab80b270fe6a4f766f6b88a5a3605..107b2177e6c5a44bcbc390f989c98e1565d7aecc 100644 (file)
@@ -1392,35 +1392,6 @@ int cayman_cp_resume(struct radeon_device *rdev)
        return 0;
 }
 
-bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-       u32 srbm_status;
-       u32 grbm_status;
-       u32 grbm_status_se0, grbm_status_se1;
-       struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup;
-       int r;
-
-       srbm_status = RREG32(SRBM_STATUS);
-       grbm_status = RREG32(GRBM_STATUS);
-       grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
-       grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
-       if (!(grbm_status & GUI_ACTIVE)) {
-               r100_gpu_lockup_update(lockup, ring);
-               return false;
-       }
-       /* force CP activities */
-       r = radeon_ring_lock(rdev, ring, 2);
-       if (!r) {
-               /* PACKET2 NOP */
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_unlock_commit(rdev, ring);
-       }
-       /* XXX deal with CP0,1,2 */
-       ring->rptr = RREG32(ring->rptr_reg);
-       return r100_gpu_cp_is_lockup(rdev, lockup, ring);
-}
-
 static int cayman_gpu_soft_reset(struct radeon_device *rdev)
 {
        struct evergreen_mc_save save;
@@ -1601,12 +1572,9 @@ static int cayman_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        r = radeon_vm_manager_start(rdev);
        if (r)
@@ -1776,7 +1744,6 @@ void cayman_fini(struct radeon_device *rdev)
        cayman_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
-       radeon_semaphore_driver_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);
        radeon_atombios_fini(rdev);
index 81801c176aa5c8b4cc45644df5c5a7a471128cd3..0874a6dd411fe4c01ebdb28adf00bf40bd372fd8 100644 (file)
@@ -139,9 +139,9 @@ int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
                }
 
                tmp |= tile_flags;
-               p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
+               p->ib.ptr[idx] = (value & 0x3fc00000) | tmp;
        } else
-               p->ib->ptr[idx] = (value & 0xffc00000) | tmp;
+               p->ib.ptr[idx] = (value & 0xffc00000) | tmp;
        return 0;
 }
 
@@ -156,7 +156,7 @@ int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
        volatile uint32_t *ib;
        u32 idx_value;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        track = (struct r100_cs_track *)p->track;
        c = radeon_get_ib_value(p, idx++) & 0x1F;
        if (c > 16) {
@@ -660,7 +660,7 @@ int r100_pci_gart_enable(struct radeon_device *rdev)
        tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
        WREG32(RADEON_AIC_CNTL, tmp);
        r100_pci_gart_tlb_flush(rdev);
-       DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
+       DRM_INFO("PCI GART of %uM enabled (table at 0x%016llX).\n",
                 (unsigned)(rdev->mc.gtt_size >> 20),
                 (unsigned long long)rdev->gart.table_addr);
        rdev->gart.ready = true;
@@ -1180,6 +1180,10 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
        WREG32(RADEON_CP_RB_WPTR_DELAY, 0);
        WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D);
        WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM);
+
+       /* at this point everything should be setup correctly to enable master */
+       pci_set_master(rdev->pdev);
+
        radeon_ring_start(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
        r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring);
        if (r) {
@@ -1271,7 +1275,7 @@ void r100_cs_dump_packet(struct radeon_cs_parser *p,
        unsigned i;
        unsigned idx;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        idx = pkt->idx;
        for (i = 0; i <= (pkt->count + 1); i++, idx++) {
                DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]);
@@ -1350,7 +1354,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
        uint32_t header, h_idx, reg;
        volatile uint32_t *ib;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
 
        /* parse the wait until */
        r = r100_cs_packet_parse(p, &waitreloc, p->idx);
@@ -1529,7 +1533,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
        u32 tile_flags = 0;
        u32 idx_value;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        track = (struct r100_cs_track *)p->track;
 
        idx_value = radeon_get_ib_value(p, idx);
@@ -1885,7 +1889,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
        volatile uint32_t *ib;
        int r;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        idx = pkt->idx + 1;
        track = (struct r100_cs_track *)p->track;
        switch (pkt->opcode) {
@@ -2155,79 +2159,18 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev)
        return -1;
 }
 
-void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_ring *ring)
-{
-       lockup->last_cp_rptr = ring->rptr;
-       lockup->last_jiffies = jiffies;
-}
-
-/**
- * r100_gpu_cp_is_lockup() - check if CP is lockup by recording information
- * @rdev:      radeon device structure
- * @lockup:    r100_gpu_lockup structure holding CP lockup tracking informations
- * @cp:                radeon_cp structure holding CP information
- *
- * We don't need to initialize the lockup tracking information as we will either
- * have CP rptr to a different value of jiffies wrap around which will force
- * initialization of the lockup tracking informations.
- *
- * A possible false positivie is if we get call after while and last_cp_rptr ==
- * the current CP rptr, even if it's unlikely it might happen. To avoid this
- * if the elapsed time since last call is bigger than 2 second than we return
- * false and update the tracking information. Due to this the caller must call
- * r100_gpu_cp_is_lockup several time in less than 2sec for lockup to be reported
- * the fencing code should be cautious about that.
- *
- * Caller should write to the ring to force CP to do something so we don't get
- * false positive when CP is just gived nothing to do.
- *
- **/
-bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *lockup, struct radeon_ring *ring)
-{
-       unsigned long cjiffies, elapsed;
-
-       cjiffies = jiffies;
-       if (!time_after(cjiffies, lockup->last_jiffies)) {
-               /* likely a wrap around */
-               lockup->last_cp_rptr = ring->rptr;
-               lockup->last_jiffies = jiffies;
-               return false;
-       }
-       if (ring->rptr != lockup->last_cp_rptr) {
-               /* CP is still working no lockup */
-               lockup->last_cp_rptr = ring->rptr;
-               lockup->last_jiffies = jiffies;
-               return false;
-       }
-       elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies);
-       if (elapsed >= 10000) {
-               dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed);
-               return true;
-       }
-       /* give a chance to the GPU ... */
-       return false;
-}
-
 bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
 {
        u32 rbbm_status;
-       int r;
 
        rbbm_status = RREG32(R_000E40_RBBM_STATUS);
        if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
-               r100_gpu_lockup_update(&rdev->config.r100.lockup, ring);
+               radeon_ring_lockup_update(ring);
                return false;
        }
        /* force CP activities */
-       r = radeon_ring_lock(rdev, ring, 2);
-       if (!r) {
-               /* PACKET2 NOP */
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_unlock_commit(rdev, ring);
-       }
-       ring->rptr = RREG32(ring->rptr_reg);
-       return r100_gpu_cp_is_lockup(rdev, &rdev->config.r100.lockup, ring);
+       radeon_ring_force_activity(rdev, ring);
+       return radeon_ring_test_lockup(rdev, ring);
 }
 
 void r100_bm_disable(struct radeon_device *rdev)
@@ -2296,7 +2239,6 @@ int r100_asic_reset(struct radeon_device *rdev)
        if (G_000E40_SE_BUSY(status) || G_000E40_RE_BUSY(status) ||
                G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) {
                dev_err(rdev->dev, "failed to reset GPU\n");
-               rdev->gpu_lockup = true;
                ret = -1;
        } else
                dev_info(rdev->dev, "GPU reset succeed\n");
@@ -2553,7 +2495,7 @@ static void r100_pll_errata_after_data(struct radeon_device *rdev)
         * or the chip could hang on a subsequent access
         */
        if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) {
-               udelay(5000);
+               mdelay(5);
        }
 
        /* This function is required to workaround a hardware bug in some (all?)
@@ -3742,7 +3684,7 @@ void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 
 int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
 {
-       struct radeon_ib *ib;
+       struct radeon_ib ib;
        uint32_t scratch;
        uint32_t tmp = 0;
        unsigned i;
@@ -3758,22 +3700,22 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
        if (r) {
                return r;
        }
-       ib->ptr[0] = PACKET0(scratch, 0);
-       ib->ptr[1] = 0xDEADBEEF;
-       ib->ptr[2] = PACKET2(0);
-       ib->ptr[3] = PACKET2(0);
-       ib->ptr[4] = PACKET2(0);
-       ib->ptr[5] = PACKET2(0);
-       ib->ptr[6] = PACKET2(0);
-       ib->ptr[7] = PACKET2(0);
-       ib->length_dw = 8;
-       r = radeon_ib_schedule(rdev, ib);
+       ib.ptr[0] = PACKET0(scratch, 0);
+       ib.ptr[1] = 0xDEADBEEF;
+       ib.ptr[2] = PACKET2(0);
+       ib.ptr[3] = PACKET2(0);
+       ib.ptr[4] = PACKET2(0);
+       ib.ptr[5] = PACKET2(0);
+       ib.ptr[6] = PACKET2(0);
+       ib.ptr[7] = PACKET2(0);
+       ib.length_dw = 8;
+       r = radeon_ib_schedule(rdev, &ib);
        if (r) {
                radeon_scratch_free(rdev, scratch);
                radeon_ib_free(rdev, &ib);
                return r;
        }
-       r = radeon_fence_wait(ib->fence, false);
+       r = radeon_fence_wait(ib.fence, false);
        if (r) {
                return r;
        }
@@ -3965,12 +3907,9 @@ static int r100_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        return 0;
 }
index a59cc474d53725978deaaa221892104bc876f27e..a26144d012074bc302d15607b0660c2609347334 100644 (file)
@@ -154,7 +154,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
        u32 tile_flags = 0;
        u32 idx_value;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        track = (struct r100_cs_track *)p->track;
        idx_value = radeon_get_ib_value(p, idx);
        switch (reg) {
index fa14383f9ca09cea2c8f1aaf486f9a7c241ff04e..97722a33e5131a4a6b63be014026775dad283f56 100644 (file)
@@ -377,28 +377,6 @@ void r300_gpu_init(struct radeon_device *rdev)
                 rdev->num_gb_pipes, rdev->num_z_pipes);
 }
 
-bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
-{
-       u32 rbbm_status;
-       int r;
-
-       rbbm_status = RREG32(R_000E40_RBBM_STATUS);
-       if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
-               r100_gpu_lockup_update(&rdev->config.r300.lockup, ring);
-               return false;
-       }
-       /* force CP activities */
-       r = radeon_ring_lock(rdev, ring, 2);
-       if (!r) {
-               /* PACKET2 NOP */
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_unlock_commit(rdev, ring);
-       }
-       ring->rptr = RREG32(RADEON_CP_RB_RPTR);
-       return r100_gpu_cp_is_lockup(rdev, &rdev->config.r300.lockup, ring);
-}
-
 int r300_asic_reset(struct radeon_device *rdev)
 {
        struct r100_mc_save save;
@@ -449,7 +427,6 @@ int r300_asic_reset(struct radeon_device *rdev)
        /* Check if GPU is idle */
        if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
                dev_err(rdev->dev, "failed to reset GPU\n");
-               rdev->gpu_lockup = true;
                ret = -1;
        } else
                dev_info(rdev->dev, "GPU reset succeed\n");
@@ -627,7 +604,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
        int r;
        u32 idx_value;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        track = (struct r100_cs_track *)p->track;
        idx_value = radeon_get_ib_value(p, idx);
 
@@ -1169,7 +1146,7 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
        unsigned idx;
        int r;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        idx = pkt->idx + 1;
        track = (struct r100_cs_track *)p->track;
        switch(pkt->opcode) {
@@ -1418,12 +1395,9 @@ static int r300_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        return 0;
 }
index f3fcaacfea01eb873583bf7728d5a8e27c5f1ec5..99137be7a3004253e15e11602a8b16eee585b342 100644 (file)
@@ -279,12 +279,9 @@ static int r420_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        return 0;
 }
index ebcc15b03c9f9223d738ec15cef74b64d699cc68..b5cf8375cd256aef8bd36cd4b60643facbdfb059 100644 (file)
@@ -207,12 +207,10 @@ static int r520_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
+
        return 0;
 }
 
index 391bd2636a8054bb5e102388060e54a1b10f9c97..4c0d8c96a0eca88adb969470f6b9f94c6ed35866 100644 (file)
@@ -1135,7 +1135,7 @@ static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc
        }
        if (rdev->flags & RADEON_IS_AGP) {
                size_bf = mc->gtt_start;
-               size_af = 0xFFFFFFFF - mc->gtt_end + 1;
+               size_af = 0xFFFFFFFF - mc->gtt_end;
                if (size_bf > size_af) {
                        if (mc->mc_vram_size > size_bf) {
                                dev_warn(rdev->dev, "limiting VRAM\n");
@@ -1149,7 +1149,7 @@ static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc
                                mc->real_vram_size = size_af;
                                mc->mc_vram_size = size_af;
                        }
-                       mc->vram_start = mc->gtt_end;
+                       mc->vram_start = mc->gtt_end + 1;
                }
                mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
                dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
@@ -1350,31 +1350,17 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
        u32 srbm_status;
        u32 grbm_status;
        u32 grbm_status2;
-       struct r100_gpu_lockup *lockup;
-       int r;
-
-       if (rdev->family >= CHIP_RV770)
-               lockup = &rdev->config.rv770.lockup;
-       else
-               lockup = &rdev->config.r600.lockup;
 
        srbm_status = RREG32(R_000E50_SRBM_STATUS);
        grbm_status = RREG32(R_008010_GRBM_STATUS);
        grbm_status2 = RREG32(R_008014_GRBM_STATUS2);
        if (!G_008010_GUI_ACTIVE(grbm_status)) {
-               r100_gpu_lockup_update(lockup, ring);
+               radeon_ring_lockup_update(ring);
                return false;
        }
        /* force CP activities */
-       r = radeon_ring_lock(rdev, ring, 2);
-       if (!r) {
-               /* PACKET2 NOP */
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_unlock_commit(rdev, ring);
-       }
-       ring->rptr = RREG32(ring->rptr_reg);
-       return r100_gpu_cp_is_lockup(rdev, lockup, ring);
+       radeon_ring_force_activity(rdev, ring);
+       return radeon_ring_test_lockup(rdev, ring);
 }
 
 int r600_asic_reset(struct radeon_device *rdev)
@@ -2377,20 +2363,15 @@ int r600_copy_blit(struct radeon_device *rdev,
                   unsigned num_gpu_pages,
                   struct radeon_fence *fence)
 {
+       struct radeon_sa_bo *vb = NULL;
        int r;
 
-       mutex_lock(&rdev->r600_blit.mutex);
-       rdev->r600_blit.vb_ib = NULL;
-       r = r600_blit_prepare_copy(rdev, num_gpu_pages);
+       r = r600_blit_prepare_copy(rdev, num_gpu_pages, &vb);
        if (r) {
-               if (rdev->r600_blit.vb_ib)
-                       radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
-               mutex_unlock(&rdev->r600_blit.mutex);
                return r;
        }
-       r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages);
-       r600_blit_done_copy(rdev, fence);
-       mutex_unlock(&rdev->r600_blit.mutex);
+       r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb);
+       r600_blit_done_copy(rdev, fence, vb);
        return 0;
 }
 
@@ -2494,12 +2475,9 @@ int r600_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        return 0;
 }
@@ -2675,7 +2653,6 @@ void r600_fini(struct radeon_device *rdev)
        r600_vram_scratch_fini(rdev);
        radeon_agp_fini(rdev);
        radeon_gem_fini(rdev);
-       radeon_semaphore_driver_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);
        radeon_atombios_fini(rdev);
@@ -2704,7 +2681,7 @@ void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 
 int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
 {
-       struct radeon_ib *ib;
+       struct radeon_ib ib;
        uint32_t scratch;
        uint32_t tmp = 0;
        unsigned i;
@@ -2722,18 +2699,18 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
                DRM_ERROR("radeon: failed to get ib (%d).\n", r);
                return r;
        }
-       ib->ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1);
-       ib->ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
-       ib->ptr[2] = 0xDEADBEEF;
-       ib->length_dw = 3;
-       r = radeon_ib_schedule(rdev, ib);
+       ib.ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1);
+       ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
+       ib.ptr[2] = 0xDEADBEEF;
+       ib.length_dw = 3;
+       r = radeon_ib_schedule(rdev, &ib);
        if (r) {
                radeon_scratch_free(rdev, scratch);
                radeon_ib_free(rdev, &ib);
                DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
                return r;
        }
-       r = radeon_fence_wait(ib->fence, false);
+       r = radeon_fence_wait(ib.fence, false);
        if (r) {
                DRM_ERROR("radeon: fence wait failed (%d).\n", r);
                return r;
@@ -2745,7 +2722,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
                DRM_UDELAY(1);
        }
        if (i < rdev->usec_timeout) {
-               DRM_INFO("ib test on ring %d succeeded in %u usecs\n", ib->fence->ring, i);
+               DRM_INFO("ib test on ring %d succeeded in %u usecs\n", ib.fence->ring, i);
        } else {
                DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n",
                          scratch, tmp);
@@ -2839,7 +2816,7 @@ void r600_rlc_stop(struct radeon_device *rdev)
                /* r7xx asics need to soft reset RLC before halting */
                WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC);
                RREG32(SRBM_SOFT_RESET);
-               udelay(15000);
+               mdelay(15);
                WREG32(SRBM_SOFT_RESET, 0);
                RREG32(SRBM_SOFT_RESET);
        }
@@ -2968,6 +2945,15 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev)
                        WREG32(DC_HPD5_INT_CONTROL, tmp);
                        tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
                        WREG32(DC_HPD6_INT_CONTROL, tmp);
+                       tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
+                       WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp);
+                       tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
+                       WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp);
+               } else {
+                       tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
+                       WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp);
+                       tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
+                       WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp);
                }
        } else {
                WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
@@ -2978,6 +2964,10 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev)
                WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
                tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
                WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
+               tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
+               WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp);
+               tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
+               WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp);
        }
 }
 
@@ -3047,6 +3037,9 @@ int r600_irq_init(struct radeon_device *rdev)
        else
                r600_disable_interrupt_state(rdev);
 
+       /* at this point everything should be setup correctly to enable master */
+       pci_set_master(rdev->pdev);
+
        /* enable irqs */
        r600_enable_interrupts(rdev);
 
@@ -3071,7 +3064,7 @@ int r600_irq_set(struct radeon_device *rdev)
        u32 mode_int = 0;
        u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
        u32 grbm_int_cntl = 0;
-       u32 hdmi1, hdmi2;
+       u32 hdmi0, hdmi1;
        u32 d1grph = 0, d2grph = 0;
 
        if (!rdev->irq.installed) {
@@ -3086,9 +3079,7 @@ int r600_irq_set(struct radeon_device *rdev)
                return 0;
        }
 
-       hdmi1 = RREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
        if (ASIC_IS_DCE3(rdev)) {
-               hdmi2 = RREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
                hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
                hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
                hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
@@ -3096,12 +3087,18 @@ int r600_irq_set(struct radeon_device *rdev)
                if (ASIC_IS_DCE32(rdev)) {
                        hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
                        hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
+                       hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
+                       hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK;
+               } else {
+                       hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
+                       hdmi1 = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
                }
        } else {
-               hdmi2 = RREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL) & ~R600_HDMI_INT_EN;
                hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN;
                hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN;
                hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN;
+               hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
+               hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK;
        }
 
        if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) {
@@ -3143,13 +3140,13 @@ int r600_irq_set(struct radeon_device *rdev)
                DRM_DEBUG("r600_irq_set: hpd 6\n");
                hpd6 |= DC_HPDx_INT_EN;
        }
-       if (rdev->irq.hdmi[0]) {
-               DRM_DEBUG("r600_irq_set: hdmi 1\n");
-               hdmi1 |= R600_HDMI_INT_EN;
+       if (rdev->irq.afmt[0]) {
+               DRM_DEBUG("r600_irq_set: hdmi 0\n");
+               hdmi0 |= HDMI0_AZ_FORMAT_WTRIG_MASK;
        }
-       if (rdev->irq.hdmi[1]) {
-               DRM_DEBUG("r600_irq_set: hdmi 2\n");
-               hdmi2 |= R600_HDMI_INT_EN;
+       if (rdev->irq.afmt[1]) {
+               DRM_DEBUG("r600_irq_set: hdmi 0\n");
+               hdmi1 |= HDMI0_AZ_FORMAT_WTRIG_MASK;
        }
        if (rdev->irq.gui_idle) {
                DRM_DEBUG("gui idle\n");
@@ -3161,9 +3158,7 @@ int r600_irq_set(struct radeon_device *rdev)
        WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph);
        WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph);
        WREG32(GRBM_INT_CNTL, grbm_int_cntl);
-       WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1);
        if (ASIC_IS_DCE3(rdev)) {
-               WREG32(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, hdmi2);
                WREG32(DC_HPD1_INT_CONTROL, hpd1);
                WREG32(DC_HPD2_INT_CONTROL, hpd2);
                WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -3171,12 +3166,18 @@ int r600_irq_set(struct radeon_device *rdev)
                if (ASIC_IS_DCE32(rdev)) {
                        WREG32(DC_HPD5_INT_CONTROL, hpd5);
                        WREG32(DC_HPD6_INT_CONTROL, hpd6);
+                       WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, hdmi0);
+                       WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, hdmi1);
+               } else {
+                       WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
+                       WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, hdmi1);
                }
        } else {
-               WREG32(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, hdmi2);
                WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
                WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
                WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3);
+               WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
+               WREG32(HDMI1_AUDIO_PACKET_CONTROL, hdmi1);
        }
 
        return 0;
@@ -3190,10 +3191,19 @@ static void r600_irq_ack(struct radeon_device *rdev)
                rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
                rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE);
                rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2);
+               if (ASIC_IS_DCE32(rdev)) {
+                       rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET0);
+                       rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET1);
+               } else {
+                       rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS);
+                       rdev->irq.stat_regs.r600.hdmi1_status = RREG32(DCE3_HDMI1_STATUS);
+               }
        } else {
                rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS);
                rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
                rdev->irq.stat_regs.r600.disp_int_cont2 = 0;
+               rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS);
+               rdev->irq.stat_regs.r600.hdmi1_status = RREG32(HDMI1_STATUS);
        }
        rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS);
        rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS);
@@ -3259,17 +3269,32 @@ static void r600_irq_ack(struct radeon_device *rdev)
                        tmp |= DC_HPDx_INT_ACK;
                        WREG32(DC_HPD6_INT_CONTROL, tmp);
                }
-       }
-       if (RREG32(R600_HDMI_BLOCK1 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) {
-               WREG32_P(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK);
-       }
-       if (ASIC_IS_DCE3(rdev)) {
-               if (RREG32(R600_HDMI_BLOCK3 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) {
-                       WREG32_P(R600_HDMI_BLOCK3 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK);
+               if (rdev->irq.stat_regs.r600.hdmi0_status & AFMT_AZ_FORMAT_WTRIG) {
+                       tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0);
+                       tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
+                       WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp);
+               }
+               if (rdev->irq.stat_regs.r600.hdmi1_status & AFMT_AZ_FORMAT_WTRIG) {
+                       tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1);
+                       tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
+                       WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp);
                }
        } else {
-               if (RREG32(R600_HDMI_BLOCK2 + R600_HDMI_STATUS) & R600_HDMI_INT_PENDING) {
-                       WREG32_P(R600_HDMI_BLOCK2 + R600_HDMI_CNTL, R600_HDMI_INT_ACK, ~R600_HDMI_INT_ACK);
+               if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) {
+                       tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL);
+                       tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK;
+                       WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp);
+               }
+               if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) {
+                       if (ASIC_IS_DCE3(rdev)) {
+                               tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL);
+                               tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK;
+                               WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp);
+                       } else {
+                               tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL);
+                               tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK;
+                               WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp);
+                       }
                }
        }
 }
@@ -3345,6 +3370,7 @@ int r600_irq_process(struct radeon_device *rdev)
        u32 ring_index;
        unsigned long flags;
        bool queue_hotplug = false;
+       bool queue_hdmi = false;
 
        if (!rdev->ih.enabled || rdev->shutdown)
                return IRQ_NONE;
@@ -3480,9 +3506,26 @@ restart_ih:
                                break;
                        }
                        break;
-               case 21: /* HDMI */
-                       DRM_DEBUG("IH: HDMI: 0x%x\n", src_data);
-                       r600_audio_schedule_polling(rdev);
+               case 21: /* hdmi */
+                       switch (src_data) {
+                       case 4:
+                               if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) {
+                                       rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG;
+                                       queue_hdmi = true;
+                                       DRM_DEBUG("IH: HDMI0\n");
+                               }
+                               break;
+                       case 5:
+                               if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) {
+                                       rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG;
+                                       queue_hdmi = true;
+                                       DRM_DEBUG("IH: HDMI1\n");
+                               }
+                               break;
+                       default:
+                               DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
+                               break;
+                       }
                        break;
                case 176: /* CP_INT in ring buffer */
                case 177: /* CP_INT in IB1 */
@@ -3514,6 +3557,8 @@ restart_ih:
                goto restart_ih;
        if (queue_hotplug)
                schedule_work(&rdev->hotplug_work);
+       if (queue_hdmi)
+               schedule_work(&rdev->audio_work);
        rdev->ih.rptr = rptr;
        WREG32(IH_RB_RPTR, rdev->ih.rptr);
        spin_unlock_irqrestore(&rdev->ih.lock, flags);
index ba66f3093d46138be6010d299f7b103d49b4e5eb..b922a3cd90dba7824ac73b6e46308098b0d826d7 100644 (file)
@@ -29,8 +29,6 @@
 #include "radeon_asic.h"
 #include "atom.h"
 
-#define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */
-
 /*
  * check if the chipset is supported
  */
@@ -105,21 +103,13 @@ uint8_t r600_audio_category_code(struct radeon_device *rdev)
        return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff;
 }
 
-/*
- * schedule next audio update event
- */
-void r600_audio_schedule_polling(struct radeon_device *rdev)
-{
-       mod_timer(&rdev->audio_timer,
-               jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
-}
-
 /*
  * update all hdmi interfaces with current audio parameters
  */
-static void r600_audio_update_hdmi(unsigned long param)
+void r600_audio_update_hdmi(struct work_struct *work)
 {
-       struct radeon_device *rdev = (struct radeon_device *)param;
+       struct radeon_device *rdev = container_of(work, struct radeon_device,
+                                                 audio_work);
        struct drm_device *dev = rdev->ddev;
 
        int channels = r600_audio_channels(rdev);
@@ -127,33 +117,27 @@ static void r600_audio_update_hdmi(unsigned long param)
        int bps = r600_audio_bits_per_sample(rdev);
        uint8_t status_bits = r600_audio_status_bits(rdev);
        uint8_t category_code = r600_audio_category_code(rdev);
-
        struct drm_encoder *encoder;
-       int changes = 0, still_going = 0;
+       int changes = 0;
 
-       changes |= channels != rdev->audio_channels;
-       changes |= rate != rdev->audio_rate;
-       changes |= bps != rdev->audio_bits_per_sample;
-       changes |= status_bits != rdev->audio_status_bits;
-       changes |= category_code != rdev->audio_category_code;
+       changes |= channels != rdev->audio.channels;
+       changes |= rate != rdev->audio.rate;
+       changes |= bps != rdev->audio.bits_per_sample;
+       changes |= status_bits != rdev->audio.status_bits;
+       changes |= category_code != rdev->audio.category_code;
 
        if (changes) {
-               rdev->audio_channels = channels;
-               rdev->audio_rate = rate;
-               rdev->audio_bits_per_sample = bps;
-               rdev->audio_status_bits = status_bits;
-               rdev->audio_category_code = category_code;
+               rdev->audio.channels = channels;
+               rdev->audio.rate = rate;
+               rdev->audio.bits_per_sample = bps;
+               rdev->audio.status_bits = status_bits;
+               rdev->audio.category_code = category_code;
        }
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-               still_going |= radeon_encoder->audio_polling_active;
                if (changes || r600_hdmi_buffer_status_changed(encoder))
                        r600_hdmi_update_audio_settings(encoder);
        }
-
-       if (still_going)
-               r600_audio_schedule_polling(rdev);
 }
 
 /*
@@ -173,11 +157,11 @@ static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable)
                WREG32_P(R600_AUDIO_ENABLE,
                         enable ? 0x81000000 : 0x0, ~0x81000000);
        }
-       rdev->audio_enabled = enable;
+       rdev->audio.enabled = enable;
 }
 
 /*
- * initialize the audio vars and register the update timer
+ * initialize the audio vars
  */
 int r600_audio_init(struct radeon_device *rdev)
 {
@@ -186,50 +170,15 @@ int r600_audio_init(struct radeon_device *rdev)
 
        r600_audio_engine_enable(rdev, true);
 
-       rdev->audio_channels = -1;
-       rdev->audio_rate = -1;
-       rdev->audio_bits_per_sample = -1;
-       rdev->audio_status_bits = 0;
-       rdev->audio_category_code = 0;
-
-       setup_timer(
-               &rdev->audio_timer,
-               r600_audio_update_hdmi,
-               (unsigned long)rdev);
+       rdev->audio.channels = -1;
+       rdev->audio.rate = -1;
+       rdev->audio.bits_per_sample = -1;
+       rdev->audio.status_bits = 0;
+       rdev->audio.category_code = 0;
 
        return 0;
 }
 
-/*
- * enable the polling timer, to check for status changes
- */
-void r600_audio_enable_polling(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-
-       DRM_DEBUG("r600_audio_enable_polling: %d\n",
-               radeon_encoder->audio_polling_active);
-       if (radeon_encoder->audio_polling_active)
-               return;
-
-       radeon_encoder->audio_polling_active = 1;
-       if (rdev->audio_enabled)
-               mod_timer(&rdev->audio_timer, jiffies + 1);
-}
-
-/*
- * disable the polling timer, so we get no more status updates
- */
-void r600_audio_disable_polling(struct drm_encoder *encoder)
-{
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       DRM_DEBUG("r600_audio_disable_polling: %d\n",
-               radeon_encoder->audio_polling_active);
-       radeon_encoder->audio_polling_active = 0;
-}
-
 /*
  * atach the audio codec to the clock source of the encoder
  */
@@ -294,10 +243,8 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
  */
 void r600_audio_fini(struct radeon_device *rdev)
 {
-       if (!rdev->audio_enabled)
+       if (!rdev->audio.enabled)
                return;
 
-       del_timer(&rdev->audio_timer);
-
        r600_audio_engine_enable(rdev, false);
 }
index db38f587f27ae0afda533313f924f5e4b4e4a92b..ef20822a1586a03d05f149098f172fedf55b7f4b 100644 (file)
@@ -513,7 +513,6 @@ int r600_blit_init(struct radeon_device *rdev)
        rdev->r600_blit.primitives.set_default_state = set_default_state;
 
        rdev->r600_blit.ring_size_common = 40; /* shaders + def state */
-       rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
        rdev->r600_blit.ring_size_common += 5; /* done copy */
        rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
 
@@ -528,7 +527,6 @@ int r600_blit_init(struct radeon_device *rdev)
        if (rdev->r600_blit.shader_obj)
                goto done;
 
-       mutex_init(&rdev->r600_blit.mutex);
        rdev->r600_blit.state_offset = 0;
 
        if (rdev->family >= CHIP_RV770)
@@ -621,27 +619,6 @@ void r600_blit_fini(struct radeon_device *rdev)
        radeon_bo_unref(&rdev->r600_blit.shader_obj);
 }
 
-static int r600_vb_ib_get(struct radeon_device *rdev, unsigned size)
-{
-       int r;
-       r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX,
-                         &rdev->r600_blit.vb_ib, size);
-       if (r) {
-               DRM_ERROR("failed to get IB for vertex buffer\n");
-               return r;
-       }
-
-       rdev->r600_blit.vb_total = size;
-       rdev->r600_blit.vb_used = 0;
-       return 0;
-}
-
-static void r600_vb_ib_put(struct radeon_device *rdev)
-{
-       radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence);
-       radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
-}
-
 static unsigned r600_blit_create_rect(unsigned num_gpu_pages,
                                      int *width, int *height, int max_dim)
 {
@@ -688,7 +665,8 @@ static unsigned r600_blit_create_rect(unsigned num_gpu_pages,
 }
 
 
-int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages)
+int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages,
+                          struct radeon_sa_bo **vb)
 {
        struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        int r;
@@ -705,46 +683,54 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages)
        }
 
        /* 48 bytes for vertex per loop */
-       r = r600_vb_ib_get(rdev, (num_loops*48)+256);
-       if (r)
+       r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, vb,
+                            (num_loops*48)+256, 256, true);
+       if (r) {
                return r;
+       }
 
        /* calculate number of loops correctly */
        ring_size = num_loops * dwords_per_loop;
        ring_size += rdev->r600_blit.ring_size_common;
        r = radeon_ring_lock(rdev, ring, ring_size);
-       if (r)
+       if (r) {
+               radeon_sa_bo_free(rdev, vb, NULL);
                return r;
+       }
 
        rdev->r600_blit.primitives.set_default_state(rdev);
        rdev->r600_blit.primitives.set_shaders(rdev);
        return 0;
 }
 
-void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence)
+void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence,
+                        struct radeon_sa_bo *vb)
 {
+       struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
        int r;
 
-       if (rdev->r600_blit.vb_ib)
-               r600_vb_ib_put(rdev);
-
-       if (fence)
-               r = radeon_fence_emit(rdev, fence);
+       r = radeon_fence_emit(rdev, fence);
+       if (r) {
+               radeon_ring_unlock_undo(rdev, ring);
+               return;
+       }
 
-       radeon_ring_unlock_commit(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
+       radeon_ring_unlock_commit(rdev, ring);
+       radeon_sa_bo_free(rdev, &vb, fence);
 }
 
 void r600_kms_blit_copy(struct radeon_device *rdev,
                        u64 src_gpu_addr, u64 dst_gpu_addr,
-                       unsigned num_gpu_pages)
+                       unsigned num_gpu_pages,
+                       struct radeon_sa_bo *vb)
 {
        u64 vb_gpu_addr;
-       u32 *vb;
+       u32 *vb_cpu_addr;
 
-       DRM_DEBUG("emitting copy %16llx %16llx %d %d\n",
-                 src_gpu_addr, dst_gpu_addr,
-                 num_gpu_pages, rdev->r600_blit.vb_used);
-       vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
+       DRM_DEBUG("emitting copy %16llx %16llx %d\n",
+                 src_gpu_addr, dst_gpu_addr, num_gpu_pages);
+       vb_cpu_addr = (u32 *)radeon_sa_bo_cpu_addr(vb);
+       vb_gpu_addr = radeon_sa_bo_gpu_addr(vb);
 
        while (num_gpu_pages) {
                int w, h;
@@ -756,39 +742,34 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
                size_in_bytes = pages_per_loop * RADEON_GPU_PAGE_SIZE;
                DRM_DEBUG("rectangle w=%d h=%d\n", w, h);
 
-               if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
-                       WARN_ON(1);
-               }
-
-               vb[0] = 0;
-               vb[1] = 0;
-               vb[2] = 0;
-               vb[3] = 0;
+               vb_cpu_addr[0] = 0;
+               vb_cpu_addr[1] = 0;
+               vb_cpu_addr[2] = 0;
+               vb_cpu_addr[3] = 0;
 
-               vb[4] = 0;
-               vb[5] = i2f(h);
-               vb[6] = 0;
-               vb[7] = i2f(h);
+               vb_cpu_addr[4] = 0;
+               vb_cpu_addr[5] = i2f(h);
+               vb_cpu_addr[6] = 0;
+               vb_cpu_addr[7] = i2f(h);
 
-               vb[8] = i2f(w);
-               vb[9] = i2f(h);
-               vb[10] = i2f(w);
-               vb[11] = i2f(h);
+               vb_cpu_addr[8] = i2f(w);
+               vb_cpu_addr[9] = i2f(h);
+               vb_cpu_addr[10] = i2f(w);
+               vb_cpu_addr[11] = i2f(h);
 
                rdev->r600_blit.primitives.set_tex_resource(rdev, FMT_8_8_8_8,
                                                            w, h, w, src_gpu_addr, size_in_bytes);
                rdev->r600_blit.primitives.set_render_target(rdev, COLOR_8_8_8_8,
                                                             w, h, dst_gpu_addr);
                rdev->r600_blit.primitives.set_scissors(rdev, 0, 0, w, h);
-               vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
                rdev->r600_blit.primitives.set_vtx_resource(rdev, vb_gpu_addr);
                rdev->r600_blit.primitives.draw_auto(rdev);
                rdev->r600_blit.primitives.cp_set_surface_sync(rdev,
                                    PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
                                    size_in_bytes, dst_gpu_addr);
 
-               vb += 12;
-               rdev->r600_blit.vb_used += 4*12;
+               vb_cpu_addr += 12;
+               vb_gpu_addr += 4*12;
                src_gpu_addr += size_in_bytes;
                dst_gpu_addr += size_in_bytes;
                num_gpu_pages -= pages_per_loop;
index 84c546250955bfc354456dc858f839c6bb27fcfa..75ed17c96115f30bca7aa4c7ca9fe7f65c035cb9 100644 (file)
@@ -407,7 +407,7 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
 
        RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
        RADEON_READ(R600_GRBM_SOFT_RESET);
-       DRM_UDELAY(15000);
+       mdelay(15);
        RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
 
        fw_data = (const __be32 *)dev_priv->me_fw->data;
@@ -500,7 +500,7 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
 
        RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
        RADEON_READ(R600_GRBM_SOFT_RESET);
-       DRM_UDELAY(15000);
+       mdelay(15);
        RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
 
        fw_data = (const __be32 *)dev_priv->pfp_fw->data;
@@ -1797,7 +1797,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
 
        RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
        RADEON_READ(R600_GRBM_SOFT_RESET);
-       DRM_UDELAY(15000);
+       mdelay(15);
        RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
 
 
index b8e12af304a9657db9b5b906c2df1e289edb46f9..0133f5f09bd6c71cc95d2472beaacef51c3ffa2a 100644 (file)
@@ -345,7 +345,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        u32 height, height_align, pitch, pitch_align, depth_align;
        u64 base_offset, base_align;
        struct array_mode_checker array_check;
-       volatile u32 *ib = p->ib->ptr;
+       volatile u32 *ib = p->ib.ptr;
        unsigned array_mode;
        u32 format;
 
@@ -471,7 +471,7 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
        u64 base_offset, base_align;
        struct array_mode_checker array_check;
        int array_mode;
-       volatile u32 *ib = p->ib->ptr;
+       volatile u32 *ib = p->ib.ptr;
 
 
        if (track->db_bo == NULL) {
@@ -961,7 +961,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
        uint32_t header, h_idx, reg, wait_reg_mem_info;
        volatile uint32_t *ib;
 
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
 
        /* parse the WAIT_REG_MEM */
        r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx);
@@ -1110,7 +1110,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        m = 1 << ((reg >> 2) & 31);
        if (!(r600_reg_safe_bm[i] & m))
                return 0;
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        switch (reg) {
        /* force following reg to 0 in an attempt to disable out buffer
         * which will need us to better understand how it works to perform
@@ -1714,7 +1714,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
        u32 idx_value;
 
        track = (struct r600_cs_track *)p->track;
-       ib = p->ib->ptr;
+       ib = p->ib.ptr;
        idx = pkt->idx + 1;
        idx_value = radeon_get_ib_value(p, idx);
 
@@ -2249,8 +2249,8 @@ int r600_cs_parse(struct radeon_cs_parser *p)
                }
        } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
 #if 0
-       for (r = 0; r < p->ib->length_dw; r++) {
-               printk(KERN_INFO "%05d  0x%08X\n", r, p->ib->ptr[r]);
+       for (r = 0; r < p->ib.length_dw; r++) {
+               printk(KERN_INFO "%05d  0x%08X\n", r, p->ib.ptr[r]);
                mdelay(1);
        }
 #endif
@@ -2298,7 +2298,6 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
 {
        struct radeon_cs_parser parser;
        struct radeon_cs_chunk *ib_chunk;
-       struct radeon_ib fake_ib;
        struct r600_cs_track *track;
        int r;
 
@@ -2314,9 +2313,8 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
        parser.dev = &dev->pdev->dev;
        parser.rdev = NULL;
        parser.family = family;
-       parser.ib = &fake_ib;
        parser.track = track;
-       fake_ib.ptr = ib;
+       parser.ib.ptr = ib;
        r = radeon_cs_parser_init(&parser, data);
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
@@ -2333,8 +2331,8 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
         * input memory (cached) and write to the IB (which can be
         * uncached). */
        ib_chunk = &parser.chunks[parser.chunk_ib_idx];
-       parser.ib->length_dw = ib_chunk->length_dw;
-       *l = parser.ib->length_dw;
+       parser.ib.length_dw = ib_chunk->length_dw;
+       *l = parser.ib.length_dw;
        r = r600_cs_parse(&parser);
        if (r) {
                DRM_ERROR("Invalid command stream !\n");
index 0b59206714505e24aa329b8adc2e0fd0e7dbc8ad..c6de0022c070da0a34c0e12d80669c648c20273d 100644 (file)
@@ -27,6 +27,7 @@
 #include "radeon_drm.h"
 #include "radeon.h"
 #include "radeon_asic.h"
+#include "r600d.h"
 #include "atom.h"
 
 /*
@@ -108,20 +109,20 @@ static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
        CTS = r600_hdmi_ACR[i].CTS_32kHz;
        N = r600_hdmi_ACR[i].N_32kHz;
        r600_hdmi_calc_CTS(clock, &CTS, N, 32000);
-       WREG32(offset+R600_HDMI_32kHz_CTS, CTS << 12);
-       WREG32(offset+R600_HDMI_32kHz_N, N);
+       WREG32(HDMI0_ACR_32_0 + offset, HDMI0_ACR_CTS_32(CTS));
+       WREG32(HDMI0_ACR_32_1 + offset, N);
 
        CTS = r600_hdmi_ACR[i].CTS_44_1kHz;
        N = r600_hdmi_ACR[i].N_44_1kHz;
        r600_hdmi_calc_CTS(clock, &CTS, N, 44100);
-       WREG32(offset+R600_HDMI_44_1kHz_CTS, CTS << 12);
-       WREG32(offset+R600_HDMI_44_1kHz_N, N);
+       WREG32(HDMI0_ACR_44_0 + offset, HDMI0_ACR_CTS_44(CTS));
+       WREG32(HDMI0_ACR_44_1 + offset, N);
 
        CTS = r600_hdmi_ACR[i].CTS_48kHz;
        N = r600_hdmi_ACR[i].N_48kHz;
        r600_hdmi_calc_CTS(clock, &CTS, N, 48000);
-       WREG32(offset+R600_HDMI_48kHz_CTS, CTS << 12);
-       WREG32(offset+R600_HDMI_48kHz_N, N);
+       WREG32(HDMI0_ACR_48_0 + offset, HDMI0_ACR_CTS_48(CTS));
+       WREG32(HDMI0_ACR_48_1 + offset, N);
 }
 
 /*
@@ -204,13 +205,13 @@ static void r600_hdmi_videoinfoframe(
         * workaround this issue. */
        frame[0x0] += 2;
 
-       WREG32(offset+R600_HDMI_VIDEOINFOFRAME_0,
+       WREG32(HDMI0_AVI_INFO0 + offset,
                frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
-       WREG32(offset+R600_HDMI_VIDEOINFOFRAME_1,
+       WREG32(HDMI0_AVI_INFO1 + offset,
                frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24));
-       WREG32(offset+R600_HDMI_VIDEOINFOFRAME_2,
+       WREG32(HDMI0_AVI_INFO2 + offset,
                frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
-       WREG32(offset+R600_HDMI_VIDEOINFOFRAME_3,
+       WREG32(HDMI0_AVI_INFO3 + offset,
                frame[0xC] | (frame[0xD] << 8));
 }
 
@@ -249,9 +250,9 @@ static void r600_hdmi_audioinfoframe(
 
        r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame);
 
-       WREG32(offset+R600_HDMI_AUDIOINFOFRAME_0,
+       WREG32(HDMI0_AUDIO_INFO0 + offset,
                frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
-       WREG32(offset+R600_HDMI_AUDIOINFOFRAME_1,
+       WREG32(HDMI0_AUDIO_INFO1 + offset,
                frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24));
 }
 
@@ -264,7 +265,7 @@ static int r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder)
        struct radeon_device *rdev = dev->dev_private;
        uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
 
-       return (RREG32(offset+R600_HDMI_STATUS) & 0x10) != 0;
+       return (RREG32(HDMI0_STATUS + offset) & 0x10) != 0;
 }
 
 /*
@@ -275,7 +276,7 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        int status, result;
 
-       if (!radeon_encoder->hdmi_offset)
+       if (!radeon_encoder->hdmi_enabled)
                return 0;
 
        status = r600_hdmi_is_audio_buffer_filled(encoder);
@@ -295,18 +296,18 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        uint32_t offset = radeon_encoder->hdmi_offset;
 
-       if (!offset)
+       if (!radeon_encoder->hdmi_enabled)
                return;
 
        if (!radeon_encoder->hdmi_audio_workaround ||
                r600_hdmi_is_audio_buffer_filled(encoder)) {
 
                /* disable audio workaround */
-               WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001);
+               WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, 0x0001, ~0x1001);
 
        } else {
                /* enable audio workaround */
-               WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001);
+               WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, 0x1001, ~0x1001);
        }
 }
 
@@ -323,34 +324,34 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
        if (ASIC_IS_DCE5(rdev))
                return;
 
-       if (!offset)
+       if (!to_radeon_encoder(encoder)->hdmi_enabled)
                return;
 
        r600_audio_set_clock(encoder, mode->clock);
 
-       WREG32(offset+R600_HDMI_UNKNOWN_0, 0x1000);
-       WREG32(offset+R600_HDMI_UNKNOWN_1, 0x0);
-       WREG32(offset+R600_HDMI_UNKNOWN_2, 0x1000);
+       WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);
+       WREG32(HDMI0_GC + offset, 0x0);
+       WREG32(HDMI0_ACR_PACKET_CONTROL + offset, 0x1000);
 
        r600_hdmi_update_ACR(encoder, mode->clock);
 
-       WREG32(offset+R600_HDMI_VIDEOCNTL, 0x13);
+       WREG32(HDMI0_INFOFRAME_CONTROL0 + offset, 0x13);
 
-       WREG32(offset+R600_HDMI_VERSION, 0x202);
+       WREG32(HDMI0_INFOFRAME_CONTROL1 + offset, 0x202);
 
        r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
        /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
-       WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF);
-       WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF);
-       WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001);
-       WREG32(offset+R600_HDMI_AUDIO_DEBUG_3, 0x00000001);
+       WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
+       WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
+       WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
+       WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
 
        r600_hdmi_audio_workaround(encoder);
 
        /* audio packets per line, does anyone know how to calc this ? */
-       WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000);
+       WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset, 0x00040000, ~0x001F0000);
 }
 
 /*
@@ -370,7 +371,7 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
 
        uint32_t iec;
 
-       if (!offset)
+       if (!to_radeon_encoder(encoder)->hdmi_enabled)
                return;
 
        DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n",
@@ -401,7 +402,7 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
        case 192000: iec |= 0xe << 24; break;
        }
 
-       WREG32(offset+R600_HDMI_IEC60958_1, iec);
+       WREG32(HDMI0_60958_0 + offset, iec);
 
        iec = 0;
        switch (bps) {
@@ -412,49 +413,15 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
        if (status_bits & AUDIO_STATUS_V)
                iec |= 0x5 << 16;
 
-       WREG32_P(offset+R600_HDMI_IEC60958_2, iec, ~0x5000f);
+       WREG32_P(HDMI0_60958_1 + offset, iec, ~0x5000f);
 
        /* 0x021 or 0x031 sets the audio frame length */
-       WREG32(offset+R600_HDMI_AUDIOCNTL, 0x31);
+       WREG32(HDMI0_VBI_PACKET_CONTROL + offset, 0x31);
        r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0);
 
        r600_hdmi_audio_workaround(encoder);
 }
 
-static int r600_hdmi_find_free_block(struct drm_device *dev)
-{
-       struct radeon_device *rdev = dev->dev_private;
-       struct drm_encoder *encoder;
-       struct radeon_encoder *radeon_encoder;
-       bool free_blocks[3] = { true, true, true };
-
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               radeon_encoder = to_radeon_encoder(encoder);
-               switch (radeon_encoder->hdmi_offset) {
-               case R600_HDMI_BLOCK1:
-                       free_blocks[0] = false;
-                       break;
-               case R600_HDMI_BLOCK2:
-                       free_blocks[1] = false;
-                       break;
-               case R600_HDMI_BLOCK3:
-                       free_blocks[2] = false;
-                       break;
-               }
-       }
-
-       if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690 ||
-           rdev->family == CHIP_RS740) {
-               return free_blocks[0] ? R600_HDMI_BLOCK1 : 0;
-       } else if (rdev->family >= CHIP_R600) {
-               if (free_blocks[0])
-                       return R600_HDMI_BLOCK1;
-               else if (free_blocks[1])
-                       return R600_HDMI_BLOCK2;
-       }
-       return 0;
-}
-
 static void r600_hdmi_assign_block(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
@@ -483,20 +450,24 @@ static void r600_hdmi_assign_block(struct drm_encoder *encoder)
                        dev_err(rdev->dev, "Enabling HDMI on unknown dig\n");
                        return;
                }
-               radeon_encoder->hdmi_offset = EVERGREEN_HDMI_BASE +
-                                               eg_offsets[dig->dig_encoder];
-               radeon_encoder->hdmi_config_offset = radeon_encoder->hdmi_offset
-                                               + EVERGREEN_HDMI_CONFIG_OFFSET;
+               radeon_encoder->hdmi_offset = eg_offsets[dig->dig_encoder];
+               /* Temp hack for Evergreen until we split r600_hdmi.c
+                * Evergreen first block is 0x7030 instead of 0x7400.
+                */
+               radeon_encoder->hdmi_offset -= 0x3d0;
        } else if (ASIC_IS_DCE3(rdev)) {
                radeon_encoder->hdmi_offset = dig->dig_encoder ?
-                       R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1;
-               if (ASIC_IS_DCE32(rdev))
-                       radeon_encoder->hdmi_config_offset = dig->dig_encoder ?
-                               R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1;
-       } else if (rdev->family >= CHIP_R600 || rdev->family == CHIP_RS600 ||
-                  rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
-               radeon_encoder->hdmi_offset = r600_hdmi_find_free_block(dev);
+                       DCE3_HDMI_OFFSET1 : DCE3_HDMI_OFFSET0;
+       } else if (rdev->family >= CHIP_R600) {
+               /* 2 routable blocks, but using dig_encoder should be fine */
+               radeon_encoder->hdmi_offset = dig->dig_encoder ?
+                       DCE2_HDMI_OFFSET1 : DCE2_HDMI_OFFSET0;
+       } else if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690 ||
+                  rdev->family == CHIP_RS740) {
+               /* Only 1 routable block */
+               radeon_encoder->hdmi_offset = DCE2_HDMI_OFFSET0;
        }
+       radeon_encoder->hdmi_enabled = true;
 }
 
 /*
@@ -512,9 +483,9 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
        if (ASIC_IS_DCE5(rdev))
                return;
 
-       if (!radeon_encoder->hdmi_offset) {
+       if (!radeon_encoder->hdmi_enabled) {
                r600_hdmi_assign_block(encoder);
-               if (!radeon_encoder->hdmi_offset) {
+               if (!radeon_encoder->hdmi_enabled) {
                        dev_warn(rdev->dev, "Could not find HDMI block for "
                                "0x%x encoder\n", radeon_encoder->encoder_id);
                        return;
@@ -525,9 +496,9 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
        if (ASIC_IS_DCE5(rdev)) {
                /* TODO */
        } else if (ASIC_IS_DCE4(rdev)) {
-               WREG32_P(radeon_encoder->hdmi_config_offset + 0xc, 0x1, ~0x1);
+               WREG32_P(0x74fc + radeon_encoder->hdmi_offset, 0x1, ~0x1);
        } else if (ASIC_IS_DCE32(rdev)) {
-               WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1);
+               WREG32_P(AFMT_AUDIO_PACKET_CONTROL + radeon_encoder->hdmi_offset, 0x1, ~0x1);
        } else if (ASIC_IS_DCE3(rdev)) {
                /* TODO */
        } else if (rdev->family >= CHIP_R600) {
@@ -535,12 +506,12 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
                case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
                        WREG32_P(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN,
                                 ~AVIVO_TMDSA_CNTL_HDMI_EN);
-                       WREG32(offset + R600_HDMI_ENABLE, 0x101);
+                       WREG32(HDMI0_CONTROL + offset, 0x101);
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
                        WREG32_P(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN,
                                 ~AVIVO_LVTMA_CNTL_HDMI_EN);
-                       WREG32(offset + R600_HDMI_ENABLE, 0x105);
+                       WREG32(HDMI0_CONTROL + offset, 0x105);
                        break;
                default:
                        dev_err(rdev->dev, "Unknown HDMI output type\n");
@@ -548,19 +519,10 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
                }
        }
 
-       if (rdev->irq.installed
-           && rdev->family != CHIP_RS600
-           && rdev->family != CHIP_RS690
-           && rdev->family != CHIP_RS740
-           && !ASIC_IS_DCE4(rdev)) {
+       if (rdev->irq.installed) {
                /* if irq is available use it */
-               rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = true;
+               rdev->irq.afmt[offset == 0 ? 0 : 1] = true;
                radeon_irq_set(rdev);
-
-               r600_audio_disable_polling(encoder);
-       } else {
-               /* if not fallback to polling */
-               r600_audio_enable_polling(encoder);
        }
 
        DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
@@ -581,7 +543,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
                return;
 
        offset = radeon_encoder->hdmi_offset;
-       if (!offset) {
+       if (!radeon_encoder->hdmi_enabled) {
                dev_err(rdev->dev, "Disabling not enabled HDMI\n");
                return;
        }
@@ -590,29 +552,27 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
                offset, radeon_encoder->encoder_id);
 
        /* disable irq */
-       rdev->irq.hdmi[offset == R600_HDMI_BLOCK1 ? 0 : 1] = false;
+       rdev->irq.afmt[offset == 0 ? 0 : 1] = false;
        radeon_irq_set(rdev);
 
-       /* disable polling */
-       r600_audio_disable_polling(encoder);
 
        if (ASIC_IS_DCE5(rdev)) {
                /* TODO */
        } else if (ASIC_IS_DCE4(rdev)) {
-               WREG32_P(radeon_encoder->hdmi_config_offset + 0xc, 0, ~0x1);
+               WREG32_P(0x74fc + radeon_encoder->hdmi_offset, 0, ~0x1);
        } else if (ASIC_IS_DCE32(rdev)) {
-               WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1);
+               WREG32_P(AFMT_AUDIO_PACKET_CONTROL + radeon_encoder->hdmi_offset, 0, ~0x1);
        } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
                switch (radeon_encoder->encoder_id) {
                case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
                        WREG32_P(AVIVO_TMDSA_CNTL, 0,
                                 ~AVIVO_TMDSA_CNTL_HDMI_EN);
-                       WREG32(offset + R600_HDMI_ENABLE, 0);
+                       WREG32(HDMI0_CONTROL + offset, 0);
                        break;
                case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
                        WREG32_P(AVIVO_LVTMA_CNTL, 0,
                                 ~AVIVO_LVTMA_CNTL_HDMI_EN);
-                       WREG32(offset + R600_HDMI_ENABLE, 0);
+                       WREG32(HDMI0_CONTROL + offset, 0);
                        break;
                default:
                        dev_err(rdev->dev, "Unknown HDMI output type\n");
@@ -620,6 +580,6 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
                }
        }
 
+       radeon_encoder->hdmi_enabled = false;
        radeon_encoder->hdmi_offset = 0;
-       radeon_encoder->hdmi_config_offset = 0;
 }
index f869897c745699ab4494738e390a689081fe4e59..c44304ad8bdaa77b7f065de85f1ed4668604529f 100644 (file)
 #define R600_AUDIO_PIN_WIDGET_CNTL        0x73d4
 #define R600_AUDIO_STATUS_BITS            0x73d8
 
-/* HDMI base register addresses */
-#define R600_HDMI_BLOCK1                  0x7400
-#define R600_HDMI_BLOCK2                  0x7700
-#define R600_HDMI_BLOCK3                  0x7800
-
-/* HDMI registers */
-#define R600_HDMI_ENABLE                0x00
-#define R600_HDMI_STATUS                0x04
-#       define R600_HDMI_INT_PENDING    (1 << 29)
-#define R600_HDMI_CNTL                  0x08
-#       define R600_HDMI_INT_EN         (1 << 28)
-#       define R600_HDMI_INT_ACK        (1 << 29)
-#define R600_HDMI_UNKNOWN_0             0x0C
-#define R600_HDMI_AUDIOCNTL             0x10
-#define R600_HDMI_VIDEOCNTL             0x14
-#define R600_HDMI_VERSION               0x18
-#define R600_HDMI_UNKNOWN_1             0x28
-#define R600_HDMI_VIDEOINFOFRAME_0      0x54
-#define R600_HDMI_VIDEOINFOFRAME_1      0x58
-#define R600_HDMI_VIDEOINFOFRAME_2      0x5c
-#define R600_HDMI_VIDEOINFOFRAME_3      0x60
-#define R600_HDMI_32kHz_CTS             0xac
-#define R600_HDMI_32kHz_N               0xb0
-#define R600_HDMI_44_1kHz_CTS           0xb4
-#define R600_HDMI_44_1kHz_N             0xb8
-#define R600_HDMI_48kHz_CTS             0xbc
-#define R600_HDMI_48kHz_N               0xc0
-#define R600_HDMI_AUDIOINFOFRAME_0      0xcc
-#define R600_HDMI_AUDIOINFOFRAME_1      0xd0
-#define R600_HDMI_IEC60958_1            0xd4
-#define R600_HDMI_IEC60958_2            0xd8
-#define R600_HDMI_UNKNOWN_2             0xdc
-#define R600_HDMI_AUDIO_DEBUG_0         0xe0
-#define R600_HDMI_AUDIO_DEBUG_1         0xe4
-#define R600_HDMI_AUDIO_DEBUG_2         0xe8
-#define R600_HDMI_AUDIO_DEBUG_3         0xec
-
-/* HDMI additional config base register addresses */
-#define R600_HDMI_CONFIG1                 0x7600
-#define R600_HDMI_CONFIG2                 0x7a00
-
 #endif
index 59f9c993cc31b4cdb550b85b5b99de588b5430b0..a9652be93b6688a25fa5df257f46dc9e2866f853 100644 (file)
 #       define TARGET_LINK_SPEED_MASK                     (0xf << 0)
 #       define SELECTABLE_DEEMPHASIS                      (1 << 6)
 
+/* Audio clocks */
+#define DCCG_AUDIO_DTO0_PHASE             0x0514
+#define DCCG_AUDIO_DTO0_MODULE            0x0518
+#define DCCG_AUDIO_DTO0_LOAD              0x051c
+#       define DTO_LOAD                   (1 << 31)
+#define DCCG_AUDIO_DTO0_CNTL              0x0520
+
+#define DCCG_AUDIO_DTO1_PHASE             0x0524
+#define DCCG_AUDIO_DTO1_MODULE            0x0528
+#define DCCG_AUDIO_DTO1_LOAD              0x052c
+#define DCCG_AUDIO_DTO1_CNTL              0x0530
+
+#define DCCG_AUDIO_DTO_SELECT             0x0534
+
+/* digital blocks */
+#define TMDSA_CNTL                       0x7880
+#       define TMDSA_HDMI_EN             (1 << 2)
+#define LVTMA_CNTL                       0x7a80
+#       define LVTMA_HDMI_EN             (1 << 2)
+#define DDIA_CNTL                        0x7200
+#       define DDIA_HDMI_EN              (1 << 2)
+#define DIG0_CNTL                        0x75a0
+#       define DIG_MODE(x)               (((x) & 7) << 8)
+#       define DIG_MODE_DP               0
+#       define DIG_MODE_LVDS             1
+#       define DIG_MODE_TMDS_DVI         2
+#       define DIG_MODE_TMDS_HDMI        3
+#       define DIG_MODE_SDVO             4
+#define DIG1_CNTL                        0x79a0
+
+/* rs6xx/rs740 and r6xx share the same HDMI blocks, however, rs6xx has only one
+ * instance of the blocks while r6xx has 2.  DCE 3.0 cards are slightly
+ * different due to the new DIG blocks, but also have 2 instances.
+ * DCE 3.0 HDMI blocks are part of each DIG encoder.
+ */
+
+/* rs6xx/rs740/r6xx/dce3 */
+#define HDMI0_CONTROL                0x7400
+/* rs6xx/rs740/r6xx */
+#       define HDMI0_ENABLE          (1 << 0)
+#       define HDMI0_STREAM(x)       (((x) & 3) << 2)
+#       define HDMI0_STREAM_TMDSA    0
+#       define HDMI0_STREAM_LVTMA    1
+#       define HDMI0_STREAM_DVOA     2
+#       define HDMI0_STREAM_DDIA     3
+/* rs6xx/r6xx/dce3 */
+#       define HDMI0_ERROR_ACK       (1 << 8)
+#       define HDMI0_ERROR_MASK      (1 << 9)
+#define HDMI0_STATUS                 0x7404
+#       define HDMI0_ACTIVE_AVMUTE   (1 << 0)
+#       define HDMI0_AUDIO_ENABLE    (1 << 4)
+#       define HDMI0_AZ_FORMAT_WTRIG     (1 << 28)
+#       define HDMI0_AZ_FORMAT_WTRIG_INT (1 << 29)
+#define HDMI0_AUDIO_PACKET_CONTROL   0x7408
+#       define HDMI0_AUDIO_SAMPLE_SEND  (1 << 0)
+#       define HDMI0_AUDIO_DELAY_EN(x)  (((x) & 3) << 4)
+#       define HDMI0_AUDIO_SEND_MAX_PACKETS  (1 << 8)
+#       define HDMI0_AUDIO_TEST_EN         (1 << 12)
+#       define HDMI0_AUDIO_PACKETS_PER_LINE(x)  (((x) & 0x1f) << 16)
+#       define HDMI0_AUDIO_CHANNEL_SWAP    (1 << 24)
+#       define HDMI0_60958_CS_UPDATE       (1 << 26)
+#       define HDMI0_AZ_FORMAT_WTRIG_MASK  (1 << 28)
+#       define HDMI0_AZ_FORMAT_WTRIG_ACK   (1 << 29)
+#define HDMI0_AUDIO_CRC_CONTROL      0x740c
+#       define HDMI0_AUDIO_CRC_EN    (1 << 0)
+#define HDMI0_VBI_PACKET_CONTROL     0x7410
+#       define HDMI0_NULL_SEND       (1 << 0)
+#       define HDMI0_GC_SEND         (1 << 4)
+#       define HDMI0_GC_CONT         (1 << 5) /* 0 - once; 1 - every frame */
+#define HDMI0_INFOFRAME_CONTROL0     0x7414
+#       define HDMI0_AVI_INFO_SEND   (1 << 0)
+#       define HDMI0_AVI_INFO_CONT   (1 << 1)
+#       define HDMI0_AUDIO_INFO_SEND (1 << 4)
+#       define HDMI0_AUDIO_INFO_CONT (1 << 5)
+#       define HDMI0_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hmdi regs */
+#       define HDMI0_AUDIO_INFO_UPDATE (1 << 7)
+#       define HDMI0_MPEG_INFO_SEND  (1 << 8)
+#       define HDMI0_MPEG_INFO_CONT  (1 << 9)
+#       define HDMI0_MPEG_INFO_UPDATE  (1 << 10)
+#define HDMI0_INFOFRAME_CONTROL1     0x7418
+#       define HDMI0_AVI_INFO_LINE(x)  (((x) & 0x3f) << 0)
+#       define HDMI0_AUDIO_INFO_LINE(x)  (((x) & 0x3f) << 8)
+#       define HDMI0_MPEG_INFO_LINE(x)  (((x) & 0x3f) << 16)
+#define HDMI0_GENERIC_PACKET_CONTROL 0x741c
+#       define HDMI0_GENERIC0_SEND   (1 << 0)
+#       define HDMI0_GENERIC0_CONT   (1 << 1)
+#       define HDMI0_GENERIC0_UPDATE (1 << 2)
+#       define HDMI0_GENERIC1_SEND   (1 << 4)
+#       define HDMI0_GENERIC1_CONT   (1 << 5)
+#       define HDMI0_GENERIC0_LINE(x)  (((x) & 0x3f) << 16)
+#       define HDMI0_GENERIC1_LINE(x)  (((x) & 0x3f) << 24)
+#define HDMI0_GC                     0x7428
+#       define HDMI0_GC_AVMUTE       (1 << 0)
+#define HDMI0_AVI_INFO0              0x7454
+#       define HDMI0_AVI_INFO_CHECKSUM(x)  (((x) & 0xff) << 0)
+#       define HDMI0_AVI_INFO_S(x)   (((x) & 3) << 8)
+#       define HDMI0_AVI_INFO_B(x)   (((x) & 3) << 10)
+#       define HDMI0_AVI_INFO_A(x)   (((x) & 1) << 12)
+#       define HDMI0_AVI_INFO_Y(x)   (((x) & 3) << 13)
+#       define HDMI0_AVI_INFO_Y_RGB       0
+#       define HDMI0_AVI_INFO_Y_YCBCR422  1
+#       define HDMI0_AVI_INFO_Y_YCBCR444  2
+#       define HDMI0_AVI_INFO_Y_A_B_S(x)   (((x) & 0xff) << 8)
+#       define HDMI0_AVI_INFO_R(x)   (((x) & 0xf) << 16)
+#       define HDMI0_AVI_INFO_M(x)   (((x) & 0x3) << 20)
+#       define HDMI0_AVI_INFO_C(x)   (((x) & 0x3) << 22)
+#       define HDMI0_AVI_INFO_C_M_R(x)   (((x) & 0xff) << 16)
+#       define HDMI0_AVI_INFO_SC(x)  (((x) & 0x3) << 24)
+#       define HDMI0_AVI_INFO_ITC_EC_Q_SC(x)  (((x) & 0xff) << 24)
+#define HDMI0_AVI_INFO1              0x7458
+#       define HDMI0_AVI_INFO_VIC(x) (((x) & 0x7f) << 0) /* don't use avi infoframe v1 */
+#       define HDMI0_AVI_INFO_PR(x)  (((x) & 0xf) << 8) /* don't use avi infoframe v1 */
+#       define HDMI0_AVI_INFO_TOP(x) (((x) & 0xffff) << 16)
+#define HDMI0_AVI_INFO2              0x745c
+#       define HDMI0_AVI_INFO_BOTTOM(x)  (((x) & 0xffff) << 0)
+#       define HDMI0_AVI_INFO_LEFT(x)    (((x) & 0xffff) << 16)
+#define HDMI0_AVI_INFO3              0x7460
+#       define HDMI0_AVI_INFO_RIGHT(x)    (((x) & 0xffff) << 0)
+#       define HDMI0_AVI_INFO_VERSION(x)  (((x) & 3) << 24)
+#define HDMI0_MPEG_INFO0             0x7464
+#       define HDMI0_MPEG_INFO_CHECKSUM(x)  (((x) & 0xff) << 0)
+#       define HDMI0_MPEG_INFO_MB0(x)  (((x) & 0xff) << 8)
+#       define HDMI0_MPEG_INFO_MB1(x)  (((x) & 0xff) << 16)
+#       define HDMI0_MPEG_INFO_MB2(x)  (((x) & 0xff) << 24)
+#define HDMI0_MPEG_INFO1             0x7468
+#       define HDMI0_MPEG_INFO_MB3(x)  (((x) & 0xff) << 0)
+#       define HDMI0_MPEG_INFO_MF(x)   (((x) & 3) << 8)
+#       define HDMI0_MPEG_INFO_FR(x)   (((x) & 1) << 12)
+#define HDMI0_GENERIC0_HDR           0x746c
+#define HDMI0_GENERIC0_0             0x7470
+#define HDMI0_GENERIC0_1             0x7474
+#define HDMI0_GENERIC0_2             0x7478
+#define HDMI0_GENERIC0_3             0x747c
+#define HDMI0_GENERIC0_4             0x7480
+#define HDMI0_GENERIC0_5             0x7484
+#define HDMI0_GENERIC0_6             0x7488
+#define HDMI0_GENERIC1_HDR           0x748c
+#define HDMI0_GENERIC1_0             0x7490
+#define HDMI0_GENERIC1_1             0x7494
+#define HDMI0_GENERIC1_2             0x7498
+#define HDMI0_GENERIC1_3             0x749c
+#define HDMI0_GENERIC1_4             0x74a0
+#define HDMI0_GENERIC1_5             0x74a4
+#define HDMI0_GENERIC1_6             0x74a8
+#define HDMI0_ACR_32_0               0x74ac
+#       define HDMI0_ACR_CTS_32(x)   (((x) & 0xfffff) << 12)
+#define HDMI0_ACR_32_1               0x74b0
+#       define HDMI0_ACR_N_32(x)   (((x) & 0xfffff) << 0)
+#define HDMI0_ACR_44_0               0x74b4
+#       define HDMI0_ACR_CTS_44(x)   (((x) & 0xfffff) << 12)
+#define HDMI0_ACR_44_1               0x74b8
+#       define HDMI0_ACR_N_44(x)   (((x) & 0xfffff) << 0)
+#define HDMI0_ACR_48_0               0x74bc
+#       define HDMI0_ACR_CTS_48(x)   (((x) & 0xfffff) << 12)
+#define HDMI0_ACR_48_1               0x74c0
+#       define HDMI0_ACR_N_48(x)   (((x) & 0xfffff) << 0)
+#define HDMI0_ACR_STATUS_0           0x74c4
+#define HDMI0_ACR_STATUS_1           0x74c8
+#define HDMI0_AUDIO_INFO0            0x74cc
+#       define HDMI0_AUDIO_INFO_CHECKSUM(x)  (((x) & 0xff) << 0)
+#       define HDMI0_AUDIO_INFO_CC(x)  (((x) & 7) << 8)
+#define HDMI0_AUDIO_INFO1            0x74d0
+#       define HDMI0_AUDIO_INFO_CA(x)  (((x) & 0xff) << 0)
+#       define HDMI0_AUDIO_INFO_LSV(x)  (((x) & 0xf) << 11)
+#       define HDMI0_AUDIO_INFO_DM_INH(x)  (((x) & 1) << 15)
+#       define HDMI0_AUDIO_INFO_DM_INH_LSV(x)  (((x) & 0xff) << 8)
+#define HDMI0_60958_0                0x74d4
+#       define HDMI0_60958_CS_A(x)   (((x) & 1) << 0)
+#       define HDMI0_60958_CS_B(x)   (((x) & 1) << 1)
+#       define HDMI0_60958_CS_C(x)   (((x) & 1) << 2)
+#       define HDMI0_60958_CS_D(x)   (((x) & 3) << 3)
+#       define HDMI0_60958_CS_MODE(x)   (((x) & 3) << 6)
+#       define HDMI0_60958_CS_CATEGORY_CODE(x)      (((x) & 0xff) << 8)
+#       define HDMI0_60958_CS_SOURCE_NUMBER(x)      (((x) & 0xf) << 16)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_L(x)   (((x) & 0xf) << 20)
+#       define HDMI0_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24)
+#       define HDMI0_60958_CS_CLOCK_ACCURACY(x)     (((x) & 3) << 28)
+#define HDMI0_60958_1                0x74d8
+#       define HDMI0_60958_CS_WORD_LENGTH(x)        (((x) & 0xf) << 0)
+#       define HDMI0_60958_CS_ORIGINAL_SAMPLING_FREQUENCY(x)   (((x) & 0xf) << 4)
+#       define HDMI0_60958_CS_VALID_L(x)   (((x) & 1) << 16)
+#       define HDMI0_60958_CS_VALID_R(x)   (((x) & 1) << 18)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_R(x)   (((x) & 0xf) << 20)
+#define HDMI0_ACR_PACKET_CONTROL     0x74dc
+#       define HDMI0_ACR_SEND        (1 << 0)
+#       define HDMI0_ACR_CONT        (1 << 1)
+#       define HDMI0_ACR_SELECT(x)   (((x) & 3) << 4)
+#       define HDMI0_ACR_HW          0
+#       define HDMI0_ACR_32          1
+#       define HDMI0_ACR_44          2
+#       define HDMI0_ACR_48          3
+#       define HDMI0_ACR_SOURCE      (1 << 8) /* 0 - hw; 1 - cts value */
+#       define HDMI0_ACR_AUTO_SEND   (1 << 12)
+#define HDMI0_RAMP_CONTROL0          0x74e0
+#       define HDMI0_RAMP_MAX_COUNT(x)   (((x) & 0xffffff) << 0)
+#define HDMI0_RAMP_CONTROL1          0x74e4
+#       define HDMI0_RAMP_MIN_COUNT(x)   (((x) & 0xffffff) << 0)
+#define HDMI0_RAMP_CONTROL2          0x74e8
+#       define HDMI0_RAMP_INC_COUNT(x)   (((x) & 0xffffff) << 0)
+#define HDMI0_RAMP_CONTROL3          0x74ec
+#       define HDMI0_RAMP_DEC_COUNT(x)   (((x) & 0xffffff) << 0)
+/* HDMI0_60958_2 is r7xx only */
+#define HDMI0_60958_2                0x74f0
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_2(x)   (((x) & 0xf) << 0)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_3(x)   (((x) & 0xf) << 4)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_4(x)   (((x) & 0xf) << 8)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_5(x)   (((x) & 0xf) << 12)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_6(x)   (((x) & 0xf) << 16)
+#       define HDMI0_60958_CS_CHANNEL_NUMBER_7(x)   (((x) & 0xf) << 20)
+/* r6xx only; second instance starts at 0x7700 */
+#define HDMI1_CONTROL                0x7700
+#define HDMI1_STATUS                 0x7704
+#define HDMI1_AUDIO_PACKET_CONTROL   0x7708
+/* DCE3; second instance starts at 0x7800 NOT 0x7700 */
+#define DCE3_HDMI1_CONTROL                0x7800
+#define DCE3_HDMI1_STATUS                 0x7804
+#define DCE3_HDMI1_AUDIO_PACKET_CONTROL   0x7808
+/* DCE3.2 (for interrupts) */
+#define AFMT_STATUS                          0x7600
+#       define AFMT_AUDIO_ENABLE             (1 << 4)
+#       define AFMT_AZ_FORMAT_WTRIG          (1 << 28)
+#       define AFMT_AZ_FORMAT_WTRIG_INT      (1 << 29)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG      (1 << 30)
+#define AFMT_AUDIO_PACKET_CONTROL            0x7604
+#       define AFMT_AUDIO_SAMPLE_SEND        (1 << 0)
+#       define AFMT_AUDIO_TEST_EN            (1 << 12)
+#       define AFMT_AUDIO_CHANNEL_SWAP       (1 << 24)
+#       define AFMT_60958_CS_UPDATE          (1 << 26)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG_MASK (1 << 27)
+#       define AFMT_AZ_FORMAT_WTRIG_MASK     (1 << 28)
+#       define AFMT_AZ_FORMAT_WTRIG_ACK      (1 << 29)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG_ACK  (1 << 30)
+
+#define DCE2_HDMI_OFFSET0              (0x7400 - 0x7400)
+#define DCE2_HDMI_OFFSET1              (0x7700 - 0x7400)
+/* DCE3.2 second instance starts at 0x7800 */
+#define DCE3_HDMI_OFFSET0              (0x7400 - 0x7400)
+#define DCE3_HDMI_OFFSET1              (0x7800 - 0x7400)
+
 /*
  * PM4
  */
index 138b95216d8d0c469a9924e6d272b31b97fda34e..60233d7a6f7dd21c8b95628c0d3625945a880b63 100644 (file)
@@ -94,33 +94,38 @@ extern int radeon_disp_priority;
 extern int radeon_hw_i2c;
 extern int radeon_pcie_gen2;
 extern int radeon_msi;
+extern int radeon_lockup_timeout;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
  * symbol;
  */
-#define RADEON_MAX_USEC_TIMEOUT                100000  /* 100 ms */
-#define RADEON_FENCE_JIFFIES_TIMEOUT   (HZ / 2)
+#define RADEON_MAX_USEC_TIMEOUT                        100000  /* 100 ms */
+#define RADEON_FENCE_JIFFIES_TIMEOUT           (HZ / 2)
 /* RADEON_IB_POOL_SIZE must be a power of 2 */
-#define RADEON_IB_POOL_SIZE            16
-#define RADEON_DEBUGFS_MAX_COMPONENTS  32
-#define RADEONFB_CONN_LIMIT            4
-#define RADEON_BIOS_NUM_SCRATCH                8
+#define RADEON_IB_POOL_SIZE                    16
+#define RADEON_DEBUGFS_MAX_COMPONENTS          32
+#define RADEONFB_CONN_LIMIT                    4
+#define RADEON_BIOS_NUM_SCRATCH                        8
 
 /* max number of rings */
-#define RADEON_NUM_RINGS 3
+#define RADEON_NUM_RINGS                       3
+
+/* fence seq are set to this number when signaled */
+#define RADEON_FENCE_SIGNALED_SEQ              0LL
+#define RADEON_FENCE_NOTEMITED_SEQ             (~0LL)
 
 /* internal ring indices */
 /* r1xx+ has gfx CP ring */
-#define RADEON_RING_TYPE_GFX_INDEX  0
+#define RADEON_RING_TYPE_GFX_INDEX             0
 
 /* cayman has 2 compute CP rings */
-#define CAYMAN_RING_TYPE_CP1_INDEX 1
-#define CAYMAN_RING_TYPE_CP2_INDEX 2
+#define CAYMAN_RING_TYPE_CP1_INDEX             1
+#define CAYMAN_RING_TYPE_CP2_INDEX             2
 
 /* hardcode those limit for now */
-#define RADEON_VA_RESERVED_SIZE                (8 << 20)
-#define RADEON_IB_VM_MAX_SIZE          (64 << 10)
+#define RADEON_VA_RESERVED_SIZE                        (8 << 20)
+#define RADEON_IB_VM_MAX_SIZE                  (64 << 10)
 
 /*
  * Errata workarounds.
@@ -253,28 +258,20 @@ struct radeon_fence_driver {
        uint32_t                        scratch_reg;
        uint64_t                        gpu_addr;
        volatile uint32_t               *cpu_addr;
-       atomic_t                        seq;
-       uint32_t                        last_seq;
-       unsigned long                   last_jiffies;
-       unsigned long                   last_timeout;
-       wait_queue_head_t               queue;
-       struct list_head                created;
-       struct list_head                emitted;
-       struct list_head                signaled;
+       /* seq is protected by ring emission lock */
+       uint64_t                        seq;
+       atomic64_t                      last_seq;
+       unsigned long                   last_activity;
        bool                            initialized;
 };
 
 struct radeon_fence {
        struct radeon_device            *rdev;
        struct kref                     kref;
-       struct list_head                list;
        /* protected by radeon_fence.lock */
-       uint32_t                        seq;
-       bool                            emitted;
-       bool                            signaled;
+       uint64_t                        seq;
        /* RB, DMA, etc. */
-       int                             ring;
-       struct radeon_semaphore         *semaphore;
+       unsigned                        ring;
 };
 
 int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
@@ -285,11 +282,14 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence);
 void radeon_fence_process(struct radeon_device *rdev, int ring);
 bool radeon_fence_signaled(struct radeon_fence *fence);
 int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
-int radeon_fence_wait_next(struct radeon_device *rdev, int ring);
-int radeon_fence_wait_last(struct radeon_device *rdev, int ring);
+int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring);
+int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
+int radeon_fence_wait_any(struct radeon_device *rdev,
+                         struct radeon_fence **fences,
+                         bool intr);
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
-int radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
+unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring);
 
 /*
  * Tiling registers
@@ -382,8 +382,11 @@ struct radeon_bo_list {
  * alignment).
  */
 struct radeon_sa_manager {
+       spinlock_t              lock;
        struct radeon_bo        *bo;
-       struct list_head        sa_bo;
+       struct list_head        *hole;
+       struct list_head        flist[RADEON_NUM_RINGS];
+       struct list_head        olist;
        unsigned                size;
        uint64_t                gpu_addr;
        void                    *cpu_ptr;
@@ -394,10 +397,12 @@ struct radeon_sa_bo;
 
 /* sub-allocation buffer */
 struct radeon_sa_bo {
-       struct list_head                list;
+       struct list_head                olist;
+       struct list_head                flist;
        struct radeon_sa_manager        *manager;
-       unsigned                        offset;
-       unsigned                        size;
+       unsigned                        soffset;
+       unsigned                        eoffset;
+       struct radeon_fence             *fence;
 };
 
 /*
@@ -428,42 +433,26 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv,
 /*
  * Semaphores.
  */
-struct radeon_ring;
-
-#define        RADEON_SEMAPHORE_BO_SIZE        256
-
-struct radeon_semaphore_driver {
-       rwlock_t                        lock;
-       struct list_head                bo;
-};
-
-struct radeon_semaphore_bo;
-
 /* everything here is constant */
 struct radeon_semaphore {
-       struct list_head                list;
+       struct radeon_sa_bo             *sa_bo;
+       signed                          waiters;
        uint64_t                        gpu_addr;
-       uint32_t                        *cpu_ptr;
-       struct radeon_semaphore_bo      *bo;
-};
-
-struct radeon_semaphore_bo {
-       struct list_head                list;
-       struct radeon_ib                *ib;
-       struct list_head                free;
-       struct radeon_semaphore         semaphores[RADEON_SEMAPHORE_BO_SIZE/8];
-       unsigned                        nused;
 };
 
-void radeon_semaphore_driver_fini(struct radeon_device *rdev);
 int radeon_semaphore_create(struct radeon_device *rdev,
                            struct radeon_semaphore **semaphore);
 void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
                                  struct radeon_semaphore *semaphore);
 void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
                                struct radeon_semaphore *semaphore);
+int radeon_semaphore_sync_rings(struct radeon_device *rdev,
+                               struct radeon_semaphore *semaphore,
+                               bool sync_to[RADEON_NUM_RINGS],
+                               int dst_ring);
 void radeon_semaphore_free(struct radeon_device *rdev,
-                          struct radeon_semaphore *semaphore);
+                          struct radeon_semaphore *semaphore,
+                          struct radeon_fence *fence);
 
 /*
  * GART structures, functions & helpers
@@ -560,6 +549,7 @@ struct radeon_unpin_work {
 
 struct r500_irq_stat_regs {
        u32 disp_int;
+       u32 hdmi0_status;
 };
 
 struct r600_irq_stat_regs {
@@ -568,6 +558,8 @@ struct r600_irq_stat_regs {
        u32 disp_int_cont2;
        u32 d1grph_int;
        u32 d2grph_int;
+       u32 hdmi0_status;
+       u32 hdmi1_status;
 };
 
 struct evergreen_irq_stat_regs {
@@ -583,6 +575,12 @@ struct evergreen_irq_stat_regs {
        u32 d4grph_int;
        u32 d5grph_int;
        u32 d6grph_int;
+       u32 afmt_status1;
+       u32 afmt_status2;
+       u32 afmt_status3;
+       u32 afmt_status4;
+       u32 afmt_status5;
+       u32 afmt_status6;
 };
 
 union radeon_irq_stat_regs {
@@ -593,7 +591,7 @@ union radeon_irq_stat_regs {
 
 #define RADEON_MAX_HPD_PINS 6
 #define RADEON_MAX_CRTCS 6
-#define RADEON_MAX_HDMI_BLOCKS 2
+#define RADEON_MAX_AFMT_BLOCKS 6
 
 struct radeon_irq {
        bool            installed;
@@ -605,7 +603,7 @@ struct radeon_irq {
        bool            gui_idle;
        bool            gui_idle_acked;
        wait_queue_head_t       idle_queue;
-       bool            hdmi[RADEON_MAX_HDMI_BLOCKS];
+       bool            afmt[RADEON_MAX_AFMT_BLOCKS];
        spinlock_t sw_lock;
        int sw_refcount[RADEON_NUM_RINGS];
        union radeon_irq_stat_regs stat_regs;
@@ -625,26 +623,14 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc);
  */
 
 struct radeon_ib {
-       struct radeon_sa_bo     sa_bo;
-       unsigned                idx;
-       uint32_t                length_dw;
-       uint64_t                gpu_addr;
-       uint32_t                *ptr;
-       struct radeon_fence     *fence;
-       unsigned                vm_id;
-       bool                    is_const_ib;
-};
-
-/*
- * locking -
- * mutex protects scheduled_ibs, ready, alloc_bm
- */
-struct radeon_ib_pool {
-       struct radeon_mutex             mutex;
-       struct radeon_sa_manager        sa_manager;
-       struct radeon_ib                ibs[RADEON_IB_POOL_SIZE];
-       bool                            ready;
-       unsigned                        head_id;
+       struct radeon_sa_bo             *sa_bo;
+       uint32_t                        length_dw;
+       uint64_t                        gpu_addr;
+       uint32_t                        *ptr;
+       struct radeon_fence             *fence;
+       unsigned                        vm_id;
+       bool                            is_const_ib;
+       struct radeon_semaphore         *semaphore;
 };
 
 struct radeon_ring {
@@ -659,10 +645,11 @@ struct radeon_ring {
        unsigned                ring_size;
        unsigned                ring_free_dw;
        int                     count_dw;
+       unsigned long           last_activity;
+       unsigned                last_rptr;
        uint64_t                gpu_addr;
        uint32_t                align_mask;
        uint32_t                ptr_mask;
-       struct mutex            mutex;
        bool                    ready;
        u32                     ptr_reg_shift;
        u32                     ptr_reg_mask;
@@ -679,7 +666,7 @@ struct radeon_vm {
        unsigned                        last_pfn;
        u64                             pt_gpu_addr;
        u64                             *pt;
-       struct radeon_sa_bo             sa_bo;
+       struct radeon_sa_bo             *sa_bo;
        struct mutex                    mutex;
        /* last fence for cs using this vm */
        struct radeon_fence             *fence;
@@ -756,7 +743,6 @@ struct r600_blit_cp_primitives {
 };
 
 struct r600_blit {
-       struct mutex            mutex;
        struct radeon_bo        *shader_obj;
        struct r600_blit_cp_primitives primitives;
        int max_dim;
@@ -766,8 +752,6 @@ struct r600_blit {
        u32 vs_offset, ps_offset;
        u32 state_offset;
        u32 state_len;
-       u32 vb_used, vb_total;
-       struct radeon_ib *vb_ib;
 };
 
 void r600_blit_suspend(struct radeon_device *rdev);
@@ -785,14 +769,14 @@ struct si_rlc {
 };
 
 int radeon_ib_get(struct radeon_device *rdev, int ring,
-                 struct radeon_ib **ib, unsigned size);
-void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
-bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib);
+                 struct radeon_ib *ib, unsigned size);
+void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
 int radeon_ib_pool_init(struct radeon_device *rdev);
 void radeon_ib_pool_fini(struct radeon_device *rdev);
 int radeon_ib_pool_start(struct radeon_device *rdev);
 int radeon_ib_pool_suspend(struct radeon_device *rdev);
+int radeon_ib_ring_tests(struct radeon_device *rdev);
 /* Ring access between begin & end cannot sleep */
 int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *cp);
 void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp);
@@ -800,8 +784,12 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsign
 int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw);
 void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp);
 void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp);
+void radeon_ring_undo(struct radeon_ring *ring);
 void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp);
 int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp);
+void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring);
+void radeon_ring_lockup_update(struct radeon_ring *ring);
+bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
 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 ptr_reg_shift, u32 ptr_reg_mask, u32 nop);
@@ -850,8 +838,8 @@ struct radeon_cs_parser {
        int                     chunk_relocs_idx;
        int                     chunk_flags_idx;
        int                     chunk_const_ib_idx;
-       struct radeon_ib        *ib;
-       struct radeon_ib        *const_ib;
+       struct radeon_ib        ib;
+       struct radeon_ib        const_ib;
        void                    *track;
        unsigned                family;
        int                     parser_error;
@@ -1105,6 +1093,15 @@ int radeon_pm_get_type_index(struct radeon_device *rdev,
                             enum radeon_pm_state_type ps_type,
                             int instance);
 
+struct r600_audio {
+       bool                    enabled;
+       int                     channels;
+       int                     rate;
+       int                     bits_per_sample;
+       u8                      status_bits;
+       u8                      category_code;
+};
+
 /*
  * Benchmarking
  */
@@ -1144,7 +1141,6 @@ struct radeon_asic {
        int (*resume)(struct radeon_device *rdev);
        int (*suspend)(struct radeon_device *rdev);
        void (*vga_set_state)(struct radeon_device *rdev, bool state);
-       bool (*gpu_is_lockup)(struct radeon_device *rdev, struct radeon_ring *cp);
        int (*asic_reset)(struct radeon_device *rdev);
        /* ioctl hw specific callback. Some hw might want to perform special
         * operation on specific ioctl. For instance on wait idle some hw
@@ -1173,6 +1169,7 @@ struct radeon_asic {
                void (*ring_start)(struct radeon_device *rdev, struct radeon_ring *cp);
                int (*ring_test)(struct radeon_device *rdev, struct radeon_ring *cp);
                int (*ib_test)(struct radeon_device *rdev, struct radeon_ring *cp);
+               bool (*is_lockup)(struct radeon_device *rdev, struct radeon_ring *cp);
        } ring[RADEON_NUM_RINGS];
        /* irqs */
        struct {
@@ -1251,16 +1248,10 @@ struct radeon_asic {
 /*
  * Asic structures
  */
-struct r100_gpu_lockup {
-       unsigned long   last_jiffies;
-       u32             last_cp_rptr;
-};
-
 struct r100_asic {
        const unsigned          *reg_safe_bm;
        unsigned                reg_safe_bm_size;
        u32                     hdp_cntl;
-       struct r100_gpu_lockup  lockup;
 };
 
 struct r300_asic {
@@ -1268,7 +1259,6 @@ struct r300_asic {
        unsigned                reg_safe_bm_size;
        u32                     resync_scratch;
        u32                     hdp_cntl;
-       struct r100_gpu_lockup  lockup;
 };
 
 struct r600_asic {
@@ -1290,7 +1280,6 @@ struct r600_asic {
        unsigned                tiling_group_size;
        unsigned                tile_config;
        unsigned                backend_map;
-       struct r100_gpu_lockup  lockup;
 };
 
 struct rv770_asic {
@@ -1316,7 +1305,6 @@ struct rv770_asic {
        unsigned                tiling_group_size;
        unsigned                tile_config;
        unsigned                backend_map;
-       struct r100_gpu_lockup  lockup;
 };
 
 struct evergreen_asic {
@@ -1343,7 +1331,6 @@ struct evergreen_asic {
        unsigned tiling_group_size;
        unsigned tile_config;
        unsigned backend_map;
-       struct r100_gpu_lockup  lockup;
 };
 
 struct cayman_asic {
@@ -1382,7 +1369,6 @@ struct cayman_asic {
        unsigned multi_gpu_tile_size;
 
        unsigned tile_config;
-       struct r100_gpu_lockup  lockup;
 };
 
 struct si_asic {
@@ -1413,7 +1399,6 @@ struct si_asic {
        unsigned multi_gpu_tile_size;
 
        unsigned tile_config;
-       struct r100_gpu_lockup  lockup;
 };
 
 union radeon_asic_config {
@@ -1516,11 +1501,12 @@ struct radeon_device {
        struct radeon_mode_info         mode_info;
        struct radeon_scratch           scratch;
        struct radeon_mman              mman;
-       rwlock_t                        fence_lock;
        struct radeon_fence_driver      fence_drv[RADEON_NUM_RINGS];
-       struct radeon_semaphore_driver  semaphore_drv;
+       wait_queue_head_t               fence_queue;
+       struct mutex                    ring_lock;
        struct radeon_ring              ring[RADEON_NUM_RINGS];
-       struct radeon_ib_pool           ib_pool;
+       bool                            ib_pool_ready;
+       struct radeon_sa_manager        ring_tmp_bo;
        struct radeon_irq               irq;
        struct radeon_asic              *asic;
        struct radeon_gem               gem;
@@ -1529,7 +1515,6 @@ struct radeon_device {
        struct radeon_mutex             cs_mutex;
        struct radeon_wb                wb;
        struct radeon_dummy_page        dummy_page;
-       bool                            gpu_lockup;
        bool                            shutdown;
        bool                            suspend;
        bool                            need_dma32;
@@ -1546,19 +1531,11 @@ struct radeon_device {
        struct r600_ih ih; /* r6/700 interrupt ring */
        struct si_rlc rlc;
        struct work_struct hotplug_work;
+       struct work_struct audio_work;
        int num_crtc; /* number of crtcs */
        struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
        struct mutex vram_mutex;
-
-       /* audio stuff */
-       bool                    audio_enabled;
-       struct timer_list       audio_timer;
-       int                     audio_channels;
-       int                     audio_rate;
-       int                     audio_bits_per_sample;
-       uint8_t                 audio_status_bits;
-       uint8_t                 audio_category_code;
-
+       struct r600_audio audio; /* audio stuff */
        struct notifier_block acpi_nb;
        /* only one userspace can use Hyperz features or CMASK at a time */
        struct drm_file *hyperz_filp;
@@ -1730,7 +1707,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
 #define radeon_cs_parse(rdev, r, p) (rdev)->asic->ring[(r)].cs_parse((p))
 #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
-#define radeon_gpu_is_lockup(rdev, cp) (rdev)->asic->gpu_is_lockup((rdev), (cp))
 #define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev))
 #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev))
 #define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart.set_page((rdev), (i), (p))
@@ -1739,6 +1715,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_ib_test(rdev, r, cp) (rdev)->asic->ring[(r)].ib_test((rdev), (cp))
 #define radeon_ring_ib_execute(rdev, r, ib) (rdev)->asic->ring[(r)].ib_execute((rdev), (ib))
 #define radeon_ring_ib_parse(rdev, r, ib) (rdev)->asic->ring[(r)].ib_parse((rdev), (ib))
+#define radeon_ring_is_lockup(rdev, r, cp) (rdev)->asic->ring[(r)].is_lockup((rdev), (cp))
 #define radeon_irq_set(rdev) (rdev)->asic->irq.set((rdev))
 #define radeon_irq_process(rdev) (rdev)->asic->irq.process((rdev))
 #define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->display.get_vblank_counter((rdev), (crtc))
@@ -1828,6 +1805,8 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
                     struct radeon_vm *vm,
                     struct radeon_bo *bo);
 
+/* audio */
+void r600_audio_update_hdmi(struct work_struct *work);
 
 /*
  * R600 vram scratch functions
index be4dc2ff0e40f4bfadef1e3085bc5a8ab1b3532f..f533df5f7d508a671d5f35c505d6af7327569b66 100644 (file)
@@ -134,7 +134,6 @@ static struct radeon_asic r100_asic = {
        .suspend = &r100_suspend,
        .resume = &r100_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r100_gpu_is_lockup,
        .asic_reset = &r100_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -152,6 +151,7 @@ static struct radeon_asic r100_asic = {
                        .ring_start = &r100_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -208,7 +208,6 @@ static struct radeon_asic r200_asic = {
        .suspend = &r100_suspend,
        .resume = &r100_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r100_gpu_is_lockup,
        .asic_reset = &r100_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -226,6 +225,7 @@ static struct radeon_asic r200_asic = {
                        .ring_start = &r100_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -282,7 +282,6 @@ static struct radeon_asic r300_asic = {
        .suspend = &r300_suspend,
        .resume = &r300_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r300_gpu_is_lockup,
        .asic_reset = &r300_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -300,6 +299,7 @@ static struct radeon_asic r300_asic = {
                        .ring_start = &r300_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -356,7 +356,6 @@ static struct radeon_asic r300_asic_pcie = {
        .suspend = &r300_suspend,
        .resume = &r300_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r300_gpu_is_lockup,
        .asic_reset = &r300_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -374,6 +373,7 @@ static struct radeon_asic r300_asic_pcie = {
                        .ring_start = &r300_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -430,7 +430,6 @@ static struct radeon_asic r420_asic = {
        .suspend = &r420_suspend,
        .resume = &r420_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r300_gpu_is_lockup,
        .asic_reset = &r300_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -448,6 +447,7 @@ static struct radeon_asic r420_asic = {
                        .ring_start = &r300_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -504,7 +504,6 @@ static struct radeon_asic rs400_asic = {
        .suspend = &rs400_suspend,
        .resume = &rs400_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r300_gpu_is_lockup,
        .asic_reset = &r300_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -522,6 +521,7 @@ static struct radeon_asic rs400_asic = {
                        .ring_start = &r300_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -578,7 +578,6 @@ static struct radeon_asic rs600_asic = {
        .suspend = &rs600_suspend,
        .resume = &rs600_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r300_gpu_is_lockup,
        .asic_reset = &rs600_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -596,6 +595,7 @@ static struct radeon_asic rs600_asic = {
                        .ring_start = &r300_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -652,7 +652,6 @@ static struct radeon_asic rs690_asic = {
        .suspend = &rs690_suspend,
        .resume = &rs690_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r300_gpu_is_lockup,
        .asic_reset = &rs600_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -670,6 +669,7 @@ static struct radeon_asic rs690_asic = {
                        .ring_start = &r300_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -726,7 +726,6 @@ static struct radeon_asic rv515_asic = {
        .suspend = &rv515_suspend,
        .resume = &rv515_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r300_gpu_is_lockup,
        .asic_reset = &rs600_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -744,6 +743,7 @@ static struct radeon_asic rv515_asic = {
                        .ring_start = &rv515_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -800,7 +800,6 @@ static struct radeon_asic r520_asic = {
        .suspend = &rv515_suspend,
        .resume = &r520_resume,
        .vga_set_state = &r100_vga_set_state,
-       .gpu_is_lockup = &r300_gpu_is_lockup,
        .asic_reset = &rs600_asic_reset,
        .ioctl_wait_idle = NULL,
        .gui_idle = &r100_gui_idle,
@@ -818,6 +817,7 @@ static struct radeon_asic r520_asic = {
                        .ring_start = &rv515_ring_start,
                        .ring_test = &r100_ring_test,
                        .ib_test = &r100_ib_test,
+                       .is_lockup = &r100_gpu_is_lockup,
                }
        },
        .irq = {
@@ -874,7 +874,6 @@ static struct radeon_asic r600_asic = {
        .suspend = &r600_suspend,
        .resume = &r600_resume,
        .vga_set_state = &r600_vga_set_state,
-       .gpu_is_lockup = &r600_gpu_is_lockup,
        .asic_reset = &r600_asic_reset,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
        .gui_idle = &r600_gui_idle,
@@ -891,6 +890,7 @@ static struct radeon_asic r600_asic = {
                        .cs_parse = &r600_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &r600_gpu_is_lockup,
                }
        },
        .irq = {
@@ -946,7 +946,6 @@ static struct radeon_asic rs780_asic = {
        .fini = &r600_fini,
        .suspend = &r600_suspend,
        .resume = &r600_resume,
-       .gpu_is_lockup = &r600_gpu_is_lockup,
        .vga_set_state = &r600_vga_set_state,
        .asic_reset = &r600_asic_reset,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
@@ -964,6 +963,7 @@ static struct radeon_asic rs780_asic = {
                        .cs_parse = &r600_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &r600_gpu_is_lockup,
                }
        },
        .irq = {
@@ -1020,7 +1020,6 @@ static struct radeon_asic rv770_asic = {
        .suspend = &rv770_suspend,
        .resume = &rv770_resume,
        .asic_reset = &r600_asic_reset,
-       .gpu_is_lockup = &r600_gpu_is_lockup,
        .vga_set_state = &r600_vga_set_state,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
        .gui_idle = &r600_gui_idle,
@@ -1037,6 +1036,7 @@ static struct radeon_asic rv770_asic = {
                        .cs_parse = &r600_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &r600_gpu_is_lockup,
                }
        },
        .irq = {
@@ -1092,7 +1092,6 @@ static struct radeon_asic evergreen_asic = {
        .fini = &evergreen_fini,
        .suspend = &evergreen_suspend,
        .resume = &evergreen_resume,
-       .gpu_is_lockup = &evergreen_gpu_is_lockup,
        .asic_reset = &evergreen_asic_reset,
        .vga_set_state = &r600_vga_set_state,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
@@ -1110,6 +1109,7 @@ static struct radeon_asic evergreen_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                }
        },
        .irq = {
@@ -1165,7 +1165,6 @@ static struct radeon_asic sumo_asic = {
        .fini = &evergreen_fini,
        .suspend = &evergreen_suspend,
        .resume = &evergreen_resume,
-       .gpu_is_lockup = &evergreen_gpu_is_lockup,
        .asic_reset = &evergreen_asic_reset,
        .vga_set_state = &r600_vga_set_state,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
@@ -1183,6 +1182,7 @@ static struct radeon_asic sumo_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                },
        },
        .irq = {
@@ -1238,7 +1238,6 @@ static struct radeon_asic btc_asic = {
        .fini = &evergreen_fini,
        .suspend = &evergreen_suspend,
        .resume = &evergreen_resume,
-       .gpu_is_lockup = &evergreen_gpu_is_lockup,
        .asic_reset = &evergreen_asic_reset,
        .vga_set_state = &r600_vga_set_state,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
@@ -1256,6 +1255,7 @@ static struct radeon_asic btc_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                }
        },
        .irq = {
@@ -1321,7 +1321,6 @@ static struct radeon_asic cayman_asic = {
        .fini = &cayman_fini,
        .suspend = &cayman_suspend,
        .resume = &cayman_resume,
-       .gpu_is_lockup = &cayman_gpu_is_lockup,
        .asic_reset = &cayman_asic_reset,
        .vga_set_state = &r600_vga_set_state,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
@@ -1340,6 +1339,7 @@ static struct radeon_asic cayman_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                },
                [CAYMAN_RING_TYPE_CP1_INDEX] = {
                        .ib_execute = &cayman_ring_ib_execute,
@@ -1349,6 +1349,7 @@ static struct radeon_asic cayman_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                },
                [CAYMAN_RING_TYPE_CP2_INDEX] = {
                        .ib_execute = &cayman_ring_ib_execute,
@@ -1358,6 +1359,7 @@ static struct radeon_asic cayman_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                }
        },
        .irq = {
@@ -1413,7 +1415,6 @@ static struct radeon_asic trinity_asic = {
        .fini = &cayman_fini,
        .suspend = &cayman_suspend,
        .resume = &cayman_resume,
-       .gpu_is_lockup = &cayman_gpu_is_lockup,
        .asic_reset = &cayman_asic_reset,
        .vga_set_state = &r600_vga_set_state,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
@@ -1432,6 +1433,7 @@ static struct radeon_asic trinity_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                },
                [CAYMAN_RING_TYPE_CP1_INDEX] = {
                        .ib_execute = &cayman_ring_ib_execute,
@@ -1441,6 +1443,7 @@ static struct radeon_asic trinity_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                },
                [CAYMAN_RING_TYPE_CP2_INDEX] = {
                        .ib_execute = &cayman_ring_ib_execute,
@@ -1450,6 +1453,7 @@ static struct radeon_asic trinity_asic = {
                        .cs_parse = &evergreen_cs_parse,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &evergreen_gpu_is_lockup,
                }
        },
        .irq = {
@@ -1515,7 +1519,6 @@ static struct radeon_asic si_asic = {
        .fini = &si_fini,
        .suspend = &si_suspend,
        .resume = &si_resume,
-       .gpu_is_lockup = &si_gpu_is_lockup,
        .asic_reset = &si_asic_reset,
        .vga_set_state = &r600_vga_set_state,
        .ioctl_wait_idle = r600_ioctl_wait_idle,
@@ -1534,6 +1537,7 @@ static struct radeon_asic si_asic = {
                        .cs_parse = NULL,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &si_gpu_is_lockup,
                },
                [CAYMAN_RING_TYPE_CP1_INDEX] = {
                        .ib_execute = &si_ring_ib_execute,
@@ -1543,6 +1547,7 @@ static struct radeon_asic si_asic = {
                        .cs_parse = NULL,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &si_gpu_is_lockup,
                },
                [CAYMAN_RING_TYPE_CP2_INDEX] = {
                        .ib_execute = &si_ring_ib_execute,
@@ -1552,6 +1557,7 @@ static struct radeon_asic si_asic = {
                        .cs_parse = NULL,
                        .ring_test = &r600_ring_test,
                        .ib_test = &r600_ib_test,
+                       .is_lockup = &si_gpu_is_lockup,
                }
        },
        .irq = {
index 3d9f9f1d8f904c05fb70caee7e2ba805e44b8124..05a4e15f54657b916e6117f4c782de98221dcc98 100644 (file)
@@ -103,11 +103,6 @@ int r100_pci_gart_enable(struct radeon_device *rdev);
 void r100_pci_gart_disable(struct radeon_device *rdev);
 int r100_debugfs_mc_info_init(struct radeon_device *rdev);
 int r100_gui_wait_for_idle(struct radeon_device *rdev);
-void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup,
-                           struct radeon_ring *cp);
-bool r100_gpu_cp_is_lockup(struct radeon_device *rdev,
-                          struct r100_gpu_lockup *lockup,
-                          struct radeon_ring *cp);
 void r100_ib_fini(struct radeon_device *rdev);
 int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
 void r100_irq_disable(struct radeon_device *rdev);
@@ -159,7 +154,6 @@ extern int r300_init(struct radeon_device *rdev);
 extern void r300_fini(struct radeon_device *rdev);
 extern int r300_suspend(struct radeon_device *rdev);
 extern int r300_resume(struct radeon_device *rdev);
-extern bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
 extern int r300_asic_reset(struct radeon_device *rdev);
 extern void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring);
 extern void r300_fence_ring_emit(struct radeon_device *rdev,
@@ -369,19 +363,19 @@ int r600_audio_bits_per_sample(struct radeon_device *rdev);
 int r600_audio_rate(struct radeon_device *rdev);
 uint8_t r600_audio_status_bits(struct radeon_device *rdev);
 uint8_t r600_audio_category_code(struct radeon_device *rdev);
-void r600_audio_schedule_polling(struct radeon_device *rdev);
-void r600_audio_enable_polling(struct drm_encoder *encoder);
-void r600_audio_disable_polling(struct drm_encoder *encoder);
 void r600_audio_fini(struct radeon_device *rdev);
 void r600_hdmi_init(struct drm_encoder *encoder);
 int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
 void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
 /* r600 blit */
-int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages);
-void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
+int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages,
+                          struct radeon_sa_bo **vb);
+void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence,
+                        struct radeon_sa_bo *vb);
 void r600_kms_blit_copy(struct radeon_device *rdev,
                        u64 src_gpu_addr, u64 dst_gpu_addr,
-                       unsigned num_gpu_pages);
+                       unsigned num_gpu_pages,
+                       struct radeon_sa_bo *vb);
 int r600_mc_wait_for_idle(struct radeon_device *rdev);
 
 /*
@@ -446,7 +440,6 @@ int cayman_init(struct radeon_device *rdev);
 void cayman_fini(struct radeon_device *rdev);
 int cayman_suspend(struct radeon_device *rdev);
 int cayman_resume(struct radeon_device *rdev);
-bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
 int cayman_asic_reset(struct radeon_device *rdev);
 void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int cayman_vm_init(struct radeon_device *rdev);
index 6ae0c75f016acfaaf7bcb705503c187a563f7198..9c6b29a4192773087b1db8b62326e76bb2d971d2 100644 (file)
@@ -633,7 +633,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                tmp &= ~(R300_SCLK_FORCE_VAP);
                                tmp |= RADEON_SCLK_FORCE_CP;
                                WREG32_PLL(RADEON_SCLK_CNTL, tmp);
-                               udelay(15000);
+                               mdelay(15);
 
                                tmp = RREG32_PLL(R300_SCLK_CNTL2);
                                tmp &= ~(R300_SCLK_FORCE_TCL |
@@ -651,12 +651,12 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                        tmp |= (RADEON_ENGIN_DYNCLK_MODE |
                                (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
                        WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp);
-                       udelay(15000);
+                       mdelay(15);
 
                        tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
                        tmp |= RADEON_SCLK_DYN_START_CNTL;
                        WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
-                       udelay(15000);
+                       mdelay(15);
 
                        /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
                           to lockup randomly, leave them as set by BIOS.
@@ -696,7 +696,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                        tmp |= RADEON_SCLK_MORE_FORCEON;
                                }
                                WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
-                               udelay(15000);
+                               mdelay(15);
                        }
 
                        /* RV200::A11 A12, RV250::A11 A12 */
@@ -709,7 +709,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                tmp |= RADEON_TCL_BYPASS_DISABLE;
                                WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
                        }
-                       udelay(15000);
+                       mdelay(15);
 
                        /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */
                        tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
@@ -722,14 +722,14 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                RADEON_PIXCLK_TMDS_ALWAYS_ONb);
 
                        WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
-                       udelay(15000);
+                       mdelay(15);
 
                        tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
                        tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
                                RADEON_PIXCLK_DAC_ALWAYS_ONb);
 
                        WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
-                       udelay(15000);
+                       mdelay(15);
                }
        } else {
                /* Turn everything OFF (ForceON to everything) */
@@ -861,7 +861,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                        }
                        WREG32_PLL(RADEON_SCLK_CNTL, tmp);
 
-                       udelay(16000);
+                       mdelay(16);
 
                        if ((rdev->family == CHIP_R300) ||
                            (rdev->family == CHIP_R350)) {
@@ -870,7 +870,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                        R300_SCLK_FORCE_GA |
                                        R300_SCLK_FORCE_CBA);
                                WREG32_PLL(R300_SCLK_CNTL2, tmp);
-                               udelay(16000);
+                               mdelay(16);
                        }
 
                        if (rdev->flags & RADEON_IS_IGP) {
@@ -878,7 +878,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                tmp &= ~(RADEON_FORCEON_MCLKA |
                                         RADEON_FORCEON_YCLKA);
                                WREG32_PLL(RADEON_MCLK_CNTL, tmp);
-                               udelay(16000);
+                               mdelay(16);
                        }
 
                        if ((rdev->family == CHIP_RV200) ||
@@ -887,7 +887,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
                                tmp |= RADEON_SCLK_MORE_FORCEON;
                                WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
-                               udelay(16000);
+                               mdelay(16);
                        }
 
                        tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
@@ -900,7 +900,7 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable)
                                 RADEON_PIXCLK_TMDS_ALWAYS_ONb);
 
                        WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
-                       udelay(16000);
+                       mdelay(16);
 
                        tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
                        tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
index 81fc100be7e18c321c088bc787e1154de96e11e3..576f4f6919f28d075ba0e77365d0a0cc52814f25 100644 (file)
@@ -1561,6 +1561,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                           (rdev->pdev->subsystem_device == 0x4150)) {
                        /* Mac G5 tower 9600 */
                        rdev->mode_info.connector_table = CT_MAC_G5_9600;
+               } else if ((rdev->pdev->device == 0x4c66) &&
+                          (rdev->pdev->subsystem_vendor == 0x1002) &&
+                          (rdev->pdev->subsystem_device == 0x4c66)) {
+                       /* SAM440ep RV250 embedded board */
+                       rdev->mode_info.connector_table = CT_SAM440EP;
                } else
 #endif /* CONFIG_PPC_PMAC */
 #ifdef CONFIG_PPC64
@@ -2134,6 +2139,67 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                                            CONNECTOR_OBJECT_ID_SVIDEO,
                                            &hpd);
                break;
+       case CT_SAM440EP:
+               DRM_INFO("Connector Table: %d (SAM440ep embedded board)\n",
+                        rdev->mode_info.connector_table);
+               /* LVDS */
+               ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0);
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_LCD1_SUPPORT,
+                                                               0),
+                                         ATOM_DEVICE_LCD1_SUPPORT);
+               radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
+                                           DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_LVDS,
+                                           &hpd);
+               /* DVI-I - secondary dac, int tmds */
+               ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0);
+               hpd.hpd = RADEON_HPD_1; /* ??? */
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_DFP1_SUPPORT,
+                                                               0),
+                                         ATOM_DEVICE_DFP1_SUPPORT);
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_CRT2_SUPPORT,
+                                                               2),
+                                         ATOM_DEVICE_CRT2_SUPPORT);
+               radeon_add_legacy_connector(dev, 1,
+                                           ATOM_DEVICE_DFP1_SUPPORT |
+                                           ATOM_DEVICE_CRT2_SUPPORT,
+                                           DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+                                           &hpd);
+               /* VGA - primary dac */
+               ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0);
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_CRT1_SUPPORT,
+                                                               1),
+                                         ATOM_DEVICE_CRT1_SUPPORT);
+               radeon_add_legacy_connector(dev, 2,
+                                           ATOM_DEVICE_CRT1_SUPPORT,
+                                           DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_VGA,
+                                           &hpd);
+               /* TV - TV DAC */
+               ddc_i2c.valid = false;
+               hpd.hpd = RADEON_HPD_NONE;
+               radeon_add_legacy_encoder(dev,
+                                         radeon_get_encoder_enum(dev,
+                                                               ATOM_DEVICE_TV1_SUPPORT,
+                                                               2),
+                                         ATOM_DEVICE_TV1_SUPPORT);
+               radeon_add_legacy_connector(dev, 3, ATOM_DEVICE_TV1_SUPPORT,
+                                           DRM_MODE_CONNECTOR_SVIDEO,
+                                           &ddc_i2c,
+                                           CONNECTOR_OBJECT_ID_SVIDEO,
+                                           &hpd);
+               break;
        default:
                DRM_INFO("Connector table: %d (invalid)\n",
                         rdev->mode_info.connector_table);
@@ -2845,7 +2911,7 @@ bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
                                        case 4:
                                                val = RBIOS16(index);
                                                index += 2;
-                                               udelay(val * 1000);
+                                               mdelay(val);
                                                break;
                                        case 6:
                                                slave_addr = id & 0xff;
@@ -3044,7 +3110,7 @@ static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset)
                                        udelay(150);
                                        break;
                                case 2:
-                                       udelay(1000);
+                                       mdelay(1);
                                        break;
                                case 3:
                                        while (tmp--) {
@@ -3075,13 +3141,13 @@ static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset)
                                                /*mclk_cntl |= 0x00001111;*//* ??? */
                                                WREG32_PLL(RADEON_MCLK_CNTL,
                                                           mclk_cntl);
-                                               udelay(10000);
+                                               mdelay(10);
 #endif
                                                WREG32_PLL
                                                    (RADEON_CLK_PWRMGT_CNTL,
                                                     tmp &
                                                     ~RADEON_CG_NO1_DEBUG_0);
-                                               udelay(10000);
+                                               mdelay(10);
                                        }
                                        break;
                                default:
index bd05156edbdb07fc30188215fcba9d0bbef3c31f..2914c5761cfc7a8816f6dcc745aa17282385e626 100644 (file)
@@ -84,6 +84,62 @@ static void radeon_property_change_mode(struct drm_encoder *encoder)
                                         crtc->x, crtc->y, crtc->fb);
        }
 }
+
+int radeon_get_monitor_bpc(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct radeon_connector_atom_dig *dig_connector;
+       int bpc = 8;
+
+       switch (connector->connector_type) {
+       case DRM_MODE_CONNECTOR_DVII:
+       case DRM_MODE_CONNECTOR_HDMIB:
+               if (radeon_connector->use_digital) {
+                       if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                               if (connector->display_info.bpc)
+                                       bpc = connector->display_info.bpc;
+                       }
+               }
+               break;
+       case DRM_MODE_CONNECTOR_DVID:
+       case DRM_MODE_CONNECTOR_HDMIA:
+               if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       if (connector->display_info.bpc)
+                               bpc = connector->display_info.bpc;
+               }
+               break;
+       case DRM_MODE_CONNECTOR_DisplayPort:
+               dig_connector = radeon_connector->con_priv;
+               if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+                   (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
+                   drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       if (connector->display_info.bpc)
+                               bpc = connector->display_info.bpc;
+               }
+               break;
+       case DRM_MODE_CONNECTOR_eDP:
+       case DRM_MODE_CONNECTOR_LVDS:
+               if (connector->display_info.bpc)
+                       bpc = connector->display_info.bpc;
+               else if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+                       struct drm_connector_helper_funcs *connector_funcs =
+                               connector->helper_private;
+                       struct drm_encoder *encoder = connector_funcs->best_encoder(connector);
+                       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+                       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+                       if (dig->lcd_misc & ATOM_PANEL_MISC_V13_6BIT_PER_COLOR)
+                               bpc = 6;
+                       else if (dig->lcd_misc & ATOM_PANEL_MISC_V13_8BIT_PER_COLOR)
+                               bpc = 8;
+               }
+               break;
+       }
+       return bpc;
+}
+
 static void
 radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status)
 {
@@ -970,7 +1026,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
                        encoder = obj_to_encoder(obj);
 
-                       if (encoder->encoder_type != DRM_MODE_ENCODER_DAC ||
+                       if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
                            encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
                                continue;
 
@@ -1000,6 +1056,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
         * cases the DVI port is actually a virtual KVM port connected to the service
         * processor.
         */
+out:
        if ((!rdev->is_atom_bios) &&
            (ret == connector_status_disconnected) &&
            rdev->mode_info.bios_hardcoded_edid_size) {
@@ -1007,7 +1064,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                ret = connector_status_connected;
        }
 
-out:
        /* updated in get modes as well since we need to know if it's analog or digital */
        radeon_connector_update_scratch_regs(connector, ret);
        return ret;
index 5cac8327833840d5b2503d0e8dd028b283d858a7..c7d64a7390339e7b6fe29e27de06265843a865ff 100644 (file)
@@ -118,44 +118,33 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
 static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
 {
        bool sync_to_ring[RADEON_NUM_RINGS] = { };
+       bool need_sync = false;
        int i, r;
 
        for (i = 0; i < p->nrelocs; i++) {
+               struct radeon_fence *fence;
+
                if (!p->relocs[i].robj || !p->relocs[i].robj->tbo.sync_obj)
                        continue;
 
-               if (!(p->relocs[i].flags & RADEON_RELOC_DONT_SYNC)) {
-                       struct radeon_fence *fence = p->relocs[i].robj->tbo.sync_obj;
-                       if (!radeon_fence_signaled(fence)) {
-                               sync_to_ring[fence->ring] = true;
-                       }
+               fence = p->relocs[i].robj->tbo.sync_obj;
+               if (fence->ring != p->ring && !radeon_fence_signaled(fence)) {
+                       sync_to_ring[fence->ring] = true;
+                       need_sync = true;
                }
        }
 
-       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-               /* no need to sync to our own or unused rings */
-               if (i == p->ring || !sync_to_ring[i] || !p->rdev->ring[i].ready)
-                       continue;
-
-               if (!p->ib->fence->semaphore) {
-                       r = radeon_semaphore_create(p->rdev, &p->ib->fence->semaphore);
-                       if (r)
-                               return r;
-               }
-
-               r = radeon_ring_lock(p->rdev, &p->rdev->ring[i], 3);
-               if (r)
-                       return r;
-               radeon_semaphore_emit_signal(p->rdev, i, p->ib->fence->semaphore);
-               radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[i]);
+       if (!need_sync) {
+               return 0;
+       }
 
-               r = radeon_ring_lock(p->rdev, &p->rdev->ring[p->ring], 3);
-               if (r)
-                       return r;
-               radeon_semaphore_emit_wait(p->rdev, p->ring, p->ib->fence->semaphore);
-               radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[p->ring]);
+       r = radeon_semaphore_create(p->rdev, &p->ib.semaphore);
+       if (r) {
+               return r;
        }
-       return 0;
+
+       return radeon_semaphore_sync_rings(p->rdev, p->ib.semaphore,
+                                          sync_to_ring, p->ring);
 }
 
 int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
@@ -172,6 +161,10 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
        /* get chunks */
        INIT_LIST_HEAD(&p->validated);
        p->idx = 0;
+       p->ib.sa_bo = NULL;
+       p->ib.semaphore = NULL;
+       p->const_ib.sa_bo = NULL;
+       p->const_ib.semaphore = NULL;
        p->chunk_ib_idx = -1;
        p->chunk_relocs_idx = -1;
        p->chunk_flags_idx = -1;
@@ -278,11 +271,16 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                                  p->chunks[p->chunk_ib_idx].length_dw);
                        return -EINVAL;
                }
-               p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
-               p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
-               if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL ||
-                   p->chunks[p->chunk_ib_idx].kpage[1] == NULL)
-                       return -ENOMEM;
+               if ((p->rdev->flags & RADEON_IS_AGP)) {
+                       p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
+                       p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
+                       if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL ||
+                           p->chunks[p->chunk_ib_idx].kpage[1] == NULL) {
+                               kfree(p->chunks[i].kpage[0]);
+                               kfree(p->chunks[i].kpage[1]);
+                               return -ENOMEM;
+                       }
+               }
                p->chunks[p->chunk_ib_idx].kpage_idx[0] = -1;
                p->chunks[p->chunk_ib_idx].kpage_idx[1] = -1;
                p->chunks[p->chunk_ib_idx].last_copied_page = -1;
@@ -305,10 +303,9 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
 {
        unsigned i;
 
-
-       if (!error && parser->ib)
+       if (!error)
                ttm_eu_fence_buffer_objects(&parser->validated,
-                                           parser->ib->fence);
+                                           parser->ib.fence);
        else
                ttm_eu_backoff_reservation(&parser->validated);
 
@@ -323,12 +320,15 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
        kfree(parser->relocs_ptr);
        for (i = 0; i < parser->nchunks; i++) {
                kfree(parser->chunks[i].kdata);
-               kfree(parser->chunks[i].kpage[0]);
-               kfree(parser->chunks[i].kpage[1]);
+               if ((parser->rdev->flags & RADEON_IS_AGP)) {
+                       kfree(parser->chunks[i].kpage[0]);
+                       kfree(parser->chunks[i].kpage[1]);
+               }
        }
        kfree(parser->chunks);
        kfree(parser->chunks_array);
        radeon_ib_free(parser->rdev, &parser->ib);
+       radeon_ib_free(parser->rdev, &parser->const_ib);
 }
 
 static int radeon_cs_ib_chunk(struct radeon_device *rdev,
@@ -354,7 +354,7 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
                DRM_ERROR("Failed to get ib !\n");
                return r;
        }
-       parser->ib->length_dw = ib_chunk->length_dw;
+       parser->ib.length_dw = ib_chunk->length_dw;
        r = radeon_cs_parse(rdev, parser->ring, parser);
        if (r || parser->parser_error) {
                DRM_ERROR("Invalid command stream !\n");
@@ -369,8 +369,8 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
        if (r) {
                DRM_ERROR("Failed to synchronize rings !\n");
        }
-       parser->ib->vm_id = 0;
-       r = radeon_ib_schedule(rdev, parser->ib);
+       parser->ib.vm_id = 0;
+       r = radeon_ib_schedule(rdev, &parser->ib);
        if (r) {
                DRM_ERROR("Failed to schedule IB !\n");
        }
@@ -421,14 +421,14 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
                        DRM_ERROR("Failed to get const ib !\n");
                        return r;
                }
-               parser->const_ib->is_const_ib = true;
-               parser->const_ib->length_dw = ib_chunk->length_dw;
+               parser->const_ib.is_const_ib = true;
+               parser->const_ib.length_dw = ib_chunk->length_dw;
                /* Copy the packet into the IB */
-               if (DRM_COPY_FROM_USER(parser->const_ib->ptr, ib_chunk->user_ptr,
+               if (DRM_COPY_FROM_USER(parser->const_ib.ptr, ib_chunk->user_ptr,
                                       ib_chunk->length_dw * 4)) {
                        return -EFAULT;
                }
-               r = radeon_ring_ib_parse(rdev, parser->ring, parser->const_ib);
+               r = radeon_ring_ib_parse(rdev, parser->ring, &parser->const_ib);
                if (r) {
                        return r;
                }
@@ -445,13 +445,13 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
                DRM_ERROR("Failed to get ib !\n");
                return r;
        }
-       parser->ib->length_dw = ib_chunk->length_dw;
+       parser->ib.length_dw = ib_chunk->length_dw;
        /* Copy the packet into the IB */
-       if (DRM_COPY_FROM_USER(parser->ib->ptr, ib_chunk->user_ptr,
+       if (DRM_COPY_FROM_USER(parser->ib.ptr, ib_chunk->user_ptr,
                               ib_chunk->length_dw * 4)) {
                return -EFAULT;
        }
-       r = radeon_ring_ib_parse(rdev, parser->ring, parser->ib);
+       r = radeon_ring_ib_parse(rdev, parser->ring, &parser->ib);
        if (r) {
                return r;
        }
@@ -472,34 +472,44 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
 
        if ((rdev->family >= CHIP_TAHITI) &&
            (parser->chunk_const_ib_idx != -1)) {
-               parser->const_ib->vm_id = vm->id;
+               parser->const_ib.vm_id = vm->id;
                /* ib pool is bind at 0 in virtual address space to gpu_addr is the
                 * offset inside the pool bo
                 */
-               parser->const_ib->gpu_addr = parser->const_ib->sa_bo.offset;
-               r = radeon_ib_schedule(rdev, parser->const_ib);
+               parser->const_ib.gpu_addr = parser->const_ib.sa_bo->soffset;
+               r = radeon_ib_schedule(rdev, &parser->const_ib);
                if (r)
                        goto out;
        }
 
-       parser->ib->vm_id = vm->id;
+       parser->ib.vm_id = vm->id;
        /* ib pool is bind at 0 in virtual address space to gpu_addr is the
         * offset inside the pool bo
         */
-       parser->ib->gpu_addr = parser->ib->sa_bo.offset;
-       parser->ib->is_const_ib = false;
-       r = radeon_ib_schedule(rdev, parser->ib);
+       parser->ib.gpu_addr = parser->ib.sa_bo->soffset;
+       parser->ib.is_const_ib = false;
+       r = radeon_ib_schedule(rdev, &parser->ib);
 out:
        if (!r) {
                if (vm->fence) {
                        radeon_fence_unref(&vm->fence);
                }
-               vm->fence = radeon_fence_ref(parser->ib->fence);
+               vm->fence = radeon_fence_ref(parser->ib.fence);
        }
        mutex_unlock(&fpriv->vm.mutex);
        return r;
 }
 
+static int radeon_cs_handle_lockup(struct radeon_device *rdev, int r)
+{
+       if (r == -EDEADLK) {
+               r = radeon_gpu_reset(rdev);
+               if (!r)
+                       r = -EAGAIN;
+       }
+       return r;
+}
+
 int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
        struct radeon_device *rdev = dev->dev_private;
@@ -521,6 +531,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
                radeon_cs_parser_fini(&parser, r);
+               r = radeon_cs_handle_lockup(rdev, r);
                radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
@@ -529,6 +540,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                if (r != -ERESTARTSYS)
                        DRM_ERROR("Failed to parse relocation %d!\n", r);
                radeon_cs_parser_fini(&parser, r);
+               r = radeon_cs_handle_lockup(rdev, r);
                radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
@@ -542,6 +554,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        }
 out:
        radeon_cs_parser_fini(&parser, r);
+       r = radeon_cs_handle_lockup(rdev, r);
        radeon_mutex_unlock(&rdev->cs_mutex);
        return r;
 }
@@ -559,7 +572,7 @@ int radeon_cs_finish_pages(struct radeon_cs_parser *p)
                                size = PAGE_SIZE;
                }
                
-               if (DRM_COPY_FROM_USER(p->ib->ptr + (i * (PAGE_SIZE/4)),
+               if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)),
                                       ibc->user_ptr + (i * PAGE_SIZE),
                                       size))
                        return -EFAULT;
@@ -573,9 +586,10 @@ int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
        struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
        int i;
        int size = PAGE_SIZE;
+       bool copy1 = (p->rdev->flags & RADEON_IS_AGP) ? false : true;
 
        for (i = ibc->last_copied_page + 1; i < pg_idx; i++) {
-               if (DRM_COPY_FROM_USER(p->ib->ptr + (i * (PAGE_SIZE/4)),
+               if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)),
                                       ibc->user_ptr + (i * PAGE_SIZE),
                                       PAGE_SIZE)) {
                        p->parser_error = -EFAULT;
@@ -583,14 +597,16 @@ int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
                }
        }
 
-       new_page = ibc->kpage_idx[0] < ibc->kpage_idx[1] ? 0 : 1;
-
        if (pg_idx == ibc->last_page_index) {
                size = (ibc->length_dw * 4) % PAGE_SIZE;
-                       if (size == 0)
-                               size = PAGE_SIZE;
+               if (size == 0)
+                       size = PAGE_SIZE;
        }
 
+       new_page = ibc->kpage_idx[0] < ibc->kpage_idx[1] ? 0 : 1;
+       if (copy1)
+               ibc->kpage[new_page] = p->ib.ptr + (pg_idx * (PAGE_SIZE / 4));
+
        if (DRM_COPY_FROM_USER(ibc->kpage[new_page],
                               ibc->user_ptr + (pg_idx * PAGE_SIZE),
                               size)) {
@@ -598,8 +614,9 @@ int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
                return 0;
        }
 
-       /* copy to IB here */
-       memcpy((void *)(p->ib->ptr+(pg_idx*(PAGE_SIZE/4))), ibc->kpage[new_page], size);
+       /* copy to IB for non single case */
+       if (!copy1)
+               memcpy((void *)(p->ib.ptr+(pg_idx*(PAGE_SIZE/4))), ibc->kpage[new_page], size);
 
        ibc->last_copied_page = pg_idx;
        ibc->kpage_idx[new_page] = pg_idx;
index ea7df16e2f84f267f0a129fac762333b96d54b56..3d41525c1bcf4a3a03846606a2f3c74d899a0429 100644 (file)
@@ -225,9 +225,9 @@ int radeon_wb_init(struct radeon_device *rdev)
        /* disable event_write fences */
        rdev->wb.use_event = false;
        /* disabled via module param */
-       if (radeon_no_wb == 1)
+       if (radeon_no_wb == 1) {
                rdev->wb.enabled = false;
-       else {
+       else {
                if (rdev->flags & RADEON_IS_AGP) {
                        /* often unreliable on AGP */
                        rdev->wb.enabled = false;
@@ -237,12 +237,13 @@ int radeon_wb_init(struct radeon_device *rdev)
                } else {
                        rdev->wb.enabled = true;
                        /* event_write fences are only available on r600+ */
-                       if (rdev->family >= CHIP_R600)
+                       if (rdev->family >= CHIP_R600) {
                                rdev->wb.use_event = true;
+                       }
                }
        }
-       /* always use writeback/events on NI */
-       if (ASIC_IS_DCE5(rdev)) {
+       /* always use writeback/events on NI, APUs */
+       if (rdev->family >= CHIP_PALM) {
                rdev->wb.enabled = true;
                rdev->wb.use_event = true;
        }
@@ -696,6 +697,11 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
        return can_switch;
 }
 
+static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
+       .set_gpu_state = radeon_switcheroo_set_state,
+       .reprobe = NULL,
+       .can_switch = radeon_switcheroo_can_switch,
+};
 
 int radeon_device_init(struct radeon_device *rdev,
                       struct drm_device *ddev,
@@ -714,7 +720,6 @@ int radeon_device_init(struct radeon_device *rdev,
        rdev->is_atom_bios = false;
        rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT;
        rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-       rdev->gpu_lockup = false;
        rdev->accel_working = false;
 
        DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
@@ -724,21 +729,16 @@ int radeon_device_init(struct radeon_device *rdev,
        /* mutex initialization are all done here so we
         * can recall function without having locking issues */
        radeon_mutex_init(&rdev->cs_mutex);
-       radeon_mutex_init(&rdev->ib_pool.mutex);
-       for (i = 0; i < RADEON_NUM_RINGS; ++i)
-               mutex_init(&rdev->ring[i].mutex);
+       mutex_init(&rdev->ring_lock);
        mutex_init(&rdev->dc_hw_i2c_mutex);
        if (rdev->family >= CHIP_R600)
                spin_lock_init(&rdev->ih.lock);
        mutex_init(&rdev->gem.mutex);
        mutex_init(&rdev->pm.mutex);
        mutex_init(&rdev->vram_mutex);
-       rwlock_init(&rdev->fence_lock);
-       rwlock_init(&rdev->semaphore_drv.lock);
        INIT_LIST_HEAD(&rdev->gem.objects);
        init_waitqueue_head(&rdev->irq.vblank_queue);
        init_waitqueue_head(&rdev->irq.idle_queue);
-       INIT_LIST_HEAD(&rdev->semaphore_drv.bo);
        /* initialize vm here */
        rdev->vm_manager.use_bitmap = 1;
        rdev->vm_manager.max_pfn = 1 << 20;
@@ -814,10 +814,7 @@ int radeon_device_init(struct radeon_device *rdev,
        /* this will fail for cards that aren't VGA class devices, just
         * ignore it */
        vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
-       vga_switcheroo_register_client(rdev->pdev,
-                                      radeon_switcheroo_set_state,
-                                      NULL,
-                                      radeon_switcheroo_can_switch);
+       vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops);
 
        r = radeon_init(rdev);
        if (r)
@@ -914,9 +911,12 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
        }
        /* evict vram memory */
        radeon_bo_evict_vram(rdev);
+
+       mutex_lock(&rdev->ring_lock);
        /* wait for gpu to finish processing current batch */
        for (i = 0; i < RADEON_NUM_RINGS; i++)
-               radeon_fence_wait_last(rdev, i);
+               radeon_fence_wait_empty_locked(rdev, i);
+       mutex_unlock(&rdev->ring_lock);
 
        radeon_save_bios_scratch_regs(rdev);
 
@@ -955,7 +955,6 @@ int radeon_resume_kms(struct drm_device *dev)
                console_unlock();
                return -1;
        }
-       pci_set_master(dev->pdev);
        /* resume AGP if in use */
        radeon_agp_resume(rdev);
        radeon_resume(rdev);
@@ -988,9 +987,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
        int r;
        int resched;
 
-       /* Prevent CS ioctl from interfering */
-       radeon_mutex_lock(&rdev->cs_mutex);
-
        radeon_save_bios_scratch_regs(rdev);
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
@@ -1005,8 +1001,6 @@ int radeon_gpu_reset(struct radeon_device *rdev)
                ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
        }
 
-       radeon_mutex_unlock(&rdev->cs_mutex);
-
        if (r) {
                /* bad news, how to tell it to userspace ? */
                dev_info(rdev->dev, "GPU reset failed\n");
index 8086c96e0b06a4b80cf77a03b43736cefdf713e2..0a1d4bd65edcebc31cbb425120e3c5090f7e2382 100644 (file)
@@ -533,7 +533,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
                radeon_legacy_init_crtc(dev, radeon_crtc);
 }
 
-static const char *encoder_names[36] = {
+static const char *encoder_names[37] = {
        "NONE",
        "INTERNAL_LVDS",
        "INTERNAL_TMDS1",
@@ -570,6 +570,7 @@ static const char *encoder_names[36] = {
        "INTERNAL_UNIPHY2",
        "NUTMEG",
        "TRAVIS",
+       "INTERNAL_VCE"
 };
 
 static const char *connector_names[15] = {
index ef7bb3f6ecae9e0c5e7c647947122b9364c93f78..e62e56a57ee4429074b7b51fa1a73e342a06526e 100644 (file)
@@ -128,6 +128,7 @@ int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = 0;
 int radeon_msi = -1;
+int radeon_lockup_timeout = 10000;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -177,6 +178,9 @@ module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
 MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
 module_param_named(msi, radeon_msi, int, 0444);
 
+MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (defaul 10000 = 10 seconds, 0 = disable)");
+module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
index 4bd36a354fbef7d473dd321d92c96f828611d815..11f5f402d22cb331deed24dcb3b671e92a54892e 100644 (file)
@@ -63,98 +63,82 @@ static u32 radeon_fence_read(struct radeon_device *rdev, int ring)
 
 int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
 {
-       unsigned long irq_flags;
-
-       write_lock_irqsave(&rdev->fence_lock, irq_flags);
-       if (fence->emitted) {
-               write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
+       /* we are protected by the ring emission mutex */
+       if (fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) {
                return 0;
        }
-       fence->seq = atomic_add_return(1, &rdev->fence_drv[fence->ring].seq);
-       if (!rdev->ring[fence->ring].ready)
-               /* FIXME: cp is not running assume everythings is done right
-                * away
-                */
-               radeon_fence_write(rdev, fence->seq, fence->ring);
-       else
-               radeon_fence_ring_emit(rdev, fence->ring, fence);
-
+       fence->seq = ++rdev->fence_drv[fence->ring].seq;
+       radeon_fence_ring_emit(rdev, fence->ring, fence);
        trace_radeon_fence_emit(rdev->ddev, fence->seq);
-       fence->emitted = true;
-       list_move_tail(&fence->list, &rdev->fence_drv[fence->ring].emitted);
-       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
        return 0;
 }
 
-static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring)
+void radeon_fence_process(struct radeon_device *rdev, int ring)
 {
-       struct radeon_fence *fence;
-       struct list_head *i, *n;
-       uint32_t seq;
+       uint64_t seq, last_seq;
+       unsigned count_loop = 0;
        bool wake = false;
-       unsigned long cjiffies;
 
-       seq = radeon_fence_read(rdev, ring);
-       if (seq != rdev->fence_drv[ring].last_seq) {
-               rdev->fence_drv[ring].last_seq = seq;
-               rdev->fence_drv[ring].last_jiffies = jiffies;
-               rdev->fence_drv[ring].last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
-       } else {
-               cjiffies = jiffies;
-               if (time_after(cjiffies, rdev->fence_drv[ring].last_jiffies)) {
-                       cjiffies -= rdev->fence_drv[ring].last_jiffies;
-                       if (time_after(rdev->fence_drv[ring].last_timeout, cjiffies)) {
-                               /* update the timeout */
-                               rdev->fence_drv[ring].last_timeout -= cjiffies;
-                       } else {
-                               /* the 500ms timeout is elapsed we should test
-                                * for GPU lockup
-                                */
-                               rdev->fence_drv[ring].last_timeout = 1;
-                       }
-               } else {
-                       /* wrap around update last jiffies, we will just wait
-                        * a little longer
-                        */
-                       rdev->fence_drv[ring].last_jiffies = cjiffies;
+       /* Note there is a scenario here for an infinite loop but it's
+        * very unlikely to happen. For it to happen, the current polling
+        * process need to be interrupted by another process and another
+        * process needs to update the last_seq btw the atomic read and
+        * xchg of the current process.
+        *
+        * More over for this to go in infinite loop there need to be
+        * continuously new fence signaled ie radeon_fence_read needs
+        * to return a different value each time for both the currently
+        * polling process and the other process that xchg the last_seq
+        * btw atomic read and xchg of the current process. And the
+        * value the other process set as last seq must be higher than
+        * the seq value we just read. Which means that current process
+        * need to be interrupted after radeon_fence_read and before
+        * atomic xchg.
+        *
+        * To be even more safe we count the number of time we loop and
+        * we bail after 10 loop just accepting the fact that we might
+        * have temporarly set the last_seq not to the true real last
+        * seq but to an older one.
+        */
+       last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
+       do {
+               seq = radeon_fence_read(rdev, ring);
+               seq |= last_seq & 0xffffffff00000000LL;
+               if (seq < last_seq) {
+                       seq += 0x100000000LL;
                }
-               return false;
-       }
-       n = NULL;
-       list_for_each(i, &rdev->fence_drv[ring].emitted) {
-               fence = list_entry(i, struct radeon_fence, list);
-               if (fence->seq == seq) {
-                       n = i;
+
+               if (seq == last_seq) {
                        break;
                }
-       }
-       /* all fence previous to this one are considered as signaled */
-       if (n) {
-               i = n;
-               do {
-                       n = i->prev;
-                       list_move_tail(i, &rdev->fence_drv[ring].signaled);
-                       fence = list_entry(i, struct radeon_fence, list);
-                       fence->signaled = true;
-                       i = n;
-               } while (i != &rdev->fence_drv[ring].emitted);
+               /* If we loop over we don't want to return without
+                * checking if a fence is signaled as it means that the
+                * seq we just read is different from the previous on.
+                */
                wake = true;
+               last_seq = seq;
+               if ((count_loop++) > 10) {
+                       /* We looped over too many time leave with the
+                        * fact that we might have set an older fence
+                        * seq then the current real last seq as signaled
+                        * by the hw.
+                        */
+                       break;
+               }
+       } while (atomic64_xchg(&rdev->fence_drv[ring].last_seq, seq) > seq);
+
+       if (wake) {
+               rdev->fence_drv[ring].last_activity = jiffies;
+               wake_up_all(&rdev->fence_queue);
        }
-       return wake;
 }
 
 static void radeon_fence_destroy(struct kref *kref)
 {
-       unsigned long irq_flags;
-        struct radeon_fence *fence;
+       struct radeon_fence *fence;
 
        fence = container_of(kref, struct radeon_fence, kref);
-       write_lock_irqsave(&fence->rdev->fence_lock, irq_flags);
-       list_del(&fence->list);
-       fence->emitted = false;
-       write_unlock_irqrestore(&fence->rdev->fence_lock, irq_flags);
-       if (fence->semaphore)
-               radeon_semaphore_free(fence->rdev, fence->semaphore);
+       fence->seq = RADEON_FENCE_NOTEMITED_SEQ;
        kfree(fence);
 }
 
@@ -162,171 +146,342 @@ int radeon_fence_create(struct radeon_device *rdev,
                        struct radeon_fence **fence,
                        int ring)
 {
-       unsigned long irq_flags;
-
        *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL);
        if ((*fence) == NULL) {
                return -ENOMEM;
        }
        kref_init(&((*fence)->kref));
        (*fence)->rdev = rdev;
-       (*fence)->emitted = false;
-       (*fence)->signaled = false;
-       (*fence)->seq = 0;
+       (*fence)->seq = RADEON_FENCE_NOTEMITED_SEQ;
        (*fence)->ring = ring;
-       (*fence)->semaphore = NULL;
-       INIT_LIST_HEAD(&(*fence)->list);
-
-       write_lock_irqsave(&rdev->fence_lock, irq_flags);
-       list_add_tail(&(*fence)->list, &rdev->fence_drv[ring].created);
-       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
        return 0;
 }
 
-bool radeon_fence_signaled(struct radeon_fence *fence)
+static bool radeon_fence_seq_signaled(struct radeon_device *rdev,
+                                     u64 seq, unsigned ring)
 {
-       unsigned long irq_flags;
-       bool signaled = false;
-
-       if (!fence)
+       if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) {
                return true;
-
-       if (fence->rdev->gpu_lockup)
+       }
+       /* poll new last sequence at least once */
+       radeon_fence_process(rdev, ring);
+       if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) {
                return true;
+       }
+       return false;
+}
 
-       write_lock_irqsave(&fence->rdev->fence_lock, irq_flags);
-       signaled = fence->signaled;
-       /* if we are shuting down report all fence as signaled */
-       if (fence->rdev->shutdown) {
-               signaled = true;
+bool radeon_fence_signaled(struct radeon_fence *fence)
+{
+       if (!fence) {
+               return true;
        }
-       if (!fence->emitted) {
+       if (fence->seq == RADEON_FENCE_NOTEMITED_SEQ) {
                WARN(1, "Querying an unemitted fence : %p !\n", fence);
-               signaled = true;
+               return true;
        }
-       if (!signaled) {
-               radeon_fence_poll_locked(fence->rdev, fence->ring);
-               signaled = fence->signaled;
+       if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) {
+               return true;
+       }
+       if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) {
+               fence->seq = RADEON_FENCE_SIGNALED_SEQ;
+               return true;
        }
-       write_unlock_irqrestore(&fence->rdev->fence_lock, irq_flags);
-       return signaled;
+       return false;
+}
+
+static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq,
+                                unsigned ring, bool intr, bool lock_ring)
+{
+       unsigned long timeout, last_activity;
+       uint64_t seq;
+       unsigned i;
+       bool signaled;
+       int r;
+
+       while (target_seq > atomic64_read(&rdev->fence_drv[ring].last_seq)) {
+               if (!rdev->ring[ring].ready) {
+                       return -EBUSY;
+               }
+
+               timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT;
+               if (time_after(rdev->fence_drv[ring].last_activity, timeout)) {
+                       /* the normal case, timeout is somewhere before last_activity */
+                       timeout = rdev->fence_drv[ring].last_activity - timeout;
+               } else {
+                       /* either jiffies wrapped around, or no fence was signaled in the last 500ms
+                        * anyway we will just wait for the minimum amount and then check for a lockup
+                        */
+                       timeout = 1;
+               }
+               seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
+               /* Save current last activity valuee, used to check for GPU lockups */
+               last_activity = rdev->fence_drv[ring].last_activity;
+
+               trace_radeon_fence_wait_begin(rdev->ddev, seq);
+               radeon_irq_kms_sw_irq_get(rdev, ring);
+               if (intr) {
+                       r = wait_event_interruptible_timeout(rdev->fence_queue,
+                               (signaled = radeon_fence_seq_signaled(rdev, target_seq, ring)),
+                               timeout);
+                } else {
+                       r = wait_event_timeout(rdev->fence_queue,
+                               (signaled = radeon_fence_seq_signaled(rdev, target_seq, ring)),
+                               timeout);
+               }
+               radeon_irq_kms_sw_irq_put(rdev, ring);
+               if (unlikely(r < 0)) {
+                       return r;
+               }
+               trace_radeon_fence_wait_end(rdev->ddev, seq);
+
+               if (unlikely(!signaled)) {
+                       /* we were interrupted for some reason and fence
+                        * isn't signaled yet, resume waiting */
+                       if (r) {
+                               continue;
+                       }
+
+                       /* check if sequence value has changed since last_activity */
+                       if (seq != atomic64_read(&rdev->fence_drv[ring].last_seq)) {
+                               continue;
+                       }
+
+                       if (lock_ring) {
+                               mutex_lock(&rdev->ring_lock);
+                       }
+
+                       /* test if somebody else has already decided that this is a lockup */
+                       if (last_activity != rdev->fence_drv[ring].last_activity) {
+                               if (lock_ring) {
+                                       mutex_unlock(&rdev->ring_lock);
+                               }
+                               continue;
+                       }
+
+                       if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) {
+                               /* good news we believe it's a lockup */
+                               dev_warn(rdev->dev, "GPU lockup (waiting for 0x%016llx last fence id 0x%016llx)\n",
+                                        target_seq, seq);
+
+                               /* change last activity so nobody else think there is a lockup */
+                               for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+                                       rdev->fence_drv[i].last_activity = jiffies;
+                               }
+
+                               /* mark the ring as not ready any more */
+                               rdev->ring[ring].ready = false;
+                               if (lock_ring) {
+                                       mutex_unlock(&rdev->ring_lock);
+                               }
+                               return -EDEADLK;
+                       }
+
+                       if (lock_ring) {
+                               mutex_unlock(&rdev->ring_lock);
+                       }
+               }
+       }
+       return 0;
 }
 
 int radeon_fence_wait(struct radeon_fence *fence, bool intr)
 {
-       struct radeon_device *rdev;
-       unsigned long irq_flags, timeout;
-       u32 seq;
        int r;
 
        if (fence == NULL) {
                WARN(1, "Querying an invalid fence : %p !\n", fence);
-               return 0;
+               return -EINVAL;
        }
-       rdev = fence->rdev;
-       if (radeon_fence_signaled(fence)) {
-               return 0;
+
+       r = radeon_fence_wait_seq(fence->rdev, fence->seq,
+                                 fence->ring, intr, true);
+       if (r) {
+               return r;
        }
-       timeout = rdev->fence_drv[fence->ring].last_timeout;
-retry:
-       /* save current sequence used to check for GPU lockup */
-       seq = rdev->fence_drv[fence->ring].last_seq;
-       trace_radeon_fence_wait_begin(rdev->ddev, seq);
-       if (intr) {
-               radeon_irq_kms_sw_irq_get(rdev, fence->ring);
-               r = wait_event_interruptible_timeout(rdev->fence_drv[fence->ring].queue,
-                               radeon_fence_signaled(fence), timeout);
-               radeon_irq_kms_sw_irq_put(rdev, fence->ring);
-               if (unlikely(r < 0)) {
-                       return r;
+       fence->seq = RADEON_FENCE_SIGNALED_SEQ;
+       return 0;
+}
+
+bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq)
+{
+       unsigned i;
+
+       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               if (seq[i] && radeon_fence_seq_signaled(rdev, seq[i], i)) {
+                       return true;
                }
-       } else {
-               radeon_irq_kms_sw_irq_get(rdev, fence->ring);
-               r = wait_event_timeout(rdev->fence_drv[fence->ring].queue,
-                        radeon_fence_signaled(fence), timeout);
-               radeon_irq_kms_sw_irq_put(rdev, fence->ring);
        }
-       trace_radeon_fence_wait_end(rdev->ddev, seq);
-       if (unlikely(!radeon_fence_signaled(fence))) {
-               /* we were interrupted for some reason and fence isn't
-                * isn't signaled yet, resume wait
-                */
-               if (r) {
-                       timeout = r;
-                       goto retry;
+       return false;
+}
+
+static int radeon_fence_wait_any_seq(struct radeon_device *rdev,
+                                    u64 *target_seq, bool intr)
+{
+       unsigned long timeout, last_activity, tmp;
+       unsigned i, ring = RADEON_NUM_RINGS;
+       bool signaled;
+       int r;
+
+       for (i = 0, last_activity = 0; i < RADEON_NUM_RINGS; ++i) {
+               if (!target_seq[i]) {
+                       continue;
+               }
+
+               /* use the most recent one as indicator */
+               if (time_after(rdev->fence_drv[i].last_activity, last_activity)) {
+                       last_activity = rdev->fence_drv[i].last_activity;
                }
-               /* don't protect read access to rdev->fence_drv[t].last_seq
-                * if we experiencing a lockup the value doesn't change
+
+               /* For lockup detection just pick the lowest ring we are
+                * actively waiting for
                 */
-               if (seq == rdev->fence_drv[fence->ring].last_seq &&
-                   radeon_gpu_is_lockup(rdev, &rdev->ring[fence->ring])) {
-                       /* good news we believe it's a lockup */
-                       printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n",
-                            fence->seq, seq);
-                       /* FIXME: what should we do ? marking everyone
-                        * as signaled for now
+               if (i < ring) {
+                       ring = i;
+               }
+       }
+
+       /* nothing to wait for ? */
+       if (ring == RADEON_NUM_RINGS) {
+               return 0;
+       }
+
+       while (!radeon_fence_any_seq_signaled(rdev, target_seq)) {
+               timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT;
+               if (time_after(last_activity, timeout)) {
+                       /* the normal case, timeout is somewhere before last_activity */
+                       timeout = last_activity - timeout;
+               } else {
+                       /* either jiffies wrapped around, or no fence was signaled in the last 500ms
+                        * anyway we will just wait for the minimum amount and then check for a lockup
                         */
-                       rdev->gpu_lockup = true;
-                       r = radeon_gpu_reset(rdev);
-                       if (r)
-                               return r;
-                       radeon_fence_write(rdev, fence->seq, fence->ring);
-                       rdev->gpu_lockup = false;
+                       timeout = 1;
+               }
+
+               trace_radeon_fence_wait_begin(rdev->ddev, target_seq[ring]);
+               for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+                       if (target_seq[i]) {
+                               radeon_irq_kms_sw_irq_get(rdev, i);
+                       }
+               }
+               if (intr) {
+                       r = wait_event_interruptible_timeout(rdev->fence_queue,
+                               (signaled = radeon_fence_any_seq_signaled(rdev, target_seq)),
+                               timeout);
+               } else {
+                       r = wait_event_timeout(rdev->fence_queue,
+                               (signaled = radeon_fence_any_seq_signaled(rdev, target_seq)),
+                               timeout);
+               }
+               for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+                       if (target_seq[i]) {
+                               radeon_irq_kms_sw_irq_put(rdev, i);
+                       }
+               }
+               if (unlikely(r < 0)) {
+                       return r;
+               }
+               trace_radeon_fence_wait_end(rdev->ddev, target_seq[ring]);
+
+               if (unlikely(!signaled)) {
+                       /* we were interrupted for some reason and fence
+                        * isn't signaled yet, resume waiting */
+                       if (r) {
+                               continue;
+                       }
+
+                       mutex_lock(&rdev->ring_lock);
+                       for (i = 0, tmp = 0; i < RADEON_NUM_RINGS; ++i) {
+                               if (time_after(rdev->fence_drv[i].last_activity, tmp)) {
+                                       tmp = rdev->fence_drv[i].last_activity;
+                               }
+                       }
+                       /* test if somebody else has already decided that this is a lockup */
+                       if (last_activity != tmp) {
+                               last_activity = tmp;
+                               mutex_unlock(&rdev->ring_lock);
+                               continue;
+                       }
+
+                       if (radeon_ring_is_lockup(rdev, ring, &rdev->ring[ring])) {
+                               /* good news we believe it's a lockup */
+                               dev_warn(rdev->dev, "GPU lockup (waiting for 0x%016llx)\n",
+                                        target_seq[ring]);
+
+                               /* change last activity so nobody else think there is a lockup */
+                               for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+                                       rdev->fence_drv[i].last_activity = jiffies;
+                               }
+
+                               /* mark the ring as not ready any more */
+                               rdev->ring[ring].ready = false;
+                               mutex_unlock(&rdev->ring_lock);
+                               return -EDEADLK;
+                       }
+                       mutex_unlock(&rdev->ring_lock);
                }
-               timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
-               write_lock_irqsave(&rdev->fence_lock, irq_flags);
-               rdev->fence_drv[fence->ring].last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
-               rdev->fence_drv[fence->ring].last_jiffies = jiffies;
-               write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
-               goto retry;
        }
        return 0;
 }
 
-int radeon_fence_wait_next(struct radeon_device *rdev, int ring)
+int radeon_fence_wait_any(struct radeon_device *rdev,
+                         struct radeon_fence **fences,
+                         bool intr)
 {
-       unsigned long irq_flags;
-       struct radeon_fence *fence;
+       uint64_t seq[RADEON_NUM_RINGS];
+       unsigned i;
        int r;
 
-       if (rdev->gpu_lockup) {
-               return 0;
+       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               seq[i] = 0;
+
+               if (!fences[i]) {
+                       continue;
+               }
+
+               if (fences[i]->seq == RADEON_FENCE_SIGNALED_SEQ) {
+                       /* something was allready signaled */
+                       return 0;
+               }
+
+               if (fences[i]->seq < RADEON_FENCE_NOTEMITED_SEQ) {
+                       seq[i] = fences[i]->seq;
+               }
        }
-       write_lock_irqsave(&rdev->fence_lock, irq_flags);
-       if (list_empty(&rdev->fence_drv[ring].emitted)) {
-               write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
-               return 0;
+
+       r = radeon_fence_wait_any_seq(rdev, seq, intr);
+       if (r) {
+               return r;
        }
-       fence = list_entry(rdev->fence_drv[ring].emitted.next,
-                          struct radeon_fence, list);
-       radeon_fence_ref(fence);
-       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
-       r = radeon_fence_wait(fence, false);
-       radeon_fence_unref(&fence);
-       return r;
+       return 0;
 }
 
-int radeon_fence_wait_last(struct radeon_device *rdev, int ring)
+int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring)
 {
-       unsigned long irq_flags;
-       struct radeon_fence *fence;
-       int r;
-
-       if (rdev->gpu_lockup) {
-               return 0;
+       uint64_t seq;
+
+       /* We are not protected by ring lock when reading current seq but
+        * it's ok as worst case is we return to early while we could have
+        * wait.
+        */
+       seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL;
+       if (seq >= rdev->fence_drv[ring].seq) {
+               /* nothing to wait for, last_seq is
+                  already the last emited fence */
+               return -ENOENT;
        }
-       write_lock_irqsave(&rdev->fence_lock, irq_flags);
-       if (list_empty(&rdev->fence_drv[ring].emitted)) {
-               write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
-               return 0;
-       }
-       fence = list_entry(rdev->fence_drv[ring].emitted.prev,
-                          struct radeon_fence, list);
-       radeon_fence_ref(fence);
-       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
-       r = radeon_fence_wait(fence, false);
-       radeon_fence_unref(&fence);
-       return r;
+       return radeon_fence_wait_seq(rdev, seq, ring, false, false);
+}
+
+int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring)
+{
+       /* We are not protected by ring lock when reading current seq
+        * but it's ok as wait empty is call from place where no more
+        * activity can be scheduled so there won't be concurrent access
+        * to seq value.
+        */
+       return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq,
+                                    ring, false, false);
 }
 
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence)
@@ -345,49 +500,27 @@ void radeon_fence_unref(struct radeon_fence **fence)
        }
 }
 
-void radeon_fence_process(struct radeon_device *rdev, int ring)
-{
-       unsigned long irq_flags;
-       bool wake;
-
-       write_lock_irqsave(&rdev->fence_lock, irq_flags);
-       wake = radeon_fence_poll_locked(rdev, ring);
-       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
-       if (wake) {
-               wake_up_all(&rdev->fence_drv[ring].queue);
-       }
-}
-
-int radeon_fence_count_emitted(struct radeon_device *rdev, int ring)
+unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring)
 {
-       unsigned long irq_flags;
-       int not_processed = 0;
-
-       read_lock_irqsave(&rdev->fence_lock, irq_flags);
-       if (!rdev->fence_drv[ring].initialized) {
-               read_unlock_irqrestore(&rdev->fence_lock, irq_flags);
-               return 0;
+       uint64_t emitted;
+
+       /* We are not protected by ring lock when reading the last sequence
+        * but it's ok to report slightly wrong fence count here.
+        */
+       radeon_fence_process(rdev, ring);
+       emitted = rdev->fence_drv[ring].seq - atomic64_read(&rdev->fence_drv[ring].last_seq);
+       /* to avoid 32bits warp around */
+       if (emitted > 0x10000000) {
+               emitted = 0x10000000;
        }
-
-       if (!list_empty(&rdev->fence_drv[ring].emitted)) {
-               struct list_head *ptr;
-               list_for_each(ptr, &rdev->fence_drv[ring].emitted) {
-                       /* count up to 3, that's enought info */
-                       if (++not_processed >= 3)
-                               break;
-               }
-       }
-       read_unlock_irqrestore(&rdev->fence_lock, irq_flags);
-       return not_processed;
+       return (unsigned)emitted;
 }
 
 int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
 {
-       unsigned long irq_flags;
        uint64_t index;
        int r;
 
-       write_lock_irqsave(&rdev->fence_lock, irq_flags);
        radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
        if (rdev->wb.use_event) {
                rdev->fence_drv[ring].scratch_reg = 0;
@@ -396,7 +529,6 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
                r = radeon_scratch_get(rdev, &rdev->fence_drv[ring].scratch_reg);
                if (r) {
                        dev_err(rdev->dev, "fence failed to get scratch register\n");
-                       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
                        return r;
                }
                index = RADEON_WB_SCRATCH_OFFSET +
@@ -405,11 +537,10 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)
        }
        rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
        rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index;
-       radeon_fence_write(rdev, atomic_read(&rdev->fence_drv[ring].seq), ring);
+       radeon_fence_write(rdev, rdev->fence_drv[ring].seq, ring);
        rdev->fence_drv[ring].initialized = true;
-       DRM_INFO("fence driver on ring %d use gpu addr 0x%08Lx and cpu addr 0x%p\n",
+       dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n",
                 ring, rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr);
-       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
        return 0;
 }
 
@@ -418,24 +549,20 @@ static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring)
        rdev->fence_drv[ring].scratch_reg = -1;
        rdev->fence_drv[ring].cpu_addr = NULL;
        rdev->fence_drv[ring].gpu_addr = 0;
-       atomic_set(&rdev->fence_drv[ring].seq, 0);
-       INIT_LIST_HEAD(&rdev->fence_drv[ring].created);
-       INIT_LIST_HEAD(&rdev->fence_drv[ring].emitted);
-       INIT_LIST_HEAD(&rdev->fence_drv[ring].signaled);
-       init_waitqueue_head(&rdev->fence_drv[ring].queue);
+       rdev->fence_drv[ring].seq = 0;
+       atomic64_set(&rdev->fence_drv[ring].last_seq, 0);
+       rdev->fence_drv[ring].last_activity = jiffies;
        rdev->fence_drv[ring].initialized = false;
 }
 
 int radeon_fence_driver_init(struct radeon_device *rdev)
 {
-       unsigned long irq_flags;
        int ring;
 
-       write_lock_irqsave(&rdev->fence_lock, irq_flags);
+       init_waitqueue_head(&rdev->fence_queue);
        for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
                radeon_fence_driver_init_ring(rdev, ring);
        }
-       write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
        if (radeon_debugfs_fence_init(rdev)) {
                dev_err(rdev->dev, "fence debugfs file creation failed\n");
        }
@@ -444,19 +571,18 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
 
 void radeon_fence_driver_fini(struct radeon_device *rdev)
 {
-       unsigned long irq_flags;
        int ring;
 
+       mutex_lock(&rdev->ring_lock);
        for (ring = 0; ring < RADEON_NUM_RINGS; ring++) {
                if (!rdev->fence_drv[ring].initialized)
                        continue;
-               radeon_fence_wait_last(rdev, ring);
-               wake_up_all(&rdev->fence_drv[ring].queue);
-               write_lock_irqsave(&rdev->fence_lock, irq_flags);
+               radeon_fence_wait_empty_locked(rdev, ring);
+               wake_up_all(&rdev->fence_queue);
                radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
-               write_unlock_irqrestore(&rdev->fence_lock, irq_flags);
                rdev->fence_drv[ring].initialized = false;
        }
+       mutex_unlock(&rdev->ring_lock);
 }
 
 
@@ -469,7 +595,6 @@ static int radeon_debugfs_fence_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 radeon_device *rdev = dev->dev_private;
-       struct radeon_fence *fence;
        int i;
 
        for (i = 0; i < RADEON_NUM_RINGS; ++i) {
@@ -477,14 +602,10 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
                        continue;
 
                seq_printf(m, "--- ring %d ---\n", i);
-               seq_printf(m, "Last signaled fence 0x%08X\n",
-                          radeon_fence_read(rdev, i));
-               if (!list_empty(&rdev->fence_drv[i].emitted)) {
-                       fence = list_entry(rdev->fence_drv[i].emitted.prev,
-                                          struct radeon_fence, list);
-                       seq_printf(m, "Last emitted fence %p with 0x%08X\n",
-                                  fence,  fence->seq);
-               }
+               seq_printf(m, "Last signaled fence 0x%016llx\n",
+                          (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq));
+               seq_printf(m, "Last emitted  0x%016llx\n",
+                          rdev->fence_drv[i].seq);
        }
        return 0;
 }
index c58a036233fb4409b3b4b656a1aba1c103b1b40a..8e9ef3403acd91652163f0bf97c98d6568977092 100644 (file)
@@ -326,7 +326,7 @@ static void radeon_vm_unbind_locked(struct radeon_device *rdev,
        rdev->vm_manager.use_bitmap &= ~(1 << vm->id);
        list_del_init(&vm->list);
        vm->id = -1;
-       radeon_sa_bo_free(rdev, &vm->sa_bo);
+       radeon_sa_bo_free(rdev, &vm->sa_bo, NULL);
        vm->pt = NULL;
 
        list_for_each_entry(bo_va, &vm->va, vm_list) {
@@ -395,7 +395,7 @@ int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm)
 retry:
        r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, &vm->sa_bo,
                             RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8),
-                            RADEON_GPU_PAGE_SIZE);
+                            RADEON_GPU_PAGE_SIZE, false);
        if (r) {
                if (list_empty(&rdev->vm_manager.lru_vm)) {
                        return r;
@@ -404,10 +404,8 @@ retry:
                radeon_vm_unbind(rdev, vm_evict);
                goto retry;
        }
-       vm->pt = rdev->vm_manager.sa_manager.cpu_ptr;
-       vm->pt += (vm->sa_bo.offset >> 3);
-       vm->pt_gpu_addr = rdev->vm_manager.sa_manager.gpu_addr;
-       vm->pt_gpu_addr += vm->sa_bo.offset;
+       vm->pt = radeon_sa_bo_cpu_addr(vm->sa_bo);
+       vm->pt_gpu_addr = radeon_sa_bo_gpu_addr(vm->sa_bo);
        memset(vm->pt, 0, RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8));
 
 retry_id:
@@ -428,14 +426,14 @@ retry_id:
        /* do hw bind */
        r = rdev->vm_manager.funcs->bind(rdev, vm, id);
        if (r) {
-               radeon_sa_bo_free(rdev, &vm->sa_bo);
+               radeon_sa_bo_free(rdev, &vm->sa_bo, NULL);
                return r;
        }
        rdev->vm_manager.use_bitmap |= 1 << id;
        vm->id = id;
        list_add_tail(&vm->list, &rdev->vm_manager.lru_vm);
-       return radeon_vm_bo_update_pte(rdev, vm, rdev->ib_pool.sa_manager.bo,
-                                      &rdev->ib_pool.sa_manager.bo->tbo.mem);
+       return radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo,
+                                      &rdev->ring_tmp_bo.bo->tbo.mem);
 }
 
 /* object have to be reserved */
@@ -633,7 +631,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
        /* map the ib pool buffer at 0 in virtual address space, set
         * read only
         */
-       r = radeon_vm_bo_add(rdev, vm, rdev->ib_pool.sa_manager.bo, 0,
+       r = radeon_vm_bo_add(rdev, vm, rdev->ring_tmp_bo.bo, 0,
                             RADEON_VM_PAGE_READABLE | RADEON_VM_PAGE_SNOOPED);
        return r;
 }
@@ -650,12 +648,12 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
        radeon_mutex_unlock(&rdev->cs_mutex);
 
        /* remove all bo */
-       r = radeon_bo_reserve(rdev->ib_pool.sa_manager.bo, false);
+       r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
        if (!r) {
-               bo_va = radeon_bo_va(rdev->ib_pool.sa_manager.bo, vm);
+               bo_va = radeon_bo_va(rdev->ring_tmp_bo.bo, vm);
                list_del_init(&bo_va->bo_list);
                list_del_init(&bo_va->vm_list);
-               radeon_bo_unreserve(rdev->ib_pool.sa_manager.bo);
+               radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
                kfree(bo_va);
        }
        if (!list_empty(&vm->va)) {
index c7008b5210f74d43481017c6d544ae77f78f83cf..e15cb1fe2c393bca0cba1d38d040300024aff9c5 100644 (file)
@@ -154,6 +154,17 @@ void radeon_gem_object_close(struct drm_gem_object *obj,
        radeon_bo_unreserve(rbo);
 }
 
+static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r)
+{
+       if (r == -EDEADLK) {
+               radeon_mutex_lock(&rdev->cs_mutex);
+               r = radeon_gpu_reset(rdev);
+               if (!r)
+                       r = -EAGAIN;
+               radeon_mutex_unlock(&rdev->cs_mutex);
+       }
+       return r;
+}
 
 /*
  * GEM ioctls.
@@ -210,12 +221,14 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
                                        args->initial_domain, false,
                                        false, &gobj);
        if (r) {
+               r = radeon_gem_handle_lockup(rdev, r);
                return r;
        }
        r = drm_gem_handle_create(filp, gobj, &handle);
        /* drop reference from allocate - handle holds it now */
        drm_gem_object_unreference_unlocked(gobj);
        if (r) {
+               r = radeon_gem_handle_lockup(rdev, r);
                return r;
        }
        args->handle = handle;
@@ -245,6 +258,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
        r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
 
        drm_gem_object_unreference_unlocked(gobj);
+       r = radeon_gem_handle_lockup(robj->rdev, r);
        return r;
 }
 
@@ -301,6 +315,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
                break;
        }
        drm_gem_object_unreference_unlocked(gobj);
+       r = radeon_gem_handle_lockup(robj->rdev, r);
        return r;
 }
 
@@ -322,6 +337,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
        if (robj->rdev->asic->ioctl_wait_idle)
                robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj);
        drm_gem_object_unreference_unlocked(gobj);
+       r = radeon_gem_handle_lockup(robj->rdev, r);
        return r;
 }
 
index 85bcfc8923a789bf73101a1c5ef7cadc9ec1300f..3edec1c198e3145addb0b47bbafdf3cf2abd1e49 100644 (file)
@@ -900,6 +900,10 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
        struct radeon_i2c_chan *i2c;
        int ret;
 
+       /* don't add the mm_i2c bus unless hw_i2c is enabled */
+       if (rec->mm_i2c && (radeon_hw_i2c == 0))
+               return NULL;
+
        i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
        if (i2c == NULL)
                return NULL;
index 66d5fe1c81747cfa73da445d1f2099d36e9e4261..5df58d1aba06661cd706522f86b5e7a88407a350 100644 (file)
@@ -73,6 +73,7 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
        for (i = 0; i < RADEON_MAX_CRTCS; i++) {
                rdev->irq.crtc_vblank_int[i] = false;
                rdev->irq.pflip[i] = false;
+               rdev->irq.afmt[i] = false;
        }
        radeon_irq_set(rdev);
        /* Clear bits */
@@ -108,6 +109,7 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
        for (i = 0; i < RADEON_MAX_CRTCS; i++) {
                rdev->irq.crtc_vblank_int[i] = false;
                rdev->irq.pflip[i] = false;
+               rdev->irq.afmt[i] = false;
        }
        radeon_irq_set(rdev);
 }
@@ -147,6 +149,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
            (rdev->pdev->subsystem_device == 0x01fd))
                return true;
 
+       /* RV515 seems to have MSI issues where it loses
+        * MSI rearms occasionally. This leads to lockups and freezes.
+        * disable it by default.
+        */
+       if (rdev->family == CHIP_RV515)
+               return false;
        if (rdev->flags & RADEON_IS_IGP) {
                /* APUs work fine with MSIs */
                if (rdev->family >= CHIP_PALM)
@@ -164,6 +172,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
        int r = 0;
 
        INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
+       INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
 
        spin_lock_init(&rdev->irq.sw_lock);
        for (i = 0; i < rdev->num_crtc; i++)
index 3c2628b14d56231997f5eb704a8e8a974611a081..f1016a5820d1f0b0cc3e89195f4576b836e9a269 100644 (file)
@@ -57,8 +57,6 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
        }
        dev->dev_private = (void *)rdev;
 
-       pci_set_master(dev->pdev);
-
        /* update BUS flag */
        if (drm_pci_device_is_agp(dev)) {
                flags |= RADEON_IS_AGP;
index 2f46e0c8df53256a9bf5d6271b55141be2f8b35a..42db254f6bb04e13f86c8ba238e6be7685a20578 100644 (file)
@@ -88,7 +88,7 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
                lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
                lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
                WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
-               udelay(1000);
+               mdelay(1);
 
                lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
                lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
@@ -101,7 +101,7 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
                                  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
                if (is_mac)
                        lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
-               udelay(panel_pwr_delay * 1000);
+               mdelay(panel_pwr_delay);
                WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
                break;
        case DRM_MODE_DPMS_STANDBY:
@@ -118,10 +118,10 @@ static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
                        WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
                        lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
                }
-               udelay(panel_pwr_delay * 1000);
+               mdelay(panel_pwr_delay);
                WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
                WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
-               udelay(panel_pwr_delay * 1000);
+               mdelay(panel_pwr_delay);
                break;
        }
 
@@ -656,7 +656,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
 
        WREG32(RADEON_DAC_MACRO_CNTL, tmp);
 
-       udelay(2000);
+       mdelay(2);
 
        if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT)
                found = connector_status_connected;
@@ -1499,7 +1499,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
        tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
        WREG32(RADEON_DAC_CNTL2, tmp);
 
-       udelay(10000);
+       mdelay(10);
 
        if (ASIC_IS_R300(rdev)) {
                if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B)
index f7eb5d8b9fd3d1b0957d2912da9886b73ac50874..499a5fed8b2629def9458dacef5b2dde680c3fef 100644 (file)
@@ -210,6 +210,7 @@ enum radeon_connector_table {
        CT_RN50_POWER,
        CT_MAC_X800,
        CT_MAC_G5_9600,
+       CT_SAM440EP
 };
 
 enum radeon_dvo_chip {
@@ -384,8 +385,8 @@ struct radeon_encoder {
        struct drm_display_mode native_mode;
        void *enc_priv;
        int audio_polling_active;
+       bool hdmi_enabled;
        int hdmi_offset;
-       int hdmi_config_offset;
        int hdmi_audio_workaround;
        int hdmi_buffer_status;
        bool is_ext_encoder;
@@ -476,6 +477,7 @@ extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
 extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
 extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
 extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
+extern int radeon_get_monitor_bpc(struct drm_connector *connector);
 
 extern void radeon_connector_hotplug(struct drm_connector *connector);
 extern int radeon_dp_mode_valid_helper(struct drm_connector *connector,
index 6f70158d34e41f979ade9268cadeab8905ea4e81..df6a4dbd93f81acec1aa27f0312d2e47b5331b5c 100644 (file)
@@ -241,7 +241,8 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
                                domain_start = bo->rdev->mc.vram_start;
                        else
                                domain_start = bo->rdev->mc.gtt_start;
-                       WARN_ON_ONCE((*gpu_addr - domain_start) > max_offset);
+                       WARN_ON_ONCE(max_offset <
+                                    (radeon_bo_gpu_offset(bo) - domain_start));
                }
 
                return 0;
index f9104be88d7c12e48ec92254109ec6991b9e725e..befec7d12132a131e58bb54773f80914e9bca761 100644 (file)
@@ -146,6 +146,17 @@ extern struct radeon_bo_va *radeon_bo_va(struct radeon_bo *rbo,
 /*
  * sub allocation
  */
+
+static inline uint64_t radeon_sa_bo_gpu_addr(struct radeon_sa_bo *sa_bo)
+{
+       return sa_bo->manager->gpu_addr + sa_bo->soffset;
+}
+
+static inline void * radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo)
+{
+       return sa_bo->manager->cpu_ptr + sa_bo->soffset;
+}
+
 extern int radeon_sa_bo_manager_init(struct radeon_device *rdev,
                                     struct radeon_sa_manager *sa_manager,
                                     unsigned size, u32 domain);
@@ -157,9 +168,15 @@ extern int radeon_sa_bo_manager_suspend(struct radeon_device *rdev,
                                        struct radeon_sa_manager *sa_manager);
 extern int radeon_sa_bo_new(struct radeon_device *rdev,
                            struct radeon_sa_manager *sa_manager,
-                           struct radeon_sa_bo *sa_bo,
-                           unsigned size, unsigned align);
+                           struct radeon_sa_bo **sa_bo,
+                           unsigned size, unsigned align, bool block);
 extern void radeon_sa_bo_free(struct radeon_device *rdev,
-                             struct radeon_sa_bo *sa_bo);
+                             struct radeon_sa_bo **sa_bo,
+                             struct radeon_fence *fence);
+#if defined(CONFIG_DEBUG_FS)
+extern void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
+                                        struct seq_file *m);
+#endif
+
 
 #endif
index caa55d68f319cd6352311f836cc1597aeb3b46b3..08825548ee69c487909e16019ddbfca0e7cbcb6a 100644 (file)
@@ -252,10 +252,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
 
        mutex_lock(&rdev->ddev->struct_mutex);
        mutex_lock(&rdev->vram_mutex);
-       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-               if (rdev->ring[i].ring_obj)
-                       mutex_lock(&rdev->ring[i].mutex);
-       }
+       mutex_lock(&rdev->ring_lock);
 
        /* gui idle int has issues on older chips it seems */
        if (rdev->family >= CHIP_R600) {
@@ -273,13 +270,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
        } else {
                struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
                if (ring->ready) {
-                       struct radeon_fence *fence;
-                       radeon_ring_alloc(rdev, ring, 64);
-                       radeon_fence_create(rdev, &fence, radeon_ring_index(rdev, ring));
-                       radeon_fence_emit(rdev, fence);
-                       radeon_ring_commit(rdev, ring);
-                       radeon_fence_wait(fence, false);
-                       radeon_fence_unref(&fence);
+                       radeon_fence_wait_empty_locked(rdev, RADEON_RING_TYPE_GFX_INDEX);
                }
        }
        radeon_unmap_vram_bos(rdev);
@@ -311,10 +302,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
 
        rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
 
-       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-               if (rdev->ring[i].ring_obj)
-                       mutex_unlock(&rdev->ring[i].mutex);
-       }
+       mutex_unlock(&rdev->ring_lock);
        mutex_unlock(&rdev->vram_mutex);
        mutex_unlock(&rdev->ddev->struct_mutex);
 }
index cc33b3d7c33b8f4bfa293cd3ce973fdc8b92aff6..a5dee76f4ebbc493b9e616b403871983d49f2ad7 100644 (file)
@@ -24,6 +24,7 @@
  * Authors: Dave Airlie
  *          Alex Deucher
  *          Jerome Glisse
+ *          Christian König
  */
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include "radeon.h"
 #include "atom.h"
 
-int radeon_debugfs_ib_init(struct radeon_device *rdev);
-int radeon_debugfs_ring_init(struct radeon_device *rdev);
+/*
+ * IB.
+ */
+int radeon_debugfs_sa_init(struct radeon_device *rdev);
 
 u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
 {
@@ -61,123 +64,37 @@ u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
        return idx_value;
 }
 
-void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
-{
-#if DRM_DEBUG_CODE
-       if (ring->count_dw <= 0) {
-               DRM_ERROR("radeon: writting more dword to ring than expected !\n");
-       }
-#endif
-       ring->ring[ring->wptr++] = v;
-       ring->wptr &= ring->ptr_mask;
-       ring->count_dw--;
-       ring->ring_free_dw--;
-}
-
-/*
- * IB.
- */
-bool radeon_ib_try_free(struct radeon_device *rdev, struct radeon_ib *ib)
-{
-       bool done = false;
-
-       /* only free ib which have been emited */
-       if (ib->fence && ib->fence->emitted) {
-               if (radeon_fence_signaled(ib->fence)) {
-                       radeon_fence_unref(&ib->fence);
-                       radeon_sa_bo_free(rdev, &ib->sa_bo);
-                       done = true;
-               }
-       }
-       return done;
-}
-
 int radeon_ib_get(struct radeon_device *rdev, int ring,
-                 struct radeon_ib **ib, unsigned size)
+                 struct radeon_ib *ib, unsigned size)
 {
-       struct radeon_fence *fence;
-       unsigned cretry = 0;
-       int r = 0, i, idx;
-
-       *ib = NULL;
-       /* align size on 256 bytes */
-       size = ALIGN(size, 256);
+       int r;
 
-       r = radeon_fence_create(rdev, &fence, ring);
+       r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true);
        if (r) {
-               dev_err(rdev->dev, "failed to create fence for new IB\n");
+               dev_err(rdev->dev, "failed to get a new IB (%d)\n", r);
                return r;
        }
-
-       radeon_mutex_lock(&rdev->ib_pool.mutex);
-       idx = rdev->ib_pool.head_id;
-retry:
-       if (cretry > 5) {
-               dev_err(rdev->dev, "failed to get an ib after 5 retry\n");
-               radeon_mutex_unlock(&rdev->ib_pool.mutex);
-               radeon_fence_unref(&fence);
-               return -ENOMEM;
-       }
-       cretry++;
-       for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
-               radeon_ib_try_free(rdev, &rdev->ib_pool.ibs[idx]);
-               if (rdev->ib_pool.ibs[idx].fence == NULL) {
-                       r = radeon_sa_bo_new(rdev, &rdev->ib_pool.sa_manager,
-                                            &rdev->ib_pool.ibs[idx].sa_bo,
-                                            size, 256);
-                       if (!r) {
-                               *ib = &rdev->ib_pool.ibs[idx];
-                               (*ib)->ptr = rdev->ib_pool.sa_manager.cpu_ptr;
-                               (*ib)->ptr += ((*ib)->sa_bo.offset >> 2);
-                               (*ib)->gpu_addr = rdev->ib_pool.sa_manager.gpu_addr;
-                               (*ib)->gpu_addr += (*ib)->sa_bo.offset;
-                               (*ib)->fence = fence;
-                               (*ib)->vm_id = 0;
-                               (*ib)->is_const_ib = false;
-                               /* ib are most likely to be allocated in a ring fashion
-                                * thus rdev->ib_pool.head_id should be the id of the
-                                * oldest ib
-                                */
-                               rdev->ib_pool.head_id = (1 + idx);
-                               rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1);
-                               radeon_mutex_unlock(&rdev->ib_pool.mutex);
-                               return 0;
-                       }
-               }
-               idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1);
-       }
-       /* this should be rare event, ie all ib scheduled none signaled yet.
-        */
-       for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
-               if (rdev->ib_pool.ibs[idx].fence && rdev->ib_pool.ibs[idx].fence->emitted) {
-                       r = radeon_fence_wait(rdev->ib_pool.ibs[idx].fence, false);
-                       if (!r) {
-                               goto retry;
-                       }
-                       /* an error happened */
-                       break;
-               }
-               idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1);
+       r = radeon_fence_create(rdev, &ib->fence, ring);
+       if (r) {
+               dev_err(rdev->dev, "failed to create fence for new IB (%d)\n", r);
+               radeon_sa_bo_free(rdev, &ib->sa_bo, NULL);
+               return r;
        }
-       radeon_mutex_unlock(&rdev->ib_pool.mutex);
-       radeon_fence_unref(&fence);
-       return r;
+
+       ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo);
+       ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo);
+       ib->vm_id = 0;
+       ib->is_const_ib = false;
+       ib->semaphore = NULL;
+
+       return 0;
 }
 
-void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
+void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
 {
-       struct radeon_ib *tmp = *ib;
-
-       *ib = NULL;
-       if (tmp == NULL) {
-               return;
-       }
-       radeon_mutex_lock(&rdev->ib_pool.mutex);
-       if (tmp->fence && !tmp->fence->emitted) {
-               radeon_sa_bo_free(rdev, &tmp->sa_bo);
-               radeon_fence_unref(&tmp->fence);
-       }
-       radeon_mutex_unlock(&rdev->ib_pool.mutex);
+       radeon_semaphore_free(rdev, ib->semaphore, ib->fence);
+       radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence);
+       radeon_fence_unref(&ib->fence);
 }
 
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
@@ -187,14 +104,14 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
 
        if (!ib->length_dw || !ring->ready) {
                /* TODO: Nothings in the ib we should report. */
-               DRM_ERROR("radeon: couldn't schedule IB(%u).\n", ib->idx);
+               dev_err(rdev->dev, "couldn't schedule ib\n");
                return -EINVAL;
        }
 
        /* 64 dwords should be enough for fence too */
        r = radeon_ring_lock(rdev, ring, 64);
        if (r) {
-               DRM_ERROR("radeon: scheduling IB failed (%d).\n", r);
+               dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
                return r;
        }
        radeon_ring_ib_execute(rdev, ib->fence->ring, ib);
@@ -205,74 +122,90 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
 
 int radeon_ib_pool_init(struct radeon_device *rdev)
 {
-       struct radeon_sa_manager tmp;
-       int i, r;
+       int r;
 
-       r = radeon_sa_bo_manager_init(rdev, &tmp,
+       if (rdev->ib_pool_ready) {
+               return 0;
+       }
+       r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo,
                                      RADEON_IB_POOL_SIZE*64*1024,
                                      RADEON_GEM_DOMAIN_GTT);
        if (r) {
                return r;
        }
-
-       radeon_mutex_lock(&rdev->ib_pool.mutex);
-       if (rdev->ib_pool.ready) {
-               radeon_mutex_unlock(&rdev->ib_pool.mutex);
-               radeon_sa_bo_manager_fini(rdev, &tmp);
-               return 0;
-       }
-
-       rdev->ib_pool.sa_manager = tmp;
-       INIT_LIST_HEAD(&rdev->ib_pool.sa_manager.sa_bo);
-       for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
-               rdev->ib_pool.ibs[i].fence = NULL;
-               rdev->ib_pool.ibs[i].idx = i;
-               rdev->ib_pool.ibs[i].length_dw = 0;
-               INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].sa_bo.list);
-       }
-       rdev->ib_pool.head_id = 0;
-       rdev->ib_pool.ready = true;
-       DRM_INFO("radeon: ib pool ready.\n");
-
-       if (radeon_debugfs_ib_init(rdev)) {
-               DRM_ERROR("Failed to register debugfs file for IB !\n");
-       }
-       if (radeon_debugfs_ring_init(rdev)) {
-               DRM_ERROR("Failed to register debugfs file for rings !\n");
+       rdev->ib_pool_ready = true;
+       if (radeon_debugfs_sa_init(rdev)) {
+               dev_err(rdev->dev, "failed to register debugfs file for SA\n");
        }
-       radeon_mutex_unlock(&rdev->ib_pool.mutex);
        return 0;
 }
 
 void radeon_ib_pool_fini(struct radeon_device *rdev)
 {
-       unsigned i;
-
-       radeon_mutex_lock(&rdev->ib_pool.mutex);
-       if (rdev->ib_pool.ready) {
-               for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
-                       radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo);
-                       radeon_fence_unref(&rdev->ib_pool.ibs[i].fence);
-               }
-               radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager);
-               rdev->ib_pool.ready = false;
+       if (rdev->ib_pool_ready) {
+               radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo);
+               rdev->ib_pool_ready = false;
        }
-       radeon_mutex_unlock(&rdev->ib_pool.mutex);
 }
 
 int radeon_ib_pool_start(struct radeon_device *rdev)
 {
-       return radeon_sa_bo_manager_start(rdev, &rdev->ib_pool.sa_manager);
+       return radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo);
 }
 
 int radeon_ib_pool_suspend(struct radeon_device *rdev)
 {
-       return radeon_sa_bo_manager_suspend(rdev, &rdev->ib_pool.sa_manager);
+       return radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo);
+}
+
+int radeon_ib_ring_tests(struct radeon_device *rdev)
+{
+       unsigned i;
+       int r;
+
+       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               struct radeon_ring *ring = &rdev->ring[i];
+
+               if (!ring->ready)
+                       continue;
+
+               r = radeon_ib_test(rdev, i, ring);
+               if (r) {
+                       ring->ready = false;
+
+                       if (i == RADEON_RING_TYPE_GFX_INDEX) {
+                               /* oh, oh, that's really bad */
+                               DRM_ERROR("radeon: failed testing IB on GFX ring (%d).\n", r);
+                               rdev->accel_working = false;
+                               return r;
+
+                       } else {
+                               /* still not good, but we can live with it */
+                               DRM_ERROR("radeon: failed testing IB on ring %d (%d).\n", i, r);
+                       }
+               }
+       }
+       return 0;
 }
 
 /*
  * Ring.
  */
+int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring);
+
+void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
+{
+#if DRM_DEBUG_CODE
+       if (ring->count_dw <= 0) {
+               DRM_ERROR("radeon: writting more dword to ring than expected !\n");
+       }
+#endif
+       ring->ring[ring->wptr++] = v;
+       ring->wptr &= ring->ptr_mask;
+       ring->count_dw--;
+       ring->ring_free_dw--;
+}
+
 int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *ring)
 {
        /* r1xx-r5xx only has CP ring */
@@ -319,7 +252,7 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi
                if (ndw < ring->ring_free_dw) {
                        break;
                }
-               r = radeon_fence_wait_next(rdev, radeon_ring_index(rdev, ring));
+               r = radeon_fence_wait_next_locked(rdev, radeon_ring_index(rdev, ring));
                if (r)
                        return r;
        }
@@ -332,10 +265,10 @@ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsig
 {
        int r;
 
-       mutex_lock(&ring->mutex);
+       mutex_lock(&rdev->ring_lock);
        r = radeon_ring_alloc(rdev, ring, ndw);
        if (r) {
-               mutex_unlock(&ring->mutex);
+               mutex_unlock(&rdev->ring_lock);
                return r;
        }
        return 0;
@@ -360,13 +293,85 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring)
 void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring)
 {
        radeon_ring_commit(rdev, ring);
-       mutex_unlock(&ring->mutex);
+       mutex_unlock(&rdev->ring_lock);
 }
 
-void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring)
+void radeon_ring_undo(struct radeon_ring *ring)
 {
        ring->wptr = ring->wptr_old;
-       mutex_unlock(&ring->mutex);
+}
+
+void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       radeon_ring_undo(ring);
+       mutex_unlock(&rdev->ring_lock);
+}
+
+void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       int r;
+
+       radeon_ring_free_size(rdev, ring);
+       if (ring->rptr == ring->wptr) {
+               r = radeon_ring_alloc(rdev, ring, 1);
+               if (!r) {
+                       radeon_ring_write(ring, ring->nop);
+                       radeon_ring_commit(rdev, ring);
+               }
+       }
+}
+
+void radeon_ring_lockup_update(struct radeon_ring *ring)
+{
+       ring->last_rptr = ring->rptr;
+       ring->last_activity = jiffies;
+}
+
+/**
+ * radeon_ring_test_lockup() - check if ring is lockedup by recording information
+ * @rdev:       radeon device structure
+ * @ring:       radeon_ring structure holding ring information
+ *
+ * We don't need to initialize the lockup tracking information as we will either
+ * have CP rptr to a different value of jiffies wrap around which will force
+ * initialization of the lockup tracking informations.
+ *
+ * A possible false positivie is if we get call after while and last_cp_rptr ==
+ * the current CP rptr, even if it's unlikely it might happen. To avoid this
+ * if the elapsed time since last call is bigger than 2 second than we return
+ * false and update the tracking information. Due to this the caller must call
+ * radeon_ring_test_lockup several time in less than 2sec for lockup to be reported
+ * the fencing code should be cautious about that.
+ *
+ * Caller should write to the ring to force CP to do something so we don't get
+ * false positive when CP is just gived nothing to do.
+ *
+ **/
+bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
+{
+       unsigned long cjiffies, elapsed;
+       uint32_t rptr;
+
+       cjiffies = jiffies;
+       if (!time_after(cjiffies, ring->last_activity)) {
+               /* likely a wrap around */
+               radeon_ring_lockup_update(ring);
+               return false;
+       }
+       rptr = RREG32(ring->rptr_reg);
+       ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift;
+       if (ring->rptr != ring->last_rptr) {
+               /* CP is still working no lockup */
+               radeon_ring_lockup_update(ring);
+               return false;
+       }
+       elapsed = jiffies_to_msecs(cjiffies - ring->last_activity);
+       if (radeon_lockup_timeout && elapsed >= radeon_lockup_timeout) {
+               dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed);
+               return true;
+       }
+       /* give a chance to the GPU ... */
+       return false;
 }
 
 int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size,
@@ -411,6 +416,9 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig
        }
        ring->ptr_mask = (ring->ring_size / 4) - 1;
        ring->ring_free_dw = ring->ring_size / 4;
+       if (radeon_debugfs_ring_init(rdev, ring)) {
+               DRM_ERROR("Failed to register debugfs file for rings !\n");
+       }
        return 0;
 }
 
@@ -419,11 +427,12 @@ void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring)
        int r;
        struct radeon_bo *ring_obj;
 
-       mutex_lock(&ring->mutex);
+       mutex_lock(&rdev->ring_lock);
        ring_obj = ring->ring_obj;
+       ring->ready = false;
        ring->ring = NULL;
        ring->ring_obj = NULL;
-       mutex_unlock(&ring->mutex);
+       mutex_unlock(&rdev->ring_lock);
 
        if (ring_obj) {
                r = radeon_bo_reserve(ring_obj, false);
@@ -476,59 +485,48 @@ static struct drm_info_list radeon_debugfs_ring_info_list[] = {
        {"radeon_ring_cp2", radeon_debugfs_ring_info, 0, &cayman_ring_type_cp2_index},
 };
 
-static int radeon_debugfs_ib_info(struct seq_file *m, void *data)
+static int radeon_debugfs_sa_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 radeon_device *rdev = dev->dev_private;
-       struct radeon_ib *ib = &rdev->ib_pool.ibs[*((unsigned*)node->info_ent->data)];
-       unsigned i;
 
-       if (ib == NULL) {
-               return 0;
-       }
-       seq_printf(m, "IB %04u\n", ib->idx);
-       seq_printf(m, "IB fence %p\n", ib->fence);
-       seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
-       for (i = 0; i < ib->length_dw; i++) {
-               seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]);
-       }
+       radeon_sa_bo_dump_debug_info(&rdev->ring_tmp_bo, m);
+
        return 0;
+
 }
 
-static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
-static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
-static unsigned radeon_debugfs_ib_idx[RADEON_IB_POOL_SIZE];
+static struct drm_info_list radeon_debugfs_sa_list[] = {
+        {"radeon_sa_info", &radeon_debugfs_sa_info, 0, NULL},
+};
+
 #endif
 
-int radeon_debugfs_ring_init(struct radeon_device *rdev)
+int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring)
 {
 #if defined(CONFIG_DEBUG_FS)
-       if (rdev->family >= CHIP_CAYMAN)
-               return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list,
-                                               ARRAY_SIZE(radeon_debugfs_ring_info_list));
-       else
-               return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, 1);
-#else
-       return 0;
+       unsigned i;
+       for (i = 0; i < ARRAY_SIZE(radeon_debugfs_ring_info_list); ++i) {
+               struct drm_info_list *info = &radeon_debugfs_ring_info_list[i];
+               int ridx = *(int*)radeon_debugfs_ring_info_list[i].data;
+               unsigned r;
+
+               if (&rdev->ring[ridx] != ring)
+                       continue;
+
+               r = radeon_debugfs_add_files(rdev, info, 1);
+               if (r)
+                       return r;
+       }
 #endif
+       return 0;
 }
 
-int radeon_debugfs_ib_init(struct radeon_device *rdev)
+int radeon_debugfs_sa_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
-       unsigned i;
-
-       for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
-               sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
-               radeon_debugfs_ib_idx[i] = i;
-               radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i];
-               radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info;
-               radeon_debugfs_ib_list[i].driver_features = 0;
-               radeon_debugfs_ib_list[i].data = &radeon_debugfs_ib_idx[i];
-       }
-       return radeon_debugfs_add_files(rdev, radeon_debugfs_ib_list,
-                                       RADEON_IB_POOL_SIZE);
+       return radeon_debugfs_add_files(rdev, radeon_debugfs_sa_list, 1);
 #else
        return 0;
 #endif
index 4cce47e7dc0dd2b983b55c4d0cd5c4c65d7711ee..c3ac7f4c7b7035ccf6bfcf2ed9a0a74a446d15bd 100644 (file)
  * Authors:
  *    Jerome Glisse <glisse@freedesktop.org>
  */
+/* Algorithm:
+ *
+ * We store the last allocated bo in "hole", we always try to allocate
+ * after the last allocated bo. Principle is that in a linear GPU ring
+ * progression was is after last is the oldest bo we allocated and thus
+ * the first one that should no longer be in use by the GPU.
+ *
+ * If it's not the case we skip over the bo after last to the closest
+ * done bo if such one exist. If none exist and we are not asked to
+ * block we report failure to allocate.
+ *
+ * If we are asked to block we wait on all the oldest fence of all
+ * rings. We just wait for any of those fence to complete.
+ */
 #include "drmP.h"
 #include "drm.h"
 #include "radeon.h"
 
+static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo);
+static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager);
+
 int radeon_sa_bo_manager_init(struct radeon_device *rdev,
                              struct radeon_sa_manager *sa_manager,
                              unsigned size, u32 domain)
 {
-       int r;
+       int i, r;
 
+       spin_lock_init(&sa_manager->lock);
        sa_manager->bo = NULL;
        sa_manager->size = size;
        sa_manager->domain = domain;
-       INIT_LIST_HEAD(&sa_manager->sa_bo);
+       sa_manager->hole = &sa_manager->olist;
+       INIT_LIST_HEAD(&sa_manager->olist);
+       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               INIT_LIST_HEAD(&sa_manager->flist[i]);
+       }
 
        r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true,
                             RADEON_GEM_DOMAIN_CPU, &sa_manager->bo);
@@ -57,11 +79,15 @@ void radeon_sa_bo_manager_fini(struct radeon_device *rdev,
 {
        struct radeon_sa_bo *sa_bo, *tmp;
 
-       if (!list_empty(&sa_manager->sa_bo)) {
-               dev_err(rdev->dev, "sa_manager is not empty, clearing anyway\n");
+       if (!list_empty(&sa_manager->olist)) {
+               sa_manager->hole = &sa_manager->olist,
+               radeon_sa_bo_try_free(sa_manager);
+               if (!list_empty(&sa_manager->olist)) {
+                       dev_err(rdev->dev, "sa_manager is not empty, clearing anyway\n");
+               }
        }
-       list_for_each_entry_safe(sa_bo, tmp, &sa_manager->sa_bo, list) {
-               list_del_init(&sa_bo->list);
+       list_for_each_entry_safe(sa_bo, tmp, &sa_manager->olist, olist) {
+               radeon_sa_bo_remove_locked(sa_bo);
        }
        radeon_bo_unref(&sa_manager->bo);
        sa_manager->size = 0;
@@ -113,77 +139,248 @@ int radeon_sa_bo_manager_suspend(struct radeon_device *rdev,
        return r;
 }
 
-/*
- * Principe is simple, we keep a list of sub allocation in offset
- * order (first entry has offset == 0, last entry has the highest
- * offset).
- *
- * When allocating new object we first check if there is room at
- * the end total_size - (last_object_offset + last_object_size) >=
- * alloc_size. If so we allocate new object there.
- *
- * When there is not enough room at the end, we start waiting for
- * each sub object until we reach object_offset+object_size >=
- * alloc_size, this object then become the sub object we return.
- *
- * Alignment can't be bigger than page size
- */
+static void radeon_sa_bo_remove_locked(struct radeon_sa_bo *sa_bo)
+{
+       struct radeon_sa_manager *sa_manager = sa_bo->manager;
+       if (sa_manager->hole == &sa_bo->olist) {
+               sa_manager->hole = sa_bo->olist.prev;
+       }
+       list_del_init(&sa_bo->olist);
+       list_del_init(&sa_bo->flist);
+       radeon_fence_unref(&sa_bo->fence);
+       kfree(sa_bo);
+}
+
+static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager)
+{
+       struct radeon_sa_bo *sa_bo, *tmp;
+
+       if (sa_manager->hole->next == &sa_manager->olist)
+               return;
+
+       sa_bo = list_entry(sa_manager->hole->next, struct radeon_sa_bo, olist);
+       list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) {
+               if (sa_bo->fence == NULL || !radeon_fence_signaled(sa_bo->fence)) {
+                       return;
+               }
+               radeon_sa_bo_remove_locked(sa_bo);
+       }
+}
+
+static inline unsigned radeon_sa_bo_hole_soffset(struct radeon_sa_manager *sa_manager)
+{
+       struct list_head *hole = sa_manager->hole;
+
+       if (hole != &sa_manager->olist) {
+               return list_entry(hole, struct radeon_sa_bo, olist)->eoffset;
+       }
+       return 0;
+}
+
+static inline unsigned radeon_sa_bo_hole_eoffset(struct radeon_sa_manager *sa_manager)
+{
+       struct list_head *hole = sa_manager->hole;
+
+       if (hole->next != &sa_manager->olist) {
+               return list_entry(hole->next, struct radeon_sa_bo, olist)->soffset;
+       }
+       return sa_manager->size;
+}
+
+static bool radeon_sa_bo_try_alloc(struct radeon_sa_manager *sa_manager,
+                                  struct radeon_sa_bo *sa_bo,
+                                  unsigned size, unsigned align)
+{
+       unsigned soffset, eoffset, wasted;
+
+       soffset = radeon_sa_bo_hole_soffset(sa_manager);
+       eoffset = radeon_sa_bo_hole_eoffset(sa_manager);
+       wasted = (align - (soffset % align)) % align;
+
+       if ((eoffset - soffset) >= (size + wasted)) {
+               soffset += wasted;
+
+               sa_bo->manager = sa_manager;
+               sa_bo->soffset = soffset;
+               sa_bo->eoffset = soffset + size;
+               list_add(&sa_bo->olist, sa_manager->hole);
+               INIT_LIST_HEAD(&sa_bo->flist);
+               sa_manager->hole = &sa_bo->olist;
+               return true;
+       }
+       return false;
+}
+
+static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager,
+                                  struct radeon_fence **fences,
+                                  unsigned *tries)
+{
+       struct radeon_sa_bo *best_bo = NULL;
+       unsigned i, soffset, best, tmp;
+
+       /* if hole points to the end of the buffer */
+       if (sa_manager->hole->next == &sa_manager->olist) {
+               /* try again with its beginning */
+               sa_manager->hole = &sa_manager->olist;
+               return true;
+       }
+
+       soffset = radeon_sa_bo_hole_soffset(sa_manager);
+       /* to handle wrap around we add sa_manager->size */
+       best = sa_manager->size * 2;
+       /* go over all fence list and try to find the closest sa_bo
+        * of the current last
+        */
+       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               struct radeon_sa_bo *sa_bo;
+
+               if (list_empty(&sa_manager->flist[i])) {
+                       continue;
+               }
+
+               sa_bo = list_first_entry(&sa_manager->flist[i],
+                                        struct radeon_sa_bo, flist);
+
+               if (!radeon_fence_signaled(sa_bo->fence)) {
+                       fences[i] = sa_bo->fence;
+                       continue;
+               }
+
+               /* limit the number of tries each ring gets */
+               if (tries[i] > 2) {
+                       continue;
+               }
+
+               tmp = sa_bo->soffset;
+               if (tmp < soffset) {
+                       /* wrap around, pretend it's after */
+                       tmp += sa_manager->size;
+               }
+               tmp -= soffset;
+               if (tmp < best) {
+                       /* this sa bo is the closest one */
+                       best = tmp;
+                       best_bo = sa_bo;
+               }
+       }
+
+       if (best_bo) {
+               ++tries[best_bo->fence->ring];
+               sa_manager->hole = best_bo->olist.prev;
+
+               /* we knew that this one is signaled,
+                  so it's save to remote it */
+               radeon_sa_bo_remove_locked(best_bo);
+               return true;
+       }
+       return false;
+}
+
 int radeon_sa_bo_new(struct radeon_device *rdev,
                     struct radeon_sa_manager *sa_manager,
-                    struct radeon_sa_bo *sa_bo,
-                    unsigned size, unsigned align)
+                    struct radeon_sa_bo **sa_bo,
+                    unsigned size, unsigned align, bool block)
 {
-       struct radeon_sa_bo *tmp;
-       struct list_head *head;
-       unsigned offset = 0, wasted = 0;
+       struct radeon_fence *fences[RADEON_NUM_RINGS];
+       unsigned tries[RADEON_NUM_RINGS];
+       int i, r = -ENOMEM;
 
        BUG_ON(align > RADEON_GPU_PAGE_SIZE);
        BUG_ON(size > sa_manager->size);
 
-       /* no one ? */
-       head = sa_manager->sa_bo.prev;
-       if (list_empty(&sa_manager->sa_bo)) {
-               goto out;
+       *sa_bo = kmalloc(sizeof(struct radeon_sa_bo), GFP_KERNEL);
+       if ((*sa_bo) == NULL) {
+               return -ENOMEM;
        }
+       (*sa_bo)->manager = sa_manager;
+       (*sa_bo)->fence = NULL;
+       INIT_LIST_HEAD(&(*sa_bo)->olist);
+       INIT_LIST_HEAD(&(*sa_bo)->flist);
 
-       /* look for a hole big enough */
-       offset = 0;
-       list_for_each_entry(tmp, &sa_manager->sa_bo, list) {
-               /* room before this object ? */
-               if ((tmp->offset - offset) >= size) {
-                       head = tmp->list.prev;
-                       goto out;
+       spin_lock(&sa_manager->lock);
+       do {
+               for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+                       fences[i] = NULL;
+                       tries[i] = 0;
                }
-               offset = tmp->offset + tmp->size;
-               wasted = offset % align;
-               if (wasted) {
-                       wasted = align - wasted;
+
+               do {
+                       radeon_sa_bo_try_free(sa_manager);
+
+                       if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo,
+                                                  size, align)) {
+                               spin_unlock(&sa_manager->lock);
+                               return 0;
+                       }
+
+                       /* see if we can skip over some allocations */
+               } while (radeon_sa_bo_next_hole(sa_manager, fences, tries));
+
+               if (block) {
+                       spin_unlock(&sa_manager->lock);
+                       r = radeon_fence_wait_any(rdev, fences, false);
+                       spin_lock(&sa_manager->lock);
+                       if (r) {
+                               /* if we have nothing to wait for we
+                                  are practically out of memory */
+                               if (r == -ENOENT) {
+                                       r = -ENOMEM;
+                               }
+                               goto out_err;
+                       }
                }
-               offset += wasted;
-       }
-       /* room at the end ? */
-       head = sa_manager->sa_bo.prev;
-       tmp = list_entry(head, struct radeon_sa_bo, list);
-       offset = tmp->offset + tmp->size;
-       wasted = offset % align;
-       if (wasted) {
-               wasted = align - wasted;
-       }
-       offset += wasted;
-       if ((sa_manager->size - offset) < size) {
-               /* failed to find somethings big enough */
-               return -ENOMEM;
+       } while (block);
+
+out_err:
+       spin_unlock(&sa_manager->lock);
+       kfree(*sa_bo);
+       *sa_bo = NULL;
+       return r;
+}
+
+void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo,
+                      struct radeon_fence *fence)
+{
+       struct radeon_sa_manager *sa_manager;
+
+       if (sa_bo == NULL || *sa_bo == NULL) {
+               return;
        }
 
-out:
-       sa_bo->manager = sa_manager;
-       sa_bo->offset = offset;
-       sa_bo->size = size;
-       list_add(&sa_bo->list, head);
-       return 0;
+       sa_manager = (*sa_bo)->manager;
+       spin_lock(&sa_manager->lock);
+       if (fence && fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) {
+               (*sa_bo)->fence = radeon_fence_ref(fence);
+               list_add_tail(&(*sa_bo)->flist,
+                             &sa_manager->flist[fence->ring]);
+       } else {
+               radeon_sa_bo_remove_locked(*sa_bo);
+       }
+       spin_unlock(&sa_manager->lock);
+       *sa_bo = NULL;
 }
 
-void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo *sa_bo)
+#if defined(CONFIG_DEBUG_FS)
+void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
+                                 struct seq_file *m)
 {
-       list_del_init(&sa_bo->list);
+       struct radeon_sa_bo *i;
+
+       spin_lock(&sa_manager->lock);
+       list_for_each_entry(i, &sa_manager->olist, olist) {
+               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);
+               if (i->fence) {
+                       seq_printf(m, " protected by 0x%016llx on ring %d",
+                                  i->fence->seq, i->fence->ring);
+               }
+               seq_printf(m, "\n");
+       }
+       spin_unlock(&sa_manager->lock);
 }
+#endif
index 61dd4e3c9209692aaefbd6c4104235300a9d0314..e2ace5dce11710adafb9427a7dd62eaac3f66947 100644 (file)
 #include "drm.h"
 #include "radeon.h"
 
-static int radeon_semaphore_add_bo(struct radeon_device *rdev)
-{
-       struct radeon_semaphore_bo *bo;
-       unsigned long irq_flags;
-       uint64_t gpu_addr;
-       uint32_t *cpu_ptr;
-       int r, i;
-
-
-       bo = kmalloc(sizeof(struct radeon_semaphore_bo), GFP_KERNEL);
-       if (bo == NULL) {
-               return -ENOMEM;
-       }
-       INIT_LIST_HEAD(&bo->free);
-       INIT_LIST_HEAD(&bo->list);
-       bo->nused = 0;
-
-       r = radeon_ib_get(rdev, 0, &bo->ib, RADEON_SEMAPHORE_BO_SIZE);
-       if (r) {
-               dev_err(rdev->dev, "failed to get a bo after 5 retry\n");
-               kfree(bo);
-               return r;
-       }
-       gpu_addr = rdev->ib_pool.sa_manager.gpu_addr;
-       gpu_addr += bo->ib->sa_bo.offset;
-       cpu_ptr = rdev->ib_pool.sa_manager.cpu_ptr;
-       cpu_ptr += (bo->ib->sa_bo.offset >> 2);
-       for (i = 0; i < (RADEON_SEMAPHORE_BO_SIZE/8); i++) {
-               bo->semaphores[i].gpu_addr = gpu_addr;
-               bo->semaphores[i].cpu_ptr = cpu_ptr;
-               bo->semaphores[i].bo = bo;
-               list_add_tail(&bo->semaphores[i].list, &bo->free);
-               gpu_addr += 8;
-               cpu_ptr += 2;
-       }
-       write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-       list_add_tail(&bo->list, &rdev->semaphore_drv.bo);
-       write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
-       return 0;
-}
-
-static void radeon_semaphore_del_bo_locked(struct radeon_device *rdev,
-                                          struct radeon_semaphore_bo *bo)
-{
-       radeon_sa_bo_free(rdev, &bo->ib->sa_bo);
-       radeon_fence_unref(&bo->ib->fence);
-       list_del(&bo->list);
-       kfree(bo);
-}
-
-void radeon_semaphore_shrink_locked(struct radeon_device *rdev)
-{
-       struct radeon_semaphore_bo *bo, *n;
-
-       if (list_empty(&rdev->semaphore_drv.bo)) {
-               return;
-       }
-       /* only shrink if first bo has free semaphore */
-       bo = list_first_entry(&rdev->semaphore_drv.bo, struct radeon_semaphore_bo, list);
-       if (list_empty(&bo->free)) {
-               return;
-       }
-       list_for_each_entry_safe_continue(bo, n, &rdev->semaphore_drv.bo, list) {
-               if (bo->nused)
-                       continue;
-               radeon_semaphore_del_bo_locked(rdev, bo);
-       }
-}
 
 int radeon_semaphore_create(struct radeon_device *rdev,
                            struct radeon_semaphore **semaphore)
 {
-       struct radeon_semaphore_bo *bo;
-       unsigned long irq_flags;
-       bool do_retry = true;
        int r;
 
-retry:
-       *semaphore = NULL;
-       write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-       list_for_each_entry(bo, &rdev->semaphore_drv.bo, list) {
-               if (list_empty(&bo->free))
-                       continue;
-               *semaphore = list_first_entry(&bo->free, struct radeon_semaphore, list);
-               (*semaphore)->cpu_ptr[0] = 0;
-               (*semaphore)->cpu_ptr[1] = 0;
-               list_del(&(*semaphore)->list);
-               bo->nused++;
-               break;
-       }
-       write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
-
+       *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
        if (*semaphore == NULL) {
-               if (do_retry) {
-                       do_retry = false;
-                       r = radeon_semaphore_add_bo(rdev);
-                       if (r)
-                               return r;
-                       goto retry;
-               }
                return -ENOMEM;
        }
-
+       r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo,
+                            &(*semaphore)->sa_bo, 8, 8, true);
+       if (r) {
+               kfree(*semaphore);
+               *semaphore = NULL;
+               return r;
+       }
+       (*semaphore)->waiters = 0;
+       (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo);
+       *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0;
        return 0;
 }
 
 void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
                                  struct radeon_semaphore *semaphore)
 {
+       --semaphore->waiters;
        radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false);
 }
 
 void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
                                struct radeon_semaphore *semaphore)
 {
+       ++semaphore->waiters;
        radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true);
 }
 
-void radeon_semaphore_free(struct radeon_device *rdev,
-                          struct radeon_semaphore *semaphore)
+int radeon_semaphore_sync_rings(struct radeon_device *rdev,
+                               struct radeon_semaphore *semaphore,
+                               bool sync_to[RADEON_NUM_RINGS],
+                               int dst_ring)
 {
-       unsigned long irq_flags;
+       int i = 0, r;
+
+       mutex_lock(&rdev->ring_lock);
+       r = radeon_ring_alloc(rdev, &rdev->ring[dst_ring], RADEON_NUM_RINGS * 8);
+       if (r) {
+               goto error;
+       }
+
+       for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+               /* no need to sync to our own or unused rings */
+               if (!sync_to[i] || i == dst_ring)
+                       continue;
 
-       write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-       semaphore->bo->nused--;
-       list_add_tail(&semaphore->list, &semaphore->bo->free);
-       radeon_semaphore_shrink_locked(rdev);
-       write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
+               /* prevent GPU deadlocks */
+               if (!rdev->ring[i].ready) {
+                       dev_err(rdev->dev, "Trying to sync to a disabled ring!");
+                       r = -EINVAL;
+                       goto error;
+               }
+
+               r = radeon_ring_alloc(rdev, &rdev->ring[i], 8);
+               if (r) {
+                       goto error;
+               }
+
+               radeon_semaphore_emit_signal(rdev, i, semaphore);
+               radeon_semaphore_emit_wait(rdev, dst_ring, semaphore);
+
+               radeon_ring_commit(rdev, &rdev->ring[i]);
+       }
+
+       radeon_ring_commit(rdev, &rdev->ring[dst_ring]);
+       mutex_unlock(&rdev->ring_lock);
+
+       return 0;
+
+error:
+       /* unlock all locks taken so far */
+       for (--i; i >= 0; --i) {
+               if (sync_to[i] || i == dst_ring) {
+                       radeon_ring_undo(&rdev->ring[i]);
+               }
+       }
+       radeon_ring_undo(&rdev->ring[dst_ring]);
+       mutex_unlock(&rdev->ring_lock);
+       return r;
 }
 
-void radeon_semaphore_driver_fini(struct radeon_device *rdev)
+void radeon_semaphore_free(struct radeon_device *rdev,
+                          struct radeon_semaphore *semaphore,
+                          struct radeon_fence *fence)
 {
-       struct radeon_semaphore_bo *bo, *n;
-       unsigned long irq_flags;
-
-       write_lock_irqsave(&rdev->semaphore_drv.lock, irq_flags);
-       /* we force to free everything */
-       list_for_each_entry_safe(bo, n, &rdev->semaphore_drv.bo, list) {
-               if (!list_empty(&bo->free)) {
-                       dev_err(rdev->dev, "still in use semaphore\n");
-               }
-               radeon_semaphore_del_bo_locked(rdev, bo);
+       if (semaphore == NULL) {
+               return;
+       }
+       if (semaphore->waiters > 0) {
+               dev_err(rdev->dev, "semaphore %p has more waiters than signalers,"
+                       " hardware lockup imminent!\n", semaphore);
        }
-       write_unlock_irqrestore(&rdev->semaphore_drv.lock, irq_flags);
+       radeon_sa_bo_free(rdev, &semaphore->sa_bo, fence);
+       kfree(semaphore);
 }
index dc5dcf483aa3c0217c85a2db318ac07542754dde..b05738762790504c4495ce39ab664892a7e77498 100644 (file)
@@ -317,7 +317,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
 
 out_cleanup:
        if (semaphore)
-               radeon_semaphore_free(rdev, semaphore);
+               radeon_semaphore_free(rdev, semaphore, NULL);
 
        if (fence1)
                radeon_fence_unref(&fence1);
@@ -437,7 +437,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev,
 
 out_cleanup:
        if (semaphore)
-               radeon_semaphore_free(rdev, semaphore);
+               radeon_semaphore_free(rdev, semaphore, NULL);
 
        if (fenceA)
                radeon_fence_unref(&fenceA);
index f493c6403af54169fd497b4572a2748df2cdc0e8..0f6aee8aa15289244b39fc9e3747a7bc2b1e11f9 100644 (file)
@@ -222,8 +222,9 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
 {
        struct radeon_device *rdev;
        uint64_t old_start, new_start;
-       struct radeon_fence *fence;
-       int r, i;
+       struct radeon_fence *fence, *old_fence;
+       struct radeon_semaphore *sem = NULL;
+       int r;
 
        rdev = radeon_get_rdev(bo->bdev);
        r = radeon_fence_create(rdev, &fence, radeon_copy_ring_index(rdev));
@@ -242,6 +243,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
                break;
        default:
                DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
+               radeon_fence_unref(&fence);
                return -EINVAL;
        }
        switch (new_mem->mem_type) {
@@ -253,42 +255,36 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
                break;
        default:
                DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
+               radeon_fence_unref(&fence);
                return -EINVAL;
        }
        if (!rdev->ring[radeon_copy_ring_index(rdev)].ready) {
                DRM_ERROR("Trying to move memory with ring turned off.\n");
+               radeon_fence_unref(&fence);
                return -EINVAL;
        }
 
        BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0);
 
        /* sync other rings */
-       if (rdev->family >= CHIP_R600) {
-               for (i = 0; i < RADEON_NUM_RINGS; ++i) {
-                       /* no need to sync to our own or unused rings */
-                       if (i == radeon_copy_ring_index(rdev) || !rdev->ring[i].ready)
-                               continue;
-
-                       if (!fence->semaphore) {
-                               r = radeon_semaphore_create(rdev, &fence->semaphore);
-                               /* FIXME: handle semaphore error */
-                               if (r)
-                                       continue;
-                       }
+       old_fence = bo->sync_obj;
+       if (old_fence && old_fence->ring != fence->ring
+           && !radeon_fence_signaled(old_fence)) {
+               bool sync_to_ring[RADEON_NUM_RINGS] = { };
+               sync_to_ring[old_fence->ring] = true;
+
+               r = radeon_semaphore_create(rdev, &sem);
+               if (r) {
+                       radeon_fence_unref(&fence);
+                       return r;
+               }
 
-                       r = radeon_ring_lock(rdev, &rdev->ring[i], 3);
-                       /* FIXME: handle ring lock error */
-                       if (r)
-                               continue;
-                       radeon_semaphore_emit_signal(rdev, i, fence->semaphore);
-                       radeon_ring_unlock_commit(rdev, &rdev->ring[i]);
-
-                       r = radeon_ring_lock(rdev, &rdev->ring[radeon_copy_ring_index(rdev)], 3);
-                       /* FIXME: handle ring lock error */
-                       if (r)
-                               continue;
-                       radeon_semaphore_emit_wait(rdev, radeon_copy_ring_index(rdev), fence->semaphore);
-                       radeon_ring_unlock_commit(rdev, &rdev->ring[radeon_copy_ring_index(rdev)]);
+               r = radeon_semaphore_sync_rings(rdev, sem,
+                                               sync_to_ring, fence->ring);
+               if (r) {
+                       radeon_semaphore_free(rdev, sem, NULL);
+                       radeon_fence_unref(&fence);
+                       return r;
                }
        }
 
@@ -298,6 +294,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
        /* FIXME: handle copy error */
        r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL,
                                      evict, no_wait_reserve, no_wait_gpu, new_mem);
+       radeon_semaphore_free(rdev, sem, fence);
        radeon_fence_unref(&fence);
        return r;
 }
index 4cf381b3a6d81eee21fdc666d24001b4d75e34be..a464eb5e2df2c93306585579a5f5c60f43da10e0 100644 (file)
@@ -430,12 +430,9 @@ static int rs400_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        return 0;
 }
index d25cf869d08dddaa2e0d9f0aec49e2b173297f54..25f9eef12c42a8caf6d05a0de3b37d5d6d6352a7 100644 (file)
@@ -396,7 +396,6 @@ int rs600_asic_reset(struct radeon_device *rdev)
        /* Check if GPU is idle */
        if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
                dev_err(rdev->dev, "failed to reset GPU\n");
-               rdev->gpu_lockup = true;
                ret = -1;
        } else
                dev_info(rdev->dev, "GPU reset succeed\n");
@@ -553,6 +552,12 @@ int rs600_irq_set(struct radeon_device *rdev)
                ~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1);
        u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) &
                ~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
+       u32 hdmi0;
+       if (ASIC_IS_DCE2(rdev))
+               hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) &
+                       ~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1);
+       else
+               hdmi0 = 0;
 
        if (!rdev->irq.installed) {
                WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@@ -579,10 +584,15 @@ int rs600_irq_set(struct radeon_device *rdev)
        if (rdev->irq.hpd[1]) {
                hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
        }
+       if (rdev->irq.afmt[0]) {
+               hdmi0 |= S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1);
+       }
        WREG32(R_000040_GEN_INT_CNTL, tmp);
        WREG32(R_006540_DxMODE_INT_MASK, mode_int);
        WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
        WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
+       if (ASIC_IS_DCE2(rdev))
+               WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
        return 0;
 }
 
@@ -622,6 +632,17 @@ static inline u32 rs600_irq_ack(struct radeon_device *rdev)
                rdev->irq.stat_regs.r500.disp_int = 0;
        }
 
+       if (ASIC_IS_DCE2(rdev)) {
+               rdev->irq.stat_regs.r500.hdmi0_status = RREG32(R_007404_HDMI0_STATUS) &
+                       S_007404_HDMI0_AZ_FORMAT_WTRIG(1);
+               if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) {
+                       tmp = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL);
+                       tmp |= S_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(1);
+                       WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, tmp);
+               }
+       } else
+               rdev->irq.stat_regs.r500.hdmi0_status = 0;
+
        if (irqs) {
                WREG32(R_000044_GEN_INT_STATUS, irqs);
        }
@@ -630,6 +651,9 @@ static inline u32 rs600_irq_ack(struct radeon_device *rdev)
 
 void rs600_irq_disable(struct radeon_device *rdev)
 {
+       u32 hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) &
+               ~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1);
+       WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
        WREG32(R_000040_GEN_INT_CNTL, 0);
        WREG32(R_006540_DxMODE_INT_MASK, 0);
        /* Wait and acknowledge irq */
@@ -641,15 +665,20 @@ int rs600_irq_process(struct radeon_device *rdev)
 {
        u32 status, msi_rearm;
        bool queue_hotplug = false;
+       bool queue_hdmi = false;
 
        /* reset gui idle ack.  the status bit is broken */
        rdev->irq.gui_idle_acked = false;
 
        status = rs600_irq_ack(rdev);
-       if (!status && !rdev->irq.stat_regs.r500.disp_int) {
+       if (!status &&
+           !rdev->irq.stat_regs.r500.disp_int &&
+           !rdev->irq.stat_regs.r500.hdmi0_status) {
                return IRQ_NONE;
        }
-       while (status || rdev->irq.stat_regs.r500.disp_int) {
+       while (status ||
+              rdev->irq.stat_regs.r500.disp_int ||
+              rdev->irq.stat_regs.r500.hdmi0_status) {
                /* SW interrupt */
                if (G_000044_SW_INT(status)) {
                        radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX);
@@ -687,12 +716,18 @@ int rs600_irq_process(struct radeon_device *rdev)
                        queue_hotplug = true;
                        DRM_DEBUG("HPD2\n");
                }
+               if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) {
+                       queue_hdmi = true;
+                       DRM_DEBUG("HDMI0\n");
+               }
                status = rs600_irq_ack(rdev);
        }
        /* reset gui idle ack.  the status bit is broken */
        rdev->irq.gui_idle_acked = false;
        if (queue_hotplug)
                schedule_work(&rdev->hotplug_work);
+       if (queue_hdmi)
+               schedule_work(&rdev->audio_work);
        if (rdev->msi_enabled) {
                switch (rdev->family) {
                case CHIP_RS600:
@@ -883,12 +918,9 @@ static int rs600_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        return 0;
 }
index a27c13ac47c312ade8ca5ceee9ed45a3d59fcff4..f1f89414dc6366b4d65f9216a5063ebcb58867f6 100644 (file)
 #define   S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x)       (((x) & 0x1) << 16)
 #define   G_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x)       (((x) >> 16) & 0x1)
 #define   C_007D18_DC_HOT_PLUG_DETECT2_INT_EN          0xFFFEFFFF
+#define R_007404_HDMI0_STATUS                          0x007404
+#define   S_007404_HDMI0_AZ_FORMAT_WTRIG(x)            (((x) & 0x1) << 28)
+#define   G_007404_HDMI0_AZ_FORMAT_WTRIG(x)            (((x) >> 28) & 0x1)
+#define   C_007404_HDMI0_AZ_FORMAT_WTRIG               0xEFFFFFFF
+#define   S_007404_HDMI0_AZ_FORMAT_WTRIG_INT(x)        (((x) & 0x1) << 29)
+#define   G_007404_HDMI0_AZ_FORMAT_WTRIG_INT(x)        (((x) >> 29) & 0x1)
+#define   C_007404_HDMI0_AZ_FORMAT_WTRIG_INT           0xDFFFFFFF
+#define R_007408_HDMI0_AUDIO_PACKET_CONTROL            0x007408
+#define   S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(x)       (((x) & 0x1) << 28)
+#define   G_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(x)       (((x) >> 28) & 0x1)
+#define   C_007408_HDMI0_AZ_FORMAT_WTRIG_MASK          0xEFFFFFFF
+#define   S_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(x)        (((x) & 0x1) << 29)
+#define   G_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(x)        (((x) >> 29) & 0x1)
+#define   C_007408_HDMI0_AZ_FORMAT_WTRIG_ACK           0xDFFFFFFF
 
 /* MC registers */
 #define R_000000_MC_STATUS                           0x000000
index f2c3b9d75f188d0622a5cdb7c3ad697894546d70..3277ddecfe9fbd7755ba3c6bde888ebb7df68e36 100644 (file)
@@ -647,12 +647,9 @@ static int rs690_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        return 0;
 }
index d8d78fe179469009a4adbaebda77eee13fcd7802..7f08cedb533315f3c8102c8e1163141aede82068 100644 (file)
@@ -412,12 +412,10 @@ static int rv515_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "failed testing IB (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
+
        return 0;
 }
 
index c62ae4be3845f02df5934304d3b90e7b8582588c..40f82e22a621325fa26d76d4aa635b27cdd7b0bb 100644 (file)
@@ -969,7 +969,7 @@ void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
        }
        if (rdev->flags & RADEON_IS_AGP) {
                size_bf = mc->gtt_start;
-               size_af = 0xFFFFFFFF - mc->gtt_end + 1;
+               size_af = 0xFFFFFFFF - mc->gtt_end;
                if (size_bf > size_af) {
                        if (mc->mc_vram_size > size_bf) {
                                dev_warn(rdev->dev, "limiting VRAM\n");
@@ -983,7 +983,7 @@ void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
                                mc->real_vram_size = size_af;
                                mc->mc_vram_size = size_af;
                        }
-                       mc->vram_start = mc->gtt_end;
+                       mc->vram_start = mc->gtt_end + 1;
                }
                mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
                dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
@@ -1114,12 +1114,9 @@ static int rv770_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
-       if (r) {
-               dev_err(rdev->dev, "IB test failed (%d).\n", r);
-               rdev->accel_working = false;
+       r = radeon_ib_ring_tests(rdev);
+       if (r)
                return r;
-       }
 
        return 0;
 }
@@ -1281,7 +1278,6 @@ void rv770_fini(struct radeon_device *rdev)
        rv770_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
-       radeon_semaphore_driver_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_agp_fini(rdev);
        radeon_bo_fini(rdev);
index 79fa588e9ed56d76bbaa73683a765759d5a524f8..9c549f702f2f35e995db4b88ffb31ad5b4d21e9b 100644 (file)
 
 #define        SRBM_STATUS                                     0x0E50
 
+/* DCE 3.2 HDMI */
+#define HDMI_CONTROL                         0x7400
+#       define HDMI_KEEPOUT_MODE             (1 << 0)
+#       define HDMI_PACKET_GEN_VERSION       (1 << 4) /* 0 = r6xx compat */
+#       define HDMI_ERROR_ACK                (1 << 8)
+#       define HDMI_ERROR_MASK               (1 << 9)
+#define HDMI_STATUS                          0x7404
+#       define HDMI_ACTIVE_AVMUTE            (1 << 0)
+#       define HDMI_AUDIO_PACKET_ERROR       (1 << 16)
+#       define HDMI_VBI_PACKET_ERROR         (1 << 20)
+#define HDMI_AUDIO_PACKET_CONTROL            0x7408
+#       define HDMI_AUDIO_DELAY_EN(x)        (((x) & 3) << 4)
+#       define HDMI_AUDIO_PACKETS_PER_LINE(x)  (((x) & 0x1f) << 16)
+#define HDMI_ACR_PACKET_CONTROL              0x740c
+#       define HDMI_ACR_SEND                 (1 << 0)
+#       define HDMI_ACR_CONT                 (1 << 1)
+#       define HDMI_ACR_SELECT(x)            (((x) & 3) << 4)
+#       define HDMI_ACR_HW                   0
+#       define HDMI_ACR_32                   1
+#       define HDMI_ACR_44                   2
+#       define HDMI_ACR_48                   3
+#       define HDMI_ACR_SOURCE               (1 << 8) /* 0 - hw; 1 - cts value */
+#       define HDMI_ACR_AUTO_SEND            (1 << 12)
+#define HDMI_VBI_PACKET_CONTROL              0x7410
+#       define HDMI_NULL_SEND                (1 << 0)
+#       define HDMI_GC_SEND                  (1 << 4)
+#       define HDMI_GC_CONT                  (1 << 5) /* 0 - once; 1 - every frame */
+#define HDMI_INFOFRAME_CONTROL0              0x7414
+#       define HDMI_AVI_INFO_SEND            (1 << 0)
+#       define HDMI_AVI_INFO_CONT            (1 << 1)
+#       define HDMI_AUDIO_INFO_SEND          (1 << 4)
+#       define HDMI_AUDIO_INFO_CONT          (1 << 5)
+#       define HDMI_MPEG_INFO_SEND           (1 << 8)
+#       define HDMI_MPEG_INFO_CONT           (1 << 9)
+#define HDMI_INFOFRAME_CONTROL1              0x7418
+#       define HDMI_AVI_INFO_LINE(x)         (((x) & 0x3f) << 0)
+#       define HDMI_AUDIO_INFO_LINE(x)       (((x) & 0x3f) << 8)
+#       define HDMI_MPEG_INFO_LINE(x)        (((x) & 0x3f) << 16)
+#define HDMI_GENERIC_PACKET_CONTROL          0x741c
+#       define HDMI_GENERIC0_SEND            (1 << 0)
+#       define HDMI_GENERIC0_CONT            (1 << 1)
+#       define HDMI_GENERIC1_SEND            (1 << 4)
+#       define HDMI_GENERIC1_CONT            (1 << 5)
+#       define HDMI_GENERIC0_LINE(x)         (((x) & 0x3f) << 16)
+#       define HDMI_GENERIC1_LINE(x)         (((x) & 0x3f) << 24)
+#define HDMI_GC                              0x7428
+#       define HDMI_GC_AVMUTE                (1 << 0)
+#define AFMT_AUDIO_PACKET_CONTROL2           0x742c
+#       define AFMT_AUDIO_LAYOUT_OVRD        (1 << 0)
+#       define AFMT_AUDIO_LAYOUT_SELECT      (1 << 1)
+#       define AFMT_60958_CS_SOURCE          (1 << 4)
+#       define AFMT_AUDIO_CHANNEL_ENABLE(x)  (((x) & 0xff) << 8)
+#       define AFMT_DP_AUDIO_STREAM_ID(x)    (((x) & 0xff) << 16)
+#define AFMT_AVI_INFO0                       0x7454
+#       define AFMT_AVI_INFO_CHECKSUM(x)     (((x) & 0xff) << 0)
+#       define AFMT_AVI_INFO_S(x)            (((x) & 3) << 8)
+#       define AFMT_AVI_INFO_B(x)            (((x) & 3) << 10)
+#       define AFMT_AVI_INFO_A(x)            (((x) & 1) << 12)
+#       define AFMT_AVI_INFO_Y(x)            (((x) & 3) << 13)
+#       define AFMT_AVI_INFO_Y_RGB           0
+#       define AFMT_AVI_INFO_Y_YCBCR422      1
+#       define AFMT_AVI_INFO_Y_YCBCR444      2
+#       define AFMT_AVI_INFO_Y_A_B_S(x)      (((x) & 0xff) << 8)
+#       define AFMT_AVI_INFO_R(x)            (((x) & 0xf) << 16)
+#       define AFMT_AVI_INFO_M(x)            (((x) & 0x3) << 20)
+#       define AFMT_AVI_INFO_C(x)            (((x) & 0x3) << 22)
+#       define AFMT_AVI_INFO_C_M_R(x)        (((x) & 0xff) << 16)
+#       define AFMT_AVI_INFO_SC(x)           (((x) & 0x3) << 24)
+#       define AFMT_AVI_INFO_Q(x)            (((x) & 0x3) << 26)
+#       define AFMT_AVI_INFO_EC(x)           (((x) & 0x3) << 28)
+#       define AFMT_AVI_INFO_ITC(x)          (((x) & 0x1) << 31)
+#       define AFMT_AVI_INFO_ITC_EC_Q_SC(x)  (((x) & 0xff) << 24)
+#define AFMT_AVI_INFO1                       0x7458
+#       define AFMT_AVI_INFO_VIC(x)          (((x) & 0x7f) << 0) /* don't use avi infoframe v1 */
+#       define AFMT_AVI_INFO_PR(x)           (((x) & 0xf) << 8) /* don't use avi infoframe v1 */
+#       define AFMT_AVI_INFO_TOP(x)          (((x) & 0xffff) << 16)
+#define AFMT_AVI_INFO2                       0x745c
+#       define AFMT_AVI_INFO_BOTTOM(x)       (((x) & 0xffff) << 0)
+#       define AFMT_AVI_INFO_LEFT(x)         (((x) & 0xffff) << 16)
+#define AFMT_AVI_INFO3                       0x7460
+#       define AFMT_AVI_INFO_RIGHT(x)        (((x) & 0xffff) << 0)
+#       define AFMT_AVI_INFO_VERSION(x)      (((x) & 3) << 24)
+#define AFMT_MPEG_INFO0                      0x7464
+#       define AFMT_MPEG_INFO_CHECKSUM(x)    (((x) & 0xff) << 0)
+#       define AFMT_MPEG_INFO_MB0(x)         (((x) & 0xff) << 8)
+#       define AFMT_MPEG_INFO_MB1(x)         (((x) & 0xff) << 16)
+#       define AFMT_MPEG_INFO_MB2(x)         (((x) & 0xff) << 24)
+#define AFMT_MPEG_INFO1                      0x7468
+#       define AFMT_MPEG_INFO_MB3(x)         (((x) & 0xff) << 0)
+#       define AFMT_MPEG_INFO_MF(x)          (((x) & 3) << 8)
+#       define AFMT_MPEG_INFO_FR(x)          (((x) & 1) << 12)
+#define AFMT_GENERIC0_HDR                    0x746c
+#define AFMT_GENERIC0_0                      0x7470
+#define AFMT_GENERIC0_1                      0x7474
+#define AFMT_GENERIC0_2                      0x7478
+#define AFMT_GENERIC0_3                      0x747c
+#define AFMT_GENERIC0_4                      0x7480
+#define AFMT_GENERIC0_5                      0x7484
+#define AFMT_GENERIC0_6                      0x7488
+#define AFMT_GENERIC1_HDR                    0x748c
+#define AFMT_GENERIC1_0                      0x7490
+#define AFMT_GENERIC1_1                      0x7494
+#define AFMT_GENERIC1_2                      0x7498
+#define AFMT_GENERIC1_3                      0x749c
+#define AFMT_GENERIC1_4                      0x74a0
+#define AFMT_GENERIC1_5                      0x74a4
+#define AFMT_GENERIC1_6                      0x74a8
+#define HDMI_ACR_32_0                        0x74ac
+#       define HDMI_ACR_CTS_32(x)            (((x) & 0xfffff) << 12)
+#define HDMI_ACR_32_1                        0x74b0
+#       define HDMI_ACR_N_32(x)              (((x) & 0xfffff) << 0)
+#define HDMI_ACR_44_0                        0x74b4
+#       define HDMI_ACR_CTS_44(x)            (((x) & 0xfffff) << 12)
+#define HDMI_ACR_44_1                        0x74b8
+#       define HDMI_ACR_N_44(x)              (((x) & 0xfffff) << 0)
+#define HDMI_ACR_48_0                        0x74bc
+#       define HDMI_ACR_CTS_48(x)            (((x) & 0xfffff) << 12)
+#define HDMI_ACR_48_1                        0x74c0
+#       define HDMI_ACR_N_48(x)              (((x) & 0xfffff) << 0)
+#define HDMI_ACR_STATUS_0                    0x74c4
+#define HDMI_ACR_STATUS_1                    0x74c8
+#define AFMT_AUDIO_INFO0                     0x74cc
+#       define AFMT_AUDIO_INFO_CHECKSUM(x)   (((x) & 0xff) << 0)
+#       define AFMT_AUDIO_INFO_CC(x)         (((x) & 7) << 8)
+#       define AFMT_AUDIO_INFO_CHECKSUM_OFFSET(x)   (((x) & 0xff) << 16)
+#define AFMT_AUDIO_INFO1                     0x74d0
+#       define AFMT_AUDIO_INFO_CA(x)         (((x) & 0xff) << 0)
+#       define AFMT_AUDIO_INFO_LSV(x)        (((x) & 0xf) << 11)
+#       define AFMT_AUDIO_INFO_DM_INH(x)     (((x) & 1) << 15)
+#       define AFMT_AUDIO_INFO_DM_INH_LSV(x) (((x) & 0xff) << 8)
+#define AFMT_60958_0                         0x74d4
+#       define AFMT_60958_CS_A(x)            (((x) & 1) << 0)
+#       define AFMT_60958_CS_B(x)            (((x) & 1) << 1)
+#       define AFMT_60958_CS_C(x)            (((x) & 1) << 2)
+#       define AFMT_60958_CS_D(x)            (((x) & 3) << 3)
+#       define AFMT_60958_CS_MODE(x)         (((x) & 3) << 6)
+#       define AFMT_60958_CS_CATEGORY_CODE(x)      (((x) & 0xff) << 8)
+#       define AFMT_60958_CS_SOURCE_NUMBER(x)      (((x) & 0xf) << 16)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_L(x)   (((x) & 0xf) << 20)
+#       define AFMT_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24)
+#       define AFMT_60958_CS_CLOCK_ACCURACY(x)     (((x) & 3) << 28)
+#define AFMT_60958_1                         0x74d8
+#       define AFMT_60958_CS_WORD_LENGTH(x)  (((x) & 0xf) << 0)
+#       define AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY(x)   (((x) & 0xf) << 4)
+#       define AFMT_60958_CS_VALID_L(x)      (((x) & 1) << 16)
+#       define AFMT_60958_CS_VALID_R(x)      (((x) & 1) << 18)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_R(x)   (((x) & 0xf) << 20)
+#define AFMT_AUDIO_CRC_CONTROL               0x74dc
+#       define AFMT_AUDIO_CRC_EN             (1 << 0)
+#define AFMT_RAMP_CONTROL0                   0x74e0
+#       define AFMT_RAMP_MAX_COUNT(x)        (((x) & 0xffffff) << 0)
+#       define AFMT_RAMP_DATA_SIGN           (1 << 31)
+#define AFMT_RAMP_CONTROL1                   0x74e4
+#       define AFMT_RAMP_MIN_COUNT(x)        (((x) & 0xffffff) << 0)
+#       define AFMT_AUDIO_TEST_CH_DISABLE(x) (((x) & 0xff) << 24)
+#define AFMT_RAMP_CONTROL2                   0x74e8
+#       define AFMT_RAMP_INC_COUNT(x)        (((x) & 0xffffff) << 0)
+#define AFMT_RAMP_CONTROL3                   0x74ec
+#       define AFMT_RAMP_DEC_COUNT(x)        (((x) & 0xffffff) << 0)
+#define AFMT_60958_2                         0x74f0
+#       define AFMT_60958_CS_CHANNEL_NUMBER_2(x)   (((x) & 0xf) << 0)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_3(x)   (((x) & 0xf) << 4)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_4(x)   (((x) & 0xf) << 8)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_5(x)   (((x) & 0xf) << 12)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_6(x)   (((x) & 0xf) << 16)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_7(x)   (((x) & 0xf) << 20)
+#define AFMT_STATUS                          0x7600
+#       define AFMT_AUDIO_ENABLE             (1 << 4)
+#       define AFMT_AZ_FORMAT_WTRIG          (1 << 28)
+#       define AFMT_AZ_FORMAT_WTRIG_INT      (1 << 29)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG      (1 << 30)
+#define AFMT_AUDIO_PACKET_CONTROL            0x7604
+#       define AFMT_AUDIO_SAMPLE_SEND        (1 << 0)
+#       define AFMT_AUDIO_TEST_EN            (1 << 12)
+#       define AFMT_AUDIO_CHANNEL_SWAP       (1 << 24)
+#       define AFMT_60958_CS_UPDATE          (1 << 26)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG_MASK (1 << 27)
+#       define AFMT_AZ_FORMAT_WTRIG_MASK     (1 << 28)
+#       define AFMT_AZ_FORMAT_WTRIG_ACK      (1 << 29)
+#       define AFMT_AZ_AUDIO_ENABLE_CHG_ACK  (1 << 30)
+#define AFMT_VBI_PACKET_CONTROL              0x7608
+#       define AFMT_GENERIC0_UPDATE          (1 << 2)
+#define AFMT_INFOFRAME_CONTROL0              0x760c
+#       define AFMT_AUDIO_INFO_SOURCE        (1 << 6) /* 0 - sound block; 1 - hmdi regs */
+#       define AFMT_AUDIO_INFO_UPDATE        (1 << 7)
+#       define AFMT_MPEG_INFO_UPDATE         (1 << 10)
+#define AFMT_GENERIC0_7                      0x7610
+/* second instance starts at 0x7800 */
+#define HDMI_OFFSET0                      (0x7400 - 0x7400)
+#define HDMI_OFFSET1                      (0x7800 - 0x7400)
+
 #define D1GRPH_PRIMARY_SURFACE_ADDRESS                    0x6110
 #define D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH               0x6914
 #define D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH               0x6114
index ac7a199ffece9cd3df519187561aa2b6a5617f59..be3b9fd6c931b0ca4234757a73c473114b8b23db 100644 (file)
@@ -2217,8 +2217,6 @@ bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
        u32 srbm_status;
        u32 grbm_status, grbm_status2;
        u32 grbm_status_se0, grbm_status_se1;
-       struct r100_gpu_lockup *lockup = &rdev->config.si.lockup;
-       int r;
 
        srbm_status = RREG32(SRBM_STATUS);
        grbm_status = RREG32(GRBM_STATUS);
@@ -2226,20 +2224,12 @@ bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
        grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
        grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
        if (!(grbm_status & GUI_ACTIVE)) {
-               r100_gpu_lockup_update(lockup, ring);
+               radeon_ring_lockup_update(ring);
                return false;
        }
        /* force CP activities */
-       r = radeon_ring_lock(rdev, ring, 2);
-       if (!r) {
-               /* PACKET2 NOP */
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_write(ring, 0x80000000);
-               radeon_ring_unlock_commit(rdev, ring);
-       }
-       /* XXX deal with CP0,1,2 */
-       ring->rptr = RREG32(ring->rptr_reg);
-       return r100_gpu_cp_is_lockup(rdev, lockup, ring);
+       radeon_ring_force_activity(rdev, ring);
+       return radeon_ring_test_lockup(rdev, ring);
 }
 
 static int si_gpu_soft_reset(struct radeon_device *rdev)
@@ -2999,8 +2989,8 @@ int si_rlc_init(struct radeon_device *rdev)
        }
        r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM,
                          &rdev->rlc.save_restore_gpu_addr);
+       radeon_bo_unreserve(rdev->rlc.save_restore_obj);
        if (r) {
-               radeon_bo_unreserve(rdev->rlc.save_restore_obj);
                dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r);
                si_rlc_fini(rdev);
                return r;
@@ -3023,9 +3013,8 @@ int si_rlc_init(struct radeon_device *rdev)
        }
        r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM,
                          &rdev->rlc.clear_state_gpu_addr);
+       radeon_bo_unreserve(rdev->rlc.clear_state_obj);
        if (r) {
-
-               radeon_bo_unreserve(rdev->rlc.clear_state_obj);
                dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r);
                si_rlc_fini(rdev);
                return r;
@@ -3217,6 +3206,8 @@ static int si_irq_init(struct radeon_device *rdev)
        /* force the active interrupt state to all disabled */
        si_disable_interrupt_state(rdev);
 
+       pci_set_master(rdev->pdev);
+
        /* enable irqs */
        si_enable_interrupts(rdev);
 
@@ -4118,7 +4109,6 @@ void si_fini(struct radeon_device *rdev)
        si_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
-       radeon_semaphore_driver_fini(rdev);
        radeon_fence_driver_fini(rdev);
        radeon_bo_fini(rdev);
        radeon_atombios_fini(rdev);
index 031aaaf79ac2da2c2972dfbadade2530877a55cb..b6d8608375cde6b0063796d83ae763b4bd1b14db 100644 (file)
@@ -988,7 +988,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
         * for locking on FreeBSD.
         */
        if (cmdbuf->size) {
-               kcmd_addr = kmalloc(cmdbuf->size * 8, GFP_KERNEL);
+               kcmd_addr = kmalloc_array(cmdbuf->size, 8, GFP_KERNEL);
                if (kcmd_addr == NULL)
                        return -ENOMEM;
 
@@ -1015,8 +1015,8 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
                cmdbuf->vb_addr = kvb_addr;
        }
        if (cmdbuf->nbox) {
-               kbox_addr = kmalloc(cmdbuf->nbox * sizeof(struct drm_clip_rect),
-                                   GFP_KERNEL);
+               kbox_addr = kmalloc_array(cmdbuf->nbox, sizeof(struct drm_clip_rect),
+                                         GFP_KERNEL);
                if (kbox_addr == NULL) {
                        ret = -ENOMEM;
                        goto done;
index 5340c5f3987b0831d7d11f9c7a8c55735f14c4f5..53673907a6a0d93cf9367b62fdad247939bc70d3 100644 (file)
@@ -47,7 +47,7 @@ static struct vm_operations_struct udl_gem_vm_ops = {
 static const struct file_operations udl_driver_fops = {
        .owner = THIS_MODULE,
        .open = drm_open,
-       .mmap = drm_gem_mmap,
+       .mmap = udl_drm_gem_mmap,
        .poll = drm_poll,
        .read = drm_read,
        .unlocked_ioctl = drm_ioctl,
index 1612954a5bc4452e20bffdb30ab8e66b86f9e4cf..96820d03a30394a9e6b5eb8c42e528b5459ff931 100644 (file)
@@ -121,6 +121,7 @@ struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,
 
 int udl_gem_vmap(struct udl_gem_object *obj);
 void udl_gem_vunmap(struct udl_gem_object *obj);
+int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 
 int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
index 852642dc11878ff912682628c097e8757bc7acb5..92f19ef329b0319819e47b57a007538275c93eaa 100644 (file)
@@ -71,6 +71,20 @@ int udl_dumb_destroy(struct drm_file *file, struct drm_device *dev,
        return drm_gem_handle_delete(file, handle);
 }
 
+int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       int ret;
+
+       ret = drm_gem_mmap(filp, vma);
+       if (ret)
+               return ret;
+
+       vma->vm_flags &= ~VM_PFNMAP;
+       vma->vm_flags |= VM_MIXEDMAP;
+
+       return ret;
+}
+
 int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct udl_gem_object *obj = to_udl_bo(vma->vm_private_data);
index 96c83a9a76bb8f54c4d7615f217f9f82127c66fd..f34838839b08c1f6f2eb64b8fde03265a9a96ef3 100644 (file)
@@ -21,6 +21,7 @@ config VGA_SWITCHEROO
        bool "Laptop Hybrid Graphics - GPU switching support"
        depends on X86
        depends on ACPI
+       select VGA_ARB
        help
          Many laptops released in 2008/9/10 have two GPUs with a multiplexer
          to switch between them. This adds support for dynamic switching when
index 58434e804d91c5863c460390addcf10c2530bc29..38f9534ac513bcf51b90fcfff56d6bd6ed84c988 100644 (file)
 #include <linux/pci.h>
 #include <linux/vga_switcheroo.h>
 
+#include <linux/vgaarb.h>
+
 struct vga_switcheroo_client {
        struct pci_dev *pdev;
        struct fb_info *fb_info;
        int pwr_state;
-       void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state);
-       void (*reprobe)(struct pci_dev *pdev);
-       bool (*can_switch)(struct pci_dev *pdev);
+       const struct vga_switcheroo_client_ops *ops;
        int id;
        bool active;
+       struct list_head list;
 };
 
 static DEFINE_MUTEX(vgasr_mutex);
@@ -51,16 +52,23 @@ struct vgasr_priv {
        struct dentry *switch_file;
 
        int registered_clients;
-       struct vga_switcheroo_client clients[VGA_SWITCHEROO_MAX_CLIENTS];
+       struct list_head clients;
 
        struct vga_switcheroo_handler *handler;
 };
 
+#define ID_BIT_AUDIO           0x100
+#define client_is_audio(c)     ((c)->id & ID_BIT_AUDIO)
+#define client_is_vga(c)       ((c)->id == -1 || !client_is_audio(c))
+#define client_id(c)           ((c)->id & ~ID_BIT_AUDIO)
+
 static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv);
 static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv);
 
 /* only one switcheroo per system */
-static struct vgasr_priv vgasr_priv;
+static struct vgasr_priv vgasr_priv = {
+       .clients = LIST_HEAD_INIT(vgasr_priv.clients),
+};
 
 int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
 {
@@ -86,72 +94,119 @@ EXPORT_SYMBOL(vga_switcheroo_unregister_handler);
 
 static void vga_switcheroo_enable(void)
 {
-       int i;
        int ret;
+       struct vga_switcheroo_client *client;
+
        /* call the handler to init */
        vgasr_priv.handler->init();
 
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               ret = vgasr_priv.handler->get_client_id(vgasr_priv.clients[i].pdev);
+       list_for_each_entry(client, &vgasr_priv.clients, list) {
+               if (client->id != -1)
+                       continue;
+               ret = vgasr_priv.handler->get_client_id(client->pdev);
                if (ret < 0)
                        return;
 
-               vgasr_priv.clients[i].id = ret;
+               client->id = ret;
        }
        vga_switcheroo_debugfs_init(&vgasr_priv);
        vgasr_priv.active = true;
 }
 
-int vga_switcheroo_register_client(struct pci_dev *pdev,
-                                  void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state),
-                                  void (*reprobe)(struct pci_dev *pdev),
-                                  bool (*can_switch)(struct pci_dev *pdev))
+static int register_client(struct pci_dev *pdev,
+                          const struct vga_switcheroo_client_ops *ops,
+                          int id, bool active)
 {
-       int index;
+       struct vga_switcheroo_client *client;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (!client)
+               return -ENOMEM;
+
+       client->pwr_state = VGA_SWITCHEROO_ON;
+       client->pdev = pdev;
+       client->ops = ops;
+       client->id = id;
+       client->active = active;
 
        mutex_lock(&vgasr_mutex);
-       /* don't do IGD vs DIS here */
-       if (vgasr_priv.registered_clients & 1)
-               index = 1;
-       else
-               index = 0;
-
-       vgasr_priv.clients[index].pwr_state = VGA_SWITCHEROO_ON;
-       vgasr_priv.clients[index].pdev = pdev;
-       vgasr_priv.clients[index].set_gpu_state = set_gpu_state;
-       vgasr_priv.clients[index].reprobe = reprobe;
-       vgasr_priv.clients[index].can_switch = can_switch;
-       vgasr_priv.clients[index].id = -1;
-       if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
-               vgasr_priv.clients[index].active = true;
-
-       vgasr_priv.registered_clients |= (1 << index);
+       list_add_tail(&client->list, &vgasr_priv.clients);
+       if (client_is_vga(client))
+               vgasr_priv.registered_clients++;
 
        /* if we get two clients + handler */
-       if (vgasr_priv.registered_clients == 0x3 && vgasr_priv.handler) {
+       if (!vgasr_priv.active &&
+           vgasr_priv.registered_clients == 2 && vgasr_priv.handler) {
                printk(KERN_INFO "vga_switcheroo: enabled\n");
                vga_switcheroo_enable();
        }
        mutex_unlock(&vgasr_mutex);
        return 0;
 }
+
+int vga_switcheroo_register_client(struct pci_dev *pdev,
+                                  const struct vga_switcheroo_client_ops *ops)
+{
+       return register_client(pdev, ops, -1,
+                              pdev == vga_default_device());
+}
 EXPORT_SYMBOL(vga_switcheroo_register_client);
 
+int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
+                                        const struct vga_switcheroo_client_ops *ops,
+                                        int id, bool active)
+{
+       return register_client(pdev, ops, id | ID_BIT_AUDIO, active);
+}
+EXPORT_SYMBOL(vga_switcheroo_register_audio_client);
+
+static struct vga_switcheroo_client *
+find_client_from_pci(struct list_head *head, struct pci_dev *pdev)
+{
+       struct vga_switcheroo_client *client;
+       list_for_each_entry(client, head, list)
+               if (client->pdev == pdev)
+                       return client;
+       return NULL;
+}
+
+static struct vga_switcheroo_client *
+find_client_from_id(struct list_head *head, int client_id)
+{
+       struct vga_switcheroo_client *client;
+       list_for_each_entry(client, head, list)
+               if (client->id == client_id)
+                       return client;
+       return NULL;
+}
+
+static struct vga_switcheroo_client *
+find_active_client(struct list_head *head)
+{
+       struct vga_switcheroo_client *client;
+       list_for_each_entry(client, head, list)
+               if (client->active && client_is_vga(client))
+                       return client;
+       return NULL;
+}
+
 void vga_switcheroo_unregister_client(struct pci_dev *pdev)
 {
-       int i;
+       struct vga_switcheroo_client *client;
 
        mutex_lock(&vgasr_mutex);
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               if (vgasr_priv.clients[i].pdev == pdev) {
-                       vgasr_priv.registered_clients &= ~(1 << i);
-                       break;
-               }
+       client = find_client_from_pci(&vgasr_priv.clients, pdev);
+       if (client) {
+               if (client_is_vga(client))
+                       vgasr_priv.registered_clients--;
+               list_del(&client->list);
+               kfree(client);
+       }
+       if (vgasr_priv.active && vgasr_priv.registered_clients < 2) {
+               printk(KERN_INFO "vga_switcheroo: disabled\n");
+               vga_switcheroo_debugfs_fini(&vgasr_priv);
+               vgasr_priv.active = false;
        }
-
-       printk(KERN_INFO "vga_switcheroo: disabled\n");
-       vga_switcheroo_debugfs_fini(&vgasr_priv);
-       vgasr_priv.active = false;
        mutex_unlock(&vgasr_mutex);
 }
 EXPORT_SYMBOL(vga_switcheroo_unregister_client);
@@ -159,29 +214,29 @@ EXPORT_SYMBOL(vga_switcheroo_unregister_client);
 void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
                                 struct fb_info *info)
 {
-       int i;
+       struct vga_switcheroo_client *client;
 
        mutex_lock(&vgasr_mutex);
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               if (vgasr_priv.clients[i].pdev == pdev) {
-                       vgasr_priv.clients[i].fb_info = info;
-                       break;
-               }
-       }
+       client = find_client_from_pci(&vgasr_priv.clients, pdev);
+       if (client)
+               client->fb_info = info;
        mutex_unlock(&vgasr_mutex);
 }
 EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
 
 static int vga_switcheroo_show(struct seq_file *m, void *v)
 {
-       int i;
+       struct vga_switcheroo_client *client;
+       int i = 0;
        mutex_lock(&vgasr_mutex);
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               seq_printf(m, "%d:%s:%c:%s:%s\n", i,
-                          vgasr_priv.clients[i].id == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
-                          vgasr_priv.clients[i].active ? '+' : ' ',
-                          vgasr_priv.clients[i].pwr_state ? "Pwr" : "Off",
-                          pci_name(vgasr_priv.clients[i].pdev));
+       list_for_each_entry(client, &vgasr_priv.clients, list) {
+               seq_printf(m, "%d:%s%s:%c:%s:%s\n", i,
+                          client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
+                          client_is_vga(client) ? "" : "-Audio",
+                          client->active ? '+' : ' ',
+                          client->pwr_state ? "Pwr" : "Off",
+                          pci_name(client->pdev));
+               i++;
        }
        mutex_unlock(&vgasr_mutex);
        return 0;
@@ -197,7 +252,7 @@ static int vga_switchon(struct vga_switcheroo_client *client)
        if (vgasr_priv.handler->power_state)
                vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
        /* call the driver callback to turn on device */
-       client->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON);
+       client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON);
        client->pwr_state = VGA_SWITCHEROO_ON;
        return 0;
 }
@@ -205,34 +260,39 @@ static int vga_switchon(struct vga_switcheroo_client *client)
 static int vga_switchoff(struct vga_switcheroo_client *client)
 {
        /* call the driver callback to turn off device */
-       client->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF);
+       client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF);
        if (vgasr_priv.handler->power_state)
                vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
        client->pwr_state = VGA_SWITCHEROO_OFF;
        return 0;
 }
 
+static void set_audio_state(int id, int state)
+{
+       struct vga_switcheroo_client *client;
+
+       client = find_client_from_id(&vgasr_priv.clients, id | ID_BIT_AUDIO);
+       if (client && client->pwr_state != state) {
+               client->ops->set_gpu_state(client->pdev, state);
+               client->pwr_state = state;
+       }
+}
+
 /* stage one happens before delay */
 static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
 {
-       int i;
-       struct vga_switcheroo_client *active = NULL;
+       struct vga_switcheroo_client *active;
 
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               if (vgasr_priv.clients[i].active == true) {
-                       active = &vgasr_priv.clients[i];
-                       break;
-               }
-       }
+       active = find_active_client(&vgasr_priv.clients);
        if (!active)
                return 0;
 
        if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
                vga_switchon(new_client);
 
-       /* swap shadow resource to denote boot VGA device has changed so X starts on new device */
-       active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW;
-       new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+       vga_set_default_device(new_client->pdev);
+       set_audio_state(new_client->id, VGA_SWITCHEROO_ON);
+
        return 0;
 }
 
@@ -240,15 +300,9 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
 static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 {
        int ret;
-       int i;
-       struct vga_switcheroo_client *active = NULL;
+       struct vga_switcheroo_client *active;
 
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               if (vgasr_priv.clients[i].active == true) {
-                       active = &vgasr_priv.clients[i];
-                       break;
-               }
-       }
+       active = find_active_client(&vgasr_priv.clients);
        if (!active)
                return 0;
 
@@ -264,8 +318,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
        if (ret)
                return ret;
 
-       if (new_client->reprobe)
-               new_client->reprobe(new_client->pdev);
+       if (new_client->ops->reprobe)
+               new_client->ops->reprobe(new_client->pdev);
+
+       set_audio_state(active->id, VGA_SWITCHEROO_OFF);
 
        if (active->pwr_state == VGA_SWITCHEROO_ON)
                vga_switchoff(active);
@@ -274,13 +330,26 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
        return 0;
 }
 
+static bool check_can_switch(void)
+{
+       struct vga_switcheroo_client *client;
+
+       list_for_each_entry(client, &vgasr_priv.clients, list) {
+               if (!client->ops->can_switch(client->pdev)) {
+                       printk(KERN_ERR "vga_switcheroo: client %x refused switch\n", client->id);
+                       return false;
+               }
+       }
+       return true;
+}
+
 static ssize_t
 vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
                             size_t cnt, loff_t *ppos)
 {
        char usercmd[64];
        const char *pdev_name;
-       int i, ret;
+       int ret;
        bool delay = false, can_switch;
        bool just_mux = false;
        int client_id = -1;
@@ -301,21 +370,21 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 
        /* pwr off the device not in use */
        if (strncmp(usercmd, "OFF", 3) == 0) {
-               for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-                       if (vgasr_priv.clients[i].active)
+               list_for_each_entry(client, &vgasr_priv.clients, list) {
+                       if (client->active)
                                continue;
-                       if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_ON)
-                               vga_switchoff(&vgasr_priv.clients[i]);
+                       if (client->pwr_state == VGA_SWITCHEROO_ON)
+                               vga_switchoff(client);
                }
                goto out;
        }
        /* pwr on the device not in use */
        if (strncmp(usercmd, "ON", 2) == 0) {
-               for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-                       if (vgasr_priv.clients[i].active)
+               list_for_each_entry(client, &vgasr_priv.clients, list) {
+                       if (client->active)
                                continue;
-                       if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_OFF)
-                               vga_switchon(&vgasr_priv.clients[i]);
+                       if (client->pwr_state == VGA_SWITCHEROO_OFF)
+                               vga_switchon(client);
                }
                goto out;
        }
@@ -348,13 +417,9 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 
        if (client_id == -1)
                goto out;
-
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               if (vgasr_priv.clients[i].id == client_id) {
-                       client = &vgasr_priv.clients[i];
-                       break;
-               }
-       }
+       client = find_client_from_id(&vgasr_priv.clients, client_id);
+       if (!client)
+               goto out;
 
        vgasr_priv.delayed_switch_active = false;
 
@@ -363,23 +428,16 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
                goto out;
        }
 
-       if (client->active == true)
+       if (client->active)
                goto out;
 
        /* okay we want a switch - test if devices are willing to switch */
-       can_switch = true;
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev);
-               if (can_switch == false) {
-                       printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i);
-                       break;
-               }
-       }
+       can_switch = check_can_switch();
 
        if (can_switch == false && delay == false)
                goto out;
 
-       if (can_switch == true) {
+       if (can_switch) {
                pdev_name = pci_name(client->pdev);
                ret = vga_switchto_stage1(client);
                if (ret)
@@ -451,10 +509,8 @@ fail:
 
 int vga_switcheroo_process_delayed_switch(void)
 {
-       struct vga_switcheroo_client *client = NULL;
+       struct vga_switcheroo_client *client;
        const char *pdev_name;
-       bool can_switch = true;
-       int i;
        int ret;
        int err = -EINVAL;
 
@@ -464,17 +520,9 @@ int vga_switcheroo_process_delayed_switch(void)
 
        printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id);
 
-       for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
-               if (vgasr_priv.clients[i].id == vgasr_priv.delayed_client_id)
-                       client = &vgasr_priv.clients[i];
-               can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev);
-               if (can_switch == false) {
-                       printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i);
-                       break;
-               }
-       }
-
-       if (can_switch == false || client == NULL)
+       client = find_client_from_id(&vgasr_priv.clients,
+                                    vgasr_priv.delayed_client_id);
+       if (!client || !check_can_switch())
                goto err;
 
        pdev_name = pci_name(client->pdev);
index 111d956d8e7d0d919d088405ddeaf3b341c87092..3df8fc0ec01a93ab95883139b2c3f531b72e5934 100644 (file)
@@ -136,6 +136,13 @@ struct pci_dev *vga_default_device(void)
 {
        return vga_default;
 }
+
+EXPORT_SYMBOL_GPL(vga_default_device);
+
+void vga_set_default_device(struct pci_dev *pdev)
+{
+       vga_default = pdev;
+}
 #endif
 
 static inline void vga_irq_set_state(struct vga_device *vgadev, bool state)
@@ -605,10 +612,12 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
                goto bail;
        }
 
+#ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
        if (vga_default == pdev) {
                pci_dev_put(vga_default);
                vga_default = NULL;
        }
+#endif
 
        if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
                vga_decode_count--;
index a3d033252995aeb388fbcabc1dab8a286e38cb51..ffddcba32af62b637baa09fd9487f515451fca4f 100644 (file)
@@ -34,7 +34,7 @@ config HID
 config HID_BATTERY_STRENGTH
        bool
        depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY
-       default y
+       default n
 
 config HIDRAW
        bool "/dev/hidraw raw HID device support"
index 12f9777c385d4038825d2fddcd59a18182e13b3c..45c3433f798699ec6749cee885a2b78d490e2b21 100644 (file)
@@ -1525,12 +1525,6 @@ static const struct file_operations picolcd_debug_reset_fops = {
 /*
  * The "eeprom" file
  */
-static int picolcd_debug_eeprom_open(struct inode *i, struct file *f)
-{
-       f->private_data = i->i_private;
-       return 0;
-}
-
 static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u,
                size_t s, loff_t *off)
 {
@@ -1618,7 +1612,7 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
  */
 static const struct file_operations picolcd_debug_eeprom_fops = {
        .owner    = THIS_MODULE,
-       .open     = picolcd_debug_eeprom_open,
+       .open     = simple_open,
        .read     = picolcd_debug_eeprom_read,
        .write    = picolcd_debug_eeprom_write,
        .llseek   = generic_file_llseek,
@@ -1627,12 +1621,6 @@ static const struct file_operations picolcd_debug_eeprom_fops = {
 /*
  * The "flash" file
  */
-static int picolcd_debug_flash_open(struct inode *i, struct file *f)
-{
-       f->private_data = i->i_private;
-       return 0;
-}
-
 /* record a flash address to buf (bounds check to be done by caller) */
 static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off)
 {
@@ -1817,7 +1805,7 @@ static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u,
  */
 static const struct file_operations picolcd_debug_flash_fops = {
        .owner    = THIS_MODULE,
-       .open     = picolcd_debug_flash_open,
+       .open     = simple_open,
        .read     = picolcd_debug_flash_read,
        .write    = picolcd_debug_flash_write,
        .llseek   = generic_file_llseek,
index de47039c708c5546232bc1c05606d2a3e89b99d2..9f85f827607fd6fca72b03152ca7a51b061ec82c 100644 (file)
@@ -62,7 +62,7 @@ static int tivo_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 
 static const struct hid_device_id tivo_devices[] = {
        /* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */
-       { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
        { }
 };
index 17dabc1f339e93ee9eff1221a433b03784dea3c7..eec329197c160e6739ccf1cbb0a24adc766b15ee 100644 (file)
@@ -23,12 +23,6 @@ struct wiimote_debug {
        struct dentry *drm;
 };
 
-static int wiidebug_eeprom_open(struct inode *i, struct file *f)
-{
-       f->private_data = i->i_private;
-       return 0;
-}
-
 static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s,
                                                                loff_t *off)
 {
@@ -83,7 +77,7 @@ static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s,
 
 static const struct file_operations wiidebug_eeprom_fops = {
        .owner = THIS_MODULE,
-       .open = wiidebug_eeprom_open,
+       .open = simple_open,
        .read = wiidebug_eeprom_read,
        .llseek = generic_file_llseek,
 };
diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig
new file mode 100644 (file)
index 0000000..d94e38d
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# HSI driver configuration
+#
+menuconfig HSI
+       tristate "HSI support"
+       ---help---
+         The "High speed synchronous Serial Interface" is
+         synchronous serial interface used mainly to connect
+         application engines and cellular modems.
+
+if HSI
+
+config HSI_BOARDINFO
+       bool
+       default y
+
+source "drivers/hsi/clients/Kconfig"
+
+endif # HSI
diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile
new file mode 100644 (file)
index 0000000..9d5d33f
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for HSI
+#
+obj-$(CONFIG_HSI_BOARDINFO)    += hsi_boardinfo.o
+obj-$(CONFIG_HSI)              += hsi.o
+obj-y                          += clients/
diff --git a/drivers/hsi/clients/Kconfig b/drivers/hsi/clients/Kconfig
new file mode 100644 (file)
index 0000000..3bacd27
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# HSI clients configuration
+#
+
+comment "HSI clients"
+
+config HSI_CHAR
+       tristate "HSI/SSI character driver"
+       depends on HSI
+       ---help---
+         If you say Y here, you will enable the HSI/SSI character driver.
+         This driver provides a simple character device interface for
+         serial communication with the cellular modem over HSI/SSI bus.
diff --git a/drivers/hsi/clients/Makefile b/drivers/hsi/clients/Makefile
new file mode 100644 (file)
index 0000000..327c0e2
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for HSI clients
+#
+
+obj-$(CONFIG_HSI_CHAR) += hsi_char.o
diff --git a/drivers/hsi/clients/hsi_char.c b/drivers/hsi/clients/hsi_char.c
new file mode 100644 (file)
index 0000000..3ad91f6
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ * HSI character device driver, implements the character device
+ * interface.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Andras Domokos <andras.domokos@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/kmemleak.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <linux/stat.h>
+#include <linux/hsi/hsi.h>
+#include <linux/hsi/hsi_char.h>
+
+#define HSC_DEVS               16 /* Num of channels */
+#define HSC_MSGS               4
+
+#define HSC_RXBREAK            0
+
+#define HSC_ID_BITS            6
+#define HSC_PORT_ID_BITS       4
+#define HSC_ID_MASK            3
+#define HSC_PORT_ID_MASK       3
+#define HSC_CH_MASK            0xf
+
+/*
+ * We support up to 4 controllers that can have up to 4
+ * ports, which should currently be more than enough.
+ */
+#define HSC_BASEMINOR(id, port_id) \
+               ((((id) & HSC_ID_MASK) << HSC_ID_BITS) | \
+               (((port_id) & HSC_PORT_ID_MASK) << HSC_PORT_ID_BITS))
+
+enum {
+       HSC_CH_OPEN,
+       HSC_CH_READ,
+       HSC_CH_WRITE,
+       HSC_CH_WLINE,
+};
+
+enum {
+       HSC_RX,
+       HSC_TX,
+};
+
+struct hsc_client_data;
+/**
+ * struct hsc_channel - hsi_char internal channel data
+ * @ch: channel number
+ * @flags: Keeps state of the channel (open/close, reading, writing)
+ * @free_msgs_list: List of free HSI messages/requests
+ * @rx_msgs_queue: List of pending RX requests
+ * @tx_msgs_queue: List of pending TX requests
+ * @lock: Serialize access to the lists
+ * @cl: reference to the associated hsi_client
+ * @cl_data: reference to the client data that this channels belongs to
+ * @rx_wait: RX requests wait queue
+ * @tx_wait: TX requests wait queue
+ */
+struct hsc_channel {
+       unsigned int            ch;
+       unsigned long           flags;
+       struct list_head        free_msgs_list;
+       struct list_head        rx_msgs_queue;
+       struct list_head        tx_msgs_queue;
+       spinlock_t              lock;
+       struct hsi_client       *cl;
+       struct hsc_client_data *cl_data;
+       wait_queue_head_t       rx_wait;
+       wait_queue_head_t       tx_wait;
+};
+
+/**
+ * struct hsc_client_data - hsi_char internal client data
+ * @cdev: Characther device associated to the hsi_client
+ * @lock: Lock to serialize open/close access
+ * @flags: Keeps track of port state (rx hwbreak armed)
+ * @usecnt: Use count for claiming the HSI port (mutex protected)
+ * @cl: Referece to the HSI client
+ * @channels: Array of channels accessible by the client
+ */
+struct hsc_client_data {
+       struct cdev             cdev;
+       struct mutex            lock;
+       unsigned long           flags;
+       unsigned int            usecnt;
+       struct hsi_client       *cl;
+       struct hsc_channel      channels[HSC_DEVS];
+};
+
+/* Stores the major number dynamically allocated for hsi_char */
+static unsigned int hsc_major;
+/* Maximum buffer size that hsi_char will accept from userspace */
+static unsigned int max_data_size = 0x1000;
+module_param(max_data_size, uint, 0);
+MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)");
+
+static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg,
+                                                       struct list_head *queue)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&channel->lock, flags);
+       list_add_tail(&msg->link, queue);
+       spin_unlock_irqrestore(&channel->lock, flags);
+}
+
+static struct hsi_msg *hsc_get_first_msg(struct hsc_channel *channel,
+                                                       struct list_head *queue)
+{
+       struct hsi_msg *msg = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&channel->lock, flags);
+
+       if (list_empty(queue))
+               goto out;
+
+       msg = list_first_entry(queue, struct hsi_msg, link);
+       list_del(&msg->link);
+out:
+       spin_unlock_irqrestore(&channel->lock, flags);
+
+       return msg;
+}
+
+static inline void hsc_msg_free(struct hsi_msg *msg)
+{
+       kfree(sg_virt(msg->sgt.sgl));
+       hsi_free_msg(msg);
+}
+
+static void hsc_free_list(struct list_head *list)
+{
+       struct hsi_msg *msg, *tmp;
+
+       list_for_each_entry_safe(msg, tmp, list, link) {
+               list_del(&msg->link);
+               hsc_msg_free(msg);
+       }
+}
+
+static void hsc_reset_list(struct hsc_channel *channel, struct list_head *l)
+{
+       unsigned long flags;
+       LIST_HEAD(list);
+
+       spin_lock_irqsave(&channel->lock, flags);
+       list_splice_init(l, &list);
+       spin_unlock_irqrestore(&channel->lock, flags);
+
+       hsc_free_list(&list);
+}
+
+static inline struct hsi_msg *hsc_msg_alloc(unsigned int alloc_size)
+{
+       struct hsi_msg *msg;
+       void *buf;
+
+       msg = hsi_alloc_msg(1, GFP_KERNEL);
+       if (!msg)
+               goto out;
+       buf = kmalloc(alloc_size, GFP_KERNEL);
+       if (!buf) {
+               hsi_free_msg(msg);
+               goto out;
+       }
+       sg_init_one(msg->sgt.sgl, buf, alloc_size);
+       /* Ignore false positive, due to sg pointer handling */
+       kmemleak_ignore(buf);
+
+       return msg;
+out:
+       return NULL;
+}
+
+static inline int hsc_msgs_alloc(struct hsc_channel *channel)
+{
+       struct hsi_msg *msg;
+       int i;
+
+       for (i = 0; i < HSC_MSGS; i++) {
+               msg = hsc_msg_alloc(max_data_size);
+               if (!msg)
+                       goto out;
+               msg->channel = channel->ch;
+               list_add_tail(&msg->link, &channel->free_msgs_list);
+       }
+
+       return 0;
+out:
+       hsc_free_list(&channel->free_msgs_list);
+
+       return -ENOMEM;
+}
+
+static inline unsigned int hsc_msg_len_get(struct hsi_msg *msg)
+{
+       return msg->sgt.sgl->length;
+}
+
+static inline void hsc_msg_len_set(struct hsi_msg *msg, unsigned int len)
+{
+       msg->sgt.sgl->length = len;
+}
+
+static void hsc_rx_completed(struct hsi_msg *msg)
+{
+       struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+       struct hsc_channel *channel = cl_data->channels + msg->channel;
+
+       if (test_bit(HSC_CH_READ, &channel->flags)) {
+               hsc_add_tail(channel, msg, &channel->rx_msgs_queue);
+               wake_up(&channel->rx_wait);
+       } else {
+               hsc_add_tail(channel, msg, &channel->free_msgs_list);
+       }
+}
+
+static void hsc_rx_msg_destructor(struct hsi_msg *msg)
+{
+       msg->status = HSI_STATUS_ERROR;
+       hsc_msg_len_set(msg, 0);
+       hsc_rx_completed(msg);
+}
+
+static void hsc_tx_completed(struct hsi_msg *msg)
+{
+       struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+       struct hsc_channel *channel = cl_data->channels + msg->channel;
+
+       if (test_bit(HSC_CH_WRITE, &channel->flags)) {
+               hsc_add_tail(channel, msg, &channel->tx_msgs_queue);
+               wake_up(&channel->tx_wait);
+       } else {
+               hsc_add_tail(channel, msg, &channel->free_msgs_list);
+       }
+}
+
+static void hsc_tx_msg_destructor(struct hsi_msg *msg)
+{
+       msg->status = HSI_STATUS_ERROR;
+       hsc_msg_len_set(msg, 0);
+       hsc_tx_completed(msg);
+}
+
+static void hsc_break_req_destructor(struct hsi_msg *msg)
+{
+       struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+
+       hsi_free_msg(msg);
+       clear_bit(HSC_RXBREAK, &cl_data->flags);
+}
+
+static void hsc_break_received(struct hsi_msg *msg)
+{
+       struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+       struct hsc_channel *channel = cl_data->channels;
+       int i, ret;
+
+       /* Broadcast HWBREAK on all channels */
+       for (i = 0; i < HSC_DEVS; i++, channel++) {
+               struct hsi_msg *msg2;
+
+               if (!test_bit(HSC_CH_READ, &channel->flags))
+                       continue;
+               msg2 = hsc_get_first_msg(channel, &channel->free_msgs_list);
+               if (!msg2)
+                       continue;
+               clear_bit(HSC_CH_READ, &channel->flags);
+               hsc_msg_len_set(msg2, 0);
+               msg2->status = HSI_STATUS_COMPLETED;
+               hsc_add_tail(channel, msg2, &channel->rx_msgs_queue);
+               wake_up(&channel->rx_wait);
+       }
+       hsi_flush(msg->cl);
+       ret = hsi_async_read(msg->cl, msg);
+       if (ret < 0)
+               hsc_break_req_destructor(msg);
+}
+
+static int hsc_break_request(struct hsi_client *cl)
+{
+       struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
+       struct hsi_msg *msg;
+       int ret;
+
+       if (test_and_set_bit(HSC_RXBREAK, &cl_data->flags))
+               return -EBUSY;
+
+       msg = hsi_alloc_msg(0, GFP_KERNEL);
+       if (!msg) {
+               clear_bit(HSC_RXBREAK, &cl_data->flags);
+               return -ENOMEM;
+       }
+       msg->break_frame = 1;
+       msg->complete = hsc_break_received;
+       msg->destructor = hsc_break_req_destructor;
+       ret = hsi_async_read(cl, msg);
+       if (ret < 0)
+               hsc_break_req_destructor(msg);
+
+       return ret;
+}
+
+static int hsc_break_send(struct hsi_client *cl)
+{
+       struct hsi_msg *msg;
+       int ret;
+
+       msg = hsi_alloc_msg(0, GFP_ATOMIC);
+       if (!msg)
+               return -ENOMEM;
+       msg->break_frame = 1;
+       msg->complete = hsi_free_msg;
+       msg->destructor = hsi_free_msg;
+       ret = hsi_async_write(cl, msg);
+       if (ret < 0)
+               hsi_free_msg(msg);
+
+       return ret;
+}
+
+static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
+{
+       struct hsi_config tmp;
+       int ret;
+
+       if ((rxc->mode != HSI_MODE_STREAM) && (rxc->mode != HSI_MODE_FRAME))
+               return -EINVAL;
+       if ((rxc->channels == 0) || (rxc->channels > HSC_DEVS))
+               return -EINVAL;
+       if (rxc->channels & (rxc->channels - 1))
+               return -EINVAL;
+       if ((rxc->flow != HSI_FLOW_SYNC) && (rxc->flow != HSI_FLOW_PIPE))
+               return -EINVAL;
+       tmp = cl->rx_cfg;
+       cl->rx_cfg.mode = rxc->mode;
+       cl->rx_cfg.channels = rxc->channels;
+       cl->rx_cfg.flow = rxc->flow;
+       ret = hsi_setup(cl);
+       if (ret < 0) {
+               cl->rx_cfg = tmp;
+               return ret;
+       }
+       if (rxc->mode == HSI_MODE_FRAME)
+               hsc_break_request(cl);
+
+       return ret;
+}
+
+static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc)
+{
+       rxc->mode = cl->rx_cfg.mode;
+       rxc->channels = cl->rx_cfg.channels;
+       rxc->flow = cl->rx_cfg.flow;
+}
+
+static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
+{
+       struct hsi_config tmp;
+       int ret;
+
+       if ((txc->mode != HSI_MODE_STREAM) && (txc->mode != HSI_MODE_FRAME))
+               return -EINVAL;
+       if ((txc->channels == 0) || (txc->channels > HSC_DEVS))
+               return -EINVAL;
+       if (txc->channels & (txc->channels - 1))
+               return -EINVAL;
+       if ((txc->arb_mode != HSI_ARB_RR) && (txc->arb_mode != HSI_ARB_PRIO))
+               return -EINVAL;
+       tmp = cl->tx_cfg;
+       cl->tx_cfg.mode = txc->mode;
+       cl->tx_cfg.channels = txc->channels;
+       cl->tx_cfg.speed = txc->speed;
+       cl->tx_cfg.arb_mode = txc->arb_mode;
+       ret = hsi_setup(cl);
+       if (ret < 0) {
+               cl->tx_cfg = tmp;
+               return ret;
+       }
+
+       return ret;
+}
+
+static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc)
+{
+       txc->mode = cl->tx_cfg.mode;
+       txc->channels = cl->tx_cfg.channels;
+       txc->speed = cl->tx_cfg.speed;
+       txc->arb_mode = cl->tx_cfg.arb_mode;
+}
+
+static ssize_t hsc_read(struct file *file, char __user *buf, size_t len,
+                                               loff_t *ppos __maybe_unused)
+{
+       struct hsc_channel *channel = file->private_data;
+       struct hsi_msg *msg;
+       ssize_t ret;
+
+       if (len == 0)
+               return 0;
+       if (!IS_ALIGNED(len, sizeof(u32)))
+               return -EINVAL;
+       if (len > max_data_size)
+               len = max_data_size;
+       if (channel->ch >= channel->cl->rx_cfg.channels)
+               return -ECHRNG;
+       if (test_and_set_bit(HSC_CH_READ, &channel->flags))
+               return -EBUSY;
+       msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
+       if (!msg) {
+               ret = -ENOSPC;
+               goto out;
+       }
+       hsc_msg_len_set(msg, len);
+       msg->complete = hsc_rx_completed;
+       msg->destructor = hsc_rx_msg_destructor;
+       ret = hsi_async_read(channel->cl, msg);
+       if (ret < 0) {
+               hsc_add_tail(channel, msg, &channel->free_msgs_list);
+               goto out;
+       }
+
+       ret = wait_event_interruptible(channel->rx_wait,
+                                       !list_empty(&channel->rx_msgs_queue));
+       if (ret < 0) {
+               clear_bit(HSC_CH_READ, &channel->flags);
+               hsi_flush(channel->cl);
+               return -EINTR;
+       }
+
+       msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue);
+       if (msg) {
+               if (msg->status != HSI_STATUS_ERROR) {
+                       ret = copy_to_user((void __user *)buf,
+                       sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg));
+                       if (ret)
+                               ret = -EFAULT;
+                       else
+                               ret = hsc_msg_len_get(msg);
+               } else {
+                       ret = -EIO;
+               }
+               hsc_add_tail(channel, msg, &channel->free_msgs_list);
+       }
+out:
+       clear_bit(HSC_CH_READ, &channel->flags);
+
+       return ret;
+}
+
+static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len,
+                                               loff_t *ppos __maybe_unused)
+{
+       struct hsc_channel *channel = file->private_data;
+       struct hsi_msg *msg;
+       ssize_t ret;
+
+       if ((len == 0) || !IS_ALIGNED(len, sizeof(u32)))
+               return -EINVAL;
+       if (len > max_data_size)
+               len = max_data_size;
+       if (channel->ch >= channel->cl->tx_cfg.channels)
+               return -ECHRNG;
+       if (test_and_set_bit(HSC_CH_WRITE, &channel->flags))
+               return -EBUSY;
+       msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
+       if (!msg) {
+               clear_bit(HSC_CH_WRITE, &channel->flags);
+               return -ENOSPC;
+       }
+       if (copy_from_user(sg_virt(msg->sgt.sgl), (void __user *)buf, len)) {
+               ret = -EFAULT;
+               goto out;
+       }
+       hsc_msg_len_set(msg, len);
+       msg->complete = hsc_tx_completed;
+       msg->destructor = hsc_tx_msg_destructor;
+       ret = hsi_async_write(channel->cl, msg);
+       if (ret < 0)
+               goto out;
+
+       ret = wait_event_interruptible(channel->tx_wait,
+                                       !list_empty(&channel->tx_msgs_queue));
+       if (ret < 0) {
+               clear_bit(HSC_CH_WRITE, &channel->flags);
+               hsi_flush(channel->cl);
+               return -EINTR;
+       }
+
+       msg = hsc_get_first_msg(channel, &channel->tx_msgs_queue);
+       if (msg) {
+               if (msg->status == HSI_STATUS_ERROR)
+                       ret = -EIO;
+               else
+                       ret = hsc_msg_len_get(msg);
+
+               hsc_add_tail(channel, msg, &channel->free_msgs_list);
+       }
+out:
+       clear_bit(HSC_CH_WRITE, &channel->flags);
+
+       return ret;
+}
+
+static long hsc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct hsc_channel *channel = file->private_data;
+       unsigned int state;
+       struct hsc_rx_config rxc;
+       struct hsc_tx_config txc;
+       long ret = 0;
+
+       switch (cmd) {
+       case HSC_RESET:
+               hsi_flush(channel->cl);
+               break;
+       case HSC_SET_PM:
+               if (copy_from_user(&state, (void __user *)arg, sizeof(state)))
+                       return -EFAULT;
+               if (state == HSC_PM_DISABLE) {
+                       if (test_and_set_bit(HSC_CH_WLINE, &channel->flags))
+                               return -EINVAL;
+                       ret = hsi_start_tx(channel->cl);
+               } else if (state == HSC_PM_ENABLE) {
+                       if (!test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
+                               return -EINVAL;
+                       ret = hsi_stop_tx(channel->cl);
+               } else {
+                       ret = -EINVAL;
+               }
+               break;
+       case HSC_SEND_BREAK:
+               return hsc_break_send(channel->cl);
+       case HSC_SET_RX:
+               if (copy_from_user(&rxc, (void __user *)arg, sizeof(rxc)))
+                       return -EFAULT;
+               return hsc_rx_set(channel->cl, &rxc);
+       case HSC_GET_RX:
+               hsc_rx_get(channel->cl, &rxc);
+               if (copy_to_user((void __user *)arg, &rxc, sizeof(rxc)))
+                       return -EFAULT;
+               break;
+       case HSC_SET_TX:
+               if (copy_from_user(&txc, (void __user *)arg, sizeof(txc)))
+                       return -EFAULT;
+               return hsc_tx_set(channel->cl, &txc);
+       case HSC_GET_TX:
+               hsc_tx_get(channel->cl, &txc);
+               if (copy_to_user((void __user *)arg, &txc, sizeof(txc)))
+                       return -EFAULT;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return ret;
+}
+
+static inline void __hsc_port_release(struct hsc_client_data *cl_data)
+{
+       BUG_ON(cl_data->usecnt == 0);
+
+       if (--cl_data->usecnt == 0) {
+               hsi_flush(cl_data->cl);
+               hsi_release_port(cl_data->cl);
+       }
+}
+
+static int hsc_open(struct inode *inode, struct file *file)
+{
+       struct hsc_client_data *cl_data;
+       struct hsc_channel *channel;
+       int ret = 0;
+
+       pr_debug("open, minor = %d\n", iminor(inode));
+
+       cl_data = container_of(inode->i_cdev, struct hsc_client_data, cdev);
+       mutex_lock(&cl_data->lock);
+       channel = cl_data->channels + (iminor(inode) & HSC_CH_MASK);
+
+       if (test_and_set_bit(HSC_CH_OPEN, &channel->flags)) {
+               ret = -EBUSY;
+               goto out;
+       }
+       /*
+        * Check if we have already claimed the port associated to the HSI
+        * client. If not then try to claim it, else increase its refcount
+        */
+       if (cl_data->usecnt == 0) {
+               ret = hsi_claim_port(cl_data->cl, 0);
+               if (ret < 0)
+                       goto out;
+               hsi_setup(cl_data->cl);
+       }
+       cl_data->usecnt++;
+
+       ret = hsc_msgs_alloc(channel);
+       if (ret < 0) {
+               __hsc_port_release(cl_data);
+               goto out;
+       }
+
+       file->private_data = channel;
+       mutex_unlock(&cl_data->lock);
+
+       return ret;
+out:
+       mutex_unlock(&cl_data->lock);
+
+       return ret;
+}
+
+static int hsc_release(struct inode *inode __maybe_unused, struct file *file)
+{
+       struct hsc_channel *channel = file->private_data;
+       struct hsc_client_data *cl_data = channel->cl_data;
+
+       mutex_lock(&cl_data->lock);
+       file->private_data = NULL;
+       if (test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
+               hsi_stop_tx(channel->cl);
+       __hsc_port_release(cl_data);
+       hsc_reset_list(channel, &channel->rx_msgs_queue);
+       hsc_reset_list(channel, &channel->tx_msgs_queue);
+       hsc_reset_list(channel, &channel->free_msgs_list);
+       clear_bit(HSC_CH_READ, &channel->flags);
+       clear_bit(HSC_CH_WRITE, &channel->flags);
+       clear_bit(HSC_CH_OPEN, &channel->flags);
+       wake_up(&channel->rx_wait);
+       wake_up(&channel->tx_wait);
+       mutex_unlock(&cl_data->lock);
+
+       return 0;
+}
+
+static const struct file_operations hsc_fops = {
+       .owner          = THIS_MODULE,
+       .read           = hsc_read,
+       .write          = hsc_write,
+       .unlocked_ioctl = hsc_ioctl,
+       .open           = hsc_open,
+       .release        = hsc_release,
+};
+
+static void __devinit hsc_channel_init(struct hsc_channel *channel)
+{
+       init_waitqueue_head(&channel->rx_wait);
+       init_waitqueue_head(&channel->tx_wait);
+       spin_lock_init(&channel->lock);
+       INIT_LIST_HEAD(&channel->free_msgs_list);
+       INIT_LIST_HEAD(&channel->rx_msgs_queue);
+       INIT_LIST_HEAD(&channel->tx_msgs_queue);
+}
+
+static int __devinit hsc_probe(struct device *dev)
+{
+       const char devname[] = "hsi_char";
+       struct hsc_client_data *cl_data;
+       struct hsc_channel *channel;
+       struct hsi_client *cl = to_hsi_client(dev);
+       unsigned int hsc_baseminor;
+       dev_t hsc_dev;
+       int ret;
+       int i;
+
+       cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL);
+       if (!cl_data) {
+               dev_err(dev, "Could not allocate hsc_client_data\n");
+               return -ENOMEM;
+       }
+       hsc_baseminor = HSC_BASEMINOR(hsi_id(cl), hsi_port_id(cl));
+       if (!hsc_major) {
+               ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor,
+                                               HSC_DEVS, devname);
+               if (ret > 0)
+                       hsc_major = MAJOR(hsc_dev);
+       } else {
+               hsc_dev = MKDEV(hsc_major, hsc_baseminor);
+               ret = register_chrdev_region(hsc_dev, HSC_DEVS, devname);
+       }
+       if (ret < 0) {
+               dev_err(dev, "Device %s allocation failed %d\n",
+                                       hsc_major ? "minor" : "major", ret);
+               goto out1;
+       }
+       mutex_init(&cl_data->lock);
+       hsi_client_set_drvdata(cl, cl_data);
+       cdev_init(&cl_data->cdev, &hsc_fops);
+       cl_data->cdev.owner = THIS_MODULE;
+       cl_data->cl = cl;
+       for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) {
+               hsc_channel_init(channel);
+               channel->ch = i;
+               channel->cl = cl;
+               channel->cl_data = cl_data;
+       }
+
+       /* 1 hsi client -> N char devices (one for each channel) */
+       ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS);
+       if (ret) {
+               dev_err(dev, "Could not add char device %d\n", ret);
+               goto out2;
+       }
+
+       return 0;
+out2:
+       unregister_chrdev_region(hsc_dev, HSC_DEVS);
+out1:
+       kfree(cl_data);
+
+       return ret;
+}
+
+static int __devexit hsc_remove(struct device *dev)
+{
+       struct hsi_client *cl = to_hsi_client(dev);
+       struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
+       dev_t hsc_dev = cl_data->cdev.dev;
+
+       cdev_del(&cl_data->cdev);
+       unregister_chrdev_region(hsc_dev, HSC_DEVS);
+       hsi_client_set_drvdata(cl, NULL);
+       kfree(cl_data);
+
+       return 0;
+}
+
+static struct hsi_client_driver hsc_driver = {
+       .driver = {
+               .name   = "hsi_char",
+               .owner  = THIS_MODULE,
+               .probe  = hsc_probe,
+               .remove = __devexit_p(hsc_remove),
+       },
+};
+
+static int __init hsc_init(void)
+{
+       int ret;
+
+       if ((max_data_size < 4) || (max_data_size > 0x10000) ||
+               (max_data_size & (max_data_size - 1))) {
+               pr_err("Invalid max read/write data size");
+               return -EINVAL;
+       }
+
+       ret = hsi_register_client_driver(&hsc_driver);
+       if (ret) {
+               pr_err("Error while registering HSI/SSI driver %d", ret);
+               return ret;
+       }
+
+       pr_info("HSI/SSI char device loaded\n");
+
+       return 0;
+}
+module_init(hsc_init);
+
+static void __exit hsc_exit(void)
+{
+       hsi_unregister_client_driver(&hsc_driver);
+       pr_info("HSI char device removed\n");
+}
+module_exit(hsc_exit);
+
+MODULE_AUTHOR("Andras Domokos <andras.domokos@nokia.com>");
+MODULE_ALIAS("hsi:hsi_char");
+MODULE_DESCRIPTION("HSI character device");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
new file mode 100644 (file)
index 0000000..2d58f93
--- /dev/null
@@ -0,0 +1,507 @@
+/*
+ * HSI core.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/hsi/hsi.h>
+#include <linux/compiler.h>
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+#include "hsi_core.h"
+
+static ssize_t modalias_show(struct device *dev,
+                       struct device_attribute *a __maybe_unused, char *buf)
+{
+       return sprintf(buf, "hsi:%s\n", dev_name(dev));
+}
+
+static struct device_attribute hsi_bus_dev_attrs[] = {
+       __ATTR_RO(modalias),
+       __ATTR_NULL,
+};
+
+static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));
+
+       return 0;
+}
+
+static int hsi_bus_match(struct device *dev, struct device_driver *driver)
+{
+       return strcmp(dev_name(dev), driver->name) == 0;
+}
+
+static struct bus_type hsi_bus_type = {
+       .name           = "hsi",
+       .dev_attrs      = hsi_bus_dev_attrs,
+       .match          = hsi_bus_match,
+       .uevent         = hsi_bus_uevent,
+};
+
+static void hsi_client_release(struct device *dev)
+{
+       kfree(to_hsi_client(dev));
+}
+
+static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
+{
+       struct hsi_client *cl;
+
+       cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+       if (!cl)
+               return;
+       cl->tx_cfg = info->tx_cfg;
+       cl->rx_cfg = info->rx_cfg;
+       cl->device.bus = &hsi_bus_type;
+       cl->device.parent = &port->device;
+       cl->device.release = hsi_client_release;
+       dev_set_name(&cl->device, info->name);
+       cl->device.platform_data = info->platform_data;
+       if (info->archdata)
+               cl->device.archdata = *info->archdata;
+       if (device_register(&cl->device) < 0) {
+               pr_err("hsi: failed to register client: %s\n", info->name);
+               put_device(&cl->device);
+       }
+}
+
+static void hsi_scan_board_info(struct hsi_controller *hsi)
+{
+       struct hsi_cl_info *cl_info;
+       struct hsi_port *p;
+
+       list_for_each_entry(cl_info, &hsi_board_list, list)
+               if (cl_info->info.hsi_id == hsi->id) {
+                       p = hsi_find_port_num(hsi, cl_info->info.port);
+                       if (!p)
+                               continue;
+                       hsi_new_client(p, &cl_info->info);
+               }
+}
+
+static int hsi_remove_client(struct device *dev, void *data __maybe_unused)
+{
+       device_unregister(dev);
+
+       return 0;
+}
+
+static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
+{
+       device_for_each_child(dev, NULL, hsi_remove_client);
+       device_unregister(dev);
+
+       return 0;
+}
+
+static void hsi_controller_release(struct device *dev)
+{
+       struct hsi_controller *hsi = to_hsi_controller(dev);
+
+       kfree(hsi->port);
+       kfree(hsi);
+}
+
+static void hsi_port_release(struct device *dev)
+{
+       kfree(to_hsi_port(dev));
+}
+
+/**
+ * hsi_unregister_controller - Unregister an HSI controller
+ * @hsi: The HSI controller to register
+ */
+void hsi_unregister_controller(struct hsi_controller *hsi)
+{
+       device_for_each_child(&hsi->device, NULL, hsi_remove_port);
+       device_unregister(&hsi->device);
+}
+EXPORT_SYMBOL_GPL(hsi_unregister_controller);
+
+/**
+ * hsi_register_controller - Register an HSI controller and its ports
+ * @hsi: The HSI controller to register
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_register_controller(struct hsi_controller *hsi)
+{
+       unsigned int i;
+       int err;
+
+       err = device_add(&hsi->device);
+       if (err < 0)
+               return err;
+       for (i = 0; i < hsi->num_ports; i++) {
+               hsi->port[i]->device.parent = &hsi->device;
+               err = device_add(&hsi->port[i]->device);
+               if (err < 0)
+                       goto out;
+       }
+       /* Populate HSI bus with HSI clients */
+       hsi_scan_board_info(hsi);
+
+       return 0;
+out:
+       while (i-- > 0)
+               device_del(&hsi->port[i]->device);
+       device_del(&hsi->device);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(hsi_register_controller);
+
+/**
+ * hsi_register_client_driver - Register an HSI client to the HSI bus
+ * @drv: HSI client driver to register
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_register_client_driver(struct hsi_client_driver *drv)
+{
+       drv->driver.bus = &hsi_bus_type;
+
+       return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(hsi_register_client_driver);
+
+static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused)
+{
+       return 0;
+}
+
+static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
+{
+       return 0;
+}
+
+/**
+ * hsi_put_controller - Free an HSI controller
+ *
+ * @hsi: Pointer to the HSI controller to freed
+ *
+ * HSI controller drivers should only use this function if they need
+ * to free their allocated hsi_controller structures before a successful
+ * call to hsi_register_controller. Other use is not allowed.
+ */
+void hsi_put_controller(struct hsi_controller *hsi)
+{
+       unsigned int i;
+
+       if (!hsi)
+               return;
+
+       for (i = 0; i < hsi->num_ports; i++)
+               if (hsi->port && hsi->port[i])
+                       put_device(&hsi->port[i]->device);
+       put_device(&hsi->device);
+}
+EXPORT_SYMBOL_GPL(hsi_put_controller);
+
+/**
+ * hsi_alloc_controller - Allocate an HSI controller and its ports
+ * @n_ports: Number of ports on the HSI controller
+ * @flags: Kernel allocation flags
+ *
+ * Return NULL on failure or a pointer to an hsi_controller on success.
+ */
+struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
+{
+       struct hsi_controller   *hsi;
+       struct hsi_port         **port;
+       unsigned int            i;
+
+       if (!n_ports)
+               return NULL;
+
+       hsi = kzalloc(sizeof(*hsi), flags);
+       if (!hsi)
+               return NULL;
+       port = kzalloc(sizeof(*port)*n_ports, flags);
+       if (!port) {
+               kfree(hsi);
+               return NULL;
+       }
+       hsi->num_ports = n_ports;
+       hsi->port = port;
+       hsi->device.release = hsi_controller_release;
+       device_initialize(&hsi->device);
+
+       for (i = 0; i < n_ports; i++) {
+               port[i] = kzalloc(sizeof(**port), flags);
+               if (port[i] == NULL)
+                       goto out;
+               port[i]->num = i;
+               port[i]->async = hsi_dummy_msg;
+               port[i]->setup = hsi_dummy_cl;
+               port[i]->flush = hsi_dummy_cl;
+               port[i]->start_tx = hsi_dummy_cl;
+               port[i]->stop_tx = hsi_dummy_cl;
+               port[i]->release = hsi_dummy_cl;
+               mutex_init(&port[i]->lock);
+               ATOMIC_INIT_NOTIFIER_HEAD(&port[i]->n_head);
+               dev_set_name(&port[i]->device, "port%d", i);
+               hsi->port[i]->device.release = hsi_port_release;
+               device_initialize(&hsi->port[i]->device);
+       }
+
+       return hsi;
+out:
+       hsi_put_controller(hsi);
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(hsi_alloc_controller);
+
+/**
+ * hsi_free_msg - Free an HSI message
+ * @msg: Pointer to the HSI message
+ *
+ * Client is responsible to free the buffers pointed by the scatterlists.
+ */
+void hsi_free_msg(struct hsi_msg *msg)
+{
+       if (!msg)
+               return;
+       sg_free_table(&msg->sgt);
+       kfree(msg);
+}
+EXPORT_SYMBOL_GPL(hsi_free_msg);
+
+/**
+ * hsi_alloc_msg - Allocate an HSI message
+ * @nents: Number of memory entries
+ * @flags: Kernel allocation flags
+ *
+ * nents can be 0. This mainly makes sense for read transfer.
+ * In that case, HSI drivers will call the complete callback when
+ * there is data to be read without consuming it.
+ *
+ * Return NULL on failure or a pointer to an hsi_msg on success.
+ */
+struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags)
+{
+       struct hsi_msg *msg;
+       int err;
+
+       msg = kzalloc(sizeof(*msg), flags);
+       if (!msg)
+               return NULL;
+
+       if (!nents)
+               return msg;
+
+       err = sg_alloc_table(&msg->sgt, nents, flags);
+       if (unlikely(err)) {
+               kfree(msg);
+               msg = NULL;
+       }
+
+       return msg;
+}
+EXPORT_SYMBOL_GPL(hsi_alloc_msg);
+
+/**
+ * hsi_async - Submit an HSI transfer to the controller
+ * @cl: HSI client sending the transfer
+ * @msg: The HSI transfer passed to controller
+ *
+ * The HSI message must have the channel, ttype, complete and destructor
+ * fields set beforehand. If nents > 0 then the client has to initialize
+ * also the scatterlists to point to the buffers to write to or read from.
+ *
+ * HSI controllers relay on pre-allocated buffers from their clients and they
+ * do not allocate buffers on their own.
+ *
+ * Once the HSI message transfer finishes, the HSI controller calls the
+ * complete callback with the status and actual_len fields of the HSI message
+ * updated. The complete callback can be called before returning from
+ * hsi_async.
+ *
+ * Returns -errno on failure or 0 on success
+ */
+int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)
+{
+       struct hsi_port *port = hsi_get_port(cl);
+
+       if (!hsi_port_claimed(cl))
+               return -EACCES;
+
+       WARN_ON_ONCE(!msg->destructor || !msg->complete);
+       msg->cl = cl;
+
+       return port->async(msg);
+}
+EXPORT_SYMBOL_GPL(hsi_async);
+
+/**
+ * hsi_claim_port - Claim the HSI client's port
+ * @cl: HSI client that wants to claim its port
+ * @share: Flag to indicate if the client wants to share the port or not.
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_claim_port(struct hsi_client *cl, unsigned int share)
+{
+       struct hsi_port *port = hsi_get_port(cl);
+       int err = 0;
+
+       mutex_lock(&port->lock);
+       if ((port->claimed) && (!port->shared || !share)) {
+               err = -EBUSY;
+               goto out;
+       }
+       if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) {
+               err = -ENODEV;
+               goto out;
+       }
+       port->claimed++;
+       port->shared = !!share;
+       cl->pclaimed = 1;
+out:
+       mutex_unlock(&port->lock);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(hsi_claim_port);
+
+/**
+ * hsi_release_port - Release the HSI client's port
+ * @cl: HSI client which previously claimed its port
+ */
+void hsi_release_port(struct hsi_client *cl)
+{
+       struct hsi_port *port = hsi_get_port(cl);
+
+       mutex_lock(&port->lock);
+       /* Allow HW driver to do some cleanup */
+       port->release(cl);
+       if (cl->pclaimed)
+               port->claimed--;
+       BUG_ON(port->claimed < 0);
+       cl->pclaimed = 0;
+       if (!port->claimed)
+               port->shared = 0;
+       module_put(to_hsi_controller(port->device.parent)->owner);
+       mutex_unlock(&port->lock);
+}
+EXPORT_SYMBOL_GPL(hsi_release_port);
+
+static int hsi_event_notifier_call(struct notifier_block *nb,
+                               unsigned long event, void *data __maybe_unused)
+{
+       struct hsi_client *cl = container_of(nb, struct hsi_client, nb);
+
+       (*cl->ehandler)(cl, event);
+
+       return 0;
+}
+
+/**
+ * hsi_register_port_event - Register a client to receive port events
+ * @cl: HSI client that wants to receive port events
+ * @cb: Event handler callback
+ *
+ * Clients should register a callback to be able to receive
+ * events from the ports. Registration should happen after
+ * claiming the port.
+ * The handler can be called in interrupt context.
+ *
+ * Returns -errno on error, or 0 on success.
+ */
+int hsi_register_port_event(struct hsi_client *cl,
+                       void (*handler)(struct hsi_client *, unsigned long))
+{
+       struct hsi_port *port = hsi_get_port(cl);
+
+       if (!handler || cl->ehandler)
+               return -EINVAL;
+       if (!hsi_port_claimed(cl))
+               return -EACCES;
+       cl->ehandler = handler;
+       cl->nb.notifier_call = hsi_event_notifier_call;
+
+       return atomic_notifier_chain_register(&port->n_head, &cl->nb);
+}
+EXPORT_SYMBOL_GPL(hsi_register_port_event);
+
+/**
+ * hsi_unregister_port_event - Stop receiving port events for a client
+ * @cl: HSI client that wants to stop receiving port events
+ *
+ * Clients should call this function before releasing their associated
+ * port.
+ *
+ * Returns -errno on error, or 0 on success.
+ */
+int hsi_unregister_port_event(struct hsi_client *cl)
+{
+       struct hsi_port *port = hsi_get_port(cl);
+       int err;
+
+       WARN_ON(!hsi_port_claimed(cl));
+
+       err = atomic_notifier_chain_unregister(&port->n_head, &cl->nb);
+       if (!err)
+               cl->ehandler = NULL;
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(hsi_unregister_port_event);
+
+/**
+ * hsi_event -Notifies clients about port events
+ * @port: Port where the event occurred
+ * @event: The event type
+ *
+ * Clients should not be concerned about wake line behavior. However, due
+ * to a race condition in HSI HW protocol, clients need to be notified
+ * about wake line changes, so they can implement a workaround for it.
+ *
+ * Events:
+ * HSI_EVENT_START_RX - Incoming wake line high
+ * HSI_EVENT_STOP_RX - Incoming wake line down
+ *
+ * Returns -errno on error, or 0 on success.
+ */
+int hsi_event(struct hsi_port *port, unsigned long event)
+{
+       return atomic_notifier_call_chain(&port->n_head, event, NULL);
+}
+EXPORT_SYMBOL_GPL(hsi_event);
+
+static int __init hsi_init(void)
+{
+       return bus_register(&hsi_bus_type);
+}
+postcore_initcall(hsi_init);
+
+static void __exit hsi_exit(void)
+{
+       bus_unregister(&hsi_bus_type);
+}
+module_exit(hsi_exit);
+
+MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
+MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hsi/hsi_boardinfo.c b/drivers/hsi/hsi_boardinfo.c
new file mode 100644 (file)
index 0000000..e56bc6d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * HSI clients registration interface
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/hsi/hsi.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "hsi_core.h"
+
+/*
+ * hsi_board_list is only used internally by the HSI framework.
+ * No one else is allowed to make use of it.
+ */
+LIST_HEAD(hsi_board_list);
+EXPORT_SYMBOL_GPL(hsi_board_list);
+
+/**
+ * hsi_register_board_info - Register HSI clients information
+ * @info: Array of HSI clients on the board
+ * @len: Length of the array
+ *
+ * HSI clients are statically declared and registered on board files.
+ *
+ * HSI clients will be automatically registered to the HSI bus once the
+ * controller and the port where the clients wishes to attach are registered
+ * to it.
+ *
+ * Return -errno on failure, 0 on success.
+ */
+int __init hsi_register_board_info(struct hsi_board_info const *info,
+                                                       unsigned int len)
+{
+       struct hsi_cl_info *cl_info;
+
+       cl_info = kzalloc(sizeof(*cl_info) * len, GFP_KERNEL);
+       if (!cl_info)
+               return -ENOMEM;
+
+       for (; len; len--, info++, cl_info++) {
+               cl_info->info = *info;
+               list_add_tail(&cl_info->list, &hsi_board_list);
+       }
+
+       return 0;
+}
diff --git a/drivers/hsi/hsi_core.h b/drivers/hsi/hsi_core.h
new file mode 100644 (file)
index 0000000..ab5c2fb
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * HSI framework internal interfaces,
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_HSI_CORE_H__
+#define __LINUX_HSI_CORE_H__
+
+#include <linux/hsi/hsi.h>
+
+struct hsi_cl_info {
+       struct list_head        list;
+       struct hsi_board_info   info;
+};
+
+extern struct list_head hsi_board_list;
+
+#endif /* __LINUX_HSI_CORE_H__ */
index 5b32d56dbb4dcc903f2736c920b8a4e62a682cca..8deedc1b98405f8622cca6bff7d826b7114f00fc 100644 (file)
@@ -253,7 +253,8 @@ config SENSORS_K10TEMP
          If you say yes here you get support for the temperature
          sensor(s) inside your CPU. Supported are later revisions of
          the AMD Family 10h and all revisions of the AMD Family 11h,
-         12h (Llano), 14h (Brazos) and 15h (Bulldozer) microarchitectures.
+         12h (Llano), 14h (Brazos) and 15h (Bulldozer/Trinity)
+         microarchitectures.
 
          This driver can also be built as a module.  If so, the module
          will be called k10temp.
@@ -425,7 +426,7 @@ config SENSORS_GL520SM
 
 config SENSORS_GPIO_FAN
        tristate "GPIO fan"
-       depends on GENERIC_GPIO
+       depends on GPIOLIB
        help
          If you say yes here you get support for fans connected to GPIO lines.
 
@@ -883,7 +884,7 @@ source drivers/hwmon/pmbus/Kconfig
 
 config SENSORS_SHT15
        tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
-       depends on GENERIC_GPIO
+       depends on GPIOLIB
        help
          If you say yes here you get support for the Sensiron SHT10, SHT11,
          SHT15, SHT71, SHT75 humidity and temperature sensors.
index 554f046bcf20a4949fc108fab40e11206486856d..9140236a0182b4f73d80efbab7d6fdac11aca539 100644 (file)
@@ -391,6 +391,7 @@ static ssize_t show_str(struct device *dev,
                break;
        default:
                BUG();
+               val = "";
        }
 
        return sprintf(buf, "%s\n", val);
@@ -632,6 +633,7 @@ static int register_ro_attrs(struct acpi_power_meter_resource *resource,
                sensors->dev_attr.show = ro->show;
                sensors->index = ro->index;
 
+               sysfs_attr_init(&sensors->dev_attr.attr);
                res = device_create_file(dev, &sensors->dev_attr);
                if (res) {
                        sensors->dev_attr.attr.name = NULL;
@@ -661,6 +663,7 @@ static int register_rw_attrs(struct acpi_power_meter_resource *resource,
                sensors->dev_attr.store = rw->set;
                sensors->index = rw->index;
 
+               sysfs_attr_init(&sensors->dev_attr.attr);
                res = device_create_file(dev, &sensors->dev_attr);
                if (res) {
                        sensors->dev_attr.attr.name = NULL;
index 0e0cfcc36f8d8f0cd656e482d526f31c299fc9ec..f85ce70d96779b5dcd366983f48d4458cc782704 100644 (file)
@@ -47,7 +47,7 @@ struct ad7314_data {
        u16 rx ____cacheline_aligned;
 };
 
-static int ad7314_spi_read(struct ad7314_data *chip, s16 *data)
+static int ad7314_spi_read(struct ad7314_data *chip)
 {
        int ret;
 
@@ -57,9 +57,7 @@ static int ad7314_spi_read(struct ad7314_data *chip, s16 *data)
                return ret;
        }
 
-       *data = be16_to_cpu(chip->rx);
-
-       return ret;
+       return be16_to_cpu(chip->rx);
 }
 
 static ssize_t ad7314_show_temperature(struct device *dev,
@@ -70,12 +68,12 @@ static ssize_t ad7314_show_temperature(struct device *dev,
        s16 data;
        int ret;
 
-       ret = ad7314_spi_read(chip, &data);
+       ret = ad7314_spi_read(chip);
        if (ret < 0)
                return ret;
        switch (spi_get_device_id(chip->spi_dev)->driver_data) {
        case ad7314:
-               data = (data & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
+               data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
                data = (data << 6) >> 6;
 
                return sprintf(buf, "%d\n", 250 * data);
@@ -86,7 +84,7 @@ static ssize_t ad7314_show_temperature(struct device *dev,
                 * with a sign bit - which is a 14 bit 2's complement
                 * register.  1lsb - 31.25 milli degrees centigrade
                 */
-               data &= ADT7301_TEMP_MASK;
+               data = ret & ADT7301_TEMP_MASK;
                data = (data << 2) >> 2;
 
                return sprintf(buf, "%d\n",
@@ -128,6 +126,7 @@ static int __devinit ad7314_probe(struct spi_device *spi_dev)
                ret = PTR_ERR(chip->hwmon_dev);
                goto error_remove_group;
        }
+       chip->spi_dev = spi_dev;
 
        return 0;
 error_remove_group:
index ff37363ea5bc39f90a7abc7afada12a9630a3910..44e1fd7f3d81f652ce70da1ba6d4da3890414c47 100644 (file)
@@ -233,18 +233,15 @@ static const auto_chan_table_t auto_channel_select_table_adm1030 = {
  * nearest match if no exact match where found.
  */
 static int
-get_fan_auto_nearest(struct adm1031_data *data,
-                    int chan, u8 val, u8 reg, u8 *new_reg)
+get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg)
 {
        int i;
        int first_match = -1, exact_match = -1;
        u8 other_reg_val =
            (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
 
-       if (val == 0) {
-               *new_reg = 0;
+       if (val == 0)
                return 0;
-       }
 
        for (i = 0; i < 8; i++) {
                if ((val == (*data->chan_select_table)[i][chan]) &&
@@ -264,13 +261,11 @@ get_fan_auto_nearest(struct adm1031_data *data,
        }
 
        if (exact_match >= 0)
-               *new_reg = exact_match;
+               return exact_match;
        else if (first_match >= 0)
-               *new_reg = first_match;
-       else
-               return -EINVAL;
+               return first_match;
 
-       return 0;
+       return -EINVAL;
 }
 
 static ssize_t show_fan_auto_channel(struct device *dev,
@@ -301,11 +296,12 @@ set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
 
        mutex_lock(&data->update_lock);
 
-       ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg);
-       if (ret) {
+       ret = get_fan_auto_nearest(data, nr, val, data->conf1);
+       if (ret < 0) {
                mutex_unlock(&data->update_lock);
                return ret;
        }
+       reg = ret;
        data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
        if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
            (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
index 7765e4f74ec56177ad8cc39476320d6d2436f719..1958f03efd7aaa43f72416f809eb42fe569b413f 100644 (file)
@@ -59,14 +59,11 @@ struct ads1015_data {
        struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
 };
 
-static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
-                             int *value)
+static int ads1015_read_adc(struct i2c_client *client, unsigned int channel)
 {
        u16 config;
-       s16 conversion;
        struct ads1015_data *data = i2c_get_clientdata(client);
        unsigned int pga = data->channel_data[channel].pga;
-       int fullscale;
        unsigned int data_rate = data->channel_data[channel].data_rate;
        unsigned int conversion_time_ms;
        int res;
@@ -78,7 +75,6 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
        if (res < 0)
                goto err_unlock;
        config = res;
-       fullscale = fullscale_table[pga];
        conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);
 
        /* setup and start single conversion */
@@ -105,33 +101,36 @@ static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
        }
 
        res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
-       if (res < 0)
-               goto err_unlock;
-       conversion = res;
-
-       mutex_unlock(&data->update_lock);
-
-       *value = DIV_ROUND_CLOSEST(conversion * fullscale, 0x7ff0);
-
-       return 0;
 
 err_unlock:
        mutex_unlock(&data->update_lock);
        return res;
 }
 
+static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel,
+                            s16 reg)
+{
+       struct ads1015_data *data = i2c_get_clientdata(client);
+       unsigned int pga = data->channel_data[channel].pga;
+       int fullscale = fullscale_table[pga];
+
+       return DIV_ROUND_CLOSEST(reg * fullscale, 0x7ff0);
+}
+
 /* sysfs callback function */
 static ssize_t show_in(struct device *dev, struct device_attribute *da,
        char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct i2c_client *client = to_i2c_client(dev);
-       int in;
        int res;
+       int index = attr->index;
 
-       res = ads1015_read_value(client, attr->index, &in);
+       res = ads1015_read_adc(client, index);
+       if (res < 0)
+               return res;
 
-       return (res < 0) ? res : sprintf(buf, "%d\n", in);
+       return sprintf(buf, "%d\n", ads1015_reg_to_mv(client, index, res));
 }
 
 static const struct sensor_device_attribute ads1015_in[] = {
index 0d3141fbbc204bbb533dfce334bc0a741f0b7095..b9d512331ed49561331b638b78f29e5120288b39 100644 (file)
@@ -52,7 +52,7 @@ module_param_named(tjmax, force_tjmax, int, 0444);
 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         16      /* Number of Real cores per cpu */
+#define NUM_REAL_CORES         32      /* Number of Real cores per cpu */
 #define CORETEMP_NAME_LENGTH   17      /* String Length of attrs */
 #define MAX_CORE_ATTRS         4       /* Maximum no of basic attrs */
 #define TOTAL_ATTRS            (MAX_CORE_ATTRS + 1)
@@ -709,6 +709,10 @@ static void __cpuinit put_core_offline(unsigned int cpu)
 
        indx = TO_ATTR_NO(cpu);
 
+       /* The core id is too big, just return */
+       if (indx > MAX_CORE_DATA - 1)
+               return;
+
        if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu)
                coretemp_remove_core(pdata, &pdev->dev, indx);
 
index 729499e7521038b59bcba9ecc390f875ca8d5966..ece4159bd4536553abafed0689d60d71f361d312 100644 (file)
@@ -276,6 +276,7 @@ static bool duty_mode_enabled(u8 pwm_enable)
                return false;
        default:
                BUG();
+               return true;
        }
 }
 
@@ -291,6 +292,7 @@ static bool auto_mode_enabled(u8 pwm_enable)
                return true;
        default:
                BUG();
+               return false;
        }
 }
 
index b7494af1e4a9ba8cb6952c83d96b845f19f9e7fd..e8e18cab1fb8c34d63c259a64afb461833df8be7 100644 (file)
@@ -122,6 +122,41 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
        return true;
 }
 
+/*
+ * Newer BKDG versions have an updated recommendation on how to properly
+ * initialize the running average range (was: 0xE, now: 0x9). This avoids
+ * counter saturations resulting in bogus power readings.
+ * We correct this value ourselves to cope with older BIOSes.
+ */
+static DEFINE_PCI_DEVICE_TABLE(affected_device) = {
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
+       { 0 }
+};
+
+static void __devinit tweak_runavg_range(struct pci_dev *pdev)
+{
+       u32 val;
+
+       /*
+        * let this quirk apply only to the current version of the
+        * northbridge, since future versions may change the behavior
+        */
+       if (!pci_match_id(affected_device, pdev))
+               return;
+
+       pci_bus_read_config_dword(pdev->bus,
+               PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
+               REG_TDP_RUNNING_AVERAGE, &val);
+       if ((val & 0xf) != 0xe)
+               return;
+
+       val &= ~0xf;
+       val |=  0x9;
+       pci_bus_write_config_dword(pdev->bus,
+               PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
+               REG_TDP_RUNNING_AVERAGE, val);
+}
+
 static void __devinit fam15h_power_init_data(struct pci_dev *f4,
                                             struct fam15h_power_data *data)
 {
@@ -155,6 +190,13 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev,
        struct device *dev;
        int err;
 
+       /*
+        * though we ignore every other northbridge, we still have to
+        * do the tweaking on _each_ node in MCM processors as the counters
+        * are working hand-in-hand
+        */
+       tweak_runavg_range(pdev);
+
        if (!fam15h_power_is_internal_node0(pdev)) {
                err = -ENODEV;
                goto exit;
index aba29d63f1957a3570dec270639dce04be59558b..307bb325dde952bcc6929ed39d4dd96fc9eca70d 100644 (file)
@@ -33,6 +33,9 @@ static bool force;
 module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
 
+/* PCI-IDs for Northbridge devices not used anywhere else */
+#define PCI_DEVICE_ID_AMD_15H_M10H_NB_F3       0x1403
+
 /* CPUID function 0x80000001, ebx */
 #define CPUID_PKGTYPE_MASK     0xf0000000
 #define CPUID_PKGTYPE_F                0x00000000
@@ -210,6 +213,7 @@ static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_NB_F3) },
        {}
 };
 MODULE_DEVICE_TABLE(pci, k10temp_id_table);
index 193067e27b6f355290921d0452d391d6f9e44fc1..de8f7adaccbd9bba107d731d88b00e22ef5053fd 100644 (file)
@@ -596,8 +596,10 @@ static int max6639_remove(struct i2c_client *client)
        return 0;
 }
 
-static int max6639_suspend(struct i2c_client *client, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+static int max6639_suspend(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
        if (data < 0)
                return data;
@@ -606,8 +608,9 @@ static int max6639_suspend(struct i2c_client *client, pm_message_t mesg)
                        MAX6639_REG_GCONFIG, data | MAX6639_GCONFIG_STANDBY);
 }
 
-static int max6639_resume(struct i2c_client *client)
+static int max6639_resume(struct device *dev)
 {
+       struct i2c_client *client = to_i2c_client(dev);
        int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
        if (data < 0)
                return data;
@@ -615,6 +618,7 @@ static int max6639_resume(struct i2c_client *client)
        return i2c_smbus_write_byte_data(client,
                        MAX6639_REG_GCONFIG, data & ~MAX6639_GCONFIG_STANDBY);
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static const struct i2c_device_id max6639_id[] = {
        {"max6639", 0},
@@ -623,15 +627,18 @@ static const struct i2c_device_id max6639_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, max6639_id);
 
+static const struct dev_pm_ops max6639_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(max6639_suspend, max6639_resume)
+};
+
 static struct i2c_driver max6639_driver = {
        .class = I2C_CLASS_HWMON,
        .driver = {
                   .name = "max6639",
+                  .pm = &max6639_pm_ops,
                   },
        .probe = max6639_probe,
        .remove = max6639_remove,
-       .suspend = max6639_suspend,
-       .resume = max6639_resume,
        .id_table = max6639_id,
        .detect = max6639_detect,
        .address_list = normal_i2c,
index be51037363c89b19fb3263084c37c5acbba4083b..29b319db573efed8c8d5ec38fce66a36cb265ed8 100644 (file)
@@ -710,13 +710,13 @@ static u16 pmbus_data2reg(struct pmbus_data *data,
  * If a negative value is stored in any of the referenced registers, this value
  * reflects an error code which will be returned.
  */
-static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val)
+static int pmbus_get_boolean(struct pmbus_data *data, int index)
 {
        u8 s1 = (index >> 24) & 0xff;
        u8 s2 = (index >> 16) & 0xff;
        u8 reg = (index >> 8) & 0xff;
        u8 mask = index & 0xff;
-       int status;
+       int ret, status;
        u8 regval;
 
        status = data->status[reg];
@@ -725,7 +725,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val)
 
        regval = status & mask;
        if (!s1 && !s2)
-               *val = !!regval;
+               ret = !!regval;
        else {
                long v1, v2;
                struct pmbus_sensor *sensor1, *sensor2;
@@ -739,9 +739,9 @@ static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val)
 
                v1 = pmbus_reg2data(data, sensor1);
                v2 = pmbus_reg2data(data, sensor2);
-               *val = !!(regval && v1 >= v2);
+               ret = !!(regval && v1 >= v2);
        }
-       return 0;
+       return ret;
 }
 
 static ssize_t pmbus_show_boolean(struct device *dev,
@@ -750,11 +750,10 @@ static ssize_t pmbus_show_boolean(struct device *dev,
        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
        struct pmbus_data *data = pmbus_update_device(dev);
        int val;
-       int err;
 
-       err = pmbus_get_boolean(data, attr->index, &val);
-       if (err)
-               return err;
+       val = pmbus_get_boolean(data, attr->index);
+       if (val < 0)
+               return val;
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 }
 
index d3b778da3f8603cf80e9173dd7207a210fe11f35..c5f6be478bad2468dd495ec1c3659c9abf550f2e 100644 (file)
@@ -343,10 +343,11 @@ exit:
        return err;
 }
 
-static int __init smsc47b397_find(unsigned short *addr)
+static int __init smsc47b397_find(void)
 {
        u8 id, rev;
        char *name;
+       unsigned short addr;
 
        superio_enter();
        id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
@@ -370,14 +371,14 @@ static int __init smsc47b397_find(unsigned short *addr)
        rev = superio_inb(SUPERIO_REG_DEVREV);
 
        superio_select(SUPERIO_REG_LD8);
-       *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
+       addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
                 |  superio_inb(SUPERIO_REG_BASE_LSB);
 
        pr_info("found SMSC %s (base address 0x%04x, revision %u)\n",
-               name, *addr, rev);
+               name, addr, rev);
 
        superio_exit();
-       return 0;
+       return addr;
 }
 
 static int __init smsc47b397_init(void)
@@ -385,9 +386,10 @@ static int __init smsc47b397_init(void)
        unsigned short address;
        int ret;
 
-       ret = smsc47b397_find(&address);
-       if (ret)
+       ret = smsc47b397_find();
+       if (ret < 0)
                return ret;
+       address = ret;
 
        ret = platform_driver_register(&smsc47b397_driver);
        if (ret)
index c590c146979325d7be42431ca0c2f1fcd248fed4..b5aa38dd7ab90fe06a9cfbfb9d0bb6323a5237c4 100644 (file)
@@ -491,10 +491,10 @@ static const struct attribute_group smsc47m1_group = {
        .attrs = smsc47m1_attributes,
 };
 
-static int __init smsc47m1_find(unsigned short *addr,
-                               struct smsc47m1_sio_data *sio_data)
+static int __init smsc47m1_find(struct smsc47m1_sio_data *sio_data)
 {
        u8 val;
+       unsigned short addr;
 
        superio_enter();
        val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
@@ -546,9 +546,9 @@ static int __init smsc47m1_find(unsigned short *addr,
        }
 
        superio_select();
-       *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
+       addr = (superio_inb(SUPERIO_REG_BASE) << 8)
              |  superio_inb(SUPERIO_REG_BASE + 1);
-       if (*addr == 0) {
+       if (addr == 0) {
                pr_info("Device address not set, will not use\n");
                superio_exit();
                return -ENODEV;
@@ -565,7 +565,7 @@ static int __init smsc47m1_find(unsigned short *addr,
        }
 
        superio_exit();
-       return 0;
+       return addr;
 }
 
 /* Restore device to its initial state */
@@ -938,13 +938,15 @@ static int __init sm_smsc47m1_init(void)
        unsigned short address;
        struct smsc47m1_sio_data sio_data;
 
-       if (smsc47m1_find(&address, &sio_data))
-               return -ENODEV;
+       err = smsc47m1_find(&sio_data);
+       if (err < 0)
+               return err;
+       address = err;
 
        /* Sets global pdev as a side effect */
        err = smsc47m1_device_add(address, &sio_data);
        if (err)
-               goto exit;
+               return err;
 
        err = platform_driver_probe(&smsc47m1_driver, smsc47m1_probe);
        if (err)
@@ -955,7 +957,6 @@ static int __init sm_smsc47m1_init(void)
 exit_device:
        platform_device_unregister(pdev);
        smsc47m1_restore(&sio_data);
-exit:
        return err;
 }
 
index a25350cf9554d35cdfaa6131a0c0b2b02b3c9c44..54922ed129787df0e6a6c4fe92f0115d88d303b5 100644 (file)
@@ -2619,15 +2619,15 @@ static struct platform_driver w83627ehf_driver = {
 static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
                                 struct w83627ehf_sio_data *sio_data)
 {
-       static const char __initdata sio_name_W83627EHF[] = "W83627EHF";
-       static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
-       static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
-       static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
-       static const char __initdata sio_name_W83627UHG[] = "W83627UHG";
-       static const char __initdata sio_name_W83667HG[] = "W83667HG";
-       static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B";
-       static const char __initdata sio_name_NCT6775[] = "NCT6775F";
-       static const char __initdata sio_name_NCT6776[] = "NCT6776F";
+       static const char sio_name_W83627EHF[] __initconst = "W83627EHF";
+       static const char sio_name_W83627EHG[] __initconst = "W83627EHG";
+       static const char sio_name_W83627DHG[] __initconst = "W83627DHG";
+       static const char sio_name_W83627DHG_P[] __initconst = "W83627DHG-P";
+       static const char sio_name_W83627UHG[] __initconst = "W83627UHG";
+       static const char sio_name_W83667HG[] __initconst = "W83667HG";
+       static const char sio_name_W83667HG_B[] __initconst = "W83667HG-B";
+       static const char sio_name_NCT6775[] __initconst = "NCT6775F";
+       static const char sio_name_NCT6776[] __initconst = "NCT6776F";
 
        u16 val;
        const char *sio_name;
index 37f42113af31bc54da67d953938630c513955a4d..00e8f213f56e51ed15b12b551af627eff9ef00b7 100644 (file)
@@ -182,7 +182,6 @@ static int i2c_dw_pci_resume(struct device *dev)
        pci_restore_state(pdev);
 
        i2c_dw_init(i2c);
-       i2c_dw_enable(i2c);
        return 0;
 }
 
index f086131cb1c70372384d1af7be50414ce73b4356..c811289b61e21628f28d79b71f27651c39e3e024 100644 (file)
@@ -324,7 +324,7 @@ static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
 {
        long ret;
        ret = wait_event_timeout(pch_event,
-                       (adap->pch_event_flag != 0), msecs_to_jiffies(50));
+                       (adap->pch_event_flag != 0), msecs_to_jiffies(1000));
 
        if (ret == 0) {
                pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
@@ -1063,6 +1063,6 @@ module_exit(pch_pci_exit);
 
 MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semico ML7213/ML7223/ML7831 IOH I2C");
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.lapis-semi.com>");
+MODULE_AUTHOR("Tomoya MORINAGA. <tomoya.rohm@gmail.com>");
 module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
 module_param(pch_clk, int, (S_IRUSR | S_IWUSR));
index 3d471d56bf15d1faf295f606c31f19d90f384e79..76b8af44f63492884d1b2b9ebc70ec58da9b9eba 100644 (file)
@@ -227,6 +227,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
                return -EINVAL;
 
        init_completion(&i2c->cmd_complete);
+       i2c->cmd_err = 0;
 
        flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
 
@@ -252,6 +253,9 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 
        if (i2c->cmd_err == -ENXIO)
                mxs_i2c_reset(i2c);
+       else
+               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+                               i2c->regs + MXS_I2C_QUEUECTRL_CLR);
 
        dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
 
@@ -299,8 +303,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
                    MXS_I2C_CTRL1_SLAVE_STOP_IRQ | MXS_I2C_CTRL1_SLAVE_IRQ))
                /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
                i2c->cmd_err = -EIO;
-       else
-               i2c->cmd_err = 0;
 
        is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
                MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
@@ -384,8 +386,6 @@ static int __devexit mxs_i2c_remove(struct platform_device *pdev)
        if (ret)
                return -EBUSY;
 
-       writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                       i2c->regs + MXS_I2C_QUEUECTRL_CLR);
        writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
 
        platform_set_drvdata(pdev, NULL);
index 04be9f82e14bda8518c4d9562c680731e42c23b3..eb8ad538c79ffb97616e43f135b5d9ff991cce96 100644 (file)
@@ -546,8 +546,7 @@ static int i2c_pnx_controller_suspend(struct platform_device *pdev,
 {
        struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
 
-       /* FIXME: shouldn't this be clk_disable? */
-       clk_enable(alg_data->clk);
+       clk_disable(alg_data->clk);
 
        return 0;
 }
index e978635e60f04189e6478ccb112a0df4a2596ed3..55e5ea62ccee3b69148c13ce337a1ff8531bc467 100644 (file)
@@ -516,6 +516,14 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
        if (likely(i2c_dev->msg_err == I2C_ERR_NONE))
                return 0;
 
+       /*
+        * NACK interrupt is generated before the I2C controller generates the
+        * STOP condition on the bus. So wait for 2 clock periods before resetting
+        * the controller so that STOP condition has been delivered properly.
+        */
+       if (i2c_dev->msg_err == I2C_ERR_NO_ACK)
+               udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate));
+
        tegra_i2c_init(i2c_dev);
        if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
                if (msg->flags & I2C_M_IGNORE_NAK)
index c976285d313eea4a6b5e2916c73a56350eeb3074..fa080ebd568f83fcaf821a7650e31983e8221300 100644 (file)
@@ -516,12 +516,6 @@ static struct notifier_block i7300_idle_nb = {
 
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
-int stats_open_generic(struct inode *inode, struct file *fp)
-{
-       fp->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
                                loff_t *off)
 {
@@ -534,7 +528,7 @@ static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
 }
 
 static const struct file_operations idle_fops = {
-       .open   = stats_open_generic,
+       .open   = simple_open,
        .read   = stats_read_ul,
        .llseek = default_llseek,
 };
index 426bb7617ec6fa4027dd6d535eab1fa6675562fc..b0d0bc8a6fb6ca58c61206ff11dab9f2f5cd5e8e 100644 (file)
@@ -1854,6 +1854,8 @@ static bool generate_unmatched_resp(struct ib_mad_private *recv,
                response->mad.mad.mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
                response->mad.mad.mad_hdr.status =
                        cpu_to_be16(IB_MGMT_MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB);
+               if (recv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+                       response->mad.mad.mad_hdr.status |= IB_SMP_DIRECTION;
 
                return true;
        } else {
@@ -1869,6 +1871,7 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
        struct ib_mad_list_head *mad_list;
        struct ib_mad_agent_private *mad_agent;
        int port_num;
+       int ret = IB_MAD_RESULT_SUCCESS;
 
        mad_list = (struct ib_mad_list_head *)(unsigned long)wc->wr_id;
        qp_info = mad_list->mad_queue->qp_info;
@@ -1952,8 +1955,6 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
 local:
        /* Give driver "right of first refusal" on incoming MAD */
        if (port_priv->device->process_mad) {
-               int ret;
-
                ret = port_priv->device->process_mad(port_priv->device, 0,
                                                     port_priv->port_num,
                                                     wc, &recv->grh,
@@ -1981,7 +1982,8 @@ local:
                 * or via recv_handler in ib_mad_complete_recv()
                 */
                recv = NULL;
-       } else if (generate_unmatched_resp(recv, response)) {
+       } else if ((ret & IB_MAD_RESULT_SUCCESS) &&
+                  generate_unmatched_resp(recv, response)) {
                agent_send_response(&response->mad.mad, &recv->grh, wc,
                                    port_priv->device, port_num, qp_info->qp->qp_num);
        }
index 83b720ef6c3497eec02327e62a930a1c6d478667..246fdc1516524cbc31940a6ed946e9b14ec741e8 100644 (file)
@@ -179,7 +179,7 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
 {
        struct ib_port_attr attr;
        char *speed = "";
-       int rate = -1;          /* in deci-Gb/sec */
+       int rate;               /* in deci-Gb/sec */
        ssize_t ret;
 
        ret = ib_query_port(p->ibdev, p->port_num, &attr);
@@ -187,9 +187,6 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
                return ret;
 
        switch (attr.active_speed) {
-       case IB_SPEED_SDR:
-               rate = 25;
-               break;
        case IB_SPEED_DDR:
                speed = " DDR";
                rate = 50;
@@ -210,6 +207,10 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
                speed = " EDR";
                rate = 250;
                break;
+       case IB_SPEED_SDR:
+       default:                /* default to SDR for invalid rates */
+               rate = 25;
+               break;
        }
 
        rate *= ib_width_enum_to_int(attr.active_width);
index 75d30562930058b14dd38700e3fe441f3bdcc796..b948b6dd5d553c9059cb9f655f104e3f9af7de34 100644 (file)
@@ -247,12 +247,17 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
                err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
                                   NULL, NULL, in_mad, out_mad);
                if (err)
-                       return err;
+                       goto out;
 
                /* Checking LinkSpeedActive for FDR-10 */
                if (out_mad->data[15] & 0x1)
                        props->active_speed = IB_SPEED_FDR10;
        }
+
+       /* Avoid wrong speed value returned by FW if the IB link is down. */
+       if (props->state == IB_PORT_DOWN)
+                props->active_speed = IB_SPEED_SDR;
+
 out:
        kfree(in_mad);
        kfree(out_mad);
index 69e2ad06e51593203df2a5abe99aeb353d1cdc3d..daf21b8999998781bde4856415a542bef142707e 100644 (file)
@@ -3232,6 +3232,7 @@ static void srpt_add_one(struct ib_device *device)
        srq_attr.attr.max_wr = sdev->srq_size;
        srq_attr.attr.max_sge = 1;
        srq_attr.attr.srq_limit = 0;
+       srq_attr.srq_type = IB_SRQT_BASIC;
 
        sdev->srq = ib_create_srq(sdev->pd, &srq_attr);
        if (IS_ERR(sdev->srq))
index 2d787796bf50a186d87652edbaad100217f85084..7faf4a7fcaa9219d278b67b75a77a6c10081f678 100644 (file)
@@ -380,8 +380,7 @@ config INPUT_TWL4030_VIBRA
 
 config INPUT_TWL6040_VIBRA
        tristate "Support for TWL6040 Vibrator"
-       depends on TWL4030_CORE
-       select TWL6040_CORE
+       depends on TWL6040_CORE
        select INPUT_FF_MEMLESS
        help
          This option enables support for TWL6040 Vibrator Driver.
index 34aebb8cd080602479de04d496ff3c5b9ee4b8f0..3c843cd725fac0ec0a7f4c63310f47ad942da0a0 100644 (file)
@@ -95,7 +95,8 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev)
        input_dev = input_allocate_device();
        if (!onkey || !input_dev) {
                dev_err(&pdev->dev, "Failed to allocate memory\n");
-               return -ENOMEM;
+               error = -ENOMEM;
+               goto err_free_mem;
        }
 
        onkey->input = input_dev;
index 45874fed523ab771e94f8b3d9dccf415b8cfa6af..14e94f56cb7d4dab69581335b2b82e9b822895f9 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
-#include <linux/i2c/twl.h>
+#include <linux/input.h>
 #include <linux/mfd/twl6040.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -257,7 +257,7 @@ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
 
 static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
 {
-       struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+       struct twl6040_vibra_data *pdata = pdev->dev.platform_data;
        struct vibra_info *info;
        int ret;
 
index d2c0db159b18dfc364c2ff7fc036863ef2de9614..479011004a111dcf41cc344356da29e3deb74902 100644 (file)
@@ -486,7 +486,6 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
        unsigned char *packet = psmouse->packet;
 
        input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
-       input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
        input_mt_report_pointer_emulation(dev, true);
        input_sync(dev);
 }
@@ -967,6 +966,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
        if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
                return -1;
 
+       __set_bit(INPUT_PROP_POINTER, dev->propbit);
        __set_bit(EV_KEY, dev->evbit);
        __set_bit(EV_ABS, dev->evbit);
        __clear_bit(EV_REL, dev->evbit);
@@ -1017,7 +1017,9 @@ static int elantech_set_input_params(struct psmouse *psmouse)
                         */
                        psmouse_warn(psmouse, "couldn't query resolution data.\n");
                }
-
+               /* v4 is clickpad, with only one button. */
+               __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
+               __clear_bit(BTN_RIGHT, dev->keybit);
                __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
                /* For X to recognize me as touchpad. */
                input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
@@ -1245,6 +1247,8 @@ static void elantech_disconnect(struct psmouse *psmouse)
  */
 static int elantech_reconnect(struct psmouse *psmouse)
 {
+       psmouse_reset(psmouse);
+
        if (elantech_detect(psmouse, 0))
                return -1;
 
@@ -1324,6 +1328,8 @@ int elantech_init(struct psmouse *psmouse)
        if (!etd)
                return -ENOMEM;
 
+       psmouse_reset(psmouse);
+
        etd->parity[0] = 1;
        for (i = 1; i < 256; i++)
                etd->parity[i] = etd->parity[i & (i - 1)] ^ 1;
index a9ad8e1402be217786574e88146d6e5d652a1e8e..39fe9b737cae5c57aca9a588247038cb75ff375c 100644 (file)
@@ -12,9 +12,9 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/input-polldev.h>
+#include <linux/gpio.h>
 #include <linux/gpio_mouse.h>
 
-#include <asm/gpio.h>
 
 /*
  * Timer function which is run every scan_ms ms when the device is opened.
index a977bfaa6821faef1c2993c919f77a854b9a03d8..661a0ca3b3d6939df7b11efd2576f4eb8dcc55f5 100644 (file)
@@ -741,6 +741,14 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
                        }
                } else {
                        /* SFAC packet */
+                       if ((packet[0] & (FSP_PB0_LBTN|FSP_PB0_PHY_BTN)) ==
+                               FSP_PB0_LBTN) {
+                               /* On-pad click in SFAC mode should be handled
+                                * by userspace.  On-pad clicks in MFMC mode
+                                * are real clickpad clicks, and not ignored.
+                                */
+                               packet[0] &= ~FSP_PB0_LBTN;
+                       }
 
                        /* no multi-finger information */
                        ad->last_mt_fgr = 0;
index 8081a0a5d602c0b9f04557b5323882c4bcf89694..a4b14a41cbf43a2d788989d7bfc3e71294ffc94e 100644 (file)
@@ -274,7 +274,8 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
        static unsigned char param = 0xc8;
        struct synaptics_data *priv = psmouse->private;
 
-       if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+       if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+             SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
                return 0;
 
        if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
index 22b218018137d964fdae5987addd66a1b7272320..f3102494237d207ecf5639d11d78e36d09e78050 100644 (file)
@@ -304,7 +304,7 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
                return 0;
 
        if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
-               printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
+               psmouse_warn(psmouse, "failed to get extended button data\n");
                button_info = 0;
        }
 
@@ -326,16 +326,18 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
 
        error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
        if (error) {
-               printk(KERN_ERR
-                       "trackpoint.c: failed to create sysfs attributes, error: %d\n",
-                       error);
+               psmouse_err(psmouse,
+                           "failed to create sysfs attributes, error: %d\n",
+                           error);
                kfree(psmouse->private);
                psmouse->private = NULL;
                return -1;
        }
 
-       printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
-               firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
+       psmouse_info(psmouse,
+                    "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
+                    firmware_id,
+                    (button_info & 0xf0) >> 4, button_info & 0x0f);
 
        return 0;
 }
index 6c6f6d8ea9b413d68b97b47c72e6d1e192e70e05..f7eda3d00fadb46216f09de8eaa9d7c911350d97 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/input/touchscreen/tps6507x_ts.c
- *
  * Touchscreen driver for the tps6507x chip.
  *
  * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com)
@@ -376,4 +374,4 @@ module_platform_driver(tps6507x_ts_driver);
 MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>");
 MODULE_DESCRIPTION("TPS6507x - TouchScreen driver");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:tps6507x-tsc");
+MODULE_ALIAS("platform:tps6507x-ts");
index ae2ec929e52f3e4ba76159e4df9448a6e315b115..a5bee8e2dfce7904b637f8fd3d9871c75b7824a5 100644 (file)
@@ -2707,7 +2707,8 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
  * The exported alloc_coherent function for dma_ops.
  */
 static void *alloc_coherent(struct device *dev, size_t size,
-                           dma_addr_t *dma_addr, gfp_t flag)
+                           dma_addr_t *dma_addr, gfp_t flag,
+                           struct dma_attrs *attrs)
 {
        unsigned long flags;
        void *virt_addr;
@@ -2765,7 +2766,8 @@ out_free:
  * The exported free_coherent function for dma_ops.
  */
 static void free_coherent(struct device *dev, size_t size,
-                         void *virt_addr, dma_addr_t dma_addr)
+                         void *virt_addr, dma_addr_t dma_addr,
+                         struct dma_attrs *attrs)
 {
        unsigned long flags;
        struct protection_domain *domain;
@@ -2846,8 +2848,8 @@ static void __init prealloc_protection_domains(void)
 }
 
 static struct dma_map_ops amd_iommu_dma_ops = {
-       .alloc_coherent = alloc_coherent,
-       .free_coherent = free_coherent,
+       .alloc = alloc_coherent,
+       .free = free_coherent,
        .map_page = map_page,
        .unmap_page = unmap_page,
        .map_sg = map_sg,
index 132f93b0515488a41ada28353e9de872e2c4f333..f93d5ac8f81c0b2ff02b6f97b2ae079b8b3f80a7 100644 (file)
@@ -2949,7 +2949,8 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
 }
 
 static void *intel_alloc_coherent(struct device *hwdev, size_t size,
-                                 dma_addr_t *dma_handle, gfp_t flags)
+                                 dma_addr_t *dma_handle, gfp_t flags,
+                                 struct dma_attrs *attrs)
 {
        void *vaddr;
        int order;
@@ -2981,7 +2982,7 @@ static void *intel_alloc_coherent(struct device *hwdev, size_t size,
 }
 
 static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
-                               dma_addr_t dma_handle)
+                               dma_addr_t dma_handle, struct dma_attrs *attrs)
 {
        int order;
 
@@ -3126,8 +3127,8 @@ static int intel_mapping_error(struct device *dev, dma_addr_t dma_addr)
 }
 
 struct dma_map_ops intel_dma_ops = {
-       .alloc_coherent = intel_alloc_coherent,
-       .free_coherent = intel_free_coherent,
+       .alloc = intel_alloc_coherent,
+       .free = intel_free_coherent,
        .map_sg = intel_map_sg,
        .unmap_sg = intel_unmap_sg,
        .map_page = intel_map_page,
index 103dbd92e2563ac55116b335fa35cb84f73fe7a8..f55fc5dfbadcfe420030cfd8b6632b98b48c2601 100644 (file)
@@ -323,15 +323,9 @@ err_out:
        return count;
 }
 
-static int debug_open_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 #define DEBUG_FOPS(name)                                               \
        static const struct file_operations debug_##name##_fops = {     \
-               .open = debug_open_generic,                             \
+               .open = simple_open,                                    \
                .read = debug_read_##name,                              \
                .write = debug_write_##name,                            \
                .llseek = generic_file_llseek,                          \
@@ -339,7 +333,7 @@ static int debug_open_generic(struct inode *inode, struct file *file)
 
 #define DEBUG_FOPS_RO(name)                                            \
        static const struct file_operations debug_##name##_fops = {     \
-               .open = debug_open_generic,                             \
+               .open = simple_open,                                    \
                .read = debug_read_##name,                              \
                .llseek = generic_file_llseek,                          \
        };
index b3d6ac17272d2872c0afc7c3bf1b72497e67266b..a6d9fd2858f74d2b6690cfcf9c6edc832f641bb2 100644 (file)
@@ -176,7 +176,7 @@ static void if_close(struct tty_struct *tty, struct file *filp)
        struct cardstate *cs = tty->driver_data;
 
        if (!cs) { /* happens if we didn't find cs in open */
-               printk(KERN_DEBUG "%s: no cardstate\n", __func__);
+               gig_dbg(DEBUG_IF, "%s: no cardstate", __func__);
                return;
        }
 
index 05ed4d0cb18b0e0195bbceae9fc4d6fea8956a0b..c0b8c960ee3f7f115c6a5cd9ca3a7469b3185f3b 100644 (file)
@@ -891,7 +891,7 @@ open_bchannel(struct fritzcard *fc, struct channel_req *rq)
 {
        struct bchannel         *bch;
 
-       if (rq->adr.channel > 2)
+       if (rq->adr.channel == 0 || rq->adr.channel > 2)
                return -EINVAL;
        if (rq->protocol == ISDN_P_NONE)
                return -EINVAL;
index d055ae7fa040ff80fb77841e94e15d66575505ba..e2c83a2d76910629fc319d506af8735b323d080a 100644 (file)
@@ -1962,7 +1962,7 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq)
 {
        struct bchannel         *bch;
 
-       if (rq->adr.channel > 2)
+       if (rq->adr.channel == 0 || rq->adr.channel > 2)
                return -EINVAL;
        if (rq->protocol == ISDN_P_NONE)
                return -EINVAL;
index 602338734634e184f50d8952911fa1d68d1cb9fd..8cde2a0538ab862f65b36411d4c3f06d2e0ec45e 100644 (file)
@@ -486,7 +486,7 @@ open_bchannel(struct hfcsusb *hw, struct channel_req *rq)
 {
        struct bchannel         *bch;
 
-       if (rq->adr.channel > 2)
+       if (rq->adr.channel == 0 || rq->adr.channel > 2)
                return -EINVAL;
        if (rq->protocol == ISDN_P_NONE)
                return -EINVAL;
index b47e9bed2185a5c944ce7d25b473ed816d560418..884369f09cad1e3dbd519a8ea392227e4c2b0fce 100644 (file)
@@ -1506,7 +1506,7 @@ open_bchannel(struct ipac_hw *ipac, struct channel_req *rq)
 {
        struct bchannel         *bch;
 
-       if (rq->adr.channel > 2)
+       if (rq->adr.channel == 0 || rq->adr.channel > 2)
                return -EINVAL;
        if (rq->protocol == ISDN_P_NONE)
                return -EINVAL;
index 10446ab404b55e48eb98be5b525ece01864db524..9a6da6edcfa899c99f62c140af7fe48223ce44cc 100644 (file)
@@ -1670,7 +1670,7 @@ isar_open(struct isar_hw *isar, struct channel_req *rq)
 {
        struct bchannel         *bch;
 
-       if (rq->adr.channel > 2)
+       if (rq->adr.channel == 0 || rq->adr.channel > 2)
                return -EINVAL;
        if (rq->protocol == ISDN_P_NONE)
                return -EINVAL;
index dd6de9f7a8a34ed0dd4f808c3b1a9f6783edc442..c726e09d0981bafc8ee3c1d2680a1e83326422c0 100644 (file)
@@ -860,7 +860,7 @@ open_bchannel(struct tiger_hw *card, struct channel_req *rq)
 {
        struct bchannel *bch;
 
-       if (rq->adr.channel > 2)
+       if (rq->adr.channel == 0 || rq->adr.channel > 2)
                return -EINVAL;
        if (rq->protocol == ISDN_P_NONE)
                return -EINVAL;
index 7f1e7ba75cd10c149d57c85551c54c02d3ee3db7..2183357f079948fe7590df8c095289329c231748 100644 (file)
@@ -1015,7 +1015,7 @@ open_bchannel(struct w6692_hw *card, struct channel_req *rq)
 {
        struct bchannel *bch;
 
-       if (rq->adr.channel > 2)
+       if (rq->adr.channel == 0 || rq->adr.channel > 2)
                return -EINVAL;
        if (rq->protocol == ISDN_P_NONE)
                return -EINVAL;
index 800243b6037ed9edc5b945b74d226a17be05f712..64ad702a2ecc64eff2505fd0f4217126fd10bdf9 100644 (file)
@@ -35,7 +35,7 @@ static void pwmled_brightness(struct led_classdev *cdev, enum led_brightness b)
  * NOTE:  we reuse the platform_data structure of GPIO leds,
  * but repurpose its "gpio" number as a PWM channel number.
  */
-static int __init pwmled_probe(struct platform_device *pdev)
+static int __devinit pwmled_probe(struct platform_device *pdev)
 {
        const struct gpio_led_platform_data     *pdata;
        struct pwmled                           *leds;
index 3d0dfa7a89a2d683c8ccdbe76eedd02260550cba..17e2b472e16dccba1a94202f616f260e8f656b6c 100644 (file)
@@ -539,9 +539,6 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap)
        bitmap->events_cleared = bitmap->mddev->events;
        sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
 
-       bitmap->flags |= BITMAP_HOSTENDIAN;
-       sb->version = cpu_to_le32(BITMAP_MAJOR_HOSTENDIAN);
-
        kunmap_atomic(sb);
 
        return 0;
@@ -1730,8 +1727,7 @@ int bitmap_create(struct mddev *mddev)
        bitmap->chunkshift = (ffz(~mddev->bitmap_info.chunksize)
                              - BITMAP_BLOCK_SHIFT);
 
-       /* now that chunksize and chunkshift are set, we can use these macros */
-       chunks = (blocks + bitmap->chunkshift - 1) >>
+       chunks = (blocks + (1 << bitmap->chunkshift) - 1) >>
                        bitmap->chunkshift;
        pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;
 
@@ -1788,7 +1784,9 @@ int bitmap_load(struct mddev *mddev)
                 * re-add of a missing device */
                start = mddev->recovery_cp;
 
+       mutex_lock(&mddev->bitmap_info.mutex);
        err = bitmap_init_from_disk(bitmap, start);
+       mutex_unlock(&mddev->bitmap_info.mutex);
 
        if (err)
                goto out;
index 55ca5aec84e4cb06280f335a6b260ac2ae23dd5c..b44b0aba2d47b970f9b76f39763192995e5984fb 100644 (file)
@@ -101,9 +101,6 @@ typedef __u16 bitmap_counter_t;
 
 #define BITMAP_BLOCK_SHIFT 9
 
-/* how many blocks per chunk? (this is variable) */
-#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->mddev->bitmap_info.chunksize >> BITMAP_BLOCK_SHIFT)
-
 #endif
 
 /*
index b0ba52459ed7381d4a802acb94e69df02f979149..68965e663248e2f0b0158aaf9a75f2583be2704c 100644 (file)
@@ -859,7 +859,7 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
        int ret;
        unsigned redundancy = 0;
        struct raid_dev *dev;
-       struct md_rdev *rdev, *freshest;
+       struct md_rdev *rdev, *tmp, *freshest;
        struct mddev *mddev = &rs->md;
 
        switch (rs->raid_type->level) {
@@ -877,7 +877,7 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
        }
 
        freshest = NULL;
-       rdev_for_each(rdev, mddev) {
+       rdev_for_each_safe(rdev, tmp, mddev) {
                if (!rdev->meta_bdev)
                        continue;
 
index b0fcc7d02adb49b37275ccf9caa2c48465e886ad..fa211d80fc0a1e4e37603b1455184cbee7da6e56 100644 (file)
@@ -198,6 +198,7 @@ out:
 static int linear_run (struct mddev *mddev)
 {
        struct linear_conf *conf;
+       int ret;
 
        if (md_check_no_bitmap(mddev))
                return -EINVAL;
@@ -211,7 +212,13 @@ static int linear_run (struct mddev *mddev)
        blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
        mddev->queue->backing_dev_info.congested_fn = linear_congested;
        mddev->queue->backing_dev_info.congested_data = mddev;
-       return md_integrity_register(mddev);
+
+       ret =  md_integrity_register(mddev);
+       if (ret) {
+               kfree(conf);
+               mddev->private = NULL;
+       }
+       return ret;
 }
 
 static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
index b572e1e386ceab73643f3d0ffc272c1989b91474..477eb2e180c031d84b33d659167d8aea760babfe 100644 (file)
@@ -7560,14 +7560,14 @@ void md_check_recovery(struct mddev *mddev)
                 * any transients in the value of "sync_action".
                 */
                set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
-               clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                /* Clear some bits that don't mean anything, but
                 * might be left set
                 */
                clear_bit(MD_RECOVERY_INTR, &mddev->recovery);
                clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
 
-               if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
+               if (!test_and_clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
+                   test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
                        goto unlock;
                /* no recovery is running.
                 * remove any failed drives, then
@@ -8140,7 +8140,8 @@ static int md_notify_reboot(struct notifier_block *this,
 
        for_each_mddev(mddev, tmp) {
                if (mddev_trylock(mddev)) {
-                       __md_stop_writes(mddev);
+                       if (mddev->pers)
+                               __md_stop_writes(mddev);
                        mddev->safemode = 2;
                        mddev_unlock(mddev);
                }
index 6f31f5596e01e0d032f50db71077e07d3af5c3e4..de63a1fc3737b7ac2af3c0f7cbf60cd99b495a31 100644 (file)
@@ -407,6 +407,8 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks
        return array_sectors;
 }
 
+static int raid0_stop(struct mddev *mddev);
+
 static int raid0_run(struct mddev *mddev)
 {
        struct r0conf *conf;
@@ -454,7 +456,12 @@ static int raid0_run(struct mddev *mddev)
 
        blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
        dump_zones(mddev);
-       return md_integrity_register(mddev);
+
+       ret = md_integrity_register(mddev);
+       if (ret)
+               raid0_stop(mddev);
+
+       return ret;
 }
 
 static int raid0_stop(struct mddev *mddev)
@@ -625,6 +632,7 @@ static void *raid0_takeover_raid10(struct mddev *mddev)
 static void *raid0_takeover_raid1(struct mddev *mddev)
 {
        struct r0conf *priv_conf;
+       int chunksect;
 
        /* Check layout:
         *  - (N - 1) mirror drives must be already faulty
@@ -635,10 +643,25 @@ static void *raid0_takeover_raid1(struct mddev *mddev)
                return ERR_PTR(-EINVAL);
        }
 
+       /*
+        * a raid1 doesn't have the notion of chunk size, so
+        * figure out the largest suitable size we can use.
+        */
+       chunksect = 64 * 2; /* 64K by default */
+
+       /* The array must be an exact multiple of chunksize */
+       while (chunksect && (mddev->array_sectors & (chunksect - 1)))
+               chunksect >>= 1;
+
+       if ((chunksect << 9) < PAGE_SIZE)
+               /* array size does not allow a suitable chunk size */
+               return ERR_PTR(-EINVAL);
+
        /* Set new parameters */
        mddev->new_level = 0;
        mddev->new_layout = 0;
-       mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */
+       mddev->new_chunk_sectors = chunksect;
+       mddev->chunk_sectors = chunksect;
        mddev->delta_disks = 1 - mddev->raid_disks;
        mddev->raid_disks = 1;
        /* make sure it will be not marked as dirty */
index 4a40a200d7696319c59cafacfffbf9044d12743c..15dd59b84e94442c50ae164cb2ec1c130a74bc52 100644 (file)
@@ -1712,6 +1712,7 @@ static int process_checks(struct r1bio *r1_bio)
        struct r1conf *conf = mddev->private;
        int primary;
        int i;
+       int vcnt;
 
        for (primary = 0; primary < conf->raid_disks * 2; primary++)
                if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
@@ -1721,9 +1722,9 @@ static int process_checks(struct r1bio *r1_bio)
                        break;
                }
        r1_bio->read_disk = primary;
+       vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9);
        for (i = 0; i < conf->raid_disks * 2; i++) {
                int j;
-               int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9);
                struct bio *pbio = r1_bio->bios[primary];
                struct bio *sbio = r1_bio->bios[i];
                int size;
@@ -1738,7 +1739,7 @@ static int process_checks(struct r1bio *r1_bio)
                                s = sbio->bi_io_vec[j].bv_page;
                                if (memcmp(page_address(p),
                                           page_address(s),
-                                          PAGE_SIZE))
+                                          sbio->bi_io_vec[j].bv_len))
                                        break;
                        }
                } else
@@ -2386,8 +2387,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
                int ok = 1;
                for (i = 0 ; i < conf->raid_disks * 2 ; i++)
                        if (r1_bio->bios[i]->bi_end_io == end_sync_write) {
-                               struct md_rdev *rdev =
-                                       rcu_dereference(conf->mirrors[i].rdev);
+                               struct md_rdev *rdev = conf->mirrors[i].rdev;
                                ok = rdev_set_badblocks(rdev, sector_nr,
                                                        min_bad, 0
                                        ) && ok;
@@ -2636,11 +2636,13 @@ static struct r1conf *setup_conf(struct mddev *mddev)
        return ERR_PTR(err);
 }
 
+static int stop(struct mddev *mddev);
 static int run(struct mddev *mddev)
 {
        struct r1conf *conf;
        int i;
        struct md_rdev *rdev;
+       int ret;
 
        if (mddev->level != 1) {
                printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n",
@@ -2705,7 +2707,11 @@ static int run(struct mddev *mddev)
                mddev->queue->backing_dev_info.congested_data = mddev;
                blk_queue_merge_bvec(mddev->queue, raid1_mergeable_bvec);
        }
-       return md_integrity_register(mddev);
+
+       ret =  md_integrity_register(mddev);
+       if (ret)
+               stop(mddev);
+       return ret;
 }
 
 static int stop(struct mddev *mddev)
index 3540316886f2bca71a7bd943c4cf98de610ac1ae..c8dbb84d53579ab3e5c9ebc012a06cdb5205058f 100644 (file)
@@ -1788,6 +1788,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
        struct r10conf *conf = mddev->private;
        int i, first;
        struct bio *tbio, *fbio;
+       int vcnt;
 
        atomic_set(&r10_bio->remaining, 1);
 
@@ -1802,10 +1803,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
        first = i;
        fbio = r10_bio->devs[i].bio;
 
+       vcnt = (r10_bio->sectors + (PAGE_SIZE >> 9) - 1) >> (PAGE_SHIFT - 9);
        /* now find blocks with errors */
        for (i=0 ; i < conf->copies ; i++) {
                int  j, d;
-               int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
 
                tbio = r10_bio->devs[i].bio;
 
@@ -1821,7 +1822,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
                        for (j = 0; j < vcnt; j++)
                                if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
                                           page_address(tbio->bi_io_vec[j].bv_page),
-                                          PAGE_SIZE))
+                                          fbio->bi_io_vec[j].bv_len))
                                        break;
                        if (j == vcnt)
                                continue;
@@ -1871,7 +1872,6 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
         */
        for (i = 0; i < conf->copies; i++) {
                int j, d;
-               int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
 
                tbio = r10_bio->devs[i].repl_bio;
                if (!tbio || !tbio->bi_end_io)
index 23ac880bba9a5cbee0533e5144f135d3eb120ace..f351422938e05f0718d9d71be8ff1b86621b948c 100644 (file)
@@ -2471,39 +2471,41 @@ handle_failed_sync(struct r5conf *conf, struct stripe_head *sh,
        int abort = 0;
        int i;
 
-       md_done_sync(conf->mddev, STRIPE_SECTORS, 0);
        clear_bit(STRIPE_SYNCING, &sh->state);
        s->syncing = 0;
        s->replacing = 0;
        /* There is nothing more to do for sync/check/repair.
+        * Don't even need to abort as that is handled elsewhere
+        * if needed, and not always wanted e.g. if there is a known
+        * bad block here.
         * For recover/replace we need to record a bad block on all
         * non-sync devices, or abort the recovery
         */
-       if (!test_bit(MD_RECOVERY_RECOVER, &conf->mddev->recovery))
-               return;
-       /* During recovery devices cannot be removed, so locking and
-        * refcounting of rdevs is not needed
-        */
-       for (i = 0; i < conf->raid_disks; i++) {
-               struct md_rdev *rdev = conf->disks[i].rdev;
-               if (rdev
-                   && !test_bit(Faulty, &rdev->flags)
-                   && !test_bit(In_sync, &rdev->flags)
-                   && !rdev_set_badblocks(rdev, sh->sector,
-                                          STRIPE_SECTORS, 0))
-                       abort = 1;
-               rdev = conf->disks[i].replacement;
-               if (rdev
-                   && !test_bit(Faulty, &rdev->flags)
-                   && !test_bit(In_sync, &rdev->flags)
-                   && !rdev_set_badblocks(rdev, sh->sector,
-                                          STRIPE_SECTORS, 0))
-                       abort = 1;
-       }
-       if (abort) {
-               conf->recovery_disabled = conf->mddev->recovery_disabled;
-               set_bit(MD_RECOVERY_INTR, &conf->mddev->recovery);
+       if (test_bit(MD_RECOVERY_RECOVER, &conf->mddev->recovery)) {
+               /* During recovery devices cannot be removed, so
+                * locking and refcounting of rdevs is not needed
+                */
+               for (i = 0; i < conf->raid_disks; i++) {
+                       struct md_rdev *rdev = conf->disks[i].rdev;
+                       if (rdev
+                           && !test_bit(Faulty, &rdev->flags)
+                           && !test_bit(In_sync, &rdev->flags)
+                           && !rdev_set_badblocks(rdev, sh->sector,
+                                                  STRIPE_SECTORS, 0))
+                               abort = 1;
+                       rdev = conf->disks[i].replacement;
+                       if (rdev
+                           && !test_bit(Faulty, &rdev->flags)
+                           && !test_bit(In_sync, &rdev->flags)
+                           && !rdev_set_badblocks(rdev, sh->sector,
+                                                  STRIPE_SECTORS, 0))
+                               abort = 1;
+               }
+               if (abort)
+                       conf->recovery_disabled =
+                               conf->mddev->recovery_disabled;
        }
+       md_done_sync(conf->mddev, STRIPE_SECTORS, !abort);
 }
 
 static int want_replace(struct stripe_head *sh, int disk_idx)
@@ -3203,7 +3205,8 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
                        /* Not in-sync */;
                else if (is_bad) {
                        /* also not in-sync */
-                       if (!test_bit(WriteErrorSeen, &rdev->flags)) {
+                       if (!test_bit(WriteErrorSeen, &rdev->flags) &&
+                           test_bit(R5_UPTODATE, &dev->flags)) {
                                /* treat as in-sync, but with a read error
                                 * which we can now try to correct
                                 */
@@ -3276,12 +3279,14 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
                /* If there is a failed device being replaced,
                 *     we must be recovering.
                 * else if we are after recovery_cp, we must be syncing
+                * else if MD_RECOVERY_REQUESTED is set, we also are syncing.
                 * else we can only be replacing
                 * sync and recovery both need to read all devices, and so
                 * use the same flag.
                 */
                if (do_recovery ||
-                   sh->sector >= conf->mddev->recovery_cp)
+                   sh->sector >= conf->mddev->recovery_cp ||
+                   test_bit(MD_RECOVERY_REQUESTED, &(conf->mddev->recovery)))
                        s->syncing = 1;
                else
                        s->replacing = 1;
index 7f98984e4fad0526fbe98335a29b166cf6bba428..eab2ea42420090c7847cd5d4eaa889659bf351b4 100644 (file)
@@ -54,6 +54,7 @@ struct xc5000_priv {
        struct list_head hybrid_tuner_instance_list;
 
        u32 if_khz;
+       u32 xtal_khz;
        u32 freq_hz;
        u32 bandwidth;
        u8  video_standard;
@@ -214,9 +215,9 @@ static const struct xc5000_fw_cfg xc5000a_1_6_114 = {
        .size = 12401,
 };
 
-static const struct xc5000_fw_cfg xc5000c_41_024_5_31875 = {
-       .name = "dvb-fe-xc5000c-41.024.5-31875.fw",
-       .size = 16503,
+static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
+       .name = "dvb-fe-xc5000c-41.024.5.fw",
+       .size = 16497,
 };
 
 static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
@@ -226,7 +227,7 @@ static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
        case XC5000A:
                return &xc5000a_1_6_114;
        case XC5000C:
-               return &xc5000c_41_024_5_31875;
+               return &xc5000c_41_024_5;
        }
 }
 
@@ -572,6 +573,31 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
        return found;
 }
 
+static int xc_set_xtal(struct dvb_frontend *fe)
+{
+       struct xc5000_priv *priv = fe->tuner_priv;
+       int ret = XC_RESULT_SUCCESS;
+
+       switch (priv->chip_id) {
+       default:
+       case XC5000A:
+               /* 32.000 MHz xtal is default */
+               break;
+       case XC5000C:
+               switch (priv->xtal_khz) {
+               default:
+               case 32000:
+                       /* 32.000 MHz xtal is default */
+                       break;
+               case 31875:
+                       /* 31.875 MHz xtal configuration */
+                       ret = xc_write_reg(priv, 0x000f, 0x8081);
+                       break;
+               }
+               break;
+       }
+       return ret;
+}
 
 static int xc5000_fwupload(struct dvb_frontend *fe)
 {
@@ -603,6 +629,8 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
        } else {
                printk(KERN_INFO "xc5000: firmware uploading...\n");
                ret = xc_load_i2c_sequence(fe,  fw->data);
+               if (XC_RESULT_SUCCESS == ret)
+                       ret = xc_set_xtal(fe);
                printk(KERN_INFO "xc5000: firmware upload complete...\n");
        }
 
@@ -1164,6 +1192,9 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                priv->if_khz = cfg->if_khz;
        }
 
+       if (priv->xtal_khz == 0)
+               priv->xtal_khz = cfg->xtal_khz;
+
        if (priv->radio_input == 0)
                priv->radio_input = cfg->radio_input;
 
index 3396f8e02b40c2fb1363bedb891c76badbbf9da8..39a73bf01406c8e3d2df4a3f6cc53ac7f065467c 100644 (file)
@@ -34,6 +34,7 @@ struct xc5000_config {
        u8   i2c_address;
        u32  if_khz;
        u8   radio_input;
+       u32  xtal_khz;
 
        int chip_id;
 };
index 4555baa383b26ec58b987bb65fecbe8303d7c504..0f64d71826572d298d4cbf19050e8be254fce887 100644 (file)
@@ -143,10 +143,12 @@ struct dvb_frontend_private {
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
 static int dtv_get_frontend(struct dvb_frontend *fe,
                            struct dvb_frontend_parameters *p_out);
+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
+                                          struct dvb_frontend_parameters *p);
 
 static bool has_get_frontend(struct dvb_frontend *fe)
 {
-       return fe->ops.get_frontend;
+       return fe->ops.get_frontend != NULL;
 }
 
 /*
@@ -697,6 +699,7 @@ restart:
                                        fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
                                        fepriv->delay = HZ / 2;
                                }
+                               dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
                                fe->ops.read_status(fe, &s);
                                if (s != fepriv->status) {
                                        dvb_frontend_add_event(fe, s); /* update event list */
@@ -1443,6 +1446,28 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                                __func__);
                        return -EINVAL;
                }
+               /*
+                * Get a delivery system that is compatible with DVBv3
+                * NOTE: in order for this to work with softwares like Kaffeine that
+                *      uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
+                *      DVB-S, drivers that support both should put the SYS_DVBS entry
+                *      before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
+                *      The real fix is that userspace applications should not use DVBv3
+                *      and not trust on calling FE_SET_FRONTEND to switch the delivery
+                *      system.
+                */
+               ncaps = 0;
+               while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+                       if (fe->ops.delsys[ncaps] == desired_system) {
+                               delsys = desired_system;
+                               break;
+                       }
+                       ncaps++;
+               }
+               if (delsys == SYS_UNDEFINED) {
+                       dprintk("%s() Couldn't find a delivery system that matches %d\n",
+                               __func__, desired_system);
+               }
        } else {
                /*
                 * This is a DVBv5 call. So, it likely knows the supported
@@ -1491,9 +1516,10 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                                __func__);
                        return -EINVAL;
                }
-               c->delivery_system = delsys;
        }
 
+       c->delivery_system = delsys;
+
        /*
         * The DVBv3 or DVBv5 call is requesting a different system. So,
         * emulation is needed.
@@ -1832,6 +1858,13 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
        if (dvb_frontend_check_parameters(fe) < 0)
                return -EINVAL;
 
+       /*
+        * Initialize output parameters to match the values given by
+        * the user. FE_SET_FRONTEND triggers an initial frontend event
+        * with status = 0, which copies output parameters to userspace.
+        */
+       dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
+
        /*
         * Be sure that the bandwidth will be filled for all
         * non-satellite systems, as tuners need to know what
index 3b7b102f20ae076fe5033092db4333dfbcdbb8fe..482d249ca7f3f0613d8aee2bf7c3ca27804a908a 100644 (file)
@@ -238,12 +238,27 @@ static int it913x_read_reg(struct usb_device *udev, u32 reg)
 
 static u32 it913x_query(struct usb_device *udev, u8 pro)
 {
-       int ret;
+       int ret, i;
        u8 data[4];
-       ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
-               0x1222, 0, &data[0], 3);
+       u8 ver;
+
+       for (i = 0; i < 5; i++) {
+               ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
+                       0x1222, 0, &data[0], 3);
+               ver = data[0];
+               if (ver > 0 && ver < 3)
+                       break;
+               msleep(100);
+       }
 
-       it913x_config.chip_ver = data[0];
+       if (ver < 1 || ver > 2) {
+               info("Failed to identify chip version applying 1");
+               it913x_config.chip_ver = 0x1;
+               it913x_config.chip_type = 0x9135;
+               return 0;
+       }
+
+       it913x_config.chip_ver = ver;
        it913x_config.chip_type = (u16)(data[2] << 8) + data[1];
 
        info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver,
@@ -660,30 +675,41 @@ static int it913x_download_firmware(struct usb_device *udev,
                        if ((packet_size > min_pkt) || (i == fw->size)) {
                                fw_data = (u8 *)(fw->data + pos);
                                pos += packet_size;
-                               if (packet_size > 0)
-                                       ret |= it913x_io(udev, WRITE_DATA,
+                               if (packet_size > 0) {
+                                       ret = it913x_io(udev, WRITE_DATA,
                                                DEV_0, CMD_SCATTER_WRITE, 0,
                                                0, fw_data, packet_size);
+                                       if (ret < 0)
+                                               break;
+                               }
                                udelay(1000);
                        }
                }
                i++;
        }
 
-       ret |= it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
-
-       msleep(100);
-
        if (ret < 0)
-               info("FRM Firmware Download Failed (%04x)" , ret);
+               info("FRM Firmware Download Failed (%d)" , ret);
        else
                info("FRM Firmware Download Completed - Resetting Device");
 
-       ret |= it913x_return_status(udev);
+       msleep(30);
+
+       ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
+       if (ret < 0)
+               info("FRM Device not responding to reboot");
+
+       ret = it913x_return_status(udev);
+       if (ret == 0) {
+               info("FRM Failed to reboot device");
+               return -ENODEV;
+       }
 
        msleep(30);
 
-       ret |= it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_400);
+       ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_400);
+
+       msleep(30);
 
        /* Tuner function */
        if (it913x_config.dual_mode)
@@ -901,5 +927,5 @@ module_usb_driver(it913x_driver);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("it913x USB 2 Driver");
-MODULE_VERSION("1.27");
+MODULE_VERSION("1.28");
 MODULE_LICENSE("GPL");
index 36d11756492f5f62471ba412786d8183e271aecc..a414b1f2b6a5a0f2cd1c4dcfef210ea45189f912 100644 (file)
@@ -1520,8 +1520,10 @@ static int scu_command(struct drxk_state *state,
        dprintk(1, "\n");
 
        if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) ||
-           ((resultLen > 0) && (result == NULL)))
-               goto error;
+           ((resultLen > 0) && (result == NULL))) {
+               printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+               return status;
+       }
 
        mutex_lock(&state->mutex);
 
index b09c5fae489bd020ea4748cd9c33d67dc12568b0..af526586fa263f63ccf6d2088f10a779724fb3a8 100644 (file)
@@ -1046,6 +1046,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
                goto exit_unregister_led;
        }
 
+       data->dev->driver_type = RC_DRIVER_IR_RAW;
        data->dev->driver_name = WBCIR_NAME;
        data->dev->input_name = WBCIR_NAME;
        data->dev->input_phys = "wbcir/cir0";
index f2479c5c0eb23071d6f3d29c6cd598b7f777e55b..ce1e7ba940f6c75ac2818b799010deee37553c48 100644 (file)
@@ -492,7 +492,7 @@ config VIDEO_VS6624
 
 config VIDEO_MT9M032
        tristate "MT9M032 camera sensor support"
-       depends on I2C && VIDEO_V4L2
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
        select VIDEO_APTINA_PLL
        ---help---
          This driver supports MT9M032 camera sensors from Aptina, monochrome
index 5452beef8e117cf75a99963a5e04f204d13d5083..989e556913edd063f35013c3004677196bfa19f5 100644 (file)
@@ -1763,13 +1763,13 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
                IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
                if (iarg > AUDIO_STEREO_SWAPPED)
                        return -EINVAL;
-               return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg);
+               return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
 
        case AUDIO_BILINGUAL_CHANNEL_SELECT:
                IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
                if (iarg > AUDIO_STEREO_SWAPPED)
                        return -EINVAL;
-               return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg);
+               return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
 
        default:
                return -EINVAL;
index 7636672c3548a45fc1b76dc502d099b34c472533..645973c5feb01d7a9413310a106a35af59dd4c0d 100644 (file)
@@ -392,10 +392,11 @@ static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
        }
 
        /* Scaling is not supported, the format is thus fixed. */
-       ret = mt9m032_get_pad_format(subdev, fh, fmt);
+       fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which);
+       ret = 0;
 
 done:
-       mutex_lock(&sensor->lock);
+       mutex_unlock(&sensor->lock);
        return ret;
 }
 
index 4a44f9a1bae00e0610f8c3d382cd5110d422f851..b76b0ac0958f8d2d27a5a7193c623badfac5ee67 100644 (file)
@@ -468,22 +468,30 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
        spin_unlock_irqrestore(&stream->clock.lock, flags);
 }
 
-static int uvc_video_clock_init(struct uvc_streaming *stream)
+static void uvc_video_clock_reset(struct uvc_streaming *stream)
 {
        struct uvc_clock *clock = &stream->clock;
 
-       spin_lock_init(&clock->lock);
        clock->head = 0;
        clock->count = 0;
-       clock->size = 32;
        clock->last_sof = -1;
        clock->sof_offset = -1;
+}
+
+static int uvc_video_clock_init(struct uvc_streaming *stream)
+{
+       struct uvc_clock *clock = &stream->clock;
+
+       spin_lock_init(&clock->lock);
+       clock->size = 32;
 
        clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
                                 GFP_KERNEL);
        if (clock->samples == NULL)
                return -ENOMEM;
 
+       uvc_video_clock_reset(stream);
+
        return 0;
 }
 
@@ -1424,8 +1432,6 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
 
        if (free_buffers)
                uvc_free_urb_buffers(stream);
-
-       uvc_video_clock_cleanup(stream);
 }
 
 /*
@@ -1555,10 +1561,6 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
 
        uvc_video_stats_start(stream);
 
-       ret = uvc_video_clock_init(stream);
-       if (ret < 0)
-               return ret;
-
        if (intf->num_altsetting > 1) {
                struct usb_host_endpoint *best_ep = NULL;
                unsigned int best_psize = 3 * 1024;
@@ -1683,6 +1685,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset)
 
        stream->frozen = 0;
 
+       uvc_video_clock_reset(stream);
+
        ret = uvc_commit_video(stream, &stream->ctrl);
        if (ret < 0) {
                uvc_queue_enable(&stream->queue, 0);
@@ -1819,25 +1823,35 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
                uvc_uninit_video(stream, 1);
                usb_set_interface(stream->dev->udev, stream->intfnum, 0);
                uvc_queue_enable(&stream->queue, 0);
+               uvc_video_clock_cleanup(stream);
                return 0;
        }
 
-       ret = uvc_queue_enable(&stream->queue, 1);
+       ret = uvc_video_clock_init(stream);
        if (ret < 0)
                return ret;
 
+       ret = uvc_queue_enable(&stream->queue, 1);
+       if (ret < 0)
+               goto error_queue;
+
        /* Commit the streaming parameters. */
        ret = uvc_commit_video(stream, &stream->ctrl);
-       if (ret < 0) {
-               uvc_queue_enable(&stream->queue, 0);
-               return ret;
-       }
+       if (ret < 0)
+               goto error_commit;
 
        ret = uvc_init_video(stream, GFP_KERNEL);
-       if (ret < 0) {
-               usb_set_interface(stream->dev->udev, stream->intfnum, 0);
-               uvc_queue_enable(&stream->queue, 0);
-       }
+       if (ret < 0)
+               goto error_video;
+
+       return 0;
+
+error_video:
+       usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+error_commit:
+       uvc_queue_enable(&stream->queue, 0);
+error_queue:
+       uvc_video_clock_cleanup(stream);
 
        return ret;
 }
index 29f463cc09cbc5dc56ec215a225548be8a65b900..11e44386fa9bba2287c3fda66b422b3f88c57963 100644 (file)
@@ -268,10 +268,17 @@ config TWL6030_PWM
          This is used to control charging LED brightness.
 
 config TWL6040_CORE
-       bool
-       depends on TWL4030_CORE && GENERIC_HARDIRQS
+       bool "Support for TWL6040 audio codec"
+       depends on I2C=y && GENERIC_HARDIRQS
        select MFD_CORE
+       select REGMAP_I2C
        default n
+       help
+         Say yes here if you want support for Texas Instruments TWL6040 audio
+         codec.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device (audio, vibra).
 
 config MFD_STMPE
        bool "Support STMicroelectronics STMPE"
index 3aa36eb5c79bcf769616013cd3176ed04af500bc..44a3fdbadef40df1e09b12884f44caa46b76f0ac 100644 (file)
@@ -262,13 +262,6 @@ static ssize_t aat2870_dump_reg(struct aat2870_data *aat2870, char *buf)
        return count;
 }
 
-static int aat2870_reg_open_file(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-
-       return 0;
-}
-
 static ssize_t aat2870_reg_read_file(struct file *file, char __user *user_buf,
                                     size_t count, loff_t *ppos)
 {
@@ -330,7 +323,7 @@ static ssize_t aat2870_reg_write_file(struct file *file,
 }
 
 static const struct file_operations aat2870_reg_fops = {
-       .open = aat2870_reg_open_file,
+       .open = simple_open,
        .read = aat2870_reg_read_file,
        .write = aat2870_reg_write_file,
 };
index 60107ee166fc4852da4bd63835913fca96becac6..1efad20fb1757523713359ff5af65f3d13ca4302 100644 (file)
@@ -483,12 +483,6 @@ struct ab3100_get_set_reg_priv {
        bool mode;
 };
 
-static int ab3100_get_set_reg_open_file(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t ab3100_get_set_reg(struct file *file,
                                  const char __user *user_buf,
                                  size_t count, loff_t *ppos)
@@ -583,7 +577,7 @@ static ssize_t ab3100_get_set_reg(struct file *file,
 }
 
 static const struct file_operations ab3100_get_set_reg_fops = {
-       .open = ab3100_get_set_reg_open_file,
+       .open = simple_open,
        .write = ab3100_get_set_reg,
        .llseek = noop_llseek,
 };
index 1895cf9fab8c1b1c491cbc611335775f014760e0..1582c3d952579e66306e1ad8ce2713f3b0d03f9c 100644 (file)
@@ -527,7 +527,9 @@ static void asic3_gpio_set(struct gpio_chip *chip,
 
 static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-       return (offset < ASIC3_NUM_GPIOS) ? IRQ_BOARD_START + offset : -ENXIO;
+       struct asic3 *asic = container_of(chip, struct asic3, gpio);
+
+       return (offset < ASIC3_NUM_GPIOS) ? asic->irq_base + offset : -ENXIO;
 }
 
 static __init int asic3_gpio_probe(struct platform_device *pdev,
index ebc1e8658226bbfca7505f2d109d119a9598e690..5be32489714f61a279b4fe30ce7badb37d5833a4 100644 (file)
@@ -2788,6 +2788,7 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                .constraints = {
                        .name = "db8500-vape",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+                       .always_on = true,
                },
                .consumer_supplies = db8500_vape_consumers,
                .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers),
index 95a2e546a48962c18cfaa151aa7dc539e4c94035..7e96bb2297244f7946537a5da5f78226e6a4db40 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
-#include <linux/gpio.h>
+#include <plat/cpu.h>
 #include <plat/usb.h>
 #include <linux/pm_runtime.h>
 
@@ -502,19 +502,6 @@ static void omap_usbhs_init(struct device *dev)
        pm_runtime_get_sync(dev);
        spin_lock_irqsave(&omap->lock, flags);
 
-       if (pdata->ehci_data->phy_reset) {
-               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
-                       gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
-                                        GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
-
-               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
-                       gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
-                                        GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
-
-               /* Hold the PHY in RESET for enough time till DIR is high */
-               udelay(10);
-       }
-
        omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
        dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
 
@@ -593,39 +580,10 @@ static void omap_usbhs_init(struct device *dev)
                        usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT);
        }
 
-       if (pdata->ehci_data->phy_reset) {
-               /* Hold the PHY in RESET for enough time till
-                * PHY is settled and ready
-                */
-               udelay(10);
-
-               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
-                       gpio_set_value
-                               (pdata->ehci_data->reset_gpio_port[0], 1);
-
-               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
-                       gpio_set_value
-                               (pdata->ehci_data->reset_gpio_port[1], 1);
-       }
-
        spin_unlock_irqrestore(&omap->lock, flags);
        pm_runtime_put_sync(dev);
 }
 
-static void omap_usbhs_deinit(struct device *dev)
-{
-       struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
-       struct usbhs_omap_platform_data *pdata = &omap->platdata;
-
-       if (pdata->ehci_data->phy_reset) {
-               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
-                       gpio_free(pdata->ehci_data->reset_gpio_port[0]);
-
-               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
-                       gpio_free(pdata->ehci_data->reset_gpio_port[1]);
-       }
-}
-
 
 /**
  * usbhs_omap_probe - initialize TI-based HCDs
@@ -860,7 +818,6 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
 {
        struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
 
-       omap_usbhs_deinit(&pdev->dev);
        iounmap(omap->tll_base);
        iounmap(omap->uhh_base);
        clk_put(omap->init_60m_fclk);
index 99ef944c621df5e00f1f440c05fe5e8938938415..44afae0a69ce75a5fada79d48acae246db1dfdb0 100644 (file)
@@ -80,44 +80,6 @@ static struct mfd_cell rc5t583_subdevs[] = {
        {.name = "rc5t583-key",      }
 };
 
-int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
-{
-       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
-       return regmap_write(rc5t583->regmap, reg, val);
-}
-
-int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
-{
-       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
-       unsigned int ival;
-       int ret;
-       ret = regmap_read(rc5t583->regmap, reg, &ival);
-       if (!ret)
-               *val = (uint8_t)ival;
-       return ret;
-}
-
-int rc5t583_set_bits(struct device *dev, unsigned int reg,
-                       unsigned int bit_mask)
-{
-       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
-       return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
-}
-
-int rc5t583_clear_bits(struct device *dev, unsigned int reg,
-                       unsigned int bit_mask)
-{
-       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
-       return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
-}
-
-int rc5t583_update(struct device *dev, unsigned int reg,
-               unsigned int val, unsigned int mask)
-{
-       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
-       return regmap_update_bits(rc5t583->regmap, reg, mask, val);
-}
-
 static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
        int id, int ext_pwr, int slots)
 {
@@ -197,6 +159,7 @@ int rc5t583_ext_power_req_config(struct device *dev, int ds_id,
                        ds_id, ext_pwr_req);
        return 0;
 }
+EXPORT_SYMBOL(rc5t583_ext_power_req_config);
 
 static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583,
        struct rc5t583_platform_data *pdata)
index b2d8e512d3cb002b6f3e809e47a12f01f96de588..2d6bedadca096d68eec4ce61332b57d6f08140a8 100644 (file)
@@ -30,7 +30,9 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
-#include <linux/i2c/twl.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/twl6040.h>
 
@@ -39,7 +41,7 @@
 int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
 {
        int ret;
-       u8 val = 0;
+       unsigned int val;
 
        mutex_lock(&twl6040->io_mutex);
        /* Vibra control registers from cache */
@@ -47,7 +49,7 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
                     reg == TWL6040_REG_VIBCTLR)) {
                val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
        } else {
-               ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+               ret = regmap_read(twl6040->regmap, reg, &val);
                if (ret < 0) {
                        mutex_unlock(&twl6040->io_mutex);
                        return ret;
@@ -64,7 +66,7 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
        int ret;
 
        mutex_lock(&twl6040->io_mutex);
-       ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+       ret = regmap_write(twl6040->regmap, reg, val);
        /* Cache the vibra control registers */
        if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
                twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
@@ -77,16 +79,9 @@ EXPORT_SYMBOL(twl6040_reg_write);
 int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
 {
        int ret;
-       u8 val;
 
        mutex_lock(&twl6040->io_mutex);
-       ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
-       if (ret)
-               goto out;
-
-       val |= mask;
-       ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
-out:
+       ret = regmap_update_bits(twl6040->regmap, reg, mask, mask);
        mutex_unlock(&twl6040->io_mutex);
        return ret;
 }
@@ -95,16 +90,9 @@ EXPORT_SYMBOL(twl6040_set_bits);
 int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
 {
        int ret;
-       u8 val;
 
        mutex_lock(&twl6040->io_mutex);
-       ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
-       if (ret)
-               goto out;
-
-       val &= ~mask;
-       ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
-out:
+       ret = regmap_update_bits(twl6040->regmap, reg, mask, 0);
        mutex_unlock(&twl6040->io_mutex);
        return ret;
 }
@@ -494,32 +482,58 @@ static struct resource twl6040_codec_rsrc[] = {
        },
 };
 
-static int __devinit twl6040_probe(struct platform_device *pdev)
+static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
 {
-       struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+       /* Register 0 is not readable */
+       if (!reg)
+               return false;
+       return true;
+}
+
+static struct regmap_config twl6040_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = TWL6040_REG_STATUS, /* 0x2e */
+
+       .readable_reg = twl6040_readable_reg,
+};
+
+static int __devinit twl6040_probe(struct i2c_client *client,
+                                    const struct i2c_device_id *id)
+{
+       struct twl6040_platform_data *pdata = client->dev.platform_data;
        struct twl6040 *twl6040;
        struct mfd_cell *cell = NULL;
        int ret, children = 0;
 
        if (!pdata) {
-               dev_err(&pdev->dev, "Platform data is missing\n");
+               dev_err(&client->dev, "Platform data is missing\n");
                return -EINVAL;
        }
 
        /* In order to operate correctly we need valid interrupt config */
-       if (!pdata->naudint_irq || !pdata->irq_base) {
-               dev_err(&pdev->dev, "Invalid IRQ configuration\n");
+       if (!client->irq || !pdata->irq_base) {
+               dev_err(&client->dev, "Invalid IRQ configuration\n");
                return -EINVAL;
        }
 
-       twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL);
-       if (!twl6040)
-               return -ENOMEM;
+       twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040),
+                              GFP_KERNEL);
+       if (!twl6040) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       twl6040->regmap = regmap_init_i2c(client, &twl6040_regmap_config);
+       if (IS_ERR(twl6040->regmap)) {
+               ret = PTR_ERR(twl6040->regmap);
+               goto err;
+       }
 
-       platform_set_drvdata(pdev, twl6040);
+       i2c_set_clientdata(client, twl6040);
 
-       twl6040->dev = &pdev->dev;
-       twl6040->irq = pdata->naudint_irq;
+       twl6040->dev = &client->dev;
+       twl6040->irq = client->irq;
        twl6040->irq_base = pdata->irq_base;
 
        mutex_init(&twl6040->mutex);
@@ -588,12 +602,12 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
        }
 
        if (children) {
-               ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells,
+               ret = mfd_add_devices(&client->dev, -1, twl6040->cells,
                                      children, NULL, 0);
                if (ret)
                        goto mfd_err;
        } else {
-               dev_err(&pdev->dev, "No platform data found for children\n");
+               dev_err(&client->dev, "No platform data found for children\n");
                ret = -ENODEV;
                goto mfd_err;
        }
@@ -608,14 +622,15 @@ gpio2_err:
        if (gpio_is_valid(twl6040->audpwron))
                gpio_free(twl6040->audpwron);
 gpio1_err:
-       platform_set_drvdata(pdev, NULL);
-       kfree(twl6040);
+       i2c_set_clientdata(client, NULL);
+       regmap_exit(twl6040->regmap);
+err:
        return ret;
 }
 
-static int __devexit twl6040_remove(struct platform_device *pdev)
+static int __devexit twl6040_remove(struct i2c_client *client)
 {
-       struct twl6040 *twl6040 = platform_get_drvdata(pdev);
+       struct twl6040 *twl6040 = i2c_get_clientdata(client);
 
        if (twl6040->power_count)
                twl6040_power(twl6040, 0);
@@ -626,23 +641,30 @@ static int __devexit twl6040_remove(struct platform_device *pdev)
        free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
        twl6040_irq_exit(twl6040);
 
-       mfd_remove_devices(&pdev->dev);
-       platform_set_drvdata(pdev, NULL);
-       kfree(twl6040);
+       mfd_remove_devices(&client->dev);
+       i2c_set_clientdata(client, NULL);
+       regmap_exit(twl6040->regmap);
 
        return 0;
 }
 
-static struct platform_driver twl6040_driver = {
+static const struct i2c_device_id twl6040_i2c_id[] = {
+       { "twl6040", 0, },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id);
+
+static struct i2c_driver twl6040_driver = {
+       .driver = {
+               .name = "twl6040",
+               .owner = THIS_MODULE,
+       },
        .probe          = twl6040_probe,
        .remove         = __devexit_p(twl6040_remove),
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "twl6040",
-       },
+       .id_table       = twl6040_i2c_id,
 };
 
-module_platform_driver(twl6040_driver);
+module_i2c_driver(twl6040_driver);
 
 MODULE_DESCRIPTION("TWL6040 MFD");
 MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
index 1c034b80d4082c4c3e328403749c03b8e83bdada..6673e578b3e9a00bce4a949cc19495359c66ebda 100644 (file)
@@ -500,12 +500,6 @@ static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf,
        return 1;
 }
 
-static int remote_settings_file_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static int remote_settings_file_close(struct inode *inode, struct file *file)
 {
        return 0;
@@ -600,7 +594,7 @@ static const struct file_operations r_heartbeat_fops = {
 };
 
 static const struct file_operations remote_settings_fops = {
-       .open =         remote_settings_file_open,
+       .open =         simple_open,
        .release =      remote_settings_file_close,
        .read =         remote_settings_file_read,
        .write =        remote_settings_file_write,
index 3f7ad83ed740bc0f008ca50ec8efdc125369d644..3aa9a969b373a4ffd102e35e2f5c804274675dab 100644 (file)
@@ -134,12 +134,17 @@ static int force_hwbrks;
 static int hwbreaks_ok;
 static int hw_break_val;
 static int hw_break_val2;
+static int cont_instead_of_sstep;
+static unsigned long cont_thread_id;
+static unsigned long sstep_thread_id;
 #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC)
 static int arch_needs_sstep_emulation = 1;
 #else
 static int arch_needs_sstep_emulation;
 #endif
+static unsigned long cont_addr;
 static unsigned long sstep_addr;
+static int restart_from_top_after_write;
 static int sstep_state;
 
 /* Storage for the registers, in GDB format. */
@@ -187,7 +192,8 @@ static int kgdbts_unreg_thread(void *ptr)
         */
        while (!final_ack)
                msleep_interruptible(1500);
-
+       /* Pause for any other threads to exit after final ack. */
+       msleep_interruptible(1000);
        if (configured)
                kgdb_unregister_io_module(&kgdbts_io_ops);
        configured = 0;
@@ -211,7 +217,7 @@ static unsigned long lookup_addr(char *arg)
        if (!strcmp(arg, "kgdbts_break_test"))
                addr = (unsigned long)kgdbts_break_test;
        else if (!strcmp(arg, "sys_open"))
-               addr = (unsigned long)sys_open;
+               addr = (unsigned long)do_sys_open;
        else if (!strcmp(arg, "do_fork"))
                addr = (unsigned long)do_fork;
        else if (!strcmp(arg, "hw_break_val"))
@@ -283,6 +289,16 @@ static void hw_break_val_write(void)
        hw_break_val++;
 }
 
+static int get_thread_id_continue(char *put_str, char *arg)
+{
+       char *ptr = &put_str[11];
+
+       if (put_str[1] != 'T' || put_str[2] != '0')
+               return 1;
+       kgdb_hex2long(&ptr, &cont_thread_id);
+       return 0;
+}
+
 static int check_and_rewind_pc(char *put_str, char *arg)
 {
        unsigned long addr = lookup_addr(arg);
@@ -299,13 +315,21 @@ static int check_and_rewind_pc(char *put_str, char *arg)
        if (addr + BREAK_INSTR_SIZE == ip)
                offset = -BREAK_INSTR_SIZE;
 #endif
-       if (strcmp(arg, "silent") && ip + offset != addr) {
+
+       if (arch_needs_sstep_emulation && sstep_addr &&
+           ip + offset == sstep_addr &&
+           ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) {
+               /* This is special case for emulated single step */
+               v2printk("Emul: rewind hit single step bp\n");
+               restart_from_top_after_write = 1;
+       } else if (strcmp(arg, "silent") && ip + offset != addr) {
                eprintk("kgdbts: BP mismatch %lx expected %lx\n",
                           ip + offset, addr);
                return 1;
        }
        /* Readjust the instruction pointer if needed */
        ip += offset;
+       cont_addr = ip;
 #ifdef GDB_ADJUSTS_BREAK_OFFSET
        instruction_pointer_set(&kgdbts_regs, ip);
 #endif
@@ -315,6 +339,8 @@ static int check_and_rewind_pc(char *put_str, char *arg)
 static int check_single_step(char *put_str, char *arg)
 {
        unsigned long addr = lookup_addr(arg);
+       static int matched_id;
+
        /*
         * From an arch indepent point of view the instruction pointer
         * should be on a different instruction
@@ -324,6 +350,29 @@ static int check_single_step(char *put_str, char *arg)
        gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
        v2printk("Singlestep stopped at IP: %lx\n",
                   instruction_pointer(&kgdbts_regs));
+
+       if (sstep_thread_id != cont_thread_id) {
+               /*
+                * Ensure we stopped in the same thread id as before, else the
+                * debugger should continue until the original thread that was
+                * single stepped is scheduled again, emulating gdb's behavior.
+                */
+               v2printk("ThrID does not match: %lx\n", cont_thread_id);
+               if (arch_needs_sstep_emulation) {
+                       if (matched_id &&
+                           instruction_pointer(&kgdbts_regs) != addr)
+                               goto continue_test;
+                       matched_id++;
+                       ts.idx -= 2;
+                       sstep_state = 0;
+                       return 0;
+               }
+               cont_instead_of_sstep = 1;
+               ts.idx -= 4;
+               return 0;
+       }
+continue_test:
+       matched_id = 0;
        if (instruction_pointer(&kgdbts_regs) == addr) {
                eprintk("kgdbts: SingleStep failed at %lx\n",
                           instruction_pointer(&kgdbts_regs));
@@ -365,10 +414,40 @@ static int got_break(char *put_str, char *arg)
        return 1;
 }
 
+static void get_cont_catch(char *arg)
+{
+       /* Always send detach because the test is completed at this point */
+       fill_get_buf("D");
+}
+
+static int put_cont_catch(char *put_str, char *arg)
+{
+       /* This is at the end of the test and we catch any and all input */
+       v2printk("kgdbts: cleanup task: %lx\n", sstep_thread_id);
+       ts.idx--;
+       return 0;
+}
+
+static int emul_reset(char *put_str, char *arg)
+{
+       if (strncmp(put_str, "$OK", 3))
+               return 1;
+       if (restart_from_top_after_write) {
+               restart_from_top_after_write = 0;
+               ts.idx = -1;
+       }
+       return 0;
+}
+
 static void emul_sstep_get(char *arg)
 {
        if (!arch_needs_sstep_emulation) {
-               fill_get_buf(arg);
+               if (cont_instead_of_sstep) {
+                       cont_instead_of_sstep = 0;
+                       fill_get_buf("c");
+               } else {
+                       fill_get_buf(arg);
+               }
                return;
        }
        switch (sstep_state) {
@@ -398,9 +477,11 @@ static void emul_sstep_get(char *arg)
 static int emul_sstep_put(char *put_str, char *arg)
 {
        if (!arch_needs_sstep_emulation) {
-               if (!strncmp(put_str+1, arg, 2))
-                       return 0;
-               return 1;
+               char *ptr = &put_str[11];
+               if (put_str[1] != 'T' || put_str[2] != '0')
+                       return 1;
+               kgdb_hex2long(&ptr, &sstep_thread_id);
+               return 0;
        }
        switch (sstep_state) {
        case 1:
@@ -411,8 +492,7 @@ static int emul_sstep_put(char *put_str, char *arg)
                v2printk("Stopped at IP: %lx\n",
                         instruction_pointer(&kgdbts_regs));
                /* Want to stop at IP + break instruction size by default */
-               sstep_addr = instruction_pointer(&kgdbts_regs) +
-                       BREAK_INSTR_SIZE;
+               sstep_addr = cont_addr + BREAK_INSTR_SIZE;
                break;
        case 2:
                if (strncmp(put_str, "$OK", 3)) {
@@ -424,6 +504,9 @@ static int emul_sstep_put(char *put_str, char *arg)
                if (strncmp(put_str, "$T0", 3)) {
                        eprintk("kgdbts: failed continue sstep\n");
                        return 1;
+               } else {
+                       char *ptr = &put_str[11];
+                       kgdb_hex2long(&ptr, &sstep_thread_id);
                }
                break;
        case 4:
@@ -502,10 +585,10 @@ static struct test_struct bad_read_test[] = {
 static struct test_struct singlestep_break_test[] = {
        { "?", "S0*" }, /* Clear break points */
        { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
-       { "c", "T0*", }, /* Continue */
+       { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
+       { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
        { "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
        { "write", "OK", write_regs }, /* Write registers */
-       { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
        { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
        { "g", "kgdbts_break_test", NULL, check_single_step },
        { "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
@@ -523,16 +606,16 @@ static struct test_struct singlestep_break_test[] = {
 static struct test_struct do_fork_test[] = {
        { "?", "S0*" }, /* Clear break points */
        { "do_fork", "OK", sw_break, }, /* set sw breakpoint */
-       { "c", "T0*", }, /* Continue */
-       { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
-       { "write", "OK", write_regs }, /* Write registers */
+       { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
        { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
+       { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
+       { "write", "OK", write_regs, emul_reset }, /* Write registers */
        { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
        { "g", "do_fork", NULL, check_single_step },
        { "do_fork", "OK", sw_break, }, /* set sw breakpoint */
        { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
        { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
-       { "", "" },
+       { "", "", get_cont_catch, put_cont_catch },
 };
 
 /* Test for hitting a breakpoint at sys_open for what ever the number
@@ -541,16 +624,16 @@ static struct test_struct do_fork_test[] = {
 static struct test_struct sys_open_test[] = {
        { "?", "S0*" }, /* Clear break points */
        { "sys_open", "OK", sw_break, }, /* set sw breakpoint */
-       { "c", "T0*", }, /* Continue */
-       { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
-       { "write", "OK", write_regs }, /* Write registers */
+       { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
        { "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
+       { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
+       { "write", "OK", write_regs, emul_reset }, /* Write registers */
        { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
        { "g", "sys_open", NULL, check_single_step },
        { "sys_open", "OK", sw_break, }, /* set sw breakpoint */
        { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
        { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
-       { "", "" },
+       { "", "", get_cont_catch, put_cont_catch },
 };
 
 /*
@@ -693,8 +776,8 @@ static int run_simple_test(int is_get_char, int chr)
        /* This callback is a put char which is when kgdb sends data to
         * this I/O module.
         */
-       if (ts.tst[ts.idx].get[0] == '\0' &&
-               ts.tst[ts.idx].put[0] == '\0') {
+       if (ts.tst[ts.idx].get[0] == '\0' && ts.tst[ts.idx].put[0] == '\0' &&
+           !ts.tst[ts.idx].get_handler) {
                eprintk("kgdbts: ERROR: beyond end of test on"
                           " '%s' line %i\n", ts.name, ts.idx);
                return 0;
@@ -907,6 +990,17 @@ static void kgdbts_run_tests(void)
        if (ptr)
                sstep_test = simple_strtol(ptr+1, NULL, 10);
 
+       /* All HW break point tests */
+       if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
+               hwbreaks_ok = 1;
+               v1printk("kgdbts:RUN hw breakpoint test\n");
+               run_breakpoint_test(1);
+               v1printk("kgdbts:RUN hw write breakpoint test\n");
+               run_hw_break_test(1);
+               v1printk("kgdbts:RUN access write breakpoint test\n");
+               run_hw_break_test(0);
+       }
+
        /* required internal KGDB tests */
        v1printk("kgdbts:RUN plant and detach test\n");
        run_plant_and_detach_test(0);
@@ -924,35 +1018,11 @@ static void kgdbts_run_tests(void)
 
        /* ===Optional tests=== */
 
-       /* All HW break point tests */
-       if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
-               hwbreaks_ok = 1;
-               v1printk("kgdbts:RUN hw breakpoint test\n");
-               run_breakpoint_test(1);
-               v1printk("kgdbts:RUN hw write breakpoint test\n");
-               run_hw_break_test(1);
-               v1printk("kgdbts:RUN access write breakpoint test\n");
-               run_hw_break_test(0);
-       }
-
        if (nmi_sleep) {
                v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep);
                run_nmi_sleep_test(nmi_sleep);
        }
 
-#ifdef CONFIG_DEBUG_RODATA
-       /* Until there is an api to write to read-only text segments, use
-        * HW breakpoints for the remainder of any tests, else print a
-        * failure message if hw breakpoints do not work.
-        */
-       if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) {
-               eprintk("kgdbts: HW breakpoints do not work,"
-                       "skipping remaining tests\n");
-               return;
-       }
-       force_hwbrks = 1;
-#endif /* CONFIG_DEBUG_RODATA */
-
        /* If the do_fork test is run it will be the last test that is
         * executed because a kernel thread will be spawned at the very
         * end to unregister the debug hooks.
index eed213a5c8cba8f53ae8bdba6e2f6525eedc9657..dabec556ebb87421f04372ecf1452b645629ab17 100644 (file)
@@ -873,7 +873,7 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
 {
        struct mmc_blk_data *md = mq->data;
        struct mmc_card *card = md->queue.card;
-       unsigned int from, nr, arg;
+       unsigned int from, nr, arg, trim_arg, erase_arg;
        int err = 0, type = MMC_BLK_SECDISCARD;
 
        if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
@@ -881,20 +881,26 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
                goto out;
        }
 
+       from = blk_rq_pos(req);
+       nr = blk_rq_sectors(req);
+
        /* The sanitize operation is supported at v4.5 only */
        if (mmc_can_sanitize(card)) {
-               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                               EXT_CSD_SANITIZE_START, 1, 0);
-               goto out;
+               erase_arg = MMC_ERASE_ARG;
+               trim_arg = MMC_TRIM_ARG;
+       } else {
+               erase_arg = MMC_SECURE_ERASE_ARG;
+               trim_arg = MMC_SECURE_TRIM1_ARG;
        }
 
-       from = blk_rq_pos(req);
-       nr = blk_rq_sectors(req);
-
-       if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
-               arg = MMC_SECURE_TRIM1_ARG;
-       else
-               arg = MMC_SECURE_ERASE_ARG;
+       if (mmc_erase_group_aligned(card, from, nr))
+               arg = erase_arg;
+       else if (mmc_can_trim(card))
+               arg = trim_arg;
+       else {
+               err = -EINVAL;
+               goto out;
+       }
 retry:
        if (card->quirks & MMC_QUIRK_INAND_CMD38) {
                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -904,25 +910,41 @@ retry:
                                 INAND_CMD38_ARG_SECERASE,
                                 0);
                if (err)
-                       goto out;
+                       goto out_retry;
        }
+
        err = mmc_erase(card, from, nr, arg);
-       if (!err && arg == MMC_SECURE_TRIM1_ARG) {
+       if (err == -EIO)
+               goto out_retry;
+       if (err)
+               goto out;
+
+       if (arg == MMC_SECURE_TRIM1_ARG) {
                if (card->quirks & MMC_QUIRK_INAND_CMD38) {
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                         INAND_CMD38_ARG_EXT_CSD,
                                         INAND_CMD38_ARG_SECTRIM2,
                                         0);
                        if (err)
-                               goto out;
+                               goto out_retry;
                }
+
                err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
+               if (err == -EIO)
+                       goto out_retry;
+               if (err)
+                       goto out;
        }
-out:
-       if (err == -EIO && !mmc_blk_reset(md, card->host, type))
+
+       if (mmc_can_sanitize(card))
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                                EXT_CSD_SANITIZE_START, 1, 0);
+out_retry:
+       if (err && !mmc_blk_reset(md, card->host, type))
                goto retry;
        if (!err)
                mmc_blk_reset_success(md, type);
+out:
        spin_lock_irq(&md->lock);
        __blk_end_request(req, err, blk_rq_bytes(req));
        spin_unlock_irq(&md->lock);
@@ -1623,24 +1645,6 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
        return ret;
 }
 
-static int
-mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
-{
-       int err;
-
-       mmc_claim_host(card->host);
-       err = mmc_set_blocklen(card, 512);
-       mmc_release_host(card->host);
-
-       if (err) {
-               pr_err("%s: unable to set block size to 512: %d\n",
-                       md->disk->disk_name, err);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static void mmc_blk_remove_req(struct mmc_blk_data *md)
 {
        struct mmc_card *card;
@@ -1768,7 +1772,6 @@ static const struct mmc_fixup blk_fixups[] =
 static int mmc_blk_probe(struct mmc_card *card)
 {
        struct mmc_blk_data *md, *part_md;
-       int err;
        char cap_str[10];
 
        /*
@@ -1781,10 +1784,6 @@ static int mmc_blk_probe(struct mmc_card *card)
        if (IS_ERR(md))
                return PTR_ERR(md);
 
-       err = mmc_blk_set_blksize(md, card);
-       if (err)
-               goto out;
-
        string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
                        cap_str, sizeof(cap_str));
        pr_info("%s: %s %s %s %s\n",
@@ -1809,7 +1808,7 @@ static int mmc_blk_probe(struct mmc_card *card)
  out:
        mmc_blk_remove_parts(card, md);
        mmc_blk_remove_req(md);
-       return err;
+       return 0;
 }
 
 static void mmc_blk_remove(struct mmc_card *card)
@@ -1825,7 +1824,7 @@ static void mmc_blk_remove(struct mmc_card *card)
 }
 
 #ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
+static int mmc_blk_suspend(struct mmc_card *card)
 {
        struct mmc_blk_data *part_md;
        struct mmc_blk_data *md = mmc_get_drvdata(card);
@@ -1845,8 +1844,6 @@ static int mmc_blk_resume(struct mmc_card *card)
        struct mmc_blk_data *md = mmc_get_drvdata(card);
 
        if (md) {
-               mmc_blk_set_blksize(md, card);
-
                /*
                 * Resume involves the card going into idle state,
                 * so current partition is always the main one.
index 2517547b4366a9bbdc6eea69ce1f1dc35ef09f08..996f8e36e23d8aa8bbf7c333fd6d6d56b8ec79ad 100644 (file)
@@ -139,7 +139,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,
 
        queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
        q->limits.max_discard_sectors = max_discard;
-       if (card->erased_byte == 0)
+       if (card->erased_byte == 0 && !mmc_can_discard(card))
                q->limits.discard_zeroes_data = 1;
        q->limits.discard_granularity = card->pref_erase << 9;
        /* granularity must not be greater than max. discard */
index 5d011a39dfff3b68a88813e202c76a4722fa3c57..c60cee92a2b2fe9bfd4a9b863dbc95d0e76e2eae 100644 (file)
@@ -122,14 +122,14 @@ static int mmc_bus_remove(struct device *dev)
        return 0;
 }
 
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+static int mmc_bus_suspend(struct device *dev)
 {
        struct mmc_driver *drv = to_mmc_driver(dev->driver);
        struct mmc_card *card = mmc_dev_to_card(dev);
        int ret = 0;
 
        if (dev->driver && drv->suspend)
-               ret = drv->suspend(card, state);
+               ret = drv->suspend(card);
        return ret;
 }
 
@@ -165,20 +165,14 @@ static int mmc_runtime_idle(struct device *dev)
        return pm_runtime_suspend(dev);
 }
 
+#endif /* !CONFIG_PM_RUNTIME */
+
 static const struct dev_pm_ops mmc_bus_pm_ops = {
-       .runtime_suspend        = mmc_runtime_suspend,
-       .runtime_resume         = mmc_runtime_resume,
-       .runtime_idle           = mmc_runtime_idle,
+       SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
+                       mmc_runtime_idle)
+       SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
 };
 
-#define MMC_PM_OPS_PTR (&mmc_bus_pm_ops)
-
-#else /* !CONFIG_PM_RUNTIME */
-
-#define MMC_PM_OPS_PTR NULL
-
-#endif /* !CONFIG_PM_RUNTIME */
-
 static struct bus_type mmc_bus_type = {
        .name           = "mmc",
        .dev_attrs      = mmc_dev_attrs,
@@ -186,9 +180,7 @@ static struct bus_type mmc_bus_type = {
        .uevent         = mmc_bus_uevent,
        .probe          = mmc_bus_probe,
        .remove         = mmc_bus_remove,
-       .suspend        = mmc_bus_suspend,
-       .resume         = mmc_bus_resume,
-       .pm             = MMC_PM_OPS_PTR,
+       .pm             = &mmc_bus_pm_ops,
 };
 
 int mmc_register_bus(void)
@@ -267,6 +259,15 @@ int mmc_add_card(struct mmc_card *card)
 {
        int ret;
        const char *type;
+       const char *uhs_bus_speed_mode = "";
+       static const char *const uhs_speeds[] = {
+               [UHS_SDR12_BUS_SPEED] = "SDR12 ",
+               [UHS_SDR25_BUS_SPEED] = "SDR25 ",
+               [UHS_SDR50_BUS_SPEED] = "SDR50 ",
+               [UHS_SDR104_BUS_SPEED] = "SDR104 ",
+               [UHS_DDR50_BUS_SPEED] = "DDR50 ",
+       };
+
 
        dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
 
@@ -296,6 +297,10 @@ int mmc_add_card(struct mmc_card *card)
                break;
        }
 
+       if (mmc_sd_card_uhs(card) &&
+               (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds)))
+               uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed];
+
        if (mmc_host_is_spi(card->host)) {
                pr_info("%s: new %s%s%s card on SPI\n",
                        mmc_hostname(card->host),
@@ -303,13 +308,13 @@ int mmc_add_card(struct mmc_card *card)
                        mmc_card_ddr_mode(card) ? "DDR " : "",
                        type);
        } else {
-               pr_info("%s: new %s%s%s%s card at address %04x\n",
+               pr_info("%s: new %s%s%s%s%s card at address %04x\n",
                        mmc_hostname(card->host),
                        mmc_card_uhs(card) ? "ultra high speed " :
                        (mmc_card_highspeed(card) ? "high speed " : ""),
                        (mmc_card_hs200(card) ? "HS200 " : ""),
                        mmc_card_ddr_mode(card) ? "DDR " : "",
-                       type, card->rca);
+                       uhs_bus_speed_mode, type, card->rca);
        }
 
 #ifdef CONFIG_DEBUG_FS
index 29de31e260dda56da18d0345f15a3886c6c1063a..2c14be73254c385d9a481c89db978c7c82c1b6e9 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
+#include <linux/mmc/cd-gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 14f262e9246d7a853ad2e1d78ce561e1c51d58c2..ba821fe70bca03dd3fbf17661e150ff737af242c 100644 (file)
@@ -527,10 +527,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
 
                if (data->flags & MMC_DATA_WRITE)
                        /*
-                        * The limit is really 250 ms, but that is
-                        * insufficient for some crappy cards.
+                        * The MMC spec "It is strongly recommended
+                        * for hosts to implement more than 500ms
+                        * timeout value even if the card indicates
+                        * the 250ms maximum busy length."  Even the
+                        * previous value of 300ms is known to be
+                        * insufficient for some cards.
                         */
-                       limit_us = 300000;
+                       limit_us = 3000000;
                else
                        limit_us = 100000;
 
@@ -1405,7 +1409,10 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
 {
        unsigned int erase_timeout;
 
-       if (card->ext_csd.erase_group_def & 1) {
+       if (arg == MMC_DISCARD_ARG ||
+           (arg == MMC_TRIM_ARG && card->ext_csd.rev >= 6)) {
+               erase_timeout = card->ext_csd.trim_timeout;
+       } else if (card->ext_csd.erase_group_def & 1) {
                /* High Capacity Erase Group Size uses HC timeouts */
                if (arg == MMC_TRIM_ARG)
                        erase_timeout = card->ext_csd.trim_timeout;
@@ -1677,8 +1684,6 @@ int mmc_can_trim(struct mmc_card *card)
 {
        if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)
                return 1;
-       if (mmc_can_discard(card))
-               return 1;
        return 0;
 }
 EXPORT_SYMBOL(mmc_can_trim);
@@ -1697,6 +1702,8 @@ EXPORT_SYMBOL(mmc_can_discard);
 
 int mmc_can_sanitize(struct mmc_card *card)
 {
+       if (!mmc_can_trim(card) && !mmc_can_erase(card))
+               return 0;
        if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE)
                return 1;
        return 0;
@@ -2231,6 +2238,7 @@ int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
                        mmc_card_is_removable(host))
                return err;
 
+       mmc_claim_host(host);
        if (card && mmc_card_mmc(card) &&
                        (card->ext_csd.cache_size > 0)) {
                enable = !!enable;
@@ -2248,6 +2256,7 @@ int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
                                card->ext_csd.cache_ctrl = enable;
                }
        }
+       mmc_release_host(host);
 
        return err;
 }
@@ -2265,49 +2274,32 @@ int mmc_suspend_host(struct mmc_host *host)
 
        cancel_delayed_work(&host->detect);
        mmc_flush_scheduled_work();
-       if (mmc_try_claim_host(host)) {
-               err = mmc_cache_ctrl(host, 0);
-               mmc_release_host(host);
-       } else {
-               err = -EBUSY;
-       }
 
+       err = mmc_cache_ctrl(host, 0);
        if (err)
                goto out;
 
        mmc_bus_get(host);
        if (host->bus_ops && !host->bus_dead) {
 
-               /*
-                * A long response time is not acceptable for device drivers
-                * when doing suspend. Prevent mmc_claim_host in the suspend
-                * sequence, to potentially wait "forever" by trying to
-                * pre-claim the host.
-                */
-               if (mmc_try_claim_host(host)) {
-                       if (host->bus_ops->suspend) {
-                               err = host->bus_ops->suspend(host);
-                       }
-                       mmc_release_host(host);
+               if (host->bus_ops->suspend)
+                       err = host->bus_ops->suspend(host);
 
-                       if (err == -ENOSYS || !host->bus_ops->resume) {
-                               /*
-                                * We simply "remove" the card in this case.
-                                * It will be redetected on resume.  (Calling
-                                * bus_ops->remove() with a claimed host can
-                                * deadlock.)
-                                */
-                               if (host->bus_ops->remove)
-                                       host->bus_ops->remove(host);
-                               mmc_claim_host(host);
-                               mmc_detach_bus(host);
-                               mmc_power_off(host);
-                               mmc_release_host(host);
-                               host->pm_flags = 0;
-                               err = 0;
-                       }
-               } else {
-                       err = -EBUSY;
+               if (err == -ENOSYS || !host->bus_ops->resume) {
+                       /*
+                        * We simply "remove" the card in this case.
+                        * It will be redetected on resume.  (Calling
+                        * bus_ops->remove() with a claimed host can
+                        * deadlock.)
+                        */
+                       if (host->bus_ops->remove)
+                               host->bus_ops->remove(host);
+                       mmc_claim_host(host);
+                       mmc_detach_bus(host);
+                       mmc_power_off(host);
+                       mmc_release_host(host);
+                       host->pm_flags = 0;
+                       err = 0;
                }
        }
        mmc_bus_put(host);
index 02914d609a91ab3d28577aed913702e119a695f6..54df5adc04137741ee7710d6ef5ee119add388d7 100644 (file)
@@ -695,6 +695,11 @@ static int mmc_select_powerclass(struct mmc_card *card,
                else if (host->ios.clock <= 200000000)
                        index = EXT_CSD_PWR_CL_200_195;
                break;
+       case MMC_VDD_27_28:
+       case MMC_VDD_28_29:
+       case MMC_VDD_29_30:
+       case MMC_VDD_30_31:
+       case MMC_VDD_31_32:
        case MMC_VDD_32_33:
        case MMC_VDD_33_34:
        case MMC_VDD_34_35:
@@ -1111,11 +1116,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
                                EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
                err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
-               if (err) {
-                       pr_err("%s: power class selection to bus width %d failed\n",
-                               mmc_hostname(card->host), 1 << bus_width);
-                       goto err;
-               }
+               if (err)
+                       pr_warning("%s: power class selection to bus width %d"
+                                  " failed\n", mmc_hostname(card->host),
+                                  1 << bus_width);
        }
 
        /*
@@ -1147,10 +1151,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                        err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
                                                    ext_csd);
                        if (err)
-                               pr_err("%s: power class selection to "
-                                      "bus width %d failed\n",
-                                      mmc_hostname(card->host),
-                                      1 << bus_width);
+                               pr_warning("%s: power class selection to "
+                                          "bus width %d failed\n",
+                                          mmc_hostname(card->host),
+                                          1 << bus_width);
 
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                         EXT_CSD_BUS_WIDTH,
@@ -1178,10 +1182,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                        err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
                                                    ext_csd);
                        if (err)
-                               pr_err("%s: power class selection to "
-                                      "bus width %d ddr %d failed\n",
-                                      mmc_hostname(card->host),
-                                      1 << bus_width, ddr);
+                               pr_warning("%s: power class selection to "
+                                          "bus width %d ddr %d failed\n",
+                                          mmc_hostname(card->host),
+                                          1 << bus_width, ddr);
 
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                         EXT_CSD_BUS_WIDTH,
index 40989e6bb53a588a8afa1e4281c1cd320999f117..236842ec955aa59f4af1ddc5fed8ab44a043dc89 100644 (file)
@@ -192,9 +192,15 @@ static int sdio_bus_remove(struct device *dev)
        return ret;
 }
 
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
+
+static int pm_no_operation(struct device *dev)
+{
+       return 0;
+}
 
 static const struct dev_pm_ops sdio_bus_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
        SET_RUNTIME_PM_OPS(
                pm_generic_runtime_suspend,
                pm_generic_runtime_resume,
@@ -204,11 +210,11 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
 
 #define SDIO_PM_OPS_PTR        (&sdio_bus_pm_ops)
 
-#else /* !CONFIG_PM_RUNTIME */
+#else /* !CONFIG_PM */
 
 #define SDIO_PM_OPS_PTR        NULL
 
-#endif /* !CONFIG_PM_RUNTIME */
+#endif /* !CONFIG_PM */
 
 static struct bus_type sdio_bus_type = {
        .name           = "sdio",
index 000b3ad0f5ca5d7e1bb1c5a0d81b2130c2279d73..787aba1682bb362efa7f06baf16370f4551f2074 100644 (file)
@@ -31,6 +31,7 @@
 # define ATMCI_MR_PDCFBYTE             (  1 << 13)     /* Force Byte Transfer */
 # define ATMCI_MR_PDCPADV              (  1 << 14)     /* Padding Value */
 # define ATMCI_MR_PDCMODE              (  1 << 15)     /* PDC-oriented Mode */
+# define ATMCI_MR_CLKODD(x)            ((x) << 16)     /* LSB of Clock Divider */
 #define ATMCI_DTOR                     0x0008  /* Data Timeout */
 # define ATMCI_DTOCYC(x)               ((x) <<  0)     /* Data Timeout Cycles */
 # define ATMCI_DTOMUL(x)               ((x) <<  4)     /* Data Timeout Multiplier */
index 9819dc09ce08d24f7bd2924fd35d786cc013b0ac..e94476beca181287b39c3af3a0b542a519bef353 100644 (file)
@@ -77,6 +77,7 @@ struct atmel_mci_caps {
        bool    has_cstor_reg;
        bool    has_highspeed;
        bool    has_rwproof;
+       bool    has_odd_clk_div;
 };
 
 struct atmel_mci_dma {
@@ -482,7 +483,14 @@ err:
 static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
                                        unsigned int ns)
 {
-       return (ns * (host->bus_hz / 1000000) + 999) / 1000;
+       /*
+        * It is easier here to use us instead of ns for the timeout,
+        * it prevents from overflows during calculation.
+        */
+       unsigned int us = DIV_ROUND_UP(ns, 1000);
+
+       /* Maximum clock frequency is host->bus_hz/2 */
+       return us * (DIV_ROUND_UP(host->bus_hz, 2000000));
 }
 
 static void atmci_set_timeout(struct atmel_mci *host,
@@ -1127,16 +1135,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                }
 
                /* Calculate clock divider */
-               clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
-               if (clkdiv > 255) {
-                       dev_warn(&mmc->class_dev,
-                               "clock %u too slow; using %lu\n",
-                               clock_min, host->bus_hz / (2 * 256));
-                       clkdiv = 255;
+               if (host->caps.has_odd_clk_div) {
+                       clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2;
+                       if (clkdiv > 511) {
+                               dev_warn(&mmc->class_dev,
+                                        "clock %u too slow; using %lu\n",
+                                        clock_min, host->bus_hz / (511 + 2));
+                               clkdiv = 511;
+                       }
+                       host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1)
+                                        | ATMCI_MR_CLKODD(clkdiv & 1);
+               } else {
+                       clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
+                       if (clkdiv > 255) {
+                               dev_warn(&mmc->class_dev,
+                                        "clock %u too slow; using %lu\n",
+                                        clock_min, host->bus_hz / (2 * 256));
+                               clkdiv = 255;
+                       }
+                       host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
                }
 
-               host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
-
                /*
                 * WRPROOF and RDPROOF prevent overruns/underruns by
                 * stopping the clock when the FIFO is full/empty.
@@ -2007,35 +2026,35 @@ static void __init atmci_get_cap(struct atmel_mci *host)
                        "version: 0x%x\n", version);
 
        host->caps.has_dma = 0;
-       host->caps.has_pdc = 0;
+       host->caps.has_pdc = 1;
        host->caps.has_cfg_reg = 0;
        host->caps.has_cstor_reg = 0;
        host->caps.has_highspeed = 0;
        host->caps.has_rwproof = 0;
+       host->caps.has_odd_clk_div = 0;
 
        /* keep only major version number */
        switch (version & 0xf00) {
-       case 0x100:
-       case 0x200:
-               host->caps.has_pdc = 1;
-               host->caps.has_rwproof = 1;
-               break;
-       case 0x300:
-       case 0x400:
        case 0x500:
+               host->caps.has_odd_clk_div = 1;
+       case 0x400:
+       case 0x300:
 #ifdef CONFIG_AT_HDMAC
                host->caps.has_dma = 1;
 #else
-               host->caps.has_dma = 0;
                dev_info(&host->pdev->dev,
                        "has dma capability but dma engine is not selected, then use pio\n");
 #endif
+               host->caps.has_pdc = 0;
                host->caps.has_cfg_reg = 1;
                host->caps.has_cstor_reg = 1;
                host->caps.has_highspeed = 1;
+       case 0x200:
                host->caps.has_rwproof = 1;
+       case 0x100:
                break;
        default:
+               host->caps.has_pdc = 0;
                dev_warn(&host->pdev->dev,
                                "Unmanaged mci version, set minimum capabilities\n");
                break;
index bf3c9b456aaf1080d6db5163eacefb3e7805787a..ab3fc46171079d4c8d07da35d5d00792032854d0 100644 (file)
@@ -526,8 +526,10 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
                return -ENODEV;
 
        sg_len = dw_mci_pre_dma_transfer(host, data, 0);
-       if (sg_len < 0)
+       if (sg_len < 0) {
+               host->dma_ops->stop(host);
                return sg_len;
+       }
 
        host->using_dma = 1;
 
@@ -1879,7 +1881,8 @@ static void dw_mci_init_dma(struct dw_mci *host)
        if (!host->dma_ops)
                goto no_dma;
 
-       if (host->dma_ops->init) {
+       if (host->dma_ops->init && host->dma_ops->start &&
+           host->dma_ops->stop && host->dma_ops->cleanup) {
                if (host->dma_ops->init(host)) {
                        dev_err(&host->dev, "%s: Unable to initialize "
                                "DMA Controller.\n", __func__);
index b0f2ef9881883df42f5513eb3f1f0479e6c83653..e3f5af96ab87f325942075ecba8705d137776c0c 100644 (file)
@@ -363,6 +363,7 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)
                goto out;
 
        dmaengine_submit(desc);
+       dma_async_issue_pending(host->dmach);
        return;
 
 out:
@@ -403,6 +404,7 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
                goto out;
 
        dmaengine_submit(desc);
+       dma_async_issue_pending(host->dmach);
        return;
 
 out:
@@ -531,6 +533,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
                goto out;
 
        dmaengine_submit(desc);
+       dma_async_issue_pending(host->dmach);
        return;
 out:
        dev_warn(mmc_dev(host->mmc),
index 47adb161d3adfd98e4c14279d04f4015d7283d2a..56d4499d43889e42a971fcfffb9bd0c334645294 100644 (file)
@@ -249,7 +249,7 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
         * the pbias cell programming support is still missing when
         * booting with Device tree
         */
-       if (of_have_populated_dt() && !vdd)
+       if (dev->of_node && !vdd)
                return 0;
 
        if (mmc_slot(host).before_set_reg)
@@ -1549,7 +1549,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                         * can't be allowed when booting with device
                         * tree.
                         */
-                       (!of_have_populated_dt())) {
+                       !host->dev->of_node) {
                                /*
                                 * The mmc_select_voltage fn of the core does
                                 * not seem to set the power_mode to
@@ -1741,7 +1741,7 @@ static const struct of_device_id omap_mmc_of_match[] = {
                .data = &omap4_reg_offset,
        },
        {},
-}
+};
 MODULE_DEVICE_TABLE(of, omap_mmc_of_match);
 
 static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
@@ -1785,7 +1785,7 @@ static inline struct omap_mmc_platform_data
 }
 #endif
 
-static int __init omap_hsmmc_probe(struct platform_device *pdev)
+static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 {
        struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
        struct mmc_host *mmc;
@@ -1818,8 +1818,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        if (res == NULL || irq < 0)
                return -ENXIO;
 
-       res->start += pdata->reg_offset;
-       res->end += pdata->reg_offset;
        res = request_mem_region(res->start, resource_size(res), pdev->name);
        if (res == NULL)
                return -EBUSY;
@@ -1843,7 +1841,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        host->dma_ch    = -1;
        host->irq       = irq;
        host->slot_id   = 0;
-       host->mapbase   = res->start;
+       host->mapbase   = res->start + pdata->reg_offset;
        host->base      = ioremap(host->mapbase, SZ_4K);
        host->power_mode = MMC_POWER_OFF;
        host->next_data.cookie = 1;
@@ -1875,8 +1873,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       omap_hsmmc_context_save(host);
-
        if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
                dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
                mmc->caps2 |= MMC_CAP2_NO_MULTI_READ;
@@ -1887,6 +1883,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY);
        pm_runtime_use_autosuspend(host->dev);
 
+       omap_hsmmc_context_save(host);
+
        if (cpu_is_omap2430()) {
                host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
                /*
@@ -2018,8 +2016,7 @@ err_reg:
 err_irq_cd_init:
        free_irq(host->irq, host);
 err_irq:
-       pm_runtime_mark_last_busy(host->dev);
-       pm_runtime_put_autosuspend(host->dev);
+       pm_runtime_put_sync(host->dev);
        pm_runtime_disable(host->dev);
        clk_put(host->fclk);
        if (host->got_dbclk) {
@@ -2037,35 +2034,33 @@ err:
        return ret;
 }
 
-static int omap_hsmmc_remove(struct platform_device *pdev)
+static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
 {
        struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
        struct resource *res;
 
-       if (host) {
-               pm_runtime_get_sync(host->dev);
-               mmc_remove_host(host->mmc);
-               if (host->use_reg)
-                       omap_hsmmc_reg_put(host);
-               if (host->pdata->cleanup)
-                       host->pdata->cleanup(&pdev->dev);
-               free_irq(host->irq, host);
-               if (mmc_slot(host).card_detect_irq)
-                       free_irq(mmc_slot(host).card_detect_irq, host);
-
-               pm_runtime_put_sync(host->dev);
-               pm_runtime_disable(host->dev);
-               clk_put(host->fclk);
-               if (host->got_dbclk) {
-                       clk_disable(host->dbclk);
-                       clk_put(host->dbclk);
-               }
+       pm_runtime_get_sync(host->dev);
+       mmc_remove_host(host->mmc);
+       if (host->use_reg)
+               omap_hsmmc_reg_put(host);
+       if (host->pdata->cleanup)
+               host->pdata->cleanup(&pdev->dev);
+       free_irq(host->irq, host);
+       if (mmc_slot(host).card_detect_irq)
+               free_irq(mmc_slot(host).card_detect_irq, host);
 
-               mmc_free_host(host->mmc);
-               iounmap(host->base);
-               omap_hsmmc_gpio_free(pdev->dev.platform_data);
+       pm_runtime_put_sync(host->dev);
+       pm_runtime_disable(host->dev);
+       clk_put(host->fclk);
+       if (host->got_dbclk) {
+               clk_disable(host->dbclk);
+               clk_put(host->dbclk);
        }
 
+       mmc_free_host(host->mmc);
+       iounmap(host->base);
+       omap_hsmmc_gpio_free(pdev->dev.platform_data);
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res)
                release_mem_region(res->start, resource_size(res));
@@ -2078,49 +2073,45 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 static int omap_hsmmc_suspend(struct device *dev)
 {
        int ret = 0;
-       struct platform_device *pdev = to_platform_device(dev);
-       struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
 
-       if (host && host->suspended)
+       if (!host)
                return 0;
 
-       if (host) {
-               pm_runtime_get_sync(host->dev);
-               host->suspended = 1;
-               if (host->pdata->suspend) {
-                       ret = host->pdata->suspend(&pdev->dev,
-                                                       host->slot_id);
-                       if (ret) {
-                               dev_dbg(mmc_dev(host->mmc),
-                                       "Unable to handle MMC board"
-                                       " level suspend\n");
-                               host->suspended = 0;
-                               return ret;
-                       }
-               }
-               ret = mmc_suspend_host(host->mmc);
+       if (host && host->suspended)
+               return 0;
 
+       pm_runtime_get_sync(host->dev);
+       host->suspended = 1;
+       if (host->pdata->suspend) {
+               ret = host->pdata->suspend(dev, host->slot_id);
                if (ret) {
+                       dev_dbg(dev, "Unable to handle MMC board"
+                                       " level suspend\n");
                        host->suspended = 0;
-                       if (host->pdata->resume) {
-                               ret = host->pdata->resume(&pdev->dev,
-                                                         host->slot_id);
-                               if (ret)
-                                       dev_dbg(mmc_dev(host->mmc),
-                                               "Unmask interrupt failed\n");
-                       }
-                       goto err;
+                       return ret;
                }
+       }
+       ret = mmc_suspend_host(host->mmc);
 
-               if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) {
-                       omap_hsmmc_disable_irq(host);
-                       OMAP_HSMMC_WRITE(host->base, HCTL,
-                               OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
+       if (ret) {
+               host->suspended = 0;
+               if (host->pdata->resume) {
+                       ret = host->pdata->resume(dev, host->slot_id);
+                       if (ret)
+                               dev_dbg(dev, "Unmask interrupt failed\n");
                }
-               if (host->got_dbclk)
-                       clk_disable(host->dbclk);
+               goto err;
+       }
 
+       if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) {
+               omap_hsmmc_disable_irq(host);
+               OMAP_HSMMC_WRITE(host->base, HCTL,
+                               OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
        }
+
+       if (host->got_dbclk)
+               clk_disable(host->dbclk);
 err:
        pm_runtime_put_sync(host->dev);
        return ret;
@@ -2130,38 +2121,37 @@ err:
 static int omap_hsmmc_resume(struct device *dev)
 {
        int ret = 0;
-       struct platform_device *pdev = to_platform_device(dev);
-       struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+       if (!host)
+               return 0;
 
        if (host && !host->suspended)
                return 0;
 
-       if (host) {
-               pm_runtime_get_sync(host->dev);
+       pm_runtime_get_sync(host->dev);
 
-               if (host->got_dbclk)
-                       clk_enable(host->dbclk);
+       if (host->got_dbclk)
+               clk_enable(host->dbclk);
 
-               if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
-                       omap_hsmmc_conf_bus_power(host);
+       if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
+               omap_hsmmc_conf_bus_power(host);
 
-               if (host->pdata->resume) {
-                       ret = host->pdata->resume(&pdev->dev, host->slot_id);
-                       if (ret)
-                               dev_dbg(mmc_dev(host->mmc),
-                                       "Unmask interrupt failed\n");
-               }
+       if (host->pdata->resume) {
+               ret = host->pdata->resume(dev, host->slot_id);
+               if (ret)
+                       dev_dbg(dev, "Unmask interrupt failed\n");
+       }
 
-               omap_hsmmc_protect_card(host);
+       omap_hsmmc_protect_card(host);
 
-               /* Notify the core to resume the host */
-               ret = mmc_resume_host(host->mmc);
-               if (ret == 0)
-                       host->suspended = 0;
+       /* Notify the core to resume the host */
+       ret = mmc_resume_host(host->mmc);
+       if (ret == 0)
+               host->suspended = 0;
 
-               pm_runtime_mark_last_busy(host->dev);
-               pm_runtime_put_autosuspend(host->dev);
-       }
+       pm_runtime_mark_last_busy(host->dev);
+       pm_runtime_put_autosuspend(host->dev);
 
        return ret;
 
@@ -2178,7 +2168,7 @@ static int omap_hsmmc_runtime_suspend(struct device *dev)
 
        host = platform_get_drvdata(to_platform_device(dev));
        omap_hsmmc_context_save(host);
-       dev_dbg(mmc_dev(host->mmc), "disabled\n");
+       dev_dbg(dev, "disabled\n");
 
        return 0;
 }
@@ -2189,7 +2179,7 @@ static int omap_hsmmc_runtime_resume(struct device *dev)
 
        host = platform_get_drvdata(to_platform_device(dev));
        omap_hsmmc_context_restore(host);
-       dev_dbg(mmc_dev(host->mmc), "enabled\n");
+       dev_dbg(dev, "enabled\n");
 
        return 0;
 }
@@ -2202,7 +2192,8 @@ static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
 };
 
 static struct platform_driver omap_hsmmc_driver = {
-       .remove         = omap_hsmmc_remove,
+       .probe          = omap_hsmmc_probe,
+       .remove         = __devexit_p(omap_hsmmc_remove),
        .driver         = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
@@ -2211,21 +2202,7 @@ static struct platform_driver omap_hsmmc_driver = {
        },
 };
 
-static int __init omap_hsmmc_init(void)
-{
-       /* Register the MMC driver */
-       return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe);
-}
-
-static void __exit omap_hsmmc_cleanup(void)
-{
-       /* Unregister MMC driver */
-       platform_driver_unregister(&omap_hsmmc_driver);
-}
-
-module_init(omap_hsmmc_init);
-module_exit(omap_hsmmc_cleanup);
-
+module_platform_driver(omap_hsmmc_driver);
 MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRIVER_NAME);
index 46fd1fd1b605033b8f437a70da844f11f5e04226..177f697b5835529aa3a4079966229c751f7bc428 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/module.h>
 #include <linux/mmc/host.h>
 
 #include "sdhci-pltfm.h"
index 6193a0d7bde52b8cc29e52837179d90eed50faeb..8abdaf6697a8db6e0bf0949e9c54900cb2ac0889 100644 (file)
@@ -467,8 +467,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
        clk_prepare_enable(clk);
        pltfm_host->clk = clk;
 
-       if (!is_imx25_esdhc(imx_data))
-               host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+       host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
        if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
                /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
index fbbebe251e016cf8b24906aa6a0b4ad31f64cd40..69ef0beae104f3a83d4a36277b129e20ba5db207 100644 (file)
@@ -1418,8 +1418,6 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
 
        slots = chip->num_slots;        /* Quirk may have changed this */
 
-       pci_enable_msi(pdev);
-
        for (i = 0; i < slots; i++) {
                slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i);
                if (IS_ERR(slot)) {
@@ -1438,8 +1436,6 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
        return 0;
 
 free:
-       pci_disable_msi(pdev);
-
        pci_set_drvdata(pdev, NULL);
        kfree(chip);
 
@@ -1462,8 +1458,6 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
                for (i = 0; i < chip->num_slots; i++)
                        sdhci_pci_remove_slot(chip->slots[i]);
 
-               pci_disable_msi(pdev);
-
                pci_set_drvdata(pdev, NULL);
                kfree(chip);
        }
index b19e7d435f8d6d1561a60156dff038c7508e0e2e..55a164fcaa157ece64d9c2be581e5c7b46b71e9d 100644 (file)
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/mmc/host.h>
 
@@ -53,6 +57,18 @@ struct sdhci_s3c {
        struct clk              *clk_bus[MAX_BUS_CLK];
 };
 
+/**
+ * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data
+ * @sdhci_quirks: sdhci host specific quirks.
+ *
+ * Specifies platform specific configuration of sdhci controller.
+ * Note: A structure for driver specific platform data is used for future
+ * expansion of its usage.
+ */
+struct sdhci_s3c_drv_data {
+       unsigned int    sdhci_quirks;
+};
+
 static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
 {
        return sdhci_priv(host);
@@ -132,10 +148,10 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
                return UINT_MAX;
 
        /*
-        * Clock divider's step is different as 1 from that of host controller
-        * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL.
+        * If controller uses a non-standard clock division, find the best clock
+        * speed possible with selected clock source and skip the division.
         */
-       if (ourhost->pdata->clk_type) {
+       if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
                rate = clk_round_rate(clksrc, wanted);
                return wanted - rate;
        }
@@ -272,6 +288,8 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
 static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        struct sdhci_s3c *ourhost = to_s3c(host);
+       unsigned long timeout;
+       u16 clk = 0;
 
        /* don't bother if the clock is going off */
        if (clock == 0)
@@ -282,6 +300,25 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
        clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
 
        host->clock = clock;
+
+       clk = SDHCI_CLOCK_INT_EN;
+       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+       /* Wait max 20 ms */
+       timeout = 20;
+       while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+               & SDHCI_CLOCK_INT_STABLE)) {
+               if (timeout == 0) {
+                       printk(KERN_ERR "%s: Internal clock never "
+                               "stabilised.\n", mmc_hostname(host->mmc));
+                       return;
+               }
+               timeout--;
+               mdelay(1);
+       }
+
+       clk |= SDHCI_CLOCK_CARD_EN;
+       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 }
 
 /**
@@ -382,16 +419,24 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
        }
 }
 
+static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
+                       struct platform_device *pdev)
+{
+       return (struct sdhci_s3c_drv_data *)
+                       platform_get_device_id(pdev)->driver_data;
+}
+
 static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 {
-       struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
+       struct s3c_sdhci_platdata *pdata;
+       struct sdhci_s3c_drv_data *drv_data;
        struct device *dev = &pdev->dev;
        struct sdhci_host *host;
        struct sdhci_s3c *sc;
        struct resource *res;
        int ret, irq, ptr, clks;
 
-       if (!pdata) {
+       if (!pdev->dev.platform_data) {
                dev_err(dev, "no device data specified\n");
                return -ENOENT;
        }
@@ -402,18 +447,20 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
                return irq;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "no memory specified\n");
-               return -ENOENT;
-       }
-
        host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
        if (IS_ERR(host)) {
                dev_err(dev, "sdhci_alloc_host() failed\n");
                return PTR_ERR(host);
        }
 
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               ret = -ENOMEM;
+               goto err_io_clk;
+       }
+       memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
+
+       drv_data = sdhci_s3c_get_driver_data(pdev);
        sc = sdhci_priv(host);
 
        sc->host = host;
@@ -464,15 +511,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
                goto err_no_busclks;
        }
 
-       sc->ioarea = request_mem_region(res->start, resource_size(res),
-                                       mmc_hostname(host->mmc));
-       if (!sc->ioarea) {
-               dev_err(dev, "failed to reserve register area\n");
-               ret = -ENXIO;
-               goto err_req_regs;
-       }
-
-       host->ioaddr = ioremap_nocache(res->start, resource_size(res));
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       host->ioaddr = devm_request_and_ioremap(&pdev->dev, res);
        if (!host->ioaddr) {
                dev_err(dev, "failed to map registers\n");
                ret = -ENXIO;
@@ -491,6 +531,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        /* Setup quirks for the controller */
        host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
        host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
+       if (drv_data)
+               host->quirks |= drv_data->sdhci_quirks;
 
 #ifndef CONFIG_MMC_SDHCI_S3C_DMA
 
@@ -518,6 +560,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
                host->mmc->caps = MMC_CAP_NONREMOVABLE;
 
+       switch (pdata->max_width) {
+       case 8:
+               host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+       case 4:
+               host->mmc->caps |= MMC_CAP_4_BIT_DATA;
+               break;
+       }
+
        if (pdata->pm_caps)
                host->mmc->pm_caps |= pdata->pm_caps;
 
@@ -531,7 +581,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
         * If controller does not have internal clock divider,
         * we can use overriding functions instead of default.
         */
-       if (pdata->clk_type) {
+       if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
                sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
                sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
                sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
@@ -544,10 +594,17 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        if (pdata->host_caps2)
                host->mmc->caps2 |= pdata->host_caps2;
 
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_suspend_ignore_children(&pdev->dev, 1);
+
        ret = sdhci_add_host(host);
        if (ret) {
                dev_err(dev, "sdhci_add_host() failed\n");
-               goto err_add_host;
+               pm_runtime_forbid(&pdev->dev);
+               pm_runtime_get_noresume(&pdev->dev);
+               goto err_req_regs;
        }
 
        /* The following two methods of card detection might call
@@ -561,10 +618,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 
        return 0;
 
- err_add_host:
-       release_resource(sc->ioarea);
-       kfree(sc->ioarea);
-
  err_req_regs:
        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
@@ -601,6 +654,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
 
        sdhci_remove_host(host, 1);
 
+       pm_runtime_disable(&pdev->dev);
+
        for (ptr = 0; ptr < 3; ptr++) {
                if (sc->clk_bus[ptr]) {
                        clk_disable(sc->clk_bus[ptr]);
@@ -610,18 +665,13 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
        clk_disable(sc->clk_io);
        clk_put(sc->clk_io);
 
-       iounmap(host->ioaddr);
-       release_resource(sc->ioarea);
-       kfree(sc->ioarea);
-
        sdhci_free_host(host);
        platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
 
-#ifdef CONFIG_PM
-
+#ifdef CONFIG_PM_SLEEP
 static int sdhci_s3c_suspend(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
@@ -635,10 +685,29 @@ static int sdhci_s3c_resume(struct device *dev)
 
        return sdhci_resume_host(host);
 }
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int sdhci_s3c_runtime_suspend(struct device *dev)
+{
+       struct sdhci_host *host = dev_get_drvdata(dev);
+
+       return sdhci_runtime_suspend_host(host);
+}
 
+static int sdhci_s3c_runtime_resume(struct device *dev)
+{
+       struct sdhci_host *host = dev_get_drvdata(dev);
+
+       return sdhci_runtime_resume_host(host);
+}
+#endif
+
+#ifdef CONFIG_PM
 static const struct dev_pm_ops sdhci_s3c_pmops = {
-       .suspend        = sdhci_s3c_suspend,
-       .resume         = sdhci_s3c_resume,
+       SET_SYSTEM_SLEEP_PM_OPS(sdhci_s3c_suspend, sdhci_s3c_resume)
+       SET_RUNTIME_PM_OPS(sdhci_s3c_runtime_suspend, sdhci_s3c_runtime_resume,
+                          NULL)
 };
 
 #define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops)
@@ -647,9 +716,31 @@ static const struct dev_pm_ops sdhci_s3c_pmops = {
 #define SDHCI_S3C_PMOPS NULL
 #endif
 
+#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
+static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
+       .sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
+};
+#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
+#else
+#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)NULL)
+#endif
+
+static struct platform_device_id sdhci_s3c_driver_ids[] = {
+       {
+               .name           = "s3c-sdhci",
+               .driver_data    = (kernel_ulong_t)NULL,
+       }, {
+               .name           = "exynos4-sdhci",
+               .driver_data    = EXYNOS4_SDHCI_DRV_DATA,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);
+
 static struct platform_driver sdhci_s3c_driver = {
        .probe          = sdhci_s3c_probe,
        .remove         = __devexit_p(sdhci_s3c_remove),
+       .id_table       = sdhci_s3c_driver_ids,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "s3c-sdhci",
index 8262cadfdab77b82e5590da88ff0042479d3a697..ccefdebeff1458a6041f269c7494fc26cac0d8a3 100644 (file)
@@ -147,7 +147,7 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
        u32 present, irqs;
 
        if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
-           !mmc_card_is_removable(host->mmc))
+           (host->mmc->caps & MMC_CAP_NONREMOVABLE))
                return;
 
        present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
@@ -2782,8 +2782,9 @@ int sdhci_add_host(struct sdhci_host *host)
            mmc_card_is_removable(mmc))
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
-       /* UHS-I mode(s) supported by the host controller. */
-       if (host->version >= SDHCI_SPEC_300)
+       /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
+       if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+                      SDHCI_SUPPORT_DDR50))
                mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
 
        /* SDR104 supports also implies SDR50 support */
index aafaf0b6eb1c96bcf298307b180dca75a259b424..724b35e85a265f70faa11fe8f603931a687f04af 100644 (file)
@@ -454,7 +454,8 @@ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
                sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
        else
                sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
-                               ((fls(host->clk / clk) - 1) << 16));
+                               ((fls(DIV_ROUND_UP(host->clk,
+                                                  clk) - 1) - 1) << 16));
 
        sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
 }
@@ -1297,14 +1298,8 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
        spin_lock_init(&host->lock);
 
        mmc->ops = &sh_mmcif_ops;
-       mmc->f_max = host->clk;
-       /* close to 400KHz */
-       if (mmc->f_max < 51200000)
-               mmc->f_min = mmc->f_max / 128;
-       else if (mmc->f_max < 102400000)
-               mmc->f_min = mmc->f_max / 256;
-       else
-               mmc->f_min = mmc->f_max / 512;
+       mmc->f_max = host->clk / 2;
+       mmc->f_min = host->clk / 512;
        if (pd->ocr)
                mmc->ocr_avail = pd->ocr;
        mmc->caps = MMC_CAP_MMC_HIGHSPEED;
index 94eb05b1afdfd2bcab367a6e6fa6dbab0667dca9..58fc65f5c8176d130bef3795ccb5163328489be6 100644 (file)
@@ -106,16 +106,14 @@ static int mtdchar_open(struct inode *inode, struct file *file)
        }
 
        if (mtd->type == MTD_ABSENT) {
-               put_mtd_device(mtd);
                ret = -ENODEV;
-               goto out;
+               goto out1;
        }
 
        mtd_ino = iget_locked(mnt->mnt_sb, devnum);
        if (!mtd_ino) {
-               put_mtd_device(mtd);
                ret = -ENOMEM;
-               goto out;
+               goto out1;
        }
        if (mtd_ino->i_state & I_NEW) {
                mtd_ino->i_private = mtd;
@@ -127,23 +125,25 @@ static int mtdchar_open(struct inode *inode, struct file *file)
 
        /* You can't open it RW if it's not a writeable device */
        if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
-               iput(mtd_ino);
-               put_mtd_device(mtd);
                ret = -EACCES;
-               goto out;
+               goto out2;
        }
 
        mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
        if (!mfi) {
-               iput(mtd_ino);
-               put_mtd_device(mtd);
                ret = -ENOMEM;
-               goto out;
+               goto out2;
        }
        mfi->ino = mtd_ino;
        mfi->mtd = mtd;
        file->private_data = mfi;
+       mutex_unlock(&mtd_mutex);
+       return 0;
 
+out2:
+       iput(mtd_ino);
+out1:
+       put_mtd_device(mtd);
 out:
        mutex_unlock(&mtd_mutex);
        simple_release_fs(&mnt, &count);
index 75b1dde1635884986097786bab730e2264c01072..9ec51cec2e14a42de34d10d1eee0c44c17e78dde 100644 (file)
@@ -266,6 +266,7 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this,
        desc->callback          = dma_irq_callback;
        desc->callback_param    = this;
        dmaengine_submit(desc);
+       dma_async_issue_pending(get_dma_chan(this));
 
        /* Wait for the interrupt from the DMA block. */
        err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
index e2cdebf40840e4f3630e6a7bf9868ab46781ab74..61af9bb560ab6777cd90ea5125790f38ee6139a9 100644 (file)
@@ -386,19 +386,11 @@ out:
        return count;
 }
 
-static int default_open(struct inode *inode, struct file *file)
-{
-       if (inode->i_private)
-               file->private_data = inode->i_private;
-
-       return 0;
-}
-
 /* File operations for all UBI debugfs files */
 static const struct file_operations dfs_fops = {
        .read   = dfs_file_read,
        .write  = dfs_file_write,
-       .open   = default_open,
+       .open   = simple_open,
        .llseek = no_llseek,
        .owner  = THIS_MODULE,
 };
index 25197b698dd64efad9243bc6579f4808d6a93802..b8b4c7ba884f0c2ed9499e1ede4a20ad1df4f732 100644 (file)
@@ -89,16 +89,16 @@ static int __init arcrimi_probe(struct net_device *dev)
        BUGLVL(D_NORMAL) printk(VERSION);
        BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n");
 
-       BUGMSG(D_NORMAL, "Given: node %02Xh, shmem %lXh, irq %d\n",
+       BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n",
               dev->dev_addr[0], dev->mem_start, dev->irq);
 
        if (dev->mem_start <= 0 || dev->irq <= 0) {
-               BUGMSG(D_NORMAL, "No autoprobe for RIM I; you "
+               BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you "
                       "must specify the shmem and irq!\n");
                return -ENODEV;
        }
        if (dev->dev_addr[0] == 0) {
-               BUGMSG(D_NORMAL, "You need to specify your card's station "
+               BUGLVL(D_NORMAL) printk("You need to specify your card's station "
                       "ID!\n");
                return -ENODEV;
        }
@@ -109,7 +109,7 @@ static int __init arcrimi_probe(struct net_device *dev)
         * will be taken.
         */
        if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) {
-               BUGMSG(D_NORMAL, "Card memory already allocated\n");
+               BUGLVL(D_NORMAL) printk("Card memory already allocated\n");
                return -ENODEV;
        }
        return arcrimi_found(dev);
index 0c76186bb9e75aff0c3f7024780a8802d025285b..62d2409bb293c54de4173e8ef9452e35b6f172e2 100644 (file)
@@ -891,9 +891,15 @@ static void bond_do_fail_over_mac(struct bonding *bond,
 
        switch (bond->params.fail_over_mac) {
        case BOND_FOM_ACTIVE:
-               if (new_active)
+               if (new_active) {
                        memcpy(bond->dev->dev_addr,  new_active->dev->dev_addr,
                               new_active->dev->addr_len);
+                       write_unlock_bh(&bond->curr_slave_lock);
+                       read_unlock(&bond->lock);
+                       call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
+                       read_lock(&bond->lock);
+                       write_lock_bh(&bond->curr_slave_lock);
+               }
                break;
        case BOND_FOM_FOLLOW:
                /*
@@ -2028,6 +2034,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
        write_unlock_bh(&bond->lock);
        unblock_netpoll_tx();
 
+       if (bond->slave_cnt == 0)
+               call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
+
        bond_compute_features(bond);
        if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
            (old_features & NETIF_F_VLAN_CHALLENGED))
@@ -3001,7 +3010,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
                                           trans_start + delta_in_ticks)) ||
                            bond->curr_active_slave != slave) {
                                slave->link = BOND_LINK_UP;
-                               bond->current_arp_slave = NULL;
+                               if (bond->current_arp_slave) {
+                                       bond_set_slave_inactive_flags(
+                                               bond->current_arp_slave);
+                                       bond->current_arp_slave = NULL;
+                               }
 
                                pr_info("%s: link status definitely up for interface %s.\n",
                                        bond->dev->name, slave->dev->name);
@@ -3695,17 +3708,52 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
        read_unlock(&bond->lock);
 }
 
-static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms)
+static int bond_neigh_init(struct neighbour *n)
 {
-       struct bonding *bond = netdev_priv(dev);
+       struct bonding *bond = netdev_priv(n->dev);
        struct slave *slave = bond->first_slave;
+       const struct net_device_ops *slave_ops;
+       struct neigh_parms parms;
+       int ret;
+
+       if (!slave)
+               return 0;
+
+       slave_ops = slave->dev->netdev_ops;
+
+       if (!slave_ops->ndo_neigh_setup)
+               return 0;
+
+       parms.neigh_setup = NULL;
+       parms.neigh_cleanup = NULL;
+       ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
+       if (ret)
+               return ret;
+
+       /*
+        * Assign slave's neigh_cleanup to neighbour in case cleanup is called
+        * after the last slave has been detached.  Assumes that all slaves
+        * utilize the same neigh_cleanup (true at this writing as only user
+        * is ipoib).
+        */
+       n->parms->neigh_cleanup = parms.neigh_cleanup;
+
+       if (!parms.neigh_setup)
+               return 0;
+
+       return parms.neigh_setup(n);
+}
+
+/*
+ * The bonding ndo_neigh_setup is called at init time beofre any
+ * slave exists. So we must declare proxy setup function which will
+ * be used at run time to resolve the actual slave neigh param setup.
+ */
+static int bond_neigh_setup(struct net_device *dev,
+                           struct neigh_parms *parms)
+{
+       parms->neigh_setup   = bond_neigh_init;
 
-       if (slave) {
-               const struct net_device_ops *slave_ops
-                       = slave->dev->netdev_ops;
-               if (slave_ops->ndo_neigh_setup)
-                       return slave_ops->ndo_neigh_setup(slave->dev, parms);
-       }
        return 0;
 }
 
index 9a66e2a910ae21f586ff59439b8116fe891d4c95..9c1c8cd5223f4144f90d6eb034d7a2bfcf0ff429 100644 (file)
@@ -744,14 +744,14 @@ static void cfhsi_wake_up(struct work_struct *work)
                size_t fifo_occupancy = 0;
 
                /* Wakeup timeout */
-               dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
+               dev_dbg(&cfhsi->ndev->dev, "%s: Timeout.\n",
                        __func__);
 
                /* Check FIFO to check if modem has sent something. */
                WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
                                        &fifo_occupancy));
 
-               dev_err(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n",
+               dev_dbg(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n",
                                __func__, (unsigned) fifo_occupancy);
 
                /* Check if we misssed the interrupt. */
@@ -1210,7 +1210,7 @@ int cfhsi_probe(struct platform_device *pdev)
 
 static void cfhsi_shutdown(struct cfhsi *cfhsi)
 {
-       u8 *tx_buf, *rx_buf;
+       u8 *tx_buf, *rx_buf, *flip_buf;
 
        /* Stop TXing */
        netif_tx_stop_all_queues(cfhsi->ndev);
@@ -1234,7 +1234,7 @@ static void cfhsi_shutdown(struct cfhsi *cfhsi)
        /* Store bufferes: will be freed later. */
        tx_buf = cfhsi->tx_buf;
        rx_buf = cfhsi->rx_buf;
-
+       flip_buf = cfhsi->rx_flip_buf;
        /* Flush transmit queues. */
        cfhsi_abort_tx(cfhsi);
 
@@ -1247,6 +1247,7 @@ static void cfhsi_shutdown(struct cfhsi *cfhsi)
        /* Free buffers. */
        kfree(tx_buf);
        kfree(rx_buf);
+       kfree(flip_buf);
 }
 
 int cfhsi_remove(struct platform_device *pdev)
index 96391c36fa74c77a66b47add6cf188f069fcce0a..b71ce9bf0afb7297df000208492e420ff9bd58ad 100644 (file)
@@ -127,12 +127,6 @@ static inline void dev_debugfs_rem(struct cfspi *cfspi)
        debugfs_remove(cfspi->dbgfs_dir);
 }
 
-static int dbgfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t dbgfs_state(struct file *file, char __user *user_buf,
                           size_t count, loff_t *ppos)
 {
@@ -243,13 +237,13 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf,
 }
 
 static const struct file_operations dbgfs_state_fops = {
-       .open = dbgfs_open,
+       .open = simple_open,
        .read = dbgfs_state,
        .owner = THIS_MODULE
 };
 
 static const struct file_operations dbgfs_frame_fops = {
-       .open = dbgfs_open,
+       .open = simple_open,
        .read = dbgfs_frame,
        .owner = THIS_MODULE
 };
index 5234586dff15d32a4ac63dc42246a414ada41760..629c4ba5d49d95792717f75b3a8919543a60b5d0 100644 (file)
@@ -875,6 +875,7 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
                                            PCAN_USBPRO_INFO_FW,
                                            &fi, sizeof(fi));
                if (err) {
+                       kfree(usb_if);
                        dev_err(dev->netdev->dev.parent,
                                "unable to read %s firmware info (err %d)\n",
                                pcan_usb_pro.name, err);
@@ -885,6 +886,7 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
                                            PCAN_USBPRO_INFO_BL,
                                            &bi, sizeof(bi));
                if (err) {
+                       kfree(usb_if);
                        dev_err(dev->netdev->dev.parent,
                                "unable to read %s bootloader info (err %d)\n",
                                pcan_usb_pro.name, err);
index d5c6d92f1ee77b1df16d59faf4c18e6d5889c07c..442d91a2747b9d8136dd5809ec3d192fc8c1e04c 100644 (file)
@@ -107,14 +107,14 @@ static int dummy_dev_init(struct net_device *dev)
        return 0;
 }
 
-static void dummy_dev_free(struct net_device *dev)
+static void dummy_dev_uninit(struct net_device *dev)
 {
        free_percpu(dev->dstats);
-       free_netdev(dev);
 }
 
 static const struct net_device_ops dummy_netdev_ops = {
        .ndo_init               = dummy_dev_init,
+       .ndo_uninit             = dummy_dev_uninit,
        .ndo_start_xmit         = dummy_xmit,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = set_multicast_list,
@@ -128,7 +128,7 @@ static void dummy_setup(struct net_device *dev)
 
        /* Initialize the device structure. */
        dev->netdev_ops = &dummy_netdev_ops;
-       dev->destructor = dummy_dev_free;
+       dev->destructor = free_netdev;
 
        /* Fill in device structure with ethernet-generic values. */
        dev->tx_queue_len = 0;
index a59cf961a436be4fc151b62160f2ad3d17429491..f219d38acf580075f4a9c6b93b54bfdcddbd0865 100644 (file)
 #include <linux/if.h>
 #include <linux/if_arp.h>
 #include <linux/if_eql.h>
+#include <linux/pkt_sched.h>
 
 #include <asm/uaccess.h>
 
@@ -143,7 +144,7 @@ static void eql_timer(unsigned long param)
        equalizer_t *eql = (equalizer_t *) param;
        struct list_head *this, *tmp, *head;
 
-       spin_lock_bh(&eql->queue.lock);
+       spin_lock(&eql->queue.lock);
        head = &eql->queue.all_slaves;
        list_for_each_safe(this, tmp, head) {
                slave_t *slave = list_entry(this, slave_t, list);
@@ -157,7 +158,7 @@ static void eql_timer(unsigned long param)
                }
 
        }
-       spin_unlock_bh(&eql->queue.lock);
+       spin_unlock(&eql->queue.lock);
 
        eql->timer.expires = jiffies + EQL_DEFAULT_RESCHED_IVAL;
        add_timer(&eql->timer);
@@ -341,7 +342,7 @@ static netdev_tx_t eql_slave_xmit(struct sk_buff *skb, struct net_device *dev)
                struct net_device *slave_dev = slave->dev;
 
                skb->dev = slave_dev;
-               skb->priority = 1;
+               skb->priority = TC_PRIO_FILLER;
                slave->bytes_queued += skb->len;
                dev_queue_xmit(skb);
                dev->stats.tx_packets++;
index 40ac414365490b59ac1eacab9fbd11123af39f23..c926857e8205fd79226cc7c0f0a897d7cb65ab88 100644 (file)
@@ -2476,7 +2476,7 @@ static irqreturn_t atl1_intr(int irq, void *data)
                                        "pcie phy link down %x\n", status);
                        if (netif_running(adapter->netdev)) {   /* reset MAC */
                                iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-                               schedule_work(&adapter->pcie_dma_to_rst_task);
+                               schedule_work(&adapter->reset_dev_task);
                                return IRQ_HANDLED;
                        }
                }
@@ -2488,7 +2488,7 @@ static irqreturn_t atl1_intr(int irq, void *data)
                                        "pcie DMA r/w error (status = 0x%x)\n",
                                        status);
                        iowrite32(0, adapter->hw.hw_addr + REG_IMR);
-                       schedule_work(&adapter->pcie_dma_to_rst_task);
+                       schedule_work(&adapter->reset_dev_task);
                        return IRQ_HANDLED;
                }
 
@@ -2633,10 +2633,10 @@ static void atl1_down(struct atl1_adapter *adapter)
        atl1_clean_rx_ring(adapter);
 }
 
-static void atl1_tx_timeout_task(struct work_struct *work)
+static void atl1_reset_dev_task(struct work_struct *work)
 {
        struct atl1_adapter *adapter =
-               container_of(work, struct atl1_adapter, tx_timeout_task);
+               container_of(work, struct atl1_adapter, reset_dev_task);
        struct net_device *netdev = adapter->netdev;
 
        netif_device_detach(netdev);
@@ -3038,12 +3038,10 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
                    (unsigned long)adapter);
        adapter->phy_timer_pending = false;
 
-       INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+       INIT_WORK(&adapter->reset_dev_task, atl1_reset_dev_task);
 
        INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
 
-       INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
-
        err = register_netdev(netdev);
        if (err)
                goto err_common;
index 109d6da8be97c14927c2e7fa79fc1b1073f84bb6..e04bf4d71e4657618655ac94f89da96c5cef96fa 100644 (file)
@@ -758,9 +758,8 @@ struct atl1_adapter {
        u16 link_speed;
        u16 link_duplex;
        spinlock_t lock;
-       struct work_struct tx_timeout_task;
+       struct work_struct reset_dev_task;
        struct work_struct link_chg_task;
-       struct work_struct pcie_dma_to_rst_task;
 
        struct timer_list phy_config_timer;
        bool phy_timer_pending;
index 3cd8837236dc1de68727991cc399b6906e30d5c3..c9e9dc57986c0743b3f7800273303f536fa47fc6 100644 (file)
@@ -194,7 +194,7 @@ static void atlx_tx_timeout(struct net_device *netdev)
 {
        struct atlx_adapter *adapter = netdev_priv(netdev);
        /* Do the reset outside of interrupt context */
-       schedule_work(&adapter->tx_timeout_task);
+       schedule_work(&adapter->reset_dev_task);
 }
 
 /*
index e37161f19250c278c69459fc9a08b86661c13c9a..2c9ee552dffcccd5cb22fcfbbbc99dea7e309141 100644 (file)
@@ -1173,6 +1173,13 @@ enum {
 };
 
 
+struct bnx2x_prev_path_list {
+       u8 bus;
+       u8 slot;
+       u8 path;
+       struct list_head list;
+};
+
 struct bnx2x {
        /* Fields used in the tx and intr/napi performance paths
         * are grouped together in the beginning of the structure
index f1f3ca65667ac379a0cdc7c435f92be3b721f623..4b054812713a7b3f9968d4b82310c171a6f4fff6 100644 (file)
@@ -1721,6 +1721,29 @@ static void bnx2x_squeeze_objects(struct bnx2x *bp)
        } while (0)
 #endif
 
+bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err)
+{
+       /* build FW version dword */
+       u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) +
+                   (BCM_5710_FW_MINOR_VERSION << 8) +
+                   (BCM_5710_FW_REVISION_VERSION << 16) +
+                   (BCM_5710_FW_ENGINEERING_VERSION << 24);
+
+       /* read loaded FW from chip */
+       u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
+
+       DP(NETIF_MSG_IFUP, "loaded fw %x, my fw %x\n", loaded_fw, my_fw);
+
+       if (loaded_fw != my_fw) {
+               if (is_err)
+                       BNX2X_ERR("bnx2x with FW %x was already loaded, which mismatches my %x FW. aborting\n",
+                                 loaded_fw, my_fw);
+               return false;
+       }
+
+       return true;
+}
+
 /* must be called with rtnl_lock */
 int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 {
@@ -1815,23 +1838,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                }
                if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP &&
                    load_code != FW_MSG_CODE_DRV_LOAD_COMMON) {
-                       /* build FW version dword */
-                       u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) +
-                                       (BCM_5710_FW_MINOR_VERSION << 8) +
-                                       (BCM_5710_FW_REVISION_VERSION << 16) +
-                                       (BCM_5710_FW_ENGINEERING_VERSION << 24);
-
-                       /* read loaded FW from chip */
-                       u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
-
-                       DP(BNX2X_MSG_SP, "loaded fw %x, my fw %x",
-                          loaded_fw, my_fw);
-
                        /* abort nic load if version mismatch */
-                       if (my_fw != loaded_fw) {
-                               BNX2X_ERR("bnx2x with FW %x already loaded, "
-                                         "which mismatches my %x FW. aborting",
-                                         loaded_fw, my_fw);
+                       if (!bnx2x_test_firmware_version(bp, true)) {
                                rc = -EBUSY;
                                LOAD_ERROR_EXIT(bp, load_error2);
                        }
@@ -1866,7 +1874,6 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                 * bnx2x_periodic_task().
                 */
                smp_mb();
-               queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
        } else
                bp->port.pmf = 0;
 
index 8b163388659a63fa3fe8b056873065f02f679bdc..5c27454d2ec276c81e31cb09b7241b158db68441 100644 (file)
@@ -431,6 +431,9 @@ void bnx2x_panic_dump(struct bnx2x *bp);
 
 void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
 
+/* validate currect fw is loaded */
+bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err);
+
 /* dev_close main block */
 int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
 
index cd6dfa9eaa3aa24c122316c9e4d052ca93d6c47d..b9b2633234363485d7f86980ee4ed3e7abac0e09 100644 (file)
        (IRO[149].base + ((funcId) * IRO[149].m1))
 #define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
 #define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
-       (IRO[315].base + ((pfId) * IRO[315].m1))
-#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
        (IRO[316].base + ((pfId) * IRO[316].m1))
+#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+       (IRO[317].base + ((pfId) * IRO[317].m1))
 #define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
-       (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
+       (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
 #define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
-       (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
+       (IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
 #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
-       (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
+       (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
 #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
-       (IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
+       (IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
 #define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
-       (IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * IRO[307].m2))
+       (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
 #define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
-       (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
+       (IRO[314].base + ((pfId) * IRO[314].m1) + ((iscsiEqId) * IRO[314].m2))
 #define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
-       (IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
+       (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
 #define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
-       (IRO[314].base + ((pfId) * IRO[314].m1))
+       (IRO[315].base + ((pfId) * IRO[315].m1))
 #define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-       (IRO[306].base + ((pfId) * IRO[306].m1))
+       (IRO[307].base + ((pfId) * IRO[307].m1))
 #define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-       (IRO[305].base + ((pfId) * IRO[305].m1))
+       (IRO[306].base + ((pfId) * IRO[306].m1))
 #define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-       (IRO[304].base + ((pfId) * IRO[304].m1))
+       (IRO[305].base + ((pfId) * IRO[305].m1))
 #define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
        (IRO[151].base + ((funcId) * IRO[151].m1))
 #define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
 #define TSTORM_FUNC_EN_OFFSET(funcId) \
        (IRO[103].base + ((funcId) * IRO[103].m1))
 #define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
-       (IRO[271].base + ((pfId) * IRO[271].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
        (IRO[272].base + ((pfId) * IRO[272].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
+#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
        (IRO[273].base + ((pfId) * IRO[273].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
+#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
        (IRO[274].base + ((pfId) * IRO[274].m1))
+#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
+       (IRO[275].base + ((pfId) * IRO[275].m1))
 #define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-       (IRO[270].base + ((pfId) * IRO[270].m1))
+       (IRO[271].base + ((pfId) * IRO[271].m1))
 #define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-       (IRO[269].base + ((pfId) * IRO[269].m1))
+       (IRO[270].base + ((pfId) * IRO[270].m1))
 #define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-       (IRO[268].base + ((pfId) * IRO[268].m1))
+       (IRO[269].base + ((pfId) * IRO[269].m1))
 #define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
-       (IRO[267].base + ((pfId) * IRO[267].m1))
+       (IRO[268].base + ((pfId) * IRO[268].m1))
 #define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
-       (IRO[276].base + ((pfId) * IRO[276].m1))
+       (IRO[277].base + ((pfId) * IRO[277].m1))
 #define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
-       (IRO[263].base + ((pfId) * IRO[263].m1))
-#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
        (IRO[264].base + ((pfId) * IRO[264].m1))
-#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \
+#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
        (IRO[265].base + ((pfId) * IRO[265].m1))
-#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \
        (IRO[266].base + ((pfId) * IRO[266].m1))
+#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+       (IRO[267].base + ((pfId) * IRO[267].m1))
 #define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
        (IRO[202].base + ((pfId) * IRO[202].m1))
 #define TSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
        (IRO[105].base + ((funcId) * IRO[105].m1))
 #define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
-       (IRO[216].base + ((pfId) * IRO[216].m1))
+       (IRO[217].base + ((pfId) * IRO[217].m1))
 #define TSTORM_VF_TO_PF_OFFSET(funcId) \
        (IRO[104].base + ((funcId) * IRO[104].m1))
 #define USTORM_AGG_DATA_OFFSET (IRO[206].base)
 #define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
        (IRO[183].base + ((portId) * IRO[183].m1))
 #define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
-       (IRO[317].base + ((pfId) * IRO[317].m1))
+       (IRO[318].base + ((pfId) * IRO[318].m1))
 #define USTORM_FUNC_EN_OFFSET(funcId) \
        (IRO[178].base + ((funcId) * IRO[178].m1))
 #define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
-       (IRO[281].base + ((pfId) * IRO[281].m1))
-#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
        (IRO[282].base + ((pfId) * IRO[282].m1))
+#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+       (IRO[283].base + ((pfId) * IRO[283].m1))
 #define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
-       (IRO[286].base + ((pfId) * IRO[286].m1))
+       (IRO[287].base + ((pfId) * IRO[287].m1))
 #define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
-       (IRO[283].base + ((pfId) * IRO[283].m1))
+       (IRO[284].base + ((pfId) * IRO[284].m1))
 #define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-       (IRO[279].base + ((pfId) * IRO[279].m1))
+       (IRO[280].base + ((pfId) * IRO[280].m1))
 #define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-       (IRO[278].base + ((pfId) * IRO[278].m1))
+       (IRO[279].base + ((pfId) * IRO[279].m1))
 #define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-       (IRO[277].base + ((pfId) * IRO[277].m1))
+       (IRO[278].base + ((pfId) * IRO[278].m1))
 #define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
-       (IRO[280].base + ((pfId) * IRO[280].m1))
+       (IRO[281].base + ((pfId) * IRO[281].m1))
 #define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
-       (IRO[284].base + ((pfId) * IRO[284].m1))
-#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
        (IRO[285].base + ((pfId) * IRO[285].m1))
+#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+       (IRO[286].base + ((pfId) * IRO[286].m1))
 #define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
        (IRO[182].base + ((pfId) * IRO[182].m1))
 #define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
 #define XSTORM_FUNC_EN_OFFSET(funcId) \
        (IRO[47].base + ((funcId) * IRO[47].m1))
 #define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
-       (IRO[294].base + ((pfId) * IRO[294].m1))
+       (IRO[295].base + ((pfId) * IRO[295].m1))
 #define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
-       (IRO[297].base + ((pfId) * IRO[297].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
        (IRO[298].base + ((pfId) * IRO[298].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
        (IRO[299].base + ((pfId) * IRO[299].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
        (IRO[300].base + ((pfId) * IRO[300].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
        (IRO[301].base + ((pfId) * IRO[301].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
        (IRO[302].base + ((pfId) * IRO[302].m1))
-#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
        (IRO[303].base + ((pfId) * IRO[303].m1))
+#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
+       (IRO[304].base + ((pfId) * IRO[304].m1))
 #define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
-       (IRO[293].base + ((pfId) * IRO[293].m1))
+       (IRO[294].base + ((pfId) * IRO[294].m1))
 #define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
-       (IRO[292].base + ((pfId) * IRO[292].m1))
+       (IRO[293].base + ((pfId) * IRO[293].m1))
 #define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
-       (IRO[291].base + ((pfId) * IRO[291].m1))
+       (IRO[292].base + ((pfId) * IRO[292].m1))
 #define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
-       (IRO[296].base + ((pfId) * IRO[296].m1))
+       (IRO[297].base + ((pfId) * IRO[297].m1))
 #define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
-       (IRO[295].base + ((pfId) * IRO[295].m1))
+       (IRO[296].base + ((pfId) * IRO[296].m1))
 #define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
-       (IRO[290].base + ((pfId) * IRO[290].m1))
+       (IRO[291].base + ((pfId) * IRO[291].m1))
 #define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
-       (IRO[289].base + ((pfId) * IRO[289].m1))
+       (IRO[290].base + ((pfId) * IRO[290].m1))
 #define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
-       (IRO[288].base + ((pfId) * IRO[288].m1))
+       (IRO[289].base + ((pfId) * IRO[289].m1))
 #define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
-       (IRO[287].base + ((pfId) * IRO[287].m1))
+       (IRO[288].base + ((pfId) * IRO[288].m1))
 #define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
        (IRO[44].base + ((pfId) * IRO[44].m1))
 #define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
index 5d71b7d43237f807cb45d1cc1e764d5439451c35..dbff5915b81a3b998f41d1f9bed232421417791b 100644 (file)
@@ -1251,6 +1251,9 @@ struct drv_func_mb {
 
        #define DRV_MSG_CODE_LINK_STATUS_CHANGED        0x01000000
 
+       #define DRV_MSG_CODE_INITIATE_FLR               0x02000000
+       #define REQ_BC_VER_4_INITIATE_FLR               0x00070213
+
        #define BIOS_MSG_CODE_LIC_CHALLENGE             0xff010000
        #define BIOS_MSG_CODE_LIC_RESPONSE              0xff020000
        #define BIOS_MSG_CODE_VIRT_MAC_PRIM             0xff030000
index beb4cdbdb6e1a5f06b980c9fad75f41faf65a154..64392ec410a3898b3b4372523db4a19d3614b390 100644 (file)
@@ -35,7 +35,6 @@
 #define ETH_MAX_PACKET_SIZE            1500
 #define ETH_MAX_JUMBO_PACKET_SIZE      9600
 #define MDIO_ACCESS_TIMEOUT            1000
-#define BMAC_CONTROL_RX_ENABLE         2
 #define WC_LANE_MAX                    4
 #define I2C_SWITCH_WIDTH               2
 #define I2C_BSC0                       0
@@ -943,6 +942,12 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
        const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
                DCBX_E3B0_MAX_NUM_COS_PORT0;
 
+       if (pri >= max_num_of_cos) {
+               DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
+                  "parameter Illegal strict priority\n");
+           return -EINVAL;
+       }
+
        if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) {
                DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
                                   "parameter There can't be two COS's with "
@@ -950,12 +955,6 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
                return -EINVAL;
        }
 
-       if (pri > max_num_of_cos) {
-               DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
-                  "parameter Illegal strict priority\n");
-           return -EINVAL;
-       }
-
        sp_pri_to_cos[pri] = cos_entry;
        return 0;
 
@@ -1372,7 +1371,14 @@ static void bnx2x_update_pfc_xmac(struct link_params *params,
                pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN |
                        XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN |
                        XMAC_PFC_CTRL_HI_REG_RX_PFC_EN |
-                       XMAC_PFC_CTRL_HI_REG_TX_PFC_EN;
+                       XMAC_PFC_CTRL_HI_REG_TX_PFC_EN |
+                       XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON;
+               /* Write pause and PFC registers */
+               REG_WR(bp, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
+               REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
+               REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
+               pfc1_val &= ~XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON;
+
        }
 
        /* Write pause and PFC registers */
@@ -3649,6 +3655,33 @@ static void bnx2x_ext_phy_update_adv_fc(struct bnx2x_phy *phy,
        if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
                bnx2x_cl22_read(bp, phy, 0x4, &ld_pause);
                bnx2x_cl22_read(bp, phy, 0x5, &lp_pause);
+       } else if (CHIP_IS_E3(bp) &&
+               SINGLE_MEDIA_DIRECT(params)) {
+               u8 lane = bnx2x_get_warpcore_lane(phy, params);
+               u16 gp_status, gp_mask;
+               bnx2x_cl45_read(bp, phy,
+                               MDIO_AN_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_4,
+                               &gp_status);
+               gp_mask = (MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL |
+                          MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP) <<
+                       lane;
+               if ((gp_status & gp_mask) == gp_mask) {
+                       bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                                       MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+                       bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                                       MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+               } else {
+                       bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                                       MDIO_AN_REG_CL37_FC_LD, &ld_pause);
+                       bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                                       MDIO_AN_REG_CL37_FC_LP, &lp_pause);
+                       ld_pause = ((ld_pause &
+                                    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
+                                   << 3);
+                       lp_pause = ((lp_pause &
+                                    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
+                                   << 3);
+               }
        } else {
                bnx2x_cl45_read(bp, phy,
                                MDIO_AN_DEVAD,
@@ -3699,7 +3732,23 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        u16 val16 = 0, lane, bam37 = 0;
        struct bnx2x *bp = params->bp;
        DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
-
+       /* Set to default registers that may be overriden by 10G force */
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7);
+       bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+                        MDIO_WC_REG_PAR_DET_10G_CTRL, 0);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555);
+       bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+                        MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_RX66_CONTROL, 0x7415);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190);
        /* Disable Autoneg: re-enable it after adv is done. */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
                         MDIO_WC_REG_IEEE0BLK_MIICNTL, 0);
@@ -3945,13 +3994,13 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
 
        } else {
                misc1_val |= 0x9;
-               tap_val = ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
-                          (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
-                          (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
+               tap_val = ((0x0f << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+                          (0x2b << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+                          (0x02 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
                tx_driver_val =
-                     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+                     ((0x03 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
                       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
-                      (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+                      (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
        }
        bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
                         MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
@@ -4369,7 +4418,7 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                switch (serdes_net_if) {
                case PORT_HW_CFG_NET_SERDES_IF_KR:
                        /* Enable KR Auto Neg */
-                       if (params->loopback_mode == LOOPBACK_NONE)
+                       if (params->loopback_mode != LOOPBACK_EXT)
                                bnx2x_warpcore_enable_AN_KR(phy, params, vars);
                        else {
                                DP(NETIF_MSG_LINK, "Setting KR 10G-Force\n");
@@ -6167,12 +6216,14 @@ int bnx2x_set_led(struct link_params *params,
 
                tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
                if (params->phy[EXT_PHY1].type ==
-                         PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
-                       EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp & 0xfff1);
-               else {
-                       EMAC_WR(bp, EMAC_REG_EMAC_LED,
-                               (tmp | EMAC_LED_OVERRIDE));
-               }
+                       PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
+                       tmp &= ~(EMAC_LED_1000MB_OVERRIDE |
+                               EMAC_LED_100MB_OVERRIDE |
+                               EMAC_LED_10MB_OVERRIDE);
+               else
+                       tmp |= EMAC_LED_OVERRIDE;
+
+               EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp);
                break;
 
        case LED_MODE_OPER:
@@ -6227,10 +6278,15 @@ int bnx2x_set_led(struct link_params *params,
                                       hw_led_mode);
                } else if ((params->phy[EXT_PHY1].type ==
                            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) &&
-                          (mode != LED_MODE_OPER)) {
+                          (mode == LED_MODE_ON)) {
                        REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
                        tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
-                       EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp | 0x3);
+                       EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp |
+                               EMAC_LED_OVERRIDE | EMAC_LED_1000MB_OVERRIDE);
+                       /* Break here; otherwise, it'll disable the
+                        * intended override.
+                        */
+                       break;
                } else
                        REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
                               hw_led_mode);
@@ -6245,13 +6301,9 @@ int bnx2x_set_led(struct link_params *params,
                               LED_BLINK_RATE_VAL_E1X_E2);
                REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
                       port*4, 1);
-               if ((params->phy[EXT_PHY1].type !=
-                    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) &&
-                   (mode != LED_MODE_OPER)) {
-                       tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
-                       EMAC_WR(bp, EMAC_REG_EMAC_LED,
-                               (tmp & (~EMAC_LED_OVERRIDE)));
-               }
+               tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+               EMAC_WR(bp, EMAC_REG_EMAC_LED,
+                       (tmp & (~EMAC_LED_OVERRIDE)));
 
                if (CHIP_IS_E1(bp) &&
                    ((speed == SPEED_2500) ||
@@ -6844,6 +6896,12 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
                          SINGLE_MEDIA_DIRECT(params)) &&
                         (phy_vars[active_external_phy].fault_detected == 0));
 
+       /* Update the PFC configuration in case it was changed */
+       if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+               vars->link_status |= LINK_STATUS_PFC_ENABLED;
+       else
+               vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
+
        if (vars->link_up)
                rc = bnx2x_update_link_up(params, vars, link_10g_plus);
        else
@@ -8031,7 +8089,9 @@ static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
        netdev_err(bp->dev,  "Warning: Unqualified SFP+ module detected,"
                              " Port %d from %s part number %s\n",
                         params->port, vendor_name, vendor_pn);
-       phy->flags |= FLAGS_SFP_NOT_APPROVED;
+       if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
+           PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG)
+               phy->flags |= FLAGS_SFP_NOT_APPROVED;
        return -EINVAL;
 }
 
@@ -9091,6 +9151,12 @@ static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
                tmp2 &= 0xFFEF;
                bnx2x_cl45_write(bp, phy,
                        MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2);
+               bnx2x_cl45_read(bp, phy,
+                               MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
+                               &tmp2);
+               bnx2x_cl45_write(bp, phy,
+                                MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
+                                (tmp2 & 0x7fff));
        }
 
        return 0;
@@ -9271,12 +9337,11 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
                                 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
                                 ((1<<5) | (1<<2)));
        }
-       DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
-       bnx2x_8727_specific_func(phy, params, ENABLE_TX);
-       /* If transmitter is disabled, ignore false link up indication */
-       bnx2x_cl45_read(bp, phy,
-                       MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
-       if (val1 & (1<<15)) {
+
+       if (!(phy->flags & FLAGS_SFP_NOT_APPROVED)) {
+               DP(NETIF_MSG_LINK, "Enabling 8727 TX laser\n");
+               bnx2x_sfp_set_transmitter(params, phy, 1);
+       } else {
                DP(NETIF_MSG_LINK, "Tx is disabled\n");
                return 0;
        }
@@ -9370,8 +9435,7 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 
        if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
                bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
-               bnx2x_save_spirom_version(bp, port,
-                               ((fw_ver1 & 0xf000)>>5) | (fw_ver1 & 0x7f),
+               bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff,
                                phy->ver_addr);
        } else {
                /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
@@ -9794,6 +9858,15 @@ static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
                                other_shmem_base_addr));
 
        u32 shmem_base_path[2];
+
+       /* Work around for 84833 LED failure inside RESET status */
+       bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+               MDIO_AN_REG_8481_LEGACY_MII_CTRL,
+               MDIO_AN_REG_8481_MII_CTRL_FORCE_1G);
+       bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+               MDIO_AN_REG_8481_1G_100T_EXT_CTRL,
+               MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF);
+
        shmem_base_path[0] = params->shmem_base;
        shmem_base_path[1] = other_shmem_base_addr;
 
@@ -10104,7 +10177,7 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
        u8 port;
        u16 val16;
 
-       if (!(CHIP_IS_E1(bp)))
+       if (!(CHIP_IS_E1x(bp)))
                port = BP_PATH(bp);
        else
                port = params->port;
@@ -10131,7 +10204,7 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
        u16 val;
        u8 port;
 
-       if (!(CHIP_IS_E1(bp)))
+       if (!(CHIP_IS_E1x(bp)))
                port = BP_PATH(bp);
        else
                port = params->port;
@@ -12050,6 +12123,9 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 
        bnx2x_emac_init(params, vars);
 
+       if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+               vars->link_status |= LINK_STATUS_PFC_ENABLED;
+
        if (params->num_phys == 0) {
                DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
                return -EINVAL;
@@ -12129,10 +12205,10 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
         * Hold it as vars low
         */
         /* clear link led */
+       bnx2x_set_mdio_clk(bp, params->chip_id, port);
        bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
 
        if (reset_ext_phy) {
-               bnx2x_set_mdio_clk(bp, params->chip_id, port);
                for (phy_index = EXT_PHY1; phy_index < params->num_phys;
                      phy_index++) {
                        if (params->phy[phy_index].link_reset) {
index 7ba557a610da1ea27d301b38814c28f299e0c0b4..763535ee4832e3882a3ee62a6654eeac7d328ae6 100644 (file)
@@ -89,6 +89,8 @@
 #define PFC_BRB_FULL_LB_XON_THRESHOLD                          250
 
 #define MAXVAL(a, b) (((a) > (b)) ? (a) : (b))
+
+#define BMAC_CONTROL_RX_ENABLE         2
 /***********************************************************/
 /*                         Structs                         */
 /***********************************************************/
index f7f9aa807264f51d8faef59a1f7297fa509d1b4f..e077d25087273721c0994b1c44dd5a41cceab882 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/prefetch.h>
 #include <linux/zlib.h>
 #include <linux/io.h>
+#include <linux/semaphore.h>
 #include <linux/stringify.h>
 #include <linux/vmalloc.h>
 
@@ -211,6 +212,10 @@ static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
 
 MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl);
 
+/* Global resources for unloading a previously loaded device */
+#define BNX2X_PREV_WAIT_NEEDED 1
+static DEFINE_SEMAPHORE(bnx2x_prev_sem);
+static LIST_HEAD(bnx2x_prev_list);
 /****************************************************************************
 * General service functions
 ****************************************************************************/
@@ -8812,109 +8817,371 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
                bnx2x_undi_int_disable_e1h(bp);
 }
 
-static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
+static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
 {
-       u32 val;
+       u32 val, base_addr, offset, mask, reset_reg;
+       bool mac_stopped = false;
+       u8 port = BP_PORT(bp);
 
-       /* possibly another driver is trying to reset the chip */
-       bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
+       reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2);
 
-       /* check if doorbell queue is reset */
-       if (REG_RD(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET)
-           & MISC_REGISTERS_RESET_REG_1_RST_DORQ) {
+       if (!CHIP_IS_E3(bp)) {
+               val = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port * 4);
+               mask = MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port;
+               if ((mask & reset_reg) && val) {
+                       u32 wb_data[2];
+                       BNX2X_DEV_INFO("Disable bmac Rx\n");
+                       base_addr = BP_PORT(bp) ? NIG_REG_INGRESS_BMAC1_MEM
+                                               : NIG_REG_INGRESS_BMAC0_MEM;
+                       offset = CHIP_IS_E2(bp) ? BIGMAC2_REGISTER_BMAC_CONTROL
+                                               : BIGMAC_REGISTER_BMAC_CONTROL;
 
-               /*
-                * Check if it is the UNDI driver
+                       /*
+                        * use rd/wr since we cannot use dmae. This is safe
+                        * since MCP won't access the bus due to the request
+                        * to unload, and no function on the path can be
+                        * loaded at this time.
+                        */
+                       wb_data[0] = REG_RD(bp, base_addr + offset);
+                       wb_data[1] = REG_RD(bp, base_addr + offset + 0x4);
+                       wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
+                       REG_WR(bp, base_addr + offset, wb_data[0]);
+                       REG_WR(bp, base_addr + offset + 0x4, wb_data[1]);
+
+               }
+               BNX2X_DEV_INFO("Disable emac Rx\n");
+               REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0);
+
+               mac_stopped = true;
+       } else {
+               if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) {
+                       BNX2X_DEV_INFO("Disable xmac Rx\n");
+                       base_addr = BP_PORT(bp) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+                       val = REG_RD(bp, base_addr + XMAC_REG_PFC_CTRL_HI);
+                       REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,
+                              val & ~(1 << 1));
+                       REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,
+                              val | (1 << 1));
+                       REG_WR(bp, base_addr + XMAC_REG_CTRL, 0);
+                       mac_stopped = true;
+               }
+               mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;
+               if (mask & reset_reg) {
+                       BNX2X_DEV_INFO("Disable umac Rx\n");
+                       base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+                       REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0);
+                       mac_stopped = true;
+               }
+       }
+
+       if (mac_stopped)
+               msleep(20);
+
+}
+
+#define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4))
+#define BNX2X_PREV_UNDI_RCQ(val)       ((val) & 0xffff)
+#define BNX2X_PREV_UNDI_BD(val)                ((val) >> 16 & 0xffff)
+#define BNX2X_PREV_UNDI_PROD(rcq, bd)  ((bd) << 16 | (rcq))
+
+static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
+                                                u8 inc)
+{
+       u16 rcq, bd;
+       u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port));
+
+       rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc;
+       bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc;
+
+       tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd);
+       REG_WR(bp, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg);
+
+       BNX2X_DEV_INFO("UNDI producer [%d] rings bd -> 0x%04x, rcq -> 0x%04x\n",
+                      port, bd, rcq);
+}
+
+static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
+{
+       u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+       if (!rc) {
+               BNX2X_ERR("MCP response failure, aborting\n");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
+{
+       struct bnx2x_prev_path_list *tmp_list;
+       int rc = false;
+
+       if (down_trylock(&bnx2x_prev_sem))
+               return false;
+
+       list_for_each_entry(tmp_list, &bnx2x_prev_list, list) {
+               if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot &&
+                   bp->pdev->bus->number == tmp_list->bus &&
+                   BP_PATH(bp) == tmp_list->path) {
+                       rc = true;
+                       BNX2X_DEV_INFO("Path %d was already cleaned from previous drivers\n",
+                                      BP_PATH(bp));
+                       break;
+               }
+       }
+
+       up(&bnx2x_prev_sem);
+
+       return rc;
+}
+
+static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
+{
+       struct bnx2x_prev_path_list *tmp_list;
+       int rc;
+
+       tmp_list = (struct bnx2x_prev_path_list *)
+                   kmalloc(sizeof(struct bnx2x_prev_path_list), GFP_KERNEL);
+       if (!tmp_list) {
+               BNX2X_ERR("Failed to allocate 'bnx2x_prev_path_list'\n");
+               return -ENOMEM;
+       }
+
+       tmp_list->bus = bp->pdev->bus->number;
+       tmp_list->slot = PCI_SLOT(bp->pdev->devfn);
+       tmp_list->path = BP_PATH(bp);
+
+       rc = down_interruptible(&bnx2x_prev_sem);
+       if (rc) {
+               BNX2X_ERR("Received %d when tried to take lock\n", rc);
+               kfree(tmp_list);
+       } else {
+               BNX2X_DEV_INFO("Marked path [%d] - finished previous unload\n",
+                               BP_PATH(bp));
+               list_add(&tmp_list->list, &bnx2x_prev_list);
+               up(&bnx2x_prev_sem);
+       }
+
+       return rc;
+}
+
+static bool __devinit bnx2x_can_flr(struct bnx2x *bp)
+{
+       int pos;
+       u32 cap;
+       struct pci_dev *dev = bp->pdev;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return false;
+
+       pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap);
+       if (!(cap & PCI_EXP_DEVCAP_FLR))
+               return false;
+
+       return true;
+}
+
+static int __devinit bnx2x_do_flr(struct bnx2x *bp)
+{
+       int i, pos;
+       u16 status;
+       struct pci_dev *dev = bp->pdev;
+
+       /* probe the capability first */
+       if (bnx2x_can_flr(bp))
+               return -ENOTTY;
+
+       pos = pci_pcie_cap(dev);
+       if (!pos)
+               return -ENOTTY;
+
+       /* Wait for Transaction Pending bit clean */
+       for (i = 0; i < 4; i++) {
+               if (i)
+                       msleep((1 << (i - 1)) * 100);
+
+               pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+               if (!(status & PCI_EXP_DEVSTA_TRPND))
+                       goto clear;
+       }
+
+       dev_err(&dev->dev,
+               "transaction is not cleared; proceeding with reset anyway\n");
+
+clear:
+       if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) {
+               BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n",
+                         bp->common.bc_ver);
+               return -EINVAL;
+       }
+
+       bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0);
+
+       return 0;
+}
+
+static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
+{
+       int rc;
+
+       BNX2X_DEV_INFO("Uncommon unload Flow\n");
+
+       /* Test if previous unload process was already finished for this path */
+       if (bnx2x_prev_is_path_marked(bp))
+               return bnx2x_prev_mcp_done(bp);
+
+       /* If function has FLR capabilities, and existing FW version matches
+        * the one required, then FLR will be sufficient to clean any residue
+        * left by previous driver
+        */
+       if (bnx2x_test_firmware_version(bp, false) && bnx2x_can_flr(bp))
+               return bnx2x_do_flr(bp);
+
+       /* Close the MCP request, return failure*/
+       rc = bnx2x_prev_mcp_done(bp);
+       if (!rc)
+               rc = BNX2X_PREV_WAIT_NEEDED;
+
+       return rc;
+}
+
+static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
+{
+       u32 reset_reg, tmp_reg = 0, rc;
+       /* It is possible a previous function received 'common' answer,
+        * but hasn't loaded yet, therefore creating a scenario of
+        * multiple functions receiving 'common' on the same path.
+        */
+       BNX2X_DEV_INFO("Common unload Flow\n");
+
+       if (bnx2x_prev_is_path_marked(bp))
+               return bnx2x_prev_mcp_done(bp);
+
+       reset_reg = REG_RD(bp, MISC_REG_RESET_REG_1);
+
+       /* Reset should be performed after BRB is emptied */
+       if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
+               u32 timer_count = 1000;
+               bool prev_undi = false;
+
+               /* Close the MAC Rx to prevent BRB from filling up */
+               bnx2x_prev_unload_close_mac(bp);
+
+               /* Check if the UNDI driver was previously loaded
                 * UNDI driver initializes CID offset for normal bell to 0x7
                 */
-               val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
-               if (val == 0x7) {
-                       u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-                       /* save our pf_num */
-                       int orig_pf_num = bp->pf_num;
-                       int port;
-                       u32 swap_en, swap_val, value;
-
-                       /* clear the UNDI indication */
-                       REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
-
-                       BNX2X_DEV_INFO("UNDI is active! reset device\n");
-
-                       /* try unload UNDI on port 0 */
-                       bp->pf_num = 0;
-                       bp->fw_seq =
-                             (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
-                               DRV_MSG_SEQ_NUMBER_MASK);
-                       reset_code = bnx2x_fw_command(bp, reset_code, 0);
-
-                       /* if UNDI is loaded on the other port */
-                       if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
-
-                               /* send "DONE" for previous unload */
-                               bnx2x_fw_command(bp,
-                                                DRV_MSG_CODE_UNLOAD_DONE, 0);
-
-                               /* unload UNDI on port 1 */
-                               bp->pf_num = 1;
-                               bp->fw_seq =
-                             (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
-                                       DRV_MSG_SEQ_NUMBER_MASK);
-                               reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-
-                               bnx2x_fw_command(bp, reset_code, 0);
+               reset_reg = REG_RD(bp, MISC_REG_RESET_REG_1);
+               if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_DORQ) {
+                       tmp_reg = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
+                       if (tmp_reg == 0x7) {
+                               BNX2X_DEV_INFO("UNDI previously loaded\n");
+                               prev_undi = true;
+                               /* clear the UNDI indication */
+                               REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
                        }
+               }
+               /* wait until BRB is empty */
+               tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);
+               while (timer_count) {
+                       u32 prev_brb = tmp_reg;
 
-                       bnx2x_undi_int_disable(bp);
-                       port = BP_PORT(bp);
-
-                       /* close input traffic and wait for it */
-                       /* Do not rcv packets to BRB */
-                       REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
-                                          NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
-                       /* Do not direct rcv packets that are not for MCP to
-                        * the BRB */
-                       REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
-                                          NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
-                       /* clear AEU */
-                       REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
-                                          MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
-                       msleep(10);
-
-                       /* save NIG port swap info */
-                       swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
-                       swap_en = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-                       /* reset device */
-                       REG_WR(bp,
-                              GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
-                              0xd3ffffff);
-
-                       value = 0x1400;
-                       if (CHIP_IS_E3(bp)) {
-                               value |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
-                               value |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
-                       }
+                       tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);
+                       if (!tmp_reg)
+                               break;
 
-                       REG_WR(bp,
-                              GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-                              value);
+                       BNX2X_DEV_INFO("BRB still has 0x%08x\n", tmp_reg);
 
-                       /* take the NIG out of reset and restore swap values */
-                       REG_WR(bp,
-                              GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
-                              MISC_REGISTERS_RESET_REG_1_RST_NIG);
-                       REG_WR(bp, NIG_REG_PORT_SWAP, swap_val);
-                       REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en);
+                       /* reset timer as long as BRB actually gets emptied */
+                       if (prev_brb > tmp_reg)
+                               timer_count = 1000;
+                       else
+                               timer_count--;
 
-                       /* send unload done to the MCP */
-                       bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+                       /* If UNDI resides in memory, manually increment it */
+                       if (prev_undi)
+                               bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
 
-                       /* restore our func and fw_seq */
-                       bp->pf_num = orig_pf_num;
+                       udelay(10);
                }
+
+               if (!timer_count)
+                       BNX2X_ERR("Failed to empty BRB, hope for the best\n");
+
        }
 
-       /* now it's safe to release the lock */
-       bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
+       /* No packets are in the pipeline, path is ready for reset */
+       bnx2x_reset_common(bp);
+
+       rc = bnx2x_prev_mark_path(bp);
+       if (rc) {
+               bnx2x_prev_mcp_done(bp);
+               return rc;
+       }
+
+       return bnx2x_prev_mcp_done(bp);
+}
+
+static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
+{
+       int time_counter = 10;
+       u32 rc, fw, hw_lock_reg, hw_lock_val;
+       BNX2X_DEV_INFO("Entering Previous Unload Flow\n");
+
+       /* Release previously held locks */
+       hw_lock_reg = (BP_FUNC(bp) <= 5) ?
+                     (MISC_REG_DRIVER_CONTROL_1 + BP_FUNC(bp) * 8) :
+                     (MISC_REG_DRIVER_CONTROL_7 + (BP_FUNC(bp) - 6) * 8);
+
+       hw_lock_val = (REG_RD(bp, hw_lock_reg));
+       if (hw_lock_val) {
+               if (hw_lock_val & HW_LOCK_RESOURCE_NVRAM) {
+                       BNX2X_DEV_INFO("Release Previously held NVRAM lock\n");
+                       REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB,
+                              (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << BP_PORT(bp)));
+               }
+
+               BNX2X_DEV_INFO("Release Previously held hw lock\n");
+               REG_WR(bp, hw_lock_reg, 0xffffffff);
+       } else
+               BNX2X_DEV_INFO("No need to release hw/nvram locks\n");
+
+       if (MCPR_ACCESS_LOCK_LOCK & REG_RD(bp, MCP_REG_MCPR_ACCESS_LOCK)) {
+               BNX2X_DEV_INFO("Release previously held alr\n");
+               REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, 0);
+       }
+
+
+       do {
+               /* Lock MCP using an unload request */
+               fw = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS, 0);
+               if (!fw) {
+                       BNX2X_ERR("MCP response failure, aborting\n");
+                       rc = -EBUSY;
+                       break;
+               }
+
+               if (fw == FW_MSG_CODE_DRV_UNLOAD_COMMON) {
+                       rc = bnx2x_prev_unload_common(bp);
+                       break;
+               }
+
+               /* non-common reply from MCP night require looping */
+               rc = bnx2x_prev_unload_uncommon(bp);
+               if (rc != BNX2X_PREV_WAIT_NEEDED)
+                       break;
+
+               msleep(20);
+       } while (--time_counter);
+
+       if (!time_counter || rc) {
+               BNX2X_ERR("Failed unloading previous driver, aborting\n");
+               rc = -EBUSY;
+       }
+
+       BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc);
+
+       return rc;
 }
 
 static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
@@ -10100,8 +10367,16 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
        func = BP_FUNC(bp);
 
        /* need to reset chip if undi was active */
-       if (!BP_NOMCP(bp))
-               bnx2x_undi_unload(bp);
+       if (!BP_NOMCP(bp)) {
+               /* init fw_seq */
+               bp->fw_seq =
+                       SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
+                                                       DRV_MSG_SEQ_NUMBER_MASK;
+               BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
+
+               bnx2x_prev_unload(bp);
+       }
+
 
        if (CHIP_REV_IS_FPGA(bp))
                dev_err(&bp->pdev->dev, "FPGA detected\n");
@@ -11431,9 +11706,18 @@ static int __init bnx2x_init(void)
 
 static void __exit bnx2x_cleanup(void)
 {
+       struct list_head *pos, *q;
        pci_unregister_driver(&bnx2x_pci_driver);
 
        destroy_workqueue(bnx2x_wq);
+
+       /* Free globablly allocated resources */
+       list_for_each_safe(pos, q, &bnx2x_prev_list) {
+               struct bnx2x_prev_path_list *tmp =
+                       list_entry(pos, struct bnx2x_prev_path_list, list);
+               list_del(pos);
+               kfree(tmp);
+       }
 }
 
 void bnx2x_notify_link_changed(struct bnx2x *bp)
index fd7fb45818491b7fc6c206bb7f1958cc9aa38183..c25803b9c0ca3e3e91ecb69cc53f92124e0101c7 100644 (file)
  * clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
 #define IGU_REG_WRITE_DONE_PENDING                              0x130480
 #define MCP_A_REG_MCPR_SCRATCH                                  0x3a0000
+#define MCP_REG_MCPR_ACCESS_LOCK                                0x8009c
 #define MCP_REG_MCPR_CPU_PROGRAM_COUNTER                        0x8501c
 #define MCP_REG_MCPR_GP_INPUTS                                  0x800c0
 #define MCP_REG_MCPR_GP_OENABLE                                         0x800c8
    [10] rst_dbg; [11] rst_misc_core; [12] rst_dbue (UART); [13]
    Pci_resetmdio_n; [14] rst_emac0_hard_core; [15] rst_emac1_hard_core; 16]
    rst_pxp_rq_rd_wr; 31:17] reserved */
+#define MISC_REG_RESET_REG_1                                    0xa580
 #define MISC_REG_RESET_REG_2                                    0xa590
 /* [RW 20] 20 bit GRC address where the scratch-pad of the MCP that is
    shared with the driver resides */
 #define XMAC_CTRL_REG_TX_EN                                     (0x1<<0)
 #define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN                                 (0x1<<18)
 #define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN                                 (0x1<<17)
+#define XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON                      (0x1<<1)
 #define XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN                     (0x1<<0)
 #define XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN                       (0x1<<3)
 #define XMAC_PFC_CTRL_HI_REG_RX_PFC_EN                          (0x1<<4)
 /* [RC 32] Parity register #0 read clear */
 #define XSEM_REG_XSEM_PRTY_STS_CLR_0                            0x280128
 #define XSEM_REG_XSEM_PRTY_STS_CLR_1                            0x280138
+#define MCPR_ACCESS_LOCK_LOCK                                   (1L<<31)
 #define MCPR_NVM_ACCESS_ENABLE_EN                               (1L<<0)
 #define MCPR_NVM_ACCESS_ENABLE_WR_EN                            (1L<<1)
 #define MCPR_NVM_ADDR_NVM_ADDR_VALUE                            (0xffffffL<<0)
 #define MISC_REGISTERS_GPIO_PORT_SHIFT                          4
 #define MISC_REGISTERS_GPIO_SET_POS                             8
 #define MISC_REGISTERS_RESET_REG_1_CLEAR                        0x588
+#define MISC_REGISTERS_RESET_REG_1_RST_BRB1                     (0x1<<0)
 #define MISC_REGISTERS_RESET_REG_1_RST_DORQ                     (0x1<<19)
 #define MISC_REGISTERS_RESET_REG_1_RST_HC                       (0x1<<29)
 #define MISC_REGISTERS_RESET_REG_1_RST_NIG                      (0x1<<7)
@@ -6816,10 +6821,13 @@ Theotherbitsarereservedandshouldbezero*/
 
 #define MDIO_AN_REG_8481_10GBASE_T_AN_CTRL     0x0020
 #define MDIO_AN_REG_8481_LEGACY_MII_CTRL       0xffe0
+#define MDIO_AN_REG_8481_MII_CTRL_FORCE_1G     0x40
 #define MDIO_AN_REG_8481_LEGACY_MII_STATUS     0xffe1
 #define MDIO_AN_REG_8481_LEGACY_AN_ADV         0xffe4
 #define MDIO_AN_REG_8481_LEGACY_AN_EXPANSION   0xffe6
 #define MDIO_AN_REG_8481_1000T_CTRL            0xffe9
+#define MDIO_AN_REG_8481_1G_100T_EXT_CTRL      0xfff0
+#define MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF       0x0008
 #define MDIO_AN_REG_8481_EXPANSION_REG_RD_RW   0xfff5
 #define MDIO_AN_REG_8481_EXPANSION_REG_ACCESS  0xfff7
 #define MDIO_AN_REG_8481_AUX_CTRL              0xfff8
@@ -6939,6 +6947,10 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_GP2_STATUS_GP_2_2                  0x81d2
 #define MDIO_WC_REG_GP2_STATUS_GP_2_3                  0x81d3
 #define MDIO_WC_REG_GP2_STATUS_GP_2_4                  0x81d4
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL 0x1000
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_AN_CMPL 0x0100
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP 0x0010
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_AN_CAP 0x1
 #define MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP               0x81EE
 #define MDIO_WC_REG_UC_INFO_B1_VERSION                 0x81F0
 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE           0x81F2
index 3f52fadee3edb15c1628099b06fd8786940219ef..5135733216252e2e05767515d1f0893c9715047d 100644 (file)
@@ -3847,7 +3847,7 @@ static bool bnx2x_credit_pool_get_entry(
                        continue;
 
                /* If we've got here we are going to find a free entry */
-               for (idx = vec * BNX2X_POOL_VEC_SIZE, i = 0;
+               for (idx = vec * BIT_VEC64_ELEM_SZ, i = 0;
                      i < BIT_VEC64_ELEM_SZ; idx++, i++)
 
                        if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
index 4e4bb38758680728cd2178610fef2724f5b6f662..ceeab8e852ef6a2cf86b682bb17bd0f17ab5ade8 100644 (file)
@@ -879,8 +879,13 @@ static inline unsigned int tg3_has_work(struct tg3_napi *tnapi)
                if (sblk->status & SD_STATUS_LINK_CHG)
                        work_exists = 1;
        }
-       /* check for RX/TX work to do */
-       if (sblk->idx[0].tx_consumer != tnapi->tx_cons ||
+
+       /* check for TX work to do */
+       if (sblk->idx[0].tx_consumer != tnapi->tx_cons)
+               work_exists = 1;
+
+       /* check for RX work to do */
+       if (tnapi->rx_rcb_prod_idx &&
            *(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
                work_exists = 1;
 
@@ -2778,7 +2783,9 @@ static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
-            (tp->phy_flags & TG3_PHYFLG_MII_SERDES)))
+            (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+            !tp->pci_fn))
                return;
 
        if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
@@ -6122,6 +6129,9 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
                        return work_done;
        }
 
+       if (!tnapi->rx_rcb_prod_idx)
+               return work_done;
+
        /* run RX thread, within the bounds set by NAPI.
         * All RX "locking" is done by ensuring outside
         * code synchronizes with tg3->napi.poll()
@@ -7565,6 +7575,12 @@ static int tg3_alloc_consistent(struct tg3 *tp)
                 */
                switch (i) {
                default:
+                       if (tg3_flag(tp, ENABLE_RSS)) {
+                               tnapi->rx_rcb_prod_idx = NULL;
+                               break;
+                       }
+                       /* Fall through */
+               case 1:
                        tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
                        break;
                case 2:
index 63bfdd10bd6d857b33cb52f4702919f1843fd094..abb6ce7c1b7ed2a67ee6b064377698df2efcb9c6 100644 (file)
@@ -1149,6 +1149,48 @@ release_tpsram:
        return ret;
 }
 
+/**
+ * t3_synchronize_rx - wait for current Rx processing on a port to complete
+ * @adap: the adapter
+ * @p: the port
+ *
+ * Ensures that current Rx processing on any of the queues associated with
+ * the given port completes before returning.  We do this by acquiring and
+ * releasing the locks of the response queues associated with the port.
+ */
+static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
+{
+       int i;
+
+       for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
+               struct sge_rspq *q = &adap->sge.qs[i].rspq;
+
+               spin_lock_irq(&q->lock);
+               spin_unlock_irq(&q->lock);
+       }
+}
+
+static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
+{
+       struct port_info *pi = netdev_priv(dev);
+       struct adapter *adapter = pi->adapter;
+
+       if (adapter->params.rev > 0) {
+               t3_set_vlan_accel(adapter, 1 << pi->port_id,
+                                 features & NETIF_F_HW_VLAN_RX);
+       } else {
+               /* single control for all ports */
+               unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_RX;
+
+               for_each_port(adapter, i)
+                       have_vlans |=
+                               adapter->port[i]->features & NETIF_F_HW_VLAN_RX;
+
+               t3_set_vlan_accel(adapter, 1, have_vlans);
+       }
+       t3_synchronize_rx(adapter, pi);
+}
+
 /**
  *     cxgb_up - enable the adapter
  *     @adapter: adapter being enabled
@@ -1161,7 +1203,7 @@ release_tpsram:
  */
 static int cxgb_up(struct adapter *adap)
 {
-       int err;
+       int i, err;
 
        if (!(adap->flags & FULL_INIT_DONE)) {
                err = t3_check_fw_version(adap);
@@ -1198,6 +1240,9 @@ static int cxgb_up(struct adapter *adap)
                if (err)
                        goto out;
 
+               for_each_port(adap, i)
+                       cxgb_vlan_mode(adap->port[i], adap->port[i]->features);
+
                setup_rss(adap);
                if (!(adap->flags & NAPI_INIT))
                        init_napi(adap);
@@ -2508,48 +2553,6 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p)
        return 0;
 }
 
-/**
- * t3_synchronize_rx - wait for current Rx processing on a port to complete
- * @adap: the adapter
- * @p: the port
- *
- * Ensures that current Rx processing on any of the queues associated with
- * the given port completes before returning.  We do this by acquiring and
- * releasing the locks of the response queues associated with the port.
- */
-static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
-{
-       int i;
-
-       for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
-               struct sge_rspq *q = &adap->sge.qs[i].rspq;
-
-               spin_lock_irq(&q->lock);
-               spin_unlock_irq(&q->lock);
-       }
-}
-
-static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
-{
-       struct port_info *pi = netdev_priv(dev);
-       struct adapter *adapter = pi->adapter;
-
-       if (adapter->params.rev > 0) {
-               t3_set_vlan_accel(adapter, 1 << pi->port_id,
-                                 features & NETIF_F_HW_VLAN_RX);
-       } else {
-               /* single control for all ports */
-               unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_RX;
-
-               for_each_port(adapter, i)
-                       have_vlans |=
-                               adapter->port[i]->features & NETIF_F_HW_VLAN_RX;
-
-               t3_set_vlan_accel(adapter, 1, have_vlans);
-       }
-       t3_synchronize_rx(adapter, pi);
-}
-
 static netdev_features_t cxgb_fix_features(struct net_device *dev,
        netdev_features_t features)
 {
@@ -3353,9 +3356,6 @@ static int __devinit init_one(struct pci_dev *pdev,
        err = sysfs_create_group(&adapter->port[0]->dev.kobj,
                                 &cxgb3_attr_group);
 
-       for_each_port(adapter, i)
-               cxgb_vlan_mode(adapter->port[i], adapter->port[i]->features);
-
        print_port_info(adapter, ai);
        return 0;
 
index 05ff076af06d92fe024199cba9f68f6e1847b299..b126b98065a9835dd882326bafafa6e80cb836f9 100644 (file)
@@ -2000,13 +2000,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
 /*
  * debugfs support
  */
-
-static int mem_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
                        loff_t *ppos)
 {
@@ -2050,7 +2043,7 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
 
 static const struct file_operations mem_debugfs_fops = {
        .owner   = THIS_MODULE,
-       .open    = mem_open,
+       .open    = simple_open,
        .read    = mem_read,
        .llseek  = default_llseek,
 };
index b2dc2c81a147f66581d1302f1b8eb1ee92346288..2e09edb9cdf84b3d1cc49d7dad5167a2ce3be75a 100644 (file)
@@ -1259,55 +1259,21 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
        int phy_addr;
        struct netdev_private *np = netdev_priv(dev);
-       struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru;
-
-       struct netdev_desc *desc;
-       int i;
+       struct mii_ioctl_data *miidata = if_mii(rq);
 
        phy_addr = np->phy_addr;
        switch (cmd) {
-       case SIOCDEVPRIVATE:
-               break;
-
-       case SIOCDEVPRIVATE + 1:
-               miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num);
+       case SIOCGMIIPHY:
+               miidata->phy_id = phy_addr;
                break;
-       case SIOCDEVPRIVATE + 2:
-               mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value);
+       case SIOCGMIIREG:
+               miidata->val_out = mii_read (dev, phy_addr, miidata->reg_num);
                break;
-       case SIOCDEVPRIVATE + 3:
-               break;
-       case SIOCDEVPRIVATE + 4:
-               break;
-       case SIOCDEVPRIVATE + 5:
-               netif_stop_queue (dev);
+       case SIOCSMIIREG:
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               mii_write (dev, phy_addr, miidata->reg_num, miidata->val_in);
                break;
-       case SIOCDEVPRIVATE + 6:
-               netif_wake_queue (dev);
-               break;
-       case SIOCDEVPRIVATE + 7:
-               printk
-                   ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n",
-                    netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx,
-                    np->old_rx);
-               break;
-       case SIOCDEVPRIVATE + 8:
-               printk("TX ring:\n");
-               for (i = 0; i < TX_RING_SIZE; i++) {
-                       desc = &np->tx_ring[i];
-                       printk
-                           ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
-                            i,
-                            (u32) (np->tx_ring_dma + i * sizeof (*desc)),
-                            (u32)le64_to_cpu(desc->next_desc),
-                            (u32)le64_to_cpu(desc->status),
-                            (u32)(le64_to_cpu(desc->fraginfo) >> 32),
-                            (u32)le64_to_cpu(desc->fraginfo));
-                       printk ("\n");
-               }
-               printk ("\n");
-               break;
-
        default:
                return -EOPNOTSUPP;
        }
index ba0adcafa55ad71c2dd63098796ce003a4cb6701..30c2da3de548f92ce0ebe794dc9c894af284c010 100644 (file)
@@ -365,13 +365,6 @@ struct ioctl_data {
        char *data;
 };
 
-struct mii_data {
-       __u16 reserved;
-       __u16 reg_num;
-       __u16 in_value;
-       __u16 out_value;
-};
-
 /* The Rx and Tx buffer descriptors. */
 struct netdev_desc {
        __le64 next_desc;
index 9eb815941df56a6b207d6211c3d09ae272224dd9..f7f0bf5d037b67db6476bdfb06daef60d52e4ad1 100644 (file)
@@ -356,13 +356,13 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev)
 
                if (prop)
                        tbiaddr = *prop;
-       }
 
-       if (tbiaddr == -1) {
-               err = -EBUSY;
-               goto err_free_irqs;
-       } else {
-               out_be32(tbipa, tbiaddr);
+               if (tbiaddr == -1) {
+                       err = -EBUSY;
+                       goto err_free_irqs;
+               } else {
+                       out_be32(tbipa, tbiaddr);
+               }
        }
 
        err = of_mdiobus_register(new_bus, np);
index 4e3cd2f8debb544d4d90cfdedd2e045db6d7cdc6..9ac14f8048512a66aef3a8fc2bba992d198393ef 100644 (file)
@@ -116,10 +116,10 @@ static struct ucc_geth_info ugeth_primary_info = {
        .maxGroupAddrInHash = 4,
        .maxIndAddrInHash = 4,
        .prel = 7,
-       .maxFrameLength = 1518,
+       .maxFrameLength = 1518+16, /* Add extra bytes for VLANs etc. */
        .minFrameLength = 64,
-       .maxD1Length = 1520,
-       .maxD2Length = 1520,
+       .maxD1Length = 1520+16, /* Add extra bytes for VLANs etc. */
+       .maxD2Length = 1520+16, /* Add extra bytes for VLANs etc. */
        .vlantype = 0x8100,
        .ecamptr = ((uint32_t) NULL),
        .eventRegMask = UCCE_OTHER,
@@ -3945,6 +3945,8 @@ static int ucc_geth_probe(struct platform_device* ofdev)
                }
 
        if (max_speed == SPEED_1000) {
+               unsigned int snums = qe_get_num_of_snums();
+
                /* configure muram FIFOs for gigabit operation */
                ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT;
                ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT;
@@ -3954,11 +3956,11 @@ static int ucc_geth_probe(struct platform_device* ofdev)
                ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT;
                ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4;
 
-               /* If QE's snum number is 46 which means we need to support
+               /* If QE's snum number is 46/76 which means we need to support
                 * 4 UECs at 1000Base-T simultaneously, we need to allocate
                 * more Threads to Rx.
                 */
-               if (qe_get_num_of_snums() == 46)
+               if ((snums == 76) || (snums == 46))
                        ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6;
                else
                        ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
index 2e395a2566b8d6221747f79828cbdfb70f72947c..f71b3e7b12defe7c92489ca967fbfe72819ab382 100644 (file)
@@ -877,7 +877,7 @@ struct ucc_geth_hardware_statistics {
 
 /* Driver definitions */
 #define TX_BD_RING_LEN                          0x10
-#define RX_BD_RING_LEN                          0x10
+#define RX_BD_RING_LEN                          0x20
 
 #define TX_RING_MOD_MASK(size)                  (size-1)
 #define RX_RING_MOD_MASK(size)                  (size-1)
index 3516e17a399d3137ccf0e2eea06318c0171aeba4..c9069a28832b0bfa39e4b118c7399a744ac0c8a2 100644 (file)
@@ -290,16 +290,18 @@ static void ehea_update_bcmc_registrations(void)
 
                                arr[i].adh = adapter->handle;
                                arr[i].port_id = port->logical_port_id;
-                               arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
-                                                 EHEA_BCMC_MULTICAST |
+                               arr[i].reg_type = EHEA_BCMC_MULTICAST |
                                                  EHEA_BCMC_UNTAGGED;
+                               if (mc_entry->macaddr == 0)
+                                       arr[i].reg_type |= EHEA_BCMC_SCOPE_ALL;
                                arr[i++].macaddr = mc_entry->macaddr;
 
                                arr[i].adh = adapter->handle;
                                arr[i].port_id = port->logical_port_id;
-                               arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
-                                                 EHEA_BCMC_MULTICAST |
+                               arr[i].reg_type = EHEA_BCMC_MULTICAST |
                                                  EHEA_BCMC_VLANID_ALL;
+                               if (mc_entry->macaddr == 0)
+                                       arr[i].reg_type |= EHEA_BCMC_SCOPE_ALL;
                                arr[i++].macaddr = mc_entry->macaddr;
                                num_registrations -= 2;
                        }
@@ -1838,8 +1840,9 @@ static u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
        u64 hret;
        u8 reg_type;
 
-       reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
-                | EHEA_BCMC_UNTAGGED;
+       reg_type = EHEA_BCMC_MULTICAST | EHEA_BCMC_UNTAGGED;
+       if (mc_mac_addr == 0)
+               reg_type |= EHEA_BCMC_SCOPE_ALL;
 
        hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
                                     port->logical_port_id,
@@ -1847,8 +1850,9 @@ static u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
        if (hret)
                goto out;
 
-       reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
-                | EHEA_BCMC_VLANID_ALL;
+       reg_type = EHEA_BCMC_MULTICAST | EHEA_BCMC_VLANID_ALL;
+       if (mc_mac_addr == 0)
+               reg_type |= EHEA_BCMC_SCOPE_ALL;
 
        hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
                                     port->logical_port_id,
@@ -1898,7 +1902,7 @@ static void ehea_allmulti(struct net_device *dev, int enable)
                                netdev_err(dev,
                                           "failed enabling IFF_ALLMULTI\n");
                }
-       } else
+       } else {
                if (!enable) {
                        /* Disable ALLMULTI */
                        hret = ehea_multicast_reg_helper(port, 0, H_DEREG_BCMC);
@@ -1908,6 +1912,7 @@ static void ehea_allmulti(struct net_device *dev, int enable)
                                netdev_err(dev,
                                           "failed disabling IFF_ALLMULTI\n");
                }
+       }
 }
 
 static void ehea_add_multicast_entry(struct ehea_port *port, u8 *mc_mac_addr)
@@ -1941,11 +1946,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
        struct netdev_hw_addr *ha;
        int ret;
 
-       if (port->promisc) {
-               ehea_promiscuous(dev, 1);
-               return;
-       }
-       ehea_promiscuous(dev, 0);
+       ehea_promiscuous(dev, !!(dev->flags & IFF_PROMISC));
 
        if (dev->flags & IFF_ALLMULTI) {
                ehea_allmulti(dev, 1);
@@ -2463,6 +2464,7 @@ static int ehea_down(struct net_device *dev)
                return 0;
 
        ehea_drop_multicast_list(dev);
+       ehea_allmulti(dev, 0);
        ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
 
        ehea_free_interrupts(dev);
@@ -3261,6 +3263,7 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
        struct ehea_adapter *adapter;
        const u64 *adapter_handle;
        int ret;
+       int i;
 
        if (!dev || !dev->dev.of_node) {
                pr_err("Invalid ibmebus device probed\n");
@@ -3314,17 +3317,9 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
        tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
                     (unsigned long)adapter);
 
-       ret = ibmebus_request_irq(adapter->neq->attr.ist1,
-                                 ehea_interrupt_neq, IRQF_DISABLED,
-                                 "ehea_neq", adapter);
-       if (ret) {
-               dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
-               goto out_kill_eq;
-       }
-
        ret = ehea_create_device_sysfs(dev);
        if (ret)
-               goto out_free_irq;
+               goto out_kill_eq;
 
        ret = ehea_setup_ports(adapter);
        if (ret) {
@@ -3332,15 +3327,28 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
                goto out_rem_dev_sysfs;
        }
 
+       ret = ibmebus_request_irq(adapter->neq->attr.ist1,
+                                 ehea_interrupt_neq, IRQF_DISABLED,
+                                 "ehea_neq", adapter);
+       if (ret) {
+               dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
+               goto out_shutdown_ports;
+       }
+
+
        ret = 0;
        goto out;
 
+out_shutdown_ports:
+       for (i = 0; i < EHEA_MAX_PORTS; i++)
+               if (adapter->port[i]) {
+                       ehea_shutdown_single_port(adapter->port[i]);
+                       adapter->port[i] = NULL;
+               }
+
 out_rem_dev_sysfs:
        ehea_remove_device_sysfs(dev);
 
-out_free_irq:
-       ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
-
 out_kill_eq:
        ehea_destroy_eq(adapter->neq);
 
index 52c456ec4d6cf811567f82f80477b4e32910ee9a..8364815c32ff63f04fd7942d2f240b980e156f2f 100644 (file)
@@ -450,7 +450,7 @@ u64 ehea_h_modify_ehea_port(const u64 adapter_handle, const u16 port_num,
                            void *cb_addr);
 
 #define H_REGBCMC_PN            EHEA_BMASK_IBM(48, 63)
-#define H_REGBCMC_REGTYPE       EHEA_BMASK_IBM(61, 63)
+#define H_REGBCMC_REGTYPE       EHEA_BMASK_IBM(60, 63)
 #define H_REGBCMC_MACADDR       EHEA_BMASK_IBM(16, 63)
 #define H_REGBCMC_VLANID        EHEA_BMASK_IBM(52, 63)
 
index 0e9aec8f69170c0dcbd46ef51dee46beff283ce6..4348b6fd44fac08e06666af2f581889d418ada7a 100644 (file)
@@ -164,6 +164,8 @@ static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
 static bool e1000_vlan_used(struct e1000_adapter *adapter);
 static void e1000_vlan_mode(struct net_device *netdev,
                            netdev_features_t features);
+static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
+                                    bool filter_on);
 static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
 static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
 static void e1000_restore_vlan(struct e1000_adapter *adapter);
@@ -215,7 +217,8 @@ MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
-static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
@@ -979,7 +982,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        adapter = netdev_priv(netdev);
        adapter->netdev = netdev;
        adapter->pdev = pdev;
-       adapter->msg_enable = (1 << debug) - 1;
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
        adapter->bars = bars;
        adapter->need_ioport = need_ioport;
 
@@ -1214,7 +1217,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        if (err)
                goto err_register;
 
-       e1000_vlan_mode(netdev, netdev->features);
+       e1000_vlan_filter_on_off(adapter, false);
 
        /* print bus type/speed/width info */
        e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
@@ -4770,6 +4773,22 @@ static bool e1000_vlan_used(struct e1000_adapter *adapter)
        return false;
 }
 
+static void __e1000_vlan_mode(struct e1000_adapter *adapter,
+                             netdev_features_t features)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 ctrl;
+
+       ctrl = er32(CTRL);
+       if (features & NETIF_F_HW_VLAN_RX) {
+               /* enable VLAN tag insert/strip */
+               ctrl |= E1000_CTRL_VME;
+       } else {
+               /* disable VLAN tag insert/strip */
+               ctrl &= ~E1000_CTRL_VME;
+       }
+       ew32(CTRL, ctrl);
+}
 static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
                                     bool filter_on)
 {
@@ -4779,6 +4798,7 @@ static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
        if (!test_bit(__E1000_DOWN, &adapter->flags))
                e1000_irq_disable(adapter);
 
+       __e1000_vlan_mode(adapter, adapter->netdev->features);
        if (filter_on) {
                /* enable VLAN receive filtering */
                rctl = er32(RCTL);
@@ -4799,24 +4819,14 @@ static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
 }
 
 static void e1000_vlan_mode(struct net_device *netdev,
-       netdev_features_t features)
+                           netdev_features_t features)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
-       struct e1000_hw *hw = &adapter->hw;
-       u32 ctrl;
 
        if (!test_bit(__E1000_DOWN, &adapter->flags))
                e1000_irq_disable(adapter);
 
-       ctrl = er32(CTRL);
-       if (features & NETIF_F_HW_VLAN_RX) {
-               /* enable VLAN tag insert/strip */
-               ctrl |= E1000_CTRL_VME;
-       } else {
-               /* disable VLAN tag insert/strip */
-               ctrl &= ~E1000_CTRL_VME;
-       }
-       ew32(CTRL, ctrl);
+       __e1000_vlan_mode(adapter, features);
 
        if (!test_bit(__E1000_DOWN, &adapter->flags))
                e1000_irq_enable(adapter);
index 86cdd47939925b64ebe5f3d1859165d6f1880f30..b83897f76ee34786360261d6148c31bcf9563588 100644 (file)
@@ -161,6 +161,12 @@ struct e1000_info;
 /* Time to wait before putting the device into D3 if there's no link (in ms). */
 #define LINK_TIMEOUT           100
 
+/*
+ * Count for polling __E1000_RESET condition every 10-20msec.
+ * Experimentation has shown the reset can take approximately 210msec.
+ */
+#define E1000_CHECK_RESET_COUNT                25
+
 #define DEFAULT_RDTR                   0
 #define DEFAULT_RADV                   8
 #define BURST_RDTR                     0x20
index 64c76443a7aa2f2c661f5ea0f0f3455055eb2306..b461c24945e3abc707d13ab5ba64f549c12949c8 100644 (file)
@@ -1310,10 +1310,6 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
 
                if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
                        oem_reg |= HV_OEM_BITS_LPLU;
-
-               /* Set Restart auto-neg to activate the bits */
-               if (!hw->phy.ops.check_reset_block(hw))
-                       oem_reg |= HV_OEM_BITS_RESTART_AN;
        } else {
                if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE |
                               E1000_PHY_CTRL_NOND0A_GBE_DISABLE))
@@ -1324,6 +1320,11 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
                        oem_reg |= HV_OEM_BITS_LPLU;
        }
 
+       /* Set Restart auto-neg to activate the bits */
+       if ((d0_state || (hw->mac.type != e1000_pchlan)) &&
+           !hw->phy.ops.check_reset_block(hw))
+               oem_reg |= HV_OEM_BITS_RESTART_AN;
+
        ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
 
 release:
@@ -3682,7 +3683,11 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
 
        if (hw->mac.type >= e1000_pchlan) {
                e1000_oem_bits_config_ich8lan(hw, false);
-               e1000_phy_hw_reset_ich8lan(hw);
+
+               /* Reset PHY to activate OEM bits on 82577/8 */
+               if (hw->mac.type == e1000_pchlan)
+                       e1000e_phy_hw_reset_generic(hw);
+
                ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
                        return;
index 7152eb11b7b9391ce4d74b9b9b9775115d856a33..9520a6ac1f3069592be3cc199c9d5e2ee99215b3 100644 (file)
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
 
 static const struct e1000_info *e1000_info_tbl[] = {
@@ -1054,6 +1059,13 @@ static void e1000_print_hw_hang(struct work_struct *work)
                ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
                /* execute the writes immediately */
                e1e_flush();
+               /*
+                * Due to rare timing issues, write to TIDV again to ensure
+                * the write is successful
+                */
+               ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+               /* execute the writes immediately */
+               e1e_flush();
                adapter->tx_hang_recheck = true;
                return;
        }
@@ -3611,6 +3623,16 @@ static void e1000e_flush_descriptors(struct e1000_adapter *adapter)
 
        /* execute the writes immediately */
        e1e_flush();
+
+       /*
+        * due to rare timing issues, write to TIDV/RDTR again to ensure the
+        * write is successful
+        */
+       ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+       ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD);
+
+       /* execute the writes immediately */
+       e1e_flush();
 }
 
 static void e1000e_update_stats(struct e1000_adapter *adapter);
@@ -3777,7 +3799,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
        /* fire an unusual interrupt on the test handler */
        ew32(ICS, E1000_ICS_RXSEQ);
        e1e_flush();
-       msleep(50);
+       msleep(100);
 
        e1000_irq_disable(adapter);
 
@@ -3963,6 +3985,10 @@ static int e1000_close(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct pci_dev *pdev = adapter->pdev;
+       int count = E1000_CHECK_RESET_COUNT;
+
+       while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
+               usleep_range(10000, 20000);
 
        WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
 
@@ -5467,6 +5493,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
        netif_device_detach(netdev);
 
        if (netif_running(netdev)) {
+               int count = E1000_CHECK_RESET_COUNT;
+
+               while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
+                       usleep_range(10000, 20000);
+
                WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
                e1000e_down(adapter);
                e1000_free_irq(adapter);
@@ -6172,7 +6203,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        adapter->hw.adapter = adapter;
        adapter->hw.mac.type = ei->mac;
        adapter->max_hw_frame_size = ei->max_hw_frame_size;
-       adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
        mmio_start = pci_resource_start(pdev, 0);
        mmio_len = pci_resource_len(pdev, 0);
index ff796e42c3ebbf1b146a28b677e7bb885e1f6bf6..16adeb9418a8903e5ccbb7503e513f1918978930 100644 (file)
@@ -106,7 +106,7 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
 /*
  * Interrupt Throttle Rate (interrupts/sec)
  *
- * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+ * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative
  */
 E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
 #define DEFAULT_ITR 3
@@ -344,53 +344,60 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
 
                if (num_InterruptThrottleRate > bd) {
                        adapter->itr = InterruptThrottleRate[bd];
-                       switch (adapter->itr) {
-                       case 0:
-                               e_info("%s turned off\n", opt.name);
-                               break;
-                       case 1:
-                               e_info("%s set to dynamic mode\n", opt.name);
-                               adapter->itr_setting = adapter->itr;
-                               adapter->itr = 20000;
-                               break;
-                       case 3:
-                               e_info("%s set to dynamic conservative mode\n",
-                                       opt.name);
-                               adapter->itr_setting = adapter->itr;
-                               adapter->itr = 20000;
-                               break;
-                       case 4:
-                               e_info("%s set to simplified (2000-8000 ints) "
-                                      "mode\n", opt.name);
-                               adapter->itr_setting = 4;
-                               break;
-                       default:
-                               /*
-                                * Save the setting, because the dynamic bits
-                                * change itr.
-                                */
-                               if (e1000_validate_option(&adapter->itr, &opt,
-                                                         adapter) &&
-                                   (adapter->itr == 3)) {
-                                       /*
-                                        * In case of invalid user value,
-                                        * default to conservative mode.
-                                        */
-                                       adapter->itr_setting = adapter->itr;
-                                       adapter->itr = 20000;
-                               } else {
-                                       /*
-                                        * Clear the lower two bits because
-                                        * they are used as control.
-                                        */
-                                       adapter->itr_setting =
-                                               adapter->itr & ~3;
-                               }
-                               break;
-                       }
+
+                       /*
+                        * Make sure a message is printed for non-special
+                        * values.  And in case of an invalid option, display
+                        * warning, use default and got through itr/itr_setting
+                        * adjustment logic below
+                        */
+                       if ((adapter->itr > 4) &&
+                           e1000_validate_option(&adapter->itr, &opt, adapter))
+                               adapter->itr = opt.def;
                } else {
-                       adapter->itr_setting = opt.def;
+                       /*
+                        * If no option specified, use default value and go
+                        * through the logic below to adjust itr/itr_setting
+                        */
+                       adapter->itr = opt.def;
+
+                       /*
+                        * Make sure a message is printed for non-special
+                        * default values
+                        */
+                       if (adapter->itr > 40)
+                               e_info("%s set to default %d\n", opt.name,
+                                      adapter->itr);
+               }
+
+               adapter->itr_setting = adapter->itr;
+               switch (adapter->itr) {
+               case 0:
+                       e_info("%s turned off\n", opt.name);
+                       break;
+               case 1:
+                       e_info("%s set to dynamic mode\n", opt.name);
+                       adapter->itr = 20000;
+                       break;
+               case 3:
+                       e_info("%s set to dynamic conservative mode\n",
+                              opt.name);
                        adapter->itr = 20000;
+                       break;
+               case 4:
+                       e_info("%s set to simplified (2000-8000 ints) mode\n",
+                              opt.name);
+                       break;
+               default:
+                       /*
+                        * Save the setting, because the dynamic bits
+                        * change itr.
+                        *
+                        * Clear the lower two bits because
+                        * they are used as control.
+                        */
+                       adapter->itr_setting &= ~3;
+                       break;
                }
        }
        { /* Interrupt Mode */
index c4902411d749b1469e556b9d667c766ea2ecbe20..5ec31598ee4775708094fabcd3e1775325e65dfa 100644 (file)
@@ -238,6 +238,11 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 struct igb_reg_info {
        u32 ofs;
        char *name;
@@ -1893,7 +1898,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
        adapter->pdev = pdev;
        hw = &adapter->hw;
        hw->back = adapter;
-       adapter->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE;
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
        mmio_start = pci_resource_start(pdev, 0);
        mmio_len = pci_resource_len(pdev, 0);
index 217c143686d223233eff7fb39dad96181a10d101..8ec74b07f940a234ccc1691e9dcd2b67691e0f4b 100644 (file)
@@ -55,6 +55,11 @@ static const char igbvf_driver_string[] =
 static const char igbvf_copyright[] =
                  "Copyright (c) 2009 - 2012 Intel Corporation.";
 
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 static int igbvf_poll(struct napi_struct *napi, int budget);
 static void igbvf_reset(struct igbvf_adapter *);
 static void igbvf_set_interrupt_capability(struct igbvf_adapter *);
@@ -2649,7 +2654,7 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
        adapter->flags = ei->flags;
        adapter->hw.back = adapter;
        adapter->hw.mac.type = ei->mac;
-       adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
        /* PCI config space info */
 
@@ -2726,14 +2731,14 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
                        netdev->addr_len);
        }
 
-       if (!is_valid_ether_addr(netdev->perm_addr)) {
+       if (!is_valid_ether_addr(netdev->dev_addr)) {
                dev_err(&pdev->dev, "Invalid MAC Address: %pM\n",
                        netdev->dev_addr);
                err = -EIO;
                goto err_hw_init;
        }
 
-       memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
+       memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
 
        setup_timer(&adapter->watchdog_timer, &igbvf_watchdog,
                    (unsigned long) adapter);
index 82aaa792cbf3a1472b50b623580e14e7eda5ecc6..5fce363d810a33ca2a8b26070734058777d5098b 100644 (file)
@@ -134,8 +134,8 @@ MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
-#define DEFAULT_DEBUG_LEVEL_SHIFT 3
-static int debug = DEFAULT_DEBUG_LEVEL_SHIFT;
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
@@ -442,7 +442,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        adapter->netdev = netdev;
        adapter->pdev = pdev;
        adapter->hw.back = adapter;
-       adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT);
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
        adapter->hw.hw_addr = pci_ioremap_bar(pdev, BAR_0);
        if (!adapter->hw.hw_addr) {
index 80e26ff30ebf5d3c306cb30892e7c51ff5755877..74e192107f9ae6a204ef538d322a6975daba5962 100644 (file)
@@ -544,7 +544,7 @@ struct ixgbe_fdir_filter {
        u16 action;
 };
 
-enum ixbge_state_t {
+enum ixgbe_state_t {
        __IXGBE_TESTING,
        __IXGBE_RESETTING,
        __IXGBE_DOWN,
index dde65f951400dc7efc1c6b3d09d5c8e44710db6f..652e4b09546db699eb4ff76189f8750bd163ca9e 100644 (file)
 #define DCB_NO_HW_CHG   1  /* DCB configuration did not change */
 #define DCB_HW_CHG      2  /* DCB configuration changed, no reset */
 
-int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
-                       struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max)
+int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *scfg,
+                      struct ixgbe_dcb_config *dcfg, int tc_max)
 {
-       struct tc_configuration *src_tc_cfg = NULL;
-       struct tc_configuration *dst_tc_cfg = NULL;
-       int i;
+       struct tc_configuration *src = NULL;
+       struct tc_configuration *dst = NULL;
+       int i, j;
+       int tx = DCB_TX_CONFIG;
+       int rx = DCB_RX_CONFIG;
+       int changes = 0;
 
-       if (!src_dcb_cfg || !dst_dcb_cfg)
-               return -EINVAL;
+       if (!scfg || !dcfg)
+               return changes;
 
        for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
-               src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
-               dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
+               src = &scfg->tc_config[i - DCB_PG_ATTR_TC_0];
+               dst = &dcfg->tc_config[i - DCB_PG_ATTR_TC_0];
 
-               dst_tc_cfg->path[DCB_TX_CONFIG].prio_type =
-                               src_tc_cfg->path[DCB_TX_CONFIG].prio_type;
+               if (dst->path[tx].prio_type != src->path[tx].prio_type) {
+                       dst->path[tx].prio_type = src->path[tx].prio_type;
+                       changes |= BIT_PG_TX;
+               }
 
-               dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id =
-                               src_tc_cfg->path[DCB_TX_CONFIG].bwg_id;
+               if (dst->path[tx].bwg_id != src->path[tx].bwg_id) {
+                       dst->path[tx].bwg_id = src->path[tx].bwg_id;
+                       changes |= BIT_PG_TX;
+               }
 
-               dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent =
-                               src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent;
+               if (dst->path[tx].bwg_percent != src->path[tx].bwg_percent) {
+                       dst->path[tx].bwg_percent = src->path[tx].bwg_percent;
+                       changes |= BIT_PG_TX;
+               }
 
-               dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap =
-                               src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap;
+               if (dst->path[tx].up_to_tc_bitmap !=
+                               src->path[tx].up_to_tc_bitmap) {
+                       dst->path[tx].up_to_tc_bitmap =
+                               src->path[tx].up_to_tc_bitmap;
+                       changes |= (BIT_PG_TX | BIT_PFC | BIT_APP_UPCHG);
+               }
 
-               dst_tc_cfg->path[DCB_RX_CONFIG].prio_type =
-                               src_tc_cfg->path[DCB_RX_CONFIG].prio_type;
+               if (dst->path[rx].prio_type != src->path[rx].prio_type) {
+                       dst->path[rx].prio_type = src->path[rx].prio_type;
+                       changes |= BIT_PG_RX;
+               }
 
-               dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id =
-                               src_tc_cfg->path[DCB_RX_CONFIG].bwg_id;
+               if (dst->path[rx].bwg_id != src->path[rx].bwg_id) {
+                       dst->path[rx].bwg_id = src->path[rx].bwg_id;
+                       changes |= BIT_PG_RX;
+               }
 
-               dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent =
-                               src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent;
+               if (dst->path[rx].bwg_percent != src->path[rx].bwg_percent) {
+                       dst->path[rx].bwg_percent = src->path[rx].bwg_percent;
+                       changes |= BIT_PG_RX;
+               }
 
-               dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap =
-                               src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap;
+               if (dst->path[rx].up_to_tc_bitmap !=
+                               src->path[rx].up_to_tc_bitmap) {
+                       dst->path[rx].up_to_tc_bitmap =
+                               src->path[rx].up_to_tc_bitmap;
+                       changes |= (BIT_PG_RX | BIT_PFC | BIT_APP_UPCHG);
+               }
        }
 
        for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) {
-               dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG]
-                       [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
-                               [DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
-               dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG]
-                       [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
-                               [DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
+               j = i - DCB_PG_ATTR_BW_ID_0;
+               if (dcfg->bw_percentage[tx][j] != scfg->bw_percentage[tx][j]) {
+                       dcfg->bw_percentage[tx][j] = scfg->bw_percentage[tx][j];
+                       changes |= BIT_PG_TX;
+               }
+               if (dcfg->bw_percentage[rx][j] != scfg->bw_percentage[rx][j]) {
+                       dcfg->bw_percentage[rx][j] = scfg->bw_percentage[rx][j];
+                       changes |= BIT_PG_RX;
+               }
        }
 
        for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) {
-               dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc =
-                       src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc;
+               j = i - DCB_PFC_UP_ATTR_0;
+               if (dcfg->tc_config[j].dcb_pfc != scfg->tc_config[j].dcb_pfc) {
+                       dcfg->tc_config[j].dcb_pfc = scfg->tc_config[j].dcb_pfc;
+                       changes |= BIT_PFC;
+               }
        }
 
-       dst_dcb_cfg->pfc_mode_enable = src_dcb_cfg->pfc_mode_enable;
+       if (dcfg->pfc_mode_enable != scfg->pfc_mode_enable) {
+               dcfg->pfc_mode_enable = scfg->pfc_mode_enable;
+               changes |= BIT_PFC;
+       }
 
-       return 0;
+       return changes;
 }
 
 static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
@@ -179,20 +211,6 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
        if (up_map != DCB_ATTR_VALUE_UNDEFINED)
                adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
                        up_map;
-
-       if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type !=
-            adapter->dcb_cfg.tc_config[tc].path[0].prio_type) ||
-           (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id !=
-            adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) ||
-           (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
-            adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
-           (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
-            adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
-               adapter->dcb_set_bitmap |= BIT_PG_TX;
-
-       if (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
-            adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)
-               adapter->dcb_set_bitmap |= BIT_PFC | BIT_APP_UPCHG;
 }
 
 static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
@@ -201,10 +219,6 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
        adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
-
-       if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
-           adapter->dcb_cfg.bw_percentage[0][bwg_id])
-               adapter->dcb_set_bitmap |= BIT_PG_TX;
 }
 
 static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
@@ -223,20 +237,6 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
        if (up_map != DCB_ATTR_VALUE_UNDEFINED)
                adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
                        up_map;
-
-       if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type !=
-            adapter->dcb_cfg.tc_config[tc].path[1].prio_type) ||
-           (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id !=
-            adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) ||
-           (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
-            adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
-           (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
-            adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
-               adapter->dcb_set_bitmap |= BIT_PG_RX;
-
-       if (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
-            adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)
-               adapter->dcb_set_bitmap |= BIT_PFC;
 }
 
 static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
@@ -245,10 +245,6 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
        adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
-
-       if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
-           adapter->dcb_cfg.bw_percentage[1][bwg_id])
-               adapter->dcb_set_bitmap |= BIT_PG_RX;
 }
 
 static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
@@ -298,10 +294,8 @@ static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
 
        adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
        if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
-           adapter->dcb_cfg.tc_config[priority].dcb_pfc) {
-               adapter->dcb_set_bitmap |= BIT_PFC;
+           adapter->dcb_cfg.tc_config[priority].dcb_pfc)
                adapter->temp_dcb_cfg.pfc_mode_enable = true;
-       }
 }
 
 static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
@@ -336,7 +330,8 @@ static void ixgbe_dcbnl_devreset(struct net_device *dev)
 static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
-       int ret, i;
+       int ret = DCB_NO_HW_CHG;
+       int i;
 #ifdef IXGBE_FCOE
        struct dcb_app app = {
                              .selector = DCB_APP_IDTYPE_ETHTYPE,
@@ -355,12 +350,13 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 
        /* Fail command if not in CEE mode */
        if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
-               return 1;
+               return ret;
 
-       ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
-                                MAX_TRAFFIC_CLASS);
-       if (ret)
-               return DCB_NO_HW_CHG;
+       adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg,
+                                                     &adapter->dcb_cfg,
+                                                     MAX_TRAFFIC_CLASS);
+       if (!adapter->dcb_set_bitmap)
+               return ret;
 
        if (adapter->dcb_cfg.pfc_mode_enable) {
                switch (adapter->hw.mac.type) {
@@ -420,6 +416,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 
                for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
                        netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
+
+               ret = DCB_HW_CHG_RST;
        }
 
        if (adapter->dcb_set_bitmap & BIT_PFC) {
@@ -430,7 +428,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
                                     DCB_TX_CONFIG, prio_tc);
                ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
                ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc);
-               ret = DCB_HW_CHG;
+               if (ret != DCB_HW_CHG_RST)
+                       ret = DCB_HW_CHG;
        }
 
        if (adapter->dcb_cfg.pfc_mode_enable)
@@ -531,9 +530,6 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
        adapter->temp_dcb_cfg.pfc_mode_enable = state;
-       if (adapter->temp_dcb_cfg.pfc_mode_enable !=
-               adapter->dcb_cfg.pfc_mode_enable)
-               adapter->dcb_set_bitmap |= BIT_PFC;
 }
 
 /**
index 77ea4b7165351707192dde0ea3c678950502a71b..bc07933d67dadec6845fb667fbc9cc1edf025c3e 100644 (file)
@@ -437,6 +437,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
         */
        if ((fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA) &&
            (fctl & FC_FC_END_SEQ)) {
+               skb_linearize(skb);
                crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
                crc->fcoe_eof = FC_EOF_T;
        }
index 027d7a75be39b025c6de30a63d63a30a528424a2..ed1b47dc0834f5a5c1f76fc667e810e23125ba03 100644 (file)
@@ -622,6 +622,16 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx,
                if (adapter->hw.mac.type == ixgbe_mac_82599EB)
                        set_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state);
 
+#ifdef IXGBE_FCOE
+               if (adapter->netdev->features & NETIF_F_FCOE_MTU) {
+                       struct ixgbe_ring_feature *f;
+                       f = &adapter->ring_feature[RING_F_FCOE];
+                       if ((rxr_idx >= f->mask) &&
+                           (rxr_idx < f->mask + f->indices))
+                               set_bit(__IXGBE_RX_FCOE_BUFSZ, &ring->state);
+               }
+
+#endif /* IXGBE_FCOE */
                /* apply Rx specific ring traits */
                ring->count = adapter->rx_ring_count;
                ring->queue_index = rxr_idx;
index 398fc223cab967409f4d620d5e47f4c92d31a420..88f6b2e9b72db2ddb22b917fcb4e4ae4c9b99514 100644 (file)
@@ -63,8 +63,8 @@ static char ixgbe_default_device_descr[] =
                              "Intel(R) 10 Gigabit Network Connection";
 #endif
 #define MAJ 3
-#define MIN 6
-#define BUILD 7
+#define MIN 8
+#define BUILD 21
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
        __stringify(BUILD) "-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
@@ -141,13 +141,16 @@ module_param(allow_unsupported_sfp, uint, 0);
 MODULE_PARM_DESC(allow_unsupported_sfp,
                 "Allow unsupported and untested SFP+ modules on 82599-based adapters");
 
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
 MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
-#define DEFAULT_DEBUG_LEVEL_SHIFT 3
-
 static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
 {
        if (!test_bit(__IXGBE_DOWN, &adapter->state) &&
@@ -3151,14 +3154,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
                        set_ring_rsc_enabled(rx_ring);
                else
                        clear_ring_rsc_enabled(rx_ring);
-#ifdef IXGBE_FCOE
-               if (netdev->features & NETIF_F_FCOE_MTU) {
-                       struct ixgbe_ring_feature *f;
-                       f = &adapter->ring_feature[RING_F_FCOE];
-                       if ((i >= f->mask) && (i < f->mask + f->indices))
-                               set_bit(__IXGBE_RX_FCOE_BUFSZ, &rx_ring->state);
-               }
-#endif /* IXGBE_FCOE */
        }
 }
 
@@ -4833,7 +4828,9 @@ static int ixgbe_resume(struct pci_dev *pdev)
 
        pci_wake_from_d3(pdev, false);
 
+       rtnl_lock();
        err = ixgbe_init_interrupt_scheme(adapter);
+       rtnl_unlock();
        if (err) {
                e_dev_err("Cannot initialize interrupts for device\n");
                return err;
@@ -4876,10 +4873,6 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
        }
 
        ixgbe_clear_interrupt_scheme(adapter);
-#ifdef CONFIG_DCB
-       kfree(adapter->ixgbe_ieee_pfc);
-       kfree(adapter->ixgbe_ieee_ets);
-#endif
 
 #ifdef CONFIG_PM
        retval = pci_save_state(pdev);
@@ -4890,6 +4883,16 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
        if (wufc) {
                ixgbe_set_rx_mode(netdev);
 
+               /*
+                * enable the optics for both mult-speed fiber and
+                * 82599 SFP+ fiber as we can WoL.
+                */
+               if (hw->mac.ops.enable_tx_laser &&
+                   (hw->phy.multispeed_fiber ||
+                   (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber &&
+                    hw->mac.type == ixgbe_mac_82599EB)))
+                       hw->mac.ops.enable_tx_laser(hw);
+
                /* turn on all-multi mode if wake on multicast is enabled */
                if (wufc & IXGBE_WUFC_MC) {
                        fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
@@ -6834,7 +6837,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        adapter->pdev = pdev;
        hw = &adapter->hw;
        hw->back = adapter;
-       adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
        hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
                              pci_resource_len(pdev, 0));
@@ -7217,6 +7220,11 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
 
        ixgbe_release_hw_control(adapter);
 
+#ifdef CONFIG_DCB
+       kfree(adapter->ixgbe_ieee_pfc);
+       kfree(adapter->ixgbe_ieee_ets);
+
+#endif
        iounmap(adapter->hw.hw_addr);
        pci_release_selected_regions(pdev, pci_select_bars(pdev,
                                     IORESOURCE_MEM));
index 581c65976bb49ae21cb9433416bb46d07096599d..307611ae831d5286436f13aa89ae0afe634534c5 100644 (file)
@@ -91,7 +91,10 @@ MODULE_DESCRIPTION("Intel(R) 82599 Virtual Function Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
-#define DEFAULT_DEBUG_LEVEL_SHIFT 3
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
 /* forward decls */
 static void ixgbevf_set_itr_msix(struct ixgbevf_q_vector *q_vector);
@@ -3367,7 +3370,7 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
        adapter->pdev = pdev;
        hw = &adapter->hw;
        hw->back = adapter;
-       adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
        /*
         * call save state here in standalone driver because it relies on
index 423a1a2a702e77e6034f9ca31b8a80177d33e110..487a6c8bd4eccf6c21dc394c317e408cabe9aa12 100644 (file)
@@ -1767,13 +1767,14 @@ static int sky2_open(struct net_device *dev)
 
        sky2_hw_up(sky2);
 
+       /* Enable interrupts from phy/mac for port */
+       imask = sky2_read32(hw, B0_IMSK);
+
        if (hw->chip_id == CHIP_ID_YUKON_OPT ||
            hw->chip_id == CHIP_ID_YUKON_PRM ||
            hw->chip_id == CHIP_ID_YUKON_OP_2)
                imask |= Y2_IS_PHY_QLNK;        /* enable PHY Quick Link */
 
-       /* Enable interrupts from phy/mac for port */
-       imask = sky2_read32(hw, B0_IMSK);
        imask |= portirq_msk[port];
        sky2_write32(hw, B0_IMSK, imask);
        sky2_read32(hw, B0_IMSK);
@@ -2468,6 +2469,17 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
        return err;
 }
 
+static inline bool needs_copy(const struct rx_ring_info *re,
+                             unsigned length)
+{
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+       /* Some architectures need the IP header to be aligned */
+       if (!IS_ALIGNED(re->data_addr + ETH_HLEN, sizeof(u32)))
+               return true;
+#endif
+       return length < copybreak;
+}
+
 /* For small just reuse existing skb for next receive */
 static struct sk_buff *receive_copy(struct sky2_port *sky2,
                                    const struct rx_ring_info *re,
@@ -2482,8 +2494,13 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2,
                skb_copy_from_linear_data(re->skb, skb->data, length);
                skb->ip_summed = re->skb->ip_summed;
                skb->csum = re->skb->csum;
+               skb->rxhash = re->skb->rxhash;
+               skb->vlan_tci = re->skb->vlan_tci;
+
                pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
                                               length, PCI_DMA_FROMDEVICE);
+               re->skb->vlan_tci = 0;
+               re->skb->rxhash = 0;
                re->skb->ip_summed = CHECKSUM_NONE;
                skb_put(skb, length);
        }
@@ -2568,9 +2585,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
        struct sk_buff *skb = NULL;
        u16 count = (status & GMR_FS_LEN) >> 16;
 
-       if (status & GMR_FS_VLAN)
-               count -= VLAN_HLEN;     /* Account for vlan tag */
-
        netif_printk(sky2, rx_status, KERN_DEBUG, dev,
                     "rx slot %u status 0x%x len %d\n",
                     sky2->rx_next, status, length);
@@ -2578,6 +2592,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
        sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
        prefetch(sky2->rx_ring + sky2->rx_next);
 
+       if (vlan_tx_tag_present(re->skb))
+               count -= VLAN_HLEN;     /* Account for vlan tag */
+
        /* This chip has hardware problems that generates bogus status.
         * So do only marginal checking and expect higher level protocols
         * to handle crap frames.
@@ -2598,7 +2615,7 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
                goto error;
 
 okay:
-       if (length < copybreak)
+       if (needs_copy(re, length))
                skb = receive_copy(sky2, re, length);
        else
                skb = receive_new(sky2, re, length);
@@ -2635,11 +2652,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
 }
 
 static inline void sky2_skb_rx(const struct sky2_port *sky2,
-                              u32 status, struct sk_buff *skb)
+                              struct sk_buff *skb)
 {
-       if (status & GMR_FS_VLAN)
-               __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
-
        if (skb->ip_summed == CHECKSUM_NONE)
                netif_receive_skb(skb);
        else
@@ -2693,6 +2707,14 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
        }
 }
 
+static void sky2_rx_tag(struct sky2_port *sky2, u16 length)
+{
+       struct sk_buff *skb;
+
+       skb = sky2->rx_ring[sky2->rx_next].skb;
+       __vlan_hwaccel_put_tag(skb, be16_to_cpu(length));
+}
+
 static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
 {
        struct sk_buff *skb;
@@ -2751,8 +2773,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
                        }
 
                        skb->protocol = eth_type_trans(skb, dev);
-
-                       sky2_skb_rx(sky2, status, skb);
+                       sky2_skb_rx(sky2, skb);
 
                        /* Stop after net poll weight */
                        if (++work_done >= to_do)
@@ -2760,11 +2781,11 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
                        break;
 
                case OP_RXVLAN:
-                       sky2->rx_tag = length;
+                       sky2_rx_tag(sky2, length);
                        break;
 
                case OP_RXCHKSVLAN:
-                       sky2->rx_tag = length;
+                       sky2_rx_tag(sky2, length);
                        /* fall through */
                case OP_RXCHKS:
                        if (likely(dev->features & NETIF_F_RXCSUM))
index ff6f58bf822aa378ffa0975140733fa40bf41f5d..3c896ce80b71ec1facc6f04f666ab80711c5dfe3 100644 (file)
@@ -2241,7 +2241,6 @@ struct sky2_port {
        u16                  rx_pending;
        u16                  rx_data_size;
        u16                  rx_nfrags;
-       u16                  rx_tag;
 
        struct {
                unsigned long last;
index 9e2b911a12304ee88f5934c1c895d394d662e05a..d69fee41f24aa296106063f06826a06096b07f42 100644 (file)
@@ -83,8 +83,9 @@
 
 #define MLX4_EN_WATCHDOG_TIMEOUT       (15 * HZ)
 
-#define MLX4_EN_ALLOC_ORDER    2
-#define MLX4_EN_ALLOC_SIZE     (PAGE_SIZE << MLX4_EN_ALLOC_ORDER)
+/* Use the maximum between 16384 and a single page */
+#define MLX4_EN_ALLOC_SIZE     PAGE_ALIGN(16384)
+#define MLX4_EN_ALLOC_ORDER    get_order(MLX4_EN_ALLOC_SIZE)
 
 #define MLX4_EN_MAX_LRO_DESCRIPTORS    32
 
index c722aa607d074796985b9028c5c91752459aad8e..f8dda009d3c04722e54c659bfa3bb921d8b62fa8 100644 (file)
@@ -889,16 +889,17 @@ static int ks8851_net_stop(struct net_device *dev)
        netif_stop_queue(dev);
 
        mutex_lock(&ks->lock);
+       /* turn off the IRQs and ack any outstanding */
+       ks8851_wrreg16(ks, KS_IER, 0x0000);
+       ks8851_wrreg16(ks, KS_ISR, 0xffff);
+       mutex_unlock(&ks->lock);
 
        /* stop any outstanding work */
        flush_work(&ks->irq_work);
        flush_work(&ks->tx_work);
        flush_work(&ks->rxctrl_work);
 
-       /* turn off the IRQs and ack any outstanding */
-       ks8851_wrreg16(ks, KS_IER, 0x0000);
-       ks8851_wrreg16(ks, KS_ISR, 0xffff);
-
+       mutex_lock(&ks->lock);
        /* shutdown RX process */
        ks8851_wrreg16(ks, KS_RXCR1, 0x0000);
 
@@ -907,6 +908,7 @@ static int ks8851_net_stop(struct net_device *dev)
 
        /* set powermode to soft power down to save power */
        ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
+       mutex_unlock(&ks->lock);
 
        /* ensure any queued tx buffers are dumped */
        while (!skb_queue_empty(&ks->txq)) {
@@ -918,7 +920,6 @@ static int ks8851_net_stop(struct net_device *dev)
                dev_kfree_skb(txb);
        }
 
-       mutex_unlock(&ks->lock);
        return 0;
 }
 
@@ -1418,6 +1419,7 @@ static int __devinit ks8851_probe(struct spi_device *spi)
        struct net_device *ndev;
        struct ks8851_net *ks;
        int ret;
+       unsigned cider;
 
        ndev = alloc_etherdev(sizeof(struct ks8851_net));
        if (!ndev)
@@ -1484,8 +1486,8 @@ static int __devinit ks8851_probe(struct spi_device *spi)
        ks8851_soft_reset(ks, GRR_GSR);
 
        /* simple check for a valid chip being connected to the bus */
-
-       if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
+       cider = ks8851_rdreg16(ks, KS_CIDER);
+       if ((cider & ~CIDER_REV_MASK) != CIDER_ID) {
                dev_err(&spi->dev, "failed to read device ID\n");
                ret = -ENODEV;
                goto err_id;
@@ -1516,15 +1518,14 @@ static int __devinit ks8851_probe(struct spi_device *spi)
        }
 
        netdev_info(ndev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n",
-                   CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)),
-                   ndev->dev_addr, ndev->irq,
+                   CIDER_REV_GET(cider), ndev->dev_addr, ndev->irq,
                    ks->rc_ccr & CCR_EEPROM ? "has" : "no");
 
        return 0;
 
 
 err_netdev:
-       free_irq(ndev->irq, ndev);
+       free_irq(ndev->irq, ks);
 
 err_id:
 err_irq:
index b8104d9f40810871525eb360edaf16e483f6e945..5ffde23ac8fb729526a9dc9c7cfebd95fb2e9b09 100644 (file)
@@ -40,7 +40,7 @@
 #define        DRV_NAME        "ks8851_mll"
 
 static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 };
-#define MAX_RECV_FRAMES                        32
+#define MAX_RECV_FRAMES                        255
 #define MAX_BUF_SIZE                   2048
 #define TX_BUF_SIZE                    2000
 #define RX_BUF_SIZE                    2000
index ef723b185d853794746a3882cf54e4c00a205699..eaf9ff0262a9c63594e7d80c617d87098c957fa6 100644 (file)
@@ -5675,7 +5675,7 @@ static int netdev_set_mac_address(struct net_device *dev, void *addr)
                memcpy(hw->override_addr, mac->sa_data, ETH_ALEN);
        }
 
-       memcpy(dev->dev_addr, mac->sa_data, MAX_ADDR_LEN);
+       memcpy(dev->dev_addr, mac->sa_data, ETH_ALEN);
 
        interrupt = hw_block_intr(hw);
 
index 69444247c20bd30563552c69528b9047d4f5a697..6dfc26d85e4747bb645d577da44d8840a998405d 100644 (file)
@@ -1441,7 +1441,7 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
        }
 #endif
        if (!is_valid_ether_addr(ndev->dev_addr))
-               dev_hw_addr_random(ndev, ndev->dev_addr);
+               eth_hw_addr_random(ndev);
 
        /* Reset the ethernet controller */
        __lpc_eth_reset(pldat);
index abc79076f867baa5220361e0d6810d11e7edc8ef..b3287c0fe279b95636f80325549833edd137f590 100644 (file)
@@ -958,6 +958,11 @@ static inline void cp_start_hw (struct cp_private *cp)
        cpw8(Cmd, RxOn | TxOn);
 }
 
+static void cp_enable_irq(struct cp_private *cp)
+{
+       cpw16_f(IntrMask, cp_intr_mask);
+}
+
 static void cp_init_hw (struct cp_private *cp)
 {
        struct net_device *dev = cp->dev;
@@ -997,8 +1002,6 @@ static void cp_init_hw (struct cp_private *cp)
 
        cpw16(MultiIntr, 0);
 
-       cpw16_f(IntrMask, cp_intr_mask);
-
        cpw8_f(Cfg9346, Cfg9346_Lock);
 }
 
@@ -1130,6 +1133,8 @@ static int cp_open (struct net_device *dev)
        if (rc)
                goto err_out_hw;
 
+       cp_enable_irq(cp);
+
        netif_carrier_off(dev);
        mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
        netif_start_queue(dev);
@@ -2031,6 +2036,7 @@ static int cp_resume (struct pci_dev *pdev)
        /* FIXME: sh*t may happen if the Rx ring buffer is depleted */
        cp_init_rings_index (cp);
        cp_init_hw (cp);
+       cp_enable_irq(cp);
        netif_start_queue (dev);
 
        spin_lock_irqsave (&cp->lock, flags);
index 7b23554f80b6c0f8540bccddea0c9ae31c75f35e..f54509377efad8354345176fdb9c1951a9fdd4de 100644 (file)
@@ -5810,7 +5810,10 @@ static void __rtl8169_resume(struct net_device *dev)
 
        rtl_pll_power_up(tp);
 
+       rtl_lock_work(tp);
+       napi_enable(&tp->napi);
        set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+       rtl_unlock_work(tp);
 
        rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
 }
index 9755b49bbefb209d26ec17066ae7eebcee7fdd00..3fb2355af37e5bebcbbd7e6fa706ee120056bf8b 100644 (file)
@@ -7,7 +7,8 @@ config SH_ETH
        depends on SUPERH && \
                (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
                 CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
-                CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7757)
+                CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \
+                CPU_SUBTYPE_SH7757)
        select CRC32
        select NET_CORE
        select MII
@@ -16,4 +17,4 @@ config SH_ETH
        ---help---
          Renesas SuperH Ethernet device driver.
          This driver supporting CPUs are:
-               - SH7710, SH7712, SH7763, SH7619, SH7724, and SH7757.
+               - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763 and SH7757.
index 8615961c128761abfdcfba4df8964ce59ea04cd7..d63e09b29a961b8cfc809a23b04821b8d56e7a8f 100644 (file)
@@ -1,8 +1,8 @@
 /*
  *  SuperH Ethernet device driver
  *
- *  Copyright (C) 2006-2008 Nobuhiro Iwamatsu
- *  Copyright (C) 2008-2009 Renesas Solutions Corp.
+ *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
+ *  Copyright (C) 2008-2012 Renesas Solutions Corp.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
+#include <linux/clk.h>
 #include <linux/sh_eth.h>
 
 #include "sh_eth.h"
@@ -279,8 +280,9 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
                return &sh_eth_my_cpu_data;
 }
 
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
 #define SH_ETH_HAS_TSU 1
+static void sh_eth_reset_hw_crc(struct net_device *ndev);
 static void sh_eth_chip_reset(struct net_device *ndev)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
@@ -314,6 +316,9 @@ static void sh_eth_reset(struct net_device *ndev)
        sh_eth_write(ndev, 0x0, RDFAR);
        sh_eth_write(ndev, 0x0, RDFXR);
        sh_eth_write(ndev, 0x0, RDFFR);
+
+       /* Reset HW CRC register */
+       sh_eth_reset_hw_crc(ndev);
 }
 
 static void sh_eth_set_duplex(struct net_device *ndev)
@@ -370,8 +375,17 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
        .no_trimd       = 1,
        .no_ade         = 1,
        .tsu            = 1,
+#if defined(CONFIG_CPU_SUBTYPE_SH7734)
+       .hw_crc     = 1,
+#endif
 };
 
+static void sh_eth_reset_hw_crc(struct net_device *ndev)
+{
+       if (sh_eth_my_cpu_data.hw_crc)
+               sh_eth_write(ndev, 0x0, CSMR);
+}
+
 #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
 #define SH_ETH_RESET_DEFAULT   1
 static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
@@ -790,7 +804,7 @@ static int sh_eth_dev_init(struct net_device *ndev)
        /* all sh_eth int mask */
        sh_eth_write(ndev, 0, EESIPR);
 
-#if defined(__LITTLE_ENDIAN__)
+#if defined(__LITTLE_ENDIAN)
        if (mdp->cd->hw_swap)
                sh_eth_write(ndev, EDMR_EL, EDMR);
        else
index 57dc262611166de138727c63708834150f3dfad9..0fa14afce23d47bb95fff404ca198339d3a4b891 100644 (file)
@@ -1,8 +1,8 @@
 /*
  *  SuperH Ethernet device driver
  *
- *  Copyright (C) 2006-2008 Nobuhiro Iwamatsu
- *  Copyright (C) 2008-2011 Renesas Solutions Corp.
+ *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
+ *  Copyright (C) 2008-2012 Renesas Solutions Corp.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
@@ -98,6 +98,8 @@ enum {
        CEECR,
        MAFCR,
        RTRATE,
+       CSMR,
+       RMII_MII,
 
        /* TSU Absolute address */
        ARSTR,
@@ -172,6 +174,7 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
        [RMCR]  = 0x0458,
        [RPADIR]        = 0x0460,
        [FCFTR] = 0x0468,
+       [CSMR] = 0x04E4,
 
        [ECMR]  = 0x0500,
        [ECSR]  = 0x0510,
@@ -200,6 +203,7 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
        [CERCR] = 0x0768,
        [CEECR] = 0x0770,
        [MAFCR] = 0x0778,
+       [RMII_MII] =  0x0790,
 
        [ARSTR] = 0x0000,
        [TSU_CTRST]     = 0x0004,
@@ -377,7 +381,7 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
 /*
  * Register's bits
  */
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
+#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
 /* EDSR */
 enum EDSR_BIT {
        EDSR_ENT = 0x01, EDSR_ENR = 0x02,
@@ -689,7 +693,7 @@ enum TSU_FWSLC_BIT {
  */
 struct sh_eth_txdesc {
        u32 status;             /* TD0 */
-#if defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN)
        u16 pad0;               /* TD1 */
        u16 buffer_length;      /* TD1 */
 #else
@@ -706,7 +710,7 @@ struct sh_eth_txdesc {
  */
 struct sh_eth_rxdesc {
        u32 status;             /* RD0 */
-#if defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN)
        u16 frame_length;       /* RD1 */
        u16 buffer_length;      /* RD1 */
 #else
@@ -751,6 +755,7 @@ struct sh_eth_cpu_data {
        unsigned rpadir:1;              /* E-DMAC have RPADIR */
        unsigned no_trimd:1;            /* E-DMAC DO NOT have TRIMD */
        unsigned no_ade:1;      /* E-DMAC DO NOT have ADE bit in EESR */
+       unsigned hw_crc:1;      /* E-DMAC have CSMR */
 };
 
 struct sh_eth_private {
index 4a6971027076613f7765a187e2c28eb11df56104..cd3defb11ffb3e09822b5f20555796ddd8960fd2 100644 (file)
@@ -1166,10 +1166,8 @@ smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat)
 
 /* Quickly dumps bad packets */
 static void
-smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
+smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktwords)
 {
-       unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
-
        if (likely(pktwords >= 4)) {
                unsigned int timeout = 500;
                unsigned int val;
@@ -1233,7 +1231,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
                        continue;
                }
 
-               skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN);
+               skb = netdev_alloc_skb(dev, pktwords << 2);
                if (unlikely(!skb)) {
                        SMSC_WARN(pdata, rx_err,
                                  "Unable to allocate skb for rx packet");
@@ -1243,14 +1241,12 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
                        break;
                }
 
-               skb->data = skb->head;
-               skb_reset_tail_pointer(skb);
+               pdata->ops->rx_readfifo(pdata,
+                                (unsigned int *)skb->data, pktwords);
 
                /* Align IP on 16B boundary */
                skb_reserve(skb, NET_IP_ALIGN);
                skb_put(skb, pktlength - 4);
-               pdata->ops->rx_readfifo(pdata,
-                                (unsigned int *)skb->head, pktwords);
                skb->protocol = eth_type_trans(skb, dev);
                skb_checksum_none_assert(skb);
                netif_receive_skb(skb);
@@ -1565,7 +1561,7 @@ static int smsc911x_open(struct net_device *dev)
        smsc911x_reg_write(pdata, FIFO_INT, temp);
 
        /* set RX Data offset to 2 bytes for alignment */
-       smsc911x_reg_write(pdata, RX_CFG, (2 << 8));
+       smsc911x_reg_write(pdata, RX_CFG, (NET_IP_ALIGN << 8));
 
        /* enable NAPI polling before enabling RX interrupts */
        napi_enable(&pdata->napi);
@@ -2382,7 +2378,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
        SET_NETDEV_DEV(dev, &pdev->dev);
 
        pdata = netdev_priv(dev);
-
        dev->irq = irq_res->start;
        irq_flags = irq_res->flags & IRQF_TRIGGER_MASK;
        pdata->ioaddr = ioremap_nocache(res->start, res_size);
@@ -2446,7 +2441,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
        if (retval) {
                SMSC_WARN(pdata, probe,
                          "Unable to claim requested irq: %d", dev->irq);
-               goto out_free_irq;
+               goto out_disable_resources;
        }
 
        retval = register_netdev(dev);
index e85ffbd548302994514ec1e46e8faa48be9cd78a..48d56da62f08e94a6b4b26bf594aa8ae022a36bc 100644 (file)
@@ -1737,10 +1737,12 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
        struct mac_device_info *mac;
 
        /* Identify the MAC HW device */
-       if (priv->plat->has_gmac)
+       if (priv->plat->has_gmac) {
+               priv->dev->priv_flags |= IFF_UNICAST_FLT;
                mac = dwmac1000_setup(priv->ioaddr);
-       else
+       } else {
                mac = dwmac100_setup(priv->ioaddr);
+       }
        if (!mac)
                return -ENOMEM;
 
index 558409ff40582fa9f5cd1ae91248f9d214c51d3e..4ba969096717a7ce59e55eaa97f40bdc974ef8b2 100644 (file)
@@ -2339,7 +2339,7 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
        netif_device_detach(dev);
 
        /* Switch off chip, remember WOL setting */
-       gp->asleep_wol = gp->wake_on_lan;
+       gp->asleep_wol = !!gp->wake_on_lan;
        gem_do_stop(dev, gp->asleep_wol);
 
        /* Unlock the network stack */
index 174a3348f6762d67a661801342ea6cbe95a7810f..08aff1a2087c920207f544bf540917b481c35344 100644 (file)
@@ -1511,7 +1511,7 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
 
 static int match_first_device(struct device *dev, void *data)
 {
-       return 1;
+       return !strncmp(dev_name(dev), "davinci_mdio", 12);
 }
 
 /**
index 2757c7d6e6330460c179d025a1ddc2267d32b27d..e4e47088e26b98fe0118c16ae17da61ec0f07dde 100644 (file)
@@ -181,6 +181,11 @@ static inline int wait_for_user_access(struct davinci_mdio_data *data)
                __davinci_mdio_reset(data);
                return -EAGAIN;
        }
+
+       reg = __raw_readl(&regs->user[0].access);
+       if ((reg & USERACCESS_GO) == 0)
+               return 0;
+
        dev_err(data->dev, "timed out waiting for user access\n");
        return -ETIMEDOUT;
 }
index 817ad3bc49574670ab6040b6805528c5b863c852..efd36691ce5450881dd14114037071708df4e7c1 100644 (file)
@@ -228,7 +228,7 @@ tlan_get_skb(const struct tlan_list *tag)
        unsigned long addr;
 
        addr = tag->buffer[9].address;
-       addr |= (tag->buffer[8].address << 16) << 16;
+       addr |= ((unsigned long) tag->buffer[8].address << 16) << 16;
        return (struct sk_buff *) addr;
 }
 
index 261356c2dc99ed4bdff8af73afb132c9baa6f3e7..3d501ec7fad7f67775ca1f11fe4c3870db4f61d7 100644 (file)
@@ -342,6 +342,21 @@ inline int __netio_fastio1(u32 fastio_index, u32 arg0)
 }
 
 
+static void tile_net_return_credit(struct tile_net_cpu *info)
+{
+       struct tile_netio_queue *queue = &info->queue;
+       netio_queue_user_impl_t *qup = &queue->__user_part;
+
+       /* Return four credits after every fourth packet. */
+       if (--qup->__receive_credit_remaining == 0) {
+               u32 interval = qup->__receive_credit_interval;
+               qup->__receive_credit_remaining = interval;
+               __netio_fastio_return_credits(qup->__fastio_index, interval);
+       }
+}
+
+
+
 /*
  * Provide a linux buffer to LIPP.
  */
@@ -433,7 +448,7 @@ static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info,
        struct sk_buff **skb_ptr;
 
        /* Request 96 extra bytes for alignment purposes. */
-       skb = netdev_alloc_skb(info->napi->dev, len + padding);
+       skb = netdev_alloc_skb(info->napi.dev, len + padding);
        if (skb == NULL)
                return false;
 
@@ -864,19 +879,11 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 
                stats->rx_packets++;
                stats->rx_bytes += len;
-
-               if (small)
-                       info->num_needed_small_buffers++;
-               else
-                       info->num_needed_large_buffers++;
        }
 
-       /* Return four credits after every fourth packet. */
-       if (--qup->__receive_credit_remaining == 0) {
-               u32 interval = qup->__receive_credit_interval;
-               qup->__receive_credit_remaining = interval;
-               __netio_fastio_return_credits(qup->__fastio_index, interval);
-       }
+       /* ISSUE: It would be nice to defer this until the packet has */
+       /* actually been processed. */
+       tile_net_return_credit(info);
 
        /* Consume this packet. */
        qup->__packet_receive_read = index2;
@@ -1543,7 +1550,7 @@ static int tile_net_drain_lipp_buffers(struct tile_net_priv *priv)
 
        /* Drain all the LIPP buffers. */
        while (true) {
-               int buffer;
+               unsigned int buffer;
 
                /* NOTE: This should never fail. */
                if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&buffer,
@@ -1707,7 +1714,7 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags,
                if (!hash_default) {
                        void *va = pfn_to_kaddr(pfn) + f->page_offset;
                        BUG_ON(PageHighMem(skb_frag_page(f)));
-                       finv_buffer_remote(va, f->size, 0);
+                       finv_buffer_remote(va, skb_frag_size(f), 0);
                }
 
                cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset;
@@ -1735,8 +1742,8 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags,
  * Sometimes, if "sendfile()" requires copying, we will be called with
  * "data" containing the header and payload, with "frags" being empty.
  *
- * In theory, "sh->nr_frags" could be 3, but in practice, it seems
- * that this will never actually happen.
+ * Sometimes, for example when using NFS over TCP, a single segment can
+ * span 3 fragments, which must be handled carefully in LEPP.
  *
  * See "emulate_large_send_offload()" for some reference code, which
  * does not handle checksumming.
@@ -1844,10 +1851,8 @@ static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev)
 
        spin_lock_irqsave(&priv->eq_lock, irqflags);
 
-       /*
-        * Handle completions if needed to make room.
-        * HACK: Spin until there is sufficient room.
-        */
+       /* Handle completions if needed to make room. */
+       /* NOTE: Return NETDEV_TX_BUSY if there is still no room. */
        if (lepp_num_free_comp_slots(eq) == 0) {
                nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
                if (nolds == 0) {
@@ -1861,6 +1866,7 @@ busy:
        cmd_tail = eq->cmd_tail;
 
        /* Prepare to advance, detecting full queue. */
+       /* NOTE: Return NETDEV_TX_BUSY if the queue is full. */
        cmd_next = cmd_tail + cmd_size;
        if (cmd_tail < cmd_head && cmd_next >= cmd_head)
                goto busy;
@@ -2023,10 +2029,8 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 
        spin_lock_irqsave(&priv->eq_lock, irqflags);
 
-       /*
-        * Handle completions if needed to make room.
-        * HACK: Spin until there is sufficient room.
-        */
+       /* Handle completions if needed to make room. */
+       /* NOTE: Return NETDEV_TX_BUSY if there is still no room. */
        if (lepp_num_free_comp_slots(eq) == 0) {
                nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
                if (nolds == 0) {
@@ -2040,6 +2044,7 @@ busy:
        cmd_tail = eq->cmd_tail;
 
        /* Copy the commands, or fail. */
+       /* NOTE: Return NETDEV_TX_BUSY if the queue is full. */
        for (i = 0; i < num_frags; i++) {
 
                /* Prepare to advance, detecting full queue. */
@@ -2261,6 +2266,23 @@ static int tile_net_get_mac(struct net_device *dev)
        return 0;
 }
 
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void tile_net_netpoll(struct net_device *dev)
+{
+       struct tile_net_priv *priv = netdev_priv(dev);
+       disable_percpu_irq(priv->intr_id);
+       tile_net_handle_ingress_interrupt(priv->intr_id, dev);
+       enable_percpu_irq(priv->intr_id, 0);
+}
+#endif
+
+
 static const struct net_device_ops tile_net_ops = {
        .ndo_open = tile_net_open,
        .ndo_stop = tile_net_stop,
@@ -2269,7 +2291,10 @@ static const struct net_device_ops tile_net_ops = {
        .ndo_get_stats = tile_net_get_stats,
        .ndo_change_mtu = tile_net_change_mtu,
        .ndo_tx_timeout = tile_net_tx_timeout,
-       .ndo_set_mac_address = tile_net_set_mac_address
+       .ndo_set_mac_address = tile_net_set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller = tile_net_netpoll,
+#endif
 };
 
 
@@ -2409,7 +2434,7 @@ static void tile_net_cleanup(void)
  */
 static int tile_net_init_module(void)
 {
-       pr_info("Tilera IPP Net Driver\n");
+       pr_info("Tilera Network Driver\n");
 
        tile_net_devs[0] = tile_net_dev_init("xgbe0");
        tile_net_devs[1] = tile_net_dev_init("xgbe1");
index 39b8cf3dafcdb9c20d1ed5bedddcfde684d65f3a..fcfa01f7ceb6983f649d14cf125d8e64d7319c86 100644 (file)
@@ -503,30 +503,32 @@ static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid);
 static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
 static void rhine_restart_tx(struct net_device *dev);
 
-static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool high)
+static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool low)
 {
        void __iomem *ioaddr = rp->base;
        int i;
 
        for (i = 0; i < 1024; i++) {
-               if (high ^ !!(ioread8(ioaddr + reg) & mask))
+               bool has_mask_bits = !!(ioread8(ioaddr + reg) & mask);
+
+               if (low ^ has_mask_bits)
                        break;
                udelay(10);
        }
        if (i > 64) {
                netif_dbg(rp, hw, rp->dev, "%s bit wait (%02x/%02x) cycle "
-                         "count: %04d\n", high ? "high" : "low", reg, mask, i);
+                         "count: %04d\n", low ? "low" : "high", reg, mask, i);
        }
 }
 
 static void rhine_wait_bit_high(struct rhine_private *rp, u8 reg, u8 mask)
 {
-       rhine_wait_bit(rp, reg, mask, true);
+       rhine_wait_bit(rp, reg, mask, false);
 }
 
 static void rhine_wait_bit_low(struct rhine_private *rp, u8 reg, u8 mask)
 {
-       rhine_wait_bit(rp, reg, mask, false);
+       rhine_wait_bit(rp, reg, mask, true);
 }
 
 static u32 rhine_get_events(struct rhine_private *rp)
index cc83af083fd7b7b17a650471436ca42e74f8fbe0..44b8d2bad8c3efd09a1d572d2ef7cf36f8d4a227 100644 (file)
@@ -2,9 +2,7 @@
  * Definitions for Xilinx Axi Ethernet device driver.
  *
  * Copyright (c) 2009 Secret Lab Technologies, Ltd.
- * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
- * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
- * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
  */
 
 #ifndef XILINX_AXIENET_H
index 2fcbeba6814bead15acdae0feff0e3e264c5656d..9c365e192a3197dc11267f37ce572985c12f274b 100644 (file)
@@ -4,9 +4,9 @@
  * Copyright (c) 2008 Nissin Systems Co., Ltd.,  Yoshio Kashiwagi
  * Copyright (c) 2005-2008 DLA Systems,  David H. Lynch Jr. <dhlii@dlasys.net>
  * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
- * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
- * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
- * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2010 - 2011 PetaLogix
+ * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
  *
  * This is a driver for the Xilinx Axi Ethernet which is used in the Virtex6
  * and Spartan6.
index d70b6e79f6c0cd4a9236a67a1dcd8b67f327aeb3..e90e1f46121ef2e0fcacc1a1b3ec5b198b2df94d 100644 (file)
@@ -2,9 +2,9 @@
  * MDIO bus driver for the Xilinx Axi Ethernet device
  *
  * Copyright (c) 2009 Secret Lab Technologies, Ltd.
- * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
- * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
- * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2010 - 2011 PetaLogix
+ * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
  */
 
 #include <linux/of_address.h>
index dd294783b5c5b77c3d48ecd14067921d9e90d4bb..2d59138db7f3fd688840d6bf5ce1f449838271be 100644 (file)
@@ -44,6 +44,7 @@ struct net_device_context {
        /* point back to our device context */
        struct hv_device *device_ctx;
        struct delayed_work dwork;
+       struct work_struct work;
 };
 
 
@@ -51,30 +52,22 @@ static int ring_size = 128;
 module_param(ring_size, int, S_IRUGO);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
 
-struct set_multicast_work {
-       struct work_struct work;
-       struct net_device *net;
-};
-
 static void do_set_multicast(struct work_struct *w)
 {
-       struct set_multicast_work *swk =
-               container_of(w, struct set_multicast_work, work);
-       struct net_device *net = swk->net;
-
-       struct net_device_context *ndevctx = netdev_priv(net);
+       struct net_device_context *ndevctx =
+               container_of(w, struct net_device_context, work);
        struct netvsc_device *nvdev;
        struct rndis_device *rdev;
 
        nvdev = hv_get_drvdata(ndevctx->device_ctx);
-       if (nvdev == NULL)
-               goto out;
+       if (nvdev == NULL || nvdev->ndev == NULL)
+               return;
 
        rdev = nvdev->extension;
        if (rdev == NULL)
-               goto out;
+               return;
 
-       if (net->flags & IFF_PROMISC)
+       if (nvdev->ndev->flags & IFF_PROMISC)
                rndis_filter_set_packet_filter(rdev,
                        NDIS_PACKET_TYPE_PROMISCUOUS);
        else
@@ -82,21 +75,13 @@ static void do_set_multicast(struct work_struct *w)
                        NDIS_PACKET_TYPE_BROADCAST |
                        NDIS_PACKET_TYPE_ALL_MULTICAST |
                        NDIS_PACKET_TYPE_DIRECTED);
-
-out:
-       kfree(w);
 }
 
 static void netvsc_set_multicast_list(struct net_device *net)
 {
-       struct set_multicast_work *swk =
-               kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC);
-       if (swk == NULL)
-               return;
+       struct net_device_context *net_device_ctx = netdev_priv(net);
 
-       swk->net = net;
-       INIT_WORK(&swk->work, do_set_multicast);
-       schedule_work(&swk->work);
+       schedule_work(&net_device_ctx->work);
 }
 
 static int netvsc_open(struct net_device *net)
@@ -125,6 +110,8 @@ static int netvsc_close(struct net_device *net)
 
        netif_tx_disable(net);
 
+       /* Make sure netvsc_set_multicast_list doesn't re-enable filter! */
+       cancel_work_sync(&net_device_ctx->work);
        ret = rndis_filter_close(device_obj);
        if (ret != 0)
                netdev_err(net, "unable to close device (ret %d).\n", ret);
@@ -335,6 +322,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
 
        nvdev->start_remove = true;
        cancel_delayed_work_sync(&ndevctx->dwork);
+       cancel_work_sync(&ndevctx->work);
        netif_tx_disable(ndev);
        rndis_filter_device_remove(hdev);
 
@@ -403,6 +391,7 @@ static int netvsc_probe(struct hv_device *dev,
        net_device_ctx->device_ctx = dev;
        hv_set_drvdata(dev, net);
        INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
+       INIT_WORK(&net_device_ctx->work, do_set_multicast);
 
        net->netdev_ops = &device_ops;
 
@@ -456,6 +445,7 @@ static int netvsc_remove(struct hv_device *dev)
 
        ndev_ctx = netdev_priv(net);
        cancel_delayed_work_sync(&ndev_ctx->dwork);
+       cancel_work_sync(&ndev_ctx->work);
 
        /* Stop outbound asap */
        netif_tx_disable(net);
index a0d1913a58d322afb07a23d458709a6ffe6a3eff..e25067552b209327763da3f381a41e85be5e22a2 100644 (file)
@@ -147,7 +147,7 @@ static void sa1100_irda_dma_start(struct sa1100_buf *buf,
        struct dma_async_tx_descriptor *desc;
        struct dma_chan *chan = buf->chan;
 
-       desc = chan->device->device_prep_slave_sg(chan, &buf->sg, 1, dir,
+       desc = dmaengine_prep_slave_sg(chan, &buf->sg, 1, dir,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
        if (desc) {
                desc->callback = cb;
index 0856e1b7a849ad5d6e32cf7fe91e4b5bee861e30..5ac46f5226f3c5b4b1d35e3450ec922326902896 100644 (file)
@@ -40,6 +40,7 @@ MODULE_LICENSE("GPL");
 #define IP1001_PHASE_SEL_MASK          3       /* IP1001 RX/TXPHASE_SEL */
 #define IP1001_APS_ON                  11      /* IP1001 APS Mode  bit */
 #define IP101A_G_APS_ON                        2       /* IP101A/G APS Mode bit */
+#define IP101A_G_IRQ_CONF_STATUS       0x11    /* Conf Info IRQ & Status Reg */
 
 static int ip175c_config_init(struct phy_device *phydev)
 {
@@ -162,7 +163,8 @@ static int ip101a_g_config_init(struct phy_device *phydev)
        /* Enable Auto Power Saving mode */
        c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
        c |= IP101A_G_APS_ON;
-       return c;
+
+       return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
 }
 
 static int ip175c_read_status(struct phy_device *phydev)
@@ -184,6 +186,15 @@ static int ip175c_config_aneg(struct phy_device *phydev)
        return 0;
 }
 
+static int ip101a_g_ack_interrupt(struct phy_device *phydev)
+{
+       int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
 static struct phy_driver ip175c_driver = {
        .phy_id         = 0x02430d80,
        .name           = "ICPlus IP175C",
@@ -203,7 +214,6 @@ static struct phy_driver ip1001_driver = {
        .phy_id_mask    = 0x0ffffff0,
        .features       = PHY_GBIT_FEATURES | SUPPORTED_Pause |
                          SUPPORTED_Asym_Pause,
-       .flags          = PHY_HAS_INTERRUPT,
        .config_init    = &ip1001_config_init,
        .config_aneg    = &genphy_config_aneg,
        .read_status    = &genphy_read_status,
@@ -219,6 +229,7 @@ static struct phy_driver ip101a_g_driver = {
        .features       = PHY_BASIC_FEATURES | SUPPORTED_Pause |
                          SUPPORTED_Asym_Pause,
        .flags          = PHY_HAS_INTERRUPT,
+       .ack_interrupt  = ip101a_g_ack_interrupt,
        .config_init    = &ip101a_g_config_init,
        .config_aneg    = &genphy_config_aneg,
        .read_status    = &genphy_read_status,
index 159da2905fe979dbdf03a4c065b72ed75ea9592c..21d7151fb0ab3ea03c93208cf6d0c2749d1b825b 100644 (file)
@@ -968,7 +968,6 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
        proto = npindex_to_proto[npi];
        put_unaligned_be16(proto, pp);
 
-       netif_stop_queue(dev);
        skb_queue_tail(&ppp->file.xq, skb);
        ppp_xmit_process(ppp);
        return NETDEV_TX_OK;
@@ -1063,6 +1062,8 @@ ppp_xmit_process(struct ppp *ppp)
                   code that we can accept some more. */
                if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq))
                        netif_wake_queue(ppp->dev);
+               else
+                       netif_stop_queue(ppp->dev);
        }
        ppp_xmit_unlock(ppp);
 }
index a57f05726b5785a6d8ba7646fb3068c438869082..91d25888a1b98b136b6ec3704a58630d5f9b085c 100644 (file)
@@ -375,8 +375,8 @@ static void rionet_remove(struct rio_dev *rdev)
        struct net_device *ndev = rio_get_drvdata(rdev);
        struct rionet_peer *peer, *tmp;
 
-       free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
-                                       __fls(sizeof(void *)) + 4 : 0);
+       free_pages((unsigned long)rionet_active, get_order(sizeof(void *) *
+                       RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size)));
        unregister_netdev(ndev);
        free_netdev(ndev);
 
@@ -432,15 +432,16 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
        int rc = 0;
        struct rionet_private *rnet;
        u16 device_id;
+       const size_t rionet_active_bytes = sizeof(void *) *
+                               RIO_MAX_ROUTE_ENTRIES(mport->sys_size);
 
        rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
-                       mport->sys_size ? __fls(sizeof(void *)) + 4 : 0);
+                       get_order(rionet_active_bytes));
        if (!rionet_active) {
                rc = -ENOMEM;
                goto out;
        }
-       memset((void *)rionet_active, 0, sizeof(void *) *
-                               RIO_MAX_ROUTE_ENTRIES(mport->sys_size));
+       memset((void *)rionet_active, 0, rionet_active_bytes);
 
        /* Set up private area */
        rnet = netdev_priv(ndev);
index 5ee032cafadea0f8405f4d8f66cb356eec236262..42b5151aa78ae8523b27493394ba87e9900338a5 100644 (file)
@@ -355,7 +355,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
        u32 packet_len;
        u32 padbytes = 0xffff0000;
 
-       padlen = ((skb->len + 4) % 512) ? 0 : 4;
+       padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4;
 
        if ((!skb_cloned(skb)) &&
            ((headroom + tailroom) >= (4 + padlen))) {
@@ -377,7 +377,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
        cpu_to_le32s(&packet_len);
        skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
 
-       if ((skb->len % 512) == 0) {
+       if (padlen) {
                cpu_to_le32s(&padbytes);
                memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
                skb_put(skb, sizeof(padbytes));
index 3886b30ed37355394e6155f60bb7e559e598391e..3e41b00c6806c6b88020a0a441aee979d5c21637 100644 (file)
@@ -165,13 +165,13 @@ static void rx_complete(struct urb *req)
                                memcpy(skb_put(skb, 1), page_address(page), 1);
                                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
                                                page, 1, req->actual_length,
-                                               req->actual_length);
+                                               PAGE_SIZE);
                                page = NULL;
                        }
                } else {
                        skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
                                        page, 0, req->actual_length,
-                                       req->actual_length);
+                                       PAGE_SIZE);
                        page = NULL;
                }
                if (req->actual_length < PAGE_SIZE)
index 439690be519feba0975c7eccf162016d2040472c..685a4e22c768e4bbe4c7e4f64348dd548b397507 100644 (file)
@@ -93,6 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
        /* no jumbogram (16K) support for now */
 
        dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+       dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
 
        return 0;
 }
index 552d24bf862e124cdae480ed301418469053ccdd..d316503b35d477c3d0338c2ceeb8ba1cc5b107cf 100644 (file)
@@ -365,6 +365,27 @@ static const struct driver_info    qmi_wwan_force_int4 = {
        .data           = BIT(4), /* interface whitelist bitmap */
 };
 
+/* Sierra Wireless provide equally useless interface descriptors
+ * Devices in QMI mode can be switched between two different
+ * configurations:
+ *   a) USB interface #8 is QMI/wwan
+ *   b) USB interfaces #8, #19 and #20 are QMI/wwan
+ *
+ * Both configurations provide a number of other interfaces (serial++),
+ * some of which have the same endpoint configuration as we expect, so
+ * a whitelist or blacklist is necessary.
+ *
+ * FIXME: The below whitelist should include BIT(20).  It does not
+ * because I cannot get it to work...
+ */
+static const struct driver_info        qmi_wwan_sierra = {
+       .description    = "Sierra Wireless wwan/QMI device",
+       .flags          = FLAG_WWAN,
+       .bind           = qmi_wwan_bind_gobi,
+       .unbind         = qmi_wwan_unbind_shared,
+       .manage_power   = qmi_wwan_manage_power,
+       .data           = BIT(8) | BIT(19), /* interface whitelist bitmap */
+};
 
 #define HUAWEI_VENDOR_ID       0x12D1
 #define QMI_GOBI_DEVICE(vend, prod) \
@@ -445,6 +466,15 @@ static const struct usb_device_id products[] = {
                .bInterfaceProtocol = 0xff,
                .driver_info        = (unsigned long)&qmi_wwan_force_int4,
        },
+       {       /* Sierra Wireless MC77xx in QMI mode */
+               .match_flags        = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+               .idVendor           = 0x1199,
+               .idProduct          = 0x68a2,
+               .bInterfaceClass    = 0xff,
+               .bInterfaceSubClass = 0xff,
+               .bInterfaceProtocol = 0xff,
+               .driver_info        = (unsigned long)&qmi_wwan_sierra,
+       },
        {QMI_GOBI_DEVICE(0x05c6, 0x9212)},      /* Acer Gobi Modem Device */
        {QMI_GOBI_DEVICE(0x03f0, 0x1f1d)},      /* HP un2400 Gobi Modem Device */
        {QMI_GOBI_DEVICE(0x03f0, 0x371d)},      /* HP un2430 Mobile Broadband Module */
index 6dda2fe5b15bcd00f3d6cde0a30f6e321075154f..d363b31053da13e667dc9793026041353ef1c3bb 100644 (file)
 #define        RTL8150_REQ_SET_REGS    0x05
 
 
-/* Transmit status register errors */
-#define TSR_ECOL               (1<<5)
-#define TSR_LCOL               (1<<4)
-#define TSR_LOSS_CRS           (1<<3)
-#define TSR_JBR                        (1<<2)
-#define TSR_ERRORS             (TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR)
-/* Receive status register errors */
-#define RSR_CRC                        (1<<2)
-#define RSR_FAE                        (1<<1)
-#define RSR_ERRORS             (RSR_CRC | RSR_FAE)
-
-/* Media status register definitions */
-#define MSR_DUPLEX             (1<<4)
-#define MSR_SPEED              (1<<3)
-#define MSR_LINK               (1<<2)
-
-/* Interrupt pipe data */
-#define INT_TSR                        0x00
-#define INT_RSR                        0x01
-#define INT_MSR                        0x02
-#define INT_WAKSR              0x03
-#define INT_TXOK_CNT           0x04
-#define INT_RXLOST_CNT         0x05
-#define INT_CRERR_CNT          0x06
-#define INT_COL_CNT            0x07
-
 /* Transmit status register errors */
 #define TSR_ECOL               (1<<5)
 #define TSR_LCOL               (1<<4)
index 187d01ccb97367099b04ce40f8b44fe2824293d5..00103a8c5e04d69e17408d32f139c9bee93aa03c 100644 (file)
@@ -98,7 +98,7 @@ static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
 
        if (unlikely(ret < 0))
                netdev_warn(dev->net,
-                       "Failed to read register index 0x%08x", index);
+                       "Failed to read reg index 0x%08x: %d", index, ret);
 
        le32_to_cpus(buf);
        *data = *buf;
@@ -128,7 +128,7 @@ static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
 
        if (unlikely(ret < 0))
                netdev_warn(dev->net,
-                       "Failed to write register index 0x%08x", index);
+                       "Failed to write reg index 0x%08x: %d", index, ret);
 
        kfree(buf);
 
@@ -171,7 +171,7 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
        idx &= dev->mii.reg_num_mask;
        addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
                | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
-               | MII_ACCESS_READ;
+               | MII_ACCESS_READ | MII_ACCESS_BUSY;
        ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
        check_warn_goto_done(ret, "Error writing MII_ACCESS");
 
@@ -210,7 +210,7 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
        idx &= dev->mii.reg_num_mask;
        addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
                | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
-               | MII_ACCESS_WRITE;
+               | MII_ACCESS_WRITE | MII_ACCESS_BUSY;
        ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
        check_warn_goto_done(ret, "Error writing MII_ACCESS");
 
@@ -508,9 +508,10 @@ static int smsc75xx_link_reset(struct usbnet *dev)
        u16 lcladv, rmtadv;
        int ret;
 
-       /* clear interrupt status */
+       /* read and write to clear phy interrupt status */
        ret = smsc75xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
        check_warn_return(ret, "Error reading PHY_INT_SRC");
+       smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC, 0xffff);
 
        ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
        check_warn_return(ret, "Error writing INT_STS");
@@ -643,7 +644,7 @@ static int smsc75xx_set_mac_address(struct usbnet *dev)
 
 static int smsc75xx_phy_initialize(struct usbnet *dev)
 {
-       int bmcr, timeout = 0;
+       int bmcr, ret, timeout = 0;
 
        /* Initialize MII structure */
        dev->mii.dev = dev->net;
@@ -651,6 +652,7 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
        dev->mii.mdio_write = smsc75xx_mdio_write;
        dev->mii.phy_id_mask = 0x1f;
        dev->mii.reg_num_mask = 0x1f;
+       dev->mii.supports_gmii = 1;
        dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID;
 
        /* reset phy and wait for reset to complete */
@@ -661,7 +663,7 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
                bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
                check_warn_return(bmcr, "Error reading MII_BMCR");
                timeout++;
-       } while ((bmcr & MII_BMCR) && (timeout < 100));
+       } while ((bmcr & BMCR_RESET) && (timeout < 100));
 
        if (timeout >= 100) {
                netdev_warn(dev->net, "timeout on PHY Reset");
@@ -671,10 +673,13 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
        smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
                ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
                ADVERTISE_PAUSE_ASYM);
+       smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
+               ADVERTISE_1000FULL);
 
-       /* read to clear */
-       smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
-       check_warn_return(bmcr, "Error reading PHY_INT_SRC");
+       /* read and write to clear phy interrupt status */
+       ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
+       check_warn_return(ret, "Error reading PHY_INT_SRC");
+       smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff);
 
        smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
                PHY_INT_MASK_DEFAULT);
@@ -946,6 +951,14 @@ static int smsc75xx_reset(struct usbnet *dev)
        ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf);
        check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret);
 
+       /* allow mac to detect speed and duplex from phy */
+       ret = smsc75xx_read_reg(dev, MAC_CR, &buf);
+       check_warn_return(ret, "Failed to read MAC_CR: %d", ret);
+
+       buf |= (MAC_CR_ADD | MAC_CR_ASD);
+       ret = smsc75xx_write_reg(dev, MAC_CR, buf);
+       check_warn_return(ret, "Failed to write MAC_CR: %d", ret);
+
        ret = smsc75xx_read_reg(dev, MAC_TX, &buf);
        check_warn_return(ret, "Failed to read MAC_TX: %d", ret);
 
@@ -1051,6 +1064,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
        dev->net->flags |= IFF_MULTICAST;
        dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
+       dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
        return 0;
 }
 
@@ -1211,7 +1225,7 @@ static const struct driver_info smsc75xx_info = {
        .rx_fixup       = smsc75xx_rx_fixup,
        .tx_fixup       = smsc75xx_tx_fixup,
        .status         = smsc75xx_status,
-       .flags          = FLAG_ETHER | FLAG_SEND_ZLP,
+       .flags          = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
 };
 
 static const struct usb_device_id products[] = {
index 5f19f84d3494696254793320cda6a1f132a0e6e1..94ae66999f592a4a8a1c45fdc24505050271d086 100644 (file)
@@ -1017,6 +1017,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
        dev->net->flags |= IFF_MULTICAST;
        dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM;
+       dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
        return 0;
 }
 
@@ -1191,7 +1192,7 @@ static const struct driver_info smsc95xx_info = {
        .rx_fixup       = smsc95xx_rx_fixup,
        .tx_fixup       = smsc95xx_tx_fixup,
        .status         = smsc95xx_status,
-       .flags          = FLAG_ETHER | FLAG_SEND_ZLP,
+       .flags          = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
 };
 
 static const struct usb_device_id products[] = {
index b7b3f5b0d40654c3c50b18ae56c969c03382c71c..2d927fb4adf4ea6805b2aeb02d06c8cb5108f496 100644 (file)
@@ -210,6 +210,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
                } else {
                        usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
                                buf, maxp, intr_complete, dev, period);
+                       dev->interrupt->transfer_flags |= URB_FREE_BUFFER;
                        dev_dbg(&intf->dev,
                                "status ep%din, %d bytes period %d\n",
                                usb_pipeendpoint(pipe), maxp, period);
@@ -1443,7 +1444,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 
        status = register_netdev (net);
        if (status)
-               goto out3;
+               goto out4;
        netif_info(dev, probe, dev->net,
                   "register '%s' at usb-%s-%s, %s, %pM\n",
                   udev->dev.driver->name,
@@ -1461,6 +1462,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 
        return 0;
 
+out4:
+       usb_free_urb(dev->interrupt);
 out3:
        if (info->unbind)
                info->unbind (dev, udev);
index c3197ce0e2ad33be4e23358f4c3a25f74caffff8..34db195fb8b00880bbc6f42d9d1837bbce67c601 100644 (file)
@@ -337,6 +337,11 @@ static const struct usb_device_id  products [] = {
        .driver_info = ZAURUS_PXA_INFO,
 },
 {
+       /* Motorola Rokr E6 */
+       USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+       .driver_info = (unsigned long) &bogus_mdlm_info,
+}, {
        /* Motorola MOTOMAGX phones */
        USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
index 019da012669fe724ecb0bf37f31df7da10c7df2f..af8acc85f4bbd15bf01e939db20932845d7b8312 100644 (file)
@@ -625,16 +625,16 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* This can happen with OOM and indirect buffers. */
        if (unlikely(capacity < 0)) {
-               if (net_ratelimit()) {
-                       if (likely(capacity == -ENOMEM)) {
+               if (likely(capacity == -ENOMEM)) {
+                       if (net_ratelimit())
                                dev_warn(&dev->dev,
                                         "TX queue failure: out of memory\n");
-                       } else {
-                               dev->stats.tx_fifo_errors++;
+               } else {
+                       dev->stats.tx_fifo_errors++;
+                       if (net_ratelimit())
                                dev_warn(&dev->dev,
                                         "Unexpected TX queue failure: %d\n",
                                         capacity);
-                       }
                }
                dev->stats.tx_dropped++;
                kfree_skb(skb);
index ebb9f24eefb5e568f90b859e2b3e47028a868a70..1a623183cbe54d63f8392f924953b127ded83c1f 100644 (file)
@@ -2483,6 +2483,7 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                pr_err("Control memory remap failed\n");
                pci_release_regions(pdev);
                pci_disable_device(pdev);
+               iounmap(card->mem);
                kfree(card);
                return -ENODEV;
        }
index 129ba36bd04d6a52c205aa60c44d042c2003401b..4b66ab1d0e5cf8f9e0fb9511c145e0049585172f 100644 (file)
@@ -53,17 +53,6 @@ struct dentry *debugfs_create_netdev_queue_stopped(
                                   &fops_netdev_queue_stopped);
 }
 
-
-/*
- * inode->i_private has the @data argument to debugfs_create_file()
- */
-static
-int i2400m_stats_open(struct inode *inode, struct file *filp)
-{
-       filp->private_data = inode->i_private;
-       return 0;
-}
-
 /*
  * We don't allow partial reads of this file, as then the reader would
  * get weirdly confused data as it is updated.
@@ -117,7 +106,7 @@ ssize_t i2400m_rx_stats_write(struct file *filp, const char __user *buffer,
 static
 const struct file_operations i2400m_rx_stats_fops = {
        .owner =        THIS_MODULE,
-       .open =         i2400m_stats_open,
+       .open =         simple_open,
        .read =         i2400m_rx_stats_read,
        .write =        i2400m_rx_stats_write,
        .llseek =       default_llseek,
@@ -170,7 +159,7 @@ ssize_t i2400m_tx_stats_write(struct file *filp, const char __user *buffer,
 static
 const struct file_operations i2400m_tx_stats_fops = {
        .owner =        THIS_MODULE,
-       .open =         i2400m_stats_open,
+       .open =         simple_open,
        .read =         i2400m_tx_stats_read,
        .write =        i2400m_tx_stats_write,
        .llseek =       default_llseek,
index 63e4b709efa956b100626e3fc56bd248f4a7828f..1d76ae855f077dd5d3dbb7230d392ecc7c0b3c68 100644 (file)
@@ -597,7 +597,8 @@ static void i2400m_get_drvinfo(struct net_device *net_dev,
        struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
 
        strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1);
-       strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1);
+       strncpy(info->fw_version,
+               i2400m->fw_name ? : "", sizeof(info->fw_version) - 1);
        if (net_dev->dev.parent)
                strncpy(info->bus_info, dev_name(net_dev->dev.parent),
                        sizeof(info->bus_info) - 1);
index 2c1b8b687646eedb0ac795a706c34cc32fa5ab29..29b1e033a10b51c3e23bf01905a2887e3b73041e 100644 (file)
@@ -339,6 +339,23 @@ int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
        return result;
 }
 
+static void i2400mu_get_drvinfo(struct net_device *net_dev,
+                                struct ethtool_drvinfo *info)
+{
+       struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
+       struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+       struct usb_device *udev = i2400mu->usb_dev;
+
+       strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1);
+       strncpy(info->fw_version,
+               i2400m->fw_name ? : "", sizeof(info->fw_version) - 1);
+       usb_make_path(udev, info->bus_info, sizeof(info->bus_info));
+}
+
+static const struct ethtool_ops i2400mu_ethtool_ops = {
+       .get_drvinfo = i2400mu_get_drvinfo,
+       .get_link = ethtool_op_get_link,
+};
 
 static
 void i2400mu_netdev_setup(struct net_device *net_dev)
@@ -347,6 +364,7 @@ void i2400mu_netdev_setup(struct net_device *net_dev)
        struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
        i2400mu_init(i2400mu);
        i2400m_netdev_setup(net_dev);
+       net_dev->ethtool_ops = &i2400mu_ethtool_ops;
 }
 
 
index 8faa129da5a00b60c74dd255ae1692effb3d329d..aec33cc207fdbba47e67a6aa28a52ac19f4bfede 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <ar231x_platform.h>
 #include "ath5k.h"
 #include "debug.h"
@@ -119,7 +120,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
        if (res == NULL) {
                dev_err(&pdev->dev, "no IRQ resource found\n");
                ret = -ENXIO;
-               goto err_out;
+               goto err_iounmap;
        }
 
        irq = res->start;
@@ -128,7 +129,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
        if (hw == NULL) {
                dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
                ret = -ENOMEM;
-               goto err_out;
+               goto err_iounmap;
        }
 
        ah = hw->priv;
@@ -185,6 +186,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
  err_free_hw:
        ieee80211_free_hw(hw);
        platform_set_drvdata(pdev, NULL);
+ err_iounmap:
+        iounmap(mem);
  err_out:
        return ret;
 }
@@ -217,6 +220,7 @@ static int ath_ahb_remove(struct platform_device *pdev)
        }
 
        ath5k_deinit_ah(ah);
+       iounmap(ah->iobase);
        platform_set_drvdata(pdev, NULL);
        ieee80211_free_hw(hw);
 
index 8c5ce8b0c7346873a64c6ee9e8f358a2d5a565c6..e5e8f45d86acdb6c74faf067465e783bae96cf0e 100644 (file)
@@ -71,13 +71,6 @@ static unsigned int ath5k_debug;
 module_param_named(debug, ath5k_debug, uint, 0);
 
 
-static int ath5k_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
-
 /* debugfs: registers */
 
 struct reg {
@@ -265,7 +258,7 @@ static ssize_t write_file_beacon(struct file *file,
 static const struct file_operations fops_beacon = {
        .read = read_file_beacon,
        .write = write_file_beacon,
-       .open = ath5k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -285,7 +278,7 @@ static ssize_t write_file_reset(struct file *file,
 
 static const struct file_operations fops_reset = {
        .write = write_file_reset,
-       .open = ath5k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = noop_llseek,
 };
@@ -365,7 +358,7 @@ static ssize_t write_file_debug(struct file *file,
 static const struct file_operations fops_debug = {
        .read = read_file_debug,
        .write = write_file_debug,
-       .open = ath5k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -477,7 +470,7 @@ static ssize_t write_file_antenna(struct file *file,
 static const struct file_operations fops_antenna = {
        .read = read_file_antenna,
        .write = write_file_antenna,
-       .open = ath5k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -532,7 +525,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_misc = {
        .read = read_file_misc,
-       .open = ath5k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
 };
 
@@ -647,7 +640,7 @@ static ssize_t write_file_frameerrors(struct file *file,
 static const struct file_operations fops_frameerrors = {
        .read = read_file_frameerrors,
        .write = write_file_frameerrors,
-       .open = ath5k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -810,7 +803,7 @@ static ssize_t write_file_ani(struct file *file,
 static const struct file_operations fops_ani = {
        .read = read_file_ani,
        .write = write_file_ani,
-       .open = ath5k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -881,7 +874,7 @@ static ssize_t write_file_queue(struct file *file,
 static const struct file_operations fops_queue = {
        .read = read_file_queue,
        .write = write_file_queue,
-       .open = ath5k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
index 552adb3f80d07e85d963e65447096dae4233eaf2..d01403a263ff66b935e70fcc04f23d2f971b0a10 100644 (file)
@@ -217,12 +217,6 @@ void dump_cred_dist_stats(struct htc_target *target)
                   target->credit_info->cur_free_credits);
 }
 
-static int ath6kl_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
 {
        switch (war) {
@@ -263,7 +257,7 @@ static ssize_t read_file_war_stats(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_war_stats = {
        .read = read_file_war_stats,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -488,7 +482,7 @@ static ssize_t ath6kl_fwlog_mask_write(struct file *file,
 }
 
 static const struct file_operations fops_fwlog_mask = {
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .read = ath6kl_fwlog_mask_read,
        .write = ath6kl_fwlog_mask_write,
        .owner = THIS_MODULE,
@@ -634,7 +628,7 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_tgt_stats = {
        .read = read_file_tgt_stats,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -699,7 +693,7 @@ static ssize_t read_file_credit_dist_stats(struct file *file,
 
 static const struct file_operations fops_credit_dist_stats = {
        .read = read_file_credit_dist_stats,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -802,7 +796,7 @@ static ssize_t ath6kl_endpoint_stats_write(struct file *file,
 }
 
 static const struct file_operations fops_endpoint_stats = {
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .read = ath6kl_endpoint_stats_read,
        .write = ath6kl_endpoint_stats_write,
        .owner = THIS_MODULE,
@@ -875,7 +869,7 @@ static ssize_t ath6kl_regread_write(struct file *file,
 static const struct file_operations fops_diag_reg_read = {
        .read = ath6kl_regread_read,
        .write = ath6kl_regread_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -999,7 +993,7 @@ static ssize_t ath6kl_lrssi_roam_read(struct file *file,
 static const struct file_operations fops_lrssi_roam_threshold = {
        .read = ath6kl_lrssi_roam_read,
        .write = ath6kl_lrssi_roam_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1061,7 +1055,7 @@ static ssize_t ath6kl_regwrite_write(struct file *file,
 static const struct file_operations fops_diag_reg_write = {
        .read = ath6kl_regwrite_read,
        .write = ath6kl_regwrite_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1166,7 +1160,7 @@ static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_roam_table = {
        .read = ath6kl_roam_table_read,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1204,7 +1198,7 @@ static ssize_t ath6kl_force_roam_write(struct file *file,
 
 static const struct file_operations fops_force_roam = {
        .write = ath6kl_force_roam_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1244,7 +1238,7 @@ static ssize_t ath6kl_roam_mode_write(struct file *file,
 
 static const struct file_operations fops_roam_mode = {
        .write = ath6kl_roam_mode_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1286,7 +1280,7 @@ static ssize_t ath6kl_keepalive_write(struct file *file,
 }
 
 static const struct file_operations fops_keepalive = {
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .read = ath6kl_keepalive_read,
        .write = ath6kl_keepalive_write,
        .owner = THIS_MODULE,
@@ -1331,7 +1325,7 @@ static ssize_t ath6kl_disconnect_timeout_write(struct file *file,
 }
 
 static const struct file_operations fops_disconnect_timeout = {
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .read = ath6kl_disconnect_timeout_read,
        .write = ath6kl_disconnect_timeout_write,
        .owner = THIS_MODULE,
@@ -1512,7 +1506,7 @@ static ssize_t ath6kl_create_qos_write(struct file *file,
 
 static const struct file_operations fops_create_qos = {
        .write = ath6kl_create_qos_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1560,7 +1554,7 @@ static ssize_t ath6kl_delete_qos_write(struct file *file,
 
 static const struct file_operations fops_delete_qos = {
        .write = ath6kl_delete_qos_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1593,7 +1587,7 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file,
 
 static const struct file_operations fops_bgscan_int = {
        .write = ath6kl_bgscan_int_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1651,7 +1645,7 @@ static ssize_t ath6kl_listen_int_read(struct file *file,
 static const struct file_operations fops_listen_int = {
        .read = ath6kl_listen_int_read,
        .write = ath6kl_listen_int_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1711,7 +1705,7 @@ static ssize_t ath6kl_power_params_write(struct file *file,
 
 static const struct file_operations fops_power_params = {
        .write = ath6kl_power_params_write,
-       .open = ath6kl_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
index d7d8e91991408a7a5c18fea055a4f17f1a0741cf..aba088005b2274a43873f277993113ec59cca45e 100644 (file)
@@ -869,7 +869,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
        ar5008_hw_set_channel_regs(ah, chan);
        ar5008_hw_init_chain_masks(ah);
        ath9k_olc_init(ah);
-       ath9k_hw_apply_txpower(ah, chan);
+       ath9k_hw_apply_txpower(ah, chan, false);
 
        /* Write analog registers */
        if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
index 59647a3ceb7f98ea568d34e16248c80471290f78..3d400e8d653544ffd16bc3db8710f075598dce2f 100644 (file)
@@ -54,7 +54,7 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
 
        if (val) {
                ah->paprd_table_write_done = true;
-               ath9k_hw_apply_txpower(ah, chan);
+               ath9k_hw_apply_txpower(ah, chan, false);
        }
 
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
index bc992b237ae5a47a42f53db6b59a5cd5a59cf94d..deb6cfb2959a7344886bb7e10799feb3a5106de0 100644 (file)
@@ -694,7 +694,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
        ar9003_hw_override_ini(ah);
        ar9003_hw_set_channel_regs(ah, chan);
        ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
-       ath9k_hw_apply_txpower(ah, chan);
+       ath9k_hw_apply_txpower(ah, chan, false);
 
        if (AR_SREV_9462(ah)) {
                if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
index 2f4b48e6fb036648af5eb1cdf35bd217b97dc67f..e5cceb0775749661360e4aef376d8eb05c4615a7 100644 (file)
@@ -20,7 +20,6 @@
 
 /* Common calibration code */
 
-#define ATH9K_NF_TOO_HIGH      -60
 
 static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
 {
@@ -346,10 +345,10 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
                        "NF calibrated [%s] [chain %d] is %d\n",
                        (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
 
-               if (nf[i] > ATH9K_NF_TOO_HIGH) {
+               if (nf[i] > limit->max) {
                        ath_dbg(common, CALIBRATE,
                                "NF[%d] (%d) > MAX (%d), correcting to MAX\n",
-                               i, nf[i], ATH9K_NF_TOO_HIGH);
+                               i, nf[i], limit->max);
                        nf[i] = limit->max;
                } else if (nf[i] < limit->min) {
                        ath_dbg(common, CALIBRATE,
index 35d1c8e91d1c161140ec1513b5f0eaff0114f474..ff47b32ecaf483fd87b99bf89dbc75fe6e325fcd 100644 (file)
 #define REG_READ_D(_ah, _reg) \
        ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
 
-static int ath9k_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
 
 static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf,
                                      size_t count, loff_t *ppos)
@@ -83,7 +78,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
 static const struct file_operations fops_debug = {
        .read = read_file_debug,
        .write = write_file_debug,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -129,7 +124,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
 static const struct file_operations fops_tx_chainmask = {
        .read = read_file_tx_chainmask,
        .write = write_file_tx_chainmask,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -172,7 +167,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
 static const struct file_operations fops_rx_chainmask = {
        .read = read_file_rx_chainmask,
        .write = write_file_rx_chainmask,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -223,7 +218,7 @@ static ssize_t write_file_disable_ani(struct file *file,
 static const struct file_operations fops_disable_ani = {
        .read = read_file_disable_ani,
        .write = write_file_disable_ani,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -324,7 +319,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_dma = {
        .read = read_file_dma,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -446,7 +441,7 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_interrupt = {
        .read = read_file_interrupt,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -852,28 +847,28 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
 
 static const struct file_operations fops_xmit = {
        .read = read_file_xmit,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
 
 static const struct file_operations fops_stations = {
        .read = read_file_stations,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
 
 static const struct file_operations fops_misc = {
        .read = read_file_misc,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
 
 static const struct file_operations fops_reset = {
        .read = read_file_reset,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1016,7 +1011,7 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
 
 static const struct file_operations fops_recv = {
        .read = read_file_recv,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1055,7 +1050,7 @@ static ssize_t write_file_regidx(struct file *file, const char __user *user_buf,
 static const struct file_operations fops_regidx = {
        .read = read_file_regidx,
        .write = write_file_regidx,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1102,7 +1097,7 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf,
 static const struct file_operations fops_regval = {
        .read = read_file_regval,
        .write = write_file_regval,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1191,7 +1186,7 @@ static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_dump_nfcal = {
        .read = read_file_dump_nfcal,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1219,7 +1214,7 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_base_eeprom = {
        .read = read_file_base_eeprom,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1247,7 +1242,7 @@ static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_modal_eeprom = {
        .read = read_file_modal_eeprom,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
index 106d031d834a9aacef8f4b2f6c0ff8a81a707914..4364c103ed33df2de9e54c4254c82e6e2ec87fec 100644 (file)
@@ -60,16 +60,9 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
        return retval;
 }
 
-static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-
-       return 0;
-}
-
 static const struct file_operations fops_dfs_stats = {
        .read = read_file_dfs,
-       .open = ath9k_dfs_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
index f272236d8053d58201b973b6397b11362a112bb1..b34e8b2990b127a359b88991af37687307fbcf60 100644 (file)
@@ -824,6 +824,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
                        regulatory->max_power_level = ratesArray[i];
        }
 
+       ath9k_hw_update_regulatory_maxpower(ah);
+
        if (test)
                return;
 
index d3ff33c71aa5bbd2074d4d64c2a92c41ab144c91..3035deb7a0cdcd5343c09733942bf0d56e5886a8 100644 (file)
 
 #include "htc.h"
 
-static int ath9k_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf,
                                       size_t count, loff_t *ppos)
 {
@@ -75,7 +69,7 @@ static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_tgt_int_stats = {
        .read = read_file_tgt_int_stats,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -145,7 +139,7 @@ static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_tgt_tx_stats = {
        .read = read_file_tgt_tx_stats,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -191,7 +185,7 @@ static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_tgt_rx_stats = {
        .read = read_file_tgt_rx_stats,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -243,7 +237,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_xmit = {
        .read = read_file_xmit,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -364,7 +358,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_recv = {
        .read = read_file_recv,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -399,7 +393,7 @@ static ssize_t read_file_slot(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_slot = {
        .read = read_file_slot,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -446,7 +440,7 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_queue = {
        .read = read_file_queue,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -487,7 +481,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
 static const struct file_operations fops_debug = {
        .read = read_file_debug,
        .write = write_file_debug,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -636,7 +630,7 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_base_eeprom = {
        .read = read_file_base_eeprom,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -917,7 +911,7 @@ static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_modal_eeprom = {
        .read = read_file_modal_eeprom,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
index 6c69e4e8b1cb7ca85b6710aecb8fbe3cba1e10c9..fa84e37bf091546035c6638130892a5bbe559c66 100644 (file)
@@ -1454,7 +1454,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
                return false;
        }
        ath9k_hw_set_clockrate(ah);
-       ath9k_hw_apply_txpower(ah, chan);
+       ath9k_hw_apply_txpower(ah, chan, false);
        ath9k_hw_rfbus_done(ah);
 
        if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
@@ -2652,7 +2652,8 @@ static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
        return ah->eep_ops->get_eeprom(ah, gain_param);
 }
 
-void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
+                           bool test)
 {
        struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
        struct ieee80211_channel *channel;
@@ -2673,7 +2674,7 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
 
        ah->eep_ops->set_txpower(ah, chan,
                                 ath9k_regd_get_ctl(reg, chan),
-                                ant_reduction, new_pwr, false);
+                                ant_reduction, new_pwr, test);
 }
 
 void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
@@ -2686,7 +2687,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
        if (test)
                channel->max_power = MAX_RATE_POWER / 2;
 
-       ath9k_hw_apply_txpower(ah, chan);
+       ath9k_hw_apply_txpower(ah, chan, test);
 
        if (test)
                channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
index aa1680a0c7fdbeccd4ba36a7be8733b5a1a0ed4c..e88f182ff45c1b36b88cd8eda93af3d335b0a0e2 100644 (file)
@@ -985,7 +985,8 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
 /* PHY */
 void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
                                   u32 *coef_mantissa, u32 *coef_exponent);
-void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
+                           bool test);
 
 /*
  * Code Specific to AR5008, AR9001 or AR9002,
index 60159f4ee532aa97e2fb76d5b75b0ad8040773b6..cb006458fc4b62400a7f68e1778982c011eb6c79 100644 (file)
@@ -680,7 +680,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->queues = 4;
        hw->max_rates = 4;
        hw->channel_change_time = 5000;
-       hw->max_listen_interval = 10;
+       hw->max_listen_interval = 1;
        hw->max_rate_tries = 10;
        hw->sta_data_size = sizeof(struct ath_node);
        hw->vif_data_size = sizeof(struct ath_vif);
index 38794850f005a52ab7987c9a95f52d87adb9470d..798ea57252b403d11823aaec9582e6df0122b5a3 100644 (file)
@@ -118,15 +118,13 @@ void ath9k_ps_restore(struct ath_softc *sc)
        if (--sc->ps_usecount != 0)
                goto unlock;
 
-       if (sc->ps_flags & PS_WAIT_FOR_TX_ACK)
-               goto unlock;
-
-       if (sc->ps_idle)
+       if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
                mode = ATH9K_PM_FULL_SLEEP;
        else if (sc->ps_enabled &&
                 !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
                              PS_WAIT_FOR_CAB |
-                             PS_WAIT_FOR_PSPOLL_DATA)))
+                             PS_WAIT_FOR_PSPOLL_DATA |
+                             PS_WAIT_FOR_TX_ACK)))
                mode = ATH9K_PM_NETWORK_SLEEP;
        else
                goto unlock;
@@ -640,7 +638,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
        an->sta = sta;
        an->vif = vif;
 
-       if (sta->ht_cap.ht_supported) {
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
                ath_tx_node_init(sc, an);
                an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
                                     sta->ht_cap.ampdu_factor);
@@ -659,7 +657,7 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
        an->sta = NULL;
 #endif
 
-       if (sta->ht_cap.ht_supported)
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
                ath_tx_node_cleanup(sc, an);
 }
 
@@ -1550,6 +1548,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_conf *conf = &hw->conf;
+       bool reset_channel = false;
 
        ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
@@ -1558,6 +1557,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
                sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
                if (sc->ps_idle)
                        ath_cancel_work(sc);
+               else
+                       /*
+                        * The chip needs a reset to properly wake up from
+                        * full sleep
+                        */
+                       reset_channel = ah->chip_fullsleep;
        }
 
        /*
@@ -1586,7 +1591,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
                }
        }
 
-       if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+       if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
                struct ieee80211_channel *curchan = hw->conf.channel;
                int pos = curchan->hw_value;
                int old_pos = -1;
index 4f848493fece320edb8d8ce45619fb4a5f09538a..08bb45532701125f69bd0e39c7e0defab15e531e 100644 (file)
@@ -1480,12 +1480,6 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
 
 #ifdef CONFIG_ATH9K_DEBUGFS
 
-static int ath9k_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
                                size_t count, loff_t *ppos)
 {
@@ -1553,7 +1547,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_rcstat = {
        .read = read_file_rcstat,
-       .open = ath9k_debugfs_open,
+       .open = simple_open,
        .owner = THIS_MODULE
 };
 
index f4ae3ba994a8f85284cd157e227c8daeaf671b0c..1c4583c7ff7cffeba6ee39e1b04eefe43f71130f 100644 (file)
@@ -1913,13 +1913,13 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                if (sc->rx.frag) {
                        int space = skb->len - skb_tailroom(hdr_skb);
 
-                       sc->rx.frag = NULL;
-
                        if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
                                dev_kfree_skb(skb);
                                goto requeue_drop_frag;
                        }
 
+                       sc->rx.frag = NULL;
+
                        skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
                                                  skb->len);
                        dev_kfree_skb_any(skb);
index 834e6bc45e8b13eb2b5175043287ee5d381f622e..23eaa1b26ebe5ca9a1a242ea4de5e9fa6508b02c 100644 (file)
@@ -1820,6 +1820,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
        struct ath_frame_info *fi = get_frame_info(skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct ath_buf *bf;
+       int fragno;
        u16 seqno;
 
        bf = ath_tx_get_buffer(sc);
@@ -1831,9 +1832,16 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
        ATH_TXBUF_RESET(bf);
 
        if (tid) {
+               fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
                seqno = tid->seq_next;
                hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
-               INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+
+               if (fragno)
+                       hdr->seq_ctrl |= cpu_to_le16(fragno);
+
+               if (!ieee80211_has_morefrags(hdr->frame_control))
+                       INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+
                bf->bf_state.seqno = seqno;
        }
 
index 3c164226687f54ea74ca18a96e665eb921ae4774..93fe6003a493827dc61e0418607860c90de36d5d 100644 (file)
 #define ADD(buf, off, max, fmt, args...)                               \
        off += snprintf(&buf[off], max - off, fmt, ##args);
 
-static int carl9170_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
 
 struct carl9170_debugfs_fops {
        unsigned int read_bufsize;
@@ -178,7 +173,7 @@ static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
        .attr = _attr,                                                  \
        .req_dev_state = _dstate,                                       \
        .fops = {                                                       \
-               .open   = carl9170_debugfs_open,                        \
+               .open   = simple_open,                                  \
                .read   = carl9170_debugfs_read,                        \
                .write  = carl9170_debugfs_write,                       \
                .owner  = THIS_MODULE                                   \
index e751fdee89b25fc39eb2d41009d8e9ca07e7448a..e807bd9306471772509b0f936391c5b609ed4cfa 100644 (file)
@@ -500,12 +500,6 @@ out:
 
 #undef fappend
 
-static int b43_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
                                size_t count, loff_t *ppos)
 {
@@ -624,7 +618,7 @@ out_unlock:
                .read   = _read,                                \
                .write  = _write,                               \
                .fops   = {                                     \
-                       .open   = b43_debugfs_open,             \
+                       .open   = simple_open,                  \
                        .read   = b43_debugfs_read,             \
                        .write  = b43_debugfs_write,            \
                        .llseek = generic_file_llseek,          \
index c79e6638c88d599e6efdcd048c9145b869d6211a..e4d6dc2e37d12479ab2bdef3560d8f700e9e0d13 100644 (file)
@@ -4827,8 +4827,14 @@ static int b43_op_start(struct ieee80211_hw *hw)
  out_mutex_unlock:
        mutex_unlock(&wl->mutex);
 
-       /* reload configuration */
-       b43_op_config(hw, ~0);
+       /*
+        * Configuration may have been overwritten during initialization.
+        * Reload the configuration, but only if initialization was
+        * successful. Reloading the configuration after a failed init
+        * may hang the system.
+        */
+       if (!err)
+               b43_op_config(hw, ~0);
 
        return err;
 }
index 5e28ad0d6d17f8a1c43401594a42f2b040bbdad5..1965edb765a288d090942d81f013710ba88c0677 100644 (file)
@@ -197,12 +197,6 @@ static int restart_write_file(struct b43legacy_wldev *dev, const char *buf, size
 
 #undef fappend
 
-static int b43legacy_debugfs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
                                size_t count, loff_t *ppos)
 {
@@ -331,7 +325,7 @@ out_unlock:
                .read   = _read,                                \
                .write  = _write,                               \
                .fops   = {                                     \
-                       .open   = b43legacy_debugfs_open,               \
+                       .open   = simple_open,                          \
                        .read   = b43legacy_debugfs_read,               \
                        .write  = b43legacy_debugfs_write,              \
                        .llseek = generic_file_llseek,                  \
index 4688904908ec464b3b9895504e8566eb61d6c5e7..758c115b556ebbcde32b669ccd563c12969b01e7 100644 (file)
@@ -108,9 +108,15 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
                        sdio_release_host(sdfunc);
                }
        } else if (regaddr == SDIO_CCCR_ABORT) {
+               sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
+                                GFP_KERNEL);
+               if (!sdfunc)
+                       return -ENOMEM;
+               sdfunc->num = 0;
                sdio_claim_host(sdfunc);
                sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
                sdio_release_host(sdfunc);
+               kfree(sdfunc);
        } else if (regaddr < 0xF0) {
                brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
                err_ret = -EPERM;
@@ -486,7 +492,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
                        kfree(bus_if);
                        return -ENOMEM;
                }
-               sdiodev->func[0] = func->card->sdio_func[0];
+               sdiodev->func[0] = func;
                sdiodev->func[1] = func;
                sdiodev->bus_if = bus_if;
                bus_if->bus_priv.sdio = sdiodev;
index 2bf5dda292919868a90a9dad3722f0a4991f7024..eb3829b03cd37cf587edab5e4e12aa839e6635e0 100644 (file)
@@ -574,6 +574,8 @@ struct brcmf_sdio {
 
        struct task_struct *dpc_tsk;
        struct completion dpc_wait;
+       struct list_head dpc_tsklst;
+       spinlock_t dpc_tl_lock;
 
        struct semaphore sdsem;
 
@@ -2594,29 +2596,58 @@ clkwait:
        return resched;
 }
 
+static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
+{
+       struct list_head *new_hd;
+       unsigned long flags;
+
+       if (in_interrupt())
+               new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
+       else
+               new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL);
+       if (new_hd == NULL)
+               return;
+
+       spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+       list_add_tail(new_hd, &bus->dpc_tsklst);
+       spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
+}
+
 static int brcmf_sdbrcm_dpc_thread(void *data)
 {
        struct brcmf_sdio *bus = (struct brcmf_sdio *) data;
+       struct list_head *cur_hd, *tmp_hd;
+       unsigned long flags;
 
        allow_signal(SIGTERM);
        /* Run until signal received */
        while (1) {
                if (kthread_should_stop())
                        break;
-               if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
-                       /* Call bus dpc unless it indicated down
-                       (then clean stop) */
-                       if (bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN) {
-                               if (brcmf_sdbrcm_dpc(bus))
-                                       complete(&bus->dpc_wait);
-                       } else {
+
+               if (list_empty(&bus->dpc_tsklst))
+                       if (wait_for_completion_interruptible(&bus->dpc_wait))
+                               break;
+
+               spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+               list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) {
+                       spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
+
+                       if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
                                /* after stopping the bus, exit thread */
                                brcmf_sdbrcm_bus_stop(bus->sdiodev->dev);
                                bus->dpc_tsk = NULL;
                                break;
                        }
-               } else
-                       break;
+
+                       if (brcmf_sdbrcm_dpc(bus))
+                               brcmf_sdbrcm_adddpctsk(bus);
+
+                       spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+                       list_del(cur_hd);
+                       kfree(cur_hd);
+               }
+               spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
        }
        return 0;
 }
@@ -2669,8 +2700,10 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
        /* Schedule DPC if needed to send queued packet(s) */
        if (!bus->dpc_sched) {
                bus->dpc_sched = true;
-               if (bus->dpc_tsk)
+               if (bus->dpc_tsk) {
+                       brcmf_sdbrcm_adddpctsk(bus);
                        complete(&bus->dpc_wait);
+               }
        }
 
        return ret;
@@ -3514,8 +3547,10 @@ void brcmf_sdbrcm_isr(void *arg)
                brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
 
        bus->dpc_sched = true;
-       if (bus->dpc_tsk)
+       if (bus->dpc_tsk) {
+               brcmf_sdbrcm_adddpctsk(bus);
                complete(&bus->dpc_wait);
+       }
 }
 
 static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
@@ -3559,8 +3594,10 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
                                bus->ipend = true;
 
                                bus->dpc_sched = true;
-                               if (bus->dpc_tsk)
+                               if (bus->dpc_tsk) {
+                                       brcmf_sdbrcm_adddpctsk(bus);
                                        complete(&bus->dpc_wait);
+                               }
                        }
                }
 
@@ -3897,6 +3934,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        }
        /* Initialize DPC thread */
        init_completion(&bus->dpc_wait);
+       INIT_LIST_HEAD(&bus->dpc_tsklst);
+       spin_lock_init(&bus->dpc_tl_lock);
        bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
                                   bus, "brcmf_dpc");
        if (IS_ERR(bus->dpc_tsk)) {
index 231ddf4a674f8523e850d50ea73160f5d0b8d069..b4d92792c5028de56ef78b5bbdd1ef3c9c0c317b 100644 (file)
@@ -847,8 +847,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
         */
        if (!(txs->status & TX_STATUS_AMPDU)
            && (txs->status & TX_STATUS_INTERMEDIATE)) {
-               wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
-                         __func__);
+               BCMMSG(wlc->wiphy, "INTERMEDIATE but not AMPDU\n");
                return false;
        }
 
@@ -7614,6 +7613,7 @@ brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
 {
        int len_mpdu;
        struct ieee80211_rx_status rx_status;
+       struct ieee80211_hdr *hdr;
 
        memset(&rx_status, 0, sizeof(rx_status));
        prep_mac80211_status(wlc, rxh, p, &rx_status);
@@ -7623,6 +7623,13 @@ brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
        skb_pull(p, D11_PHY_HDR_LEN);
        __skb_trim(p, len_mpdu);
 
+       /* unmute transmit */
+       if (wlc->hw->suspended_fifos) {
+               hdr = (struct ieee80211_hdr *)p->data;
+               if (ieee80211_is_beacon(hdr->frame_control))
+                       brcms_b_mute(wlc->hw, false);
+       }
+
        memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
        ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
 }
index 4fcdac63a3007aff3822e8dd17ccd5db57ce69a6..1779db3aa2b00c3a11bbcad080dadf8f0da0984c 100644 (file)
@@ -2191,6 +2191,7 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
 {
        int rc = 0;
        unsigned long flags;
+       unsigned long now, end;
 
        spin_lock_irqsave(&priv->lock, flags);
        if (priv->status & STATUS_HCMD_ACTIVE) {
@@ -2232,10 +2233,20 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
        }
        spin_unlock_irqrestore(&priv->lock, flags);
 
+       now = jiffies;
+       end = now + HOST_COMPLETE_TIMEOUT;
+again:
        rc = wait_event_interruptible_timeout(priv->wait_command_queue,
                                              !(priv->
                                                status & STATUS_HCMD_ACTIVE),
-                                             HOST_COMPLETE_TIMEOUT);
+                                             end - now);
+       if (rc < 0) {
+               now = jiffies;
+               if (time_before(now, end))
+                       goto again;
+               rc = 0;
+       }
+
        if (rc == 0) {
                spin_lock_irqsave(&priv->lock, flags);
                if (priv->status & STATUS_HCMD_ACTIVE) {
@@ -11507,9 +11518,9 @@ static int ipw_wdev_init(struct net_device *dev)
                        rc = -ENOMEM;
                        goto out;
                }
-               /* translate geo->bg to a_band.channels */
+               /* translate geo->a to a_band.channels */
                for (i = 0; i < geo->a_channels; i++) {
-                       a_band->channels[i].band = IEEE80211_BAND_2GHZ;
+                       a_band->channels[i].band = IEEE80211_BAND_5GHZ;
                        a_band->channels[i].center_freq = geo->a[i].freq;
                        a_band->channels[i].hw_value = geo->a[i].channel;
                        a_band->channels[i].max_power = geo->a[i].max_power;
index 0c1209390169d1f81a0bacdfe452b8008ecbee2a..faec404672081d5f72d03da9f44abac0de3c27d1 100644 (file)
@@ -2673,8 +2673,6 @@ il3945_bg_restart(struct work_struct *data)
 
        if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
                mutex_lock(&il->mutex);
-               /* FIXME: vif can be dereferenced */
-               il->vif = NULL;
                il->is_open = 0;
                mutex_unlock(&il->mutex);
                il3945_down(il);
index 70bee1a4d87679e57cafdb01fa22968ec823f20e..4b10157d86864685e8f635d07b8795fbaf3ef16f 100644 (file)
@@ -821,12 +821,6 @@ out:
 }
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-static int
-il3945_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
 
 static ssize_t
 il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf,
@@ -862,7 +856,7 @@ il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf,
 
 static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
        .read = il3945_sta_dbgfs_stats_table_read,
-       .open = il3945_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
index 17f1c6853182d23ddfb092c3d0e7787a04ce0731..c46275a92565a592b15b66ff4d19fd271eb32f5b 100644 (file)
@@ -5652,8 +5652,6 @@ il4965_bg_restart(struct work_struct *data)
 
        if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
                mutex_lock(&il->mutex);
-               /* FIXME: do we dereference vif without mutex locked ? */
-               il->vif = NULL;
                il->is_open = 0;
 
                __il4965_down(il);
index d7e2856e41d3b0e90929d605096e9e40932f95ee..11ab1247fae1c841eedc4cf390be9eba167b987f 100644 (file)
@@ -2518,12 +2518,6 @@ il4965_rs_free_sta(void *il_r, struct ieee80211_sta *sta, void *il_sta)
 }
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-static int
-il4965_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
 
 static void
 il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta, u32 * rate_n_flags, int idx)
@@ -2695,7 +2689,7 @@ il4965_rs_sta_dbgfs_scale_table_read(struct file *file, char __user *user_buf,
 static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
        .write = il4965_rs_sta_dbgfs_scale_table_write,
        .read = il4965_rs_sta_dbgfs_scale_table_read,
-       .open = il4965_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -2740,7 +2734,7 @@ il4965_rs_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf,
 
 static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
        .read = il4965_rs_sta_dbgfs_stats_table_read,
-       .open = il4965_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -2768,7 +2762,7 @@ il4965_rs_sta_dbgfs_rate_scale_data_read(struct file *file,
 
 static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
        .read = il4965_rs_sta_dbgfs_rate_scale_data_read,
-       .open = il4965_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
index e5ac04739bcc5f998487c7e29845ce0a757727fa..eaf249452e51713f91fe7067a6fa804d7f6ea1d0 100644 (file)
@@ -4508,6 +4508,7 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
        struct il_priv *il = hw->priv;
        int err;
+       bool reset;
 
        mutex_lock(&il->mutex);
        D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr);
@@ -4518,7 +4519,12 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
                goto out;
        }
 
-       if (il->vif) {
+       /*
+        * We do not support multiple virtual interfaces, but on hardware reset
+        * we have to add the same interface again.
+        */
+       reset = (il->vif == vif);
+       if (il->vif && !reset) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -4528,8 +4534,11 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
        err = il_set_mode(il);
        if (err) {
-               il->vif = NULL;
-               il->iw_mode = NL80211_IFTYPE_STATION;
+               IL_WARN("Fail to set mode %d\n", vif->type);
+               if (!reset) {
+                       il->vif = NULL;
+                       il->iw_mode = NL80211_IFTYPE_STATION;
+               }
        }
 
 out:
@@ -5279,9 +5288,9 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                D_MAC80211("BSSID %pM\n", bss_conf->bssid);
 
                /*
-                * If there is currently a HW scan going on in the
-                * background then we need to cancel it else the RXON
-                * below/in post_associate will fail.
+                * If there is currently a HW scan going on in the background,
+                * then we need to cancel it, otherwise sometimes we are not
+                * able to authenticate (FIXME: why ?)
                 */
                if (il_scan_cancel_timeout(il, 100)) {
                        D_MAC80211("leave - scan abort failed\n");
@@ -5290,14 +5299,10 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                }
 
                /* mac80211 only sets assoc when in STATION mode */
-               if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
-                       memcpy(il->staging.bssid_addr, bss_conf->bssid,
-                              ETH_ALEN);
+               memcpy(il->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
 
-                       /* currently needed in a few places */
-                       memcpy(il->bssid, bss_conf->bssid, ETH_ALEN);
-               } else
-                       il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+               /* FIXME: currently needed in a few places */
+               memcpy(il->bssid, bss_conf->bssid, ETH_ALEN);
        }
 
        /*
index 229849150aac0bb20e152b6a79b0658ebf3b18bb..eff26501d60a63407fba5b8cff66778d612df54e 100644 (file)
@@ -160,18 +160,12 @@ static ssize_t il_dbgfs_##name##_write(struct file *file,              \
                                        const char __user *user_buf,    \
                                        size_t count, loff_t *ppos);
 
-static int
-il_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
 
 #define DEBUGFS_READ_FILE_OPS(name)                            \
        DEBUGFS_READ_FUNC(name);                                \
 static const struct file_operations il_dbgfs_##name##_ops = {  \
        .read = il_dbgfs_##name##_read,                         \
-       .open = il_dbgfs_open_file_generic,                     \
+       .open = simple_open,                                    \
        .llseek = generic_file_llseek,                          \
 };
 
@@ -179,7 +173,7 @@ static const struct file_operations il_dbgfs_##name##_ops = {       \
        DEBUGFS_WRITE_FUNC(name);                               \
 static const struct file_operations il_dbgfs_##name##_ops = {  \
        .write = il_dbgfs_##name##_write,                       \
-       .open = il_dbgfs_open_file_generic,                     \
+       .open = simple_open,                                    \
        .llseek = generic_file_llseek,                          \
 };
 
@@ -189,7 +183,7 @@ static const struct file_operations il_dbgfs_##name##_ops = {       \
 static const struct file_operations il_dbgfs_##name##_ops = {  \
        .write = il_dbgfs_##name##_write,                       \
        .read = il_dbgfs_##name##_read,                         \
-       .open = il_dbgfs_open_file_generic,                     \
+       .open = simple_open,                                    \
        .llseek = generic_file_llseek,                          \
 };
 
index 5b0d888f746bbc27ea492d6351458476aabdbd4d..8d80e233bc7a73aec74b267edb61bd191bdf5eb2 100644 (file)
@@ -46,8 +46,8 @@
 #include "iwl-prph.h"
 
 /* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 6
-#define IWL100_UCODE_API_MAX 6
+#define IWL1000_UCODE_API_MAX 5
+#define IWL100_UCODE_API_MAX 5
 
 /* Oldest version we won't warn about */
 #define IWL1000_UCODE_API_OK 5
@@ -226,5 +226,5 @@ const struct iwl_cfg iwl100_bg_cfg = {
        IWL_DEVICE_100,
 };
 
-MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_OK));
index 5635b9e2c69e6b4e27e9337d88f97095ac71029d..ea108622e0bd0adf4a961be817378df86664e1c1 100644 (file)
 #define IWL135_UCODE_API_MAX 6
 
 /* Oldest version we won't warn about */
-#define IWL2030_UCODE_API_OK 5
-#define IWL2000_UCODE_API_OK 5
-#define IWL105_UCODE_API_OK 5
-#define IWL135_UCODE_API_OK 5
+#define IWL2030_UCODE_API_OK 6
+#define IWL2000_UCODE_API_OK 6
+#define IWL105_UCODE_API_OK 6
+#define IWL135_UCODE_API_OK 6
 
 /* Lowest firmware API version supported */
 #define IWL2030_UCODE_API_MIN 5
@@ -328,7 +328,7 @@ const struct iwl_cfg iwl135_bgn_cfg = {
        .ht_params = &iwl2000_ht_params,
 };
 
-MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_OK));
+MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_OK));
+MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_OK));
index a805e97b89af85cb1a066c156cc1899dde7034c7..de0920c74cdd2369b7a528de29536163aba01f50 100644 (file)
 #define IWL5000_UCODE_API_MAX 5
 #define IWL5150_UCODE_API_MAX 2
 
+/* Oldest version we won't warn about */
+#define IWL5000_UCODE_API_OK 5
+#define IWL5150_UCODE_API_OK 2
+
 /* Lowest firmware API version supported */
 #define IWL5000_UCODE_API_MIN 1
 #define IWL5150_UCODE_API_MIN 1
@@ -326,6 +330,7 @@ static const struct iwl_ht_params iwl5000_ht_params = {
 #define IWL_DEVICE_5000                                                \
        .fw_name_pre = IWL5000_FW_PRE,                          \
        .ucode_api_max = IWL5000_UCODE_API_MAX,                 \
+       .ucode_api_ok = IWL5000_UCODE_API_OK,                   \
        .ucode_api_min = IWL5000_UCODE_API_MIN,                 \
        .max_inst_size = IWLAGN_RTC_INST_SIZE,                  \
        .max_data_size = IWLAGN_RTC_DATA_SIZE,                  \
@@ -371,6 +376,7 @@ const struct iwl_cfg iwl5350_agn_cfg = {
        .name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
        .fw_name_pre = IWL5000_FW_PRE,
        .ucode_api_max = IWL5000_UCODE_API_MAX,
+       .ucode_api_ok = IWL5000_UCODE_API_OK,
        .ucode_api_min = IWL5000_UCODE_API_MIN,
        .max_inst_size = IWLAGN_RTC_INST_SIZE,
        .max_data_size = IWLAGN_RTC_DATA_SIZE,
@@ -386,6 +392,7 @@ const struct iwl_cfg iwl5350_agn_cfg = {
 #define IWL_DEVICE_5150                                                \
        .fw_name_pre = IWL5150_FW_PRE,                          \
        .ucode_api_max = IWL5150_UCODE_API_MAX,                 \
+       .ucode_api_ok = IWL5150_UCODE_API_OK,                   \
        .ucode_api_min = IWL5150_UCODE_API_MIN,                 \
        .max_inst_size = IWLAGN_RTC_INST_SIZE,                  \
        .max_data_size = IWLAGN_RTC_DATA_SIZE,                  \
@@ -409,5 +416,5 @@ const struct iwl_cfg iwl5150_abg_cfg = {
        IWL_DEVICE_5150,
 };
 
-MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_OK));
index 64060cd738b5d90b069a8289eba923842365a023..f0c91505a7f775ac0e8cb819dca0be1bfc983094 100644 (file)
@@ -53,6 +53,8 @@
 /* Oldest version we won't warn about */
 #define IWL6000_UCODE_API_OK 4
 #define IWL6000G2_UCODE_API_OK 5
+#define IWL6050_UCODE_API_OK 5
+#define IWL6000G2B_UCODE_API_OK 6
 
 /* Lowest firmware API version supported */
 #define IWL6000_UCODE_API_MIN 4
@@ -388,7 +390,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
 #define IWL_DEVICE_6030                                                \
        .fw_name_pre = IWL6030_FW_PRE,                          \
        .ucode_api_max = IWL6000G2_UCODE_API_MAX,               \
-       .ucode_api_ok = IWL6000G2_UCODE_API_OK,                 \
+       .ucode_api_ok = IWL6000G2B_UCODE_API_OK,                \
        .ucode_api_min = IWL6000G2_UCODE_API_MIN,               \
        .max_inst_size = IWL60_RTC_INST_SIZE,                   \
        .max_data_size = IWL60_RTC_DATA_SIZE,                   \
@@ -557,6 +559,6 @@ const struct iwl_cfg iwl6000_3agn_cfg = {
 };
 
 MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_OK));
-MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_OK));
+MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_OK));
+MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_OK));
index 53f8c51cfcdb021d292caf5f911694413df42d4c..7e590b349dd7523f76db4c1ff235c53b5434d71b 100644 (file)
@@ -3083,11 +3083,6 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
 }
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-static int open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
 static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
                             u32 *rate_n_flags, int index)
 {
@@ -3226,7 +3221,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
 static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
        .write = rs_sta_dbgfs_scale_table_write,
        .read = rs_sta_dbgfs_scale_table_read,
-       .open = open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
@@ -3269,7 +3264,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
 
 static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
        .read = rs_sta_dbgfs_stats_table_read,
-       .open = open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -3295,7 +3290,7 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
 
 static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
        .read = rs_sta_dbgfs_rate_scale_data_read,
-       .open = open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
index f1226dbf789d796c7c366fe102f410eb32537f7f..2a9a16f901c3f940dd87f4865bcab51a53a7a48d 100644 (file)
@@ -863,7 +863,6 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
 
 void iwlagn_prepare_restart(struct iwl_priv *priv)
 {
-       struct iwl_rxon_context *ctx;
        bool bt_full_concurrent;
        u8 bt_ci_compliance;
        u8 bt_load;
@@ -872,8 +871,6 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
 
        lockdep_assert_held(&priv->mutex);
 
-       for_each_context(priv, ctx)
-               ctx->vif = NULL;
        priv->is_open = 0;
 
        /*
index b7b1c04f2fba4c7b449d8106de5471b6548c1d2c..2bbaebd99ad42a4a8c057838eead058088686dc0 100644 (file)
@@ -84,17 +84,11 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
                                        size_t count, loff_t *ppos);
 
 
-static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 #define DEBUGFS_READ_FILE_OPS(name)                                     \
        DEBUGFS_READ_FUNC(name);                                        \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
        .read = iwl_dbgfs_##name##_read,                                \
-       .open = iwl_dbgfs_open_file_generic,                            \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -102,7 +96,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \
        DEBUGFS_WRITE_FUNC(name);                                       \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
        .write = iwl_dbgfs_##name##_write,                              \
-       .open = iwl_dbgfs_open_file_generic,                            \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -113,7 +107,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
        .write = iwl_dbgfs_##name##_write,                              \
        .read = iwl_dbgfs_##name##_read,                                \
-       .open = iwl_dbgfs_open_file_generic,                            \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
index 90208094b8ebdb472fcc9078ca605c83f37d9197..74bce97a860004b3fc8e921df2afef593379ebfb 100644 (file)
  * (see struct iwl_tfd_frame).  These 16 pointer registers are offset by 0x04
  * bytes from one another.  Each TFD circular buffer in DRAM must be 256-byte
  * aligned (address bits 0-7 must be 0).
+ * Later devices have 20 (5000 series) or 30 (higher) queues, but the registers
+ * for them are in different places.
  *
  * Bit fields in each pointer register:
  *  27-0: TFD CB physical base address [35:8], must be 256-byte aligned
  */
-#define FH_MEM_CBBC_LOWER_BOUND          (FH_MEM_LOWER_BOUND + 0x9D0)
-#define FH_MEM_CBBC_UPPER_BOUND          (FH_MEM_LOWER_BOUND + 0xA10)
-
-/* Find TFD CB base pointer for given queue (range 0-15). */
-#define FH_MEM_CBBC_QUEUE(x)  (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4)
+#define FH_MEM_CBBC_0_15_LOWER_BOUND           (FH_MEM_LOWER_BOUND + 0x9D0)
+#define FH_MEM_CBBC_0_15_UPPER_BOUND           (FH_MEM_LOWER_BOUND + 0xA10)
+#define FH_MEM_CBBC_16_19_LOWER_BOUND          (FH_MEM_LOWER_BOUND + 0xBF0)
+#define FH_MEM_CBBC_16_19_UPPER_BOUND          (FH_MEM_LOWER_BOUND + 0xC00)
+#define FH_MEM_CBBC_20_31_LOWER_BOUND          (FH_MEM_LOWER_BOUND + 0xB20)
+#define FH_MEM_CBBC_20_31_UPPER_BOUND          (FH_MEM_LOWER_BOUND + 0xB80)
+
+/* Find TFD CB base pointer for given queue */
+static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
+{
+       if (chnl < 16)
+               return FH_MEM_CBBC_0_15_LOWER_BOUND + 4 * chnl;
+       if (chnl < 20)
+               return FH_MEM_CBBC_16_19_LOWER_BOUND + 4 * (chnl - 16);
+       WARN_ON_ONCE(chnl >= 32);
+       return FH_MEM_CBBC_20_31_LOWER_BOUND + 4 * (chnl - 20);
+}
 
 
 /**
index b6805f8e9a014553cca088e4992aa09c421897f7..c24a7134a6f9a3729d81350ea699246744805884 100644 (file)
@@ -1244,6 +1244,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
        struct iwl_rxon_context *tmp, *ctx = NULL;
        int err;
        enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif);
+       bool reset = false;
 
        IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
                           viftype, vif->addr);
@@ -1265,6 +1266,13 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
                        tmp->interface_modes | tmp->exclusive_interface_modes;
 
                if (tmp->vif) {
+                       /* On reset we need to add the same interface again */
+                       if (tmp->vif == vif) {
+                               reset = true;
+                               ctx = tmp;
+                               break;
+                       }
+
                        /* check if this busy context is exclusive */
                        if (tmp->exclusive_interface_modes &
                                                BIT(tmp->vif->type)) {
@@ -1291,7 +1299,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
        ctx->vif = vif;
 
        err = iwl_setup_interface(priv, ctx);
-       if (!err)
+       if (!err || reset)
                goto out;
 
        ctx->vif = NULL;
index 75dc20bd965b4d80715881b5657d099c75274854..3b1069290fa9a9cf646a2f04325d6c1862b70a7a 100644 (file)
 #define SCD_AIT                        (SCD_BASE + 0x0c)
 #define SCD_TXFACT             (SCD_BASE + 0x10)
 #define SCD_ACTIVE             (SCD_BASE + 0x14)
-#define SCD_QUEUE_WRPTR(x)     (SCD_BASE + 0x18 + (x) * 4)
-#define SCD_QUEUE_RDPTR(x)     (SCD_BASE + 0x68 + (x) * 4)
 #define SCD_QUEUECHAIN_SEL     (SCD_BASE + 0xe8)
 #define SCD_AGGR_SEL           (SCD_BASE + 0x248)
 #define SCD_INTERRUPT_MASK     (SCD_BASE + 0x108)
-#define SCD_QUEUE_STATUS_BITS(x)       (SCD_BASE + 0x10c + (x) * 4)
+
+static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl)
+{
+       if (chnl < 20)
+               return SCD_BASE + 0x18 + chnl * 4;
+       WARN_ON_ONCE(chnl >= 32);
+       return SCD_BASE + 0x284 + (chnl - 20) * 4;
+}
+
+static inline unsigned int SCD_QUEUE_RDPTR(unsigned int chnl)
+{
+       if (chnl < 20)
+               return SCD_BASE + 0x68 + chnl * 4;
+       WARN_ON_ONCE(chnl >= 32);
+       return SCD_BASE + 0x2B4 + (chnl - 20) * 4;
+}
+
+static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl)
+{
+       if (chnl < 20)
+               return SCD_BASE + 0x10c + chnl * 4;
+       WARN_ON_ONCE(chnl >= 32);
+       return SCD_BASE + 0x384 + (chnl - 20) * 4;
+}
 
 /*********************** END TX SCHEDULER *************************************/
 
index b4f796c82e1ec90ddf3a466960c242a49f99138f..4d7b30d3e64855e83b03d1cfaaa4391d6fa8b8d4 100644 (file)
@@ -1898,17 +1898,11 @@ static ssize_t iwl_dbgfs_##name##_write(struct file *file,              \
                                        size_t count, loff_t *ppos);
 
 
-static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 #define DEBUGFS_READ_FILE_OPS(name)                                    \
        DEBUGFS_READ_FUNC(name);                                        \
 static const struct file_operations iwl_dbgfs_##name##_ops = {         \
        .read = iwl_dbgfs_##name##_read,                                \
-       .open = iwl_dbgfs_open_file_generic,                            \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -1916,7 +1910,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {            \
        DEBUGFS_WRITE_FUNC(name);                                       \
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
        .write = iwl_dbgfs_##name##_write,                              \
-       .open = iwl_dbgfs_open_file_generic,                            \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -1926,7 +1920,7 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 static const struct file_operations iwl_dbgfs_##name##_ops = {         \
        .write = iwl_dbgfs_##name##_write,                              \
        .read = iwl_dbgfs_##name##_read,                                \
-       .open = iwl_dbgfs_open_file_generic,                            \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
index 87eef5773a02e35203319f53fa4ff1da58cdf60b..b6199d124bb9a5955ece37d4bdd0e808cb9c9cdd 100644 (file)
@@ -99,12 +99,6 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules,
                        iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write,
                        "%llu\n");
 
-static int iwm_generic_open(struct inode *inode, struct file *filp)
-{
-       filp->private_data = inode->i_private;
-       return 0;
-}
-
 
 static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer,
                                   size_t count, loff_t *ppos)
@@ -401,28 +395,28 @@ out:
 
 static const struct file_operations iwm_debugfs_txq_fops = {
        .owner =        THIS_MODULE,
-       .open =         iwm_generic_open,
+       .open =         simple_open,
        .read =         iwm_debugfs_txq_read,
        .llseek =       default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_tx_credit_fops = {
        .owner =        THIS_MODULE,
-       .open =         iwm_generic_open,
+       .open =         simple_open,
        .read =         iwm_debugfs_tx_credit_read,
        .llseek =       default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_rx_ticket_fops = {
        .owner =        THIS_MODULE,
-       .open =         iwm_generic_open,
+       .open =         simple_open,
        .read =         iwm_debugfs_rx_ticket_read,
        .llseek =       default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_fw_err_fops = {
        .owner =        THIS_MODULE,
-       .open =         iwm_generic_open,
+       .open =         simple_open,
        .read =         iwm_debugfs_fw_err_read,
        .llseek =       default_llseek,
 };
index 764b40dd24adad66722756dd3833b9c191969f1a..0042f204b07fabc91e182c3a6c8c2cad2b2b9ffc 100644 (file)
@@ -264,13 +264,6 @@ static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
        return ret;
 }
 
-/* debugfs hooks */
-static int iwm_debugfs_sdio_open(struct inode *inode, struct file *filp)
-{
-       filp->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer,
                                     size_t count, loff_t *ppos)
 {
@@ -363,7 +356,7 @@ err:
 
 static const struct file_operations iwm_debugfs_sdio_fops = {
        .owner =        THIS_MODULE,
-       .open =         iwm_debugfs_sdio_open,
+       .open =         simple_open,
        .read =         iwm_debugfs_sdio_read,
        .llseek =       default_llseek,
 };
index 3fa1ecebadfd33e3d15e63e1f79de46d851a7ab3..2fa879b015b6817d24e558395c0f74ef638cbc96 100644 (file)
@@ -103,7 +103,7 @@ static const u32 cipher_suites[] = {
  * Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1
  * in the firmware spec
  */
-static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type)
+static int lbs_auth_to_authtype(enum nl80211_auth_type auth_type)
 {
        int ret = -ENOTSUPP;
 
@@ -1411,7 +1411,12 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
                goto done;
        }
 
-       lbs_set_authtype(priv, sme);
+       ret = lbs_set_authtype(priv, sme);
+       if (ret == -ENOTSUPP) {
+               wiphy_err(wiphy, "unsupported authtype 0x%x\n", sme->auth_type);
+               goto done;
+       }
+
        lbs_set_radio(priv, preamble, 1);
 
        /* Do the actual association */
index c192671610fcf5bec8c117c10972e5ab569e9d03..a06cc283e23d1c3df6b645f30ce992875e0a0382 100644 (file)
@@ -21,12 +21,6 @@ static char *szStates[] = {
 static void lbs_debug_init(struct lbs_private *priv);
 #endif
 
-static int open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t write_file_dummy(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 {
@@ -696,7 +690,7 @@ out_unlock:
 
 #define FOPS(fread, fwrite) { \
        .owner = THIS_MODULE, \
-       .open = open_file_generic, \
+       .open = simple_open, \
        .read = (fread), \
        .write = (fwrite), \
        .llseek = generic_file_llseek, \
@@ -962,7 +956,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
 
 static const struct file_operations lbs_debug_fops = {
        .owner = THIS_MODULE,
-       .open = open_file_generic,
+       .open = simple_open,
        .write = lbs_debugfs_write,
        .read = lbs_debugfs_read,
        .llseek = default_llseek,
index d26a78b6b3c43d0642a181dde7815c6972b636ab..1a845074c52ac967273f17beb57bbedd924795ba 100644 (file)
@@ -139,18 +139,6 @@ static struct mwifiex_debug_data items[] = {
 
 static int num_of_items = ARRAY_SIZE(items);
 
-/*
- * Generic proc file open handler.
- *
- * This function is called every time a file is accessed for read or write.
- */
-static int
-mwifiex_open_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 /*
  * Proc info file read handler.
  *
@@ -676,19 +664,19 @@ done:
 static const struct file_operations mwifiex_dfs_##name##_fops = {       \
        .read = mwifiex_##name##_read,                                  \
        .write = mwifiex_##name##_write,                                \
-       .open = mwifiex_open_generic,                                   \
+       .open = simple_open,                                            \
 };
 
 #define MWIFIEX_DFS_FILE_READ_OPS(name)                                 \
 static const struct file_operations mwifiex_dfs_##name##_fops = {       \
        .read = mwifiex_##name##_read,                                  \
-       .open = mwifiex_open_generic,                                   \
+       .open = simple_open,                                            \
 };
 
 #define MWIFIEX_DFS_FILE_WRITE_OPS(name)                                \
 static const struct file_operations mwifiex_dfs_##name##_fops = {       \
        .write = mwifiex_##name##_write,                                \
-       .open = mwifiex_open_generic,                                   \
+       .open = simple_open,                                            \
 };
 
 
index 445ff21772e2ec948948e6338525663b9b34f6eb..2f218f9a3fd3efea52e8038345a326bfb7341243 100644 (file)
 #define PCIE_HOST_INT_STATUS_MASK                      0xC3C
 #define PCIE_SCRATCH_2_REG                             0xC40
 #define PCIE_SCRATCH_3_REG                             0xC44
-#define PCIE_SCRATCH_4_REG                             0xCC0
-#define PCIE_SCRATCH_5_REG                             0xCC4
-#define PCIE_SCRATCH_6_REG                             0xCC8
-#define PCIE_SCRATCH_7_REG                             0xCCC
-#define PCIE_SCRATCH_8_REG                             0xCD0
-#define PCIE_SCRATCH_9_REG                             0xCD4
-#define PCIE_SCRATCH_10_REG                            0xCD8
-#define PCIE_SCRATCH_11_REG                            0xCDC
-#define PCIE_SCRATCH_12_REG                            0xCE0
+#define PCIE_SCRATCH_4_REG                             0xCD0
+#define PCIE_SCRATCH_5_REG                             0xCD4
+#define PCIE_SCRATCH_6_REG                             0xCD8
+#define PCIE_SCRATCH_7_REG                             0xCDC
+#define PCIE_SCRATCH_8_REG                             0xCE0
+#define PCIE_SCRATCH_9_REG                             0xCE4
+#define PCIE_SCRATCH_10_REG                            0xCE8
+#define PCIE_SCRATCH_11_REG                            0xCEC
+#define PCIE_SCRATCH_12_REG                            0xCF0
 
 #define CPU_INTR_DNLD_RDY                              BIT(0)
 #define CPU_INTR_DOOR_BELL                             BIT(1)
index dd6c64ac406e8f28d87e69d81dff7b4d8171e19c..88e3ad2d1db8dea4d5e2fcdee52285e399644bcd 100644 (file)
@@ -1336,6 +1336,10 @@ static void qbuf_scan(struct orinoco_private *priv, void *buf,
        unsigned long flags;
 
        sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
+       if (!sd) {
+               printk(KERN_ERR "%s: failed to alloc memory\n", __func__);
+               return;
+       }
        sd->buf = buf;
        sd->len = len;
        sd->type = type;
@@ -1353,6 +1357,10 @@ static void qabort_scan(struct orinoco_private *priv)
        unsigned long flags;
 
        sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
+       if (!sd) {
+               printk(KERN_ERR "%s: failed to alloc memory\n", __func__);
+               return;
+       }
        sd->len = -1; /* Abort */
 
        spin_lock_irqsave(&priv->scan_lock, flags);
index cd490abced9159347cf875b9ea9349192c899dd3..001735f7a6619b5f5419e3abbc7371c989f432cf 100644 (file)
@@ -163,7 +163,13 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
 
                /* Reschedule urb to read TX status again instantly */
                return true;
-       } else if (rt2800usb_txstatus_pending(rt2x00dev)) {
+       }
+
+       /* Check if there is any entry that timedout waiting on TX status */
+       if (rt2800usb_txstatus_timeout(rt2x00dev))
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+
+       if (rt2800usb_txstatus_pending(rt2x00dev)) {
                /* Read register after 250 us */
                hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000),
                              HRTIMER_MODE_REL);
@@ -178,7 +184,7 @@ stop_reading:
         * here again if status reading is needed.
         */
        if (rt2800usb_txstatus_pending(rt2x00dev) &&
-           test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
+           !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
                return true;
        else
                return false;
index fc9901e027c16d521bc59a3570036ba4808bc0f0..90cc5e77265058cfa894cdc5111e34ee542774a2 100644 (file)
@@ -1062,11 +1062,6 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
 
        set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
 
-       /*
-        * Register the extra components.
-        */
-       rt2x00rfkill_register(rt2x00dev);
-
        return 0;
 }
 
@@ -1210,6 +1205,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
        rt2x00link_register(rt2x00dev);
        rt2x00leds_register(rt2x00dev);
        rt2x00debug_register(rt2x00dev);
+       rt2x00rfkill_register(rt2x00dev);
 
        return 0;
 
index 510023554e5f43ba0105a2cd5de09e8987b861dd..e54488db0e10178bfb820da5d23eb0e2a54591f8 100644 (file)
@@ -838,7 +838,10 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
        __le16 fc = hdr->frame_control;
 
        txrate = ieee80211_get_tx_rate(hw, info);
-       tcb_desc->hw_rate = txrate->hw_value;
+       if (txrate)
+               tcb_desc->hw_rate = txrate->hw_value;
+       else
+               tcb_desc->hw_rate = 0;
 
        if (ieee80211_is_data(fc)) {
                /*
index 07dd38efe62a01580c9debe210fb2d38c8ddd50e..cc15fdb36060b3dd387124e6288ac288c901cc78 100644 (file)
@@ -912,8 +912,13 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
        memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
        ring = &rtlpci->tx_ring[BEACON_QUEUE];
        pskb = __skb_dequeue(&ring->queue);
-       if (pskb)
+       if (pskb) {
+               struct rtl_tx_desc *entry = &ring->desc[ring->idx];
+               pci_unmap_single(rtlpci->pdev, rtlpriv->cfg->ops->get_desc(
+                                (u8 *) entry, true, HW_DESC_TXBUFF_ADDR),
+                                pskb->len, PCI_DMA_TODEVICE);
                kfree_skb(pskb);
+       }
 
        /*NB: the beacon data buffer must be 32-bit aligned. */
        pskb = ieee80211_beacon_get(hw, mac->vif);
@@ -1936,6 +1941,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
                rtl_deinit_deferred_work(hw);
                rtlpriv->intf_ops->adapter_stop(hw);
        }
+       rtlpriv->cfg->ops->disable_interrupt(hw);
 
        /*deinit rfkill */
        rtl_deinit_rfkill(hw);
index 1eec3a06d1f350935332a440f379367145b837d0..4c016241f34072bdb5136bea4b4ffee3f833afeb 100644 (file)
@@ -1893,7 +1893,7 @@ void rtl92c_phy_set_io(struct ieee80211_hw *hw)
                break;
        case IO_CMD_PAUSE_DM_BY_SCAN:
                rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue;
-               dm_digtable.cur_igvalue = 0x17;
+               dm_digtable.cur_igvalue = 0x37;
                rtl92c_dm_write_dig(hw);
                break;
        default:
index 34591eeb837617308284c5e5765e4f1440d5a7fd..28fc5fb8057be2ff9029619142fa2221e7690506 100644 (file)
@@ -3077,7 +3077,7 @@ static void rtl92d_phy_set_io(struct ieee80211_hw *hw)
                break;
        case IO_CMD_PAUSE_DM_BY_SCAN:
                rtlphy->initgain_backup.xaagccore1 = de_digtable.cur_igvalue;
-               de_digtable.cur_igvalue = 0x17;
+               de_digtable.cur_igvalue = 0x37;
                rtl92d_dm_write_dig(hw);
                break;
        default:
index 4898c502974db606bf725ed0664318f0655ab7f8..480862c07f921668e803694a37ef702f19d34a8d 100644 (file)
@@ -91,7 +91,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
        u8 tid;
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-       static int header_print;
 
        rtlpriv->dm.dm_initialgain_enable = true;
        rtlpriv->dm.dm_flag = 0;
@@ -171,10 +170,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
        for (tid = 0; tid < 8; tid++)
                skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
 
-       /* Only load firmware for first MAC */
-       if (header_print)
-               return 0;
-
        /* for firmware buf */
        rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
        if (!rtlpriv->rtlhal.pfirmware) {
@@ -186,7 +181,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
        rtlpriv->max_fw_size = 0x8000;
        pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
        pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
-       header_print++;
 
        /* request fw */
        err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
index 2e1e352864bb88ad33489402aee1f19ef2aa4154..d04dbda13f5a3bd699e6265490736da54adc2702 100644 (file)
@@ -124,46 +124,38 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
        return status;
 }
 
-static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
+static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len)
 {
+       struct device *dev = rtlpriv->io.dev;
+       struct usb_device *udev = to_usb_device(dev);
        u8 request;
        u16 wvalue;
        u16 index;
-       u32 *data;
-       u32 ret;
+       __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index];
 
-       data = kmalloc(sizeof(u32), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
        request = REALTEK_USB_VENQT_CMD_REQ;
        index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
 
        wvalue = (u16)addr;
        _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
-       ret = le32_to_cpu(*data);
-       kfree(data);
-       return ret;
+       if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT)
+               rtlpriv->usb_data_index = 0;
+       return le32_to_cpu(*data);
 }
 
 static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-       struct device *dev = rtlpriv->io.dev;
-
-       return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
+       return (u8)_usb_read_sync(rtlpriv, addr, 1);
 }
 
 static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-       struct device *dev = rtlpriv->io.dev;
-
-       return (u16)_usb_read_sync(to_usb_device(dev), addr, 2);
+       return (u16)_usb_read_sync(rtlpriv, addr, 2);
 }
 
 static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-       struct device *dev = rtlpriv->io.dev;
-
-       return _usb_read_sync(to_usb_device(dev), addr, 4);
+       return _usb_read_sync(rtlpriv, addr, 4);
 }
 
 static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
@@ -955,6 +947,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
                return -ENOMEM;
        }
        rtlpriv = hw->priv;
+       rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
+                                   GFP_KERNEL);
+       if (!rtlpriv->usb_data)
+               return -ENOMEM;
+       rtlpriv->usb_data_index = 0;
        init_completion(&rtlpriv->firmware_loading_complete);
        SET_IEEE80211_DEV(hw, &intf->dev);
        udev = interface_to_usbdev(intf);
@@ -1025,6 +1022,7 @@ void rtl_usb_disconnect(struct usb_interface *intf)
        /* rtl_deinit_rfkill(hw); */
        rtl_usb_deinit(hw);
        rtl_deinit_core(hw);
+       kfree(rtlpriv->usb_data);
        rtlpriv->cfg->ops->deinit_sw_leds(hw);
        rtlpriv->cfg->ops->deinit_sw_vars(hw);
        _rtl_usb_io_handler_release(hw);
index b591614c3b9bb79c7b6e00ec6fe48cb8b06c480b..28ebc69218a3e03251268325edbecdf620ce0103 100644 (file)
@@ -67,7 +67,7 @@
 #define QOS_QUEUE_NUM                          4
 #define RTL_MAC80211_NUM_QUEUE                 5
 #define REALTEK_USB_VENQT_MAX_BUF_SIZE         254
-
+#define RTL_USB_MAX_RX_COUNT                   100
 #define QBSS_LOAD_SIZE                         5
 #define MAX_WMMELE_LENGTH                      64
 
@@ -1629,6 +1629,10 @@ struct rtl_priv {
           interface or hardware */
        unsigned long status;
 
+       /* data buffer pointer for USB reads */
+       __le32 *usb_data;
+       int usb_data_index;
+
        /*This must be the last item so
           that it points to the data allocated
           beyond  this structure like:
index 6c274007d200f53fa950a4a737387d9714fb32e6..448da1f8c22f1796a0dcb8abe4c7646d3f0551c1 100644 (file)
@@ -47,7 +47,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,  \
                                                                        \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
-       .open = wl1251_open_file_generic,                               \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -84,7 +84,7 @@ static ssize_t sub## _ ##name## _read(struct file *file,              \
                                                                        \
 static const struct file_operations sub## _ ##name## _ops = {          \
        .read = sub## _ ##name## _read,                                 \
-       .open = wl1251_open_file_generic,                               \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -117,12 +117,6 @@ out:
        mutex_unlock(&wl->mutex);
 }
 
-static int wl1251_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
 
 DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
@@ -235,7 +229,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
 
 static const struct file_operations tx_queue_len_ops = {
        .read = tx_queue_len_read,
-       .open = wl1251_open_file_generic,
+       .open = simple_open,
        .llseek = generic_file_llseek,
 };
 
@@ -257,7 +251,7 @@ static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
 
 static const struct file_operations tx_queue_status_ops = {
        .read = tx_queue_status_read,
-       .open = wl1251_open_file_generic,
+       .open = simple_open,
        .llseek = generic_file_llseek,
 };
 
index 41302c7b1ad0089480a495a26dac4da2552eecf2..d1afb8e3b2ef0a3673b5ff9ef60f98379180bfa3 100644 (file)
@@ -479,6 +479,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
        cancel_work_sync(&wl->irq_work);
        cancel_work_sync(&wl->tx_work);
        cancel_work_sync(&wl->filter_work);
+       cancel_delayed_work_sync(&wl->elp_work);
 
        mutex_lock(&wl->mutex);
 
index f78694295c397f053f4a00115ff2aff22d8a4379..1b851f650e074eb795ffb708dd25b3c94a2cb9e1 100644 (file)
@@ -315,8 +315,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
 
        if (wl->irq)
                free_irq(wl->irq, wl);
-       kfree(wl_sdio);
        wl1251_free_hw(wl);
+       kfree(wl_sdio);
 
        sdio_claim_host(func);
        sdio_release_irq(func);
index e1cf727659650a90f9ae43f8636003409404eb00..564d49575c94d49cc98f5d718db2aa22c986adb0 100644 (file)
@@ -63,7 +63,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,  \
                                                                        \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
-       .open = wl1271_open_file_generic,                               \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -96,7 +96,7 @@ static ssize_t sub## _ ##name## _read(struct file *file,              \
                                                                        \
 static const struct file_operations sub## _ ##name## _ops = {          \
        .read = sub## _ ##name## _read,                                 \
-       .open = wl1271_open_file_generic,                               \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -126,12 +126,6 @@ out:
        mutex_unlock(&wl->mutex);
 }
 
-static int wl1271_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u");
 
 DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u");
@@ -243,7 +237,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
 
 static const struct file_operations tx_queue_len_ops = {
        .read = tx_queue_len_read,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -289,7 +283,7 @@ static ssize_t gpio_power_write(struct file *file,
 static const struct file_operations gpio_power_ops = {
        .read = gpio_power_read,
        .write = gpio_power_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -308,7 +302,7 @@ static ssize_t start_recovery_write(struct file *file,
 
 static const struct file_operations start_recovery_ops = {
        .write = start_recovery_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -372,7 +366,7 @@ out:
 static const struct file_operations dynamic_ps_timeout_ops = {
        .read = dynamic_ps_timeout_read,
        .write = dynamic_ps_timeout_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -441,7 +435,7 @@ out:
 static const struct file_operations forced_ps_ops = {
        .read = forced_ps_read,
        .write = forced_ps_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -483,7 +477,7 @@ static ssize_t split_scan_timeout_write(struct file *file,
 static const struct file_operations split_scan_timeout_ops = {
        .read = split_scan_timeout_read,
        .write = split_scan_timeout_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -566,7 +560,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 
 static const struct file_operations driver_state_ops = {
        .read = driver_state_read,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -675,7 +669,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
 
 static const struct file_operations vifs_state_ops = {
        .read = vifs_state_read,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -733,7 +727,7 @@ static ssize_t dtim_interval_write(struct file *file,
 static const struct file_operations dtim_interval_ops = {
        .read = dtim_interval_read,
        .write = dtim_interval_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -791,7 +785,7 @@ static ssize_t suspend_dtim_interval_write(struct file *file,
 static const struct file_operations suspend_dtim_interval_ops = {
        .read = suspend_dtim_interval_read,
        .write = suspend_dtim_interval_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -849,7 +843,7 @@ static ssize_t beacon_interval_write(struct file *file,
 static const struct file_operations beacon_interval_ops = {
        .read = beacon_interval_read,
        .write = beacon_interval_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -904,7 +898,7 @@ static ssize_t rx_streaming_interval_read(struct file *file,
 static const struct file_operations rx_streaming_interval_ops = {
        .read = rx_streaming_interval_read,
        .write = rx_streaming_interval_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -959,7 +953,7 @@ static ssize_t rx_streaming_always_read(struct file *file,
 static const struct file_operations rx_streaming_always_ops = {
        .read = rx_streaming_always_read,
        .write = rx_streaming_always_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
@@ -1003,7 +997,7 @@ out:
 
 static const struct file_operations beacon_filtering_ops = {
        .write = beacon_filtering_write,
-       .open = wl1271_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
index 663b32c2e93185f60b391b2706cbc847e4c8ffd2..0ebbb1906c308ba69ff0cff0125a84562e85116d 100644 (file)
@@ -1965,7 +1965,7 @@ static int __init netif_init(void)
        if (xen_initial_domain())
                return 0;
 
-       if (!xen_platform_pci_unplug)
+       if (xen_hvm_domain() && !xen_platform_pci_unplug)
                return -ENODEV;
 
        printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
index bba81216b4dbbbaee8b097a10a2ce505bd4bea9d..bf984b6dc477ce837c0a49ff265830e6efad2d80 100644 (file)
@@ -140,7 +140,7 @@ int of_gpio_simple_xlate(struct gpio_chip *gc,
        if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
                return -EINVAL;
 
-       if (gpiospec->args[0] > gc->ngpio)
+       if (gpiospec->args[0] >= gc->ngpio)
                return -EINVAL;
 
        if (flags)
index ee8fd037bb53c887de88cf67097c2c9dc710d72f..849357c1045c57b5c7a229dee3ccae27a9c2a922 100644 (file)
@@ -117,25 +117,17 @@ static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_
 }
 
 
-static int default_open(struct inode *inode, struct file *filp)
-{
-       if (inode->i_private)
-               filp->private_data = inode->i_private;
-       return 0;
-}
-
-
 static const struct file_operations ulong_fops = {
        .read           = ulong_read_file,
        .write          = ulong_write_file,
-       .open           = default_open,
+       .open           = simple_open,
        .llseek         = default_llseek,
 };
 
 
 static const struct file_operations ulong_ro_fops = {
        .read           = ulong_read_file,
-       .open           = default_open,
+       .open           = simple_open,
        .llseek         = default_llseek,
 };
 
@@ -187,7 +179,7 @@ static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t coun
 
 static const struct file_operations atomic_ro_fops = {
        .read           = atomic_read_file,
-       .open           = default_open,
+       .open           = simple_open,
        .llseek         = default_llseek,
 };
 
index 083a49fee56a8bbaa0d3834d92fd459225a69d0e..165274c064bc723b4c344b1755d760267074563a 100644 (file)
@@ -42,6 +42,7 @@ obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o
 obj-$(CONFIG_PARISC) += setup-bus.o
 obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
 obj-$(CONFIG_PPC) += setup-bus.o
+obj-$(CONFIG_FRV) += setup-bus.o
 obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
 obj-$(CONFIG_X86_VISWS) += setup-irq.o
 obj-$(CONFIG_MN10300) += setup-bus.o
index 0f150f271c2aa4040c8fcb9905783c99cb8b4e7a..1929c0c63b75b0773d45e39a845f663678b55d67 100644 (file)
@@ -200,7 +200,7 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
                return PCI_D1;
        case ACPI_STATE_D2:
                return PCI_D2;
-       case ACPI_STATE_D3:
+       case ACPI_STATE_D3_HOT:
                return PCI_D3hot;
        case ACPI_STATE_D3_COLD:
                return PCI_D3cold;
@@ -223,7 +223,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
                [PCI_D0] = ACPI_STATE_D0,
                [PCI_D1] = ACPI_STATE_D1,
                [PCI_D2] = ACPI_STATE_D2,
-               [PCI_D3hot] = ACPI_STATE_D3,
+               [PCI_D3hot] = ACPI_STATE_D3_HOT,
                [PCI_D3cold] = ACPI_STATE_D3
        };
        int error = -EINVAL;
index a55e248618cd00e7de495a078c3bb59d177123f4..86c63fe45d11bf22225afffd1317777edefcc8c7 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/security.h>
 #include <linux/pci-aspm.h>
 #include <linux/slab.h>
+#include <linux/vgaarb.h>
 #include "pci.h"
 
 static int sysfs_initialized;  /* = 0 */
@@ -417,6 +418,10 @@ static ssize_t
 boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
+       struct pci_dev *vga_dev = vga_default_device();
+
+       if (vga_dev)
+               return sprintf(buf, "%u\n", (pdev == vga_dev));
 
        return sprintf(buf, "%u\n",
                !!(pdev->resource[PCI_ROM_RESOURCE].flags &
index 815674415267d831a2618b1e1f977c080d34ac92..111569ccab434dda8262e1ddeb3a9aab04043171 100644 (file)
@@ -967,16 +967,59 @@ pci_save_state(struct pci_dev *dev)
        return 0;
 }
 
+static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
+                                    u32 saved_val, int retry)
+{
+       u32 val;
+
+       pci_read_config_dword(pdev, offset, &val);
+       if (val == saved_val)
+               return;
+
+       for (;;) {
+               dev_dbg(&pdev->dev, "restoring config space at offset "
+                       "%#x (was %#x, writing %#x)\n", offset, val, saved_val);
+               pci_write_config_dword(pdev, offset, saved_val);
+               if (retry-- <= 0)
+                       return;
+
+               pci_read_config_dword(pdev, offset, &val);
+               if (val == saved_val)
+                       return;
+
+               mdelay(1);
+       }
+}
+
+static void pci_restore_config_space_range(struct pci_dev *pdev,
+                                          int start, int end, int retry)
+{
+       int index;
+
+       for (index = end; index >= start; index--)
+               pci_restore_config_dword(pdev, 4 * index,
+                                        pdev->saved_config_space[index],
+                                        retry);
+}
+
+static void pci_restore_config_space(struct pci_dev *pdev)
+{
+       if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
+               pci_restore_config_space_range(pdev, 10, 15, 0);
+               /* Restore BARs before the command register. */
+               pci_restore_config_space_range(pdev, 4, 9, 10);
+               pci_restore_config_space_range(pdev, 0, 3, 0);
+       } else {
+               pci_restore_config_space_range(pdev, 0, 15, 0);
+       }
+}
+
 /** 
  * pci_restore_state - Restore the saved state of a PCI device
  * @dev: - PCI device that we're dealing with
  */
 void pci_restore_state(struct pci_dev *dev)
 {
-       int i;
-       u32 val;
-       int tries;
-
        if (!dev->state_saved)
                return;
 
@@ -984,24 +1027,8 @@ void pci_restore_state(struct pci_dev *dev)
        pci_restore_pcie_state(dev);
        pci_restore_ats_state(dev);
 
-       /*
-        * The Base Address register should be programmed before the command
-        * register(s)
-        */
-       for (i = 15; i >= 0; i--) {
-               pci_read_config_dword(dev, i * 4, &val);
-               tries = 10;             
-               while (tries && val != dev->saved_config_space[i]) {
-                       dev_dbg(&dev->dev, "restoring config "
-                               "space at offset %#x (was %#x, writing %#x)\n",
-                               i, val, (int)dev->saved_config_space[i]);
-                       pci_write_config_dword(dev,i * 4,
-                               dev->saved_config_space[i]);
-                       pci_read_config_dword(dev, i * 4, &val);
-                       mdelay(10);
-                       tries--;
-               }
-       }
+       pci_restore_config_space(dev);
+
        pci_restore_pcix_state(dev);
        pci_restore_msi_state(dev);
        pci_restore_iov_state(dev);
index fd00ff02ab4d0c51cf7b6eabe6b2a5ce9880fb12..d6cc62cb4cf7465fe22cb643fbde7a3f79f88a29 100644 (file)
@@ -290,6 +290,7 @@ static int pci_frontend_enable_msix(struct pci_dev *dev,
                } else {
                        printk(KERN_DEBUG "enable msix get value %x\n",
                                op.value);
+                       err = op.value;
                }
        } else {
                dev_err(&dev->dev, "enable msix get err %x\n", err);
index ec3b8cc188af512c2ba3645b6beec39b97f1ae40..df6296c5f47b4d6bfac67b8b47a14ad9d78b950e 100644 (file)
@@ -908,10 +908,6 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
        const struct pinctrl_ops *ops = pctldev->desc->pctlops;
        unsigned selector = 0;
 
-       /* No grouping */
-       if (!ops)
-               return 0;
-
        mutex_lock(&pinctrl_mutex);
 
        seq_puts(s, "registered pin groups:\n");
@@ -1225,6 +1221,19 @@ static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
 
 #endif
 
+static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
+{
+       const struct pinctrl_ops *ops = pctldev->desc->pctlops;
+
+       if (!ops ||
+           !ops->list_groups ||
+           !ops->get_group_name ||
+           !ops->get_group_pins)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * pinctrl_register() - register a pin controller device
  * @pctldesc: descriptor for this pin controller
@@ -1256,6 +1265,14 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
        INIT_LIST_HEAD(&pctldev->gpio_ranges);
        pctldev->dev = dev;
 
+       /* check core ops for sanity */
+       ret = pinctrl_check_ops(pctldev);
+       if (ret) {
+               pr_err("%s pinctrl ops lacks necessary functions\n",
+                       pctldesc->name);
+               goto out_err;
+       }
+
        /* If we're implementing pinmuxing, check the ops for sanity */
        if (pctldesc->pmxops) {
                ret = pinmux_check_ops(pctldev);
index bc8384c6f3ebe889d10678fe6147214c3b56858d..639db4d0aa768ef70f3be5293fc5209c8ba60cb8 100644 (file)
@@ -50,7 +50,7 @@
  */
 #undef START_IN_KERNEL_MODE
 
-#define DRV_VER "0.5.24"
+#define DRV_VER "0.5.26"
 
 /*
  * According to the Atom N270 datasheet,
@@ -83,8 +83,8 @@ static int kernelmode;
 #endif
 
 static unsigned int interval = 10;
-static unsigned int fanon = 63000;
-static unsigned int fanoff = 58000;
+static unsigned int fanon = 60000;
+static unsigned int fanoff = 53000;
 static unsigned int verbose;
 static unsigned int fanstate = ACERHDF_FAN_AUTO;
 static char force_bios[16];
@@ -150,6 +150,8 @@ static const struct bios_settings_t bios_tbl[] = {
        {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} },
        {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} },
        {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
+       /* LT1005u */
+       {"Acer", "LT-10Q", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
        /* Acer 1410 */
        {"Acer", "Aspire 1410", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1410", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
@@ -161,6 +163,7 @@ static const struct bios_settings_t bios_tbl[] = {
        {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1410", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1410", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
+       {"Acer", "Aspire 1410", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
        /* Acer 1810xx */
        {"Acer", "Aspire 1810TZ", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1810T",  "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
@@ -183,29 +186,44 @@ static const struct bios_settings_t bios_tbl[] = {
        {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1810T",  "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
+       {"Acer", "Aspire 1810T",  "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
        /* Acer 531 */
+       {"Acer", "AO531h", "v0.3104", 0x55, 0x58, {0x20, 0x00} },
        {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
+       {"Acer", "AO531h", "v0.3304", 0x55, 0x58, {0x20, 0x00} },
+       /* Acer 751 */
+       {"Acer", "AO751h", "V0.3212", 0x55, 0x58, {0x21, 0x00} },
+       /* Acer 1825 */
+       {"Acer", "Aspire 1825PTZ", "V1.3118", 0x55, 0x58, {0x9e, 0x00} },
+       {"Acer", "Aspire 1825PTZ", "V1.3127", 0x55, 0x58, {0x9e, 0x00} },
+       /* Acer TravelMate 7730 */
+       {"Acer", "TravelMate 7730G", "v0.3509", 0x55, 0x58, {0xaf, 0x00} },
        /* Gateway */
-       {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
-       {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} },
-       {"Gateway", "LT31",   "v1.3103", 0x55, 0x58, {0x9e, 0x00} },
-       {"Gateway", "LT31",   "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
-       {"Gateway", "LT31",   "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
+       {"Gateway", "AOA110", "v0.3103",  0x55, 0x58, {0x21, 0x00} },
+       {"Gateway", "AOA150", "v0.3103",  0x55, 0x58, {0x20, 0x00} },
+       {"Gateway", "LT31",   "v1.3103",  0x55, 0x58, {0x9e, 0x00} },
+       {"Gateway", "LT31",   "v1.3201",  0x55, 0x58, {0x9e, 0x00} },
+       {"Gateway", "LT31",   "v1.3302",  0x55, 0x58, {0x9e, 0x00} },
+       {"Gateway", "LT31",   "v1.3303t", 0x55, 0x58, {0x9e, 0x00} },
        /* Packard Bell */
-       {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} },
-       {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
-       {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
-       {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
-       {"Packard Bell", "DOTMU",  "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMU",  "v0.3120", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMU",  "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMU",  "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMU",  "v0.3115", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMU",  "v0.3117", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMU",  "v0.3119", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMU",  "v1.3204", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMA",  "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
-       {"Packard Bell", "DOTMA",  "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOA150",  "v0.3104",  0x55, 0x58, {0x21, 0x00} },
+       {"Packard Bell", "DOA150",  "v0.3105",  0x55, 0x58, {0x20, 0x00} },
+       {"Packard Bell", "AOA110",  "v0.3105",  0x55, 0x58, {0x21, 0x00} },
+       {"Packard Bell", "AOA150",  "v0.3105",  0x55, 0x58, {0x20, 0x00} },
+       {"Packard Bell", "ENBFT",   "V1.3118",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "ENBFT",   "V1.3127",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMU",   "v1.3303",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMU",   "v0.3120",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMU",   "v0.3108",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMU",   "v0.3113",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMU",   "v0.3115",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMU",   "v0.3117",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMU",   "v0.3119",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMU",   "v1.3204",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMA",   "v1.3201",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMA",   "v1.3302",  0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTMA",   "v1.3303t", 0x55, 0x58, {0x9e, 0x00} },
+       {"Packard Bell", "DOTVR46", "v1.3308",  0x55, 0x58, {0x9e, 0x00} },
        /* pewpew-terminator */
        {"", "", "", 0, 0, {0, 0} }
 };
@@ -701,15 +719,20 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Peter Feuerer");
 MODULE_DESCRIPTION("Aspire One temperature and fan driver");
 MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAO751h*:");
 MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
 MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1825PTZ:");
 MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
+MODULE_ALIAS("dmi:*:*Acer*:TravelMate*7730G:");
 MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
 MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
 MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
 MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOA*:");
 MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnENBFT*:");
 MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTVR46*:");
 
 module_init(acerhdf_init);
 module_exit(acerhdf_exit);
index a05fc9c955d86212cc274b8f78296c994342e2b0..e6c08ee8d46c0acb5d1652b2627bc65b5f2d4922 100644 (file)
@@ -212,6 +212,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {
                },
                .driver_data = &quirk_dell_vostro_v130,
        },
+       { }
 };
 
 static struct calling_interface_buffer *buffer;
index f7ba316e0ed612f7adddafd75fe7f94b13d78656..0ffdb3cde2bbc3ff569fee774dcd842333585031 100644 (file)
@@ -1565,7 +1565,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
                ips->poll_turbo_status = true;
 
        if (!ips_get_i915_syms(ips)) {
-               dev_err(&dev->dev, "failed to get i915 symbols, graphics turbo disabled\n");
+               dev_info(&dev->dev, "failed to get i915 symbols, graphics turbo disabled until i915 loads\n");
                ips->gpu_turbo_enabled = false;
        } else {
                dev_dbg(&dev->dev, "graphics turbo enabled\n");
index 0a3594c7e91263fcf7d1498e4e3634d4d8690ac2..bcbad8452a6f0ca5bb818b684837e207ffef7b5f 100644 (file)
@@ -78,7 +78,7 @@ static int __devinit mfld_pb_probe(struct platform_device *pdev)
 
        input_set_capability(input, EV_KEY, KEY_POWER);
 
-       error = request_threaded_irq(irq, NULL, mfld_pb_isr, 0,
+       error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_NO_SUSPEND,
                        DRIVER_NAME, input);
        if (error) {
                dev_err(&pdev->dev, "Unable to request irq %d for mfld power"
index 17499a55113ddedd9f1c7a22588b6e3caeda0d77..81fd606e47bc8d198d8bbab301b651e061d9a74d 100644 (file)
@@ -138,9 +138,10 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
        rdesc->type = REGULATOR_VOLTAGE;
        rdesc->owner = THIS_MODULE;
        sreg->mfd = anatopmfd;
-       ret = of_property_read_u32(np, "reg", &sreg->control_reg);
+       ret = of_property_read_u32(np, "anatop-reg-offset",
+                                  &sreg->control_reg);
        if (ret) {
-               dev_err(dev, "no reg property set\n");
+               dev_err(dev, "no anatop-reg-offset property set\n");
                goto anatop_probe_end;
        }
        ret = of_property_read_u32(np, "anatop-vol-bit-width",
@@ -213,7 +214,7 @@ static struct of_device_id __devinitdata of_anatop_regulator_match_tbl[] = {
        { /* end */ }
 };
 
-static struct platform_driver anatop_regulator = {
+static struct platform_driver anatop_regulator_driver = {
        .driver = {
                .name   = "anatop_regulator",
                .owner  = THIS_MODULE,
@@ -225,13 +226,13 @@ static struct platform_driver anatop_regulator = {
 
 static int __init anatop_regulator_init(void)
 {
-       return platform_driver_register(&anatop_regulator);
+       return platform_driver_register(&anatop_regulator_driver);
 }
 postcore_initcall(anatop_regulator_init);
 
 static void __exit anatop_regulator_exit(void)
 {
-       platform_driver_unregister(&anatop_regulator);
+       platform_driver_unregister(&anatop_regulator_driver);
 }
 module_exit(anatop_regulator_exit);
 
index c056abd7562a29b91666083371d888a698b85eef..e70dd382a009a2db05d78087b6e0e588584e6b6e 100644 (file)
@@ -2992,14 +2992,14 @@ void regulator_unregister(struct regulator_dev *rdev)
        if (rdev == NULL)
                return;
 
+       if (rdev->supply)
+               regulator_put(rdev->supply);
        mutex_lock(&regulator_list_mutex);
        debugfs_remove_recursive(rdev->debugfs);
        flush_work_sync(&rdev->disable_work.work);
        WARN_ON(rdev->open_count);
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
-       if (rdev->supply)
-               regulator_put(rdev->supply);
        kfree(rdev->constraints);
        device_unregister(&rdev->dev);
        mutex_unlock(&regulator_list_mutex);
index 30d0a15b8949a1407773f3d30df66d93961b0c3b..cacd33c9d042fae944b3684811ad1cdc20ef5268 100644 (file)
@@ -18,7 +18,6 @@ static void regulator_fixed_release(struct device *dev)
 
 /**
  * regulator_register_fixed - register a no-op fixed regulator
- * @name: supply name
  * @id: platform device id
  * @supplies: consumers for this regulator
  * @num_supplies: number of consumers
@@ -32,7 +31,7 @@ struct platform_device *regulator_register_fixed(int id,
        if (!data)
                return NULL;
 
-       data->cfg.supply_name = "dummy";
+       data->cfg.supply_name = "fixed-dummy";
        data->cfg.microvolts = 0;
        data->cfg.gpio = -EINVAL;
        data->cfg.enabled_at_boot = 1;
index e8cfc99dd8f066eb4a4ab3bc99007b70cf358bbc..845aa2263b8af7a1de6b7456fb4c8cf547167c18 100644 (file)
@@ -552,7 +552,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
        mc13xxx_lock(mc13892);
        ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val);
        if (ret)
-               goto err_free;
+               goto err_unlock;
 
        /* enable switch auto mode */
        if ((val & 0x0000FFFF) == 0x45d0) {
@@ -562,7 +562,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
                        MC13892_SWITCHERS4_SW1MODE_AUTO |
                        MC13892_SWITCHERS4_SW2MODE_AUTO);
                if (ret)
-                       goto err_free;
+                       goto err_unlock;
 
                ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5,
                        MC13892_SWITCHERS5_SW3MODE_M |
@@ -570,7 +570,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
                        MC13892_SWITCHERS5_SW3MODE_AUTO |
                        MC13892_SWITCHERS5_SW4MODE_AUTO);
                if (ret)
-                       goto err_free;
+                       goto err_unlock;
        }
        mc13xxx_unlock(mc13892);
 
@@ -612,10 +612,10 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
 err:
        while (--i >= 0)
                regulator_unregister(priv->regulators[i]);
+       return ret;
 
-err_free:
+err_unlock:
        mc13xxx_unlock(mc13892);
-
        return ret;
 }
 
index 58447db15de14c15ebc30cd24c62c1ad42a11e4f..4ca2db0590048e833ddb88e9eb2a88fee1e3c494 100644 (file)
@@ -311,8 +311,7 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
        struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
        const struct s5m_voltage_desc *desc;
        int reg_id = rdev_get_id(rdev);
-       int reg, mask, ret;
-       int i;
+       int sel, reg, mask, ret;
        u8 val;
 
        switch (reg_id) {
@@ -333,19 +332,20 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
 
        desc = reg_voltage_map[reg_id];
 
-       i = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
-       if (i < 0)
-               return i;
+       sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
+       if (sel < 0)
+               return sel;
 
        ret = s5m8767_get_voltage_register(rdev, &reg);
        if (ret)
                return ret;
 
        s5m_reg_read(s5m8767->iodev, reg, &val);
-       val = val & mask;
+       val &= ~mask;
+       val |= sel;
 
        ret = s5m_reg_write(s5m8767->iodev, reg, val);
-       *selector = i;
+       *selector = sel;
 
        return ret;
 }
index 29b615ce3affa75c259937c42cfb4fdc1401ff1c..cfc1f16f777125152678dfbdef3402d28e80c1cd 100644 (file)
@@ -79,6 +79,11 @@ static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev,
                                     unsigned selector)
 {
        struct tps6586x_regulator *info = rdev_get_drvdata(rdev);
+       int rid = rdev_get_id(rdev);
+
+       /* LDO0 has minimal voltage 1.2V rather than 1.25V */
+       if ((rid == TPS6586X_ID_LDO_0) && (selector == 0))
+               return (info->voltages[0] - 50) * 1000;
 
        return info->voltages[selector] * 1000;
 }
index 4904a40b0d46f6b3b870155a535312623e72a831..ff810e787eac52931933eb400784a17df8d7bced 100644 (file)
@@ -380,13 +380,15 @@ static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev,
        int i;
 
        for (i = 0; i < ARRAY_SIZE(wm831x_dcdc_ilim); i++) {
-               if (max_uA <= wm831x_dcdc_ilim[i])
+               if ((min_uA <= wm831x_dcdc_ilim[i]) &&
+                   (wm831x_dcdc_ilim[i] <= max_uA))
                        break;
        }
        if (i == ARRAY_SIZE(wm831x_dcdc_ilim))
                return -EINVAL;
 
-       return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK, i);
+       return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK,
+                              i << WM831X_DC1_HC_THR_SHIFT);
 }
 
 static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
@@ -400,7 +402,8 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
        if (val < 0)
                return val;
 
-       return wm831x_dcdc_ilim[val & WM831X_DC1_HC_THR_MASK];
+       val = (val & WM831X_DC1_HC_THR_MASK) >> WM831X_DC1_HC_THR_SHIFT;
+       return wm831x_dcdc_ilim[val];
 }
 
 static struct regulator_ops wm831x_buckv_ops = {
index 634aac3f2d5f86c511bc4390777437997b369f87..b414e09c56200c16aa5b191bf1fa10b93ad7426f 100644 (file)
@@ -101,7 +101,7 @@ static int wm831x_isink_set_current(struct regulator_dev *rdev,
 
        for (i = 0; i < ARRAY_SIZE(wm831x_isinkv_values); i++) {
                int val = wm831x_isinkv_values[i];
-               if (min_uA >= val && val <= max_uA) {
+               if (min_uA <= val && val <= max_uA) {
                        ret = wm831x_set_bits(wm831x, isink->reg,
                                              WM831X_CS1_ISEL_MASK, i);
                        return ret;
index f1e4ab0f9fda8e02d6857c705f8fc1032fc7f23b..641e9f6499d1ba30874811a1dd23eb759e1fb481 100644 (file)
@@ -506,22 +506,19 @@ static int wm831x_aldo_set_mode(struct regulator_dev *rdev,
 {
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = ldo->wm831x;
-       int ctrl_reg = ldo->base + WM831X_LDO_CONTROL;
        int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
        int ret;
 
 
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
-               ret = wm831x_set_bits(wm831x, on_reg,
-                                     WM831X_LDO7_ON_MODE, 0);
+               ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE, 0);
                if (ret < 0)
                        return ret;
                break;
 
        case REGULATOR_MODE_IDLE:
-               ret = wm831x_set_bits(wm831x, ctrl_reg,
-                                     WM831X_LDO7_ON_MODE,
+               ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE,
                                      WM831X_LDO7_ON_MODE);
                if (ret < 0)
                        return ret;
index ab1e183a74b51e3fcf779b4a07782d935e683105..05ecfb872319c605bb3166c547c7020c5f57c0e7 100644 (file)
@@ -99,7 +99,7 @@ static int get_isink_val(int min_uA, int max_uA, u16 *setting)
 {
        int i;
 
-       for (i = ARRAY_SIZE(isink_cur) - 1; i >= 0; i--) {
+       for (i = 0; i < ARRAY_SIZE(isink_cur); i++) {
                if (min_uA <= isink_cur[i] && max_uA >= isink_cur[i]) {
                        *setting = i;
                        return 0;
@@ -186,7 +186,7 @@ static int wm8350_isink_get_current(struct regulator_dev *rdev)
                return 0;
        }
 
-       return DIV_ROUND_CLOSEST(isink_cur[val], 100);
+       return isink_cur[val];
 }
 
 /* turn on ISINK followed by DCDC */
@@ -495,25 +495,25 @@ static int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev)
                val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER)
                        & ~WM8350_DCDC_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
-                       wm8350->pmic.dcdc1_hib_mode);
+                       val | wm8350->pmic.dcdc1_hib_mode);
                break;
        case WM8350_DCDC_3:
                val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER)
                        & ~WM8350_DCDC_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
-                       wm8350->pmic.dcdc3_hib_mode);
+                       val | wm8350->pmic.dcdc3_hib_mode);
                break;
        case WM8350_DCDC_4:
                val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER)
                        & ~WM8350_DCDC_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
-                       wm8350->pmic.dcdc4_hib_mode);
+                       val | wm8350->pmic.dcdc4_hib_mode);
                break;
        case WM8350_DCDC_6:
                val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER)
                        & ~WM8350_DCDC_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
-                       wm8350->pmic.dcdc6_hib_mode);
+                       val | wm8350->pmic.dcdc6_hib_mode);
                break;
        case WM8350_DCDC_2:
        case WM8350_DCDC_5:
@@ -535,25 +535,25 @@ static int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev)
                val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
                wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
-                       WM8350_DCDC_HIB_MODE_DIS);
+                                val | WM8350_DCDC_HIB_MODE_DIS);
                break;
        case WM8350_DCDC_3:
                val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
                wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
-                       WM8350_DCDC_HIB_MODE_DIS);
+                                val | WM8350_DCDC_HIB_MODE_DIS);
                break;
        case WM8350_DCDC_4:
                val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
                wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
-                       WM8350_DCDC_HIB_MODE_DIS);
+                                val | WM8350_DCDC_HIB_MODE_DIS);
                break;
        case WM8350_DCDC_6:
                val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
                wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
-                       WM8350_DCDC_HIB_MODE_DIS);
+                                val | WM8350_DCDC_HIB_MODE_DIS);
                break;
        case WM8350_DCDC_2:
        case WM8350_DCDC_5:
@@ -575,13 +575,13 @@ static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev)
                val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
                    & ~WM8350_DC2_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
-                                WM8350_DC2_HIB_MODE_ACTIVE);
+                   (WM8350_DC2_HIB_MODE_ACTIVE << WM8350_DC2_HIB_MODE_SHIFT));
                break;
        case WM8350_DCDC_5:
                val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
-                   & ~WM8350_DC2_HIB_MODE_MASK;
+                   & ~WM8350_DC5_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
-                                WM8350_DC5_HIB_MODE_ACTIVE);
+                   (WM8350_DC5_HIB_MODE_ACTIVE << WM8350_DC5_HIB_MODE_SHIFT));
                break;
        default:
                return -EINVAL;
@@ -600,13 +600,13 @@ static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev)
                val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
                    & ~WM8350_DC2_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
-                                WM8350_DC2_HIB_MODE_DISABLE);
+                   (WM8350_DC2_HIB_MODE_DISABLE << WM8350_DC2_HIB_MODE_SHIFT));
                break;
        case WM8350_DCDC_5:
                val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
-                   & ~WM8350_DC2_HIB_MODE_MASK;
+                   & ~WM8350_DC5_HIB_MODE_MASK;
                wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
-                                WM8350_DC2_HIB_MODE_DISABLE);
+                   (WM8350_DC5_HIB_MODE_DISABLE << WM8350_DC5_HIB_MODE_SHIFT));
                break;
        default:
                return -EINVAL;
@@ -749,7 +749,7 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
 
        /* all LDOs have same mV bits */
        val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
-       wm8350_reg_write(wm8350, volt_reg, WM8350_LDO1_HIB_MODE_DIS);
+       wm8350_reg_write(wm8350, volt_reg, val | WM8350_LDO1_HIB_MODE_DIS);
        return 0;
 }
 
index 70277a530133451dd298281c214f91bcc9d66006..85d31a69e1175f597cf6b24f50158803dabdfaf9 100644 (file)
@@ -50,16 +50,9 @@ static ssize_t rproc_trace_read(struct file *filp, char __user *userbuf,
        return simple_read_from_buffer(userbuf, count, ppos, trace->va, len);
 }
 
-static int rproc_open_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-
-       return 0;
-}
-
 static const struct file_operations trace_rproc_ops = {
        .read = rproc_trace_read,
-       .open = rproc_open_generic,
+       .open = simple_open,
        .llseek = generic_file_llseek,
 };
 
@@ -94,7 +87,7 @@ static ssize_t rproc_state_read(struct file *filp, char __user *userbuf,
 
 static const struct file_operations rproc_state_ops = {
        .read = rproc_state_read,
-       .open = rproc_open_generic,
+       .open = simple_open,
        .llseek = generic_file_llseek,
 };
 
@@ -114,7 +107,7 @@ static ssize_t rproc_name_read(struct file *filp, char __user *userbuf,
 
 static const struct file_operations rproc_name_ops = {
        .read = rproc_name_read,
-       .open = rproc_open_generic,
+       .open = simple_open,
        .llseek = generic_file_llseek,
 };
 
index afee0e8ae714426ad787fbe1be7d372c888e87f0..feddefc42109b5fe891b82b0c1ed520a6b9e9613 100644 (file)
@@ -72,9 +72,9 @@ static int pm860x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
        struct pm860x_rtc_info *info = dev_get_drvdata(dev);
 
        if (enabled)
-               pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, ALARM);
+               pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, ALARM_EN);
        else
-               pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, 0);
+               pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, 0);
        return 0;
 }
 
index cd188ab72f79c7bba15f5c59d055705d2a68e140..c293d0cdb10483502784653f8617d0f0ecb55562 100644 (file)
@@ -902,6 +902,7 @@ read_rtc:
                }
                ds1307->nvram->attr.name = "nvram";
                ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR;
+               sysfs_bin_attr_init(ds1307->nvram);
                ds1307->nvram->read = ds1307_nvram_read,
                ds1307->nvram->write = ds1307_nvram_write,
                ds1307->nvram->size = chip->nvram_size;
index 550292304b0fd6d0f30d47c5f07a0fdcaf2236fc..c9f890b088daa8d7a7e4de184a321183416a1af1 100644 (file)
@@ -213,7 +213,6 @@ static struct platform_driver efi_rtc_driver = {
                .name = "rtc-efi",
                .owner = THIS_MODULE,
        },
-       .probe = efi_rtc_probe,
        .remove = __exit_p(efi_rtc_remove),
 };
 
index 42f5f829b3ee1c0ff8adfcc3d120f47367b7cd05..029e421baaed49b7f62c58c0ef89454d2fa2053b 100644 (file)
@@ -360,12 +360,11 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op)
                                                &mpc5200_rtc_ops, THIS_MODULE);
        }
 
-       rtc->rtc->uie_unsupported = 1;
-
        if (IS_ERR(rtc->rtc)) {
                err = PTR_ERR(rtc->rtc);
                goto out_free_irq;
        }
+       rtc->rtc->uie_unsupported = 1;
 
        return 0;
 
index 692de7360e94100dfbc28e5b1dda51d824c24b89..684ef4bbfce432026bcbb526c6bccbd067f15cd8 100644 (file)
@@ -339,8 +339,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
        dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision);
 
        /* Enable the clockwatch on ST Variants */
-       if ((ldata->hw_designer == AMBA_VENDOR_ST) &&
-           (ldata->hw_revision > 1))
+       if (ldata->hw_designer == AMBA_VENDOR_ST)
                writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN,
                       ldata->base + RTC_CR);
 
index 7f8e6c247935d36ba3b79ffcc835374cadbaa60d..33b6ba0afa0de1b5034970ef7b78d7d3b468ed4f 100644 (file)
@@ -122,6 +122,7 @@ static const struct rtc_class_ops r9701_rtc_ops = {
 static int __devinit r9701_probe(struct spi_device *spi)
 {
        struct rtc_device *rtc;
+       struct rtc_time dt;
        unsigned char tmp;
        int res;
 
@@ -132,6 +133,27 @@ static int __devinit r9701_probe(struct spi_device *spi)
                return -ENODEV;
        }
 
+       /*
+        * The device seems to be present. Now check if the registers
+        * contain invalid values. If so, try to write a default date:
+        * 2000/1/1 00:00:00
+        */
+       r9701_get_datetime(&spi->dev, &dt);
+       if (rtc_valid_tm(&dt)) {
+               dev_info(&spi->dev, "trying to repair invalid date/time\n");
+               dt.tm_sec  = 0;
+               dt.tm_min  = 0;
+               dt.tm_hour = 0;
+               dt.tm_mday = 1;
+               dt.tm_mon  = 0;
+               dt.tm_year = 100;
+
+               if (r9701_set_datetime(&spi->dev, &dt)) {
+                       dev_err(&spi->dev, "cannot repair RTC register\n");
+                       return -ENODEV;
+               }
+       }
+
        rtc = rtc_device_register("r9701",
                                &spi->dev, &r9701_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc))
index 9ccea134a9965a1b2878f6873ae933fb72ca0b1a..3f3a29752369b092c7b99cca4ff33232f6fa605b 100644 (file)
@@ -40,6 +40,10 @@ enum s3c_cpu_type {
        TYPE_S3C64XX,
 };
 
+struct s3c_rtc_drv_data {
+       int cpu_type;
+};
+
 /* I have yet to find an S3C implementation with more than one
  * of these rtc blocks in */
 
@@ -446,10 +450,12 @@ static const struct of_device_id s3c_rtc_dt_match[];
 static inline int s3c_rtc_get_driver_data(struct platform_device *pdev)
 {
 #ifdef CONFIG_OF
+       struct s3c_rtc_drv_data *data;
        if (pdev->dev.of_node) {
                const struct of_device_id *match;
                match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node);
-               return match->data;
+               data = (struct s3c_rtc_drv_data *) match->data;
+               return data->cpu_type;
        }
 #endif
        return platform_get_device_id(pdev)->driver_data;
@@ -664,20 +670,27 @@ static int s3c_rtc_resume(struct platform_device *pdev)
 #define s3c_rtc_resume  NULL
 #endif
 
+static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
+       [TYPE_S3C2410] = { TYPE_S3C2410 },
+       [TYPE_S3C2416] = { TYPE_S3C2416 },
+       [TYPE_S3C2443] = { TYPE_S3C2443 },
+       [TYPE_S3C64XX] = { TYPE_S3C64XX },
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id s3c_rtc_dt_match[] = {
        {
-               .compatible = "samsung,s3c2410-rtc"
-               .data = TYPE_S3C2410,
+               .compatible = "samsung,s3c2410-rtc",
+               .data = &s3c_rtc_drv_data_array[TYPE_S3C2410],
        }, {
-               .compatible = "samsung,s3c2416-rtc"
-               .data = TYPE_S3C2416,
+               .compatible = "samsung,s3c2416-rtc",
+               .data = &s3c_rtc_drv_data_array[TYPE_S3C2416],
        }, {
-               .compatible = "samsung,s3c2443-rtc"
-               .data = TYPE_S3C2443,
+               .compatible = "samsung,s3c2443-rtc",
+               .data = &s3c_rtc_drv_data_array[TYPE_S3C2443],
        }, {
-               .compatible = "samsung,s3c6410-rtc"
-               .data = TYPE_S3C64XX,
+               .compatible = "samsung,s3c6410-rtc",
+               .data = &s3c_rtc_drv_data_array[TYPE_S3C64XX],
        },
        {},
 };
index 4c2c6df2a9efc38efe61ab559df44d17898ab2ec..258abeabf6246a1ed7e4db116713bb3128009fa0 100644 (file)
@@ -112,6 +112,7 @@ static const u8 twl6030_rtc_reg_map[] = {
 #define BIT_RTC_CTRL_REG_TEST_MODE_M             0x10
 #define BIT_RTC_CTRL_REG_SET_32_COUNTER_M        0x20
 #define BIT_RTC_CTRL_REG_GET_TIME_M              0x40
+#define BIT_RTC_CTRL_REG_RTC_V_OPT               0x80
 
 /* RTC_STATUS_REG bitfields */
 #define BIT_RTC_STATUS_REG_RUN_M                 0x02
@@ -235,25 +236,57 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
        unsigned char rtc_data[ALL_TIME_REGS + 1];
        int ret;
        u8 save_control;
+       u8 rtc_control;
 
        ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
-       if (ret < 0)
+       if (ret < 0) {
+               dev_err(dev, "%s: reading CTRL_REG, error %d\n", __func__, ret);
                return ret;
+       }
+       /* for twl6030/32 make sure BIT_RTC_CTRL_REG_GET_TIME_M is clear */
+       if (twl_class_is_6030()) {
+               if (save_control & BIT_RTC_CTRL_REG_GET_TIME_M) {
+                       save_control &= ~BIT_RTC_CTRL_REG_GET_TIME_M;
+                       ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+                       if (ret < 0) {
+                               dev_err(dev, "%s clr GET_TIME, error %d\n",
+                                       __func__, ret);
+                               return ret;
+                       }
+               }
+       }
 
-       save_control |= BIT_RTC_CTRL_REG_GET_TIME_M;
+       /* Copy RTC counting registers to static registers or latches */
+       rtc_control = save_control | BIT_RTC_CTRL_REG_GET_TIME_M;
 
-       ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
-       if (ret < 0)
+       /* for twl6030/32 enable read access to static shadowed registers */
+       if (twl_class_is_6030())
+               rtc_control |= BIT_RTC_CTRL_REG_RTC_V_OPT;
+
+       ret = twl_rtc_write_u8(rtc_control, REG_RTC_CTRL_REG);
+       if (ret < 0) {
+               dev_err(dev, "%s: writing CTRL_REG, error %d\n", __func__, ret);
                return ret;
+       }
 
        ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
                        (rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS);
 
        if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
+               dev_err(dev, "%s: reading data, error %d\n", __func__, ret);
                return ret;
        }
 
+       /* for twl6030 restore original state of rtc control register */
+       if (twl_class_is_6030()) {
+               ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+               if (ret < 0) {
+                       dev_err(dev, "%s: restore CTRL_REG, error %d\n",
+                               __func__, ret);
+                       return ret;
+               }
+       }
+
        tm->tm_sec = bcd2bin(rtc_data[0]);
        tm->tm_min = bcd2bin(rtc_data[1]);
        tm->tm_hour = bcd2bin(rtc_data[2]);
index c21871a4e73da92c06119fa3e0f3b7ad93298274..bc2e8a7c265b518e8049bdb1877e0cf57a1b19a2 100644 (file)
@@ -2844,6 +2844,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
        sector_t recid, trkid;
        unsigned int offs;
        unsigned int count, count_to_trk_end;
+       int ret;
 
        basedev = block->base;
        if (rq_data_dir(req) == READ) {
@@ -2884,8 +2885,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
 
        itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0);
        if (IS_ERR(itcw)) {
-               dasd_sfree_request(cqr, startdev);
-               return ERR_PTR(-EINVAL);
+               ret = -EINVAL;
+               goto out_error;
        }
        cqr->cpaddr = itcw_get_tcw(itcw);
        if (prepare_itcw(itcw, first_trk, last_trk,
@@ -2897,8 +2898,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
                /* Clock not in sync and XRC is enabled.
                 * Try again later.
                 */
-               dasd_sfree_request(cqr, startdev);
-               return ERR_PTR(-EAGAIN);
+               ret = -EAGAIN;
+               goto out_error;
        }
        len_to_track_end = 0;
        /*
@@ -2937,8 +2938,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
                                        tidaw_flags = 0;
                                last_tidaw = itcw_add_tidaw(itcw, tidaw_flags,
                                                            dst, part_len);
-                               if (IS_ERR(last_tidaw))
-                                       return ERR_PTR(-EINVAL);
+                               if (IS_ERR(last_tidaw)) {
+                                       ret = -EINVAL;
+                                       goto out_error;
+                               }
                                dst += part_len;
                        }
                }
@@ -2947,8 +2950,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
                        dst = page_address(bv->bv_page) + bv->bv_offset;
                        last_tidaw = itcw_add_tidaw(itcw, 0x00,
                                                    dst, bv->bv_len);
-                       if (IS_ERR(last_tidaw))
-                               return ERR_PTR(-EINVAL);
+                       if (IS_ERR(last_tidaw)) {
+                               ret = -EINVAL;
+                               goto out_error;
+                       }
                }
        }
        last_tidaw->flags |= TIDAW_FLAGS_LAST;
@@ -2968,6 +2973,9 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
        cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
        return cqr;
+out_error:
+       dasd_sfree_request(cqr, startdev);
+       return ERR_PTR(ret);
 }
 
 static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
index 85f4a9a5d12e5d00a7e445bd1e1e0a784eaf7cd0..73bef0bd394cab2df006f64bf5e3c25ecce7bb3f 100644 (file)
@@ -903,7 +903,7 @@ static int ur_set_online(struct ccw_device *cdev)
                goto fail_urdev_put;
        }
 
-       cdev_init(urd->char_device, &ur_fops);
+       urd->char_device->ops = &ur_fops;
        urd->char_device->dev = MKDEV(major, minor);
        urd->char_device->owner = ur_fops.owner;
 
index 120955c66410faf8e4c8254baebba15895d38aa9..8334dadc681de98eeb7ac78fed5755336ff58d63 100644 (file)
@@ -1672,7 +1672,8 @@ static void qeth_configure_blkt_default(struct qeth_card *card, char *prcd)
 {
        QETH_DBF_TEXT(SETUP, 2, "cfgblkt");
 
-       if (prcd[74] == 0xF0 && prcd[75] == 0xF0 && prcd[76] == 0xF5) {
+       if (prcd[74] == 0xF0 && prcd[75] == 0xF0 &&
+           (prcd[76] == 0xF5 || prcd[76] == 0xF6)) {
                card->info.blkt.time_total = 250;
                card->info.blkt.inter_packet = 5;
                card->info.blkt.inter_packet_jumbo = 15;
@@ -4540,7 +4541,8 @@ static void qeth_determine_capabilities(struct qeth_card *card)
                goto out_offline;
        }
        qeth_configure_unitaddr(card, prcd);
-       qeth_configure_blkt_default(card, prcd);
+       if (ddev_offline)
+               qeth_configure_blkt_default(card, prcd);
        kfree(prcd);
 
        rc = qdio_get_ssqd_desc(ddev, &card->ssqd);
index e002cd466e9a916d24d6064012d0488c854cd63e..467dc38246f93317221239e45a798c867bd1cdb0 100644 (file)
@@ -4549,8 +4549,12 @@ static int ipr_ata_slave_alloc(struct scsi_device *sdev)
        ENTER;
        if (sdev->sdev_target)
                sata_port = sdev->sdev_target->hostdata;
-       if (sata_port)
+       if (sata_port) {
                rc = ata_sas_port_init(sata_port->ap);
+               if (rc == 0)
+                       rc = ata_sas_sync_probe(sata_port->ap);
+       }
+
        if (rc)
                ipr_slave_destroy(sdev);
 
index ef9560dff295f9252bf9ccdf3a4d9d2de61d1852..cc83b66d45b7836aebe4fe55085935922fdb4a56 100644 (file)
@@ -1742,17 +1742,19 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 
        mfs = ntohs(flp->fl_csp.sp_bb_data) &
                FC_SP_BB_DATA_MASK;
-       if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
-           mfs <= lport->mfs) {
-               lport->mfs = mfs;
-               fc_host_maxframe_size(lport->host) = mfs;
-       } else {
+
+       if (mfs < FC_SP_MIN_MAX_PAYLOAD || mfs > FC_SP_MAX_MAX_PAYLOAD) {
                FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, "
                             "lport->mfs:%hu\n", mfs, lport->mfs);
                fc_lport_error(lport, fp);
                goto err;
        }
 
+       if (mfs <= lport->mfs) {
+               lport->mfs = mfs;
+               fc_host_maxframe_size(lport->host) = mfs;
+       }
+
        csp_flags = ntohs(flp->fl_csp.sp_features);
        r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
        e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
index bc0cecc6ad62492c02b153ecee767ed0cfd650b1..441d88ad99a7bb3abadb8b1e9af25281ced8334b 100644 (file)
@@ -546,11 +546,12 @@ static struct ata_port_info sata_port_info = {
        .port_ops = &sas_sata_ops
 };
 
-int sas_ata_init_host_and_port(struct domain_device *found_dev)
+int sas_ata_init(struct domain_device *found_dev)
 {
        struct sas_ha_struct *ha = found_dev->port->ha;
        struct Scsi_Host *shost = ha->core.shost;
        struct ata_port *ap;
+       int rc;
 
        ata_host_init(&found_dev->sata_dev.ata_host,
                      ha->dev,
@@ -567,8 +568,11 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev)
        ap->private_data = found_dev;
        ap->cbl = ATA_CBL_SATA;
        ap->scsi_host = shost;
-       /* publish initialized ata port */
-       smp_wmb();
+       rc = ata_sas_port_init(ap);
+       if (rc) {
+               ata_sas_port_destroy(ap);
+               return rc;
+       }
        found_dev->sata_dev.ap = ap;
 
        return 0;
@@ -648,18 +652,13 @@ static void sas_get_ata_command_set(struct domain_device *dev)
 void sas_probe_sata(struct asd_sas_port *port)
 {
        struct domain_device *dev, *n;
-       int err;
 
        mutex_lock(&port->ha->disco_mutex);
-       list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
+       list_for_each_entry(dev, &port->disco_list, disco_list_node) {
                if (!dev_is_sata(dev))
                        continue;
 
-               err = sas_ata_init_host_and_port(dev);
-               if (err)
-                       sas_fail_probe(dev, __func__, err);
-               else
-                       ata_sas_async_port_init(dev->sata_dev.ap);
+               ata_sas_async_probe(dev->sata_dev.ap);
        }
        mutex_unlock(&port->ha->disco_mutex);
 
@@ -718,18 +717,6 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie)
        sas_put_device(dev);
 }
 
-static bool sas_ata_dev_eh_valid(struct domain_device *dev)
-{
-       struct ata_port *ap;
-
-       if (!dev_is_sata(dev))
-               return false;
-       ap = dev->sata_dev.ap;
-       /* consume fully initialized ata ports */
-       smp_rmb();
-       return !!ap;
-}
-
 void sas_ata_strategy_handler(struct Scsi_Host *shost)
 {
        struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
@@ -753,7 +740,7 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost)
 
                spin_lock(&port->dev_list_lock);
                list_for_each_entry(dev, &port->dev_list, dev_list_node) {
-                       if (!sas_ata_dev_eh_valid(dev))
+                       if (!dev_is_sata(dev))
                                continue;
                        async_schedule_domain(async_sas_ata_eh, dev, &async);
                }
index 3646796756028bd1258a7dd920025d860baa294d..629a0865b130db3fc25036103ab78aaf94eba5ea 100644 (file)
@@ -72,6 +72,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
        struct asd_sas_phy *phy;
        struct sas_rphy *rphy;
        struct domain_device *dev;
+       int rc = -ENODEV;
 
        dev = sas_alloc_device();
        if (!dev)
@@ -110,9 +111,16 @@ static int sas_get_port_device(struct asd_sas_port *port)
 
        sas_init_dev(dev);
 
+       dev->port = port;
        switch (dev->dev_type) {
-       case SAS_END_DEV:
        case SATA_DEV:
+               rc = sas_ata_init(dev);
+               if (rc) {
+                       rphy = NULL;
+                       break;
+               }
+               /* fall through */
+       case SAS_END_DEV:
                rphy = sas_end_device_alloc(port->port);
                break;
        case EDGE_DEV:
@@ -131,19 +139,14 @@ static int sas_get_port_device(struct asd_sas_port *port)
 
        if (!rphy) {
                sas_put_device(dev);
-               return -ENODEV;
+               return rc;
        }
 
-       spin_lock_irq(&port->phy_list_lock);
-       list_for_each_entry(phy, &port->phy_list, port_phy_el)
-               sas_phy_set_target(phy, dev);
-       spin_unlock_irq(&port->phy_list_lock);
        rphy->identify.phy_identifier = phy->phy->identify.phy_identifier;
        memcpy(dev->sas_addr, port->attached_sas_addr, SAS_ADDR_SIZE);
        sas_fill_in_rphy(dev, rphy);
        sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr);
        port->port_dev = dev;
-       dev->port = port;
        dev->linkrate = port->linkrate;
        dev->min_linkrate = port->linkrate;
        dev->max_linkrate = port->linkrate;
@@ -155,6 +158,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
        sas_device_set_phy(dev, port->port);
 
        dev->rphy = rphy;
+       get_device(&dev->rphy->dev);
 
        if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV)
                list_add_tail(&dev->disco_list_node, &port->disco_list);
@@ -164,6 +168,11 @@ static int sas_get_port_device(struct asd_sas_port *port)
                spin_unlock_irq(&port->dev_list_lock);
        }
 
+       spin_lock_irq(&port->phy_list_lock);
+       list_for_each_entry(phy, &port->phy_list, port_phy_el)
+               sas_phy_set_target(phy, dev);
+       spin_unlock_irq(&port->phy_list_lock);
+
        return 0;
 }
 
@@ -205,8 +214,7 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev)
 static void sas_probe_devices(struct work_struct *work)
 {
        struct domain_device *dev, *n;
-       struct sas_discovery_event *ev =
-               container_of(work, struct sas_discovery_event, work);
+       struct sas_discovery_event *ev = to_sas_discovery_event(work);
        struct asd_sas_port *port = ev->port;
 
        clear_bit(DISCE_PROBE, &port->disc.pending);
@@ -255,6 +263,9 @@ void sas_free_device(struct kref *kref)
 {
        struct domain_device *dev = container_of(kref, typeof(*dev), kref);
 
+       put_device(&dev->rphy->dev);
+       dev->rphy = NULL;
+
        if (dev->parent)
                sas_put_device(dev->parent);
 
@@ -291,8 +302,7 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d
 static void sas_destruct_devices(struct work_struct *work)
 {
        struct domain_device *dev, *n;
-       struct sas_discovery_event *ev =
-               container_of(work, struct sas_discovery_event, work);
+       struct sas_discovery_event *ev = to_sas_discovery_event(work);
        struct asd_sas_port *port = ev->port;
 
        clear_bit(DISCE_DESTRUCT, &port->disc.pending);
@@ -302,7 +312,6 @@ static void sas_destruct_devices(struct work_struct *work)
 
                sas_remove_children(&dev->rphy->dev);
                sas_rphy_delete(dev->rphy);
-               dev->rphy = NULL;
                sas_unregister_common_dev(port, dev);
        }
 }
@@ -314,11 +323,11 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
                /* this rphy never saw sas_rphy_add */
                list_del_init(&dev->disco_list_node);
                sas_rphy_free(dev->rphy);
-               dev->rphy = NULL;
                sas_unregister_common_dev(port, dev);
+               return;
        }
 
-       if (dev->rphy && !test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
+       if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
                sas_rphy_unlink(dev->rphy);
                list_move_tail(&dev->disco_list_node, &port->destroy_list);
                sas_discover_event(dev->port, DISCE_DESTRUCT);
@@ -377,8 +386,7 @@ static void sas_discover_domain(struct work_struct *work)
 {
        struct domain_device *dev;
        int error = 0;
-       struct sas_discovery_event *ev =
-               container_of(work, struct sas_discovery_event, work);
+       struct sas_discovery_event *ev = to_sas_discovery_event(work);
        struct asd_sas_port *port = ev->port;
 
        clear_bit(DISCE_DISCOVER_DOMAIN, &port->disc.pending);
@@ -419,8 +427,6 @@ static void sas_discover_domain(struct work_struct *work)
 
        if (error) {
                sas_rphy_free(dev->rphy);
-               dev->rphy = NULL;
-
                list_del_init(&dev->disco_list_node);
                spin_lock_irq(&port->dev_list_lock);
                list_del_init(&dev->dev_list_node);
@@ -437,8 +443,7 @@ static void sas_discover_domain(struct work_struct *work)
 static void sas_revalidate_domain(struct work_struct *work)
 {
        int res = 0;
-       struct sas_discovery_event *ev =
-               container_of(work, struct sas_discovery_event, work);
+       struct sas_discovery_event *ev = to_sas_discovery_event(work);
        struct asd_sas_port *port = ev->port;
        struct sas_ha_struct *ha = port->ha;
 
@@ -466,21 +471,25 @@ static void sas_revalidate_domain(struct work_struct *work)
 
 /* ---------- Events ---------- */
 
-static void sas_chain_work(struct sas_ha_struct *ha, struct work_struct *work)
+static void sas_chain_work(struct sas_ha_struct *ha, struct sas_work *sw)
 {
-       /* chained work is not subject to SA_HA_DRAINING or SAS_HA_REGISTERED */
-       scsi_queue_work(ha->core.shost, work);
+       /* chained work is not subject to SA_HA_DRAINING or
+        * SAS_HA_REGISTERED, because it is either submitted in the
+        * workqueue, or known to be submitted from a context that is
+        * not racing against draining
+        */
+       scsi_queue_work(ha->core.shost, &sw->work);
 }
 
 static void sas_chain_event(int event, unsigned long *pending,
-                           struct work_struct *work,
+                           struct sas_work *sw,
                            struct sas_ha_struct *ha)
 {
        if (!test_and_set_bit(event, pending)) {
                unsigned long flags;
 
                spin_lock_irqsave(&ha->state_lock, flags);
-               sas_chain_work(ha, work);
+               sas_chain_work(ha, sw);
                spin_unlock_irqrestore(&ha->state_lock, flags);
        }
 }
@@ -519,7 +528,7 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port)
 
        disc->pending = 0;
        for (i = 0; i < DISC_NUM_EVENTS; i++) {
-               INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]);
+               INIT_SAS_WORK(&disc->disc_work[i].work, sas_event_fns[i]);
                disc->disc_work[i].port = port;
        }
 }
index 16639bbae629d279af43a33f78072e4d88d09fc8..4e4292d210c1478131b6eda3260f51b6ffc3fa52 100644 (file)
 #include "sas_internal.h"
 #include "sas_dump.h"
 
-void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work)
+void sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw)
 {
        if (!test_bit(SAS_HA_REGISTERED, &ha->state))
                return;
 
-       if (test_bit(SAS_HA_DRAINING, &ha->state))
-               list_add(&work->entry, &ha->defer_q);
-       else
-               scsi_queue_work(ha->core.shost, work);
+       if (test_bit(SAS_HA_DRAINING, &ha->state)) {
+               /* add it to the defer list, if not already pending */
+               if (list_empty(&sw->drain_node))
+                       list_add(&sw->drain_node, &ha->defer_q);
+       } else
+               scsi_queue_work(ha->core.shost, &sw->work);
 }
 
 static void sas_queue_event(int event, unsigned long *pending,
-                           struct work_struct *work,
+                           struct sas_work *work,
                            struct sas_ha_struct *ha)
 {
        if (!test_and_set_bit(event, pending)) {
@@ -55,7 +57,7 @@ static void sas_queue_event(int event, unsigned long *pending,
 void __sas_drain_work(struct sas_ha_struct *ha)
 {
        struct workqueue_struct *wq = ha->core.shost->work_q;
-       struct work_struct *w, *_w;
+       struct sas_work *sw, *_sw;
 
        set_bit(SAS_HA_DRAINING, &ha->state);
        /* flush submitters */
@@ -66,9 +68,9 @@ void __sas_drain_work(struct sas_ha_struct *ha)
 
        spin_lock_irq(&ha->state_lock);
        clear_bit(SAS_HA_DRAINING, &ha->state);
-       list_for_each_entry_safe(w, _w, &ha->defer_q, entry) {
-               list_del_init(&w->entry);
-               sas_queue_work(ha, w);
+       list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) {
+               list_del_init(&sw->drain_node);
+               sas_queue_work(ha, sw);
        }
        spin_unlock_irq(&ha->state_lock);
 }
@@ -151,7 +153,7 @@ int sas_init_events(struct sas_ha_struct *sas_ha)
        int i;
 
        for (i = 0; i < HA_NUM_EVENTS; i++) {
-               INIT_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]);
+               INIT_SAS_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]);
                sas_ha->ha_events[i].ha = sas_ha;
        }
 
index 05acd9e35fc4def9872d8b19debdb2875302b65b..caa0525d2523037f7bace6a27cfdb007176b0448 100644 (file)
@@ -202,6 +202,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        u8 sas_addr[SAS_ADDR_SIZE];
        struct smp_resp *resp = rsp;
        struct discover_resp *dr = &resp->disc;
+       struct sas_ha_struct *ha = dev->port->ha;
        struct expander_device *ex = &dev->ex_dev;
        struct ex_phy *phy = &ex->ex_phy[phy_id];
        struct sas_rphy *rphy = dev->rphy;
@@ -209,6 +210,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        char *type;
 
        if (new_phy) {
+               if (WARN_ON_ONCE(test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)))
+                       return;
                phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
 
                /* FIXME: error_handling */
@@ -233,6 +236,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
 
        phy->attached_dev_type = to_dev_type(dr);
+       if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
+               goto out;
        phy->phy_id = phy_id;
        phy->linkrate = dr->linkrate;
        phy->attached_sata_host = dr->attached_sata_host;
@@ -240,7 +245,14 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        phy->attached_sata_ps   = dr->attached_sata_ps;
        phy->attached_iproto = dr->iproto << 1;
        phy->attached_tproto = dr->tproto << 1;
-       memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
+       /* help some expanders that fail to zero sas_address in the 'no
+        * device' case
+        */
+       if (phy->attached_dev_type == NO_DEVICE ||
+           phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
+               memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+       else
+               memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
        phy->attached_phy_id = dr->attached_phy_id;
        phy->phy_change_count = dr->change_count;
        phy->routing_attr = dr->routing_attr;
@@ -266,6 +278,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
                        return;
                }
 
+ out:
        switch (phy->attached_dev_type) {
        case SATA_PENDING:
                type = "stp pending";
@@ -304,7 +317,15 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp)
        else
                return;
 
-       SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
+       /* if the attached device type changed and ata_eh is active,
+        * make sure we run revalidation when eh completes (see:
+        * sas_enable_revalidation)
+        */
+       if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
+               set_bit(DISCE_REVALIDATE_DOMAIN, &dev->port->disc.pending);
+
+       SAS_DPRINTK("%sex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
+                   test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state) ? "ata: " : "",
                    SAS_ADDR(dev->sas_addr), phy->phy_id,
                    sas_route_char(dev, phy), phy->linkrate,
                    SAS_ADDR(phy->attached_sas_addr), type);
@@ -776,13 +797,16 @@ static struct domain_device *sas_ex_discover_end_dev(
                if (res)
                        goto out_free;
 
+               sas_init_dev(child);
+               res = sas_ata_init(child);
+               if (res)
+                       goto out_free;
                rphy = sas_end_device_alloc(phy->port);
-               if (unlikely(!rphy))
+               if (!rphy)
                        goto out_free;
 
-               sas_init_dev(child);
-
                child->rphy = rphy;
+               get_device(&rphy->dev);
 
                list_add_tail(&child->disco_list_node, &parent->port->disco_list);
 
@@ -806,6 +830,7 @@ static struct domain_device *sas_ex_discover_end_dev(
                sas_init_dev(child);
 
                child->rphy = rphy;
+               get_device(&rphy->dev);
                sas_fill_in_rphy(child, rphy);
 
                list_add_tail(&child->disco_list_node, &parent->port->disco_list);
@@ -830,8 +855,6 @@ static struct domain_device *sas_ex_discover_end_dev(
 
  out_list_del:
        sas_rphy_free(child->rphy);
-       child->rphy = NULL;
-
        list_del(&child->disco_list_node);
        spin_lock_irq(&parent->port->dev_list_lock);
        list_del(&child->dev_list_node);
@@ -911,6 +934,7 @@ static struct domain_device *sas_ex_discover_expander(
        }
        port = parent->port;
        child->rphy = rphy;
+       get_device(&rphy->dev);
        edev = rphy_to_expander_device(rphy);
        child->dev_type = phy->attached_dev_type;
        kref_get(&parent->kref);
@@ -934,6 +958,7 @@ static struct domain_device *sas_ex_discover_expander(
 
        res = sas_discover_expander(child);
        if (res) {
+               sas_rphy_delete(rphy);
                spin_lock_irq(&parent->port->dev_list_lock);
                list_del(&child->dev_list_node);
                spin_unlock_irq(&parent->port->dev_list_lock);
@@ -1718,9 +1743,17 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
                int phy_change_count = 0;
 
                res = sas_get_phy_change_count(dev, i, &phy_change_count);
-               if (res)
-                       goto out;
-               else if (phy_change_count != ex->ex_phy[i].phy_change_count) {
+               switch (res) {
+               case SMP_RESP_PHY_VACANT:
+               case SMP_RESP_NO_PHY:
+                       continue;
+               case SMP_RESP_FUNC_ACC:
+                       break;
+               default:
+                       return res;
+               }
+
+               if (phy_change_count != ex->ex_phy[i].phy_change_count) {
                        if (update)
                                ex->ex_phy[i].phy_change_count =
                                        phy_change_count;
@@ -1728,8 +1761,7 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
                        return 0;
                }
        }
-out:
-       return res;
+       return 0;
 }
 
 static int sas_get_ex_change_count(struct domain_device *dev, int *ecc)
index 120bff64be303c67cc66aba9fdfae3af7d58e2c8..10cb5ae30977cfaa9da66f5ad0b7b497aa51b758 100644 (file)
@@ -94,8 +94,7 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
 
 void sas_hae_reset(struct work_struct *work)
 {
-       struct sas_ha_event *ev =
-               container_of(work, struct sas_ha_event, work);
+       struct sas_ha_event *ev = to_sas_ha_event(work);
        struct sas_ha_struct *ha = ev->ha;
 
        clear_bit(HAE_RESET, &ha->pending);
@@ -369,14 +368,14 @@ static void sas_phy_release(struct sas_phy *phy)
 
 static void phy_reset_work(struct work_struct *work)
 {
-       struct sas_phy_data *d = container_of(work, typeof(*d), reset_work);
+       struct sas_phy_data *d = container_of(work, typeof(*d), reset_work.work);
 
        d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset);
 }
 
 static void phy_enable_work(struct work_struct *work)
 {
-       struct sas_phy_data *d = container_of(work, typeof(*d), enable_work);
+       struct sas_phy_data *d = container_of(work, typeof(*d), enable_work.work);
 
        d->enable_result = sas_phy_enable(d->phy, d->enable);
 }
@@ -389,8 +388,8 @@ static int sas_phy_setup(struct sas_phy *phy)
                return -ENOMEM;
 
        mutex_init(&d->event_lock);
-       INIT_WORK(&d->reset_work, phy_reset_work);
-       INIT_WORK(&d->enable_work, phy_enable_work);
+       INIT_SAS_WORK(&d->reset_work, phy_reset_work);
+       INIT_SAS_WORK(&d->enable_work, phy_enable_work);
        d->phy = phy;
        phy->hostdata = d;
 
index f05c63879949a1b70ef1553571d54e87922f0d18..507e4cf12e56cef87cd3b80af00215cc62db6078 100644 (file)
@@ -45,10 +45,10 @@ struct sas_phy_data {
        struct mutex event_lock;
        int hard_reset;
        int reset_result;
-       struct work_struct reset_work;
+       struct sas_work reset_work;
        int enable;
        int enable_result;
-       struct work_struct enable_work;
+       struct sas_work enable_work;
 };
 
 void sas_scsi_recover_host(struct Scsi_Host *shost);
@@ -80,7 +80,7 @@ void sas_porte_broadcast_rcvd(struct work_struct *work);
 void sas_porte_link_reset_err(struct work_struct *work);
 void sas_porte_timer_event(struct work_struct *work);
 void sas_porte_hard_reset(struct work_struct *work);
-void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work);
+void sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw);
 
 int sas_notify_lldd_dev_found(struct domain_device *);
 void sas_notify_lldd_dev_gone(struct domain_device *);
index dcfd4a9105c5e2429b210bf427f85cf97ae2620b..521422e857ab330ee3a659ad11dae2dd02aee9f0 100644 (file)
@@ -32,8 +32,7 @@
 
 static void sas_phye_loss_of_signal(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
 
        clear_bit(PHYE_LOSS_OF_SIGNAL, &phy->phy_events_pending);
@@ -43,8 +42,7 @@ static void sas_phye_loss_of_signal(struct work_struct *work)
 
 static void sas_phye_oob_done(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
 
        clear_bit(PHYE_OOB_DONE, &phy->phy_events_pending);
@@ -53,8 +51,7 @@ static void sas_phye_oob_done(struct work_struct *work)
 
 static void sas_phye_oob_error(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
        struct sas_ha_struct *sas_ha = phy->ha;
        struct asd_sas_port *port = phy->port;
@@ -85,8 +82,7 @@ static void sas_phye_oob_error(struct work_struct *work)
 
 static void sas_phye_spinup_hold(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
        struct sas_ha_struct *sas_ha = phy->ha;
        struct sas_internal *i =
@@ -127,14 +123,12 @@ int sas_register_phys(struct sas_ha_struct *sas_ha)
                phy->error = 0;
                INIT_LIST_HEAD(&phy->port_phy_el);
                for (k = 0; k < PORT_NUM_EVENTS; k++) {
-                       INIT_WORK(&phy->port_events[k].work,
-                                 sas_port_event_fns[k]);
+                       INIT_SAS_WORK(&phy->port_events[k].work, sas_port_event_fns[k]);
                        phy->port_events[k].phy = phy;
                }
 
                for (k = 0; k < PHY_NUM_EVENTS; k++) {
-                       INIT_WORK(&phy->phy_events[k].work,
-                                 sas_phy_event_fns[k]);
+                       INIT_SAS_WORK(&phy->phy_events[k].work, sas_phy_event_fns[k]);
                        phy->phy_events[k].phy = phy;
                }
 
@@ -144,8 +138,7 @@ int sas_register_phys(struct sas_ha_struct *sas_ha)
                spin_lock_init(&phy->sas_prim_lock);
                phy->frame_rcvd_size = 0;
 
-               phy->phy = sas_phy_alloc(&sas_ha->core.shost->shost_gendev,
-                                        i);
+               phy->phy = sas_phy_alloc(&sas_ha->core.shost->shost_gendev, i);
                if (!phy->phy)
                        return -ENOMEM;
 
index eb19c016d5001b1890feafa0f8ae140e1982a1bf..e884a8c58a0ccb181424051281fda4b4a45fc1a9 100644 (file)
@@ -123,7 +123,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
        spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
 
        if (!port->port) {
-               port->port = sas_port_alloc(phy->phy->dev.parent, phy->id);
+               port->port = sas_port_alloc(phy->phy->dev.parent, port->id);
                BUG_ON(!port->port);
                sas_port_add(port->port);
        }
@@ -208,8 +208,7 @@ void sas_deform_port(struct asd_sas_phy *phy, int gone)
 
 void sas_porte_bytes_dmaed(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
 
        clear_bit(PORTE_BYTES_DMAED, &phy->port_events_pending);
@@ -219,8 +218,7 @@ void sas_porte_bytes_dmaed(struct work_struct *work)
 
 void sas_porte_broadcast_rcvd(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
        unsigned long flags;
        u32 prim;
@@ -237,8 +235,7 @@ void sas_porte_broadcast_rcvd(struct work_struct *work)
 
 void sas_porte_link_reset_err(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
 
        clear_bit(PORTE_LINK_RESET_ERR, &phy->port_events_pending);
@@ -248,8 +245,7 @@ void sas_porte_link_reset_err(struct work_struct *work)
 
 void sas_porte_timer_event(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
 
        clear_bit(PORTE_TIMER_EVENT, &phy->port_events_pending);
@@ -259,8 +255,7 @@ void sas_porte_timer_event(struct work_struct *work)
 
 void sas_porte_hard_reset(struct work_struct *work)
 {
-       struct asd_sas_event *ev =
-               container_of(work, struct asd_sas_event, work);
+       struct asd_sas_event *ev = to_asd_sas_event(work);
        struct asd_sas_phy *phy = ev->phy;
 
        clear_bit(PORTE_HARD_RESET, &phy->port_events_pending);
index 5bdf2eecb1782dd4c33f863607d045ed27535fe9..af04b0d6688dbb19400fbf498781b37bb92ea420 100644 (file)
@@ -997,13 +997,6 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf,
        return nbytes;
 }
 
-static int
-lpfc_debugfs_dif_err_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t
 lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
        size_t nbytes, loff_t *ppos)
@@ -3541,7 +3534,7 @@ static const struct file_operations lpfc_debugfs_op_dumpDif = {
 #undef lpfc_debugfs_op_dif_err
 static const struct file_operations lpfc_debugfs_op_dif_err = {
        .owner =        THIS_MODULE,
-       .open =         lpfc_debugfs_dif_err_open,
+       .open =         simple_open,
        .llseek =       lpfc_debugfs_lseek,
        .read =         lpfc_debugfs_dif_err_read,
        .write =        lpfc_debugfs_dif_err_write,
index 2cfcbffa41fd559b075e7c75eae57e2c7f637488..386f0c53bea7e17cf2b74fe29af5d1d7176c25b9 100644 (file)
@@ -835,7 +835,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
 
        scsi_eh_restore_cmnd(scmd, &ses);
 
-       if (sdrv->eh_action)
+       if (sdrv && sdrv->eh_action)
                rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn);
 
        return rtn;
index ead6405f3e51465f5dfe95412cb4d242fa704608..5dfd7495d1a1bc4231123760090aa3d38eb9a764 100644 (file)
@@ -1638,7 +1638,7 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
                                         request_fn_proc *request_fn)
 {
        struct request_queue *q;
-       struct device *dev = shost->shost_gendev.parent;
+       struct device *dev = shost->dma_dev;
 
        q = blk_init_queue(request_fn, NULL);
        if (!q)
index 3ed748355b98f629619bdb5ff9e0eae4dbf2bf32..00c024039c9713a7b8468d91f5a7e42316db65d5 100644 (file)
@@ -74,7 +74,7 @@ config SPI_ATMEL
          This selects a driver for the Atmel SPI Controller, present on
          many AT32 (AVR32) and AT91 (ARM) chips.
 
-config SPI_BFIN
+config SPI_BFIN5XX
        tristate "SPI controller driver for ADI Blackfin5xx"
        depends on BLACKFIN
        help
index a1d48e0ba3dc91ad5e7ba8691be345ed5f1cc428..9d75d2198ff58bcce9ca60e587b72112a0b3c292 100644 (file)
@@ -15,7 +15,7 @@ obj-$(CONFIG_SPI_ATMEL)                       += spi-atmel.o
 obj-$(CONFIG_SPI_ATH79)                        += spi-ath79.o
 obj-$(CONFIG_SPI_AU1550)               += spi-au1550.o
 obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
-obj-$(CONFIG_SPI_BFIN)                 += spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
 obj-$(CONFIG_SPI_BFIN_SPORT)           += spi-bfin-sport.o
 obj-$(CONFIG_SPI_BITBANG)              += spi-bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi-butterfly.o
index f01b2648452e61887ce7a8712d8b91dd15559d11..7491971139a63000aac97854132645fe5125fff4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Broadcom BCM63xx SPI controller support
  *
- * Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
  * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -30,6 +30,8 @@
 #include <linux/spi/spi.h>
 #include <linux/completion.h>
 #include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
 
 #include <bcm63xx_dev_spi.h>
 
@@ -37,8 +39,6 @@
 #define DRV_VER                "0.1.2"
 
 struct bcm63xx_spi {
-       spinlock_t              lock;
-       int                     stopping;
        struct completion       done;
 
        void __iomem            *regs;
@@ -96,17 +96,12 @@ static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
        {   391000, SPI_CLK_0_391MHZ }
 };
 
-static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
-                                     struct spi_transfer *t)
+static int bcm63xx_spi_check_transfer(struct spi_device *spi,
+                                       struct spi_transfer *t)
 {
-       struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
        u8 bits_per_word;
-       u8 clk_cfg, reg;
-       u32 hz;
-       int i;
 
        bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
-       hz = (t) ? t->speed_hz : spi->max_speed_hz;
        if (bits_per_word != 8) {
                dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
                        __func__, bits_per_word);
@@ -119,6 +114,19 @@ static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
                return -EINVAL;
        }
 
+       return 0;
+}
+
+static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
+                                     struct spi_transfer *t)
+{
+       struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
+       u32 hz;
+       u8 clk_cfg, reg;
+       int i;
+
+       hz = (t) ? t->speed_hz : spi->max_speed_hz;
+
        /* Find the closest clock configuration */
        for (i = 0; i < SPI_CLK_MASK; i++) {
                if (hz <= bcm63xx_spi_freq_table[i][0]) {
@@ -139,8 +147,6 @@ static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
        bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
        dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
                clk_cfg, hz);
-
-       return 0;
 }
 
 /* the spi->mode bits understood by this driver: */
@@ -153,9 +159,6 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
 
        bs = spi_master_get_devdata(spi->master);
 
-       if (bs->stopping)
-               return -ESHUTDOWN;
-
        if (!spi->bits_per_word)
                spi->bits_per_word = 8;
 
@@ -165,7 +168,7 @@ static int bcm63xx_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
-       ret = bcm63xx_spi_setup_transfer(spi, NULL);
+       ret = bcm63xx_spi_check_transfer(spi, NULL);
        if (ret < 0) {
                dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
                        spi->mode & ~MODEBITS);
@@ -190,28 +193,29 @@ static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs)
        bs->remaining_bytes -= size;
 }
 
-static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
+                                       struct spi_transfer *t)
 {
        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
        u16 msg_ctl;
        u16 cmd;
 
+       /* Disable the CMD_DONE interrupt */
+       bcm_spi_writeb(bs, 0, SPI_INT_MASK);
+
        dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
                t->tx_buf, t->rx_buf, t->len);
 
        /* Transmitter is inhibited */
        bs->tx_ptr = t->tx_buf;
        bs->rx_ptr = t->rx_buf;
-       init_completion(&bs->done);
 
        if (t->tx_buf) {
                bs->remaining_bytes = t->len;
                bcm63xx_spi_fill_tx_fifo(bs);
        }
 
-       /* Enable the command done interrupt which
-        * we use to determine completion of a command */
-       bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
+       init_completion(&bs->done);
 
        /* Fill in the Message control register */
        msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
@@ -230,33 +234,76 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
        cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
        cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
        bcm_spi_writew(bs, cmd, SPI_CMD);
-       wait_for_completion(&bs->done);
 
-       /* Disable the CMD_DONE interrupt */
-       bcm_spi_writeb(bs, 0, SPI_INT_MASK);
+       /* Enable the CMD_DONE interrupt */
+       bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
 
        return t->len - bs->remaining_bytes;
 }
 
-static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m)
+static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
 {
-       struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
-       struct spi_transfer *t;
-       int ret = 0;
+       struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
-       if (unlikely(list_empty(&m->transfers)))
-               return -EINVAL;
+       pm_runtime_get_sync(&bs->pdev->dev);
 
-       if (bs->stopping)
-               return -ESHUTDOWN;
+       return 0;
+}
+
+static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
+{
+       struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+
+       pm_runtime_put(&bs->pdev->dev);
+
+       return 0;
+}
+
+static int bcm63xx_spi_transfer_one(struct spi_master *master,
+                                       struct spi_message *m)
+{
+       struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+       struct spi_transfer *t;
+       struct spi_device *spi = m->spi;
+       int status = 0;
+       unsigned int timeout = 0;
 
        list_for_each_entry(t, &m->transfers, transfer_list) {
-               ret += bcm63xx_txrx_bufs(spi, t);
-       }
+               unsigned int len = t->len;
+               u8 rx_tail;
 
-       m->complete(m->context);
+               status = bcm63xx_spi_check_transfer(spi, t);
+               if (status < 0)
+                       goto exit;
 
-       return ret;
+               /* configure adapter for a new transfer */
+               bcm63xx_spi_setup_transfer(spi, t);
+
+               while (len) {
+                       /* send the data */
+                       len -= bcm63xx_txrx_bufs(spi, t);
+
+                       timeout = wait_for_completion_timeout(&bs->done, HZ);
+                       if (!timeout) {
+                               status = -ETIMEDOUT;
+                               goto exit;
+                       }
+
+                       /* read out all data */
+                       rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
+
+                       /* Read out all the data */
+                       if (rx_tail)
+                               memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
+               }
+
+               m->actual_length += t->len;
+       }
+exit:
+       m->status = status;
+       spi_finalize_current_message(master);
+
+       return 0;
 }
 
 /* This driver supports single master mode only. Hence
@@ -267,39 +314,15 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
        struct spi_master *master = (struct spi_master *)dev_id;
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
        u8 intr;
-       u16 cmd;
 
        /* Read interupts and clear them immediately */
        intr = bcm_spi_readb(bs, SPI_INT_STATUS);
        bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
        bcm_spi_writeb(bs, 0, SPI_INT_MASK);
 
-       /* A tansfer completed */
-       if (intr & SPI_INTR_CMD_DONE) {
-               u8 rx_tail;
-
-               rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
-
-               /* Read out all the data */
-               if (rx_tail)
-                       memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
-
-               /* See if there is more data to send */
-               if (bs->remaining_bytes > 0) {
-                       bcm63xx_spi_fill_tx_fifo(bs);
-
-                       /* Start the transfer */
-                       bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT,
-                                      SPI_MSG_CTL);
-                       cmd = bcm_spi_readw(bs, SPI_CMD);
-                       cmd |= SPI_CMD_START_IMMEDIATE;
-                       cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
-                       bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
-                       bcm_spi_writew(bs, cmd, SPI_CMD);
-               } else {
-                       complete(&bs->done);
-               }
-       }
+       /* A transfer completed */
+       if (intr & SPI_INTR_CMD_DONE)
+               complete(&bs->done);
 
        return IRQ_HANDLED;
 }
@@ -345,7 +368,6 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
        }
 
        bs = spi_master_get_devdata(master);
-       init_completion(&bs->done);
 
        platform_set_drvdata(pdev, master);
        bs->pdev = pdev;
@@ -379,12 +401,13 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
        master->bus_num = pdata->bus_num;
        master->num_chipselect = pdata->num_chipselect;
        master->setup = bcm63xx_spi_setup;
-       master->transfer = bcm63xx_transfer;
+       master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
+       master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
+       master->transfer_one_message = bcm63xx_spi_transfer_one;
+       master->mode_bits = MODEBITS;
        bs->speed_hz = pdata->speed_hz;
-       bs->stopping = 0;
        bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
        bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
-       spin_lock_init(&bs->lock);
 
        /* Initialize hardware */
        clk_enable(bs->clk);
@@ -418,18 +441,16 @@ static int __devexit bcm63xx_spi_remove(struct platform_device *pdev)
        struct spi_master *master = platform_get_drvdata(pdev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
+       spi_unregister_master(master);
+
        /* reset spi block */
        bcm_spi_writeb(bs, 0, SPI_INT_MASK);
-       spin_lock(&bs->lock);
-       bs->stopping = 1;
 
        /* HW shutdown */
        clk_disable(bs->clk);
        clk_put(bs->clk);
 
-       spin_unlock(&bs->lock);
        platform_set_drvdata(pdev, 0);
-       spi_unregister_master(master);
 
        return 0;
 }
index 248a2cc671a9bc8e6c6a83c5b515557f432c7841..1fe51198a62292310473d22d4bdbb502cf6cf304 100644 (file)
@@ -252,19 +252,15 @@ static void
 bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data)
 {
        struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
-       unsigned int bits = (drv_data->ops == &bfin_sport_transfer_ops_u8 ? 7 : 15);
 
        bfin_sport_spi_disable(drv_data);
        dev_dbg(drv_data->dev, "restoring spi ctl state\n");
 
        bfin_write(&drv_data->regs->tcr1, chip->ctl_reg);
-       bfin_write(&drv_data->regs->tcr2, bits);
        bfin_write(&drv_data->regs->tclkdiv, chip->baud);
-       bfin_write(&drv_data->regs->tfsdiv, bits);
        SSYNC();
 
        bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS));
-       bfin_write(&drv_data->regs->rcr2, bits);
        SSYNC();
 
        bfin_sport_spi_cs_active(chip);
@@ -420,11 +416,15 @@ bfin_sport_spi_pump_transfers(unsigned long data)
        drv_data->cs_change = transfer->cs_change;
 
        /* Bits per word setup */
-       bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
-       if (bits_per_word == 8)
-               drv_data->ops = &bfin_sport_transfer_ops_u8;
-       else
+       bits_per_word = transfer->bits_per_word ? :
+               message->spi->bits_per_word ? : 8;
+       if (bits_per_word % 16 == 0)
                drv_data->ops = &bfin_sport_transfer_ops_u16;
+       else
+               drv_data->ops = &bfin_sport_transfer_ops_u8;
+       bfin_write(&drv_data->regs->tcr2, bits_per_word - 1);
+       bfin_write(&drv_data->regs->tfsdiv, bits_per_word - 1);
+       bfin_write(&drv_data->regs->rcr2, bits_per_word - 1);
 
        drv_data->state = RUNNING_STATE;
 
@@ -598,11 +598,12 @@ bfin_sport_spi_setup(struct spi_device *spi)
                        }
                        chip->cs_chg_udelay = chip_info->cs_chg_udelay;
                        chip->idle_tx_val = chip_info->idle_tx_val;
-                       spi->bits_per_word = chip_info->bits_per_word;
                }
        }
 
-       if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
+       if (spi->bits_per_word % 8) {
+               dev_err(&spi->dev, "%d bits_per_word is not supported\n",
+                               spi->bits_per_word);
                ret = -EINVAL;
                goto error;
        }
index 3b83ff8b1e2b7ac60fb5494347fbc2a189b6dc14..9bb4d4af85475f8cfed48dce4530598fd45cc73d 100644 (file)
@@ -396,7 +396,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
                /* last read */
                if (drv_data->rx) {
                        dev_dbg(&drv_data->pdev->dev, "last read\n");
-                       if (n_bytes % 2) {
+                       if (!(n_bytes % 2)) {
                                u16 *buf = (u16 *)drv_data->rx;
                                for (loop = 0; loop < n_bytes / 2; loop++)
                                        *buf++ = bfin_read(&drv_data->regs->rdbr);
@@ -424,7 +424,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
        if (drv_data->rx && drv_data->tx) {
                /* duplex */
                dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
-               if (n_bytes % 2) {
+               if (!(n_bytes % 2)) {
                        u16 *buf = (u16 *)drv_data->rx;
                        u16 *buf2 = (u16 *)drv_data->tx;
                        for (loop = 0; loop < n_bytes / 2; loop++) {
@@ -442,7 +442,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
        } else if (drv_data->rx) {
                /* read */
                dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
-               if (n_bytes % 2) {
+               if (!(n_bytes % 2)) {
                        u16 *buf = (u16 *)drv_data->rx;
                        for (loop = 0; loop < n_bytes / 2; loop++) {
                                *buf++ = bfin_read(&drv_data->regs->rdbr);
@@ -458,7 +458,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
        } else if (drv_data->tx) {
                /* write */
                dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
-               if (n_bytes % 2) {
+               if (!(n_bytes % 2)) {
                        u16 *buf = (u16 *)drv_data->tx;
                        for (loop = 0; loop < n_bytes / 2; loop++) {
                                bfin_read(&drv_data->regs->rdbr);
@@ -587,6 +587,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
        if (message->state == DONE_STATE) {
                dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
                message->status = 0;
+               bfin_spi_flush(drv_data);
                bfin_spi_giveback(drv_data);
                return;
        }
@@ -870,8 +871,10 @@ static void bfin_spi_pump_transfers(unsigned long data)
                message->actual_length += drv_data->len_in_bytes;
                /* Move to next transfer of this msg */
                message->state = bfin_spi_next_transfer(drv_data);
-               if (drv_data->cs_change)
+               if (drv_data->cs_change && message->state != DONE_STATE) {
+                       bfin_spi_flush(drv_data);
                        bfin_spi_cs_deactive(drv_data, chip);
+               }
        }
 
        /* Schedule next transfer tasklet */
@@ -1026,7 +1029,6 @@ static int bfin_spi_setup(struct spi_device *spi)
                chip->cs_chg_udelay = chip_info->cs_chg_udelay;
                chip->idle_tx_val = chip_info->idle_tx_val;
                chip->pio_interrupt = chip_info->pio_interrupt;
-               spi->bits_per_word = chip_info->bits_per_word;
        } else {
                /* force a default base state */
                chip->ctl_reg &= bfin_ctl_reg;
index 31bfba805cf473e51edbeb437a72666f9b735595..9b2901feaf78d4bf3783c9b8b3491f57bfdc2e83 100644 (file)
@@ -653,7 +653,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
                        dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
                                                                rx_buf_count);
                        if (t->tx_buf)
-                               dma_unmap_single(NULL, t->tx_dma, t->len,
+                               dma_unmap_single(&spi->dev, t->tx_dma, t->len,
                                                                DMA_TO_DEVICE);
                        return -ENOMEM;
                }
@@ -692,10 +692,10 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
        if (spicfg->io_type == SPI_IO_TYPE_DMA) {
 
                if (t->tx_buf)
-                       dma_unmap_single(NULL, t->tx_dma, t->len,
+                       dma_unmap_single(&spi->dev, t->tx_dma, t->len,
                                                                DMA_TO_DEVICE);
 
-               dma_unmap_single(NULL, t->rx_dma, rx_buf_count,
+               dma_unmap_single(&spi->dev, t->rx_dma, rx_buf_count,
                                                        DMA_FROM_DEVICE);
 
                clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
index 082458d73ce9798d38bb494840d3bec058650643..d1a495f64e2d62317602d3d2a6d1b56a0eff3f90 100644 (file)
@@ -63,12 +63,6 @@ struct chip_data {
 };
 
 #ifdef CONFIG_DEBUG_FS
-static int spi_show_regs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 #define SPI_REGS_BUFSIZE       1024
 static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
                                size_t count, loff_t *ppos)
@@ -128,7 +122,7 @@ static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
 
 static const struct file_operations mrst_spi_regs_ops = {
        .owner          = THIS_MODULE,
-       .open           = spi_show_regs_open,
+       .open           = simple_open,
        .read           = spi_show_regs,
        .llseek         = default_llseek,
 };
index 6db2887852d6befe327b53cacdf2731b8328c68b..e8055073e84df898bbd0e281745bf633377a5eda 100644 (file)
@@ -545,13 +545,12 @@ static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
  * in case of failure.
  */
 static struct dma_async_tx_descriptor *
-ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
+ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
 {
        struct spi_transfer *t = espi->current_msg->state;
        struct dma_async_tx_descriptor *txd;
        enum dma_slave_buswidth buswidth;
        struct dma_slave_config conf;
-       enum dma_transfer_direction slave_dirn;
        struct scatterlist *sg;
        struct sg_table *sgt;
        struct dma_chan *chan;
@@ -567,14 +566,13 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
        memset(&conf, 0, sizeof(conf));
        conf.direction = dir;
 
-       if (dir == DMA_FROM_DEVICE) {
+       if (dir == DMA_DEV_TO_MEM) {
                chan = espi->dma_rx;
                buf = t->rx_buf;
                sgt = &espi->rx_sgt;
 
                conf.src_addr = espi->sspdr_phys;
                conf.src_addr_width = buswidth;
-               slave_dirn = DMA_DEV_TO_MEM;
        } else {
                chan = espi->dma_tx;
                buf = t->tx_buf;
@@ -582,7 +580,6 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
 
                conf.dst_addr = espi->sspdr_phys;
                conf.dst_addr_width = buswidth;
-               slave_dirn = DMA_MEM_TO_DEV;
        }
 
        ret = dmaengine_slave_config(chan, &conf);
@@ -633,8 +630,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
        if (!nents)
                return ERR_PTR(-ENOMEM);
 
-       txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents,
-                                       slave_dirn, DMA_CTRL_ACK);
+       txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir, DMA_CTRL_ACK);
        if (!txd) {
                dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
                return ERR_PTR(-ENOMEM);
@@ -651,12 +647,12 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
  * unmapped.
  */
 static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
-                                 enum dma_data_direction dir)
+                                 enum dma_transfer_direction dir)
 {
        struct dma_chan *chan;
        struct sg_table *sgt;
 
-       if (dir == DMA_FROM_DEVICE) {
+       if (dir == DMA_DEV_TO_MEM) {
                chan = espi->dma_rx;
                sgt = &espi->rx_sgt;
        } else {
@@ -677,16 +673,16 @@ static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
        struct spi_message *msg = espi->current_msg;
        struct dma_async_tx_descriptor *rxd, *txd;
 
-       rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE);
+       rxd = ep93xx_spi_dma_prepare(espi, DMA_DEV_TO_MEM);
        if (IS_ERR(rxd)) {
                dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
                msg->status = PTR_ERR(rxd);
                return;
        }
 
-       txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE);
+       txd = ep93xx_spi_dma_prepare(espi, DMA_MEM_TO_DEV);
        if (IS_ERR(txd)) {
-               ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+               ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM);
                dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd));
                msg->status = PTR_ERR(txd);
                return;
@@ -705,8 +701,8 @@ static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
 
        wait_for_completion(&espi->wait);
 
-       ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE);
-       ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+       ep93xx_spi_dma_finish(espi, DMA_MEM_TO_DEV);
+       ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM);
 }
 
 /**
index 24cacff577867b56eca075c13d22f68acd967852..5f748c0d96bdf5444e85408fa21b515b5873639f 100644 (file)
@@ -139,10 +139,12 @@ static void fsl_spi_change_mode(struct spi_device *spi)
 static void fsl_spi_chipselect(struct spi_device *spi, int value)
 {
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-       struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
+       struct fsl_spi_platform_data *pdata;
        bool pol = spi->mode & SPI_CS_HIGH;
        struct spi_mpc8xxx_cs   *cs = spi->controller_state;
 
+       pdata = spi->dev.parent->parent->platform_data;
+
        if (value == BITBANG_CS_INACTIVE) {
                if (pdata->cs_control)
                        pdata->cs_control(spi, !pol);
index 31054e3de4c11e496ba6f102fbf41c78d1b9d334..570f22053be89fb56d99b464ecc36a9443e2cc8d 100644 (file)
@@ -83,7 +83,7 @@ struct spi_imx_data {
        struct spi_bitbang bitbang;
 
        struct completion xfer_done;
-       void *base;
+       void __iomem *base;
        int irq;
        struct clk *clk;
        unsigned long spi_clk;
@@ -766,8 +766,12 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
        }
 
        ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
-       if (ret < 0)
-               num_cs = mxc_platform_info->num_chipselect;
+       if (ret < 0) {
+               if (mxc_platform_info)
+                       num_cs = mxc_platform_info->num_chipselect;
+               else
+                       return ret;
+       }
 
        master = spi_alloc_master(&pdev->dev,
                        sizeof(struct spi_imx_data) + sizeof(int) * num_cs);
@@ -784,7 +788,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
 
        for (i = 0; i < master->num_chipselect; i++) {
                int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
-               if (cs_gpio < 0)
+               if (cs_gpio < 0 && mxc_platform_info)
                        cs_gpio = mxc_platform_info->chipselect[i];
 
                spi_imx->chipselect[i] = cs_gpio;
index 96f0da66b185b5cbb41c6cdf01d7e969e5b341ed..400ae2121a2a48cd1c78469f0c727972b180a777 100644 (file)
@@ -1667,9 +1667,15 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
        /* cpsdvsr = 254 & scr = 255 */
        min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
 
-       if (!((freq <= max_tclk) && (freq >= min_tclk))) {
+       if (freq > max_tclk)
+               dev_warn(&pl022->adev->dev,
+                       "Max speed that can be programmed is %d Hz, you requested %d\n",
+                       max_tclk, freq);
+
+       if (freq < min_tclk) {
                dev_err(&pl022->adev->dev,
-                       "controller data is incorrect: out of range frequency");
+                       "Requested frequency: %d Hz is less than minimum possible %d Hz\n",
+                       freq, min_tclk);
                return -EINVAL;
        }
 
@@ -1681,26 +1687,37 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
                while (scr <= SCR_MAX) {
                        tmp = spi_rate(rate, cpsdvsr, scr);
 
-                       if (tmp > freq)
+                       if (tmp > freq) {
+                               /* we need lower freq */
                                scr++;
+                               continue;
+                       }
+
                        /*
-                        * If found exact value, update and break.
-                        * If found more closer value, update and continue.
+                        * If found exact value, mark found and break.
+                        * If found more closer value, update and break.
                         */
-                       else if ((tmp == freq) || (tmp > best_freq)) {
+                       if (tmp > best_freq) {
                                best_freq = tmp;
                                best_cpsdvsr = cpsdvsr;
                                best_scr = scr;
 
                                if (tmp == freq)
-                                       break;
+                                       found = 1;
                        }
-                       scr++;
+                       /*
+                        * increased scr will give lower rates, which are not
+                        * required
+                        */
+                       break;
                }
                cpsdvsr += 2;
                scr = SCR_MIN;
        }
 
+       WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate \n",
+                       freq);
+
        clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
        clk_freq->scr = (u8) (best_scr & 0xFF);
        dev_dbg(&pl022->adev->dev,
@@ -1823,9 +1840,12 @@ static int pl022_setup(struct spi_device *spi)
        } else
                chip->cs_control = chip_info->cs_control;
 
-       if (bits <= 3) {
-               /* PL022 doesn't support less than 4-bits */
+       /* Check bits per word with vendor specific range */
+       if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) {
                status = -ENOTSUPP;
+               dev_err(&spi->dev, "illegal data size for this controller!\n");
+               dev_err(&spi->dev, "This controller can only handle 4 <= n <= %d bit words\n",
+                               pl022->vendor->max_bpw);
                goto err_config_params;
        } else if (bits <= 8) {
                dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
@@ -1838,20 +1858,10 @@ static int pl022_setup(struct spi_device *spi)
                chip->read = READING_U16;
                chip->write = WRITING_U16;
        } else {
-               if (pl022->vendor->max_bpw >= 32) {
-                       dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
-                       chip->n_bytes = 4;
-                       chip->read = READING_U32;
-                       chip->write = WRITING_U32;
-               } else {
-                       dev_err(&spi->dev,
-                               "illegal data size for this controller!\n");
-                       dev_err(&spi->dev,
-                               "a standard pl022 can only handle "
-                               "1 <= n <= 16 bit words\n");
-                       status = -ENOTSUPP;
-                       goto err_config_params;
-               }
+               dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
+               chip->n_bytes = 4;
+               chip->read = READING_U32;
+               chip->write = WRITING_U32;
        }
 
        /* Now Initialize all register settings required for this chip */
@@ -2195,7 +2205,6 @@ static int pl022_runtime_suspend(struct device *dev)
        struct pl022 *pl022 = dev_get_drvdata(dev);
 
        clk_disable(pl022->clk);
-       amba_vcore_disable(pl022->adev);
 
        return 0;
 }
@@ -2204,7 +2213,6 @@ static int pl022_runtime_resume(struct device *dev)
 {
        struct pl022 *pl022 = dev_get_drvdata(dev);
 
-       amba_vcore_enable(pl022->adev);
        clk_enable(pl022->clk);
 
        return 0;
index 08a3b1133d29ed476ed21e99a3a75d39a74cda3d..eb1dee26bda3662972d9e9e6e4595402ba775ee5 100644 (file)
@@ -27,13 +27,14 @@ config ANDROID_LOGGER
 
 config ANDROID_PERSISTENT_RAM
        bool
+       depends on HAVE_MEMBLOCK
        select REED_SOLOMON
        select REED_SOLOMON_ENC8
        select REED_SOLOMON_DEC8
 
 config ANDROID_RAM_CONSOLE
        bool "Android RAM buffer console"
-       depends on !S390 && !UML
+       depends on !S390 && !UML && HAVE_MEMBLOCK
        select ANDROID_PERSISTENT_RAM
        default n
 
index 052b43e4e505148aa0da8b4da5b611da85b5dd3c..b91e4bc332a77c2e6ea1219e99f92c5ee924c418 100644 (file)
@@ -55,7 +55,6 @@ static int lowmem_minfree[6] = {
 };
 static int lowmem_minfree_size = 4;
 
-static struct task_struct *lowmem_deathpending;
 static unsigned long lowmem_deathpending_timeout;
 
 #define lowmem_print(level, x...)                      \
@@ -64,24 +63,6 @@ static unsigned long lowmem_deathpending_timeout;
                        printk(x);                      \
        } while (0)
 
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data);
-
-static struct notifier_block task_nb = {
-       .notifier_call  = task_notify_func,
-};
-
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data)
-{
-       struct task_struct *task = data;
-
-       if (task == lowmem_deathpending)
-               lowmem_deathpending = NULL;
-
-       return NOTIFY_OK;
-}
-
 static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 {
        struct task_struct *tsk;
@@ -97,19 +78,6 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
        int other_file = global_page_state(NR_FILE_PAGES) -
                                                global_page_state(NR_SHMEM);
 
-       /*
-        * If we already have a death outstanding, then
-        * bail out right away; indicating to vmscan
-        * that we have nothing further to offer on
-        * this pass.
-        *
-        * Note: Currently you need CONFIG_PROFILING
-        * for this to work correctly.
-        */
-       if (lowmem_deathpending &&
-           time_before_eq(jiffies, lowmem_deathpending_timeout))
-               return 0;
-
        if (lowmem_adj_size < array_size)
                array_size = lowmem_adj_size;
        if (lowmem_minfree_size < array_size)
@@ -148,6 +116,12 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
                if (!p)
                        continue;
 
+               if (test_tsk_thread_flag(p, TIF_MEMDIE) &&
+                   time_before_eq(jiffies, lowmem_deathpending_timeout)) {
+                       task_unlock(p);
+                       rcu_read_unlock();
+                       return 0;
+               }
                oom_score_adj = p->signal->oom_score_adj;
                if (oom_score_adj < min_score_adj) {
                        task_unlock(p);
@@ -174,15 +148,9 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
                lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
                             selected->pid, selected->comm,
                             selected_oom_score_adj, selected_tasksize);
-               /*
-                * If CONFIG_PROFILING is off, then we don't want to stall
-                * the killer by setting lowmem_deathpending.
-                */
-#ifdef CONFIG_PROFILING
-               lowmem_deathpending = selected;
                lowmem_deathpending_timeout = jiffies + HZ;
-#endif
                send_sig(SIGKILL, selected, 0);
+               set_tsk_thread_flag(selected, TIF_MEMDIE);
                rem -= selected_tasksize;
        }
        lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",
@@ -198,7 +166,6 @@ static struct shrinker lowmem_shrinker = {
 
 static int __init lowmem_init(void)
 {
-       task_handoff_register(&task_nb);
        register_shrinker(&lowmem_shrinker);
        return 0;
 }
@@ -206,7 +173,6 @@ static int __init lowmem_init(void)
 static void __exit lowmem_exit(void)
 {
        unregister_shrinker(&lowmem_shrinker);
-       task_handoff_unregister(&task_nb);
 }
 
 module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
index e08f2574e30a94e7ddf4acff35ccaa4a63df9d2b..8d8c1e33e0ff11790bea6071cbeb1e9d52b36ecb 100644 (file)
@@ -399,12 +399,12 @@ static  __init
 struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc)
 {
        struct persistent_ram_zone *prz;
-       int ret;
+       int ret = -ENOMEM;
 
        prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL);
        if (!prz) {
                pr_err("persistent_ram: failed to allocate persistent ram zone\n");
-               return ERR_PTR(-ENOMEM);
+               goto err;
        }
 
        INIT_LIST_HEAD(&prz->node);
@@ -412,13 +412,13 @@ struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc)
        ret = persistent_ram_buffer_init(dev_name(dev), prz);
        if (ret) {
                pr_err("persistent_ram: failed to initialize buffer\n");
-               return ERR_PTR(ret);
+               goto err;
        }
 
        prz->ecc = ecc;
        ret = persistent_ram_init_ecc(prz, prz->buffer_size);
        if (ret)
-               return ERR_PTR(ret);
+               goto err;
 
        if (prz->buffer->sig == PERSISTENT_RAM_SIG) {
                if (buffer_size(prz) > prz->buffer_size ||
@@ -442,6 +442,9 @@ struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc)
        atomic_set(&prz->buffer->size, 0);
 
        return prz;
+err:
+       kfree(prz);
+       return ERR_PTR(ret);
 }
 
 struct persistent_ram_zone * __init
index bc723eff11aff0c988786690f2f83673372f007c..45c522cbe78446e0b0eb5e72fbf14e4a26f1d8b1 100644 (file)
@@ -85,7 +85,7 @@ static int timed_gpio_probe(struct platform_device *pdev)
        struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
        struct timed_gpio *cur_gpio;
        struct timed_gpio_data *gpio_data, *gpio_dat;
-       int i, j, ret = 0;
+       int i, ret;
 
        if (!pdata)
                return -EBUSY;
@@ -108,18 +108,12 @@ static int timed_gpio_probe(struct platform_device *pdev)
                gpio_dat->dev.get_time = gpio_get_time;
                gpio_dat->dev.enable = gpio_enable;
                ret = gpio_request(cur_gpio->gpio, cur_gpio->name);
-               if (ret >= 0) {
-                       ret = timed_output_dev_register(&gpio_dat->dev);
-                       if (ret < 0)
-                               gpio_free(cur_gpio->gpio);
-               }
+               if (ret < 0)
+                       goto err_out;
+               ret = timed_output_dev_register(&gpio_dat->dev);
                if (ret < 0) {
-                       for (j = 0; j < i; j++) {
-                               timed_output_dev_unregister(&gpio_data[i].dev);
-                               gpio_free(gpio_data[i].gpio);
-                       }
-                       kfree(gpio_data);
-                       return ret;
+                       gpio_free(cur_gpio->gpio);
+                       goto err_out;
                }
 
                gpio_dat->gpio = cur_gpio->gpio;
@@ -131,6 +125,15 @@ static int timed_gpio_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, gpio_data);
 
        return 0;
+
+err_out:
+       while (--i >= 0) {
+               timed_output_dev_unregister(&gpio_data[i].dev);
+               gpio_free(gpio_data[i].gpio);
+       }
+       kfree(gpio_data);
+
+       return ret;
 }
 
 static int timed_gpio_remove(struct platform_device *pdev)
index de2c8ea649653f9eb50be0eb0b571fdc53792483..ef07a02bf5421b662e95e3dffde2a0aebc42898a 100644 (file)
@@ -82,6 +82,7 @@ int iio_map_array_unregister(struct iio_dev *indio_dev,
                        ret = -ENODEV;
                        goto error_ret;
                }
+               i++;
        }
 error_ret:
        mutex_unlock(&iio_map_list_lock);
index d5ddac3d88311a64a0a31922b3a33cae8ed2d4a0..ebc2d0840caf4c867eb967c7ed6a8a5c93fee6f2 100644 (file)
@@ -108,7 +108,8 @@ static const int ak8975_index_to_reg[] = {
 static int ak8975_write_data(struct i2c_client *client,
                             u8 reg, u8 val, u8 mask, u8 shift)
 {
-       struct ak8975_data *data = i2c_get_clientdata(client);
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct ak8975_data *data = iio_priv(indio_dev);
        u8 regval;
        int ret;
 
@@ -159,7 +160,8 @@ static int ak8975_read_data(struct i2c_client *client,
  */
 static int ak8975_setup(struct i2c_client *client)
 {
-       struct ak8975_data *data = i2c_get_clientdata(client);
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct ak8975_data *data = iio_priv(indio_dev);
        u8 device_id;
        int ret;
 
@@ -509,6 +511,7 @@ static int ak8975_probe(struct i2c_client *client,
                goto exit_gpio;
        }
        data = iio_priv(indio_dev);
+       i2c_set_clientdata(client, indio_dev);
        /* Perform some basic start-of-day setup of the device. */
        err = ak8975_setup(client);
        if (err < 0) {
@@ -516,7 +519,6 @@ static int ak8975_probe(struct i2c_client *client,
                goto exit_free_iio;
        }
 
-       i2c_set_clientdata(client, indio_dev);
        data->client = client;
        mutex_init(&data->lock);
        data->eoc_irq = client->irq;
index 91dd3da70cb4961a9751c107bb9eb7565d48e3db..e00b416c4d331a428b1c7b8c0a799174fa96b33b 100644 (file)
@@ -521,7 +521,9 @@ static int hmc5843_detect(struct i2c_client *client,
 /* Called when we have found a new HMC5843. */
 static void hmc5843_init_client(struct i2c_client *client)
 {
-       struct hmc5843_data *data = i2c_get_clientdata(client);
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct hmc5843_data *data = iio_priv(indio_dev);
+
        hmc5843_set_meas_conf(client, data->meas_conf);
        hmc5843_set_rate(client, data->rate);
        hmc5843_configure(client, data->operating_mode);
index 43ebc43e6b9a1e1841fcb3dc87e4811216359311..1075fb1df0d9c04a967634e56eb2e5a581d3421b 100644 (file)
@@ -165,7 +165,7 @@ error:
 int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
 {
        int errno = -EFAULT;
-       const struct firmware *firmware;
+       const struct firmware *firmware = NULL;
        unsigned char *cmd_buf = NULL;
        char *fw1, *fw2;
        struct usb_device *dev = bus_adap->usb_dev;
index 400df8cbee538b55a50e7baa92ceb18cae9e28c5..d91751f9ffe860372d070be165b49d128d9dce45 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/prefetch.h>
 #include <linux/ratelimit.h>
 #include <linux/smp.h>
+#include <linux/interrupt.h>
 #include <net/dst.h>
 #ifdef CONFIG_XFRM
 #include <linux/xfrm.h>
index 56d74dc2fbd5b5f3b7122371554d51647b5effb9..91a97b3e45c67b718fdf15a90b6348d58c43f4a0 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/ip.h>
 #include <linux/ratelimit.h>
 #include <linux/string.h>
+#include <linux/interrupt.h>
 #include <net/dst.h>
 #ifdef CONFIG_XFRM
 #include <linux/xfrm.h>
index 9112cd8821540f692acfd5559183ad125459f73c..60cba8194de341c4aef6d4e565e7456ae7cc381e 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/etherdevice.h>
 #include <linux/phy.h>
 #include <linux/slab.h>
+#include <linux/interrupt.h>
 
 #include <net/dst.h>
 
index 3df5b4c58ecd73feeeff3d7b5edc9ccaa0d05fd0..620b8d54223d987f00dbf421fa7d0b34a25451d1 100644 (file)
@@ -803,9 +803,6 @@ static void pdev_shutdown(struct platform_device *device)
 static int pdev_probe(struct platform_device *device)
 {
        DBG("%s", device->name);
-       if (platform_driver_register(&omap_dmm_driver))
-               dev_err(&device->dev, "DMM registration failed\n");
-
        return drm_platform_init(&omap_drm_driver, device);
 }
 
@@ -833,6 +830,10 @@ struct platform_driver pdev = {
 static int __init omap_drm_init(void)
 {
        DBG("init");
+       if (platform_driver_register(&omap_dmm_driver)) {
+               /* we can continue on without DMM.. so not fatal */
+               dev_err(NULL, "DMM registration failed\n");
+       }
        return platform_driver_register(&pdev);
 }
 
index f7a9c122f596b7afbff8d175532345d93d89b173..c2d30a7112f30f8ae507e5a3e31b61b5d0c9184f 100644 (file)
@@ -8,5 +8,7 @@ TODO:
        - code review by USB developer community.
        - testing with as many devices as possible.
 
-Please send any patches for this driver to Chris Kelly <ckelly@ozmodevices.com>
+Please send any patches for this driver to
+Rupesh Gujare <rgujare@ozmodevices.com>
+Chris Kelly <ckelly@ozmodevices.com>
 and Greg Kroah-Hartman <gregkh@linuxfoundation.org>.
index 2b45d3d1800c13bc1a6341a9b5c5d2c8f4048086..04cd57f2a6da50eea26b54e163eef6f39af91c1a 100644 (file)
@@ -383,8 +383,6 @@ static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f)
                pd->tx_pool = &f->link;
                pd->tx_pool_count++;
                f = 0;
-       } else {
-               kfree(f);
        }
        spin_unlock_bh(&pd->tx_frame_lock);
        if (f)
index 8b57b87edda47208c3737787b76593d4b9ab0e2c..4af1f8d4b9533816b9b571d6681a2abc5ae01d78 100644 (file)
@@ -1,10 +1,6 @@
-# Dependency on CONFIG_BROKEN is because there is a commit dependency
-# on a cleancache naming change to be submitted by Konrad Wilk
-# a39c00ded70339603ffe1b0ffdf3ade85bcf009a "Merge branch 'stable/cleancache.v13'
-# into linux-next.  Once this commit is present, BROKEN can be removed
 config RAMSTER
        bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
-       depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM && BROKEN
+       depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM
        select LZO_COMPRESS
        select LZO_DECOMPRESS
        default n
index 66341dff8c99160e54c29dcdb45dabdb9a11c3f4..f9a4498984cc005f516a998a06bb061d2b9dcc8c 100644 (file)
@@ -3498,7 +3498,8 @@ static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32
 
                log_blk++;
 
-               for (seg_no = 0; seg_no < sizeof(ms_start_idx)/2; seg_no++) {
+               for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1;
+                               seg_no++) {
                        if (log_blk < ms_start_idx[seg_no+1])
                                break;
                }
index a7feb3e328a0e32c3c2ada165dcb939eddfee315..1dccd933a7e412603be0e1904c79273fd13d668f 100644 (file)
@@ -1000,6 +1000,11 @@ static int __devinit rtsx_probe(struct pci_dev *pci,
 
        rtsx_init_chip(dev->chip);
 
+       /* set the supported max_lun and max_id for the scsi host
+        * NOTE: the minimal value of max_id is 1 */
+       host->max_id = 1;
+       host->max_lun = dev->chip->max_lun;
+
        /* Start up our control thread */
        th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME);
        if (IS_ERR(th)) {
index 4e3d2c106af085d9d79d6cb6bcf356b0124bee9f..9b2e5c99870f3096571bea1eab7e24991948de86 100644 (file)
@@ -335,6 +335,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
        int sg_cnt, i, resid;
        int err = 0;
        long timeleft;
+       struct scatterlist *sg_ptr;
        u32 val = TRIG_DMA;
 
        if ((sg == NULL) || (num_sg <= 0) || !offset || !index)
@@ -371,7 +372,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
        sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
 
        resid = size;
-
+       sg_ptr = sg;
        chip->sgi = 0;
        /* Usually the next entry will be @sg@ + 1, but if this sg element
         * is part of a chained scatterlist, it could jump to the start of
@@ -379,14 +380,14 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
         * the proper sg
         */
        for (i = 0; i < *index; i++)
-               sg = sg_next(sg);
+               sg_ptr = sg_next(sg_ptr);
        for (i = *index; i < sg_cnt; i++) {
                dma_addr_t addr;
                unsigned int len;
                u8 option;
 
-               addr = sg_dma_address(sg);
-               len = sg_dma_len(sg);
+               addr = sg_dma_address(sg_ptr);
+               len = sg_dma_len(sg_ptr);
 
                RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
                             (unsigned int)addr, len);
@@ -415,7 +416,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
                if (!resid)
                        break;
 
-               sg = sg_next(sg);
+               sg_ptr = sg_next(sg_ptr);
        }
 
        RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
index ad54c2e5c9324b872b79cc82101eac0f7b0a6a13..f1701bc6e31238e2647be5edd8b58ea4ec4c1db9 100644 (file)
@@ -3114,7 +3114,7 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        current->pid);
                if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET,
                                  &call_status->status)) {
-                       dev_warn(&sep->pdev->dev,
+                       dev_dbg(&sep->pdev->dev,
                                "[PID%d] dcb prep needed before send msg\n",
                                current->pid);
                        error = -EPROTO;
@@ -3122,9 +3122,9 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                }
 
                if (!arg) {
-                       dev_warn(&sep->pdev->dev,
+                       dev_dbg(&sep->pdev->dev,
                                "[PID%d] dcb null arg\n", current->pid);
-                       error = EINVAL;
+                       error = -EINVAL;
                        goto end_function;
                }
 
index 7862513cc295449cf5479d5ff148b366effb9d8f..9cf29fcea11e58700c8010e7249fec7516042190 100644 (file)
 #define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
 #define OMAP343X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194)
 
-#define OMAP343X_CTRL_REGADDR(reg) \
-       OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
-
-
 /* Forward Declarations: */
 static int bridge_brd_monitor(struct bridge_dev_context *dev_ctxt);
 static int bridge_brd_read(struct bridge_dev_context *dev_ctxt,
@@ -418,19 +414,27 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 
                /* Assert RST1 i.e only the RST only for DSP megacell */
                if (!status) {
+                       /*
+                        * XXX: ioremapping  MUST be removed once ctrl
+                        * function is made available.
+                        */
+                       void __iomem *ctrl = ioremap(OMAP343X_CTRL_BASE, SZ_4K);
+                       if (!ctrl)
+                               return -ENOMEM;
+
                        (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK,
                                        OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD,
                                        OMAP2_RM_RSTCTRL);
                        /* Mask address with 1K for compatibility */
                        __raw_writel(dsp_addr & OMAP3_IVA2_BOOTADDR_MASK,
-                                       OMAP343X_CTRL_REGADDR(
-                                       OMAP343X_CONTROL_IVA2_BOOTADDR));
+                                       ctrl + OMAP343X_CONTROL_IVA2_BOOTADDR);
                        /*
                         * Set bootmode to self loop if dsp_debug flag is true
                         */
                        __raw_writel((dsp_debug) ? OMAP3_IVA2_BOOTMOD_IDLE : 0,
-                                       OMAP343X_CTRL_REGADDR(
-                                       OMAP343X_CONTROL_IVA2_BOOTMOD));
+                                       ctrl + OMAP343X_CONTROL_IVA2_BOOTMOD);
+
+                       iounmap(ctrl);
                }
        }
        if (!status) {
index 70055c8111ed2d208162dbcd7f93f3b6c52c70c7..870f934f4f3bee4002e0400ba77afc96e155cc23 100644 (file)
@@ -53,7 +53,10 @@ int dsp_wdt_init(void)
        int ret = 0;
 
        dsp_wdt.sm_wdt = NULL;
-       dsp_wdt.reg_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_WDT3_BASE);
+       dsp_wdt.reg_base = ioremap(OMAP34XX_WDT3_BASE, SZ_4K);
+       if (!dsp_wdt.reg_base)
+               return -ENOMEM;
+
        tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0);
 
        dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
@@ -99,6 +102,9 @@ void dsp_wdt_exit(void)
        dsp_wdt.fclk = NULL;
        dsp_wdt.iclk = NULL;
        dsp_wdt.sm_wdt = NULL;
+
+       if (dsp_wdt.reg_base)
+               iounmap(dsp_wdt.reg_base);
        dsp_wdt.reg_base = NULL;
 }
 
index 9fedc442a7790a3dce9a1f52dde38e4d6327f9cd..573c80003f0c75073ce35e6cac068e4df8d6b0ec 100644 (file)
@@ -35,10 +35,10 @@ static int vector[PIO2_CARDS_MAX];
 static int vector_num;
 static int level[PIO2_CARDS_MAX];
 static int level_num;
-static const char *variant[PIO2_CARDS_MAX];
+static char *variant[PIO2_CARDS_MAX];
 static int variant_num;
 
-static int loopback;
+static bool loopback;
 
 static int pio2_match(struct vme_dev *);
 static int __devinit pio2_probe(struct vme_dev *);
index 0ff8d7bbf2a7879af4536dfe37d2708c6890f525..774b0d4a7e068b811242924ff708ca48b0463d35 100644 (file)
@@ -655,6 +655,9 @@ bool KeybSetDefaultKey (
         return (false);
     }
 
+    if (uKeyLength > MAX_KEY_LEN)
+           return false;
+
     pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = true;
     for(ii=0;ii<ETH_ALEN;ii++)
         pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF;
index 1463d76895f023fe339d3ea8cf3a67a16544706f..d59456c29df15db61b310281841c16164e6cc4dc 100644 (file)
@@ -565,7 +565,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
                        result = -ENOMEM;
                        break;
                }
-               pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
+               pNodeList = kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
                if (pNodeList == NULL) {
                        result = -ENOMEM;
                        break;
@@ -601,6 +601,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
                        }
                }
                if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) {
+                       kfree(pNodeList);
                        result = -EFAULT;
                        break;
                }
index 27bb523c8a97853db0c8ca8911b05062d1fd62cb..ee62a06a75f4bfb0dd06fc6b93a0dfa0c6c98769 100644 (file)
@@ -684,6 +684,9 @@ BOOL KeybSetDefaultKey(
         return (FALSE);
     }
 
+    if (uKeyLength > MAX_KEY_LEN)
+           return false;
+
     pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = TRUE;
     for (ii = 0; ii < ETH_ALEN; ii++)
         pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF;
index 94d5c35e22fbce7af40f176692e70b4a1712efa3..3650bbff7686243e54d1d925f5e8de17000eac84 100644 (file)
@@ -61,7 +61,7 @@ XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
                }
                temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
                /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
-               if ((temp & 0x88) == 0x80)
+               if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08))
                        data = 0; /* DDR */
                else
                        data = 1; /* DDRII */
index 2919924213c42fddacb5fa80802d943366f1d1a5..60d4adf99923a1dcf79fd2870dff084f9f9ef7b1 100644 (file)
@@ -152,6 +152,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
                pVBInfo->pXGINew_CR97 = &XG20_CR97;
 
        if (ChipType == XG27) {
+               unsigned char temp;
                pVBInfo->MCLKData
                        = (struct SiS_MCLKData *) XGI27New_MCLKData;
                pVBInfo->CR40 = XGI27_cr41;
@@ -162,7 +163,13 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
                pVBInfo->pCRDE = XG27_CRDE;
                pVBInfo->pSR40 = &XG27_SR40;
                pVBInfo->pSR41 = &XG27_SR41;
+               pVBInfo->SR15 = XG27_SR13;
 
+               /*Z11m DDR*/
+               temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
+               /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
+               if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08))
+                       pVBInfo->pXGINew_CR97 = &Z11m_CR97;
        }
 
        if (ChipType >= XG20) {
index dddf261ed53d5e8d1a33dcb16a6db65fff0cccb1..e8d6f674b274f745da615283ca9ef119c34dcf69 100644 (file)
@@ -33,6 +33,13 @@ static struct XGI_ECLKDataStruct XGI340_ECLKData[] = {
        {0x5c, 0x23, 0x01, 166}
 };
 
+static unsigned char XG27_SR13[4][8] = {
+       {0x35, 0x45, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR13 */
+       {0x41, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR14 */
+       {0x32, 0x32, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR18 */
+       {0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}  /* SR1B */
+};
+
 static unsigned char XGI340_SR13[4][8] = {
        {0x35, 0x45, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR13 */
        {0x41, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR14 */
@@ -71,7 +78,7 @@ static unsigned char XGI27_cr41[24][8] = {
        {0x20, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0 CR41 */
        {0xC4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 1 CR8A */
        {0xC4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 2 CR8B */
-       {0xB5, 0x13, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 3 CR40[7],
+       {0xB3, 0x13, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 3 CR40[7],
                                                               CR99[2:0],
                                                               CR45[3:0]*/
        {0xf0, 0xf5, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 4 CR59 */
@@ -2803,6 +2810,8 @@ static unsigned char XG27_CRDE[2];
 static unsigned char XG27_SR40 = 0x04 ;
 static unsigned char XG27_SR41 = 0x00 ;
 
+static unsigned char Z11m_CR97 = 0x80 ;
+
 static struct XGI330_VCLKDataStruct XGI_VCLKData[] = {
        /* SR2B,SR2C,SR2D */
        {0x1B, 0xE1,  25}, /* 00 (25.175MHz) */
index 3ed2c8f656a52d8ce46eae00e6ff908314a507fa..7048e01f081714bf506c1c4f83f6e6740faacb7b 100644 (file)
@@ -2,7 +2,7 @@ config ZCACHE
        bool "Dynamic compression of swap pages and clean pagecache pages"
        # X86 dependency is because zsmalloc uses non-portable pte/tlb
        # functions
-       depends on (CLEANCACHE || FRONTSWAP) && CRYPTO && X86
+       depends on (CLEANCACHE || FRONTSWAP) && CRYPTO=y && X86
        select ZSMALLOC
        select CRYPTO_LZO
        default n
index 09caa4f2687e04f9a3ce353dbe96838a8b8f1928..917461c66014a23252399d2f7ac974c3777a0b8f 100644 (file)
@@ -267,33 +267,39 @@ static unsigned long obj_idx_to_offset(struct page *page,
        return off + obj_idx * class_size;
 }
 
+static void reset_page(struct page *page)
+{
+       clear_bit(PG_private, &page->flags);
+       clear_bit(PG_private_2, &page->flags);
+       set_page_private(page, 0);
+       page->mapping = NULL;
+       page->freelist = NULL;
+       reset_page_mapcount(page);
+}
+
 static void free_zspage(struct page *first_page)
 {
-       struct page *nextp, *tmp;
+       struct page *nextp, *tmp, *head_extra;
 
        BUG_ON(!is_first_page(first_page));
        BUG_ON(first_page->inuse);
 
-       nextp = (struct page *)page_private(first_page);
+       head_extra = (struct page *)page_private(first_page);
 
-       clear_bit(PG_private, &first_page->flags);
-       clear_bit(PG_private_2, &first_page->flags);
-       set_page_private(first_page, 0);
-       first_page->mapping = NULL;
-       first_page->freelist = NULL;
-       reset_page_mapcount(first_page);
+       reset_page(first_page);
        __free_page(first_page);
 
        /* zspage with only 1 system page */
-       if (!nextp)
+       if (!head_extra)
                return;
 
-       list_for_each_entry_safe(nextp, tmp, &nextp->lru, lru) {
+       list_for_each_entry_safe(nextp, tmp, &head_extra->lru, lru) {
                list_del(&nextp->lru);
-               clear_bit(PG_private_2, &nextp->flags);
-               nextp->index = 0;
+               reset_page(nextp);
                __free_page(nextp);
        }
+       reset_page(head_extra);
+       __free_page(head_extra);
 }
 
 /* Initialize a newly allocated zspage */
index 830657908db82d56627aec24ccc7f8844091c19a..c5eb3c33c3dbed83db4b647c07619e44f320659f 100644 (file)
@@ -122,6 +122,7 @@ struct ft_cmd {
        /* Local sense buffer */
        unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER];
        u32 was_ddp_setup:1;            /* Set only if ddp is setup */
+       u32 aborted:1;                  /* Set if aborted by reset or timeout */
        struct scatterlist *sg;         /* Set only if DDP is setup */
        u32 sg_cnt;                     /* No. of item in scatterlist */
 };
index 62dec9715ce57a37643e18d26caad8751349adab..a375f257aabcc80b19ca4d369ba4d54e5663881a 100644 (file)
@@ -121,6 +121,8 @@ int ft_queue_status(struct se_cmd *se_cmd)
        struct fc_exch *ep;
        size_t len;
 
+       if (cmd->aborted)
+               return 0;
        ft_dump_cmd(cmd, __func__);
        ep = fc_seq_exch(cmd->seq);
        lport = ep->lp;
@@ -187,6 +189,8 @@ int ft_write_pending(struct se_cmd *se_cmd)
 
        ft_dump_cmd(cmd, __func__);
 
+       if (cmd->aborted)
+               return 0;
        ep = fc_seq_exch(cmd->seq);
        lport = ep->lp;
        fp = fc_frame_alloc(lport, sizeof(*txrdy));
@@ -252,10 +256,10 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
        struct ft_cmd *cmd = arg;
        struct fc_frame_header *fh;
 
-       if (IS_ERR(fp)) {
+       if (unlikely(IS_ERR(fp))) {
                /* XXX need to find cmd if queued */
                cmd->seq = NULL;
-               transport_generic_free_cmd(&cmd->se_cmd, 0);
+               cmd->aborted = true;
                return;
        }
 
@@ -399,6 +403,8 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd)
        struct se_tmr_req *tmr = se_cmd->se_tmr_req;
        enum fcp_resp_rsp_codes code;
 
+       if (cmd->aborted)
+               return 0;
        switch (tmr->response) {
        case TMR_FUNCTION_COMPLETE:
                code = FCP_TMF_CMPL;
index f357039349ba56b2b9ee2ed3b0b154bc7bd96fa9..2948dc9446196f2f2c9fa9c8b87dc85d16300f74 100644 (file)
@@ -300,6 +300,7 @@ static struct se_portal_group *ft_add_tpg(
 {
        struct ft_lport_acl *lacl;
        struct ft_tpg *tpg;
+       struct workqueue_struct *wq;
        unsigned long index;
        int ret;
 
@@ -321,18 +322,20 @@ static struct se_portal_group *ft_add_tpg(
        tpg->lport_acl = lacl;
        INIT_LIST_HEAD(&tpg->lun_list);
 
-       ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
-                               tpg, TRANSPORT_TPG_TYPE_NORMAL);
-       if (ret < 0) {
+       wq = alloc_workqueue("tcm_fc", 0, 1);
+       if (!wq) {
                kfree(tpg);
                return NULL;
        }
 
-       tpg->workqueue = alloc_workqueue("tcm_fc", 0, 1);
-       if (!tpg->workqueue) {
+       ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
+                               tpg, TRANSPORT_TPG_TYPE_NORMAL);
+       if (ret < 0) {
+               destroy_workqueue(wq);
                kfree(tpg);
                return NULL;
        }
+       tpg->workqueue = wq;
 
        mutex_lock(&ft_lport_lock);
        list_add_tail(&tpg->list, &lacl->tpg_list);
index 2b693eefac556064c6dd54747fa7516cdb008469..dc7c0db26e20f2aa8e1be2e0ec7b471cce59b0ab 100644 (file)
@@ -81,6 +81,8 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
        void *from;
        void *to = NULL;
 
+       if (cmd->aborted)
+               return 0;
        ep = fc_seq_exch(cmd->seq);
        lport = ep->lp;
        cmd->seq = lport->tt.seq_start_next(cmd->seq);
index 24145c30c9b069104564df2f9e14b19f8728740b..6cc4358f68c12ad2c779c7837207ce875968cf40 100644 (file)
@@ -1073,8 +1073,10 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
                    (new_serial.close_delay != port->close_delay) ||
                    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
                    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-                    (port->flags & ~ASYNC_USR_MASK)))
+                    (port->flags & ~ASYNC_USR_MASK))) {
+                       tty_unlock();
                        return -EPERM;
+               }
                port->flags = ((port->flags & ~ASYNC_USR_MASK) |
                               (new_serial.flags & ASYNC_USR_MASK));
                state->custom_divisor = new_serial.custom_divisor;
index 5b149b466ec8a090d9707b51b18b4dd5123f768f..5c27f7e6c9f1b575130eb637c7ab970913851b6a 100644 (file)
@@ -1572,13 +1572,11 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
        do {
                struct uart_8250_port *up;
                struct uart_port *port;
-               bool skip;
 
                up = list_entry(l, struct uart_8250_port, list);
                port = &up->port;
-               skip = pass_counter && up->port.flags & UPF_IIR_ONCE;
 
-               if (!skip && port->handle_irq(port)) {
+               if (port->handle_irq(port)) {
                        handled = 1;
                        end = NULL;
                } else if (end == NULL)
@@ -2037,10 +2035,12 @@ static int serial8250_startup(struct uart_port *port)
                spin_unlock_irqrestore(&port->lock, flags);
 
                /*
-                * If the interrupt is not reasserted, setup a timer to
-                * kick the UART on a regular basis.
+                * If the interrupt is not reasserted, or we otherwise
+                * don't trust the iir, setup a timer to kick the UART
+                * on a regular basis.
                 */
-               if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
+               if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
+                   up->port.flags & UPF_BUG_THRE) {
                        up->bugs |= UART_BUG_THRE;
                        pr_debug("ttyS%d - using backup timer\n",
                                 serial_index(port));
index da2b0b0a183fff27805e6c5509c655c88648353d..858dca865d6ab6b35fd04beb21c826d892050f76 100644 (file)
@@ -1096,7 +1096,7 @@ static int kt_serial_setup(struct serial_private *priv,
                           const struct pciserial_board *board,
                           struct uart_port *port, int idx)
 {
-       port->flags |= UPF_IIR_ONCE;
+       port->flags |= UPF_BUG_THRE;
        return skip_tx_en_setup(priv, board, port, idx);
 }
 
@@ -1118,18 +1118,6 @@ pci_xr17c154_setup(struct serial_private *priv,
        return pci_default_setup(priv, board, port, idx);
 }
 
-static int try_enable_msi(struct pci_dev *dev)
-{
-       /* use msi if available, but fallback to legacy otherwise */
-       pci_enable_msi(dev);
-       return 0;
-}
-
-static void disable_msi(struct pci_dev *dev)
-{
-       pci_disable_msi(dev);
-}
-
 #define PCI_VENDOR_ID_SBSMODULARIO     0x124B
 #define PCI_SUBVENDOR_ID_SBSMODULARIO  0x124B
 #define PCI_DEVICE_ID_OCTPRO           0x0001
@@ -1249,9 +1237,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .device         = PCI_DEVICE_ID_INTEL_PATSBURG_KT,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
-               .init           = try_enable_msi,
                .setup          = kt_serial_setup,
-               .exit           = disable_msi,
        },
        /*
         * ITE
index 665beb68f67087a8dab9f73a8344b317964609c1..070b442c1f81abb08ffee6cd69e3ffe0ab87b209 100644 (file)
@@ -1041,7 +1041,7 @@ config SERIAL_OMAP
 
 config SERIAL_OMAP_CONSOLE
        bool "Console on OMAP serial port"
-       depends on SERIAL_OMAP
+       depends on SERIAL_OMAP=y
        select SERIAL_CORE_CONSOLE
        help
          Select this option if you would like to use omap serial port as
index e7903751e0582bb4a89a3c76e50a7f6f34342c6e..1f0330915d5a014dc9fb0cae1e66a631a703d0df 100644 (file)
@@ -556,7 +556,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
        res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res_mem)
                port->mapbase = res_mem->start;
-       else if (platp->mapbase)
+       else if (platp)
                port->mapbase = platp->mapbase;
        else
                return -EINVAL;
@@ -564,7 +564,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
        res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (res_irq)
                port->irq = res_irq->start;
-       else if (platp->irq)
+       else if (platp)
                port->irq = platp->irq;
 
        /* Check platform data first so we can override device node data */
index 0c65c9e669867bf70ed3c86e61e06b3846bf5b60..3d569cd68f58d5a6550fc37bb87f6d571eeb5de3 100644 (file)
@@ -1946,10 +1946,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
                goto unmap;
        }
 
-       /* Ensure interrupts from this UART are masked and cleared */
-       writew(0, uap->port.membase + UART011_IMSC);
-       writew(0xffff, uap->port.membase + UART011_ICR);
-
        uap->vendor = vendor;
        uap->lcrh_rx = vendor->lcrh_rx;
        uap->lcrh_tx = vendor->lcrh_tx;
@@ -1967,6 +1963,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        uap->port.line = i;
        pl011_dma_probe(uap);
 
+       /* Ensure interrupts from this UART are masked and cleared */
+       writew(0, uap->port.membase + UART011_IMSC);
+       writew(0xffff, uap->port.membase + UART011_ICR);
+
        snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
 
        amba_ports[i] = uap;
index f9a6be7a9bed62103f24f461f593fec7a6a0a89c..3d7e1ee2fa57a4a6db1deb0a7a173b90769298a3 100644 (file)
@@ -389,6 +389,8 @@ static void atmel_start_rx(struct uart_port *port)
 {
        UART_PUT_CR(port, ATMEL_US_RSTSTA);  /* reset status and receiver */
 
+       UART_PUT_CR(port, ATMEL_US_RXEN);
+
        if (atmel_use_dma_rx(port)) {
                /* enable PDC controller */
                UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
@@ -404,6 +406,8 @@ static void atmel_start_rx(struct uart_port *port)
  */
 static void atmel_stop_rx(struct uart_port *port)
 {
+       UART_PUT_CR(port, ATMEL_US_RXDIS);
+
        if (atmel_use_dma_rx(port)) {
                /* disable PDC receive */
                UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
index e6c3dbd781d61fd21e9dcafd3d85c1a0799f1f66..836fe2731234bbeabe690ef41ee230588cedea1b 100644 (file)
@@ -154,10 +154,9 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
                port->x_char = 0;
                return IRQ_HANDLED;
        }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
-               clps711xuart_stop_tx(port);
-               return IRQ_HANDLED;
-       }
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+               goto disable_tx_irq;
 
        count = port->fifosize >> 1;
        do {
@@ -171,8 +170,11 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(port);
 
-       if (uart_circ_empty(xmit))
-               clps711xuart_stop_tx(port);
+       if (uart_circ_empty(xmit)) {
+       disable_tx_irq:
+               disable_irq_nosync(TX_IRQ(port));
+               tx_enabled(port) = 0;
+       }
 
        return IRQ_HANDLED;
 }
index a9234ba8f8d5b4df867092ad4229b9b933859b6d..c4b50af46c444b237b0054f454b27b5c9ec2749f 100644 (file)
@@ -127,11 +127,6 @@ static inline void serial_out(struct uart_hsu_port *up, int offset, int value)
 
 #define HSU_REGS_BUFSIZE       1024
 
-static int hsu_show_regs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
 
 static ssize_t port_show_regs(struct file *file, char __user *user_buf,
                                size_t count, loff_t *ppos)
@@ -231,14 +226,14 @@ static ssize_t dma_show_regs(struct file *file, char __user *user_buf,
 
 static const struct file_operations port_regs_ops = {
        .owner          = THIS_MODULE,
-       .open           = hsu_show_regs_open,
+       .open           = simple_open,
        .read           = port_show_regs,
        .llseek         = default_llseek,
 };
 
 static const struct file_operations dma_regs_ops = {
        .owner          = THIS_MODULE,
-       .open           = hsu_show_regs_open,
+       .open           = simple_open,
        .read           = dma_show_regs,
        .llseek         = default_llseek,
 };
index 0121486ac4fafbf3bf162ef3744772255e8380e5..d00b38eb268e84cf58ca94f52735622198ad954c 100644 (file)
@@ -1381,29 +1381,24 @@ static int serial_omap_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       if (!request_mem_region(mem->start, resource_size(mem),
+       if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
                                pdev->dev.driver->name)) {
                dev_err(&pdev->dev, "memory region already claimed\n");
                return -EBUSY;
        }
 
        dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
-       if (!dma_rx) {
-               ret = -EINVAL;
-               goto err;
-       }
+       if (!dma_rx)
+               return -ENXIO;
 
        dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
-       if (!dma_tx) {
-               ret = -EINVAL;
-               goto err;
-       }
+       if (!dma_tx)
+               return -ENXIO;
+
+       up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL);
+       if (!up)
+               return -ENOMEM;
 
-       up = kzalloc(sizeof(*up), GFP_KERNEL);
-       if (up == NULL) {
-               ret = -ENOMEM;
-               goto do_release_region;
-       }
        up->pdev = pdev;
        up->port.dev = &pdev->dev;
        up->port.type = PORT_OMAP;
@@ -1423,16 +1418,17 @@ static int serial_omap_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n",
                                                                up->port.line);
                ret = -ENODEV;
-               goto err;
+               goto err_port_line;
        }
 
        sprintf(up->name, "OMAP UART%d", up->port.line);
        up->port.mapbase = mem->start;
-       up->port.membase = ioremap(mem->start, resource_size(mem));
+       up->port.membase = devm_ioremap(&pdev->dev, mem->start,
+                                               resource_size(mem));
        if (!up->port.membase) {
                dev_err(&pdev->dev, "can't ioremap UART\n");
                ret = -ENOMEM;
-               goto err;
+               goto err_ioremap;
        }
 
        up->port.flags = omap_up_info->flags;
@@ -1478,16 +1474,19 @@ static int serial_omap_probe(struct platform_device *pdev)
 
        ret = uart_add_one_port(&serial_omap_reg, &up->port);
        if (ret != 0)
-               goto do_release_region;
+               goto err_add_port;
 
        pm_runtime_put(&pdev->dev);
        platform_set_drvdata(pdev, up);
        return 0;
-err:
+
+err_add_port:
+       pm_runtime_put(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+err_ioremap:
+err_port_line:
        dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
                                pdev->id, __func__, ret);
-do_release_region:
-       release_mem_region(mem->start, resource_size(mem));
        return ret;
 }
 
@@ -1499,8 +1498,6 @@ static int serial_omap_remove(struct platform_device *dev)
                pm_runtime_disable(&up->pdev->dev);
                uart_remove_one_port(&serial_omap_reg, &up->port);
                pm_qos_remove_request(&up->pm_qos_request);
-
-               kfree(up);
        }
 
        platform_set_drvdata(dev, NULL);
index e825460478befc40ad9e9a4d36243fa741a48cf0..c2816f4948070157f1c969898bfde97b58bd6841 100644 (file)
@@ -210,6 +210,7 @@ enum {
 #define CMITC_UARTCLK   192000000 /* 192.0000 MHz */
 #define FRI2_64_UARTCLK  64000000 /*  64.0000 MHz */
 #define FRI2_48_UARTCLK  48000000 /*  48.0000 MHz */
+#define NTC1_UARTCLK     64000000 /*  64.0000 MHz */
 
 struct pch_uart_buffer {
        unsigned char *buf;
@@ -304,11 +305,7 @@ static const int trigger_level_1[4] = { 1, 1, 1, 1 };
 #ifdef CONFIG_DEBUG_FS
 
 #define PCH_REGS_BUFSIZE       1024
-static int pch_show_regs_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
+
 
 static ssize_t port_show_regs(struct file *file, char __user *user_buf,
                                size_t count, loff_t *ppos)
@@ -362,7 +359,7 @@ static ssize_t port_show_regs(struct file *file, char __user *user_buf,
 
 static const struct file_operations port_regs_ops = {
        .owner          = THIS_MODULE,
-       .open           = pch_show_regs_open,
+       .open           = simple_open,
        .read           = port_show_regs,
        .llseek         = default_llseek,
 };
@@ -388,6 +385,12 @@ static int pch_uart_get_uartclk(void)
        if (cmp && strstr(cmp, "Fish River Island II"))
                return FRI2_48_UARTCLK;
 
+       /* Kontron COMe-mTT10 (nanoETXexpress-TT) */
+       cmp = dmi_get_system_info(DMI_BOARD_NAME);
+       if (cmp && (strstr(cmp, "COMe-mTT") ||
+                   strstr(cmp, "nanoETXexpress-TT")))
+               return NTC1_UARTCLK;
+
        return DEFAULT_UARTCLK;
 }
 
@@ -1444,9 +1447,11 @@ static int pch_uart_verify_port(struct uart_port *port,
                        __func__);
                return -EOPNOTSUPP;
 #endif
-               priv->use_dma = 1;
                priv->use_dma_flag = 1;
                dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n");
+               if (!priv->use_dma)
+                       pch_request_dma(port);
+               priv->use_dma = 1;
        }
 
        return 0;
@@ -1655,6 +1660,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
        }
 
        pci_enable_msi(pdev);
+       pci_set_master(pdev);
 
        iobase = pci_resource_start(pdev, 0);
        mapbase = pci_resource_start(pdev, 1);
index 08ebe901bb59875a95b87148a04d15404523c019..654755a990dfc30cac559567e260b17978bbc54b 100644 (file)
@@ -469,7 +469,7 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
        tty = NULL;
        if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
                if (!ZS_IS_OPEN(uap_a)) {
-                       pmz_debug("ChanA interrupt while open !\n");
+                       pmz_debug("ChanA interrupt while not open !\n");
                        goto skip_a;
                }
                write_zsreg(uap_a, R0, RES_H_IUS);
@@ -493,8 +493,8 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
        spin_lock(&uap_b->port.lock);
        tty = NULL;
        if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
-               if (!ZS_IS_OPEN(uap_a)) {
-                       pmz_debug("ChanB interrupt while open !\n");
+               if (!ZS_IS_OPEN(uap_b)) {
+                       pmz_debug("ChanB interrupt while not open !\n");
                        goto skip_b;
                }
                write_zsreg(uap_b, R0, RES_H_IUS);
index de249d265beca004c2dc59dc663976baff63b746..d8b0aee35632ede1a2f98ea7a1a751926a3c3e0a 100644 (file)
@@ -982,6 +982,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
 
        ucon &= ucon_mask;
        wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
+       wr_regl(port, S3C2410_ULCON, cfg->ulcon);
 
        /* reset both fifos */
        wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
index bf461cf99616c04aa9e2655eaee8e62d21c782db..3158e17b665cc6fb1c5eb214674610bd42611235 100644 (file)
@@ -355,9 +355,6 @@ static void sci_serial_out(struct uart_port *p, int offset, int value)
                WARN(1, "Invalid register access\n");
 }
 
-#define sci_in(up, offset)             (up->serial_in(up, offset))
-#define sci_out(up, offset, value)     (up->serial_out(up, offset, value))
-
 static int sci_probe_regmap(struct plat_sci_port *cfg)
 {
        switch (cfg->type) {
@@ -422,9 +419,9 @@ static int sci_poll_get_char(struct uart_port *port)
        int c;
 
        do {
-               status = sci_in(port, SCxSR);
+               status = serial_port_in(port, SCxSR);
                if (status & SCxSR_ERRORS(port)) {
-                       sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+                       serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
                        continue;
                }
                break;
@@ -433,11 +430,11 @@ static int sci_poll_get_char(struct uart_port *port)
        if (!(status & SCxSR_RDxF(port)))
                return NO_POLL_CHAR;
 
-       c = sci_in(port, SCxRDR);
+       c = serial_port_in(port, SCxRDR);
 
        /* Dummy read */
-       sci_in(port, SCxSR);
-       sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+       serial_port_in(port, SCxSR);
+       serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
 
        return c;
 }
@@ -448,11 +445,11 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c)
        unsigned short status;
 
        do {
-               status = sci_in(port, SCxSR);
+               status = serial_port_in(port, SCxSR);
        } while (!(status & SCxSR_TDxE(port)));
 
-       sci_out(port, SCxTDR, c);
-       sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
+       serial_port_out(port, SCxTDR, c);
+       serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
 }
 #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
 
@@ -480,10 +477,10 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
            ((!(cflag & CRTSCTS)))) {
                unsigned short status;
 
-               status = sci_in(port, SCSPTR);
+               status = serial_port_in(port, SCSPTR);
                status &= ~SCSPTR_CTSIO;
                status |= SCSPTR_RTSIO;
-               sci_out(port, SCSPTR, status); /* Set RTS = 1 */
+               serial_port_out(port, SCSPTR, status); /* Set RTS = 1 */
        }
 }
 
@@ -493,13 +490,13 @@ static int sci_txfill(struct uart_port *port)
 
        reg = sci_getreg(port, SCTFDR);
        if (reg->size)
-               return sci_in(port, SCTFDR) & 0xff;
+               return serial_port_in(port, SCTFDR) & 0xff;
 
        reg = sci_getreg(port, SCFDR);
        if (reg->size)
-               return sci_in(port, SCFDR) >> 8;
+               return serial_port_in(port, SCFDR) >> 8;
 
-       return !(sci_in(port, SCxSR) & SCI_TDRE);
+       return !(serial_port_in(port, SCxSR) & SCI_TDRE);
 }
 
 static int sci_txroom(struct uart_port *port)
@@ -513,13 +510,13 @@ static int sci_rxfill(struct uart_port *port)
 
        reg = sci_getreg(port, SCRFDR);
        if (reg->size)
-               return sci_in(port, SCRFDR) & 0xff;
+               return serial_port_in(port, SCRFDR) & 0xff;
 
        reg = sci_getreg(port, SCFDR);
        if (reg->size)
-               return sci_in(port, SCFDR) & ((port->fifosize << 1) - 1);
+               return serial_port_in(port, SCFDR) & ((port->fifosize << 1) - 1);
 
-       return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
+       return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
 }
 
 /*
@@ -547,14 +544,14 @@ static void sci_transmit_chars(struct uart_port *port)
        unsigned short ctrl;
        int count;
 
-       status = sci_in(port, SCxSR);
+       status = serial_port_in(port, SCxSR);
        if (!(status & SCxSR_TDxE(port))) {
-               ctrl = sci_in(port, SCSCR);
+               ctrl = serial_port_in(port, SCSCR);
                if (uart_circ_empty(xmit))
                        ctrl &= ~SCSCR_TIE;
                else
                        ctrl |= SCSCR_TIE;
-               sci_out(port, SCSCR, ctrl);
+               serial_port_out(port, SCSCR, ctrl);
                return;
        }
 
@@ -573,27 +570,27 @@ static void sci_transmit_chars(struct uart_port *port)
                        break;
                }
 
-               sci_out(port, SCxTDR, c);
+               serial_port_out(port, SCxTDR, c);
 
                port->icount.tx++;
        } while (--count > 0);
 
-       sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+       serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(port);
        if (uart_circ_empty(xmit)) {
                sci_stop_tx(port);
        } else {
-               ctrl = sci_in(port, SCSCR);
+               ctrl = serial_port_in(port, SCSCR);
 
                if (port->type != PORT_SCI) {
-                       sci_in(port, SCxSR); /* Dummy read */
-                       sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+                       serial_port_in(port, SCxSR); /* Dummy read */
+                       serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
                }
 
                ctrl |= SCSCR_TIE;
-               sci_out(port, SCSCR, ctrl);
+               serial_port_out(port, SCSCR, ctrl);
        }
 }
 
@@ -608,7 +605,7 @@ static void sci_receive_chars(struct uart_port *port)
        unsigned short status;
        unsigned char flag;
 
-       status = sci_in(port, SCxSR);
+       status = serial_port_in(port, SCxSR);
        if (!(status & SCxSR_RDxF(port)))
                return;
 
@@ -621,7 +618,7 @@ static void sci_receive_chars(struct uart_port *port)
                        break;
 
                if (port->type == PORT_SCI) {
-                       char c = sci_in(port, SCxRDR);
+                       char c = serial_port_in(port, SCxRDR);
                        if (uart_handle_sysrq_char(port, c) ||
                            sci_port->break_flag)
                                count = 0;
@@ -629,9 +626,9 @@ static void sci_receive_chars(struct uart_port *port)
                                tty_insert_flip_char(tty, c, TTY_NORMAL);
                } else {
                        for (i = 0; i < count; i++) {
-                               char c = sci_in(port, SCxRDR);
+                               char c = serial_port_in(port, SCxRDR);
 
-                               status = sci_in(port, SCxSR);
+                               status = serial_port_in(port, SCxSR);
 #if defined(CONFIG_CPU_SH3)
                                /* Skip "chars" during break */
                                if (sci_port->break_flag) {
@@ -672,8 +669,8 @@ static void sci_receive_chars(struct uart_port *port)
                        }
                }
 
-               sci_in(port, SCxSR); /* dummy read */
-               sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+               serial_port_in(port, SCxSR); /* dummy read */
+               serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
 
                copied += count;
                port->icount.rx += count;
@@ -683,8 +680,8 @@ static void sci_receive_chars(struct uart_port *port)
                /* Tell the rest of the system the news. New characters! */
                tty_flip_buffer_push(tty);
        } else {
-               sci_in(port, SCxSR); /* dummy read */
-               sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+               serial_port_in(port, SCxSR); /* dummy read */
+               serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
        }
 }
 
@@ -726,7 +723,7 @@ static void sci_break_timer(unsigned long data)
 static int sci_handle_errors(struct uart_port *port)
 {
        int copied = 0;
-       unsigned short status = sci_in(port, SCxSR);
+       unsigned short status = serial_port_in(port, SCxSR);
        struct tty_struct *tty = port->state->port.tty;
        struct sci_port *s = to_sci_port(port);
 
@@ -804,8 +801,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
        if (!reg->size)
                return 0;
 
-       if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
-               sci_out(port, SCLSR, 0);
+       if ((serial_port_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
+               serial_port_out(port, SCLSR, 0);
 
                port->icount.overrun++;
 
@@ -822,7 +819,7 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
 static int sci_handle_breaks(struct uart_port *port)
 {
        int copied = 0;
-       unsigned short status = sci_in(port, SCxSR);
+       unsigned short status = serial_port_in(port, SCxSR);
        struct tty_struct *tty = port->state->port.tty;
        struct sci_port *s = to_sci_port(port);
 
@@ -859,8 +856,8 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
        struct sci_port *s = to_sci_port(port);
 
        if (s->chan_rx) {
-               u16 scr = sci_in(port, SCSCR);
-               u16 ssr = sci_in(port, SCxSR);
+               u16 scr = serial_port_in(port, SCSCR);
+               u16 ssr = serial_port_in(port, SCxSR);
 
                /* Disable future Rx interrupts */
                if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
@@ -869,9 +866,9 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
                } else {
                        scr &= ~SCSCR_RIE;
                }
-               sci_out(port, SCSCR, scr);
+               serial_port_out(port, SCSCR, scr);
                /* Clear current interrupt */
-               sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
+               serial_port_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
                dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n",
                        jiffies, s->rx_timeout);
                mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
@@ -909,15 +906,15 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr)
        if (port->type == PORT_SCI) {
                if (sci_handle_errors(port)) {
                        /* discard character in rx buffer */
-                       sci_in(port, SCxSR);
-                       sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+                       serial_port_in(port, SCxSR);
+                       serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
                }
        } else {
                sci_handle_fifo_overrun(port);
                sci_rx_interrupt(irq, ptr);
        }
 
-       sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+       serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
 
        /* Kick the transmission */
        sci_tx_interrupt(irq, ptr);
@@ -931,7 +928,7 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
 
        /* Handle BREAKs */
        sci_handle_breaks(port);
-       sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
+       serial_port_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
 
        return IRQ_HANDLED;
 }
@@ -955,8 +952,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
        struct sci_port *s = to_sci_port(port);
        irqreturn_t ret = IRQ_NONE;
 
-       ssr_status = sci_in(port, SCxSR);
-       scr_status = sci_in(port, SCSCR);
+       ssr_status = serial_port_in(port, SCxSR);
+       scr_status = serial_port_in(port, SCSCR);
        err_enabled = scr_status & port_rx_irq_mask(port);
 
        /* Tx Interrupt */
@@ -1170,7 +1167,7 @@ static void sci_free_gpios(struct sci_port *port)
 
 static unsigned int sci_tx_empty(struct uart_port *port)
 {
-       unsigned short status = sci_in(port, SCxSR);
+       unsigned short status = serial_port_in(port, SCxSR);
        unsigned short in_tx_fifo = sci_txfill(port);
 
        return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
@@ -1198,7 +1195,7 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
                 */
                reg = sci_getreg(port, SCFCR);
                if (reg->size)
-                       sci_out(port, SCFCR, sci_in(port, SCFCR) | 1);
+                       serial_port_out(port, SCFCR, serial_port_in(port, SCFCR) | 1);
        }
 }
 
@@ -1240,8 +1237,8 @@ static void sci_dma_tx_complete(void *arg)
        } else {
                s->cookie_tx = -EINVAL;
                if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-                       u16 ctrl = sci_in(port, SCSCR);
-                       sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+                       u16 ctrl = serial_port_in(port, SCSCR);
+                       serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
                }
        }
 
@@ -1494,13 +1491,13 @@ static void sci_start_tx(struct uart_port *port)
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
-               u16 new, scr = sci_in(port, SCSCR);
+               u16 new, scr = serial_port_in(port, SCSCR);
                if (s->chan_tx)
                        new = scr | 0x8000;
                else
                        new = scr & ~0x8000;
                if (new != scr)
-                       sci_out(port, SCSCR, new);
+                       serial_port_out(port, SCSCR, new);
        }
 
        if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
@@ -1512,8 +1509,8 @@ static void sci_start_tx(struct uart_port *port)
 
        if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
                /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
-               ctrl = sci_in(port, SCSCR);
-               sci_out(port, SCSCR, ctrl | SCSCR_TIE);
+               ctrl = serial_port_in(port, SCSCR);
+               serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
        }
 }
 
@@ -1522,40 +1519,40 @@ static void sci_stop_tx(struct uart_port *port)
        unsigned short ctrl;
 
        /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
-       ctrl = sci_in(port, SCSCR);
+       ctrl = serial_port_in(port, SCSCR);
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~0x8000;
 
        ctrl &= ~SCSCR_TIE;
 
-       sci_out(port, SCSCR, ctrl);
+       serial_port_out(port, SCSCR, ctrl);
 }
 
 static void sci_start_rx(struct uart_port *port)
 {
        unsigned short ctrl;
 
-       ctrl = sci_in(port, SCSCR) | port_rx_irq_mask(port);
+       ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~0x4000;
 
-       sci_out(port, SCSCR, ctrl);
+       serial_port_out(port, SCSCR, ctrl);
 }
 
 static void sci_stop_rx(struct uart_port *port)
 {
        unsigned short ctrl;
 
-       ctrl = sci_in(port, SCSCR);
+       ctrl = serial_port_in(port, SCSCR);
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
                ctrl &= ~0x4000;
 
        ctrl &= ~port_rx_irq_mask(port);
 
-       sci_out(port, SCSCR, ctrl);
+       serial_port_out(port, SCSCR, ctrl);
 }
 
 static void sci_enable_ms(struct uart_port *port)
@@ -1589,13 +1586,13 @@ static void rx_timer_fn(unsigned long arg)
 {
        struct sci_port *s = (struct sci_port *)arg;
        struct uart_port *port = &s->port;
-       u16 scr = sci_in(port, SCSCR);
+       u16 scr = serial_port_in(port, SCSCR);
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
                scr &= ~0x4000;
                enable_irq(s->cfg->irqs[1]);
        }
-       sci_out(port, SCSCR, scr | SCSCR_RIE);
+       serial_port_out(port, SCSCR, scr | SCSCR_RIE);
        dev_dbg(port->dev, "DMA Rx timed out\n");
        schedule_work(&s->work_rx);
 }
@@ -1776,14 +1773,14 @@ static void sci_reset(struct uart_port *port)
        unsigned int status;
 
        do {
-               status = sci_in(port, SCxSR);
+               status = serial_port_in(port, SCxSR);
        } while (!(status & SCxSR_TEND(port)));
 
-       sci_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
+       serial_port_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
 
        reg = sci_getreg(port, SCFCR);
        if (reg->size)
-               sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
+               serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
 }
 
 static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
@@ -1812,7 +1809,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
        sci_reset(port);
 
-       smr_val = sci_in(port, SCSMR) & 3;
+       smr_val = serial_port_in(port, SCSMR) & 3;
 
        if ((termios->c_cflag & CSIZE) == CS7)
                smr_val |= 0x40;
@@ -1825,19 +1822,19 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
        uart_update_timeout(port, termios->c_cflag, baud);
 
-       sci_out(port, SCSMR, smr_val);
+       serial_port_out(port, SCSMR, smr_val);
 
        dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
                s->cfg->scscr);
 
        if (t > 0) {
                if (t >= 256) {
-                       sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
+                       serial_port_out(port, SCSMR, (serial_port_in(port, SCSMR) & ~3) | 1);
                        t >>= 2;
                } else
-                       sci_out(port, SCSMR, sci_in(port, SCSMR) & ~3);
+                       serial_port_out(port, SCSMR, serial_port_in(port, SCSMR) & ~3);
 
-               sci_out(port, SCBRR, t);
+               serial_port_out(port, SCBRR, t);
                udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
        }
 
@@ -1845,7 +1842,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
        reg = sci_getreg(port, SCFCR);
        if (reg->size) {
-               unsigned short ctrl = sci_in(port, SCFCR);
+               unsigned short ctrl = serial_port_in(port, SCFCR);
 
                if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) {
                        if (termios->c_cflag & CRTSCTS)
@@ -1861,10 +1858,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
                 */
                ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);
 
-               sci_out(port, SCFCR, ctrl);
+               serial_port_out(port, SCFCR, ctrl);
        }
 
-       sci_out(port, SCSCR, s->cfg->scscr);
+       serial_port_out(port, SCSCR, s->cfg->scscr);
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
        /*
@@ -2166,7 +2163,7 @@ static void serial_console_write(struct console *co, const char *s,
 
        /* wait until fifo is empty and last bit has been transmitted */
        bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
-       while ((sci_in(port, SCxSR) & bits) != bits)
+       while ((serial_port_in(port, SCxSR) & bits) != bits)
                cpu_relax();
 
        sci_port_disable(sci_port);
@@ -2260,12 +2257,12 @@ static int sci_runtime_suspend(struct device *dev)
        if (uart_console(port)) {
                struct plat_sci_reg *reg;
 
-               sci_port->saved_smr = sci_in(port, SCSMR);
-               sci_port->saved_brr = sci_in(port, SCBRR);
+               sci_port->saved_smr = serial_port_in(port, SCSMR);
+               sci_port->saved_brr = serial_port_in(port, SCBRR);
 
                reg = sci_getreg(port, SCFCR);
                if (reg->size)
-                       sci_port->saved_fcr = sci_in(port, SCFCR);
+                       sci_port->saved_fcr = serial_port_in(port, SCFCR);
                else
                        sci_port->saved_fcr = 0;
        }
@@ -2279,13 +2276,13 @@ static int sci_runtime_resume(struct device *dev)
 
        if (uart_console(port)) {
                sci_reset(port);
-               sci_out(port, SCSMR, sci_port->saved_smr);
-               sci_out(port, SCBRR, sci_port->saved_brr);
+               serial_port_out(port, SCSMR, sci_port->saved_smr);
+               serial_port_out(port, SCBRR, sci_port->saved_brr);
 
                if (sci_port->saved_fcr)
-                       sci_out(port, SCFCR, sci_port->saved_fcr);
+                       serial_port_out(port, SCFCR, sci_port->saved_fcr);
 
-               sci_out(port, SCSCR, sci_port->cfg->scscr);
+               serial_port_out(port, SCSCR, sci_port->cfg->scscr);
        }
        return 0;
 }
index a1a2d364f92b6a5fa92e865e4fd91954ce6119dc..4c22a1529aac7c2304aeb15b302a6c9021c1174d 100644 (file)
     defined(CONFIG_ARCH_SH7372) || \
     defined(CONFIG_ARCH_R8A7740)
 
-# define SCxSR_RDxF_CLEAR(port)         (sci_in(port, SCxSR) & 0xfffc)
-# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
-# define SCxSR_TDxE_CLEAR(port)         (sci_in(port, SCxSR) & 0xffdf)
-# define SCxSR_BREAK_CLEAR(port) (sci_in(port, SCxSR) & 0xffe3)
+# define SCxSR_RDxF_CLEAR(port)         (serial_port_in(port, SCxSR) & 0xfffc)
+# define SCxSR_ERROR_CLEAR(port) (serial_port_in(port, SCxSR) & 0xfd73)
+# define SCxSR_TDxE_CLEAR(port)         (serial_port_in(port, SCxSR) & 0xffdf)
+# define SCxSR_BREAK_CLEAR(port) (serial_port_in(port, SCxSR) & 0xffe3)
 #else
 # define SCxSR_RDxF_CLEAR(port)         (((port)->type == PORT_SCI) ? 0xbc : 0x00fc)
 # define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073)
index b3b70b0bf85bc8abaa36dedf44c97eb5e39080a9..babd9470982b6694c2458a32248603e7bb06a79c 100644 (file)
@@ -1581,7 +1581,7 @@ static int __init sunzilog_init(void)
        if (err)
                goto out_unregister_uart;
 
-       if (!zilog_irq) {
+       if (zilog_irq) {
                struct uart_sunzilog_port *up = sunzilog_irq_chain;
                err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
                                  "zs", sunzilog_irq_chain);
@@ -1622,7 +1622,7 @@ static void __exit sunzilog_exit(void)
 {
        platform_driver_unregister(&zs_driver);
 
-       if (!zilog_irq) {
+       if (zilog_irq) {
                struct uart_sunzilog_port *up = sunzilog_irq_chain;
 
                /* Disable Interrupts */
index 136e86faa1e17e0e807a3c41b93fd464fd7c8729..05728894a88c23330e7b57eb8994f50477fc1b73 100644 (file)
@@ -327,7 +327,7 @@ static void send_sig_all(int sig)
                if (is_global_init(p))
                        continue;
 
-               force_sig(sig, p);
+               do_send_sig_info(sig, SEND_SIG_FORCED, p, true);
        }
        read_unlock(&tasklist_lock);
 }
index 86dd1e302bb3f0989d52ba2b136d1ec39e29c488..29ca20dbd335da2235339b8f7970849f2d22895f 100644 (file)
@@ -1085,15 +1085,21 @@ void vt_set_led_state(int console, int leds)
  *
  *     Handle console start. This is a wrapper for the VT layer
  *     so that we can keep kbd knowledge internal
+ *
+ *     FIXME: We eventually need to hold the kbd lock here to protect
+ *     the LED updating. We can't do it yet because fn_hold calls stop_tty
+ *     and start_tty under the kbd_event_lock, while normal tty paths
+ *     don't hold the lock. We probably need to split out an LED lock
+ *     but not during an -rc release!
  */
 void vt_kbd_con_start(int console)
 {
        struct kbd_struct * kbd = kbd_table + console;
-       unsigned long flags;
-       spin_lock_irqsave(&kbd_event_lock, flags);
+/*     unsigned long flags; */
+/*     spin_lock_irqsave(&kbd_event_lock, flags); */
        clr_vc_kbd_led(kbd, VC_SCROLLOCK);
        set_leds();
-       spin_unlock_irqrestore(&kbd_event_lock, flags);
+/*     spin_unlock_irqrestore(&kbd_event_lock, flags); */
 }
 
 /**
@@ -1102,22 +1108,28 @@ void vt_kbd_con_start(int console)
  *
  *     Handle console stop. This is a wrapper for the VT layer
  *     so that we can keep kbd knowledge internal
+ *
+ *     FIXME: We eventually need to hold the kbd lock here to protect
+ *     the LED updating. We can't do it yet because fn_hold calls stop_tty
+ *     and start_tty under the kbd_event_lock, while normal tty paths
+ *     don't hold the lock. We probably need to split out an LED lock
+ *     but not during an -rc release!
  */
 void vt_kbd_con_stop(int console)
 {
        struct kbd_struct * kbd = kbd_table + console;
-       unsigned long flags;
-       spin_lock_irqsave(&kbd_event_lock, flags);
+/*     unsigned long flags; */
+/*     spin_lock_irqsave(&kbd_event_lock, flags); */
        set_vc_kbd_led(kbd, VC_SCROLLOCK);
        set_leds();
-       spin_unlock_irqrestore(&kbd_event_lock, flags);
+/*     spin_unlock_irqrestore(&kbd_event_lock, flags); */
 }
 
 /*
  * This is the tasklet that updates LED state on all keyboards
  * attached to the box. The reason we use tasklet is that we
  * need to handle the scenario when keyboard handler is not
- * registered yet but we already getting updates form VT to
+ * registered yet but we already getting updates from the VT to
  * update led state.
  */
 static void kbd_bh(unsigned long dummy)
index 3bdd4b19dd06b6c90dd6cea689f3a31bb54454c4..2156188db4a64e73d41d8a7aa5cc8d4980f356e1 100644 (file)
@@ -2932,11 +2932,10 @@ static int __init con_init(void)
        gotoxy(vc, vc->vc_x, vc->vc_y);
        csi_J(vc, 0);
        update_screen(vc);
-       pr_info("Console: %s %s %dx%d",
+       pr_info("Console: %s %s %dx%d\n",
                vc->vc_can_do_color ? "colour" : "mono",
                display_desc, vc->vc_cols, vc->vc_rows);
        printable = 1;
-       printk("\n");
 
        console_unlock();
 
index cbd8f5f805962a2d1e6b87bce4f7c37137bb5e4c..76316a33061b91b48a62a60f6be1b921227c6ed8 100644 (file)
@@ -2,14 +2,6 @@
 # USB device configuration
 #
 
-menuconfig USB_SUPPORT
-       bool "USB support"
-       depends on HAS_IOMEM
-       default y
-       ---help---
-         This option adds core support for Universal Serial Bus (USB).
-         You will also need drivers from the following menu to make use of it.
-
 # many non-PCI SOC chips embed OHCI
 config USB_ARCH_HAS_OHCI
        boolean
@@ -63,6 +55,14 @@ config USB_ARCH_HAS_XHCI
        boolean
        default PCI
 
+menuconfig USB_SUPPORT
+       bool "USB support"
+       depends on HAS_IOMEM
+       default y
+       ---help---
+         This option adds core support for Universal Serial Bus (USB).
+         You will also need drivers from the following menu to make use of it.
+
 if USB_SUPPORT
 
 config USB_COMMON
index c6f6560d436c804bba1f539a2b6cd1c12be8633d..0bb2b3248dad99b0e114b83dc1028edd5fadb4a1 100644 (file)
@@ -157,8 +157,9 @@ static void wdm_out_callback(struct urb *urb)
        spin_lock(&desc->iuspin);
        desc->werr = urb->status;
        spin_unlock(&desc->iuspin);
-       clear_bit(WDM_IN_USE, &desc->flags);
        kfree(desc->outbuf);
+       desc->outbuf = NULL;
+       clear_bit(WDM_IN_USE, &desc->flags);
        wake_up(&desc->wait);
 }
 
@@ -338,7 +339,7 @@ static ssize_t wdm_write
        if (we < 0)
                return -EIO;
 
-       desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
+       buf = kmalloc(count, GFP_KERNEL);
        if (!buf) {
                rv = -ENOMEM;
                goto outnl;
@@ -406,10 +407,12 @@ static ssize_t wdm_write
        req->wIndex = desc->inum;
        req->wLength = cpu_to_le16(count);
        set_bit(WDM_IN_USE, &desc->flags);
+       desc->outbuf = buf;
 
        rv = usb_submit_urb(desc->command, GFP_KERNEL);
        if (rv < 0) {
                kfree(buf);
+               desc->outbuf = NULL;
                clear_bit(WDM_IN_USE, &desc->flags);
                dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
        } else {
index f8e2d6d52e5c4bf645c3679807456d8a4303ec9d..9a56635dc19ceb980ea71986dd97bb9d9ea725e8 100644 (file)
@@ -1189,8 +1189,13 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
        if (status == 0) {
                status = usb_suspend_device(udev, msg);
 
-               /* Again, ignore errors during system sleep transitions */
-               if (!PMSG_IS_AUTO(msg))
+               /*
+                * Ignore errors from non-root-hub devices during
+                * system sleep transitions.  For the most part,
+                * these devices should go to low power anyway when
+                * the entire bus is suspended.
+                */
+               if (udev->parent && !PMSG_IS_AUTO(msg))
                        status = 0;
        }
 
index 622b4a48e732e7a83b6c760d6563994394b0caa9..57ed9e400c06d938a91fd9713b95a9e97030b3a3 100644 (file)
@@ -493,6 +493,15 @@ static int hcd_pci_suspend_noirq(struct device *dev)
 
        pci_save_state(pci_dev);
 
+       /*
+        * Some systems crash if an EHCI controller is in D3 during
+        * a sleep transition.  We have to leave such controllers in D0.
+        */
+       if (hcd->broken_pci_sleep) {
+               dev_dbg(dev, "Staying in PCI D0\n");
+               return retval;
+       }
+
        /* If the root hub is dead rather than suspended, disallow remote
         * wakeup.  usb_hc_died() should ensure that both hosts are marked as
         * dying, so we only need to check the primary roothub.
index 9d7fc9a399338854426bb2a23c6990e4077b3525..140d3e11f2124291f7051fb6e743a10f74c8f541 100644 (file)
@@ -1978,6 +1978,18 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
        if (status == 0) {
                usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
                hcd->state = HC_STATE_SUSPENDED;
+
+               /* Did we race with a root-hub wakeup event? */
+               if (rhdev->do_remote_wakeup) {
+                       char    buffer[6];
+
+                       status = hcd->driver->hub_status_data(hcd, buffer);
+                       if (status != 0) {
+                               dev_dbg(&rhdev->dev, "suspend raced with wakeup event\n");
+                               hcd_bus_resume(rhdev, PMSG_AUTO_RESUME);
+                               status = -EBUSY;
+                       }
+               }
        } else {
                spin_lock_irq(&hcd_root_hub_lock);
                if (!HCD_DEAD(hcd)) {
index 28664eb7f5554cfe07f017d9d5e24be65671e85b..ec6c97dadbe4dba5e3cf8a47980e23256a44bff5 100644 (file)
@@ -1667,7 +1667,6 @@ void usb_disconnect(struct usb_device **pdev)
 {
        struct usb_device       *udev = *pdev;
        int                     i;
-       struct usb_hcd          *hcd = bus_to_hcd(udev->bus);
 
        /* mark the device as inactive, so any further urb submissions for
         * this device (and any of its children) will fail immediately.
@@ -1690,9 +1689,7 @@ void usb_disconnect(struct usb_device **pdev)
         * so that the hardware is now fully quiesced.
         */
        dev_dbg (&udev->dev, "unregistering device\n");
-       mutex_lock(hcd->bandwidth_mutex);
        usb_disable_device(udev, 0);
-       mutex_unlock(hcd->bandwidth_mutex);
        usb_hcd_synchronize_unlinks(udev);
 
        usb_remove_ep_devs(&udev->ep0);
@@ -3163,6 +3160,22 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        if (retval)
                goto fail;
 
+       /*
+        * Some superspeed devices have finished the link training process
+        * and attached to a superspeed hub port, but the device descriptor
+        * got from those devices show they aren't superspeed devices. Warm
+        * reset the port attached by the devices can fix them.
+        */
+       if ((udev->speed == USB_SPEED_SUPER) &&
+                       (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
+               dev_err(&udev->dev, "got a wrong device descriptor, "
+                               "warm reset device\n");
+               hub_port_reset(hub, port1, udev,
+                               HUB_BH_RESET_TIME, true);
+               retval = -EINVAL;
+               goto fail;
+       }
+
        if (udev->descriptor.bMaxPacketSize0 == 0xff ||
                        udev->speed == USB_SPEED_SUPER)
                i = 512;
index cefa0c8b5b6ab983468b36ceed1cac3f66cbcb0e..d2b9af59cba9ab13da2cdbaac1160a30219bf277 100644 (file)
@@ -428,18 +428,10 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
        return retval;
 }
 
-static int default_open (struct inode *inode, struct file *file)
-{
-       if (inode->i_private)
-               file->private_data = inode->i_private;
-
-       return 0;
-}
-
 static const struct file_operations default_file_operations = {
        .read =         default_read_file,
        .write =        default_write_file,
-       .open =         default_open,
+       .open =         simple_open,
        .llseek =       default_file_lseek,
 };
 
index b3bdfede45e68721376c381a42950044da9625ad..ca717da3be95ddbab8d4b5211e78af699fcb1399 100644 (file)
@@ -308,7 +308,8 @@ static void sg_complete(struct urb *urb)
                                retval = usb_unlink_urb(io->urbs [i]);
                                if (retval != -EINPROGRESS &&
                                    retval != -ENODEV &&
-                                   retval != -EBUSY)
+                                   retval != -EBUSY &&
+                                   retval != -EIDRM)
                                        dev_err(&io->dev->dev,
                                                "%s, unlink --> %d\n",
                                                __func__, retval);
@@ -317,7 +318,6 @@ static void sg_complete(struct urb *urb)
                }
                spin_lock(&io->lock);
        }
-       urb->dev = NULL;
 
        /* on the last completion, signal usb_sg_wait() */
        io->bytes += urb->actual_length;
@@ -524,7 +524,6 @@ void usb_sg_wait(struct usb_sg_request *io)
                case -ENXIO:    /* hc didn't queue this one */
                case -EAGAIN:
                case -ENOMEM:
-                       io->urbs[i]->dev = NULL;
                        retval = 0;
                        yield();
                        break;
@@ -542,7 +541,6 @@ void usb_sg_wait(struct usb_sg_request *io)
 
                        /* fail any uncompleted urbs */
                default:
-                       io->urbs[i]->dev = NULL;
                        io->urbs[i]->status = retval;
                        dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
                                __func__, retval);
@@ -593,7 +591,10 @@ void usb_sg_cancel(struct usb_sg_request *io)
                        if (!io->urbs [i]->dev)
                                continue;
                        retval = usb_unlink_urb(io->urbs [i]);
-                       if (retval != -EINPROGRESS && retval != -EBUSY)
+                       if (retval != -EINPROGRESS
+                                       && retval != -ENODEV
+                                       && retval != -EBUSY
+                                       && retval != -EIDRM)
                                dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
                                        __func__, retval);
                }
@@ -1135,8 +1136,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
  * Deallocates hcd/hardware state for the endpoints (nuking all or most
  * pending urbs) and usbcore state for the interfaces, so that usbcore
  * must usb_set_configuration() before any interfaces could be used.
- *
- * Must be called with hcd->bandwidth_mutex held.
  */
 void usb_disable_device(struct usb_device *dev, int skip_ep0)
 {
@@ -1189,7 +1188,9 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
                        usb_disable_endpoint(dev, i + USB_DIR_IN, false);
                }
                /* Remove endpoints from the host controller internal state */
+               mutex_lock(hcd->bandwidth_mutex);
                usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+               mutex_unlock(hcd->bandwidth_mutex);
                /* Second pass: remove endpoint pointers */
        }
        for (i = skip_ep0; i < 16; ++i) {
@@ -1749,7 +1750,6 @@ free_interfaces:
        /* if it's already configured, clear out old state first.
         * getting rid of old interfaces means unbinding their drivers.
         */
-       mutex_lock(hcd->bandwidth_mutex);
        if (dev->state != USB_STATE_ADDRESS)
                usb_disable_device(dev, 1);     /* Skip ep0 */
 
@@ -1762,6 +1762,7 @@ free_interfaces:
         * host controller will not allow submissions to dropped endpoints.  If
         * this call fails, the device state is unchanged.
         */
+       mutex_lock(hcd->bandwidth_mutex);
        ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
        if (ret < 0) {
                mutex_unlock(hcd->bandwidth_mutex);
index 7239a73c1b8c840f89fb22ab19b351bec1dd2b53..cd9b3a2cd8a73cef173d19971213778343edad30 100644 (file)
@@ -539,6 +539,10 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
  * never submitted, or it was unlinked before, or the hardware is already
  * finished with it), even if the completion handler has not yet run.
  *
+ * The URB must not be deallocated while this routine is running.  In
+ * particular, when a driver calls this routine, it must insure that the
+ * completion handler cannot deallocate the URB.
+ *
  * Unlinking and Endpoint Queues:
  *
  * [The behaviors and guarantees described below do not apply to virtual
@@ -603,6 +607,10 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb);
  * with error -EPERM.  Thus even if the URB's completion handler always
  * tries to resubmit, it will not succeed and the URB will become idle.
  *
+ * The URB must not be deallocated while this routine is running.  In
+ * particular, when a driver calls this routine, it must insure that the
+ * completion handler cannot deallocate the URB.
+ *
  * This routine may not be used in an interrupt context (such as a bottom
  * half or a completion handler), or when holding a spinlock, or in other
  * situations where the caller can't schedule().
@@ -640,6 +648,10 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
  * with error -EPERM.  Thus even if the URB's completion handler always
  * tries to resubmit, it will not succeed and the URB will become idle.
  *
+ * The URB must not be deallocated while this routine is running.  In
+ * particular, when a driver calls this routine, it must insure that the
+ * completion handler cannot deallocate the URB.
+ *
  * This routine may not be used in an interrupt context (such as a bottom
  * half or a completion handler), or when holding a spinlock, or in other
  * situations where the caller can't schedule().
index 7bd815a507e8c3c94f9faaf0545b465f7ed3a781..99b58d84553acd56263ad0ed1e774f9d9eb2afec 100644 (file)
@@ -206,11 +206,11 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc)
 
        for (i = 0; i < dwc->num_event_buffers; i++) {
                evt = dwc->ev_buffs[i];
-               if (evt) {
+               if (evt)
                        dwc3_free_one_event_buffer(dwc, evt);
-                       dwc->ev_buffs[i] = NULL;
-               }
        }
+
+       kfree(dwc->ev_buffs);
 }
 
 /**
index 25910e251c04b4fb7ce0ef8bb9685573e859b9b9..3584a169886f3dfa23b8513c3850dd71f71e22e0 100644 (file)
@@ -353,6 +353,9 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 
                        dwc->test_mode_nr = wIndex >> 8;
                        dwc->test_mode = true;
+                       break;
+               default:
+                       return -EINVAL;
                }
                break;
 
@@ -559,15 +562,20 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
        length = trb->size & DWC3_TRB_SIZE_MASK;
 
        if (dwc->ep0_bounced) {
+               unsigned transfer_size = ur->length;
+               unsigned maxp = ep0->endpoint.maxpacket;
+
+               transfer_size += (maxp - (transfer_size % maxp));
                transferred = min_t(u32, ur->length,
-                               ep0->endpoint.maxpacket - length);
+                               transfer_size - length);
                memcpy(ur->buf, dwc->ep0_bounce, transferred);
                dwc->ep0_bounced = false;
        } else {
                transferred = ur->length - length;
-               ur->actual += transferred;
        }
 
+       ur->actual += transferred;
+
        if ((epnum & 1) && ur->actual < ur->length) {
                /* for some reason we did not get everything out */
 
index 0c935d7c65bdf7379f466e5c3f1522fb88a7e266..9d7bcd910074d0715a282c35d0e439539cdd3367 100644 (file)
@@ -1863,8 +1863,8 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
                        mod_timer(&udc->vbus_timer,
                                  jiffies + VBUS_POLL_TIMEOUT);
                } else {
-                       if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
-                                       0, driver_name, udc)) {
+                       if (request_irq(gpio_to_irq(udc->board.vbus_pin),
+                                       at91_vbus_irq, 0, driver_name, udc)) {
                                DBG("request vbus irq %d failed\n",
                                    udc->board.vbus_pin);
                                retval = -EBUSY;
@@ -1886,7 +1886,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
        return 0;
 fail4:
        if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled)
-               free_irq(udc->board.vbus_pin, udc);
+               free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
 fail3:
        if (gpio_is_valid(udc->board.vbus_pin))
                gpio_free(udc->board.vbus_pin);
@@ -1924,7 +1924,7 @@ static int __exit at91udc_remove(struct platform_device *pdev)
        device_init_wakeup(&pdev->dev, 0);
        remove_debug_file(udc);
        if (gpio_is_valid(udc->board.vbus_pin)) {
-               free_irq(udc->board.vbus_pin, udc);
+               free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
                gpio_free(udc->board.vbus_pin);
        }
        free_irq(udc->udp_irq, udc);
index a6dfd21641661c08df7a524850ee6ccf670a4f3e..170cbe89d9f8ad47b9bb6ee54596521012c8de7f 100644 (file)
@@ -927,7 +927,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
 
        dum->driver = NULL;
 
-       dummy_pullup(&dum->gadget, 0);
        return 0;
 }
 
index 1cbba70836bcd7c1516c21253b3a54dd24a5849a..f52cb1ae45d9a5ab27a46cb40b34cdb94e93a484 100644 (file)
@@ -712,7 +712,7 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
        if (code == FUNCTIONFS_INTERFACE_REVMAP) {
                struct ffs_function *func = ffs->func;
                ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
-       } else if (gadget->ops->ioctl) {
+       } else if (gadget && gadget->ops->ioctl) {
                ret = gadget->ops->ioctl(gadget, code, value);
        } else {
                ret = -ENOTTY;
@@ -1382,6 +1382,7 @@ static void functionfs_unbind(struct ffs_data *ffs)
                ffs->ep0req = NULL;
                ffs->gadget = NULL;
                ffs_data_put(ffs);
+               clear_bit(FFS_FL_BOUND, &ffs->flags);
        }
 }
 
index a371e966425fce2ccf391e13d2d523f02bee52c3..cb8c162cae5af059c5c8cce2c07679b9b3611177 100644 (file)
@@ -2189,7 +2189,7 @@ unknown_cmnd:
                common->data_size_from_cmnd = 0;
                sprintf(unknown, "Unknown x%02x", common->cmnd[0]);
                reply = check_command(common, common->cmnd_size,
-                                     DATA_DIR_UNKNOWN, 0xff, 0, unknown);
+                                     DATA_DIR_UNKNOWN, ~0, 0, unknown);
                if (reply == 0) {
                        common->curlun->sense_data = SS_INVALID_COMMAND;
                        reply = -EINVAL;
index 85a5cebe96b3635fb521d648f937c7e938e7a6c2..965a6293206acc5bb52facb12d8acf50d3c3c6a2 100644 (file)
@@ -345,7 +345,7 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
                }
 
                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
-                               skb->len <= 1, req->actual, req->actual);
+                               skb->len <= 1, req->actual, PAGE_SIZE);
                page = NULL;
 
                if (req->actual < req->length) { /* Last fragment */
index 7b1cf18df5e3e4cd0706422d3e16d17bc1aad075..52343654f5df5218929e86bf7bdac64bf2577b9e 100644 (file)
@@ -500,6 +500,7 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
                        if (buf) {
                                memcpy(req->buf, buf, n);
                                req->complete = rndis_response_complete;
+                               req->context = rndis;
                                rndis_free_response(rndis->config, buf);
                                value = n;
                        }
index 4fac569277411b45815aa1ff6d3ffe3d398d3623..a896d73f7a9336f5a34015c44ea5a6b04ce34f10 100644 (file)
@@ -2579,7 +2579,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
                fsg->data_size_from_cmnd = 0;
                sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
                if ((reply = check_command(fsg, fsg->cmnd_size,
-                               DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) {
+                               DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
                        fsg->curlun->sense_data = SS_INVALID_COMMAND;
                        reply = -EINVAL;
                }
index 5f94e79cd6b9b3f8856dad2d97d1e74677f62bad..55abfb6bd612dc96da58c67fb59def9e0cc14ea0 100644 (file)
@@ -730,7 +730,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
                : (1 << (ep_index(ep)));
 
        /* check if the pipe is empty */
-       if (!(list_empty(&ep->queue))) {
+       if (!(list_empty(&ep->queue)) && !(ep_index(ep) == 0)) {
                /* Add td to the end */
                struct fsl_req *lastreq;
                lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
@@ -918,10 +918,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                return -ENOMEM;
        }
 
-       /* Update ep0 state */
-       if ((ep_index(ep) == 0))
-               udc->ep0_state = DATA_STATE_XMIT;
-
        /* irq handler advances the queue */
        if (req != NULL)
                list_add_tail(&req->queue, &ep->queue);
@@ -1279,7 +1275,8 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
                udc->ep0_dir = USB_DIR_OUT;
 
        ep = &udc->eps[0];
-       udc->ep0_state = WAIT_FOR_OUT_STATUS;
+       if (udc->ep0_state != DATA_STATE_XMIT)
+               udc->ep0_state = WAIT_FOR_OUT_STATUS;
 
        req->ep = ep;
        req->req.length = 0;
@@ -1384,6 +1381,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
 
        list_add_tail(&req->queue, &ep->queue);
        udc->ep0_state = DATA_STATE_XMIT;
+       if (ep0_prime_status(udc, EP_DIR_OUT))
+               ep0stall(udc);
+
        return;
 stall:
        ep0stall(udc);
@@ -1492,6 +1492,14 @@ static void setup_received_irq(struct fsl_udc *udc,
                spin_lock(&udc->lock);
                udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
                                ?  DATA_STATE_XMIT : DATA_STATE_RECV;
+               /*
+                * If the data stage is IN, send status prime immediately.
+                * See 2.0 Spec chapter 8.5.3.3 for detail.
+                */
+               if (udc->ep0_state == DATA_STATE_XMIT)
+                       if (ep0_prime_status(udc, EP_DIR_OUT))
+                               ep0stall(udc);
+
        } else {
                /* No data phase, IN status from gadget */
                udc->ep0_dir = USB_DIR_IN;
@@ -1520,9 +1528,8 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0,
 
        switch (udc->ep0_state) {
        case DATA_STATE_XMIT:
-               /* receive status phase */
-               if (ep0_prime_status(udc, EP_DIR_OUT))
-                       ep0stall(udc);
+               /* already primed at setup_received_irq */
+               udc->ep0_state = WAIT_FOR_OUT_STATUS;
                break;
        case DATA_STATE_RECV:
                /* send status phase */
index 331cd6729d3cf4d1ac8bccf9b4ca5746d4d79821..a85eaf40b948592f4df5746cd1dca2a87141cf8d 100644 (file)
@@ -161,7 +161,7 @@ static struct usb_composite_driver gfs_driver = {
 static struct ffs_data *gfs_ffs_data;
 static unsigned long gfs_registered;
 
-static int  gfs_init(void)
+static int __init gfs_init(void)
 {
        ENTER();
 
@@ -169,7 +169,7 @@ static int  gfs_init(void)
 }
 module_init(gfs_init);
 
-static void  gfs_exit(void)
+static void __exit gfs_exit(void)
 {
        ENTER();
 
index 8793f32bab113524fcd5f184c0fed016be0e189f..e58b1644297172a8c1136fc78b2aea802df17f41 100644 (file)
@@ -1574,7 +1574,6 @@ static void destroy_ep_files (struct dev_data *dev)
        DBG (dev, "%s %d\n", __func__, dev->state);
 
        /* dev->state must prevent interference */
-restart:
        spin_lock_irq (&dev->lock);
        while (!list_empty(&dev->epfiles)) {
                struct ep_data  *ep;
index 69295ba9d99ae12f29738533fb15f5a7b4cce046..105b206cd8443dbe01bfd32b14555a51b22438b6 100644 (file)
@@ -340,7 +340,7 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
        /* currently we allocate TX FIFOs for all possible endpoints,
         * and assume that they are all the same size. */
 
-       for (ep = 0; ep <= 15; ep++) {
+       for (ep = 1; ep <= 15; ep++) {
                val = addr;
                val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT;
                addr += size;
@@ -741,7 +741,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
        /* write size / packets */
        writel(epsize, hsotg->regs + epsize_reg);
 
-       if (using_dma(hsotg)) {
+       if (using_dma(hsotg) && !continuing) {
                unsigned int dma_reg;
 
                /* write DMA address to control register, buffer already
@@ -1696,10 +1696,12 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
        reg |= mpsval;
        writel(reg, regs + S3C_DIEPCTL(ep));
 
-       reg = readl(regs + S3C_DOEPCTL(ep));
-       reg &= ~S3C_DxEPCTL_MPS_MASK;
-       reg |= mpsval;
-       writel(reg, regs + S3C_DOEPCTL(ep));
+       if (ep) {
+               reg = readl(regs + S3C_DOEPCTL(ep));
+               reg &= ~S3C_DxEPCTL_MPS_MASK;
+               reg |= mpsval;
+               writel(reg, regs + S3C_DOEPCTL(ep));
+       }
 
        return;
 
@@ -1919,7 +1921,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
                    ints & S3C_DIEPMSK_TxFIFOEmpty) {
                        dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
                                __func__, idx);
-                       s3c_hsotg_trytx(hsotg, hs_ep);
+                       if (!using_dma(hsotg))
+                               s3c_hsotg_trytx(hsotg, hs_ep);
                }
        }
 }
index 56da49f31d6c35a0f61611c1bb651b51e59732ab..e5e44f8cde9a3c99052e19e5e8c641ab3123a534 100644 (file)
@@ -263,9 +263,9 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 
        if (udc_is_newstyle(udc)) {
                udc->driver->disconnect(udc->gadget);
+               usb_gadget_disconnect(udc->gadget);
                udc->driver->unbind(udc->gadget);
                usb_gadget_udc_stop(udc->gadget, udc->driver);
-               usb_gadget_disconnect(udc->gadget);
        } else {
                usb_gadget_stop(udc->gadget, udc->driver);
        }
@@ -411,9 +411,13 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
        struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
 
        if (sysfs_streq(buf, "connect")) {
+               if (udc_is_newstyle(udc))
+                       usb_gadget_udc_start(udc->gadget, udc->driver);
                usb_gadget_connect(udc->gadget);
        } else if (sysfs_streq(buf, "disconnect")) {
                usb_gadget_disconnect(udc->gadget);
+               if (udc_is_newstyle(udc))
+                       usb_gadget_udc_stop(udc->gadget, udc->driver);
        } else {
                dev_err(dev, "unsupported command '%s'\n", buf);
                return -EINVAL;
index bc78c606c12bbe5726f077832c3dff1897918134..ca4e03a1c73a6d9ec030d133a15558d50362de4a 100644 (file)
@@ -28,7 +28,7 @@
 
 struct uvc_request_data
 {
-       unsigned int length;
+       __s32 length;
        __u8 data[60];
 };
 
index d776adb2da675c24f0d669d9a931f0a15abcf37f..0cdf89d32a15817d78ce0388a76f32909b29240c 100644 (file)
@@ -543,11 +543,11 @@ done:
        return ret;
 }
 
+/* called with queue->irqlock held.. */
 static struct uvc_buffer *
 uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
 {
        struct uvc_buffer *nextbuf;
-       unsigned long flags;
 
        if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
            buf->buf.length != buf->buf.bytesused) {
@@ -556,14 +556,12 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
                return buf;
        }
 
-       spin_lock_irqsave(&queue->irqlock, flags);
        list_del(&buf->queue);
        if (!list_empty(&queue->irqqueue))
                nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
                                           queue);
        else
                nextbuf = NULL;
-       spin_unlock_irqrestore(&queue->irqlock, flags);
 
        buf->buf.sequence = queue->sequence++;
        do_gettimeofday(&buf->buf.timestamp);
index f6e083b5019137db248fc67731f24eb6e683b1ac..54d7ca559cb215f5fc963d10cdd0b99d6367c777 100644 (file)
@@ -39,7 +39,7 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
        if (data->length < 0)
                return usb_ep_set_halt(cdev->gadget->ep0);
 
-       req->length = min(uvc->event_length, data->length);
+       req->length = min_t(unsigned int, uvc->event_length, data->length);
        req->zero = data->length < uvc->event_length;
        req->dma = DMA_ADDR_INVALID;
 
index 19f318ababa286810fe44f6a5efb0fc27c2690c1..cf14c95a670040dce6f49159ec707c8df100df02 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 
 /* interface and function clocks */
index fd9109d7eb0ed9491d5212caba8d3f6af20c2452..680e1a31fb87c2ae9538e8667c8dab0861a6410f 100644 (file)
@@ -352,7 +352,6 @@ static int debug_async_open(struct inode *, struct file *);
 static int debug_periodic_open(struct inode *, struct file *);
 static int debug_registers_open(struct inode *, struct file *);
 static int debug_async_open(struct inode *, struct file *);
-static int debug_lpm_open(struct inode *, struct file *);
 static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
                                   size_t count, loff_t *ppos);
 static ssize_t debug_lpm_write(struct file *file, const char __user *buffer,
@@ -385,7 +384,7 @@ static const struct file_operations debug_registers_fops = {
 };
 static const struct file_operations debug_lpm_fops = {
        .owner          = THIS_MODULE,
-       .open           = debug_lpm_open,
+       .open           = simple_open,
        .read           = debug_lpm_read,
        .write          = debug_lpm_write,
        .release        = debug_lpm_close,
@@ -970,12 +969,6 @@ static int debug_registers_open(struct inode *inode, struct file *file)
        return file->private_data ? 0 : -ENOMEM;
 }
 
-static int debug_lpm_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static int debug_lpm_close(struct inode *inode, struct file *file)
 {
        return 0;
index 3e7345172e03a86b56b31f48f66dfc601955b899..d0a84bd3f3ebe5bca473e2c6c99711bf02069c3f 100644 (file)
@@ -218,6 +218,9 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
        u32 portsc;
        struct usb_hcd *hcd = ehci_to_hcd(ehci);
        void __iomem *non_ehci = hcd->regs;
+       struct fsl_usb2_platform_data *pdata;
+
+       pdata = hcd->self.controller->platform_data;
 
        portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
        portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
@@ -234,7 +237,9 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
                /* fall through */
        case FSL_USB2_PHY_UTMI:
                /* enable UTMI PHY */
-               setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
+               if (pdata->have_sysif_regs)
+                       setbits32(non_ehci + FSL_SOC_USB_CTRL,
+                                 CTRL_UTMI_PHY_EN);
                portsc |= PORT_PTS_UTMI;
                break;
        case FSL_USB2_PHY_NONE:
index 057cdda7a48978999ebf5ac4cbb8ecee7acc60e0..4a3bc5b7a06f82d395c9a6dae0a025ba9660cf02 100644 (file)
@@ -347,6 +347,8 @@ static int ehci_reset (struct ehci_hcd *ehci)
        if (ehci->debug)
                dbgp_external_startup();
 
+       ehci->port_c_suspend = ehci->suspended_ports =
+                       ehci->resuming_ports = 0;
        return retval;
 }
 
@@ -856,8 +858,13 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                goto dead;
        }
 
+       /*
+        * We don't use STS_FLR, but some controllers don't like it to
+        * remain on, so mask it out along with the other status bits.
+        */
+       masked_status = status & (INTR_MASK | STS_FLR);
+
        /* Shared IRQ? */
-       masked_status = status & INTR_MASK;
        if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
                spin_unlock(&ehci->lock);
                return IRQ_NONE;
@@ -908,7 +915,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                pcd_status = status;
 
                /* resume root hub? */
-               if (!(cmd & CMD_RUN))
+               if (ehci->rh_state == EHCI_RH_SUSPENDED)
                        usb_hcd_resume_root_hub(hcd);
 
                /* get per-port change detect bits */
@@ -939,6 +946,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                         * like usb_port_resume() does.
                         */
                        ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
+                       set_bit(i, &ehci->resuming_ports);
                        ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
                        mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
                }
index 256fbd42e48c19b02c808fccda6025b93a3392c5..38fe076231522875bec58c60ec74fc7b14932960 100644 (file)
@@ -223,15 +223,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
         * remote wakeup, we must fail the suspend.
         */
        if (hcd->self.root_hub->do_remote_wakeup) {
-               port = HCS_N_PORTS(ehci->hcs_params);
-               while (port--) {
-                       if (ehci->reset_done[port] != 0) {
-                               spin_unlock_irq(&ehci->lock);
-                               ehci_dbg(ehci, "suspend failed because "
-                                               "port %d is resuming\n",
-                                               port + 1);
-                               return -EBUSY;
-                       }
+               if (ehci->resuming_ports) {
+                       spin_unlock_irq(&ehci->lock);
+                       ehci_dbg(ehci, "suspend failed because a port is resuming\n");
+                       return -EBUSY;
                }
        }
 
@@ -554,16 +549,12 @@ static int
 ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
        struct ehci_hcd *ehci = hcd_to_ehci (hcd);
-       u32             temp, status = 0;
+       u32             temp, status;
        u32             mask;
        int             ports, i, retval = 1;
        unsigned long   flags;
        u32             ppcd = 0;
 
-       /* if !USB_SUSPEND, root hub timers won't get shut down ... */
-       if (ehci->rh_state != EHCI_RH_RUNNING)
-               return 0;
-
        /* init status to no-changes */
        buf [0] = 0;
        ports = HCS_N_PORTS (ehci->hcs_params);
@@ -572,6 +563,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
                retval++;
        }
 
+       /* Inform the core about resumes-in-progress by returning
+        * a non-zero value even if there are no status changes.
+        */
+       status = ehci->resuming_ports;
+
        /* Some boards (mostly VIA?) report bogus overcurrent indications,
         * causing massive log spam unless we completely ignore them.  It
         * may be relevant that VIA VT8235 controllers, where PORT_POWER is
@@ -846,6 +842,7 @@ static int ehci_hub_control (
                                ehci_writel(ehci,
                                        temp & ~(PORT_RWC_BITS | PORT_RESUME),
                                        status_reg);
+                               clear_bit(wIndex, &ehci->resuming_ports);
                                retval = handshake(ehci, status_reg,
                                           PORT_RESUME, 0, 2000 /* 2msec */);
                                if (retval != 0) {
@@ -864,6 +861,7 @@ static int ehci_hub_control (
                                        ehci->reset_done[wIndex])) {
                        status |= USB_PORT_STAT_C_RESET << 16;
                        ehci->reset_done [wIndex] = 0;
+                       clear_bit(wIndex, &ehci->resuming_ports);
 
                        /* force reset to complete */
                        ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
@@ -884,8 +882,10 @@ static int ehci_hub_control (
                                        ehci_readl(ehci, status_reg));
                }
 
-               if (!(temp & (PORT_RESUME|PORT_RESET)))
+               if (!(temp & (PORT_RESUME|PORT_RESET))) {
                        ehci->reset_done[wIndex] = 0;
+                       clear_bit(wIndex, &ehci->resuming_ports);
+               }
 
                /* transfer dedicated ports to the companion hc */
                if ((temp & PORT_CONNECT) &&
@@ -920,6 +920,7 @@ static int ehci_hub_control (
                        status |= USB_PORT_STAT_SUSPEND;
                } else if (test_bit(wIndex, &ehci->suspended_ports)) {
                        clear_bit(wIndex, &ehci->suspended_ports);
+                       clear_bit(wIndex, &ehci->resuming_ports);
                        ehci->reset_done[wIndex] = 0;
                        if (temp & PORT_PE)
                                set_bit(wIndex, &ehci->port_c_suspend);
index bba9850f32f09f78c668a04d2d024d99d3320857..5c78f9e71466ef7a81df23535ead8927dd73af24 100644 (file)
@@ -42,6 +42,7 @@
 #include <plat/usb.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
+#include <linux/gpio.h>
 
 /* EHCI Register Set */
 #define EHCI_INSNREG04                                 (0xA0)
@@ -191,6 +192,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
                }
        }
 
+       if (pdata->phy_reset) {
+               if (gpio_is_valid(pdata->reset_gpio_port[0]))
+                       gpio_request_one(pdata->reset_gpio_port[0],
+                                        GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
+
+               if (gpio_is_valid(pdata->reset_gpio_port[1]))
+                       gpio_request_one(pdata->reset_gpio_port[1],
+                                        GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
+
+               /* Hold the PHY in RESET for enough time till DIR is high */
+               udelay(10);
+       }
+
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
 
@@ -237,6 +251,19 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        /* root ports should always stay powered */
        ehci_port_power(omap_ehci, 1);
 
+       if (pdata->phy_reset) {
+               /* Hold the PHY in RESET for enough time till
+                * PHY is settled and ready
+                */
+               udelay(10);
+
+               if (gpio_is_valid(pdata->reset_gpio_port[0]))
+                       gpio_set_value(pdata->reset_gpio_port[0], 1);
+
+               if (gpio_is_valid(pdata->reset_gpio_port[1]))
+                       gpio_set_value(pdata->reset_gpio_port[1], 1);
+       }
+
        return 0;
 
 err_add_hcd:
@@ -259,8 +286,9 @@ err_io:
  */
 static int ehci_hcd_omap_remove(struct platform_device *pdev)
 {
-       struct device *dev      = &pdev->dev;
-       struct usb_hcd *hcd     = dev_get_drvdata(dev);
+       struct device *dev                              = &pdev->dev;
+       struct usb_hcd *hcd                             = dev_get_drvdata(dev);
+       struct ehci_hcd_omap_platform_data *pdata       = dev->platform_data;
 
        usb_remove_hcd(hcd);
        disable_put_regulator(dev->platform_data);
@@ -269,6 +297,13 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
        pm_runtime_put_sync(dev);
        pm_runtime_disable(dev);
 
+       if (pdata->phy_reset) {
+               if (gpio_is_valid(pdata->reset_gpio_port[0]))
+                       gpio_free(pdata->reset_gpio_port[0]);
+
+               if (gpio_is_valid(pdata->reset_gpio_port[1]))
+                       gpio_free(pdata->reset_gpio_port[1]);
+       }
        return 0;
 }
 
index 01bb7241d6efd53f3769d47e86d59a28c5cf9ce2..fe8dc069164ead9f271b3e487d2704e0e74aeaed 100644 (file)
@@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                        hcd->has_tt = 1;
                        tdi_reset(ehci);
                }
+               if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) {
+                       /* EHCI #1 or #2 on 6 Series/C200 Series chipset */
+                       if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) {
+                               ehci_info(ehci, "broken D3 during system sleep on ASUS\n");
+                               hcd->broken_pci_sleep = 1;
+                               device_set_wakeup_capable(&pdev->dev, false);
+                       }
+               }
                break;
        case PCI_VENDOR_ID_TDI:
                if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
index 3de48a2d79550df7b9af8efe0132ff73e2535fdd..f214a80cdee212ec816601ef51645b05fd3f6d68 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
 
 #include <mach/usb_phy.h>
 #include <mach/iomap.h>
@@ -37,9 +38,7 @@ struct tegra_ehci_hcd {
        struct clk *emc_clk;
        struct usb_phy *transceiver;
        int host_resumed;
-       int bus_suspended;
        int port_resuming;
-       int power_down_on_bus_suspend;
        enum tegra_usb_phy_port_speed port_speed;
 };
 
@@ -224,6 +223,7 @@ static int tegra_ehci_hub_control(
                temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
                /* start resume signalling */
                ehci_writel(ehci, temp | PORT_RESUME, status_reg);
+               set_bit(wIndex-1, &ehci->resuming_ports);
 
                spin_unlock_irqrestore(&ehci->lock, flags);
                msleep(20);
@@ -236,6 +236,7 @@ static int tegra_ehci_hub_control(
                        pr_err("%s: timeout waiting for SUSPEND\n", __func__);
 
                ehci->reset_done[wIndex-1] = 0;
+               clear_bit(wIndex-1, &ehci->resuming_ports);
 
                tegra->port_resuming = 1;
                goto done;
@@ -271,120 +272,6 @@ static void tegra_ehci_restart(struct usb_hcd *hcd)
        up_write(&ehci_cf_port_reset_rwsem);
 }
 
-static int tegra_usb_suspend(struct usb_hcd *hcd)
-{
-       struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
-       struct ehci_regs __iomem *hw = tegra->ehci->regs;
-       unsigned long flags;
-
-       spin_lock_irqsave(&tegra->ehci->lock, flags);
-
-       tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
-       ehci_halt(tegra->ehci);
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       spin_unlock_irqrestore(&tegra->ehci->lock, flags);
-
-       tegra_ehci_power_down(hcd);
-       return 0;
-}
-
-static int tegra_usb_resume(struct usb_hcd *hcd)
-{
-       struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-       struct ehci_regs __iomem *hw = ehci->regs;
-       unsigned long val;
-
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       tegra_ehci_power_up(hcd);
-
-       if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
-               /* Wait for the phy to detect new devices
-                * before we restart the controller */
-               msleep(10);
-               goto restart;
-       }
-
-       /* Force the phy to keep data lines in suspend state */
-       tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
-
-       /* Enable host mode */
-       tdi_reset(ehci);
-
-       /* Enable Port Power */
-       val = readl(&hw->port_status[0]);
-       val |= PORT_POWER;
-       writel(val, &hw->port_status[0]);
-       udelay(10);
-
-       /* Check if the phy resume from LP0. When the phy resume from LP0
-        * USB register will be reset. */
-       if (!readl(&hw->async_next)) {
-               /* Program the field PTC based on the saved speed mode */
-               val = readl(&hw->port_status[0]);
-               val &= ~PORT_TEST(~0);
-               if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
-                       val |= PORT_TEST_FORCE;
-               else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
-                       val |= PORT_TEST(6);
-               else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
-                       val |= PORT_TEST(7);
-               writel(val, &hw->port_status[0]);
-               udelay(10);
-
-               /* Disable test mode by setting PTC field to NORMAL_OP */
-               val = readl(&hw->port_status[0]);
-               val &= ~PORT_TEST(~0);
-               writel(val, &hw->port_status[0]);
-               udelay(10);
-       }
-
-       /* Poll until CCS is enabled */
-       if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
-                                                PORT_CONNECT, 2000)) {
-               pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
-               goto restart;
-       }
-
-       /* Poll until PE is enabled */
-       if (handshake(ehci, &hw->port_status[0], PORT_PE,
-                                                PORT_PE, 2000)) {
-               pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
-               goto restart;
-       }
-
-       /* Clear the PCI status, to avoid an interrupt taken upon resume */
-       val = readl(&hw->status);
-       val |= STS_PCD;
-       writel(val, &hw->status);
-
-       /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
-       val = readl(&hw->port_status[0]);
-       if ((val & PORT_POWER) && (val & PORT_PE)) {
-               val |= PORT_SUSPEND;
-               writel(val, &hw->port_status[0]);
-
-               /* Wait until port suspend completes */
-               if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
-                                                        PORT_SUSPEND, 1000)) {
-                       pr_err("%s: timeout waiting for PORT_SUSPEND\n",
-                                                               __func__);
-                       goto restart;
-               }
-       }
-
-       tegra_ehci_phy_restore_end(tegra->phy);
-       return 0;
-
-restart:
-       if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
-               tegra_ehci_phy_restore_end(tegra->phy);
-
-       tegra_ehci_restart(hcd);
-       return 0;
-}
-
 static void tegra_ehci_shutdown(struct usb_hcd *hcd)
 {
        struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
@@ -432,36 +319,6 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
        return retval;
 }
 
-#ifdef CONFIG_PM
-static int tegra_ehci_bus_suspend(struct usb_hcd *hcd)
-{
-       struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
-       int error_status = 0;
-
-       error_status = ehci_bus_suspend(hcd);
-       if (!error_status && tegra->power_down_on_bus_suspend) {
-               tegra_usb_suspend(hcd);
-               tegra->bus_suspended = 1;
-       }
-
-       return error_status;
-}
-
-static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
-{
-       struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
-
-       if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) {
-               tegra_usb_resume(hcd);
-               tegra->bus_suspended = 0;
-       }
-
-       tegra_usb_phy_preresume(tegra->phy);
-       tegra->port_resuming = 1;
-       return ehci_bus_resume(hcd);
-}
-#endif
-
 struct temp_buffer {
        void *kmalloc_ptr;
        void *old_xfer_buffer;
@@ -572,8 +429,8 @@ static const struct hc_driver tegra_ehci_hc_driver = {
        .hub_control            = tegra_ehci_hub_control,
        .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 #ifdef CONFIG_PM
-       .bus_suspend            = tegra_ehci_bus_suspend,
-       .bus_resume             = tegra_ehci_bus_resume,
+       .bus_suspend            = ehci_bus_suspend,
+       .bus_resume             = ehci_bus_resume,
 #endif
        .relinquish_port        = ehci_relinquish_port,
        .port_handed_over       = ehci_port_handed_over,
@@ -601,11 +458,187 @@ static int setup_vbus_gpio(struct platform_device *pdev)
                dev_err(&pdev->dev, "can't enable vbus\n");
                return err;
        }
-       gpio_set_value(gpio, 1);
 
        return err;
 }
 
+#ifdef CONFIG_PM
+
+static int controller_suspend(struct device *dev)
+{
+       struct tegra_ehci_hcd *tegra =
+                       platform_get_drvdata(to_platform_device(dev));
+       struct ehci_hcd *ehci = tegra->ehci;
+       struct usb_hcd *hcd = ehci_to_hcd(ehci);
+       struct ehci_regs __iomem *hw = ehci->regs;
+       unsigned long flags;
+
+       if (time_before(jiffies, ehci->next_statechange))
+               msleep(10);
+
+       spin_lock_irqsave(&ehci->lock, flags);
+
+       tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
+       ehci_halt(ehci);
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+       spin_unlock_irqrestore(&ehci->lock, flags);
+
+       tegra_ehci_power_down(hcd);
+       return 0;
+}
+
+static int controller_resume(struct device *dev)
+{
+       struct tegra_ehci_hcd *tegra =
+                       platform_get_drvdata(to_platform_device(dev));
+       struct ehci_hcd *ehci = tegra->ehci;
+       struct usb_hcd *hcd = ehci_to_hcd(ehci);
+       struct ehci_regs __iomem *hw = ehci->regs;
+       unsigned long val;
+
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       tegra_ehci_power_up(hcd);
+
+       if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
+               /* Wait for the phy to detect new devices
+                * before we restart the controller */
+               msleep(10);
+               goto restart;
+       }
+
+       /* Force the phy to keep data lines in suspend state */
+       tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
+
+       /* Enable host mode */
+       tdi_reset(ehci);
+
+       /* Enable Port Power */
+       val = readl(&hw->port_status[0]);
+       val |= PORT_POWER;
+       writel(val, &hw->port_status[0]);
+       udelay(10);
+
+       /* Check if the phy resume from LP0. When the phy resume from LP0
+        * USB register will be reset. */
+       if (!readl(&hw->async_next)) {
+               /* Program the field PTC based on the saved speed mode */
+               val = readl(&hw->port_status[0]);
+               val &= ~PORT_TEST(~0);
+               if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
+                       val |= PORT_TEST_FORCE;
+               else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
+                       val |= PORT_TEST(6);
+               else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
+                       val |= PORT_TEST(7);
+               writel(val, &hw->port_status[0]);
+               udelay(10);
+
+               /* Disable test mode by setting PTC field to NORMAL_OP */
+               val = readl(&hw->port_status[0]);
+               val &= ~PORT_TEST(~0);
+               writel(val, &hw->port_status[0]);
+               udelay(10);
+       }
+
+       /* Poll until CCS is enabled */
+       if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
+                                                PORT_CONNECT, 2000)) {
+               pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
+               goto restart;
+       }
+
+       /* Poll until PE is enabled */
+       if (handshake(ehci, &hw->port_status[0], PORT_PE,
+                                                PORT_PE, 2000)) {
+               pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
+               goto restart;
+       }
+
+       /* Clear the PCI status, to avoid an interrupt taken upon resume */
+       val = readl(&hw->status);
+       val |= STS_PCD;
+       writel(val, &hw->status);
+
+       /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
+       val = readl(&hw->port_status[0]);
+       if ((val & PORT_POWER) && (val & PORT_PE)) {
+               val |= PORT_SUSPEND;
+               writel(val, &hw->port_status[0]);
+
+               /* Wait until port suspend completes */
+               if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
+                                                        PORT_SUSPEND, 1000)) {
+                       pr_err("%s: timeout waiting for PORT_SUSPEND\n",
+                                                               __func__);
+                       goto restart;
+               }
+       }
+
+       tegra_ehci_phy_restore_end(tegra->phy);
+       goto done;
+
+ restart:
+       if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
+               tegra_ehci_phy_restore_end(tegra->phy);
+
+       tegra_ehci_restart(hcd);
+
+ done:
+       tegra_usb_phy_preresume(tegra->phy);
+       tegra->port_resuming = 1;
+       return 0;
+}
+
+static int tegra_ehci_suspend(struct device *dev)
+{
+       struct tegra_ehci_hcd *tegra =
+                       platform_get_drvdata(to_platform_device(dev));
+       struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+       int rc = 0;
+
+       /*
+        * When system sleep is supported and USB controller wakeup is
+        * implemented: If the controller is runtime-suspended and the
+        * wakeup setting needs to be changed, call pm_runtime_resume().
+        */
+       if (HCD_HW_ACCESSIBLE(hcd))
+               rc = controller_suspend(dev);
+       return rc;
+}
+
+static int tegra_ehci_resume(struct device *dev)
+{
+       int rc;
+
+       rc = controller_resume(dev);
+       if (rc == 0) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
+       }
+       return rc;
+}
+
+static int tegra_ehci_runtime_suspend(struct device *dev)
+{
+       return controller_suspend(dev);
+}
+
+static int tegra_ehci_runtime_resume(struct device *dev)
+{
+       return controller_resume(dev);
+}
+
+static const struct dev_pm_ops tegra_ehci_pm_ops = {
+       .suspend        = tegra_ehci_suspend,
+       .resume         = tegra_ehci_resume,
+       .runtime_suspend = tegra_ehci_runtime_suspend,
+       .runtime_resume = tegra_ehci_runtime_resume,
+};
+
+#endif
+
 static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
 
 static int tegra_ehci_probe(struct platform_device *pdev)
@@ -720,7 +753,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)
        }
 
        tegra->host_resumed = 1;
-       tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend;
        tegra->ehci = hcd_to_ehci(hcd);
 
        irq = platform_get_irq(pdev, 0);
@@ -729,7 +761,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)
                err = -ENODEV;
                goto fail;
        }
-       set_irq_flags(irq, IRQF_VALID);
 
 #ifdef CONFIG_USB_OTG_UTILS
        if (pdata->operating_mode == TEGRA_USB_OTG) {
@@ -745,6 +776,14 @@ static int tegra_ehci_probe(struct platform_device *pdev)
                goto fail;
        }
 
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_get_noresume(&pdev->dev);
+
+       /* Don't skip the pm_runtime_forbid call if wakeup isn't working */
+       /* if (!pdata->power_down_on_bus_suspend) */
+               pm_runtime_forbid(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_put_sync(&pdev->dev);
        return err;
 
 fail:
@@ -771,33 +810,6 @@ fail_hcd:
        return err;
 }
 
-#ifdef CONFIG_PM
-static int tegra_ehci_resume(struct platform_device *pdev)
-{
-       struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
-
-       if (tegra->bus_suspended)
-               return 0;
-
-       return tegra_usb_resume(hcd);
-}
-
-static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
-
-       if (tegra->bus_suspended)
-               return 0;
-
-       if (time_before(jiffies, tegra->ehci->next_statechange))
-               msleep(10);
-
-       return tegra_usb_suspend(hcd);
-}
-#endif
-
 static int tegra_ehci_remove(struct platform_device *pdev)
 {
        struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
@@ -806,6 +818,10 @@ static int tegra_ehci_remove(struct platform_device *pdev)
        if (tegra == NULL || hcd == NULL)
                return -EINVAL;
 
+       pm_runtime_get_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_put_noidle(&pdev->dev);
+
 #ifdef CONFIG_USB_OTG_UTILS
        if (tegra->transceiver) {
                otg_set_host(tegra->transceiver->otg, NULL);
@@ -846,13 +862,12 @@ static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
 static struct platform_driver tegra_ehci_driver = {
        .probe          = tegra_ehci_probe,
        .remove         = tegra_ehci_remove,
-#ifdef CONFIG_PM
-       .suspend        = tegra_ehci_suspend,
-       .resume         = tegra_ehci_resume,
-#endif
        .shutdown       = tegra_ehci_hcd_shutdown,
        .driver         = {
                .name   = "tegra-ehci",
                .of_match_table = tegra_ehci_of_match,
+#ifdef CONFIG_PM
+               .pm     = &tegra_ehci_pm_ops,
+#endif
        }
 };
index 8f9acbc96fde03bf320ed1a696f0fb7b164a45e3..2694ed6558d2d954c03a4ba3b77eabdc64f9c7f6 100644 (file)
@@ -117,6 +117,8 @@ struct ehci_hcd {                   /* one per controller */
                        the change-suspend feature turned on */
        unsigned long           suspended_ports;        /* which ports are
                        suspended */
+       unsigned long           resuming_ports;         /* which ports have
+                       started to resume */
 
        /* per-HC memory pools (could be per-bus, but ...) */
        struct dma_pool         *qh_pool;       /* qh per active urb */
index db8963f5fbcec11988390b32e02a693c787e2727..13ebeca8e73e3e5f78f52b6001ebc3464f40a432 100644 (file)
 #error "CONFIG_ARCH_AT91 must be defined."
 #endif
 
+#define valid_port(index)      ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS)
+#define at91_for_each_port(index)      \
+               for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++)
+
 /* interface and function clocks; sometimes also an AHB clock */
 static struct clk *iclk, *fclk, *hclk;
 static int clocked;
@@ -90,7 +94,7 @@ static void at91_stop_hc(struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
+static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
 
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
@@ -104,7 +108,7 @@ static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
  */
-static int usb_hcd_at91_probe(const struct hc_driver *driver,
+static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
                        struct platform_device *pdev)
 {
        int retval;
@@ -199,7 +203,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
  * context, "rmmod" or something similar.
  *
  */
-static void usb_hcd_at91_remove(struct usb_hcd *hcd,
+static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
                                struct platform_device *pdev)
 {
        usb_remove_hcd(hcd);
@@ -240,26 +244,26 @@ ohci_at91_start (struct usb_hcd *hcd)
 
 static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable)
 {
-       if (port < 0 || port >= 2)
+       if (!valid_port(port))
                return;
 
        if (!gpio_is_valid(pdata->vbus_pin[port]))
                return;
 
        gpio_set_value(pdata->vbus_pin[port],
-                      !pdata->vbus_pin_active_low[port] ^ enable);
+                      pdata->vbus_pin_active_low[port] ^ enable);
 }
 
 static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
 {
-       if (port < 0 || port >= 2)
+       if (!valid_port(port))
                return -EINVAL;
 
        if (!gpio_is_valid(pdata->vbus_pin[port]))
                return -EINVAL;
 
        return gpio_get_value(pdata->vbus_pin[port]) ^
-               !pdata->vbus_pin_active_low[port];
+               pdata->vbus_pin_active_low[port];
 }
 
 /*
@@ -271,9 +275,9 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
        int length = ohci_hub_status_data(hcd, buf);
        int port;
 
-       for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
+       at91_for_each_port(port) {
                if (pdata->overcurrent_changed[port]) {
-                       if (! length)
+                       if (!length)
                                length = 1;
                        buf[0] |= 1 << (port + 1);
                }
@@ -297,11 +301,17 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                "ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
                hcd, typeReq, wValue, wIndex, buf, wLength);
 
+       wIndex--;
+
        switch (typeReq) {
        case SetPortFeature:
                if (wValue == USB_PORT_FEAT_POWER) {
                        dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n");
-                       ohci_at91_usb_set_power(pdata, wIndex - 1, 1);
+                       if (valid_port(wIndex)) {
+                               ohci_at91_usb_set_power(pdata, wIndex, 1);
+                               ret = 0;
+                       }
+
                        goto out;
                }
                break;
@@ -312,9 +322,9 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        dev_dbg(hcd->self.controller,
                                "ClearPortFeature: C_OVER_CURRENT\n");
 
-                       if (wIndex == 1 || wIndex == 2) {
-                               pdata->overcurrent_changed[wIndex-1] = 0;
-                               pdata->overcurrent_status[wIndex-1] = 0;
+                       if (valid_port(wIndex)) {
+                               pdata->overcurrent_changed[wIndex] = 0;
+                               pdata->overcurrent_status[wIndex] = 0;
                        }
 
                        goto out;
@@ -323,9 +333,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        dev_dbg(hcd->self.controller,
                                "ClearPortFeature: OVER_CURRENT\n");
 
-                       if (wIndex == 1 || wIndex == 2) {
-                               pdata->overcurrent_status[wIndex-1] = 0;
-                       }
+                       if (valid_port(wIndex))
+                               pdata->overcurrent_status[wIndex] = 0;
 
                        goto out;
 
@@ -333,15 +342,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        dev_dbg(hcd->self.controller,
                                "ClearPortFeature: POWER\n");
 
-                       if (wIndex == 1 || wIndex == 2) {
-                               ohci_at91_usb_set_power(pdata, wIndex - 1, 0);
+                       if (valid_port(wIndex)) {
+                               ohci_at91_usb_set_power(pdata, wIndex, 0);
                                return 0;
                        }
                }
                break;
        }
 
-       ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+       ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength);
        if (ret)
                goto out;
 
@@ -377,18 +386,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 
                dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
 
-               if (wIndex == 1 || wIndex == 2) {
-                       if (! ohci_at91_usb_get_power(pdata, wIndex-1)) {
+               if (valid_port(wIndex)) {
+                       if (!ohci_at91_usb_get_power(pdata, wIndex))
                                *data &= ~cpu_to_le32(RH_PS_PPS);
-                       }
 
-                       if (pdata->overcurrent_changed[wIndex-1]) {
+                       if (pdata->overcurrent_changed[wIndex])
                                *data |= cpu_to_le32(RH_PS_OCIC);
-                       }
 
-                       if (pdata->overcurrent_status[wIndex-1]) {
+                       if (pdata->overcurrent_status[wIndex])
                                *data |= cpu_to_le32(RH_PS_POCI);
-                       }
                }
        }
 
@@ -450,14 +456,14 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
 
        /* From the GPIO notifying the over-current situation, find
         * out the corresponding port */
-       for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
+       at91_for_each_port(port) {
                if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
                        gpio = pdata->overcurrent_pin[port];
                        break;
                }
        }
 
-       if (port == ARRAY_SIZE(pdata->overcurrent_pin)) {
+       if (port == AT91_MAX_USBH_PORTS) {
                dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n");
                return IRQ_HANDLED;
        }
@@ -467,7 +473,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
        /* When notified of an over-current situation, disable power
           on the corresponding port, and mark this port in
           over-current. */
-       if (! val) {
+       if (!val) {
                ohci_at91_usb_set_power(pdata, port, 0);
                pdata->overcurrent_status[port]  = 1;
                pdata->overcurrent_changed[port] = 1;
@@ -492,7 +498,7 @@ static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
 static int __devinit ohci_at91_of_init(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
-       int i, ret, gpio;
+       int i, gpio;
        enum of_gpio_flags flags;
        struct at91_usbh_data   *pdata;
        u32 ports;
@@ -514,48 +520,17 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
        if (!of_property_read_u32(np, "num-ports", &ports))
                pdata->ports = ports;
 
-       for (i = 0; i < 2; i++) {
+       at91_for_each_port(i) {
                gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
                pdata->vbus_pin[i] = gpio;
                if (!gpio_is_valid(gpio))
                        continue;
                pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
-               ret = gpio_request(gpio, "ohci_vbus");
-               if (ret) {
-                       dev_warn(&pdev->dev, "can't request vbus gpio %d", gpio);
-                       continue;
-               }
-               ret = gpio_direction_output(gpio, !(flags & OF_GPIO_ACTIVE_LOW) ^ 1);
-               if (ret)
-                       dev_warn(&pdev->dev, "can't put vbus gpio %d as output %d",
-                                !(flags & OF_GPIO_ACTIVE_LOW) ^ 1, gpio);
        }
 
-       for (i = 0; i < 2; i++) {
-               gpio = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
-               pdata->overcurrent_pin[i] = gpio;
-               if (!gpio_is_valid(gpio))
-                       continue;
-               ret = gpio_request(gpio, "ohci_overcurrent");
-               if (ret) {
-                       dev_err(&pdev->dev, "can't request overcurrent gpio %d", gpio);
-                       continue;
-               }
-
-               ret = gpio_direction_input(gpio);
-               if (ret) {
-                       dev_err(&pdev->dev, "can't configure overcurrent gpio %d as input", gpio);
-                       continue;
-               }
-
-               ret = request_irq(gpio_to_irq(gpio),
-                                 ohci_hcd_at91_overcurrent_irq,
-                                 IRQF_SHARED, "ohci_overcurrent", pdev);
-               if (ret) {
-                       gpio_free(gpio);
-                       dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n");
-               }
-       }
+       at91_for_each_port(i)
+               pdata->overcurrent_pin[i] =
+                       of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
 
        pdev->dev.platform_data = pdata;
 
@@ -570,39 +545,73 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
+static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 {
        struct at91_usbh_data   *pdata;
        int                     i;
+       int                     gpio;
+       int                     ret;
 
-       i = ohci_at91_of_init(pdev);
-
-       if (i)
-               return i;
+       ret = ohci_at91_of_init(pdev);
+       if (ret)
+               return ret;
 
        pdata = pdev->dev.platform_data;
 
        if (pdata) {
-               for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
+               at91_for_each_port(i) {
                        if (!gpio_is_valid(pdata->vbus_pin[i]))
                                continue;
-                       gpio_request(pdata->vbus_pin[i], "ohci_vbus");
+                       gpio = pdata->vbus_pin[i];
+
+                       ret = gpio_request(gpio, "ohci_vbus");
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "can't request vbus gpio %d\n", gpio);
+                               continue;
+                       }
+                       ret = gpio_direction_output(gpio,
+                                               !pdata->vbus_pin_active_low[i]);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "can't put vbus gpio %d as output %d\n",
+                                       gpio, !pdata->vbus_pin_active_low[i]);
+                               gpio_free(gpio);
+                               continue;
+                       }
+
                        ohci_at91_usb_set_power(pdata, i, 1);
                }
 
-               for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
-                       int ret;
-
+               at91_for_each_port(i) {
                        if (!gpio_is_valid(pdata->overcurrent_pin[i]))
                                continue;
-                       gpio_request(pdata->overcurrent_pin[i], "ohci_overcurrent");
+                       gpio = pdata->overcurrent_pin[i];
+
+                       ret = gpio_request(gpio, "ohci_overcurrent");
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "can't request overcurrent gpio %d\n",
+                                       gpio);
+                               continue;
+                       }
+
+                       ret = gpio_direction_input(gpio);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "can't configure overcurrent gpio %d as input\n",
+                                       gpio);
+                               gpio_free(gpio);
+                               continue;
+                       }
 
-                       ret = request_irq(gpio_to_irq(pdata->overcurrent_pin[i]),
+                       ret = request_irq(gpio_to_irq(gpio),
                                          ohci_hcd_at91_overcurrent_irq,
                                          IRQF_SHARED, "ohci_overcurrent", pdev);
                        if (ret) {
-                               gpio_free(pdata->overcurrent_pin[i]);
-                               dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n");
+                               gpio_free(gpio);
+                               dev_err(&pdev->dev,
+                                       "can't get gpio IRQ for overcurrent\n");
                        }
                }
        }
@@ -611,20 +620,20 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
        return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 }
 
-static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
+static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 {
        struct at91_usbh_data   *pdata = pdev->dev.platform_data;
        int                     i;
 
        if (pdata) {
-               for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
+               at91_for_each_port(i) {
                        if (!gpio_is_valid(pdata->vbus_pin[i]))
                                continue;
                        ohci_at91_usb_set_power(pdata, i, 0);
                        gpio_free(pdata->vbus_pin[i]);
                }
 
-               for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
+               at91_for_each_port(i) {
                        if (!gpio_is_valid(pdata->overcurrent_pin[i]))
                                continue;
                        free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev);
@@ -687,7 +696,7 @@ MODULE_ALIAS("platform:at91_ohci");
 
 static struct platform_driver ohci_hcd_at91_driver = {
        .probe          = ohci_hcd_at91_drv_probe,
-       .remove         = ohci_hcd_at91_drv_remove,
+       .remove         = __devexit_p(ohci_hcd_at91_drv_remove),
        .shutdown       = usb_hcd_platform_shutdown,
        .suspend        = ohci_hcd_at91_drv_suspend,
        .resume         = ohci_hcd_at91_drv_resume,
index 11de5f1be9819311254bae707cff67cb56c6cd99..32dada8c8b4f31e639227d120203482fe487d229 100644 (file)
@@ -825,9 +825,13 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
                }
        }
 
-       /* Disable any BIOS SMIs */
-       writel(XHCI_LEGACY_DISABLE_SMI,
-                       base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
+       val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
+       /* Mask off (turn off) any enabled SMIs */
+       val &= XHCI_LEGACY_DISABLE_SMI;
+       /* Mask all SMI events bits, RW1C */
+       val |= XHCI_LEGACY_SMI_EVENTS;
+       /* Disable any BIOS SMIs and clear all SMI events*/
+       writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
 
        if (usb_is_intel_switchable_xhci(pdev))
                usb_enable_xhci_ports(pdev);
index 045cde4cbc3deafca332c28974b47cb826bae423..768d54295a20742a8f38d6224ce1a9bb1de85556 100644 (file)
@@ -196,11 +196,12 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
        status = get_hub_status_data(uhci, buf);
 
        switch (uhci->rh_state) {
-           case UHCI_RH_SUSPENDING:
            case UHCI_RH_SUSPENDED:
                /* if port change, ask to be resumed */
-               if (status || uhci->resuming_ports)
+               if (status || uhci->resuming_ports) {
+                       status = 1;
                        usb_hcd_resume_root_hub(hcd);
+               }
                break;
 
            case UHCI_RH_AUTO_STOPPED:
index e9b0f043455db2ccc7e09ecaf99a1fe2eaa7a6be..4b436f5a41711bc1a7747f3c7b187ff547c7acbd 100644 (file)
@@ -119,7 +119,7 @@ static void xhci_print_command_reg(struct xhci_hcd *xhci)
        xhci_dbg(xhci, "  Event Interrupts %s\n",
                        (temp & CMD_EIE) ? "enabled " : "disabled");
        xhci_dbg(xhci, "  Host System Error Interrupts %s\n",
-                       (temp & CMD_EIE) ? "enabled " : "disabled");
+                       (temp & CMD_HSEIE) ? "enabled " : "disabled");
        xhci_dbg(xhci, "  HC has %sfinished light reset\n",
                        (temp & CMD_LRESET) ? "not " : "");
 }
index c7f33123d4c08e59954d5ac8d561f9cd6e3c9fef..377f4242dabb8cac56456258506b0c3982495b2a 100644 (file)
@@ -62,8 +62,9 @@
 /* USB Legacy Support Control and Status Register  - section 7.1.2 */
 /* Add this offset, plus the value of xECP in HCCPARAMS to the base address */
 #define XHCI_LEGACY_CONTROL_OFFSET     (0x04)
-/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
-#define        XHCI_LEGACY_DISABLE_SMI         ((0x3 << 1) + (0xff << 5) + (0x7 << 17))
+/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
+#define        XHCI_LEGACY_DISABLE_SMI         ((0x7 << 1) + (0xff << 5) + (0x7 << 17))
+#define XHCI_LEGACY_SMI_EVENTS         (0x7 << 29)
 
 /* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */
 #define XHCI_L1C               (1 << 16)
index cae4c6f2845a39c8ea58199a61f933b317f6cac0..68eaa908ac8eaa10eca2e1d9a6a9573b14efd5a0 100644 (file)
@@ -1796,11 +1796,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        int i;
 
        /* Free the Event Ring Segment Table and the actual Event Ring */
-       if (xhci->ir_set) {
-               xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
-               xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
-               xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
-       }
        size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
        if (xhci->erst.entries)
                dma_free_coherent(&pdev->dev, size,
@@ -1812,7 +1807,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        xhci->event_ring = NULL;
        xhci_dbg(xhci, "Freed event ring\n");
 
-       xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
        if (xhci->cmd_ring)
                xhci_ring_free(xhci, xhci->cmd_ring);
        xhci->cmd_ring = NULL;
@@ -1841,7 +1835,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        xhci->medium_streams_pool = NULL;
        xhci_dbg(xhci, "Freed medium stream array pool\n");
 
-       xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
        if (xhci->dcbaa)
                dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa),
                                xhci->dcbaa, xhci->dcbaa->dma);
@@ -2459,6 +2452,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 
 fail:
        xhci_warn(xhci, "Couldn't initialize memory\n");
+       xhci_halt(xhci);
+       xhci_reset(xhci);
        xhci_mem_cleanup(xhci);
        return -ENOMEM;
 }
index ef98b38626fbb5910aa6c486aecb856f1f4b7df5..7a856a767e77c5f9190666293ddf56a0e7a863d1 100644 (file)
@@ -95,6 +95,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                xhci->quirks |= XHCI_RESET_ON_RESUME;
                xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
        }
+       if (pdev->vendor == PCI_VENDOR_ID_VIA)
+               xhci->quirks |= XHCI_RESET_ON_RESUME;
 }
 
 /* called during probe() after chip reset completes */
@@ -326,7 +328,7 @@ int __init xhci_register_pci(void)
        return pci_register_driver(&xhci_pci_driver);
 }
 
-void __exit xhci_unregister_pci(void)
+void xhci_unregister_pci(void)
 {
        pci_unregister_driver(&xhci_pci_driver);
 }
index 6bd9d53062eb3bdbb25d7b83a83c337640dc912b..3d9422f16a20b66f2eb54aaffacebaf209b76868 100644 (file)
@@ -2417,7 +2417,7 @@ hw_died:
                u32 irq_pending;
                /* Acknowledge the PCI interrupt */
                irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
-               irq_pending |= 0x3;
+               irq_pending |= IMAN_IP;
                xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending);
        }
 
@@ -2734,7 +2734,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                urb->dev->speed == USB_SPEED_FULL)
                        urb->interval /= 8;
        }
-       return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
+       return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index);
 }
 
 /*
@@ -3514,7 +3514,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
        }
        ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free;
 
-       return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
+       return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);
 }
 
 /****          Command Ring Operations         ****/
index e1963d4a430f2952c8383b5a25fff8debc6c0014..36641a7f23719058d5ebfe463feb00ac085b99f3 100644 (file)
@@ -106,6 +106,9 @@ int xhci_halt(struct xhci_hcd *xhci)
                        STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
        if (!ret)
                xhci->xhc_state |= XHCI_STATE_HALTED;
+       else
+               xhci_warn(xhci, "Host not halted after %u microseconds.\n",
+                               XHCI_MAX_HALT_USEC);
        return ret;
 }
 
@@ -664,11 +667,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci)
        xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);
        xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
        xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg);
-       xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
-       xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
        xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);
        xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
        xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+       xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+       xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
 }
 
 static void xhci_restore_registers(struct xhci_hcd *xhci)
@@ -677,10 +680,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)
        xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
        xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
        xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg);
-       xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
-       xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
        xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);
        xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
+       xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
+       xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
+       xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
 }
 
 static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
index 91074fdab3eb6cbcfd772b6c7066083155beed91..3d69c4b2b54277d57e6cb15cbf403127d70aeb1f 100644 (file)
@@ -205,6 +205,10 @@ struct xhci_op_regs {
 #define CMD_PM_INDEX   (1 << 11)
 /* bits 12:31 are reserved (and should be preserved on writes). */
 
+/* IMAN - Interrupt Management Register */
+#define IMAN_IP                (1 << 1)
+#define IMAN_IE                (1 << 0)
+
 /* USBSTS - USB status - status bitmasks */
 /* HC not running - set to 1 when run/stop bit is cleared. */
 #define STS_HALT       XHCI_STS_HALT
index 959145baf3cf8dd87669be5ed292de99541b4ed3..9dcb68f04f03025265f3747e6f7bf072ab1b8958 100644 (file)
@@ -423,7 +423,7 @@ alloc_sglist(int nents, int max, int vary)
        unsigned                i;
        unsigned                size = max;
 
-       sg = kmalloc(nents * sizeof *sg, GFP_KERNEL);
+       sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL);
        if (!sg)
                return NULL;
        sg_init_table(sg, nents);
@@ -904,6 +904,9 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
        struct ctrl_ctx         context;
        int                     i;
 
+       if (param->sglen == 0 || param->iterations > UINT_MAX / param->sglen)
+               return -EOPNOTSUPP;
+
        spin_lock_init(&context.lock);
        context.dev = dev;
        init_completion(&context.complete);
@@ -1981,8 +1984,6 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
 
        /* queued control messaging */
        case 10:
-               if (param->sglen == 0)
-                       break;
                retval = 0;
                dev_info(&intf->dev,
                                "TEST 10:  queue %d control calls, %d times\n",
@@ -2276,6 +2277,8 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id)
                        if (status < 0) {
                                WARNING(dev, "couldn't get endpoints, %d\n",
                                                status);
+                               kfree(dev->buf);
+                               kfree(dev);
                                return status;
                        }
                        /* may find bulk or ISO pipes */
index 897edda422709c016b36d469b5930532a104a30c..70201462e19c0e57d8615432a7d3e5e5813aed85 100644 (file)
@@ -99,9 +99,7 @@ static void yurex_delete(struct kref *kref)
        usb_put_dev(dev->udev);
        if (dev->cntl_urb) {
                usb_kill_urb(dev->cntl_urb);
-               if (dev->cntl_req)
-                       usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
-                               dev->cntl_req, dev->cntl_urb->setup_dma);
+               kfree(dev->cntl_req);
                if (dev->cntl_buffer)
                        usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
                                dev->cntl_buffer, dev->cntl_urb->transfer_dma);
@@ -234,9 +232,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
        }
 
        /* allocate buffer for control req */
-       dev->cntl_req = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
-                                          GFP_KERNEL,
-                                          &dev->cntl_urb->setup_dma);
+       dev->cntl_req = kmalloc(YUREX_BUF_SIZE, GFP_KERNEL);
        if (!dev->cntl_req) {
                err("Could not allocate cntl_req");
                goto error;
@@ -286,7 +282,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
                         usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
                         dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt,
                         dev, 1);
-       dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+       dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
        if (usb_submit_urb(dev->urb, GFP_KERNEL)) {
                retval = -EIO;
                err("Could not submitting URB");
index 97ab975fa4424c3bcb4b6cce5368fc144aaba845..768b4b55c816a6960733f73d7e0d7b86be54697f 100644 (file)
@@ -386,7 +386,7 @@ static int davinci_musb_init(struct musb *musb)
        usb_nop_xceiv_register();
        musb->xceiv = usb_get_transceiver();
        if (!musb->xceiv)
-               return -ENODEV;
+               goto unregister;
 
        musb->mregs += DAVINCI_BASE_OFFSET;
 
@@ -444,6 +444,7 @@ static int davinci_musb_init(struct musb *musb)
 
 fail:
        usb_put_transceiver(musb->xceiv);
+unregister:
        usb_nop_xceiv_unregister();
        return -ENODEV;
 }
index 0f8b82918a40f8038d5c75567b18e2b62d454829..66aaccf04490487f83c1aa926be58e2410d12eea 100644 (file)
@@ -137,6 +137,9 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
        int     i = 0;
        u8      r;
        u8      power;
+       int     ret;
+
+       pm_runtime_get_sync(phy->io_dev);
 
        /* Make sure the transceiver is not in low power mode */
        power = musb_readb(addr, MUSB_POWER);
@@ -154,15 +157,22 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
        while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
                                & MUSB_ULPI_REG_CMPLT)) {
                i++;
-               if (i == 10000)
-                       return -ETIMEDOUT;
+               if (i == 10000) {
+                       ret = -ETIMEDOUT;
+                       goto out;
+               }
 
        }
        r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
        r &= ~MUSB_ULPI_REG_CMPLT;
        musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
 
-       return musb_readb(addr, MUSB_ULPI_REG_DATA);
+       ret = musb_readb(addr, MUSB_ULPI_REG_DATA);
+
+out:
+       pm_runtime_put(phy->io_dev);
+
+       return ret;
 }
 
 static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
@@ -171,6 +181,9 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
        int     i = 0;
        u8      r = 0;
        u8      power;
+       int     ret = 0;
+
+       pm_runtime_get_sync(phy->io_dev);
 
        /* Make sure the transceiver is not in low power mode */
        power = musb_readb(addr, MUSB_POWER);
@@ -184,15 +197,20 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
        while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
                                & MUSB_ULPI_REG_CMPLT)) {
                i++;
-               if (i == 10000)
-                       return -ETIMEDOUT;
+               if (i == 10000) {
+                       ret = -ETIMEDOUT;
+                       goto out;
+               }
        }
 
        r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
        r &= ~MUSB_ULPI_REG_CMPLT;
        musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
 
-       return 0;
+out:
+       pm_runtime_put(phy->io_dev);
+
+       return ret;
 }
 #else
 #define musb_ulpi_read         NULL
@@ -1904,14 +1922,17 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
        if (!musb->isr) {
                status = -ENODEV;
-               goto fail3;
+               goto fail2;
        }
 
        if (!musb->xceiv->io_ops) {
+               musb->xceiv->io_dev = musb->controller;
                musb->xceiv->io_priv = musb->mregs;
                musb->xceiv->io_ops = &musb_ulpi_access;
        }
 
+       pm_runtime_get_sync(musb->controller);
+
 #ifndef CONFIG_MUSB_PIO_ONLY
        if (use_dma && dev->dma_mask) {
                struct dma_controller   *c;
@@ -2023,6 +2044,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
                goto fail5;
 #endif
 
+       pm_runtime_put(musb->controller);
+
        dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
                        ({char *s;
                         switch (musb->board_mode) {
@@ -2047,6 +2070,9 @@ fail4:
                musb_gadget_cleanup(musb);
 
 fail3:
+       pm_runtime_put_sync(musb->controller);
+
+fail2:
        if (musb->irq_wake)
                device_init_wakeup(dev, 0);
        musb_platform_exit(musb);
index 93de517a32a00009aeffbdf6691906a979ae506f..f4a40f001c8803eecfedab2af6dfcdd50d95ed22 100644 (file)
@@ -449,7 +449,7 @@ struct musb {
         * We added this flag to forcefully disable double
         * buffering until we get it working.
         */
-       unsigned                double_buffer_not_ok:1 __deprecated;
+       unsigned                double_buffer_not_ok:1;
 
        struct musb_hdrc_config *config;
 
index 79cb0af779fa07dac0702ee9b2b2d43e0a22b738..ef8d744800ac29c58dc24e089a645211fcd665ff 100644 (file)
@@ -2098,7 +2098,7 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh)
        }
 
        /* turn off DMA requests, discard state, stop polling ... */
-       if (is_in) {
+       if (ep->epnum && is_in) {
                /* giveback saves bulk toggle */
                csr = musb_h_flush_rxfifo(ep, 0);
 
index 2ae0bb3099940404044d84eb40740e7a82f52586..c7785e81254cdf96eef46f352ee134fc8ca759aa 100644 (file)
@@ -282,7 +282,8 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
 
 static int omap2430_musb_init(struct musb *musb)
 {
-       u32 l, status = 0;
+       u32 l;
+       int status = 0;
        struct device *dev = musb->controller;
        struct musb_hdrc_platform_data *plat = dev->platform_data;
        struct omap_musb_board_data *data = plat->board_data;
@@ -301,7 +302,7 @@ static int omap2430_musb_init(struct musb *musb)
 
        status = pm_runtime_get_sync(dev);
        if (status < 0) {
-               dev_err(dev, "pm_runtime_get_sync FAILED");
+               dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
                goto err1;
        }
 
@@ -333,6 +334,7 @@ static int omap2430_musb_init(struct musb *musb)
 
        setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
+       pm_runtime_put_noidle(musb->controller);
        return 0;
 
 err1:
@@ -452,14 +454,14 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
                goto err2;
        }
 
+       pm_runtime_enable(&pdev->dev);
+
        ret = platform_device_add(musb);
        if (ret) {
                dev_err(&pdev->dev, "failed to register musb device\n");
                goto err2;
        }
 
-       pm_runtime_enable(&pdev->dev);
-
        return 0;
 
 err2:
@@ -478,7 +480,6 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
 
        platform_device_del(glue->musb);
        platform_device_put(glue->musb);
-       pm_runtime_put(&pdev->dev);
        kfree(glue);
 
        return 0;
@@ -491,11 +492,13 @@ static int omap2430_runtime_suspend(struct device *dev)
        struct omap2430_glue            *glue = dev_get_drvdata(dev);
        struct musb                     *musb = glue_to_musb(glue);
 
-       musb->context.otg_interfsel = musb_readl(musb->mregs,
-                                               OTG_INTERFSEL);
+       if (musb) {
+               musb->context.otg_interfsel = musb_readl(musb->mregs,
+                               OTG_INTERFSEL);
 
-       omap2430_low_level_exit(musb);
-       usb_phy_set_suspend(musb->xceiv, 1);
+               omap2430_low_level_exit(musb);
+               usb_phy_set_suspend(musb->xceiv, 1);
+       }
 
        return 0;
 }
@@ -505,11 +508,13 @@ static int omap2430_runtime_resume(struct device *dev)
        struct omap2430_glue            *glue = dev_get_drvdata(dev);
        struct musb                     *musb = glue_to_musb(glue);
 
-       omap2430_low_level_init(musb);
-       musb_writel(musb->mregs, OTG_INTERFSEL,
-                                       musb->context.otg_interfsel);
+       if (musb) {
+               omap2430_low_level_init(musb);
+               musb_writel(musb->mregs, OTG_INTERFSEL,
+                               musb->context.otg_interfsel);
 
-       usb_phy_set_suspend(musb->xceiv, 0);
+               usb_phy_set_suspend(musb->xceiv, 0);
+       }
 
        return 0;
 }
index 3ece43a2e4c14b2b4a07fee9dcfaab4be03cfa3c..a0a2178974fe149f99da263627d8ada256faace5 100644 (file)
@@ -96,7 +96,7 @@ static void gpio_vbus_work(struct work_struct *work)
        struct gpio_vbus_data *gpio_vbus =
                container_of(work, struct gpio_vbus_data, work);
        struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
-       int gpio;
+       int gpio, status;
 
        if (!gpio_vbus->phy.otg->gadget)
                return;
@@ -108,7 +108,9 @@ static void gpio_vbus_work(struct work_struct *work)
         */
        gpio = pdata->gpio_pullup;
        if (is_vbus_powered(pdata)) {
+               status = USB_EVENT_VBUS;
                gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
+               gpio_vbus->phy.last_event = status;
                usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);
 
                /* drawing a "unit load" is *always* OK, except for OTG */
@@ -117,6 +119,9 @@ static void gpio_vbus_work(struct work_struct *work)
                /* optionally enable D+ pullup */
                if (gpio_is_valid(gpio))
                        gpio_set_value(gpio, !pdata->gpio_pullup_inverted);
+
+               atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
+                                          status, gpio_vbus->phy.otg->gadget);
        } else {
                /* optionally disable D+ pullup */
                if (gpio_is_valid(gpio))
@@ -125,7 +130,12 @@ static void gpio_vbus_work(struct work_struct *work)
                set_vbus_draw(gpio_vbus, 0);
 
                usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
+               status = USB_EVENT_NONE;
                gpio_vbus->phy.state = OTG_STATE_B_IDLE;
+               gpio_vbus->phy.last_event = status;
+
+               atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
+                                          status, gpio_vbus->phy.otg->gadget);
        }
 }
 
@@ -287,6 +297,9 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
                        irq, err);
                goto err_irq;
        }
+
+       ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier);
+
        INIT_WORK(&gpio_vbus->work, gpio_vbus_work);
 
        gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
index 7f547dc3a5903fd25e0837441115007320ae122d..ed8adb052ca74f136a14a423dea5cbe397c4d381 100644 (file)
@@ -60,8 +60,6 @@ static int usb_serial_device_probe(struct device *dev)
                retval = -ENODEV;
                goto exit;
        }
-       if (port->dev_state != PORT_REGISTERING)
-               goto exit;
 
        driver = port->serial->type;
        if (driver->port_probe) {
@@ -98,9 +96,6 @@ static int usb_serial_device_remove(struct device *dev)
        if (!port)
                return -ENODEV;
 
-       if (port->dev_state != PORT_UNREGISTERING)
-               return retval;
-
        device_remove_file(&port->dev, &dev_attr_port_number);
 
        driver = port->serial->type;
index 0310e2df59f5b78029ed5832e61039c826ae082d..ec30f95ef399e3b8bc907084c00c50592734791d 100644 (file)
@@ -287,7 +287,8 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
        /* Issue the request, attempting to read 'size' bytes */
        result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
                                request, REQTYPE_DEVICE_TO_HOST, 0x0000,
-                               port_priv->bInterfaceNumber, buf, size, 300);
+                               port_priv->bInterfaceNumber, buf, size,
+                               USB_CTRL_GET_TIMEOUT);
 
        /* Convert data into an array of integers */
        for (i = 0; i < length; i++)
@@ -340,12 +341,14 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0),
                                request, REQTYPE_HOST_TO_DEVICE, 0x0000,
-                               port_priv->bInterfaceNumber, buf, size, 300);
+                               port_priv->bInterfaceNumber, buf, size,
+                               USB_CTRL_SET_TIMEOUT);
        } else {
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0),
                                request, REQTYPE_HOST_TO_DEVICE, data[0],
-                               port_priv->bInterfaceNumber, NULL, 0, 300);
+                               port_priv->bInterfaceNumber, NULL, 0,
+                               USB_CTRL_SET_TIMEOUT);
        }
 
        kfree(buf);
index ff8605b4b4be4679a7d6b9abf177bba8ee7f630b..02e7f2d32d52601156bc85f131599e4d2b7c95cd 100644 (file)
@@ -75,7 +75,8 @@ struct ftdi_private {
        unsigned long last_dtr_rts;     /* saved modem control outputs */
        struct async_icount     icount;
        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
-       char prev_status, diff_status;        /* Used for TIOCMIWAIT */
+       char prev_status;        /* Used for TIOCMIWAIT */
+       bool dev_gone;        /* Used to abort TIOCMIWAIT */
        char transmit_empty;    /* If transmitter is empty or not */
        struct usb_serial_port *port;
        __u16 interface;        /* FT2232C, FT2232H or FT4232H port interface
@@ -1681,6 +1682,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
        init_waitqueue_head(&priv->delta_msr_wait);
 
        priv->flags = ASYNC_LOW_LATENCY;
+       priv->dev_gone = false;
 
        if (quirk && quirk->port_probe)
                quirk->port_probe(priv);
@@ -1839,6 +1841,9 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
 
        dbg("%s", __func__);
 
+       priv->dev_gone = true;
+       wake_up_interruptible_all(&priv->delta_msr_wait);
+
        remove_sysfs_attrs(port);
 
        kref_put(&priv->kref, ftdi_sio_priv_release);
@@ -1982,17 +1987,19 @@ static int ftdi_process_packet(struct tty_struct *tty,
           N.B. packet may be processed more than once, but differences
           are only processed once.  */
        status = packet[0] & FTDI_STATUS_B0_MASK;
-       if (status & FTDI_RS0_CTS)
-               priv->icount.cts++;
-       if (status & FTDI_RS0_DSR)
-               priv->icount.dsr++;
-       if (status & FTDI_RS0_RI)
-               priv->icount.rng++;
-       if (status & FTDI_RS0_RLSD)
-               priv->icount.dcd++;
        if (status != priv->prev_status) {
-               priv->diff_status |= status ^ priv->prev_status;
-               wake_up_interruptible(&priv->delta_msr_wait);
+               char diff_status = status ^ priv->prev_status;
+
+               if (diff_status & FTDI_RS0_CTS)
+                       priv->icount.cts++;
+               if (diff_status & FTDI_RS0_DSR)
+                       priv->icount.dsr++;
+               if (diff_status & FTDI_RS0_RI)
+                       priv->icount.rng++;
+               if (diff_status & FTDI_RS0_RLSD)
+                       priv->icount.dcd++;
+
+               wake_up_interruptible_all(&priv->delta_msr_wait);
                priv->prev_status = status;
        }
 
@@ -2395,15 +2402,12 @@ static int ftdi_ioctl(struct tty_struct *tty,
         */
        case TIOCMIWAIT:
                cprev = priv->icount;
-               while (1) {
+               while (!priv->dev_gone) {
                        interruptible_sleep_on(&priv->delta_msr_wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
                        cnow = priv->icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
                        if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
                            ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
                            ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
@@ -2412,7 +2416,7 @@ static int ftdi_ioctl(struct tty_struct *tty,
                        }
                        cprev = cnow;
                }
-               /* not reached */
+               return -EIO;
                break;
        case TIOCSERGETLSR:
                return get_lsr_info(port, (struct serial_struct __user *)arg);
index 6e1622f2a297f95948a4d5fc72f132801142c26e..08d16e8c002d5b59444c1b12b44585ee8fd19a6d 100644 (file)
@@ -27,8 +27,8 @@
 
 /* Product information. */
 #define FOCUS_VENDOR_ID                        0x0C2E
-#define FOCUS_PRODUCT_ID               0x0720
-#define FOCUS_PRODUCT_ID_UNI           0x0710
+#define FOCUS_PRODUCT_ID_BI            0x0720
+#define FOCUS_PRODUCT_ID_UNI           0x0700
 
 #define METROUSB_SET_REQUEST_TYPE      0x40
 #define METROUSB_SET_MODEM_CTRL_REQUEST        10
@@ -47,7 +47,7 @@ struct metrousb_private {
 
 /* Device table list. */
 static struct usb_device_id id_table[] = {
-       { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) },
+       { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) },
        { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) },
        { }, /* Terminating entry. */
 };
index 836cfa9a515fe9f2523f3a387995ac386f915ec8..f4465ccddc351b14f6f9f3f61dbdd82bab34008a 100644 (file)
@@ -708,6 +708,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) },
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) },
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) },
index ff4a174fa5de8e536572584b32b08a41defc7e1e..a1a9062954c471f57f4b173490a7bcd2a62a210c 100644 (file)
@@ -420,7 +420,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
        control = priv->line_control;
        if ((cflag & CBAUD) == B0)
                priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
-       else
+       else if ((old_termios->c_cflag & CBAUD) == B0)
                priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
        if (control != priv->line_control) {
                control = priv->line_control;
index f14465a83dd1f53e1688c399a950bf67f3ed501a..8c8bf806f6faf9b779c8ed002a273c7aba5c96c0 100644 (file)
@@ -221,7 +221,7 @@ static const struct sierra_iface_info typeB_interface_list = {
 };
 
 /* 'blacklist' of interfaces not served by this driver */
-static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 };
+static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 };
 static const struct sierra_iface_info direct_ip_interface_blacklist = {
        .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces),
        .ifaceinfo = direct_ip_non_serial_ifaces,
@@ -298,6 +298,9 @@ static const struct usb_device_id id_table[] = {
        /* Sierra Wireless HSPA Non-Composite Device */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
        { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
+       { USB_DEVICE(0x1199, 0x68A2),   /* Sierra Wireless MC77xx in QMI mode */
+         .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+       },
        { USB_DEVICE(0x1199, 0x68A3),   /* Sierra Wireless Direct IP modems */
          .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
        },
index 69230f01056ab32f551c2a0e8e953e1fee03649e..97355a15bbea8b5a36f3c7e52fd0eb5d4c3caa8a 100644 (file)
@@ -1059,6 +1059,12 @@ int usb_serial_probe(struct usb_interface *interface,
                serial->attached = 1;
        }
 
+       /* Avoid race with tty_open and serial_install by setting the
+        * disconnected flag and not clearing it until all ports have been
+        * registered.
+        */
+       serial->disconnected = 1;
+
        if (get_free_serial(serial, num_ports, &minor) == NULL) {
                dev_err(&interface->dev, "No more free serial devices\n");
                goto probe_error;
@@ -1070,19 +1076,16 @@ int usb_serial_probe(struct usb_interface *interface,
                port = serial->port[i];
                dev_set_name(&port->dev, "ttyUSB%d", port->number);
                dbg ("%s - registering %s", __func__, dev_name(&port->dev));
-               port->dev_state = PORT_REGISTERING;
                device_enable_async_suspend(&port->dev);
 
                retval = device_add(&port->dev);
-               if (retval) {
+               if (retval)
                        dev_err(&port->dev, "Error registering port device, "
                                "continuing\n");
-                       port->dev_state = PORT_UNREGISTERED;
-               } else {
-                       port->dev_state = PORT_REGISTERED;
-               }
        }
 
+       serial->disconnected = 0;
+
        usb_serial_console_init(debug, minor);
 
 exit:
@@ -1124,22 +1127,8 @@ void usb_serial_disconnect(struct usb_interface *interface)
                        }
                        kill_traffic(port);
                        cancel_work_sync(&port->work);
-                       if (port->dev_state == PORT_REGISTERED) {
-
-                               /* Make sure the port is bound so that the
-                                * driver's port_remove method is called.
-                                */
-                               if (!port->dev.driver) {
-                                       int rc;
-
-                                       port->dev.driver =
-                                                       &serial->type->driver;
-                                       rc = device_bind_driver(&port->dev);
-                               }
-                               port->dev_state = PORT_UNREGISTERING;
+                       if (device_is_registered(&port->dev))
                                device_del(&port->dev);
-                               port->dev_state = PORT_UNREGISTERED;
-                       }
                }
        }
        serial->type->disconnect(serial);
index c18538e4a6db1e0adeb26437b3b6f2de38b6b38c..2653e73db6233eabcf83f527019451820157e65d 100644 (file)
@@ -132,6 +132,35 @@ static struct us_unusual_dev for_dynamic_ids =
 #undef COMPLIANT_DEV
 #undef USUAL_DEV
 
+#ifdef CONFIG_LOCKDEP
+
+static struct lock_class_key us_interface_key[USB_MAXINTERFACES];
+
+static void us_set_lock_class(struct mutex *mutex,
+               struct usb_interface *intf)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_host_config *config = udev->actconfig;
+       int i;
+
+       for (i = 0; i < config->desc.bNumInterfaces; i++) {
+               if (config->interface[i] == intf)
+                       break;
+       }
+
+       BUG_ON(i == config->desc.bNumInterfaces);
+
+       lockdep_set_class(mutex, &us_interface_key[i]);
+}
+
+#else
+
+static void us_set_lock_class(struct mutex *mutex,
+               struct usb_interface *intf)
+{
+}
+
+#endif
 
 #ifdef CONFIG_PM       /* Minimal support for suspend and resume */
 
@@ -895,6 +924,7 @@ int usb_stor_probe1(struct us_data **pus,
        *pus = us = host_to_us(host);
        memset(us, 0, sizeof(struct us_data));
        mutex_init(&(us->dev_mutex));
+       us_set_lock_class(&us->dev_mutex, intf);
        init_completion(&us->cmnd_ready);
        init_completion(&(us->notify));
        init_waitqueue_head(&us->delay_wait);
index 66797e9c5010d35cd5c21563a99faec79cd8a175..810c90ae2c5584fc57113813f2a9251422724840 100644 (file)
@@ -645,7 +645,8 @@ void hwarc_neep_cb(struct urb *urb)
                dev_err(dev, "NEEP: URB error %d\n", urb->status);
        }
        result = usb_submit_urb(urb, GFP_ATOMIC);
-       if (result < 0) {
+       if (result < 0 && result != -ENODEV && result != -EPERM) {
+               /* ignoring unrecoverable errors */
                dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n",
                        result);
                goto error;
index a269937be1b8230898f991eb5f430e3f79ac9824..8cb71bb333c2ea830881ddc8bf19afd4096b3d60 100644 (file)
@@ -107,6 +107,7 @@ struct uwb_rc_neh {
        u8 evt_type;
        __le16 evt;
        u8 context;
+       u8 completed;
        uwb_rc_cmd_cb_f cb;
        void *arg;
 
@@ -409,6 +410,7 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size
        struct device *dev = &rc->uwb_dev.dev;
        struct uwb_rc_neh *neh;
        struct uwb_rceb *notif;
+       unsigned long flags;
 
        if (rceb->bEventContext == 0) {
                notif = kmalloc(size, GFP_ATOMIC);
@@ -422,7 +424,11 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size
        } else {
                neh = uwb_rc_neh_lookup(rc, rceb);
                if (neh) {
-                       del_timer_sync(&neh->timer);
+                       spin_lock_irqsave(&rc->neh_lock, flags);
+                       /* to guard against a timeout */
+                       neh->completed = 1;
+                       del_timer(&neh->timer);
+                       spin_unlock_irqrestore(&rc->neh_lock, flags);
                        uwb_rc_neh_cb(neh, rceb, size);
                } else
                        dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n",
@@ -568,6 +574,10 @@ static void uwb_rc_neh_timer(unsigned long arg)
        unsigned long flags;
 
        spin_lock_irqsave(&rc->neh_lock, flags);
+       if (neh->completed) {
+               spin_unlock_irqrestore(&rc->neh_lock, flags);
+               return;
+       }
        if (neh->context)
                __uwb_rc_neh_rm(rc, neh);
        else
index 2eecec0c13c9bf1bba5013865fdfdd799c175af0..6ec45beb7af5e5bf55756e6d622447dc989dfc48 100644 (file)
@@ -159,13 +159,6 @@ static int cmd_ie_rm(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_rm)
        return uwb_rc_ie_rm(rc, ie_to_rm->data[0]);
 }
 
-static int command_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-
-       return 0;
-}
-
 static ssize_t command_write(struct file *file, const char __user *buf,
                         size_t len, loff_t *off)
 {
@@ -206,7 +199,7 @@ static ssize_t command_write(struct file *file, const char __user *buf,
 }
 
 static const struct file_operations command_fops = {
-       .open   = command_open,
+       .open   = simple_open,
        .write  = command_write,
        .read   = NULL,
        .llseek = no_llseek,
index f0da2c32fbdefce2ff9d791f9fa23a73ac49de8d..1f21d2a1e52885af8db0a691170b8ab0364aa7b4 100644 (file)
@@ -238,7 +238,7 @@ static void handle_tx(struct vhost_net *net)
 
                                vq->heads[vq->upend_idx].len = len;
                                ubuf->callback = vhost_zerocopy_callback;
-                               ubuf->arg = vq->ubufs;
+                               ubuf->ctx = vq->ubufs;
                                ubuf->desc = vq->upend_idx;
                                msg.msg_control = ubuf;
                                msg.msg_controllen = sizeof(ubuf);
index fc9a1d75281f33d57be305b3c724195c578334de..3de00d9fae2e6b7f186ed1767bed6e6424f08c76 100644 (file)
@@ -155,7 +155,7 @@ static int vhost_test_release(struct inode *inode, struct file *f)
 
        vhost_test_stop(n, &private);
        vhost_test_flush(n);
-       vhost_dev_cleanup(&n->dev);
+       vhost_dev_cleanup(&n->dev, false);
        /* We do an extra flush before freeing memory,
         * since jobs can re-queue themselves. */
        vhost_test_flush(n);
index 947f00d8e091a3f2f3c01cc7cc23f5f2658d37df..51e4c1eeec4f0b09af84b5feb58c63313cd7d0cb 100644 (file)
@@ -1598,10 +1598,9 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs)
        kfree(ubufs);
 }
 
-void vhost_zerocopy_callback(void *arg)
+void vhost_zerocopy_callback(struct ubuf_info *ubuf)
 {
-       struct ubuf_info *ubuf = arg;
-       struct vhost_ubuf_ref *ubufs = ubuf->arg;
+       struct vhost_ubuf_ref *ubufs = ubuf->ctx;
        struct vhost_virtqueue *vq = ubufs->vq;
 
        /* set len = 1 to mark this desc buffers done DMA */
index 8dcf4cca6bf224ec5c36f105a994ba76b0b19188..8de1fd5b8efba8a39c20e7872a23b517e710b9ec 100644 (file)
@@ -188,7 +188,7 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
                    unsigned int log_num, u64 len);
-void vhost_zerocopy_callback(void *arg);
+void vhost_zerocopy_callback(struct ubuf_info *);
 int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq);
 
 #define vq_err(vq, fmt, ...) do {                                  \
index befcbd8ef019970eb156441d891712bca4006bac..ffbce4525468955a06051bb2df31caf83c522606 100644 (file)
@@ -499,7 +499,8 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
        au1100fb_fix.mmio_start = regs_res->start;
        au1100fb_fix.mmio_len = resource_size(regs_res);
 
-       if (!devm_request_mem_region(au1100fb_fix.mmio_start,
+       if (!devm_request_mem_region(&dev->dev,
+                                    au1100fb_fix.mmio_start,
                                     au1100fb_fix.mmio_len,
                                     DRIVER_NAME)) {
                print_err("fail to lock memory region at 0x%08lx",
@@ -516,7 +517,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
        fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
                        (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
 
-       fbdev->fb_mem = dmam_alloc_coherent(&dev->dev, &dev->dev,
+       fbdev->fb_mem = dmam_alloc_coherent(&dev->dev,
                                            PAGE_ALIGN(fbdev->fb_len),
                                            &fbdev->fb_phys, GFP_KERNEL);
        if (!fbdev->fb_mem) {
index 3e9a773db09f18540382bd42c77a696a842ed13b..7ca79f02056ebc9d967af326800687529dae37a8 100644 (file)
@@ -1724,7 +1724,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
                /* Allocate the framebuffer to the maximum screen size */
                fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
 
-               fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev, &dev->dev,
+               fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev,
                                PAGE_ALIGN(fbdev->fb_len),
                                &fbdev->fb_phys, GFP_KERNEL);
                if (!fbdev->fb_mem) {
index 7ed9991fa74785cb8d232954c10d0925caed59ab..af16884491edf45cf3105f79e340a6b912757541 100644 (file)
@@ -245,6 +245,12 @@ config BACKLIGHT_DA903X
          If you have a LCD backlight connected to the WLED output of DA9030
          or DA9034 WLED output, say Y here to enable this driver.
 
+config BACKLIGHT_DA9052
+       tristate "Dialog DA9052/DA9053 WLED"
+       depends on PMIC_DA9052
+       help
+         Enable the Backlight Driver for DA9052-BC and DA9053-AA/Bx PMICs.
+
 config BACKLIGHT_MAX8925
        tristate "Backlight driver for MAX8925"
        depends on MFD_MAX8925
index 8071eb656147796dfc410ee92a5bc84f7429aa4a..36855ae887d6ae9f56a85a0b02b24a3afa271c83 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_PWM)    += pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
+obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o
 obj-$(CONFIG_BACKLIGHT_MAX8925)        += max8925_bl.o
 obj-$(CONFIG_BACKLIGHT_APPLE)  += apple_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)   += tosa_bl.o
diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c
new file mode 100644 (file)
index 0000000..b628d68
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Backlight Driver for Dialog DA9052 PMICs
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/reg.h>
+
+#define DA9052_MAX_BRIGHTNESS          0xFF
+
+enum {
+       DA9052_WLEDS_OFF,
+       DA9052_WLEDS_ON,
+};
+
+enum {
+       DA9052_TYPE_WLED1,
+       DA9052_TYPE_WLED2,
+       DA9052_TYPE_WLED3,
+};
+
+static unsigned char wled_bank[] = {
+       DA9052_LED1_CONF_REG,
+       DA9052_LED2_CONF_REG,
+       DA9052_LED3_CONF_REG,
+};
+
+struct da9052_bl {
+       struct da9052 *da9052;
+       uint brightness;
+       uint state;
+       uint led_reg;
+};
+
+static int da9052_adjust_wled_brightness(struct da9052_bl *wleds)
+{
+       unsigned char boost_en;
+       unsigned char i_sink;
+       int ret;
+
+       boost_en = 0x3F;
+       i_sink = 0xFF;
+       if (wleds->state == DA9052_WLEDS_OFF) {
+               boost_en = 0x00;
+               i_sink = 0x00;
+       }
+
+       ret = da9052_reg_write(wleds->da9052, DA9052_BOOST_REG, boost_en);
+       if (ret < 0)
+               return ret;
+
+       ret = da9052_reg_write(wleds->da9052, DA9052_LED_CONT_REG, i_sink);
+       if (ret < 0)
+               return ret;
+
+       ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], 0x0);
+       if (ret < 0)
+               return ret;
+
+       msleep(10);
+
+       if (wleds->brightness) {
+               ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg],
+                                      wleds->brightness);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int da9052_backlight_update_status(struct backlight_device *bl)
+{
+       int brightness = bl->props.brightness;
+       struct da9052_bl *wleds = bl_get_data(bl);
+
+       wleds->brightness = brightness;
+       wleds->state = DA9052_WLEDS_ON;
+
+       return da9052_adjust_wled_brightness(wleds);
+}
+
+static int da9052_backlight_get_brightness(struct backlight_device *bl)
+{
+       struct da9052_bl *wleds = bl_get_data(bl);
+
+       return wleds->brightness;
+}
+
+static const struct backlight_ops da9052_backlight_ops = {
+       .update_status = da9052_backlight_update_status,
+       .get_brightness = da9052_backlight_get_brightness,
+};
+
+static int da9052_backlight_probe(struct platform_device *pdev)
+{
+       struct backlight_device *bl;
+       struct backlight_properties props;
+       struct da9052_bl *wleds;
+
+       wleds = devm_kzalloc(&pdev->dev, sizeof(struct da9052_bl), GFP_KERNEL);
+       if (!wleds)
+               return -ENOMEM;
+
+       wleds->da9052 = dev_get_drvdata(pdev->dev.parent);
+       wleds->brightness = 0;
+       wleds->led_reg = platform_get_device_id(pdev)->driver_data;
+       wleds->state = DA9052_WLEDS_OFF;
+
+       props.type = BACKLIGHT_RAW;
+       props.max_brightness = DA9052_MAX_BRIGHTNESS;
+
+       bl = backlight_device_register(pdev->name, wleds->da9052->dev, wleds,
+                                      &da9052_backlight_ops, &props);
+       if (IS_ERR(bl)) {
+               dev_err(&pdev->dev, "Failed to register backlight\n");
+               devm_kfree(&pdev->dev, wleds);
+               return PTR_ERR(bl);
+       }
+
+       bl->props.max_brightness = DA9052_MAX_BRIGHTNESS;
+       bl->props.brightness = 0;
+       platform_set_drvdata(pdev, bl);
+
+       return da9052_adjust_wled_brightness(wleds);
+}
+
+static int da9052_backlight_remove(struct platform_device *pdev)
+{
+       struct backlight_device *bl = platform_get_drvdata(pdev);
+       struct da9052_bl *wleds = bl_get_data(bl);
+
+       wleds->brightness = 0;
+       wleds->state = DA9052_WLEDS_OFF;
+       da9052_adjust_wled_brightness(wleds);
+       backlight_device_unregister(bl);
+       devm_kfree(&pdev->dev, wleds);
+
+       return 0;
+}
+
+static struct platform_device_id da9052_wled_ids[] = {
+       {
+               .name           = "da9052-wled1",
+               .driver_data    = DA9052_TYPE_WLED1,
+       },
+       {
+               .name           = "da9052-wled2",
+               .driver_data    = DA9052_TYPE_WLED2,
+       },
+       {
+               .name           = "da9052-wled3",
+               .driver_data    = DA9052_TYPE_WLED3,
+       },
+};
+
+static struct platform_driver da9052_wled_driver = {
+       .probe          = da9052_backlight_probe,
+       .remove         = da9052_backlight_remove,
+       .id_table       = da9052_wled_ids,
+       .driver = {
+               .name   = "da9052-wled",
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver(da9052_wled_driver);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Backlight driver for DA9052 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9052-backlight");
index be20b5cbe26cb9e1dd244a284f898727ffa5c5ea..3a6d5419e3e3003d17094c3e8248749f36cbe07f 100644 (file)
@@ -229,14 +229,7 @@ static struct locomo_driver poodle_lcd_driver = {
 
 static int __init locomolcd_init(void)
 {
-       int ret = locomo_driver_register(&poodle_lcd_driver);
-       if (ret)
-               return ret;
-
-#ifdef CONFIG_SA1100_COLLIE
-       sa1100fb_lcd_power = locomolcd_power;
-#endif
-       return 0;
+       return locomo_driver_register(&poodle_lcd_driver);
 }
 
 static void __exit locomolcd_exit(void)
index 86922ac84412b3f6a8be0ef41b52e209c684d87c..353c02fe8a952816af0f5c0d668d80e81f31d204 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/fb.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/types.h>
index 784139aed0793cab282cf52f3f3c3503a85a9a5a..b4a632ada40172574ae9aca1ad6836d632ce4e1c 100644 (file)
@@ -18,6 +18,8 @@
 
 static bool request_mem_succeeded = false;
 
+static struct pci_dev *default_vga;
+
 static struct fb_var_screeninfo efifb_defined __devinitdata = {
        .activate               = FB_ACTIVATE_NOW,
        .height                 = -1,
@@ -298,35 +300,72 @@ static struct fb_ops efifb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
+struct pci_dev *vga_default_device(void)
+{
+       return default_vga;
+}
+
+EXPORT_SYMBOL_GPL(vga_default_device);
+
+void vga_set_default_device(struct pci_dev *pdev)
+{
+       default_vga = pdev;
+}
+
 static int __init efifb_setup(char *options)
 {
        char *this_opt;
        int i;
+       struct pci_dev *dev = NULL;
+
+       if (options && *options) {
+               while ((this_opt = strsep(&options, ",")) != NULL) {
+                       if (!*this_opt) continue;
+
+                       for (i = 0; i < M_UNKNOWN; i++) {
+                               if (!strcmp(this_opt, dmi_list[i].optname) &&
+                                   dmi_list[i].base != 0) {
+                                       screen_info.lfb_base = dmi_list[i].base;
+                                       screen_info.lfb_linelength = dmi_list[i].stride;
+                                       screen_info.lfb_width = dmi_list[i].width;
+                                       screen_info.lfb_height = dmi_list[i].height;
+                               }
+                       }
+                       if (!strncmp(this_opt, "base:", 5))
+                               screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
+                       else if (!strncmp(this_opt, "stride:", 7))
+                               screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
+                       else if (!strncmp(this_opt, "height:", 7))
+                               screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
+                       else if (!strncmp(this_opt, "width:", 6))
+                               screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
+               }
+       }
 
-       if (!options || !*options)
-               return 0;
+       for_each_pci_dev(dev) {
+               int i;
 
-       while ((this_opt = strsep(&options, ",")) != NULL) {
-               if (!*this_opt) continue;
+               if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+                       continue;
 
-               for (i = 0; i < M_UNKNOWN; i++) {
-                       if (!strcmp(this_opt, dmi_list[i].optname) &&
-                                       dmi_list[i].base != 0) {
-                               screen_info.lfb_base = dmi_list[i].base;
-                               screen_info.lfb_linelength = dmi_list[i].stride;
-                               screen_info.lfb_width = dmi_list[i].width;
-                               screen_info.lfb_height = dmi_list[i].height;
-                       }
+               for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
+                       resource_size_t start, end;
+
+                       if (!(pci_resource_flags(dev, i) & IORESOURCE_MEM))
+                               continue;
+
+                       start = pci_resource_start(dev, i);
+                       end  = pci_resource_end(dev, i);
+
+                       if (!start || !end)
+                               continue;
+
+                       if (screen_info.lfb_base >= start &&
+                           (screen_info.lfb_base + screen_info.lfb_size) < end)
+                               default_vga = dev;
                }
-               if (!strncmp(this_opt, "base:", 5))
-                       screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
-               else if (!strncmp(this_opt, "stride:", 7))
-                       screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
-               else if (!strncmp(this_opt, "height:", 7))
-                       screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
-               else if (!strncmp(this_opt, "width:", 6))
-                       screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
        }
+
        return 0;
 }
 
index 5d62698825892f857211acd61e5ffa0982b77e91..50f4670e92523a629cb2834cbac6e09e729003df 100644 (file)
@@ -73,210 +73,210 @@ typedef enum _OVRL_PIX_FORMAT {
 /* Register Table */
 typedef struct {
        /* 0h  */
-       volatile unsigned long Thread0Enable;   /* 0x0000 */
-       volatile unsigned long Thread1Enable;   /* 0x0004 */
-       volatile unsigned long Thread0Recover;  /* 0x0008 */
-       volatile unsigned long Thread1Recover;  /* 0x000C */
-       volatile unsigned long Thread0Step;     /* 0x0010 */
-       volatile unsigned long Thread1Step;     /* 0x0014 */
-       volatile unsigned long VideoInStatus;   /* 0x0018 */
-       volatile unsigned long Core2InSignStart;        /* 0x001C */
-       volatile unsigned long Core1ResetVector;        /* 0x0020 */
-       volatile unsigned long Core1ROMOffset;  /* 0x0024 */
-       volatile unsigned long Core1ArbiterPriority;    /* 0x0028 */
-       volatile unsigned long VideoInControl;  /* 0x002C */
-       volatile unsigned long VideoInReg0CtrlA;        /* 0x0030 */
-       volatile unsigned long VideoInReg0CtrlB;        /* 0x0034 */
-       volatile unsigned long VideoInReg1CtrlA;        /* 0x0038 */
-       volatile unsigned long VideoInReg1CtrlB;        /* 0x003C */
-       volatile unsigned long Thread0Kicker;   /* 0x0040 */
-       volatile unsigned long Core2InputSign;  /* 0x0044 */
-       volatile unsigned long Thread0ProgCtr;  /* 0x0048 */
-       volatile unsigned long Thread1ProgCtr;  /* 0x004C */
-       volatile unsigned long Thread1Kicker;   /* 0x0050 */
-       volatile unsigned long GPRegister1;     /* 0x0054 */
-       volatile unsigned long GPRegister2;     /* 0x0058 */
-       volatile unsigned long GPRegister3;     /* 0x005C */
-       volatile unsigned long GPRegister4;     /* 0x0060 */
-       volatile unsigned long SerialIntA;      /* 0x0064 */
-
-       volatile unsigned long Fill0[6];        /* GAP 0x0068 - 0x007C */
-
-       volatile unsigned long SoftwareReset;   /* 0x0080 */
-       volatile unsigned long SerialIntB;      /* 0x0084 */
-
-       volatile unsigned long Fill1[37];       /* GAP 0x0088 - 0x011C */
-
-       volatile unsigned long ROMELQV; /* 0x011C */
-       volatile unsigned long WLWH;    /* 0x0120 */
-       volatile unsigned long ROMELWL; /* 0x0124 */
-
-       volatile unsigned long dwFill_1;        /* GAP 0x0128 */
-
-       volatile unsigned long IntStatus;       /* 0x012C */
-       volatile unsigned long IntMask; /* 0x0130 */
-       volatile unsigned long IntClear;        /* 0x0134 */
-
-       volatile unsigned long Fill2[6];        /* GAP 0x0138 - 0x014C */
-
-       volatile unsigned long ROMGPIOA;        /* 0x0150 */
-       volatile unsigned long ROMGPIOB;        /* 0x0154 */
-       volatile unsigned long ROMGPIOC;        /* 0x0158 */
-       volatile unsigned long ROMGPIOD;        /* 0x015C */
-
-       volatile unsigned long Fill3[2];        /* GAP 0x0160 - 0x0168 */
-
-       volatile unsigned long AGPIntID;        /* 0x0168 */
-       volatile unsigned long AGPIntClassCode; /* 0x016C */
-       volatile unsigned long AGPIntBIST;      /* 0x0170 */
-       volatile unsigned long AGPIntSSID;      /* 0x0174 */
-       volatile unsigned long AGPIntPMCSR;     /* 0x0178 */
-       volatile unsigned long VGAFrameBufBase; /* 0x017C */
-       volatile unsigned long VGANotify;       /* 0x0180 */
-       volatile unsigned long DACPLLMode;      /* 0x0184 */
-       volatile unsigned long Core1VideoClockDiv;      /* 0x0188 */
-       volatile unsigned long AGPIntStat;      /* 0x018C */
+       volatile u32 Thread0Enable;     /* 0x0000 */
+       volatile u32 Thread1Enable;     /* 0x0004 */
+       volatile u32 Thread0Recover;    /* 0x0008 */
+       volatile u32 Thread1Recover;    /* 0x000C */
+       volatile u32 Thread0Step;       /* 0x0010 */
+       volatile u32 Thread1Step;       /* 0x0014 */
+       volatile u32 VideoInStatus;     /* 0x0018 */
+       volatile u32 Core2InSignStart;  /* 0x001C */
+       volatile u32 Core1ResetVector;  /* 0x0020 */
+       volatile u32 Core1ROMOffset;    /* 0x0024 */
+       volatile u32 Core1ArbiterPriority;      /* 0x0028 */
+       volatile u32 VideoInControl;    /* 0x002C */
+       volatile u32 VideoInReg0CtrlA;  /* 0x0030 */
+       volatile u32 VideoInReg0CtrlB;  /* 0x0034 */
+       volatile u32 VideoInReg1CtrlA;  /* 0x0038 */
+       volatile u32 VideoInReg1CtrlB;  /* 0x003C */
+       volatile u32 Thread0Kicker;     /* 0x0040 */
+       volatile u32 Core2InputSign;    /* 0x0044 */
+       volatile u32 Thread0ProgCtr;    /* 0x0048 */
+       volatile u32 Thread1ProgCtr;    /* 0x004C */
+       volatile u32 Thread1Kicker;     /* 0x0050 */
+       volatile u32 GPRegister1;       /* 0x0054 */
+       volatile u32 GPRegister2;       /* 0x0058 */
+       volatile u32 GPRegister3;       /* 0x005C */
+       volatile u32 GPRegister4;       /* 0x0060 */
+       volatile u32 SerialIntA;        /* 0x0064 */
+
+       volatile u32 Fill0[6];  /* GAP 0x0068 - 0x007C */
+
+       volatile u32 SoftwareReset;     /* 0x0080 */
+       volatile u32 SerialIntB;        /* 0x0084 */
+
+       volatile u32 Fill1[37]; /* GAP 0x0088 - 0x011C */
+
+       volatile u32 ROMELQV;   /* 0x011C */
+       volatile u32 WLWH;      /* 0x0120 */
+       volatile u32 ROMELWL;   /* 0x0124 */
+
+       volatile u32 dwFill_1;  /* GAP 0x0128 */
+
+       volatile u32 IntStatus; /* 0x012C */
+       volatile u32 IntMask;   /* 0x0130 */
+       volatile u32 IntClear;  /* 0x0134 */
+
+       volatile u32 Fill2[6];  /* GAP 0x0138 - 0x014C */
+
+       volatile u32 ROMGPIOA;  /* 0x0150 */
+       volatile u32 ROMGPIOB;  /* 0x0154 */
+       volatile u32 ROMGPIOC;  /* 0x0158 */
+       volatile u32 ROMGPIOD;  /* 0x015C */
+
+       volatile u32 Fill3[2];  /* GAP 0x0160 - 0x0168 */
+
+       volatile u32 AGPIntID;  /* 0x0168 */
+       volatile u32 AGPIntClassCode;   /* 0x016C */
+       volatile u32 AGPIntBIST;        /* 0x0170 */
+       volatile u32 AGPIntSSID;        /* 0x0174 */
+       volatile u32 AGPIntPMCSR;       /* 0x0178 */
+       volatile u32 VGAFrameBufBase;   /* 0x017C */
+       volatile u32 VGANotify; /* 0x0180 */
+       volatile u32 DACPLLMode;        /* 0x0184 */
+       volatile u32 Core1VideoClockDiv;        /* 0x0188 */
+       volatile u32 AGPIntStat;        /* 0x018C */
 
        /*
-          volatile unsigned long Fill4[0x0400/4 - 0x0190/4]; //GAP 0x0190 - 0x0400
-          volatile unsigned long Fill5[0x05FC/4 - 0x0400/4]; //GAP 0x0400 - 0x05FC Fog Table
-          volatile unsigned long Fill6[0x0604/4 - 0x0600/4]; //GAP 0x0600 - 0x0604
-          volatile unsigned long Fill7[0x0680/4 - 0x0608/4]; //GAP 0x0608 - 0x0680
-          volatile unsigned long Fill8[0x07FC/4 - 0x0684/4]; //GAP 0x0684 - 0x07FC
+          volatile u32 Fill4[0x0400/4 - 0x0190/4]; //GAP 0x0190 - 0x0400
+          volatile u32 Fill5[0x05FC/4 - 0x0400/4]; //GAP 0x0400 - 0x05FC Fog Table
+          volatile u32 Fill6[0x0604/4 - 0x0600/4]; //GAP 0x0600 - 0x0604
+          volatile u32 Fill7[0x0680/4 - 0x0608/4]; //GAP 0x0608 - 0x0680
+          volatile u32 Fill8[0x07FC/4 - 0x0684/4]; //GAP 0x0684 - 0x07FC
         */
-       volatile unsigned long Fill4[412];      /* 0x0190 - 0x07FC */
-
-       volatile unsigned long TACtrlStreamBase;        /* 0x0800 */
-       volatile unsigned long TAObjDataBase;   /* 0x0804 */
-       volatile unsigned long TAPtrDataBase;   /* 0x0808 */
-       volatile unsigned long TARegionDataBase;        /* 0x080C */
-       volatile unsigned long TATailPtrBase;   /* 0x0810 */
-       volatile unsigned long TAPtrRegionSize; /* 0x0814 */
-       volatile unsigned long TAConfiguration; /* 0x0818 */
-       volatile unsigned long TAObjDataStartAddr;      /* 0x081C */
-       volatile unsigned long TAObjDataEndAddr;        /* 0x0820 */
-       volatile unsigned long TAXScreenClip;   /* 0x0824 */
-       volatile unsigned long TAYScreenClip;   /* 0x0828 */
-       volatile unsigned long TARHWClamp;      /* 0x082C */
-       volatile unsigned long TARHWCompare;    /* 0x0830 */
-       volatile unsigned long TAStart; /* 0x0834 */
-       volatile unsigned long TAObjReStart;    /* 0x0838 */
-       volatile unsigned long TAPtrReStart;    /* 0x083C */
-       volatile unsigned long TAStatus1;       /* 0x0840 */
-       volatile unsigned long TAStatus2;       /* 0x0844 */
-       volatile unsigned long TAIntStatus;     /* 0x0848 */
-       volatile unsigned long TAIntMask;       /* 0x084C */
-
-       volatile unsigned long Fill5[235];      /* GAP 0x0850 - 0x0BF8 */
-
-       volatile unsigned long TextureAddrThresh;       /* 0x0BFC */
-       volatile unsigned long Core1Translation;        /* 0x0C00 */
-       volatile unsigned long TextureAddrReMap;        /* 0x0C04 */
-       volatile unsigned long RenderOutAGPRemap;       /* 0x0C08 */
-       volatile unsigned long _3DRegionReadTrans;      /* 0x0C0C */
-       volatile unsigned long _3DPtrReadTrans; /* 0x0C10 */
-       volatile unsigned long _3DParamReadTrans;       /* 0x0C14 */
-       volatile unsigned long _3DRegionReadThresh;     /* 0x0C18 */
-       volatile unsigned long _3DPtrReadThresh;        /* 0x0C1C */
-       volatile unsigned long _3DParamReadThresh;      /* 0x0C20 */
-       volatile unsigned long _3DRegionReadAGPRemap;   /* 0x0C24 */
-       volatile unsigned long _3DPtrReadAGPRemap;      /* 0x0C28 */
-       volatile unsigned long _3DParamReadAGPRemap;    /* 0x0C2C */
-       volatile unsigned long ZBufferAGPRemap; /* 0x0C30 */
-       volatile unsigned long TAIndexAGPRemap; /* 0x0C34 */
-       volatile unsigned long TAVertexAGPRemap;        /* 0x0C38 */
-       volatile unsigned long TAUVAddrTrans;   /* 0x0C3C */
-       volatile unsigned long TATailPtrCacheTrans;     /* 0x0C40 */
-       volatile unsigned long TAParamWriteTrans;       /* 0x0C44 */
-       volatile unsigned long TAPtrWriteTrans; /* 0x0C48 */
-       volatile unsigned long TAParamWriteThresh;      /* 0x0C4C */
-       volatile unsigned long TAPtrWriteThresh;        /* 0x0C50 */
-       volatile unsigned long TATailPtrCacheAGPRe;     /* 0x0C54 */
-       volatile unsigned long TAParamWriteAGPRe;       /* 0x0C58 */
-       volatile unsigned long TAPtrWriteAGPRe; /* 0x0C5C */
-       volatile unsigned long SDRAMArbiterConf;        /* 0x0C60 */
-       volatile unsigned long SDRAMConf0;      /* 0x0C64 */
-       volatile unsigned long SDRAMConf1;      /* 0x0C68 */
-       volatile unsigned long SDRAMConf2;      /* 0x0C6C */
-       volatile unsigned long SDRAMRefresh;    /* 0x0C70 */
-       volatile unsigned long SDRAMPowerStat;  /* 0x0C74 */
-
-       volatile unsigned long Fill6[2];        /* GAP 0x0C78 - 0x0C7C */
-
-       volatile unsigned long RAMBistData;     /* 0x0C80 */
-       volatile unsigned long RAMBistCtrl;     /* 0x0C84 */
-       volatile unsigned long FIFOBistKey;     /* 0x0C88 */
-       volatile unsigned long RAMBistResult;   /* 0x0C8C */
-       volatile unsigned long FIFOBistResult;  /* 0x0C90 */
+       volatile u32 Fill4[412];        /* 0x0190 - 0x07FC */
+
+       volatile u32 TACtrlStreamBase;  /* 0x0800 */
+       volatile u32 TAObjDataBase;     /* 0x0804 */
+       volatile u32 TAPtrDataBase;     /* 0x0808 */
+       volatile u32 TARegionDataBase;  /* 0x080C */
+       volatile u32 TATailPtrBase;     /* 0x0810 */
+       volatile u32 TAPtrRegionSize;   /* 0x0814 */
+       volatile u32 TAConfiguration;   /* 0x0818 */
+       volatile u32 TAObjDataStartAddr;        /* 0x081C */
+       volatile u32 TAObjDataEndAddr;  /* 0x0820 */
+       volatile u32 TAXScreenClip;     /* 0x0824 */
+       volatile u32 TAYScreenClip;     /* 0x0828 */
+       volatile u32 TARHWClamp;        /* 0x082C */
+       volatile u32 TARHWCompare;      /* 0x0830 */
+       volatile u32 TAStart;   /* 0x0834 */
+       volatile u32 TAObjReStart;      /* 0x0838 */
+       volatile u32 TAPtrReStart;      /* 0x083C */
+       volatile u32 TAStatus1; /* 0x0840 */
+       volatile u32 TAStatus2; /* 0x0844 */
+       volatile u32 TAIntStatus;       /* 0x0848 */
+       volatile u32 TAIntMask; /* 0x084C */
+
+       volatile u32 Fill5[235];        /* GAP 0x0850 - 0x0BF8 */
+
+       volatile u32 TextureAddrThresh; /* 0x0BFC */
+       volatile u32 Core1Translation;  /* 0x0C00 */
+       volatile u32 TextureAddrReMap;  /* 0x0C04 */
+       volatile u32 RenderOutAGPRemap; /* 0x0C08 */
+       volatile u32 _3DRegionReadTrans;        /* 0x0C0C */
+       volatile u32 _3DPtrReadTrans;   /* 0x0C10 */
+       volatile u32 _3DParamReadTrans; /* 0x0C14 */
+       volatile u32 _3DRegionReadThresh;       /* 0x0C18 */
+       volatile u32 _3DPtrReadThresh;  /* 0x0C1C */
+       volatile u32 _3DParamReadThresh;        /* 0x0C20 */
+       volatile u32 _3DRegionReadAGPRemap;     /* 0x0C24 */
+       volatile u32 _3DPtrReadAGPRemap;        /* 0x0C28 */
+       volatile u32 _3DParamReadAGPRemap;      /* 0x0C2C */
+       volatile u32 ZBufferAGPRemap;   /* 0x0C30 */
+       volatile u32 TAIndexAGPRemap;   /* 0x0C34 */
+       volatile u32 TAVertexAGPRemap;  /* 0x0C38 */
+       volatile u32 TAUVAddrTrans;     /* 0x0C3C */
+       volatile u32 TATailPtrCacheTrans;       /* 0x0C40 */
+       volatile u32 TAParamWriteTrans; /* 0x0C44 */
+       volatile u32 TAPtrWriteTrans;   /* 0x0C48 */
+       volatile u32 TAParamWriteThresh;        /* 0x0C4C */
+       volatile u32 TAPtrWriteThresh;  /* 0x0C50 */
+       volatile u32 TATailPtrCacheAGPRe;       /* 0x0C54 */
+       volatile u32 TAParamWriteAGPRe; /* 0x0C58 */
+       volatile u32 TAPtrWriteAGPRe;   /* 0x0C5C */
+       volatile u32 SDRAMArbiterConf;  /* 0x0C60 */
+       volatile u32 SDRAMConf0;        /* 0x0C64 */
+       volatile u32 SDRAMConf1;        /* 0x0C68 */
+       volatile u32 SDRAMConf2;        /* 0x0C6C */
+       volatile u32 SDRAMRefresh;      /* 0x0C70 */
+       volatile u32 SDRAMPowerStat;    /* 0x0C74 */
+
+       volatile u32 Fill6[2];  /* GAP 0x0C78 - 0x0C7C */
+
+       volatile u32 RAMBistData;       /* 0x0C80 */
+       volatile u32 RAMBistCtrl;       /* 0x0C84 */
+       volatile u32 FIFOBistKey;       /* 0x0C88 */
+       volatile u32 RAMBistResult;     /* 0x0C8C */
+       volatile u32 FIFOBistResult;    /* 0x0C90 */
 
        /*
-          volatile unsigned long Fill11[0x0CBC/4 - 0x0C94/4]; //GAP 0x0C94 - 0x0CBC
-          volatile unsigned long Fill12[0x0CD0/4 - 0x0CC0/4]; //GAP 0x0CC0 - 0x0CD0 3DRegisters
+          volatile u32 Fill11[0x0CBC/4 - 0x0C94/4]; //GAP 0x0C94 - 0x0CBC
+          volatile u32 Fill12[0x0CD0/4 - 0x0CC0/4]; //GAP 0x0CC0 - 0x0CD0 3DRegisters
         */
 
-       volatile unsigned long Fill7[16];       /* 0x0c94 - 0x0cd0 */
+       volatile u32 Fill7[16]; /* 0x0c94 - 0x0cd0 */
 
-       volatile unsigned long SDRAMAddrSign;   /* 0x0CD4 */
-       volatile unsigned long SDRAMDataSign;   /* 0x0CD8 */
-       volatile unsigned long SDRAMSignConf;   /* 0x0CDC */
+       volatile u32 SDRAMAddrSign;     /* 0x0CD4 */
+       volatile u32 SDRAMDataSign;     /* 0x0CD8 */
+       volatile u32 SDRAMSignConf;     /* 0x0CDC */
 
        /* DWFILL; //GAP 0x0CE0 */
-       volatile unsigned long dwFill_2;
-
-       volatile unsigned long ISPSignature;    /* 0x0CE4 */
-
-       volatile unsigned long Fill8[454];      /*GAP 0x0CE8 - 0x13FC */
-
-       volatile unsigned long DACPrimAddress;  /* 0x1400 */
-       volatile unsigned long DACPrimSize;     /* 0x1404 */
-       volatile unsigned long DACCursorAddr;   /* 0x1408 */
-       volatile unsigned long DACCursorCtrl;   /* 0x140C */
-       volatile unsigned long DACOverlayAddr;  /* 0x1410 */
-       volatile unsigned long DACOverlayUAddr; /* 0x1414 */
-       volatile unsigned long DACOverlayVAddr; /* 0x1418 */
-       volatile unsigned long DACOverlaySize;  /* 0x141C */
-       volatile unsigned long DACOverlayVtDec; /* 0x1420 */
-
-       volatile unsigned long Fill9[9];        /* GAP 0x1424 - 0x1444 */
-
-       volatile unsigned long DACVerticalScal; /* 0x1448 */
-       volatile unsigned long DACPixelFormat;  /* 0x144C */
-       volatile unsigned long DACHorizontalScal;       /* 0x1450 */
-       volatile unsigned long DACVidWinStart;  /* 0x1454 */
-       volatile unsigned long DACVidWinEnd;    /* 0x1458 */
-       volatile unsigned long DACBlendCtrl;    /* 0x145C */
-       volatile unsigned long DACHorTim1;      /* 0x1460 */
-       volatile unsigned long DACHorTim2;      /* 0x1464 */
-       volatile unsigned long DACHorTim3;      /* 0x1468 */
-       volatile unsigned long DACVerTim1;      /* 0x146C */
-       volatile unsigned long DACVerTim2;      /* 0x1470 */
-       volatile unsigned long DACVerTim3;      /* 0x1474 */
-       volatile unsigned long DACBorderColor;  /* 0x1478 */
-       volatile unsigned long DACSyncCtrl;     /* 0x147C */
-       volatile unsigned long DACStreamCtrl;   /* 0x1480 */
-       volatile unsigned long DACLUTAddress;   /* 0x1484 */
-       volatile unsigned long DACLUTData;      /* 0x1488 */
-       volatile unsigned long DACBurstCtrl;    /* 0x148C */
-       volatile unsigned long DACCrcTrigger;   /* 0x1490 */
-       volatile unsigned long DACCrcDone;      /* 0x1494 */
-       volatile unsigned long DACCrcResult1;   /* 0x1498 */
-       volatile unsigned long DACCrcResult2;   /* 0x149C */
-       volatile unsigned long DACLinecount;    /* 0x14A0 */
-
-       volatile unsigned long Fill10[151];     /*GAP 0x14A4 - 0x16FC */
-
-       volatile unsigned long DigVidPortCtrl;  /* 0x1700 */
-       volatile unsigned long DigVidPortStat;  /* 0x1704 */
+       volatile u32 dwFill_2;
+
+       volatile u32 ISPSignature;      /* 0x0CE4 */
+
+       volatile u32 Fill8[454];        /*GAP 0x0CE8 - 0x13FC */
+
+       volatile u32 DACPrimAddress;    /* 0x1400 */
+       volatile u32 DACPrimSize;       /* 0x1404 */
+       volatile u32 DACCursorAddr;     /* 0x1408 */
+       volatile u32 DACCursorCtrl;     /* 0x140C */
+       volatile u32 DACOverlayAddr;    /* 0x1410 */
+       volatile u32 DACOverlayUAddr;   /* 0x1414 */
+       volatile u32 DACOverlayVAddr;   /* 0x1418 */
+       volatile u32 DACOverlaySize;    /* 0x141C */
+       volatile u32 DACOverlayVtDec;   /* 0x1420 */
+
+       volatile u32 Fill9[9];  /* GAP 0x1424 - 0x1444 */
+
+       volatile u32 DACVerticalScal;   /* 0x1448 */
+       volatile u32 DACPixelFormat;    /* 0x144C */
+       volatile u32 DACHorizontalScal; /* 0x1450 */
+       volatile u32 DACVidWinStart;    /* 0x1454 */
+       volatile u32 DACVidWinEnd;      /* 0x1458 */
+       volatile u32 DACBlendCtrl;      /* 0x145C */
+       volatile u32 DACHorTim1;        /* 0x1460 */
+       volatile u32 DACHorTim2;        /* 0x1464 */
+       volatile u32 DACHorTim3;        /* 0x1468 */
+       volatile u32 DACVerTim1;        /* 0x146C */
+       volatile u32 DACVerTim2;        /* 0x1470 */
+       volatile u32 DACVerTim3;        /* 0x1474 */
+       volatile u32 DACBorderColor;    /* 0x1478 */
+       volatile u32 DACSyncCtrl;       /* 0x147C */
+       volatile u32 DACStreamCtrl;     /* 0x1480 */
+       volatile u32 DACLUTAddress;     /* 0x1484 */
+       volatile u32 DACLUTData;        /* 0x1488 */
+       volatile u32 DACBurstCtrl;      /* 0x148C */
+       volatile u32 DACCrcTrigger;     /* 0x1490 */
+       volatile u32 DACCrcDone;        /* 0x1494 */
+       volatile u32 DACCrcResult1;     /* 0x1498 */
+       volatile u32 DACCrcResult2;     /* 0x149C */
+       volatile u32 DACLinecount;      /* 0x14A0 */
+
+       volatile u32 Fill10[151];       /*GAP 0x14A4 - 0x16FC */
+
+       volatile u32 DigVidPortCtrl;    /* 0x1700 */
+       volatile u32 DigVidPortStat;    /* 0x1704 */
 
        /*
-          volatile unsigned long Fill11[0x1FFC/4 - 0x1708/4]; //GAP 0x1708 - 0x1FFC
-          volatile unsigned long Fill17[0x3000/4 - 0x2FFC/4]; //GAP 0x2000 - 0x2FFC ALUT
+          volatile u32 Fill11[0x1FFC/4 - 0x1708/4]; //GAP 0x1708 - 0x1FFC
+          volatile u32 Fill17[0x3000/4 - 0x2FFC/4]; //GAP 0x2000 - 0x2FFC ALUT
         */
 
-       volatile unsigned long Fill11[1598];
+       volatile u32 Fill11[1598];
 
        /* DWFILL; //GAP 0x3000          ALUT 256MB offset */
-       volatile unsigned long Fill_3;
+       volatile u32 Fill_3;
 
 } STG4000REG;
 
index 4527cbf0a4ec61c4aca6956bbce7be89aea202e7..b061d709bc44ce78e114908f3e17e2eff54583d4 100644 (file)
@@ -420,7 +420,7 @@ static void mddi_resume(struct msm_mddi_client_data *cdata)
        mddi_set_auto_hibernate(&mddi->client_data, 1);
 }
 
-static int __init mddi_get_client_caps(struct mddi_info *mddi)
+static int __devinit mddi_get_client_caps(struct mddi_info *mddi)
 {
        int i, j;
 
@@ -622,9 +622,9 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg)
 
 static struct mddi_info mddi_info[2];
 
-static int __init mddi_clk_setup(struct platform_device *pdev,
-                                struct mddi_info *mddi,
-                                unsigned long clk_rate)
+static int __devinit mddi_clk_setup(struct platform_device *pdev,
+                                   struct mddi_info *mddi,
+                                   unsigned long clk_rate)
 {
        int ret;
 
index 260cca7ddb41c4da56b9009decb75052e973fbda..26e83d7fdd6feaaaaffacf3b637f34720465355c 100644 (file)
@@ -815,8 +815,15 @@ static int __devinit uvesafb_vbe_init(struct fb_info *info)
        par->pmi_setpal = pmi_setpal;
        par->ypan = ypan;
 
-       if (par->pmi_setpal || par->ypan)
-               uvesafb_vbe_getpmi(task, par);
+       if (par->pmi_setpal || par->ypan) {
+               if (__supported_pte_mask & _PAGE_NX) {
+                       par->pmi_setpal = par->ypan = 0;
+                       printk(KERN_WARNING "uvesafb: NX protection is actively."
+                               "We have better not to use the PMI.\n");
+               } else {
+                       uvesafb_vbe_getpmi(task, par);
+               }
+       }
 #else
        /* The protected mode interface is not available on non-x86. */
        par->pmi_setpal = par->ypan = 0;
index 05f0a80818a2b1c202e2d5104ced13b9802287d0..c2d05a8279fd25c3ca988d354b7335e4102780c0 100644 (file)
 #include <linux/slab.h>
 #include <linux/module.h>
 
+/*
+ * Balloon device works in 4K page units.  So each page is pointed to by
+ * multiple balloon pages.  All memory counters in this driver are in balloon
+ * page units.
+ */
+#define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
+
 struct virtio_balloon
 {
        struct virtio_device *vdev;
@@ -42,8 +49,13 @@ struct virtio_balloon
        /* Waiting for host to ack the pages we released. */
        struct completion acked;
 
-       /* The pages we've told the Host we're not using. */
+       /* Number of balloon pages we've told the Host we're not using. */
        unsigned int num_pages;
+       /*
+        * The pages we've told the Host we're not using.
+        * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE
+        * to num_pages above.
+        */
        struct list_head pages;
 
        /* The array of pfns we tell the Host about. */
@@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page)
 
        BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT);
        /* Convert pfn from Linux page size to balloon page size. */
-       return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT);
+       return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE;
+}
+
+static struct page *balloon_pfn_to_page(u32 pfn)
+{
+       BUG_ON(pfn % VIRTIO_BALLOON_PAGES_PER_PAGE);
+       return pfn_to_page(pfn / VIRTIO_BALLOON_PAGES_PER_PAGE);
 }
 
 static void balloon_ack(struct virtqueue *vq)
@@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
        wait_for_completion(&vb->acked);
 }
 
+static void set_page_pfns(u32 pfns[], struct page *page)
+{
+       unsigned int i;
+
+       /* Set balloon pfns pointing at this page.
+        * Note that the first pfn points at start of the page. */
+       for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
+               pfns[i] = page_to_balloon_pfn(page) + i;
+}
+
 static void fill_balloon(struct virtio_balloon *vb, size_t num)
 {
        /* We can only do one array worth at a time. */
        num = min(num, ARRAY_SIZE(vb->pfns));
 
-       for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
+       for (vb->num_pfns = 0; vb->num_pfns < num;
+            vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
                struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY |
                                        __GFP_NOMEMALLOC | __GFP_NOWARN);
                if (!page) {
@@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
                        msleep(200);
                        break;
                }
-               vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page);
+               set_page_pfns(vb->pfns + vb->num_pfns, page);
+               vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
                totalram_pages--;
-               vb->num_pages++;
                list_add(&page->lru, &vb->pages);
        }
 
@@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
 {
        unsigned int i;
 
-       for (i = 0; i < num; i++) {
-               __free_page(pfn_to_page(pfns[i]));
+       /* Find pfns pointing at start of each page, get pages and free them. */
+       for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
+               __free_page(balloon_pfn_to_page(pfns[i]));
                totalram_pages++;
        }
 }
@@ -143,11 +173,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
        /* We can only do one array worth at a time. */
        num = min(num, ARRAY_SIZE(vb->pfns));
 
-       for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
+       for (vb->num_pfns = 0; vb->num_pfns < num;
+            vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
                page = list_first_entry(&vb->pages, struct page, lru);
                list_del(&page->lru);
-               vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page);
-               vb->num_pages--;
+               set_page_pfns(vb->pfns + vb->num_pfns, page);
+               vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
        }
 
        /*
@@ -234,11 +265,14 @@ static void virtballoon_changed(struct virtio_device *vdev)
 
 static inline s64 towards_target(struct virtio_balloon *vb)
 {
-       u32 v;
+       __le32 v;
+       s64 target;
+
        vb->vdev->config->get(vb->vdev,
                              offsetof(struct virtio_balloon_config, num_pages),
                              &v, sizeof(v));
-       return (s64)v - vb->num_pages;
+       target = le32_to_cpu(v);
+       return target - vb->num_pages;
 }
 
 static void update_balloon_size(struct virtio_balloon *vb)
index cbc7ceef2786d418e81a1ed055c8676ad627253f..9f13b897fd6443bfccff87445bd62bc7145da30c 100644 (file)
@@ -435,16 +435,16 @@ static void hpwdt_start(void)
 {
        reload = SECS_TO_TICKS(soft_margin);
        iowrite16(reload, hpwdt_timer_reg);
-       iowrite16(0x85, hpwdt_timer_con);
+       iowrite8(0x85, hpwdt_timer_con);
 }
 
 static void hpwdt_stop(void)
 {
        unsigned long data;
 
-       data = ioread16(hpwdt_timer_con);
+       data = ioread8(hpwdt_timer_con);
        data &= 0xFE;
-       iowrite16(data, hpwdt_timer_con);
+       iowrite8(data, hpwdt_timer_con);
 }
 
 static void hpwdt_ping(void)
index 4b33acd8ed4ef262bfa43940eab2be7a3deb66f5..0a8a17cd80bea172d767f02609b0164b45fe1717 100644 (file)
@@ -274,7 +274,7 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn)
 
 static bool pirq_check_eoi_map(unsigned irq)
 {
-       return test_bit(irq, pirq_eoi_map);
+       return test_bit(pirq_from_irq(irq), pirq_eoi_map);
 }
 
 static bool pirq_needs_eoi_flag(unsigned irq)
index 99d8151c824adbff0611a16f493dde6e6927de4c..1ffd03bf8e10dcb6b015e3e0b94a2a460f0d0dcd 100644 (file)
@@ -722,7 +722,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
        vma->vm_flags |= VM_RESERVED|VM_DONTEXPAND;
 
        if (use_ptemod)
-               vma->vm_flags |= VM_DONTCOPY|VM_PFNMAP;
+               vma->vm_flags |= VM_DONTCOPY;
 
        vma->vm_private_data = map;
 
index b4d4eac761db6241042e60db3b604caa9150e91e..f100ce20b16b428880863ab768bf952ed84c43a9 100644 (file)
@@ -1029,6 +1029,7 @@ int gnttab_init(void)
        int i;
        unsigned int max_nr_glist_frames, nr_glist_frames;
        unsigned int nr_init_grefs;
+       int ret;
 
        nr_grant_frames = 1;
        boot_max_nr_grant_frames = __max_nr_grant_frames();
@@ -1047,12 +1048,16 @@ int gnttab_init(void)
        nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
        for (i = 0; i < nr_glist_frames; i++) {
                gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
-               if (gnttab_list[i] == NULL)
+               if (gnttab_list[i] == NULL) {
+                       ret = -ENOMEM;
                        goto ini_nomem;
+               }
        }
 
-       if (gnttab_resume() < 0)
-               return -ENODEV;
+       if (gnttab_resume() < 0) {
+               ret = -ENODEV;
+               goto ini_nomem;
+       }
 
        nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
 
@@ -1070,7 +1075,7 @@ int gnttab_init(void)
        for (i--; i >= 0; i--)
                free_page((unsigned long)gnttab_list[i]);
        kfree(gnttab_list);
-       return -ENOMEM;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(gnttab_init);
 
index 9e14ae6cd49c018bf45156d58c1ff4af7411fdc3..412b96cc5305746c20d554b1a6d2c7e55ab09686 100644 (file)
@@ -132,6 +132,7 @@ static void do_suspend(void)
        err = dpm_suspend_end(PMSG_FREEZE);
        if (err) {
                printk(KERN_ERR "dpm_suspend_end failed: %d\n", err);
+               si.cancelled = 0;
                goto out_resume;
        }
 
index 19e6a2041371c0fe9a908c71ac5c83cdbad3c015..1afb4fba11b430b5b7cf0f0b16cd2afa8fb61f08 100644 (file)
@@ -204,7 +204,8 @@ error:
 
 void *
 xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
-                          dma_addr_t *dma_handle, gfp_t flags)
+                          dma_addr_t *dma_handle, gfp_t flags,
+                          struct dma_attrs *attrs)
 {
        void *ret;
        int order = get_order(size);
@@ -253,7 +254,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_alloc_coherent);
 
 void
 xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
-                         dma_addr_t dev_addr)
+                         dma_addr_t dev_addr, struct dma_attrs *attrs)
 {
        int order = get_order(size);
        phys_addr_t phys;
index 174b5653cd8afd7b1ca9190d73e87e9d72f2694b..0b48579a9cd6066c170741913875ebbe716dce0c 100644 (file)
@@ -128,7 +128,10 @@ static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
                        pr_debug("     C%d: %s %d uS\n",
                                 cx->type, cx->desc, (u32)cx->latency);
                }
-       } else
+       } else if (ret != -EINVAL)
+               /* EINVAL means the ACPI ID is incorrect - meaning the ACPI
+                * table is referencing a non-existing CPU - which can happen
+                * with broken ACPI tables. */
                pr_err(DRV_NAME "(CX): Hypervisor error (%d) for ACPI CPU%u\n",
                       ret, _pr->acpi_id);
 
index 63616d7453e6d51989babcfaa643b807edbb1fc4..97f5d264c31ee6f464b92e5b6a2656bff6f00b7f 100644 (file)
@@ -234,7 +234,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
        if (dev_data)
                dev_data->ack_intr = 0;
 
-       return result;
+       return result > 0 ? 0 : result;
 }
 
 static
index f20c5f178b40e27f8d2e9a4fbdf6e2b05dbe9320..a31b54d488398675fc01eaa2878f0a21ec49fe46 100644 (file)
@@ -135,7 +135,7 @@ static int read_backend_details(struct xenbus_device *xendev)
        return xenbus_read_otherend_details(xendev, "backend-id", "backend");
 }
 
-static int is_device_connecting(struct device *dev, void *data)
+static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential)
 {
        struct xenbus_device *xendev = to_xenbus_device(dev);
        struct device_driver *drv = data;
@@ -152,16 +152,41 @@ static int is_device_connecting(struct device *dev, void *data)
        if (drv && (dev->driver != drv))
                return 0;
 
+       if (ignore_nonessential) {
+               /* With older QEMU, for PVonHVM guests the guest config files
+                * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0']
+                * which is nonsensical as there is no PV FB (there can be
+                * a PVKB) running as HVM guest. */
+
+               if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0))
+                       return 0;
+
+               if ((strncmp(xendev->nodename, "device/vfb", 10) == 0))
+                       return 0;
+       }
        xendrv = to_xenbus_driver(dev->driver);
        return (xendev->state < XenbusStateConnected ||
                (xendev->state == XenbusStateConnected &&
                 xendrv->is_ready && !xendrv->is_ready(xendev)));
 }
+static int essential_device_connecting(struct device *dev, void *data)
+{
+       return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */);
+}
+static int non_essential_device_connecting(struct device *dev, void *data)
+{
+       return is_device_connecting(dev, data, false);
+}
 
-static int exists_connecting_device(struct device_driver *drv)
+static int exists_essential_connecting_device(struct device_driver *drv)
 {
        return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
-                               is_device_connecting);
+                               essential_device_connecting);
+}
+static int exists_non_essential_connecting_device(struct device_driver *drv)
+{
+       return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
+                               non_essential_device_connecting);
 }
 
 static int print_device_status(struct device *dev, void *data)
@@ -192,6 +217,23 @@ static int print_device_status(struct device *dev, void *data)
 /* We only wait for device setup after most initcalls have run. */
 static int ready_to_wait_for_devices;
 
+static bool wait_loop(unsigned long start, unsigned int max_delay,
+                    unsigned int *seconds_waited)
+{
+       if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) {
+               if (!*seconds_waited)
+                       printk(KERN_WARNING "XENBUS: Waiting for "
+                              "devices to initialise: ");
+               *seconds_waited += 5;
+               printk("%us...", max_delay - *seconds_waited);
+               if (*seconds_waited == max_delay)
+                       return true;
+       }
+
+       schedule_timeout_interruptible(HZ/10);
+
+       return false;
+}
 /*
  * On a 5-minute timeout, wait for all devices currently configured.  We need
  * to do this to guarantee that the filesystems and / or network devices
@@ -215,19 +257,14 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
        if (!ready_to_wait_for_devices || !xen_domain())
                return;
 
-       while (exists_connecting_device(drv)) {
-               if (time_after(jiffies, start + (seconds_waited+5)*HZ)) {
-                       if (!seconds_waited)
-                               printk(KERN_WARNING "XENBUS: Waiting for "
-                                      "devices to initialise: ");
-                       seconds_waited += 5;
-                       printk("%us...", 300 - seconds_waited);
-                       if (seconds_waited == 300)
-                               break;
-               }
-
-               schedule_timeout_interruptible(HZ/10);
-       }
+       while (exists_non_essential_connecting_device(drv))
+               if (wait_loop(start, 30, &seconds_waited))
+                       break;
+
+       /* Skips PVKB and PVFB check.*/
+       while (exists_essential_connecting_device(drv))
+               if (wait_loop(start, 270, &seconds_waited))
+                       break;
 
        if (seconds_waited)
                printk("\n");
index da887604dfc51929cd4cc17b10a943645b4618ef..67a6db3e1b6f83677009d2323c54dccd38dea63d 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -93,9 +93,8 @@ static void aio_free_ring(struct kioctx *ctx)
                put_page(info->ring_pages[i]);
 
        if (info->mmap_size) {
-               down_write(&ctx->mm->mmap_sem);
-               do_munmap(ctx->mm, info->mmap_base, info->mmap_size);
-               up_write(&ctx->mm->mmap_sem);
+               BUG_ON(ctx->mm != current->mm);
+               vm_munmap(info->mmap_base, info->mmap_size);
        }
 
        if (info->ring_pages && info->ring_pages != info->internal_pages)
@@ -389,6 +388,17 @@ void exit_aio(struct mm_struct *mm)
                                "exit_aio:ioctx still alive: %d %d %d\n",
                                atomic_read(&ctx->users), ctx->dead,
                                ctx->reqs_active);
+               /*
+                * We don't need to bother with munmap() here -
+                * exit_mmap(mm) is coming and it'll unmap everything.
+                * Since aio_free_ring() uses non-zero ->mmap_size
+                * as indicator that it needs to unmap the area,
+                * just set it to 0; aio_free_ring() is the only
+                * place that uses ->mmap_size, so it's safe.
+                * That way we get all munmap done to current->mm -
+                * all other callers have ctx->mm == current->mm.
+                */
+               ctx->ring_info.mmap_size = 0;
                put_ioctx(ctx);
        }
 }
index eb1cc92cd67d26d2966fa1191bb373f646144583..908e18455413fc2e49a4d845c8020007dce95252 100644 (file)
@@ -110,7 +110,6 @@ struct autofs_sb_info {
        int sub_version;
        int min_proto;
        int max_proto;
-       int compat_daemon;
        unsigned long exp_timeout;
        unsigned int type;
        int reghost_enabled;
@@ -270,6 +269,17 @@ int autofs4_fill_super(struct super_block *, void *, int);
 struct autofs_info *autofs4_new_ino(struct autofs_sb_info *);
 void autofs4_clean_ino(struct autofs_info *);
 
+static inline int autofs_prepare_pipe(struct file *pipe)
+{
+       if (!pipe->f_op || !pipe->f_op->write)
+               return -EINVAL;
+       if (!S_ISFIFO(pipe->f_dentry->d_inode->i_mode))
+               return -EINVAL;
+       /* We want a packet pipe */
+       pipe->f_flags |= O_DIRECT;
+       return 0;
+}
+
 /* Queue management functions */
 
 int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
index 9dacb858670107bab207d4378e77d79dd3f25605..aa9103f8f01bf8d3bad8d0dcbcc8036895226e3f 100644 (file)
@@ -376,7 +376,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
                        err = -EBADF;
                        goto out;
                }
-               if (!pipe->f_op || !pipe->f_op->write) {
+               if (autofs_prepare_pipe(pipe) < 0) {
                        err = -EPIPE;
                        fput(pipe);
                        goto out;
@@ -385,7 +385,6 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
                sbi->pipefd = pipefd;
                sbi->pipe = pipe;
                sbi->catatonic = 0;
-               sbi->compat_daemon = is_compat_task();
        }
 out:
        mutex_unlock(&sbi->wq_mutex);
index d8dc002e9cc39d4b15511a6cc6df4d6b8b39897f..6e488ebe7784458623139c91ebd42fbba0752074 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/parser.h>
 #include <linux/bitops.h>
 #include <linux/magic.h>
-#include <linux/compat.h>
 #include "autofs_i.h"
 #include <linux/module.h>
 
@@ -225,7 +224,6 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        set_autofs_type_indirect(&sbi->type);
        sbi->min_proto = 0;
        sbi->max_proto = 0;
-       sbi->compat_daemon = is_compat_task();
        mutex_init(&sbi->wq_mutex);
        mutex_init(&sbi->pipe_mutex);
        spin_lock_init(&sbi->fs_lock);
@@ -292,7 +290,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
                printk("autofs: could not open pipe file descriptor\n");
                goto fail_dput;
        }
-       if (!pipe->f_op || !pipe->f_op->write)
+       if (autofs_prepare_pipe(pipe) < 0)
                goto fail_fput;
        sbi->pipe = pipe;
        sbi->pipefd = pipefd;
index 9c098db433441a36613dd126b8487ed54036f49e..da8876d38a7b7e3a50101f02817cbbbc460cec20 100644 (file)
@@ -91,24 +91,7 @@ static int autofs4_write(struct autofs_sb_info *sbi,
 
        return (bytes > 0);
 }
-
-/*
- * The autofs_v5 packet was misdesigned.
- *
- * The packets are identical on x86-32 and x86-64, but have different
- * alignment. Which means that 'sizeof()' will give different results.
- * Fix it up for the case of running 32-bit user mode on a 64-bit kernel.
- */
-static noinline size_t autofs_v5_packet_size(struct autofs_sb_info *sbi)
-{
-       size_t pktsz = sizeof(struct autofs_v5_packet);
-#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT)
-       if (sbi->compat_daemon > 0)
-               pktsz -= 4;
-#endif
-       return pktsz;
-}
-
+       
 static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                                 struct autofs_wait_queue *wq,
                                 int type)
@@ -172,7 +155,8 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
        {
                struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
 
-               pktsz = autofs_v5_packet_size(sbi);
+               pktsz = sizeof(*packet);
+
                packet->wait_queue_token = wq->wait_queue_token;
                packet->len = wq->name.len;
                memcpy(packet->name, wq->name.name, wq->name.len);
index 2eb12f13593db771987c9c4e7cd30c16515fcf11..d146e181d10df8611050c16745195b9efca62c93 100644 (file)
@@ -50,9 +50,7 @@ static int set_brk(unsigned long start, unsigned long end)
        end = PAGE_ALIGN(end);
        if (end > start) {
                unsigned long addr;
-               down_write(&current->mm->mmap_sem);
-               addr = do_brk(start, end - start);
-               up_write(&current->mm->mmap_sem);
+               addr = vm_brk(start, end - start);
                if (BAD_ADDR(addr))
                        return addr;
        }
@@ -280,9 +278,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                pos = 32;
                map_size = ex.a_text+ex.a_data;
 #endif
-               down_write(&current->mm->mmap_sem);
-               error = do_brk(text_addr & PAGE_MASK, map_size);
-               up_write(&current->mm->mmap_sem);
+               error = vm_brk(text_addr & PAGE_MASK, map_size);
                if (error != (text_addr & PAGE_MASK)) {
                        send_sig(SIGKILL, current, 0);
                        return error;
@@ -313,9 +309,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
                if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
                        loff_t pos = fd_offset;
-                       down_write(&current->mm->mmap_sem);
-                       do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
-                       up_write(&current->mm->mmap_sem);
+                       vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
                        bprm->file->f_op->read(bprm->file,
                                        (char __user *)N_TXTADDR(ex),
                                        ex.a_text+ex.a_data, &pos);
@@ -325,24 +319,20 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        goto beyond_if;
                }
 
-               down_write(&current->mm->mmap_sem);
-               error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
+               error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
                        PROT_READ | PROT_EXEC,
                        MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
                        fd_offset);
-               up_write(&current->mm->mmap_sem);
 
                if (error != N_TXTADDR(ex)) {
                        send_sig(SIGKILL, current, 0);
                        return error;
                }
 
-               down_write(&current->mm->mmap_sem);
-               error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
+               error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
                                PROT_READ | PROT_WRITE | PROT_EXEC,
                                MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
                                fd_offset + ex.a_text);
-               up_write(&current->mm->mmap_sem);
                if (error != N_DATADDR(ex)) {
                        send_sig(SIGKILL, current, 0);
                        return error;
@@ -412,9 +402,7 @@ static int load_aout_library(struct file *file)
                               "N_TXTOFF is not page aligned. Please convert library: %s\n",
                               file->f_path.dentry->d_name.name);
                }
-               down_write(&current->mm->mmap_sem);
-               do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
-               up_write(&current->mm->mmap_sem);
+               vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
                
                file->f_op->read(file, (char __user *)start_addr,
                        ex.a_text + ex.a_data, &pos);
@@ -425,12 +413,10 @@ static int load_aout_library(struct file *file)
                goto out;
        }
        /* Now use mmap to map the library into memory. */
-       down_write(&current->mm->mmap_sem);
-       error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+       error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
                        PROT_READ | PROT_WRITE | PROT_EXEC,
                        MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
                        N_TXTOFF(ex));
-       up_write(&current->mm->mmap_sem);
        retval = error;
        if (error != start_addr)
                goto out;
@@ -438,9 +424,7 @@ static int load_aout_library(struct file *file)
        len = PAGE_ALIGN(ex.a_text + ex.a_data);
        bss = ex.a_text + ex.a_data + ex.a_bss;
        if (bss > len) {
-               down_write(&current->mm->mmap_sem);
-               error = do_brk(start_addr + len, bss - len);
-               up_write(&current->mm->mmap_sem);
+               error = vm_brk(start_addr + len, bss - len);
                retval = error;
                if (error != start_addr + len)
                        goto out;
index 48ffb3dc610a7c9d6ea4428dd441666b4605b2c4..16f7354170725e050e69bf971aeb63eb57598c3e 100644 (file)
@@ -82,9 +82,7 @@ static int set_brk(unsigned long start, unsigned long end)
        end = ELF_PAGEALIGN(end);
        if (end > start) {
                unsigned long addr;
-               down_write(&current->mm->mmap_sem);
-               addr = do_brk(start, end - start);
-               up_write(&current->mm->mmap_sem);
+               addr = vm_brk(start, end - start);
                if (BAD_ADDR(addr))
                        return addr;
        }
@@ -514,9 +512,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
                elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
 
                /* Map the last of the bss segment */
-               down_write(&current->mm->mmap_sem);
-               error = do_brk(elf_bss, last_bss - elf_bss);
-               up_write(&current->mm->mmap_sem);
+               error = vm_brk(elf_bss, last_bss - elf_bss);
                if (BAD_ADDR(error))
                        goto out_close;
        }
@@ -962,10 +958,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                   and some applications "depend" upon this behavior.
                   Since we do not have the power to recompile these, we
                   emulate the SVr4 behavior. Sigh. */
-               down_write(&current->mm->mmap_sem);
-               error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
+               error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
                                MAP_FIXED | MAP_PRIVATE, 0);
-               up_write(&current->mm->mmap_sem);
        }
 
 #ifdef ELF_PLAT_INIT
@@ -1050,8 +1044,7 @@ static int load_elf_library(struct file *file)
                eppnt++;
 
        /* Now use mmap to map the library into memory. */
-       down_write(&current->mm->mmap_sem);
-       error = do_mmap(file,
+       error = vm_mmap(file,
                        ELF_PAGESTART(eppnt->p_vaddr),
                        (eppnt->p_filesz +
                         ELF_PAGEOFFSET(eppnt->p_vaddr)),
@@ -1059,7 +1052,6 @@ static int load_elf_library(struct file *file)
                        MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
                        (eppnt->p_offset -
                         ELF_PAGEOFFSET(eppnt->p_vaddr)));
-       up_write(&current->mm->mmap_sem);
        if (error != ELF_PAGESTART(eppnt->p_vaddr))
                goto out_free_ph;
 
@@ -1072,11 +1064,8 @@ static int load_elf_library(struct file *file)
        len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
                            ELF_MIN_ALIGN - 1);
        bss = eppnt->p_memsz + eppnt->p_vaddr;
-       if (bss > len) {
-               down_write(&current->mm->mmap_sem);
-               do_brk(len, bss - len);
-               up_write(&current->mm->mmap_sem);
-       }
+       if (bss > len)
+               vm_brk(len, bss - len);
        error = 0;
 
 out_free_ph:
index 9bd5612a8224fc5c6374d4dcc27ff99a58ee76e5..d390a0fffc65e1794c1985a2a626a87ed16c124b 100644 (file)
@@ -390,21 +390,17 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
            (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
                stack_prot |= PROT_EXEC;
 
-       down_write(&current->mm->mmap_sem);
-       current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
+       current->mm->start_brk = vm_mmap(NULL, 0, stack_size, stack_prot,
                                         MAP_PRIVATE | MAP_ANONYMOUS |
                                         MAP_UNINITIALIZED | MAP_GROWSDOWN,
                                         0);
 
        if (IS_ERR_VALUE(current->mm->start_brk)) {
-               up_write(&current->mm->mmap_sem);
                retval = current->mm->start_brk;
                current->mm->start_brk = 0;
                goto error_kill;
        }
 
-       up_write(&current->mm->mmap_sem);
-
        current->mm->brk = current->mm->start_brk;
        current->mm->context.end_brk = current->mm->start_brk;
        current->mm->context.end_brk +=
@@ -955,10 +951,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
        if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
                mflags |= MAP_EXECUTABLE;
 
-       down_write(&mm->mmap_sem);
-       maddr = do_mmap(NULL, load_addr, top - base,
+       maddr = vm_mmap(NULL, load_addr, top - base,
                        PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
-       up_write(&mm->mmap_sem);
        if (IS_ERR_VALUE(maddr))
                return (int) maddr;
 
@@ -1096,10 +1090,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
 
                /* create the mapping */
                disp = phdr->p_vaddr & ~PAGE_MASK;
-               down_write(&mm->mmap_sem);
-               maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
+               maddr = vm_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
                                phdr->p_offset - disp);
-               up_write(&mm->mmap_sem);
 
                kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
                       loop, phdr->p_memsz + disp, prot, flags,
@@ -1143,10 +1135,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
                        unsigned long xmaddr;
 
                        flags |= MAP_FIXED | MAP_ANONYMOUS;
-                       down_write(&mm->mmap_sem);
-                       xmaddr = do_mmap(NULL, xaddr, excess - excess1,
+                       xmaddr = vm_mmap(NULL, xaddr, excess - excess1,
                                         prot, flags, 0);
-                       up_write(&mm->mmap_sem);
 
                        kdebug("mmap[%d] <anon>"
                               " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
index 024d20ee3ca3a617e377045fa7cf6d0706a4ed43..6b2daf99fab8bcd91d314f0abd951b8472a092d2 100644 (file)
@@ -542,10 +542,8 @@ static int load_flat_file(struct linux_binprm * bprm,
                 */
                DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
 
-               down_write(&current->mm->mmap_sem);
-               textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
+               textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
                                  MAP_PRIVATE|MAP_EXECUTABLE, 0);
-               up_write(&current->mm->mmap_sem);
                if (!textpos || IS_ERR_VALUE(textpos)) {
                        if (!textpos)
                                textpos = (unsigned long) -ENOMEM;
@@ -556,10 +554,8 @@ static int load_flat_file(struct linux_binprm * bprm,
 
                len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
                len = PAGE_ALIGN(len);
-               down_write(&current->mm->mmap_sem);
-               realdatastart = do_mmap(0, 0, len,
+               realdatastart = vm_mmap(0, 0, len,
                        PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
-               up_write(&current->mm->mmap_sem);
 
                if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
                        if (!realdatastart)
@@ -603,10 +599,8 @@ static int load_flat_file(struct linux_binprm * bprm,
 
                len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
                len = PAGE_ALIGN(len);
-               down_write(&current->mm->mmap_sem);
-               textpos = do_mmap(0, 0, len,
+               textpos = vm_mmap(0, 0, len,
                        PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
-               up_write(&current->mm->mmap_sem);
 
                if (!textpos || IS_ERR_VALUE(textpos)) {
                        if (!textpos)
index e4fc746629a70000dc2ace0aac62038717add3f1..4517aaff61b4b874df51113698524fc20d44578c 100644 (file)
@@ -147,10 +147,8 @@ static int map_som_binary(struct file *file,
        code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize);
        current->mm->start_code = code_start;
        current->mm->end_code = code_start + code_size;
-       down_write(&current->mm->mmap_sem);
-       retval = do_mmap(file, code_start, code_size, prot,
+       retval = vm_mmap(file, code_start, code_size, prot,
                        flags, SOM_PAGESTART(hpuxhdr->exec_tfile));
-       up_write(&current->mm->mmap_sem);
        if (retval < 0 && retval > -1024)
                goto out;
 
@@ -158,20 +156,16 @@ static int map_som_binary(struct file *file,
        data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize);
        current->mm->start_data = data_start;
        current->mm->end_data = bss_start = data_start + data_size;
-       down_write(&current->mm->mmap_sem);
-       retval = do_mmap(file, data_start, data_size,
+       retval = vm_mmap(file, data_start, data_size,
                        prot | PROT_WRITE, flags,
                        SOM_PAGESTART(hpuxhdr->exec_dfile));
-       up_write(&current->mm->mmap_sem);
        if (retval < 0 && retval > -1024)
                goto out;
 
        som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize);
        current->mm->start_brk = current->mm->brk = som_brk;
-       down_write(&current->mm->mmap_sem);
-       retval = do_mmap(NULL, bss_start, som_brk - bss_start,
+       retval = vm_mmap(NULL, bss_start, som_brk - bss_start,
                        prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0);
-       up_write(&current->mm->mmap_sem);
        if (retval > 0 || retval < -1024)
                retval = 0;
 out:
index f4e90748940abf6c1f36f3186177e4640bd24546..bcec06750232e6cc3de09c62648201547709222b 100644 (file)
@@ -22,6 +22,7 @@
 #include "ulist.h"
 #include "transaction.h"
 #include "delayed-ref.h"
+#include "locking.h"
 
 /*
  * this structure records all encountered refs on the way up to the root
@@ -893,18 +894,22 @@ static char *iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
        s64 bytes_left = size - 1;
        struct extent_buffer *eb = eb_in;
        struct btrfs_key found_key;
+       int leave_spinning = path->leave_spinning;
 
        if (bytes_left >= 0)
                dest[bytes_left] = '\0';
 
+       path->leave_spinning = 1;
        while (1) {
                len = btrfs_inode_ref_name_len(eb, iref);
                bytes_left -= len;
                if (bytes_left >= 0)
                        read_extent_buffer(eb, dest + bytes_left,
                                                (unsigned long)(iref + 1), len);
-               if (eb != eb_in)
+               if (eb != eb_in) {
+                       btrfs_tree_read_unlock_blocking(eb);
                        free_extent_buffer(eb);
+               }
                ret = inode_ref_info(parent, 0, fs_root, path, &found_key);
                if (ret > 0)
                        ret = -ENOENT;
@@ -919,8 +924,11 @@ static char *iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                slot = path->slots[0];
                eb = path->nodes[0];
                /* make sure we can use eb after releasing the path */
-               if (eb != eb_in)
+               if (eb != eb_in) {
                        atomic_inc(&eb->refs);
+                       btrfs_tree_read_lock(eb);
+                       btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+               }
                btrfs_release_path(path);
 
                iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
@@ -931,6 +939,7 @@ static char *iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
        }
 
        btrfs_release_path(path);
+       path->leave_spinning = leave_spinning;
 
        if (ret)
                return ERR_PTR(ret);
@@ -1247,7 +1256,7 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
                                struct btrfs_path *path,
                                iterate_irefs_t *iterate, void *ctx)
 {
-       int ret;
+       int ret = 0;
        int slot;
        u32 cur;
        u32 len;
@@ -1259,7 +1268,8 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
        struct btrfs_inode_ref *iref;
        struct btrfs_key found_key;
 
-       while (1) {
+       while (!ret) {
+               path->leave_spinning = 1;
                ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path,
                                        &found_key);
                if (ret < 0)
@@ -1275,6 +1285,8 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
                eb = path->nodes[0];
                /* make sure we can use eb after releasing the path */
                atomic_inc(&eb->refs);
+               btrfs_tree_read_lock(eb);
+               btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
                btrfs_release_path(path);
 
                item = btrfs_item_nr(eb, slot);
@@ -1288,13 +1300,12 @@ static int iterate_irefs(u64 inum, struct btrfs_root *fs_root,
                                 (unsigned long long)found_key.objectid,
                                 (unsigned long long)fs_root->objectid);
                        ret = iterate(parent, iref, eb, ctx);
-                       if (ret) {
-                               free_extent_buffer(eb);
+                       if (ret)
                                break;
-                       }
                        len = sizeof(*iref) + name_len;
                        iref = (struct btrfs_inode_ref *)((char *)iref + len);
                }
+               btrfs_tree_read_unlock_blocking(eb);
                free_extent_buffer(eb);
        }
 
@@ -1414,6 +1425,8 @@ struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
 
 void free_ipath(struct inode_fs_paths *ipath)
 {
+       if (!ipath)
+               return;
        kfree(ipath->fspath);
        kfree(ipath);
 }
index d286b40a56715edbddb68c3ba1e5d4403ab94153..86eff48dab786d525d3395d31dcf3f45a11dafc1 100644 (file)
@@ -405,6 +405,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
                        bio_put(bio);
 
                        bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS);
+                       BUG_ON(!bio);
                        bio->bi_private = cb;
                        bio->bi_end_io = end_compressed_bio_write;
                        bio_add_page(bio, page, PAGE_CACHE_SIZE, 0);
@@ -687,6 +688,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 
                        comp_bio = compressed_bio_alloc(bdev, cur_disk_byte,
                                                        GFP_NOFS);
+                       BUG_ON(!comp_bio);
                        comp_bio->bi_private = cb;
                        comp_bio->bi_end_io = end_compressed_bio_read;
 
index e801f226d7e028b72ca08b5726ed409215c27b84..4106264fbc655ac79b26efa1177384ea92b72988 100644 (file)
@@ -220,10 +220,12 @@ struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root)
  */
 static void add_root_to_dirty_list(struct btrfs_root *root)
 {
+       spin_lock(&root->fs_info->trans_lock);
        if (root->track_dirty && list_empty(&root->dirty_list)) {
                list_add(&root->dirty_list,
                         &root->fs_info->dirty_cowonly_roots);
        }
+       spin_unlock(&root->fs_info->trans_lock);
 }
 
 /*
@@ -723,7 +725,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 
                cur = btrfs_find_tree_block(root, blocknr, blocksize);
                if (cur)
-                       uptodate = btrfs_buffer_uptodate(cur, gen);
+                       uptodate = btrfs_buffer_uptodate(cur, gen, 0);
                else
                        uptodate = 0;
                if (!cur || !uptodate) {
@@ -1358,7 +1360,12 @@ static noinline int reada_for_balance(struct btrfs_root *root,
                block1 = btrfs_node_blockptr(parent, slot - 1);
                gen = btrfs_node_ptr_generation(parent, slot - 1);
                eb = btrfs_find_tree_block(root, block1, blocksize);
-               if (eb && btrfs_buffer_uptodate(eb, gen))
+               /*
+                * if we get -eagain from btrfs_buffer_uptodate, we
+                * don't want to return eagain here.  That will loop
+                * forever
+                */
+               if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
                        block1 = 0;
                free_extent_buffer(eb);
        }
@@ -1366,7 +1373,7 @@ static noinline int reada_for_balance(struct btrfs_root *root,
                block2 = btrfs_node_blockptr(parent, slot + 1);
                gen = btrfs_node_ptr_generation(parent, slot + 1);
                eb = btrfs_find_tree_block(root, block2, blocksize);
-               if (eb && btrfs_buffer_uptodate(eb, gen))
+               if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
                        block2 = 0;
                free_extent_buffer(eb);
        }
@@ -1504,8 +1511,9 @@ read_block_for_search(struct btrfs_trans_handle *trans,
 
        tmp = btrfs_find_tree_block(root, blocknr, blocksize);
        if (tmp) {
-               if (btrfs_buffer_uptodate(tmp, 0)) {
-                       if (btrfs_buffer_uptodate(tmp, gen)) {
+               /* first we do an atomic uptodate check */
+               if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) {
+                       if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
                                /*
                                 * we found an up to date block without
                                 * sleeping, return
@@ -1523,8 +1531,9 @@ read_block_for_search(struct btrfs_trans_handle *trans,
                        free_extent_buffer(tmp);
                        btrfs_set_path_blocking(p);
 
+                       /* now we're allowed to do a blocking uptodate check */
                        tmp = read_tree_block(root, blocknr, blocksize, gen);
-                       if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
+                       if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) {
                                *eb_ret = tmp;
                                return 0;
                        }
@@ -1559,7 +1568,7 @@ read_block_for_search(struct btrfs_trans_handle *trans,
                 * and give up so that our caller doesn't loop forever
                 * on our EAGAINs.
                 */
-               if (!btrfs_buffer_uptodate(tmp, 0))
+               if (!btrfs_buffer_uptodate(tmp, 0, 0))
                        ret = -EIO;
                free_extent_buffer(tmp);
        }
@@ -4043,7 +4052,7 @@ again:
                        tmp = btrfs_find_tree_block(root, blockptr,
                                            btrfs_level_size(root, level - 1));
 
-                       if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
+                       if (tmp && btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
                                free_extent_buffer(tmp);
                                break;
                        }
@@ -4166,7 +4175,8 @@ next:
                                struct extent_buffer *cur;
                                cur = btrfs_find_tree_block(root, blockptr,
                                            btrfs_level_size(root, level - 1));
-                               if (!cur || !btrfs_buffer_uptodate(cur, gen)) {
+                               if (!cur ||
+                                   btrfs_buffer_uptodate(cur, gen, 1) <= 0) {
                                        slot++;
                                        if (cur)
                                                free_extent_buffer(cur);
index 5b8ef8eb35218e0f595ee93069fc1ccab49c6b1e..8fd72331d6008c100e48db1c808566eb382187b2 100644 (file)
@@ -1078,7 +1078,7 @@ struct btrfs_fs_info {
         * is required instead of the faster short fsync log commits
         */
        u64 last_trans_log_full_commit;
-       unsigned long mount_opt:21;
+       unsigned long mount_opt;
        unsigned long compress_type:4;
        u64 max_inline;
        u64 alloc_start;
@@ -2166,7 +2166,7 @@ BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item,
 
 static inline bool btrfs_root_readonly(struct btrfs_root *root)
 {
-       return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY;
+       return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0;
 }
 
 /* struct btrfs_root_backup */
index 20196f41120698f5d7efd7c6be5c56415bd44651..a7ffc88a7dbe4bcc028d3397970275dffcf0492e 100644 (file)
@@ -323,7 +323,8 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
  * in the wrong place.
  */
 static int verify_parent_transid(struct extent_io_tree *io_tree,
-                                struct extent_buffer *eb, u64 parent_transid)
+                                struct extent_buffer *eb, u64 parent_transid,
+                                int atomic)
 {
        struct extent_state *cached_state = NULL;
        int ret;
@@ -331,6 +332,9 @@ static int verify_parent_transid(struct extent_io_tree *io_tree,
        if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
                return 0;
 
+       if (atomic)
+               return -EAGAIN;
+
        lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1,
                         0, &cached_state);
        if (extent_buffer_uptodate(eb) &&
@@ -372,7 +376,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
                ret = read_extent_buffer_pages(io_tree, eb, start,
                                               WAIT_COMPLETE,
                                               btree_get_extent, mirror_num);
-               if (!ret && !verify_parent_transid(io_tree, eb, parent_transid))
+               if (!ret && !verify_parent_transid(io_tree, eb,
+                                                  parent_transid, 0))
                        break;
 
                /*
@@ -383,17 +388,16 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
                if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags))
                        break;
 
-               if (!failed_mirror) {
-                       failed = 1;
-                       printk(KERN_ERR "failed mirror was %d\n", eb->failed_mirror);
-                       failed_mirror = eb->failed_mirror;
-               }
-
                num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
                                              eb->start, eb->len);
                if (num_copies == 1)
                        break;
 
+               if (!failed_mirror) {
+                       failed = 1;
+                       failed_mirror = eb->read_mirror;
+               }
+
                mirror_num++;
                if (mirror_num == failed_mirror)
                        mirror_num++;
@@ -564,7 +568,7 @@ struct extent_buffer *find_eb_for_page(struct extent_io_tree *tree,
 }
 
 static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
-                              struct extent_state *state)
+                              struct extent_state *state, int mirror)
 {
        struct extent_io_tree *tree;
        u64 found_start;
@@ -589,6 +593,7 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
        if (!reads_done)
                goto err;
 
+       eb->read_mirror = mirror;
        if (test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) {
                ret = -EIO;
                goto err;
@@ -652,7 +657,7 @@ static int btree_io_failed_hook(struct page *page, int failed_mirror)
 
        eb = (struct extent_buffer *)page->private;
        set_bit(EXTENT_BUFFER_IOERR, &eb->bflags);
-       eb->failed_mirror = failed_mirror;
+       eb->read_mirror = failed_mirror;
        if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
                btree_readahead_hook(root, eb, eb->start, -EIO);
        return -EIO;    /* we fixed nothing */
@@ -1202,7 +1207,7 @@ static int __must_check find_and_setup_root(struct btrfs_root *tree_root,
        root->commit_root = NULL;
        root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
                                     blocksize, generation);
-       if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) {
+       if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) {
                free_extent_buffer(root->node);
                root->node = NULL;
                return -EIO;
@@ -2254,9 +2259,9 @@ int open_ctree(struct super_block *sb,
                goto fail_sb_buffer;
        }
 
-       if (sectorsize < PAGE_SIZE) {
-               printk(KERN_WARNING "btrfs: Incompatible sector size "
-                      "found on %s\n", sb->s_id);
+       if (sectorsize != PAGE_SIZE) {
+               printk(KERN_WARNING "btrfs: Incompatible sector size(%lu) "
+                      "found on %s\n", (unsigned long)sectorsize, sb->s_id);
                goto fail_sb_buffer;
        }
 
@@ -3143,7 +3148,8 @@ int close_ctree(struct btrfs_root *root)
        return 0;
 }
 
-int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
+int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
+                         int atomic)
 {
        int ret;
        struct inode *btree_inode = buf->pages[0]->mapping->host;
@@ -3153,7 +3159,9 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
                return ret;
 
        ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf,
-                                   parent_transid);
+                                   parent_transid, atomic);
+       if (ret == -EAGAIN)
+               return ret;
        return !ret;
 }
 
index a7ace1a2dd12516a57102e44591f881e922ed89d..ab1830aaf0edbffba6a0cef86d13e9b3f2742cda 100644 (file)
@@ -66,7 +66,8 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr);
 void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr);
 void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
 void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
-int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
+int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
+                         int atomic);
 int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
 int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid);
 u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);
index a84420491c11075093cc2d76f4c080953f9fc55b..49fd7b66d57b272c7aeaea7db4b1bbd0985f8aa2 100644 (file)
@@ -529,9 +529,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
         * allocate blocks for the tree root we can't do the fast caching since
         * we likely hold important locks.
         */
-       if (trans && (!trans->transaction->in_commit) &&
-           (root && root != root->fs_info->tree_root) &&
-           btrfs_test_opt(root, SPACE_CACHE)) {
+       if (fs_info->mount_opt & BTRFS_MOUNT_SPACE_CACHE) {
                ret = load_free_space_cache(fs_info, cache);
 
                spin_lock(&cache->lock);
@@ -2303,6 +2301,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
 
                                if (ret) {
                                        printk(KERN_DEBUG "btrfs: run_delayed_extent_op returned %d\n", ret);
+                                       spin_lock(&delayed_refs->lock);
                                        return ret;
                                }
 
@@ -2333,6 +2332,7 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
 
                if (ret) {
                        printk(KERN_DEBUG "btrfs: run_one_delayed_ref returned %d\n", ret);
+                       spin_lock(&delayed_refs->lock);
                        return ret;
                }
 
@@ -3152,15 +3152,14 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
 /*
  * returns target flags in extended format or 0 if restripe for this
  * chunk_type is not in progress
+ *
+ * should be called with either volume_mutex or balance_lock held
  */
 static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags)
 {
        struct btrfs_balance_control *bctl = fs_info->balance_ctl;
        u64 target = 0;
 
-       BUG_ON(!mutex_is_locked(&fs_info->volume_mutex) &&
-              !spin_is_locked(&fs_info->balance_lock));
-
        if (!bctl)
                return 0;
 
@@ -3772,13 +3771,10 @@ again:
                 */
                if (current->journal_info)
                        return -EAGAIN;
-               ret = wait_event_interruptible(space_info->wait,
-                                              !space_info->flush);
-               /* Must have been interrupted, return */
-               if (ret) {
-                       printk(KERN_DEBUG "btrfs: %s returning -EINTR\n", __func__);
+               ret = wait_event_killable(space_info->wait, !space_info->flush);
+               /* Must have been killed, return */
+               if (ret)
                        return -EINTR;
-               }
 
                spin_lock(&space_info->lock);
        }
@@ -4205,7 +4201,7 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
        num_bytes += div64_u64(data_used + meta_used, 50);
 
        if (num_bytes * 3 > meta_used)
-               num_bytes = div64_u64(meta_used, 3) * 2;
+               num_bytes = div64_u64(meta_used, 3);
 
        return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
 }
@@ -4218,8 +4214,8 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
 
        num_bytes = calc_global_metadata_size(fs_info);
 
-       spin_lock(&block_rsv->lock);
        spin_lock(&sinfo->lock);
+       spin_lock(&block_rsv->lock);
 
        block_rsv->size = num_bytes;
 
@@ -4245,8 +4241,8 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
                block_rsv->full = 1;
        }
 
-       spin_unlock(&sinfo->lock);
        spin_unlock(&block_rsv->lock);
+       spin_unlock(&sinfo->lock);
 }
 
 static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
@@ -6572,7 +6568,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
                        goto skip;
        }
 
-       if (!btrfs_buffer_uptodate(next, generation)) {
+       if (!btrfs_buffer_uptodate(next, generation, 0)) {
                btrfs_tree_unlock(next);
                free_extent_buffer(next);
                next = NULL;
index 8d904dd7ea9f6175012d8abdcf810a7d8d200ae7..c9018a05036e943a52ad91d81019bb4b934b6b9a 100644 (file)
@@ -402,20 +402,28 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
        return 0;
 }
 
+static struct extent_state *next_state(struct extent_state *state)
+{
+       struct rb_node *next = rb_next(&state->rb_node);
+       if (next)
+               return rb_entry(next, struct extent_state, rb_node);
+       else
+               return NULL;
+}
+
 /*
  * utility function to clear some bits in an extent state struct.
- * it will optionally wake up any one waiting on this state (wake == 1), or
- * forcibly remove the state from the tree (delete == 1).
+ * it will optionally wake up any one waiting on this state (wake == 1)
  *
  * If no bits are set on the state struct after clearing things, the
  * struct is freed and removed from the tree
  */
-static int clear_state_bit(struct extent_io_tree *tree,
-                           struct extent_state *state,
-                           int *bits, int wake)
+static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
+                                           struct extent_state *state,
+                                           int *bits, int wake)
 {
+       struct extent_state *next;
        int bits_to_clear = *bits & ~EXTENT_CTLBITS;
-       int ret = state->state & bits_to_clear;
 
        if ((bits_to_clear & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {
                u64 range = state->end - state->start + 1;
@@ -427,6 +435,7 @@ static int clear_state_bit(struct extent_io_tree *tree,
        if (wake)
                wake_up(&state->wq);
        if (state->state == 0) {
+               next = next_state(state);
                if (state->tree) {
                        rb_erase(&state->rb_node, &tree->state);
                        state->tree = NULL;
@@ -436,8 +445,9 @@ static int clear_state_bit(struct extent_io_tree *tree,
                }
        } else {
                merge_state(tree, state);
+               next = next_state(state);
        }
-       return ret;
+       return next;
 }
 
 static struct extent_state *
@@ -476,7 +486,6 @@ int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
        struct extent_state *state;
        struct extent_state *cached;
        struct extent_state *prealloc = NULL;
-       struct rb_node *next_node;
        struct rb_node *node;
        u64 last_end;
        int err;
@@ -528,14 +537,11 @@ hit_next:
        WARN_ON(state->end < start);
        last_end = state->end;
 
-       if (state->end < end && !need_resched())
-               next_node = rb_next(&state->rb_node);
-       else
-               next_node = NULL;
-
        /* the state doesn't have the wanted bits, go ahead */
-       if (!(state->state & bits))
+       if (!(state->state & bits)) {
+               state = next_state(state);
                goto next;
+       }
 
        /*
         *     | ---- desired range ---- |
@@ -593,16 +599,13 @@ hit_next:
                goto out;
        }
 
-       clear_state_bit(tree, state, &bits, wake);
+       state = clear_state_bit(tree, state, &bits, wake);
 next:
        if (last_end == (u64)-1)
                goto out;
        start = last_end + 1;
-       if (start <= end && next_node) {
-               state = rb_entry(next_node, struct extent_state,
-                                rb_node);
+       if (start <= end && state && !need_resched())
                goto hit_next;
-       }
        goto search_again;
 
 out:
@@ -1937,7 +1940,7 @@ int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb,
        struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
        u64 start = eb->start;
        unsigned long i, num_pages = num_extent_pages(eb->start, eb->len);
-       int ret;
+       int ret = 0;
 
        for (i = 0; i < num_pages; i++) {
                struct page *p = extent_buffer_page(eb, i);
@@ -2180,6 +2183,10 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page,
        }
 
        bio = bio_alloc(GFP_NOFS, 1);
+       if (!bio) {
+               free_io_failure(inode, failrec, 0);
+               return -EIO;
+       }
        bio->bi_private = state;
        bio->bi_end_io = failed_bio->bi_end_io;
        bio->bi_sector = failrec->logical >> 9;
@@ -2297,7 +2304,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
        u64 start;
        u64 end;
        int whole_page;
-       int failed_mirror;
+       int mirror;
        int ret;
 
        if (err)
@@ -2336,20 +2343,18 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                }
                spin_unlock(&tree->lock);
 
+               mirror = (int)(unsigned long)bio->bi_bdev;
                if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {
                        ret = tree->ops->readpage_end_io_hook(page, start, end,
-                                                             state);
+                                                             state, mirror);
                        if (ret)
                                uptodate = 0;
                        else
                                clean_io_failure(start, page);
                }
 
-               if (!uptodate)
-                       failed_mirror = (int)(unsigned long)bio->bi_bdev;
-
                if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) {
-                       ret = tree->ops->readpage_io_failed_hook(page, failed_mirror);
+                       ret = tree->ops->readpage_io_failed_hook(page, mirror);
                        if (!ret && !err &&
                            test_bit(BIO_UPTODATE, &bio->bi_flags))
                                uptodate = 1;
@@ -2364,8 +2369,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                         * can't handle the error it will return -EIO and we
                         * remain responsible for that page.
                         */
-                       ret = bio_readpage_error(bio, page, start, end,
-                                                       failed_mirror, NULL);
+                       ret = bio_readpage_error(bio, page, start, end, mirror, NULL);
                        if (ret == 0) {
                                uptodate =
                                        test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -4116,6 +4120,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
                        if (atomic_inc_not_zero(&exists->refs)) {
                                spin_unlock(&mapping->private_lock);
                                unlock_page(p);
+                               page_cache_release(p);
                                mark_extent_buffer_accessed(exists);
                                goto free_eb;
                        }
@@ -4195,8 +4200,7 @@ free_eb:
                        unlock_page(eb->pages[i]);
        }
 
-       if (!atomic_dec_and_test(&eb->refs))
-               return exists;
+       WARN_ON(!atomic_dec_and_test(&eb->refs));
        btrfs_release_extent_buffer(eb);
        return exists;
 }
@@ -4458,7 +4462,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
        }
 
        clear_bit(EXTENT_BUFFER_IOERR, &eb->bflags);
-       eb->failed_mirror = 0;
+       eb->read_mirror = 0;
        atomic_set(&eb->io_pages, num_reads);
        for (i = start_i; i < num_pages; i++) {
                page = extent_buffer_page(eb, i);
index faf10eb57f75eb29edf1a8fb42468fb7924b666a..b516c3b8dec68d825e380a1930976f34c8a3e1a4 100644 (file)
@@ -79,7 +79,7 @@ struct extent_io_ops {
                                        u64 start, u64 end,
                                       struct extent_state *state);
        int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end,
-                                   struct extent_state *state);
+                                   struct extent_state *state, int mirror);
        int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end,
                                      struct extent_state *state, int uptodate);
        void (*set_bit_hook)(struct inode *inode, struct extent_state *state,
@@ -135,7 +135,7 @@ struct extent_buffer {
        spinlock_t refs_lock;
        atomic_t refs;
        atomic_t io_pages;
-       int failed_mirror;
+       int read_mirror;
        struct list_head leak_list;
        struct rcu_head rcu_head;
        pid_t lock_owner;
index d83260d7498fe2b535a59069ebba7c3ae78e255e..53bf2d764bbc4f5814db04710d3123d03c3779ba 100644 (file)
@@ -567,6 +567,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
        int extent_type;
        int recow;
        int ret;
+       int modify_tree = -1;
 
        if (drop_cache)
                btrfs_drop_extent_cache(inode, start, end - 1, 0);
@@ -575,10 +576,13 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
        if (!path)
                return -ENOMEM;
 
+       if (start >= BTRFS_I(inode)->disk_i_size)
+               modify_tree = 0;
+
        while (1) {
                recow = 0;
                ret = btrfs_lookup_file_extent(trans, root, path, ino,
-                                              search_start, -1);
+                                              search_start, modify_tree);
                if (ret < 0)
                        break;
                if (ret > 0 && path->slots[0] > 0 && search_start == start) {
@@ -634,7 +638,8 @@ next_slot:
                }
 
                search_start = max(key.offset, start);
-               if (recow) {
+               if (recow || !modify_tree) {
+                       modify_tree = -1;
                        btrfs_release_path(path);
                        continue;
                }
index e88330d3df52f259b42e3fc5e0f865befd172e20..202008ec367d4c4c2cfcf73f7289692dd910b25c 100644 (file)
@@ -747,13 +747,6 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
        bool matched;
        u64 used = btrfs_block_group_used(&block_group->item);
 
-       /*
-        * If we're unmounting then just return, since this does a search on the
-        * normal root and not the commit root and we could deadlock.
-        */
-       if (btrfs_fs_closing(fs_info))
-               return 0;
-
        /*
         * If this block group has been marked to be cleared for one reason or
         * another then we can't trust the on disk cache, so just return.
@@ -768,6 +761,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
        path = btrfs_alloc_path();
        if (!path)
                return 0;
+       path->search_commit_root = 1;
+       path->skip_locking = 1;
 
        inode = lookup_free_space_inode(root, block_group, path);
        if (IS_ERR(inode)) {
index 115bc05e42b06fee05ef7551cef1ad4174557634..61b16c641ce0975fcbd302fc6156820233c15c93 100644 (file)
@@ -1947,7 +1947,7 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
  * extent_io.c will try to find good copies for us.
  */
 static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
-                              struct extent_state *state)
+                              struct extent_state *state, int mirror)
 {
        size_t offset = start - ((u64)page->index << PAGE_CACHE_SHIFT);
        struct inode *inode = page->mapping->host;
@@ -4069,7 +4069,7 @@ static struct inode *new_simple_dir(struct super_block *s,
        BTRFS_I(inode)->dummy_inode = 1;
 
        inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID;
-       inode->i_op = &simple_dir_inode_operations;
+       inode->i_op = &btrfs_dir_ro_inode_operations;
        inode->i_fop = &simple_dir_operations;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
@@ -4140,14 +4140,18 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
 static int btrfs_dentry_delete(const struct dentry *dentry)
 {
        struct btrfs_root *root;
+       struct inode *inode = dentry->d_inode;
 
-       if (!dentry->d_inode && !IS_ROOT(dentry))
-               dentry = dentry->d_parent;
+       if (!inode && !IS_ROOT(dentry))
+               inode = dentry->d_parent->d_inode;
 
-       if (dentry->d_inode) {
-               root = BTRFS_I(dentry->d_inode)->root;
+       if (inode) {
+               root = BTRFS_I(inode)->root;
                if (btrfs_root_refs(&root->root_item) == 0)
                        return 1;
+
+               if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
+                       return 1;
        }
        return 0;
 }
@@ -4188,7 +4192,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
        struct btrfs_path *path;
        struct list_head ins_list;
        struct list_head del_list;
-       struct qstr q;
        int ret;
        struct extent_buffer *leaf;
        int slot;
@@ -4279,7 +4282,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
 
                while (di_cur < di_total) {
                        struct btrfs_key location;
-                       struct dentry *tmp;
 
                        if (verify_dir_item(root, leaf, di))
                                break;
@@ -4300,35 +4302,15 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
                        d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
                        btrfs_dir_item_key_to_cpu(leaf, di, &location);
 
-                       q.name = name_ptr;
-                       q.len = name_len;
-                       q.hash = full_name_hash(q.name, q.len);
-                       tmp = d_lookup(filp->f_dentry, &q);
-                       if (!tmp) {
-                               struct btrfs_key *newkey;
-
-                               newkey = kzalloc(sizeof(struct btrfs_key),
-                                                GFP_NOFS);
-                               if (!newkey)
-                                       goto no_dentry;
-                               tmp = d_alloc(filp->f_dentry, &q);
-                               if (!tmp) {
-                                       kfree(newkey);
-                                       dput(tmp);
-                                       goto no_dentry;
-                               }
-                               memcpy(newkey, &location,
-                                      sizeof(struct btrfs_key));
-                               tmp->d_fsdata = newkey;
-                               tmp->d_flags |= DCACHE_NEED_LOOKUP;
-                               d_rehash(tmp);
-                               dput(tmp);
-                       } else {
-                               dput(tmp);
-                       }
-no_dentry:
+
                        /* is this a reference to our own snapshot? If so
-                        * skip it
+                        * skip it.
+                        *
+                        * In contrast to old kernels, we insert the snapshot's
+                        * dir item and dir index after it has been created, so
+                        * we won't find a reference to our own snapshot. We
+                        * still keep the following code for backward
+                        * compatibility.
                         */
                        if (location.type == BTRFS_ROOT_ITEM_KEY &&
                            location.objectid == root->root_key.objectid) {
index 18cc23d164a80b7ccc717a83499214b81f395896..14f8e1faa46ee0478ebb83d6f82d205d25c1dc51 100644 (file)
@@ -2262,7 +2262,10 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg)
        di_args->bytes_used = dev->bytes_used;
        di_args->total_bytes = dev->total_bytes;
        memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
-       strncpy(di_args->path, dev->name, sizeof(di_args->path));
+       if (dev->name)
+               strncpy(di_args->path, dev->name, sizeof(di_args->path));
+       else
+               di_args->path[0] = '\0';
 
 out:
        if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args)))
index 4f69028a68c486268bf5bcfc097a5412dbdd2ad0..086e6bdae1c4482b93b6dda4d16b1c5af288f2eb 100644 (file)
@@ -252,7 +252,7 @@ struct btrfs_data_container {
 
 struct btrfs_ioctl_ino_path_args {
        __u64                           inum;           /* in */
-       __u32                           size;           /* in */
+       __u64                           size;           /* in */
        __u64                           reserved[4];
        /* struct btrfs_data_container  *fspath;           out */
        __u64                           fspath;         /* out */
@@ -260,7 +260,7 @@ struct btrfs_ioctl_ino_path_args {
 
 struct btrfs_ioctl_logical_ino_args {
        __u64                           logical;        /* in */
-       __u32                           size;           /* in */
+       __u64                           size;           /* in */
        __u64                           reserved[4];
        /* struct btrfs_data_container  *inodes;        out   */
        __u64                           inodes;
index dc5d33146fdbb9f4fb3cf899d78a97ca361b6ac8..ac5d010858848d007e380d529476ad9eb4f6fb31 100644 (file)
@@ -250,14 +250,12 @@ static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info,
                                          struct btrfs_bio *bbio)
 {
        int ret;
-       int looped = 0;
        struct reada_zone *zone;
        struct btrfs_block_group_cache *cache = NULL;
        u64 start;
        u64 end;
        int i;
 
-again:
        zone = NULL;
        spin_lock(&fs_info->reada_lock);
        ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone,
@@ -274,9 +272,6 @@ again:
                spin_unlock(&fs_info->reada_lock);
        }
 
-       if (looped)
-               return NULL;
-
        cache = btrfs_lookup_block_group(fs_info, logical);
        if (!cache)
                return NULL;
@@ -307,13 +302,15 @@ again:
        ret = radix_tree_insert(&dev->reada_zones,
                                (unsigned long)(zone->end >> PAGE_CACHE_SHIFT),
                                zone);
-       spin_unlock(&fs_info->reada_lock);
 
-       if (ret) {
+       if (ret == -EEXIST) {
                kfree(zone);
-               looped = 1;
-               goto again;
+               ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone,
+                                            logical >> PAGE_CACHE_SHIFT, 1);
+               if (ret == 1)
+                       kref_get(&zone->refcnt);
        }
+       spin_unlock(&fs_info->reada_lock);
 
        return zone;
 }
@@ -323,26 +320,26 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
                                              struct btrfs_key *top, int level)
 {
        int ret;
-       int looped = 0;
        struct reada_extent *re = NULL;
+       struct reada_extent *re_exist = NULL;
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
        struct btrfs_bio *bbio = NULL;
        struct btrfs_device *dev;
+       struct btrfs_device *prev_dev;
        u32 blocksize;
        u64 length;
        int nzones = 0;
        int i;
        unsigned long index = logical >> PAGE_CACHE_SHIFT;
 
-again:
        spin_lock(&fs_info->reada_lock);
        re = radix_tree_lookup(&fs_info->reada_tree, index);
        if (re)
                kref_get(&re->refcnt);
        spin_unlock(&fs_info->reada_lock);
 
-       if (re || looped)
+       if (re)
                return re;
 
        re = kzalloc(sizeof(*re), GFP_NOFS);
@@ -398,16 +395,31 @@ again:
        /* insert extent in reada_tree + all per-device trees, all or nothing */
        spin_lock(&fs_info->reada_lock);
        ret = radix_tree_insert(&fs_info->reada_tree, index, re);
+       if (ret == -EEXIST) {
+               re_exist = radix_tree_lookup(&fs_info->reada_tree, index);
+               BUG_ON(!re_exist);
+               kref_get(&re_exist->refcnt);
+               spin_unlock(&fs_info->reada_lock);
+               goto error;
+       }
        if (ret) {
                spin_unlock(&fs_info->reada_lock);
-               if (ret != -ENOMEM) {
-                       /* someone inserted the extent in the meantime */
-                       looped = 1;
-               }
                goto error;
        }
+       prev_dev = NULL;
        for (i = 0; i < nzones; ++i) {
                dev = bbio->stripes[i].dev;
+               if (dev == prev_dev) {
+                       /*
+                        * in case of DUP, just add the first zone. As both
+                        * are on the same device, there's nothing to gain
+                        * from adding both.
+                        * Also, it wouldn't work, as the tree is per device
+                        * and adding would fail with EEXIST
+                        */
+                       continue;
+               }
+               prev_dev = dev;
                ret = radix_tree_insert(&dev->reada_extents, index, re);
                if (ret) {
                        while (--i >= 0) {
@@ -450,9 +462,7 @@ error:
        }
        kfree(bbio);
        kfree(re);
-       if (looped)
-               goto again;
-       return NULL;
+       return re_exist;
 }
 
 static void reada_kref_dummy(struct kref *kr)
index 017281dbb2a71f6a0c51f4f8cc52cf9e651f2fd0..646ee21bb035d9ad8a4b1628e6883544c0603ea6 100644 (file)
@@ -1279,7 +1279,9 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
                if (rb_node)
                        backref_tree_panic(rb_node, -EEXIST, node->bytenr);
        } else {
+               spin_lock(&root->fs_info->trans_lock);
                list_del_init(&root->root_list);
+               spin_unlock(&root->fs_info->trans_lock);
                kfree(node);
        }
        return 0;
@@ -3811,7 +3813,7 @@ restart:
 
                ret = btrfs_block_rsv_check(rc->extent_root, rc->block_rsv, 5);
                if (ret < 0) {
-                       if (ret != -EAGAIN) {
+                       if (ret != -ENOSPC) {
                                err = ret;
                                WARN_ON(1);
                                break;
index 90acc82046c3ab80b459ff076ced3e97ea4b0e3c..2f3d6f917fb3373c02335b6912fcba1006f5fabe 100644 (file)
@@ -998,6 +998,7 @@ static int scrub_setup_recheck_block(struct scrub_dev *sdev,
                        page = sblock->pagev + page_index;
                        page->logical = logical;
                        page->physical = bbio->stripes[mirror_index].physical;
+                       /* for missing devices, bdev is NULL */
                        page->bdev = bbio->stripes[mirror_index].dev->bdev;
                        page->mirror_num = mirror_index + 1;
                        page->page = alloc_page(GFP_NOFS);
@@ -1042,8 +1043,16 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
                struct scrub_page *page = sblock->pagev + page_num;
                DECLARE_COMPLETION_ONSTACK(complete);
 
+               if (page->bdev == NULL) {
+                       page->io_error = 1;
+                       sblock->no_io_error_seen = 0;
+                       continue;
+               }
+
                BUG_ON(!page->page);
                bio = bio_alloc(GFP_NOFS, 1);
+               if (!bio)
+                       return -EIO;
                bio->bi_bdev = page->bdev;
                bio->bi_sector = page->physical >> 9;
                bio->bi_end_io = scrub_complete_bio_end_io;
@@ -1171,6 +1180,8 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
                DECLARE_COMPLETION_ONSTACK(complete);
 
                bio = bio_alloc(GFP_NOFS, 1);
+               if (!bio)
+                       return -EIO;
                bio->bi_bdev = page_bad->bdev;
                bio->bi_sector = page_bad->physical >> 9;
                bio->bi_end_io = scrub_complete_bio_end_io;
@@ -1253,12 +1264,6 @@ static int scrub_checksum_data(struct scrub_block *sblock)
        if (memcmp(csum, on_disk_csum, sdev->csum_size))
                fail = 1;
 
-       if (fail) {
-               spin_lock(&sdev->stat_lock);
-               ++sdev->stat.csum_errors;
-               spin_unlock(&sdev->stat_lock);
-       }
-
        return fail;
 }
 
@@ -1331,15 +1336,6 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock)
        if (memcmp(calculated_csum, on_disk_csum, sdev->csum_size))
                ++crc_fail;
 
-       if (crc_fail || fail) {
-               spin_lock(&sdev->stat_lock);
-               if (crc_fail)
-                       ++sdev->stat.csum_errors;
-               if (fail)
-                       ++sdev->stat.verify_errors;
-               spin_unlock(&sdev->stat_lock);
-       }
-
        return fail || crc_fail;
 }
 
index 8d5d380f7bdb8a81b576c51ac487ccc492051d2f..c5f8fca4195fca9eb3806ebfbccf52d03049691e 100644 (file)
@@ -815,7 +815,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
                return 0;
        }
 
-       btrfs_start_delalloc_inodes(root, 0);
        btrfs_wait_ordered_extents(root, 0, 0);
 
        trans = btrfs_start_transaction(root, 0);
@@ -1148,13 +1147,15 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                if (ret)
                        goto restore;
        } else {
-               if (fs_info->fs_devices->rw_devices == 0)
+               if (fs_info->fs_devices->rw_devices == 0) {
                        ret = -EACCES;
                        goto restore;
+               }
 
-               if (btrfs_super_log_root(fs_info->super_copy) != 0)
+               if (btrfs_super_log_root(fs_info->super_copy) != 0) {
                        ret = -EINVAL;
                        goto restore;
+               }
 
                ret = btrfs_cleanup_fs_roots(fs_info);
                if (ret)
index 8da29e8e4de15999397f137825bb378c2e983ede..36422254ef6765c14290a2373fa6d83cf2d364d5 100644 (file)
@@ -73,8 +73,10 @@ loop:
 
        cur_trans = root->fs_info->running_transaction;
        if (cur_trans) {
-               if (cur_trans->aborted)
+               if (cur_trans->aborted) {
+                       spin_unlock(&root->fs_info->trans_lock);
                        return cur_trans->aborted;
+               }
                atomic_inc(&cur_trans->use_count);
                atomic_inc(&cur_trans->num_writers);
                cur_trans->num_joined++;
@@ -480,6 +482,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
        struct btrfs_transaction *cur_trans = trans->transaction;
        struct btrfs_fs_info *info = root->fs_info;
        int count = 0;
+       int err = 0;
 
        if (--trans->use_count) {
                trans->block_rsv = trans->orig_rsv;
@@ -532,18 +535,18 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        if (current->journal_info == trans)
                current->journal_info = NULL;
-       memset(trans, 0, sizeof(*trans));
-       kmem_cache_free(btrfs_trans_handle_cachep, trans);
 
        if (throttle)
                btrfs_run_delayed_iputs(root);
 
        if (trans->aborted ||
            root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
-               return -EIO;
+               err = -EIO;
        }
 
-       return 0;
+       memset(trans, 0, sizeof(*trans));
+       kmem_cache_free(btrfs_trans_handle_cachep, trans);
+       return err;
 }
 
 int btrfs_end_transaction(struct btrfs_trans_handle *trans,
@@ -1399,6 +1402,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        ret = commit_fs_roots(trans, root);
        if (ret) {
                mutex_unlock(&root->fs_info->tree_log_mutex);
+               mutex_unlock(&root->fs_info->reloc_mutex);
                goto cleanup_transaction;
        }
 
@@ -1410,6 +1414,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        ret = commit_cowonly_roots(trans, root);
        if (ret) {
                mutex_unlock(&root->fs_info->tree_log_mutex);
+               mutex_unlock(&root->fs_info->reloc_mutex);
                goto cleanup_transaction;
        }
 
index d017283ae6f56fa8ea0ba1eeaa04077d443eb0fb..eb1ae908582cc51162a61798c80f3ed38e7ab6e8 100644 (file)
@@ -279,7 +279,7 @@ static int process_one_buffer(struct btrfs_root *log,
                                                log->fs_info->extent_root,
                                                eb->start, eb->len);
 
-       if (btrfs_buffer_uptodate(eb, gen)) {
+       if (btrfs_buffer_uptodate(eb, gen, 0)) {
                if (wc->write)
                        btrfs_write_tree_block(eb);
                if (wc->wait)
index a872b48be0ae15fd77eff56e2c529470ddde0b7f..1411b99555a4c1f138a6a3bf699842849d2b3e08 100644 (file)
@@ -3324,12 +3324,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        stripe_size = devices_info[ndevs-1].max_avail;
        num_stripes = ndevs * dev_stripes;
 
-       if (stripe_size * num_stripes > max_chunk_size * ncopies) {
+       if (stripe_size * ndevs > max_chunk_size * ncopies) {
                stripe_size = max_chunk_size * ncopies;
-               do_div(stripe_size, num_stripes);
+               do_div(stripe_size, ndevs);
        }
 
        do_div(stripe_size, dev_stripes);
+
+       /* align to BTRFS_STRIPE_LEN */
        do_div(stripe_size, BTRFS_STRIPE_LEN);
        stripe_size *= BTRFS_STRIPE_LEN;
 
@@ -3805,10 +3807,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
                else if (mirror_num)
                        stripe_index += mirror_num - 1;
                else {
+                       int old_stripe_index = stripe_index;
                        stripe_index = find_live_mirror(map, stripe_index,
                                              map->sub_stripes, stripe_index +
                                              current->pid % map->sub_stripes);
-                       mirror_num = stripe_index + 1;
+                       mirror_num = stripe_index - old_stripe_index + 1;
                }
        } else {
                /*
@@ -3833,6 +3836,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
                int sub_stripes = 0;
                u64 stripes_per_dev = 0;
                u32 remaining_stripes = 0;
+               u32 last_stripe = 0;
 
                if (map->type &
                    (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) {
@@ -3846,6 +3850,8 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
                                                      stripe_nr_orig,
                                                      factor,
                                                      &remaining_stripes);
+                       div_u64_rem(stripe_nr_end - 1, factor, &last_stripe);
+                       last_stripe *= sub_stripes;
                }
 
                for (i = 0; i < num_stripes; i++) {
@@ -3858,16 +3864,29 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
                                         BTRFS_BLOCK_GROUP_RAID10)) {
                                bbio->stripes[i].length = stripes_per_dev *
                                                          map->stripe_len;
+
                                if (i / sub_stripes < remaining_stripes)
                                        bbio->stripes[i].length +=
                                                map->stripe_len;
+
+                               /*
+                                * Special for the first stripe and
+                                * the last stripe:
+                                *
+                                * |-------|...|-------|
+                                *     |----------|
+                                *    off     end_off
+                                */
                                if (i < sub_stripes)
                                        bbio->stripes[i].length -=
                                                stripe_offset;
-                               if ((i / sub_stripes + 1) %
-                                   sub_stripes == remaining_stripes)
+
+                               if (stripe_index >= last_stripe &&
+                                   stripe_index <= (last_stripe +
+                                                    sub_stripes - 1))
                                        bbio->stripes[i].length -=
                                                stripe_end_offset;
+
                                if (i == sub_stripes - 1)
                                        stripe_offset = 0;
                        } else
@@ -4334,8 +4353,10 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
 
        ret = __btrfs_open_devices(fs_devices, FMODE_READ,
                                   root->fs_info->bdev_holder);
-       if (ret)
+       if (ret) {
+               free_fs_devices(fs_devices);
                goto out;
+       }
 
        if (!fs_devices->seeding) {
                __btrfs_close_devices(fs_devices);
index 36d66653b93191c9c13c21e74dea6f511a6ac9ab..351e18ea2e53a911abcab29f57325a4f31ded786 100644 (file)
@@ -985,7 +985,6 @@ grow_dev_page(struct block_device *bdev, sector_t block,
        return page;
 
 failed:
-       BUG();
        unlock_page(page);
        page_cache_release(page);
        return NULL;
index d34212822444221d8698b716bc817857ab577f5d..ca6a3796a33bb0640b6444891713196834340eb4 100644 (file)
@@ -370,13 +370,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
                                   (int)(srcaddr->sa_family));
        }
 
-       seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
+       seq_printf(s, ",uid=%u", cifs_sb->mnt_uid);
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
                seq_printf(s, ",forceuid");
        else
                seq_printf(s, ",noforceuid");
 
-       seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
+       seq_printf(s, ",gid=%u", cifs_sb->mnt_gid);
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
                seq_printf(s, ",forcegid");
        else
@@ -434,11 +434,15 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
                seq_printf(s, ",noperm");
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
                seq_printf(s, ",strictcache");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
+               seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
+               seq_printf(s, ",backupgid=%u", cifs_sb->mnt_backupgid);
 
-       seq_printf(s, ",rsize=%d", cifs_sb->rsize);
-       seq_printf(s, ",wsize=%d", cifs_sb->wsize);
+       seq_printf(s, ",rsize=%u", cifs_sb->rsize);
+       seq_printf(s, ",wsize=%u", cifs_sb->wsize);
        /* convert actimeo and display it in seconds */
-               seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
+       seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
 
        return 0;
 }
index d1389bb33ceb98ffdc068b1192dad4f1d2b3f425..65365358c9766dcd2882ab643805565e552f4e25 100644 (file)
@@ -125,5 +125,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "1.77"
+#define CIFS_VERSION   "1.78"
 #endif                         /* _CIFSFS_H */
index 8fecc99be34443d7368f88b4db63984b8d4f3f53..da2f5446fa7ae3d3bbba6bb1b7a92cd1cc8743e4 100644 (file)
@@ -3892,13 +3892,12 @@ CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
        int rc = 0;
        int bytes_returned = 0;
        SET_SEC_DESC_REQ *pSMB = NULL;
-       NTRANSACT_RSP *pSMBr = NULL;
+       void *pSMBr;
 
 setCifsAclRetry:
-       rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
-                       (void **) &pSMBr);
+       rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
        if (rc)
-                       return (rc);
+               return rc;
 
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
@@ -3926,9 +3925,8 @@ setCifsAclRetry:
        pSMB->AclFlags = cpu_to_le32(aclflag);
 
        if (pntsd && acllen) {
-               memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
-                       (char *) pntsd,
-                       acllen);
+               memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
+                               data_offset, pntsd, acllen);
                inc_rfc1001_len(pSMB, byte_count + data_count);
        } else
                inc_rfc1001_len(pSMB, byte_count);
@@ -4846,8 +4844,12 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
                max_len = data_end - temp;
                node->node_name = cifs_strndup_from_utf16(temp, max_len,
                                                is_unicode, nls_codepage);
-               if (!node->node_name)
+               if (!node->node_name) {
                        rc = -ENOMEM;
+                       goto parse_DFS_referrals_exit;
+               }
+
+               ref++;
        }
 
 parse_DFS_referrals_exit:
@@ -5708,7 +5710,8 @@ CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
        param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
        offset = param_offset + params;
 
-       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+       data_offset = (char *)pSMB +
+                       offsetof(struct smb_hdr, Protocol) + offset;
 
        count = sizeof(FILE_BASIC_INFO);
        pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -5977,7 +5980,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
                       u16 fid, u32 pid_of_opener)
 {
        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
-       FILE_UNIX_BASIC_INFO *data_offset;
+       char *data_offset;
        int rc = 0;
        u16 params, param_offset, offset, byte_count, count;
 
@@ -5999,8 +6002,9 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
        param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
        offset = param_offset + params;
 
-       data_offset = (FILE_UNIX_BASIC_INFO *)
-                               ((char *)(&pSMB->hdr.Protocol) + offset);
+       data_offset = (char *)pSMB +
+                       offsetof(struct smb_hdr, Protocol) + offset;
+
        count = sizeof(FILE_UNIX_BASIC_INFO);
 
        pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -6022,7 +6026,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
        inc_rfc1001_len(pSMB, byte_count);
        pSMB->ByteCount = cpu_to_le16(byte_count);
 
-       cifs_fill_unix_set_info(data_offset, args);
+       cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
 
        rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
        if (rc)
index 302a15c505a954882462dc42c1a94179e60b8c78..5dcc55197fb3ff93f3ff3960e3f0b1522f163fc5 100644 (file)
@@ -109,6 +109,8 @@ enum {
 
        /* Options which could be blank */
        Opt_blank_pass,
+       Opt_blank_user,
+       Opt_blank_ip,
 
        Opt_err
 };
@@ -183,11 +185,15 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_wsize, "wsize=%s" },
        { Opt_actimeo, "actimeo=%s" },
 
+       { Opt_blank_user, "user=" },
+       { Opt_blank_user, "username=" },
        { Opt_user, "user=%s" },
        { Opt_user, "username=%s" },
        { Opt_blank_pass, "pass=" },
        { Opt_pass, "pass=%s" },
        { Opt_pass, "password=%s" },
+       { Opt_blank_ip, "ip=" },
+       { Opt_blank_ip, "addr=" },
        { Opt_ip, "ip=%s" },
        { Opt_ip, "addr=%s" },
        { Opt_unc, "unc=%s" },
@@ -209,6 +215,8 @@ static const match_table_t cifs_mount_option_tokens = {
 
        { Opt_ignore, "cred" },
        { Opt_ignore, "credentials" },
+       { Opt_ignore, "cred=%s" },
+       { Opt_ignore, "credentials=%s" },
        { Opt_ignore, "guest" },
        { Opt_ignore, "rw" },
        { Opt_ignore, "ro" },
@@ -1117,7 +1125,7 @@ static int get_option_ul(substring_t args[], unsigned long *option)
        string = match_strdup(args);
        if (string == NULL)
                return -ENOMEM;
-       rc = kstrtoul(string, 10, option);
+       rc = kstrtoul(string, 0, option);
        kfree(string);
 
        return rc;
@@ -1534,15 +1542,17 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 
                /* String Arguments */
 
+               case Opt_blank_user:
+                       /* null user, ie. anonymous authentication */
+                       vol->nullauth = 1;
+                       vol->username = NULL;
+                       break;
                case Opt_user:
                        string = match_strdup(args);
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               /* null user, ie. anonymous authentication */
-                               vol->nullauth = 1;
-                       } else if (strnlen(string, MAX_USERNAME_SIZE) >
+                       if (strnlen(string, MAX_USERNAME_SIZE) >
                                                        MAX_USERNAME_SIZE) {
                                printk(KERN_WARNING "CIFS: username too long\n");
                                goto cifs_parse_mount_err;
@@ -1565,8 +1575,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 
                        /* Obtain the value string */
                        value = strchr(data, '=');
-                       if (value != NULL)
-                               *value++ = '\0';
+                       value++;
 
                        /* Set tmp_end to end of the string */
                        tmp_end = (char *) value + strlen(value);
@@ -1612,14 +1621,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        }
                        vol->password[j] = '\0';
                        break;
+               case Opt_blank_ip:
+                       vol->UNCip = NULL;
+                       break;
                case Opt_ip:
                        string = match_strdup(args);
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               vol->UNCip = NULL;
-                       } else if (strnlen(string, INET6_ADDRSTRLEN) >
+                       if (strnlen(string, INET6_ADDRSTRLEN) >
                                                INET6_ADDRSTRLEN) {
                                printk(KERN_WARNING "CIFS: ip address "
                                                    "too long\n");
@@ -1637,18 +1647,19 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: invalid path to "
-                                                   "network resource\n");
-                               goto cifs_parse_mount_err;
-                       }
-
                        temp_len = strnlen(string, 300);
                        if (temp_len  == 300) {
                                printk(KERN_WARNING "CIFS: UNC name too long\n");
                                goto cifs_parse_mount_err;
                        }
 
+                       vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
+                       if (vol->UNC == NULL) {
+                               printk(KERN_WARNING "CIFS: no memory for UNC\n");
+                               goto cifs_parse_mount_err;
+                       }
+                       strcpy(vol->UNC, string);
+
                        if (strncmp(string, "//", 2) == 0) {
                                vol->UNC[0] = '\\';
                                vol->UNC[1] = '\\';
@@ -1658,24 +1669,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                                goto cifs_parse_mount_err;
                        }
 
-                       vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
-                       if (vol->UNC == NULL) {
-                               printk(KERN_WARNING "CIFS: no memory "
-                                                   "for UNC\n");
-                               goto cifs_parse_mount_err;
-                       }
-                       strcpy(vol->UNC, string);
                        break;
                case Opt_domain:
                        string = match_strdup(args);
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: invalid domain"
-                                                   " name\n");
-                               goto cifs_parse_mount_err;
-                       } else if (strnlen(string, 256) == 256) {
+                       if (strnlen(string, 256) == 256) {
                                printk(KERN_WARNING "CIFS: domain name too"
                                                    " long\n");
                                goto cifs_parse_mount_err;
@@ -1694,11 +1694,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: srcaddr value not"
-                                                   " specified\n");
-                               goto cifs_parse_mount_err;
-                       } else if (!cifs_convert_address(
+                       if (!cifs_convert_address(
                                        (struct sockaddr *)&vol->srcaddr,
                                        string, strlen(string))) {
                                printk(KERN_WARNING "CIFS:  Could not parse"
@@ -1711,11 +1707,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: Invalid path"
-                                                   " prefix\n");
-                               goto cifs_parse_mount_err;
-                       }
                        temp_len = strnlen(string, 1024);
                        if (string[0] != '/')
                                temp_len++; /* missing leading slash */
@@ -1743,11 +1734,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: Invalid iocharset"
-                                                   " specified\n");
-                               goto cifs_parse_mount_err;
-                       } else if (strnlen(string, 1024) >= 65) {
+                       if (strnlen(string, 1024) >= 65) {
                                printk(KERN_WARNING "CIFS: iocharset name "
                                                    "too long.\n");
                                goto cifs_parse_mount_err;
@@ -1772,11 +1759,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: No socket option"
-                                                   " specified\n");
-                               goto cifs_parse_mount_err;
-                       }
                        if (strnicmp(string, "TCP_NODELAY", 11) == 0)
                                vol->sockopt_tcp_nodelay = 1;
                        break;
@@ -1785,12 +1767,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: Invalid (empty)"
-                                                   " netbiosname\n");
-                               break;
-                       }
-
                        memset(vol->source_rfc1001_name, 0x20,
                                RFC1001_NAME_LEN);
                        /*
@@ -1818,11 +1794,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: Empty server"
-                                       " netbiosname specified\n");
-                               break;
-                       }
                        /* last byte, type, is 0x20 for servr type */
                        memset(vol->target_rfc1001_name, 0x20,
                                RFC1001_NAME_LEN_WITH_NULL);
@@ -1849,12 +1820,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               cERROR(1, "no protocol version specified"
-                                         " after vers= mount option");
-                               goto cifs_parse_mount_err;
-                       }
-
                        if (strnicmp(string, "cifs", 4) == 0 ||
                            strnicmp(string, "1", 1) == 0) {
                                /* This is the default */
@@ -1869,12 +1834,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (!*string) {
-                               printk(KERN_WARNING "CIFS: no security flavor"
-                                                   " specified\n");
-                               break;
-                       }
-
                        if (cifs_parse_security_flavors(string, vol) != 0)
                                goto cifs_parse_mount_err;
                        break;
@@ -2226,6 +2185,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
        tcp_ses->session_estab = false;
        tcp_ses->sequence_number = 0;
        tcp_ses->lstrp = jiffies;
+       spin_lock_init(&tcp_ses->req_lock);
        INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
        INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
        INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
@@ -3271,10 +3231,6 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 
        cifs_sb->mnt_uid = pvolume_info->linux_uid;
        cifs_sb->mnt_gid = pvolume_info->linux_gid;
-       if (pvolume_info->backupuid_specified)
-               cifs_sb->mnt_backupuid = pvolume_info->backupuid;
-       if (pvolume_info->backupgid_specified)
-               cifs_sb->mnt_backupgid = pvolume_info->backupgid;
        cifs_sb->mnt_file_mode = pvolume_info->file_mode;
        cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
        cFYI(1, "file mode: 0x%hx  dir mode: 0x%hx",
@@ -3305,10 +3261,14 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
        if (pvolume_info->cifs_acl)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
-       if (pvolume_info->backupuid_specified)
+       if (pvolume_info->backupuid_specified) {
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
-       if (pvolume_info->backupgid_specified)
+               cifs_sb->mnt_backupuid = pvolume_info->backupuid;
+       }
+       if (pvolume_info->backupgid_specified) {
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
+               cifs_sb->mnt_backupgid = pvolume_info->backupgid;
+       }
        if (pvolume_info->override_uid)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
        if (pvolume_info->override_gid)
@@ -3657,22 +3617,6 @@ cifs_get_volume_info(char *mount_data, const char *devname)
        return volume_info;
 }
 
-/* make sure ra_pages is a multiple of rsize */
-static inline unsigned int
-cifs_ra_pages(struct cifs_sb_info *cifs_sb)
-{
-       unsigned int reads;
-       unsigned int rsize_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
-
-       if (rsize_pages >= default_backing_dev_info.ra_pages)
-               return default_backing_dev_info.ra_pages;
-       else if (rsize_pages == 0)
-               return rsize_pages;
-
-       reads = default_backing_dev_info.ra_pages / rsize_pages;
-       return reads * rsize_pages;
-}
-
 int
 cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
 {
@@ -3760,7 +3704,7 @@ try_mount_again:
        cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
 
        /* tune readahead according to rsize */
-       cifs_sb->bdi.ra_pages = cifs_ra_pages(cifs_sb);
+       cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
 
 remote_path_check:
 #ifdef CONFIG_CIFS_DFS_UPCALL
index d172c8ed901786f9e72ee40a50cb6bc22a3be571..ec4e9a2a12f843edf9e8d2f60c8a32f58011ec4d 100644 (file)
@@ -668,12 +668,19 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
                        return 0;
                else {
                        /*
-                        * Forcibly invalidate automounting directory inodes
-                        * (remote DFS directories) so to have them
-                        * instantiated again for automount
+                        * If the inode wasn't known to be a dfs entry when
+                        * the dentry was instantiated, such as when created
+                        * via ->readdir(), it needs to be set now since the
+                        * attributes will have been updated by
+                        * cifs_revalidate_dentry().
                         */
-                       if (IS_AUTOMOUNT(direntry->d_inode))
-                               return 0;
+                       if (IS_AUTOMOUNT(direntry->d_inode) &&
+                          !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) {
+                               spin_lock(&direntry->d_lock);
+                               direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+                               spin_unlock(&direntry->d_lock);
+                       }
+
                        return 1;
                }
        }
index 460d87b7cda08b1280ac05b2f4ac3378230a4f60..81725e9286e911f501e4a78d1d7c28768753d118 100644 (file)
@@ -835,13 +835,21 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock)
        if ((flock->fl_flags & FL_POSIX) == 0)
                return rc;
 
+try_again:
        mutex_lock(&cinode->lock_mutex);
        if (!cinode->can_cache_brlcks) {
                mutex_unlock(&cinode->lock_mutex);
                return rc;
        }
-       rc = posix_lock_file_wait(file, flock);
+
+       rc = posix_lock_file(file, flock, NULL);
        mutex_unlock(&cinode->lock_mutex);
+       if (rc == FILE_LOCK_DEFERRED) {
+               rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next);
+               if (!rc)
+                       goto try_again;
+               locks_delete_block(flock);
+       }
        return rc;
 }
 
@@ -2170,7 +2178,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
        unsigned long nr_pages, i;
        size_t copied, len, cur_len;
        ssize_t total_written = 0;
-       loff_t offset = *poffset;
+       loff_t offset;
        struct iov_iter it;
        struct cifsFileInfo *open_file;
        struct cifs_tcon *tcon;
@@ -2192,6 +2200,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
        cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        open_file = file->private_data;
        tcon = tlink_tcon(open_file->tlink);
+       offset = *poffset;
 
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
                pid = open_file->pid;
index dd23a321bdda60b8eacf105bea12b8e2cce51b2f..581c225f7f50b3ae5ac4f4915b6b229c22432fd7 100644 (file)
@@ -197,8 +197,7 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len)
                memcpy(scope_id, pct + 1, slen);
                scope_id[slen] = '\0';
 
-               rc = strict_strtoul(scope_id, 0,
-                                       (unsigned long *)&s6->sin6_scope_id);
+               rc = kstrtouint(scope_id, 0, &s6->sin6_scope_id);
                rc = (rc == 0) ? 1 : 0;
        }
 
index b60ddc41d78385d168e67e98adc6020fedc1cfeb..b80531c917799475147ba59234c821ea52306fd3 100644 (file)
@@ -141,18 +141,29 @@ int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
  * Compare 2 name strings, return 0 if they match, otherwise non-zero.
  * The strings are both count bytes long, and count is non-zero.
  */
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+
+#include <asm/word-at-a-time.h>
+/*
+ * NOTE! 'cs' and 'scount' come from a dentry, so it has a
+ * aligned allocation for this particular component. We don't
+ * strictly need the load_unaligned_zeropad() safety, but it
+ * doesn't hurt either.
+ *
+ * In contrast, 'ct' and 'tcount' can be from a pathname, and do
+ * need the careful unaligned handling.
+ */
 static inline int dentry_cmp(const unsigned char *cs, size_t scount,
                                const unsigned char *ct, size_t tcount)
 {
-#ifdef CONFIG_DCACHE_WORD_ACCESS
        unsigned long a,b,mask;
 
        if (unlikely(scount != tcount))
                return 1;
 
        for (;;) {
-               a = *(unsigned long *)cs;
-               b = *(unsigned long *)ct;
+               a = load_unaligned_zeropad(cs);
+               b = load_unaligned_zeropad(ct);
                if (tcount < sizeof(unsigned long))
                        break;
                if (unlikely(a != b))
@@ -165,7 +176,13 @@ static inline int dentry_cmp(const unsigned char *cs, size_t scount,
        }
        mask = ~(~0ul << tcount*8);
        return unlikely(!!((a ^ b) & mask));
+}
+
 #else
+
+static inline int dentry_cmp(const unsigned char *cs, size_t scount,
+                               const unsigned char *ct, size_t tcount)
+{
        if (scount != tcount)
                return 1;
 
@@ -177,9 +194,10 @@ static inline int dentry_cmp(const unsigned char *cs, size_t scount,
                tcount--;
        } while (tcount);
        return 0;
-#endif
 }
 
+#endif
+
 static void __d_free(struct rcu_head *head)
 {
        struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
index 21e93605161c1909abb852b89af8c5c08a0ef336..5dfafdd1dbd3cbdd553ef3f88fce4d0ff2fe54a5 100644 (file)
@@ -33,18 +33,10 @@ static ssize_t default_write_file(struct file *file, const char __user *buf,
        return count;
 }
 
-static int default_open(struct inode *inode, struct file *file)
-{
-       if (inode->i_private)
-               file->private_data = inode->i_private;
-
-       return 0;
-}
-
 const struct file_operations debugfs_file_operations = {
        .read =         default_read_file,
        .write =        default_write_file,
-       .open =         default_open,
+       .open =         simple_open,
        .llseek =       noop_llseek,
 };
 
@@ -447,7 +439,7 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
 static const struct file_operations fops_bool = {
        .read =         read_file_bool,
        .write =        write_file_bool,
-       .open =         default_open,
+       .open =         simple_open,
        .llseek =       default_llseek,
 };
 
@@ -492,7 +484,7 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf,
 
 static const struct file_operations fops_blob = {
        .read =         read_file_blob,
-       .open =         default_open,
+       .open =         simple_open,
        .llseek =       default_llseek,
 };
 
index 3dca2b39e83fa9c8b5025f0e3aefa94252ed0a41..1c9b08095f987e0899d13801e3faadbcbf74876c 100644 (file)
@@ -609,13 +609,6 @@ static const struct file_operations format3_fops = {
 /*
  * dump lkb's on the ls_waiters list
  */
-
-static int waiters_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t waiters_read(struct file *file, char __user *userbuf,
                            size_t count, loff_t *ppos)
 {
@@ -644,7 +637,7 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf,
 
 static const struct file_operations waiters_fops = {
        .owner   = THIS_MODULE,
-       .open    = waiters_open,
+       .open    = simple_open,
        .read    = waiters_read,
        .llseek  = default_llseek,
 };
index fa5c07d51dccf2cb1b66d4b2d04a4eec8a92e7da..4c58d4a3adc4f29c6a2829bc54ac4be122c77ae7 100644 (file)
@@ -1736,6 +1736,18 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
        if (now && conv && !(lkb->lkb_exflags & DLM_LKF_QUECVT))
                return 1;
 
+       /*
+        * Even if the convert is compat with all granted locks,
+        * QUECVT forces it behind other locks on the convert queue.
+        */
+
+       if (now && conv && (lkb->lkb_exflags & DLM_LKF_QUECVT)) {
+               if (list_empty(&r->res_convertqueue))
+                       return 1;
+               else
+                       goto out;
+       }
+
        /*
         * The NOORDER flag is set to avoid the standard vms rules on grant
         * order.
index 739b0985b398ea2d837af83e26fa305a6cdfdc30..c0b3c70ee87a2b8e0e46c01a87d63ac692aecc71 100644 (file)
@@ -1663,8 +1663,10 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
        if (op == EPOLL_CTL_ADD) {
                if (is_file_epoll(tfile)) {
                        error = -ELOOP;
-                       if (ep_loop_check(ep, tfile) != 0)
+                       if (ep_loop_check(ep, tfile) != 0) {
+                               clear_tfile_check_list();
                                goto error_tgt_fput;
+                       }
                } else
                        list_add(&tfile->f_tfile_llink, &tfile_check_list);
        }
index 9a1d9f0a60abf77a55df5bef051047a23ef853d0..b1fd2025e59a1e0ea0a2f475b812987dac176e9f 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1371,7 +1371,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
        unsigned int depth = bprm->recursion_depth;
        int try,retval;
        struct linux_binfmt *fmt;
-       pid_t old_pid;
+       pid_t old_pid, old_vpid;
 
        retval = security_bprm_check(bprm);
        if (retval)
@@ -1382,8 +1382,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                return retval;
 
        /* Need to fetch pid before load_binary changes it */
+       old_pid = current->pid;
        rcu_read_lock();
-       old_pid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
+       old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
        rcu_read_unlock();
 
        retval = -ENOENT;
@@ -1406,7 +1407,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                        if (retval >= 0) {
                                if (depth == 0) {
                                        trace_sched_process_exec(current, old_pid, bprm);
-                                       ptrace_event(PTRACE_EVENT_EXEC, old_pid);
+                                       ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
                                }
                                put_binfmt(fmt);
                                allow_write_access(bprm->file);
index ab2594a30f86f8a39a0fc918a0bdc69e1d7c9e0f..0e01e90add8bc42f1492a73a2e1e78331b8ae134 100644 (file)
@@ -1203,9 +1203,6 @@ struct ext4_sb_info {
        unsigned long s_ext_blocks;
        unsigned long s_ext_extents;
 #endif
-       /* ext4 extent cache stats */
-       unsigned long extent_cache_hits;
-       unsigned long extent_cache_misses;
 
        /* for buddy allocator */
        struct ext4_group_info ***s_group_info;
index 1421938e6792a4f5426cbd8f4d218eea4f2192f9..abcdeab67f5232b66d4aa5a6cbb88838094f6247 100644 (file)
@@ -2066,10 +2066,6 @@ static int ext4_ext_check_cache(struct inode *inode, ext4_lblk_t block,
                ret = 1;
        }
 errout:
-       if (!ret)
-               sbi->extent_cache_misses++;
-       else
-               sbi->extent_cache_hits++;
        trace_ext4_ext_in_cache(inode, block, ret);
        spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
        return ret;
@@ -2882,7 +2878,7 @@ static int ext4_split_extent_at(handle_t *handle,
                if (err)
                        goto fix_extent_len;
                /* update the extent length and mark as initialized */
-               ex->ee_len = cpu_to_le32(ee_len);
+               ex->ee_len = cpu_to_le16(ee_len);
                ext4_ext_try_to_merge(inode, path, ex);
                err = ext4_ext_dirty(handle, inode, path + depth);
                goto out;
index ceebaf853beb74c7e139e63f46bf44975696566b..e1fb1d5de58eab4150792974f9784751f4638557 100644 (file)
@@ -1305,20 +1305,20 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
                ext4_msg(sb, KERN_ERR,
                        "Cannot change journaled "
                        "quota options when quota turned on");
-               return 0;
+               return -1;
        }
        qname = match_strdup(args);
        if (!qname) {
                ext4_msg(sb, KERN_ERR,
                        "Not enough memory for storing quotafile name");
-               return 0;
+               return -1;
        }
        if (sbi->s_qf_names[qtype] &&
                strcmp(sbi->s_qf_names[qtype], qname)) {
                ext4_msg(sb, KERN_ERR,
                        "%s quota file already specified", QTYPE2NAME(qtype));
                kfree(qname);
-               return 0;
+               return -1;
        }
        sbi->s_qf_names[qtype] = qname;
        if (strchr(sbi->s_qf_names[qtype], '/')) {
@@ -1326,7 +1326,7 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
                        "quotafile must be on filesystem root");
                kfree(sbi->s_qf_names[qtype]);
                sbi->s_qf_names[qtype] = NULL;
-               return 0;
+               return -1;
        }
        set_opt(sb, QUOTA);
        return 1;
@@ -1341,7 +1341,7 @@ static int clear_qf_name(struct super_block *sb, int qtype)
                sbi->s_qf_names[qtype]) {
                ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options"
                        " when quota turned on");
-               return 0;
+               return -1;
        }
        /*
         * The space will be released later when all options are confirmed
@@ -1450,6 +1450,16 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
        const struct mount_opts *m;
        int arg = 0;
 
+#ifdef CONFIG_QUOTA
+       if (token == Opt_usrjquota)
+               return set_qf_name(sb, USRQUOTA, &args[0]);
+       else if (token == Opt_grpjquota)
+               return set_qf_name(sb, GRPQUOTA, &args[0]);
+       else if (token == Opt_offusrjquota)
+               return clear_qf_name(sb, USRQUOTA);
+       else if (token == Opt_offgrpjquota)
+               return clear_qf_name(sb, GRPQUOTA);
+#endif
        if (args->from && match_int(args, &arg))
                return -1;
        switch (token) {
@@ -1549,18 +1559,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                                sbi->s_mount_opt |= m->mount_opt;
                        }
 #ifdef CONFIG_QUOTA
-               } else if (token == Opt_usrjquota) {
-                       if (!set_qf_name(sb, USRQUOTA, &args[0]))
-                               return -1;
-               } else if (token == Opt_grpjquota) {
-                       if (!set_qf_name(sb, GRPQUOTA, &args[0]))
-                               return -1;
-               } else if (token == Opt_offusrjquota) {
-                       if (!clear_qf_name(sb, USRQUOTA))
-                               return -1;
-               } else if (token == Opt_offgrpjquota) {
-                       if (!clear_qf_name(sb, GRPQUOTA))
-                               return -1;
                } else if (m->flags & MOPT_QFMT) {
                        if (sb_any_quota_loaded(sb) &&
                            sbi->s_jquota_fmt != m->mount_opt) {
@@ -1599,7 +1597,9 @@ static int parse_options(char *options, struct super_block *sb,
                         unsigned int *journal_ioprio,
                         int is_remount)
 {
+#ifdef CONFIG_QUOTA
        struct ext4_sb_info *sbi = EXT4_SB(sb);
+#endif
        char *p;
        substring_t args[MAX_OPT_ARGS];
        int token;
@@ -2366,18 +2366,6 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a,
                          EXT4_SB(sb)->s_sectors_written_start) >> 1)));
 }
 
-static ssize_t extent_cache_hits_show(struct ext4_attr *a,
-                                     struct ext4_sb_info *sbi, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits);
-}
-
-static ssize_t extent_cache_misses_show(struct ext4_attr *a,
-                                       struct ext4_sb_info *sbi, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses);
-}
-
 static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
                                          struct ext4_sb_info *sbi,
                                          const char *buf, size_t count)
@@ -2435,8 +2423,6 @@ static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
 EXT4_RO_ATTR(delayed_allocation_blocks);
 EXT4_RO_ATTR(session_write_kbytes);
 EXT4_RO_ATTR(lifetime_write_kbytes);
-EXT4_RO_ATTR(extent_cache_hits);
-EXT4_RO_ATTR(extent_cache_misses);
 EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
                 inode_readahead_blks_store, s_inode_readahead_blks);
 EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
@@ -2452,8 +2438,6 @@ static struct attribute *ext4_attrs[] = {
        ATTR_LIST(delayed_allocation_blocks),
        ATTR_LIST(session_write_kbytes),
        ATTR_LIST(lifetime_write_kbytes),
-       ATTR_LIST(extent_cache_hits),
-       ATTR_LIST(extent_cache_misses),
        ATTR_LIST(inode_readahead_blks),
        ATTR_LIST(inode_goal),
        ATTR_LIST(mb_stats),
index 206632887bb40ccf48bb80b96e497c2107c172d9..df5ac048dc74e6b33174a69dc36b3a5b6084fd74 100644 (file)
@@ -387,9 +387,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        if (fc->no_create)
                return -ENOSYS;
 
-       if (flags & O_DIRECT)
-               return -EINVAL;
-
        forget = fuse_alloc_forget();
        if (!forget)
                return -ENOMEM;
@@ -644,13 +641,12 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
        fuse_put_request(fc, req);
        if (!err) {
                struct inode *inode = entry->d_inode;
+               struct fuse_inode *fi = get_fuse_inode(inode);
 
-               /*
-                * Set nlink to zero so the inode can be cleared, if the inode
-                * does have more links this will be discovered at the next
-                * lookup/getattr.
-                */
-               clear_nlink(inode);
+               spin_lock(&fc->lock);
+               fi->attr_version = ++fc->attr_version;
+               drop_nlink(inode);
+               spin_unlock(&fc->lock);
                fuse_invalidate_attr(inode);
                fuse_invalidate_attr(dir);
                fuse_invalidate_entry_cache(entry);
@@ -762,8 +758,17 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
           will reflect changes in the backing inode (link count,
           etc.)
        */
-       if (!err || err == -EINTR)
+       if (!err) {
+               struct fuse_inode *fi = get_fuse_inode(inode);
+
+               spin_lock(&fc->lock);
+               fi->attr_version = ++fc->attr_version;
+               inc_nlink(inode);
+               spin_unlock(&fc->lock);
+               fuse_invalidate_attr(inode);
+       } else if (err == -EINTR) {
                fuse_invalidate_attr(inode);
+       }
        return err;
 }
 
index a841868bf9ce363cb9705f3a5ba978a39c682df7..504e61b7fd7515f8aafe7e3b9edd2c9fa42fd91d 100644 (file)
@@ -194,10 +194,6 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
 
-       /* VFS checks this, but only _after_ ->open() */
-       if (file->f_flags & O_DIRECT)
-               return -EINVAL;
-
        err = generic_file_open(inode, file);
        if (err)
                return err;
@@ -932,17 +928,23 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
        size_t count = 0;
+       size_t ocount = 0;
        ssize_t written = 0;
+       ssize_t written_buffered = 0;
        struct inode *inode = mapping->host;
        ssize_t err;
        struct iov_iter i;
+       loff_t endbyte = 0;
 
        WARN_ON(iocb->ki_pos != pos);
 
-       err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
+       ocount = 0;
+       err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
        if (err)
                return err;
 
+       count = ocount;
+
        mutex_lock(&inode->i_mutex);
        vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
 
@@ -962,11 +964,41 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
        file_update_time(file);
 
-       iov_iter_init(&i, iov, nr_segs, count, 0);
-       written = fuse_perform_write(file, mapping, &i, pos);
-       if (written >= 0)
-               iocb->ki_pos = pos + written;
+       if (file->f_flags & O_DIRECT) {
+               written = generic_file_direct_write(iocb, iov, &nr_segs,
+                                                   pos, &iocb->ki_pos,
+                                                   count, ocount);
+               if (written < 0 || written == count)
+                       goto out;
+
+               pos += written;
+               count -= written;
 
+               iov_iter_init(&i, iov, nr_segs, count, written);
+               written_buffered = fuse_perform_write(file, mapping, &i, pos);
+               if (written_buffered < 0) {
+                       err = written_buffered;
+                       goto out;
+               }
+               endbyte = pos + written_buffered - 1;
+
+               err = filemap_write_and_wait_range(file->f_mapping, pos,
+                                                  endbyte);
+               if (err)
+                       goto out;
+
+               invalidate_mapping_pages(file->f_mapping,
+                                        pos >> PAGE_CACHE_SHIFT,
+                                        endbyte >> PAGE_CACHE_SHIFT);
+
+               written += written_buffered;
+               iocb->ki_pos = pos + written_buffered;
+       } else {
+               iov_iter_init(&i, iov, nr_segs, count, 0);
+               written = fuse_perform_write(file, mapping, &i, pos);
+               if (written >= 0)
+                       iocb->ki_pos = pos + written;
+       }
 out:
        current->backing_dev_info = NULL;
        mutex_unlock(&inode->i_mutex);
@@ -1101,30 +1133,41 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
        return res;
 }
 
-static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
-                                size_t count, loff_t *ppos)
+static ssize_t __fuse_direct_write(struct file *file, const char __user *buf,
+                                  size_t count, loff_t *ppos)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
        ssize_t res;
 
-       if (is_bad_inode(inode))
-               return -EIO;
-
-       /* Don't allow parallel writes to the same file */
-       mutex_lock(&inode->i_mutex);
        res = generic_write_checks(file, ppos, &count, 0);
        if (!res) {
                res = fuse_direct_io(file, buf, count, ppos, 1);
                if (res > 0)
                        fuse_write_update_size(inode, *ppos);
        }
-       mutex_unlock(&inode->i_mutex);
 
        fuse_invalidate_attr(inode);
 
        return res;
 }
 
+static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       ssize_t res;
+
+       if (is_bad_inode(inode))
+               return -EIO;
+
+       /* Don't allow parallel writes to the same file */
+       mutex_lock(&inode->i_mutex);
+       res = __fuse_direct_write(file, buf, count, ppos);
+       mutex_unlock(&inode->i_mutex);
+
+       return res;
+}
+
 static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
 {
        __free_page(req->pages[0]);
@@ -2077,6 +2120,57 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc,
        return 0;
 }
 
+static ssize_t fuse_loop_dio(struct file *filp, const struct iovec *iov,
+                            unsigned long nr_segs, loff_t *ppos, int rw)
+{
+       const struct iovec *vector = iov;
+       ssize_t ret = 0;
+
+       while (nr_segs > 0) {
+               void __user *base;
+               size_t len;
+               ssize_t nr;
+
+               base = vector->iov_base;
+               len = vector->iov_len;
+               vector++;
+               nr_segs--;
+
+               if (rw == WRITE)
+                       nr = __fuse_direct_write(filp, base, len, ppos);
+               else
+                       nr = fuse_direct_read(filp, base, len, ppos);
+
+               if (nr < 0) {
+                       if (!ret)
+                               ret = nr;
+                       break;
+               }
+               ret += nr;
+               if (nr != len)
+                       break;
+       }
+
+       return ret;
+}
+
+
+static ssize_t
+fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+                       loff_t offset, unsigned long nr_segs)
+{
+       ssize_t ret = 0;
+       struct file *file = NULL;
+       loff_t pos = 0;
+
+       file = iocb->ki_filp;
+       pos = offset;
+
+       ret = fuse_loop_dio(file, iov, nr_segs, &pos, rw);
+
+       return ret;
+}
+
 static const struct file_operations fuse_file_operations = {
        .llseek         = fuse_file_llseek,
        .read           = do_sync_read,
@@ -2120,6 +2214,7 @@ static const struct address_space_operations fuse_file_aops  = {
        .readpages      = fuse_readpages,
        .set_page_dirty = __set_page_dirty_nobuffers,
        .bmap           = fuse_bmap,
+       .direct_IO      = fuse_direct_IO,
 };
 
 void fuse_init_file_inode(struct inode *inode)
index 4aec5995867e95c8c0df3e00d93b1e5ae39d25c0..26783eb2b1fc9465602cc0f452c49aa3e72d32b5 100644 (file)
@@ -947,6 +947,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_magic = FUSE_SUPER_MAGIC;
        sb->s_op = &fuse_super_operations;
        sb->s_maxbytes = MAX_LFS_FILESIZE;
+       sb->s_time_gran = 1;
        sb->s_export_op = &fuse_export_operations;
 
        file = fget(d.fd);
index c465ae066c62c6392ee22047d2be0ec650b89c98..eb08c9e43c2afb13947ca557f1a62da4626c5071 100644 (file)
@@ -1,10 +1,6 @@
 config GFS2_FS
        tristate "GFS2 file system support"
        depends on (64BIT || LBDAF)
-       select DLM if GFS2_FS_LOCKING_DLM
-       select CONFIGFS_FS if GFS2_FS_LOCKING_DLM
-       select SYSFS if GFS2_FS_LOCKING_DLM
-       select IP_SCTP if DLM_SCTP
        select FS_POSIX_ACL
        select CRC32
        select QUOTACTL
@@ -29,7 +25,8 @@ config GFS2_FS
 
 config GFS2_FS_LOCKING_DLM
        bool "GFS2 DLM locking"
-       depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && HOTPLUG
+       depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && \
+               HOTPLUG && DLM && CONFIGFS_FS && SYSFS
        help
          Multiple node locking module for GFS2
 
index 38b7a74a0f913392f1c05bcd567a82e2792d6cdb..9b2ff0e851b13ad824f1a1a06addd3bbd04763e6 100644 (file)
@@ -807,7 +807,7 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
 
        if (inode == sdp->sd_rindex) {
                adjust_fs_space(inode);
-               ip->i_gh.gh_flags |= GL_NOCACHE;
+               sdp->sd_rindex_uptodate = 0;
        }
 
        brelse(dibh);
@@ -873,7 +873,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
 
        if (inode == sdp->sd_rindex) {
                adjust_fs_space(inode);
-               ip->i_gh.gh_flags |= GL_NOCACHE;
+               sdp->sd_rindex_uptodate = 0;
        }
 
        brelse(dibh);
index 197c5c47e57763c7f8c926be7e8c527463107c0e..03c04febe26f095e58d36504e7fb4400c30be6ca 100644 (file)
@@ -724,7 +724,11 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
        int metadata;
        unsigned int revokes = 0;
        int x;
-       int error = 0;
+       int error;
+
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
 
        if (!*top)
                sm->sm_first = 0;
index c35573abd3710a123112edcdf30c29c5e9f41023..a836056343f077bee81a6f54c7a1e5b0f86cf604 100644 (file)
@@ -1844,6 +1844,10 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
        unsigned int x, size = len * sizeof(u64);
        int error;
 
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
+
        memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
 
        ht = kzalloc(size, GFP_NOFS);
index c98a60ee6dfd5bf84921e1fd8ad626c4922ca86c..a9ba2444e077ac145f23c25161038a0f8ac2f468 100644 (file)
@@ -1031,7 +1031,13 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
        struct buffer_head *bh;
        struct gfs2_holder ghs[3];
        struct gfs2_rgrpd *rgd;
-       int error = -EROFS;
+       int error;
+
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
+
+       error = -EROFS;
 
        gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
        gfs2_holder_init(ip->i_gl,  LM_ST_EXCLUSIVE, 0, ghs + 1);
@@ -1224,6 +1230,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                        return 0;
        }
 
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
+
        if (odip != ndip) {
                error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
                                           0, &r_gh);
@@ -1345,7 +1355,6 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        error = alloc_required;
        if (error < 0)
                goto out_gunlock;
-       error = 0;
 
        if (alloc_required) {
                struct gfs2_qadata *qa = gfs2_qadata_get(ndip);
index f8411bd1b805b9f93df3dd4ea53e3a388bf5957e..5f5e70e047dc73440ab88f1c08adc51938d7930b 100644 (file)
@@ -200,10 +200,11 @@ static int make_mode(const unsigned int lmstate)
        return -1;
 }
 
-static u32 make_flags(const u32 lkid, const unsigned int gfs_flags,
+static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
                      const int req)
 {
        u32 lkf = DLM_LKF_VALBLK;
+       u32 lkid = gl->gl_lksb.sb_lkid;
 
        if (gfs_flags & LM_FLAG_TRY)
                lkf |= DLM_LKF_NOQUEUE;
@@ -227,8 +228,11 @@ static u32 make_flags(const u32 lkid, const unsigned int gfs_flags,
                        BUG();
        }
 
-       if (lkid != 0) 
+       if (lkid != 0) {
                lkf |= DLM_LKF_CONVERT;
+               if (test_bit(GLF_BLOCKING, &gl->gl_flags))
+                       lkf |= DLM_LKF_QUECVT;
+       }
 
        return lkf;
 }
@@ -250,7 +254,7 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
        char strname[GDLM_STRNAME_BYTES] = "";
 
        req = make_mode(req_state);
-       lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req);
+       lkf = make_flags(gl, flags, req);
        gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
        gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
        if (gl->gl_lksb.sb_lkid) {
index 19bde40b4864c6d3faccc0ea513e830dc75f288f..3df65c9ab73b3ff3b56b338f37100d1f404ab594 100644 (file)
@@ -332,9 +332,6 @@ struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk, bool exact)
        struct rb_node *n, *next;
        struct gfs2_rgrpd *cur;
 
-       if (gfs2_rindex_update(sdp))
-               return NULL;
-
        spin_lock(&sdp->sd_rindex_spin);
        n = sdp->sd_rindex_tree.rb_node;
        while (n) {
@@ -640,6 +637,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
                return 0;
 
        error = 0; /* someone else read in the rgrp; free it and ignore it */
+       gfs2_glock_put(rgd->rd_gl);
 
 fail:
        kfree(rgd->rd_bits);
@@ -927,6 +925,10 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        } else if (copy_from_user(&r, argp, sizeof(r)))
                return -EFAULT;
 
+       ret = gfs2_rindex_update(sdp);
+       if (ret)
+               return ret;
+
        rgd = gfs2_blk2rgrpd(sdp, r.start, 0);
        rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0);
 
index 2e5ba425cae743f006b938a39b8e70469c9f471a..927f4df874ae788c744e1e7e51edb19d92b60e36 100644 (file)
@@ -238,6 +238,10 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
        unsigned int x;
        int error;
 
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
+
        if (GFS2_EA_IS_STUFFED(ea))
                return 0;
 
@@ -1330,6 +1334,10 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
        unsigned int x;
        int error;
 
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
+
        memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
 
        error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &indbh);
@@ -1439,6 +1447,10 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
        struct gfs2_holder gh;
        int error;
 
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
+
        rgd = gfs2_blk2rgrpd(sdp, ip->i_eattr, 1);
        if (!rgd) {
                gfs2_consist_inode(ip);
index 4dfbfec357e8837055c2131206e0ca812fbec4de..ec2a9c23f0c9a58b66a517aceeeab8092efaf11b 100644 (file)
@@ -366,6 +366,10 @@ int hfsplus_rename_cat(u32 cnid,
        err = hfs_brec_find(&src_fd);
        if (err)
                goto out;
+       if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) {
+               err = -EIO;
+               goto out;
+       }
 
        hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
                                src_fd.entrylength);
index 88e155f895c6f0376db9e387b9f56f521bbbeb2f..26b53fb09f684404b2c488057f13c08ec8b2c0e2 100644 (file)
@@ -150,6 +150,11 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
                filp->f_pos++;
                /* fall through */
        case 1:
+               if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+                       err = -EIO;
+                       goto out;
+               }
+
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                        fd.entrylength);
                if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
@@ -181,6 +186,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        err = -EIO;
                        goto out;
                }
+
+               if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+                       err = -EIO;
+                       goto out;
+               }
+
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                        fd.entrylength);
                type = be16_to_cpu(entry.type);
index ea251749d9d5982e6fc35ecf6d21ab61547962e8..001ef01d2fe2705a6767075032ea9f9f9ed0ec04 100644 (file)
@@ -485,6 +485,7 @@ static struct inode *hugetlbfs_get_root(struct super_block *sb,
                inode->i_fop = &simple_dir_operations;
                /* directory inodes start off with i_nlink == 2 (for "." entry) */
                inc_nlink(inode);
+               lockdep_annotate_inode_mutex_key(inode);
        }
        return inode;
 }
@@ -1031,7 +1032,6 @@ static int __init init_hugetlbfs_fs(void)
        }
 
        error = PTR_ERR(vfsmount);
-       unregister_filesystem(&hugetlbfs_fs_type);
 
  out:
        kmem_cache_destroy(hugetlbfs_inode_cachep);
index 806525a7269c5e7bd7cd864a7350563e792c1858..840f70f507924a0ac4db70a9d729f715783b49be 100644 (file)
@@ -723,7 +723,7 @@ start_journal_io:
        if (commit_transaction->t_need_data_flush &&
            (journal->j_fs_dev != journal->j_dev) &&
            (journal->j_flags & JBD2_BARRIER))
-               blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
+               blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL);
 
        /* Done it all: now write the commit record asynchronously. */
        if (JBD2_HAS_INCOMPAT_FEATURE(journal,
@@ -859,7 +859,7 @@ wait_for_iobuf:
        if (JBD2_HAS_INCOMPAT_FEATURE(journal,
                                      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) &&
            journal->j_flags & JBD2_BARRIER) {
-               blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL);
+               blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL);
        }
 
        if (err)
index 4a0d1f06da5746798a86157c50a227f63d9deed8..18d08f5db53adb46d832222357df9d81d5058f11 100644 (file)
@@ -264,6 +264,13 @@ Enomem:
        return ERR_PTR(-ENOMEM);
 }
 
+int simple_open(struct inode *inode, struct file *file)
+{
+       if (inode->i_private)
+               file->private_data = inode->i_private;
+       return 0;
+}
+
 int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
        struct inode *inode = old_dentry->d_inode;
@@ -522,6 +529,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
        return 0;
 out:
        d_genocide(root);
+       shrink_dcache_parent(root);
        dput(root);
        return -ENOMEM;
 }
@@ -984,6 +992,7 @@ EXPORT_SYMBOL(simple_dir_operations);
 EXPORT_SYMBOL(simple_empty);
 EXPORT_SYMBOL(simple_fill_super);
 EXPORT_SYMBOL(simple_getattr);
+EXPORT_SYMBOL(simple_open);
 EXPORT_SYMBOL(simple_link);
 EXPORT_SYMBOL(simple_lookup);
 EXPORT_SYMBOL(simple_pin_fs);
index 3ddcbb1c0a432728f626986b1d057d11aafdce84..13ad1539fbf2479cd7f69a45611cd3d6a460688f 100644 (file)
@@ -241,7 +241,7 @@ static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat)
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(p == NULL))
                goto out_overflow;
-       if (unlikely(*p > nlm4_failed))
+       if (unlikely(ntohl(*p) > ntohl(nlm4_failed)))
                goto out_bad_xdr;
        *stat = *p;
        return 0;
index 3d35e3e80c1ccfac1367647b6ac417ba3f5bd1b2..d269ada7670e155c7544a2aa01ea0697e98f3991 100644 (file)
@@ -236,7 +236,7 @@ static int decode_nlm_stat(struct xdr_stream *xdr,
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(p == NULL))
                goto out_overflow;
-       if (unlikely(*p > nlm_lck_denied_grace_period))
+       if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period)))
                goto out_enum;
        *stat = *p;
        return 0;
index 637694bf3a03c5652d780700686a9e719fca2709..0d68f1f817996bef79ab16a4b0c51ceecd409d65 100644 (file)
@@ -510,12 +510,13 @@ static void __locks_delete_block(struct file_lock *waiter)
 
 /*
  */
-static void locks_delete_block(struct file_lock *waiter)
+void locks_delete_block(struct file_lock *waiter)
 {
        lock_flocks();
        __locks_delete_block(waiter);
        unlock_flocks();
 }
+EXPORT_SYMBOL(locks_delete_block);
 
 /* Insert waiter into blocker's block list.
  * We use a circular list so that processes can be easily woken up in
index 1898198abc3d10ed4126c73ab24035f0c796a877..c42791914f8205e8608923608a44fcab5478a6ea 100644 (file)
@@ -1407,18 +1407,9 @@ static inline int can_lookup(struct inode *inode)
  */
 #ifdef CONFIG_DCACHE_WORD_ACCESS
 
-#ifdef CONFIG_64BIT
+#include <asm/word-at-a-time.h>
 
-/*
- * Jan Achrenius on G+: microoptimized version of
- * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
- * that works for the bytemasks without having to
- * mask them first.
- */
-static inline long count_masked_bytes(unsigned long mask)
-{
-       return mask*0x0001020304050608ul >> 56;
-}
+#ifdef CONFIG_64BIT
 
 static inline unsigned int fold_hash(unsigned long hash)
 {
@@ -1428,15 +1419,6 @@ static inline unsigned int fold_hash(unsigned long hash)
 
 #else  /* 32-bit case */
 
-/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
-static inline long count_masked_bytes(long mask)
-{
-       /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
-       long a = (0x0ff0001+mask) >> 23;
-       /* Fix the 1 for 00 case */
-       return a & mask;
-}
-
 #define fold_hash(x) (x)
 
 #endif
@@ -1447,7 +1429,7 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len)
        unsigned long hash = 0;
 
        for (;;) {
-               a = *(unsigned long *)name;
+               a = load_unaligned_zeropad(name);
                if (len < sizeof(unsigned long))
                        break;
                hash += a;
@@ -1464,17 +1446,6 @@ done:
 }
 EXPORT_SYMBOL(full_name_hash);
 
-#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
-#define ONEBYTES       REPEAT_BYTE(0x01)
-#define SLASHBYTES     REPEAT_BYTE('/')
-#define HIGHBITS       REPEAT_BYTE(0x80)
-
-/* Return the high bit set in the first byte that is a zero */
-static inline unsigned long has_zero(unsigned long a)
-{
-       return ((a - ONEBYTES) & ~a) & HIGHBITS;
-}
-
 /*
  * Calculate the length and hash of the path component, and
  * return the length of the component;
@@ -1488,9 +1459,9 @@ static inline unsigned long hash_name(const char *name, unsigned int *hashp)
        do {
                hash = (hash + a) * 9;
                len += sizeof(unsigned long);
-               a = *(unsigned long *)(name+len);
+               a = load_unaligned_zeropad(name+len);
                /* Do we have any NUL or '/' bytes in this word? */
-               mask = has_zero(a) | has_zero(a ^ SLASHBYTES);
+               mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/'));
        } while (!mask);
 
        /* The mask *below* the first high bit set */
index 9c94297bb70e9502c40825249eecb24093e142d2..7f6a23f0244e7340f2861ac6fb0d3a2d20721287 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/buffer_head.h> /* various write calls */
 #include <linux/prefetch.h>
 
+#include "../pnfs.h"
+#include "../internal.h"
 #include "blocklayout.h"
 
 #define NFSDBG_FACILITY        NFSDBG_PNFS_LD
@@ -868,7 +870,7 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
         * GETDEVICEINFO's maxcount
         */
        max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
-       max_pages = max_resp_sz >> PAGE_SHIFT;
+       max_pages = nfs_page_array_len(0, max_resp_sz);
        dprintk("%s max_resp_sz %u max_pages %d\n",
                __func__, max_resp_sz, max_pages);
 
index da7b5e4ff9ec19adc0c7e53452a87d7cd35a609b..60f7e4ec842cf1d4fd48f21862d1d5ece26efc88 100644 (file)
@@ -1729,7 +1729,8 @@ error:
  */
 struct nfs_server *nfs_clone_server(struct nfs_server *source,
                                    struct nfs_fh *fh,
-                                   struct nfs_fattr *fattr)
+                                   struct nfs_fattr *fattr,
+                                   rpc_authflavor_t flavor)
 {
        struct nfs_server *server;
        struct nfs_fattr *fattr_fsinfo;
@@ -1758,7 +1759,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
 
        error = nfs_init_server_rpcclient(server,
                        source->client->cl_timeout,
-                       source->client->cl_auth->au_flavor);
+                       flavor);
        if (error < 0)
                goto out_free_server;
        if (!IS_ERR(source->client_acl))
index 4aaf0316d76a040a1e17e60e00060b28005d59a2..8789210c6905a666c86612d9ac080f567ddbd89f 100644 (file)
@@ -1429,7 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
        }
 
        open_flags = nd->intent.open.flags;
-       attr.ia_valid = 0;
+       attr.ia_valid = ATTR_OPEN;
 
        ctx = create_nfs_open_context(dentry, open_flags);
        res = ERR_CAST(ctx);
@@ -1536,7 +1536,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
        if (IS_ERR(ctx))
                goto out;
 
-       attr.ia_valid = 0;
+       attr.ia_valid = ATTR_OPEN;
        if (openflags & O_TRUNC) {
                attr.ia_valid |= ATTR_SIZE;
                attr.ia_size = 0;
index b7f348bb618b8d8864f7a5e2569aff8f4ef4e3a7..ba3019f5934c21a610a96569b1d239b90eca0459 100644 (file)
@@ -554,12 +554,16 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
        struct nfs_client *clp;
        int error = 0;
 
+       if (!try_module_get(THIS_MODULE))
+               return 0;
+
        while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) {
                error = __rpc_pipefs_event(clp, event, sb);
                nfs_put_client(clp);
                if (error)
                        break;
        }
+       module_put(THIS_MODULE);
        return error;
 }
 
index 2476dc69365f223d78a0b514991bcb88fa144ec9..b777bdaba4c52e72ee86a1d6c1e67ec381a37788 100644 (file)
@@ -165,7 +165,8 @@ extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
 extern void nfs_free_server(struct nfs_server *server);
 extern struct nfs_server *nfs_clone_server(struct nfs_server *,
                                           struct nfs_fh *,
-                                          struct nfs_fattr *);
+                                          struct nfs_fattr *,
+                                          rpc_authflavor_t);
 extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
 extern int nfs4_check_client_ready(struct nfs_client *clp);
 extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
@@ -186,10 +187,10 @@ static inline void nfs_fs_proc_exit(void)
 
 /* nfs4namespace.c */
 #ifdef CONFIG_NFS_V4
-extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
+extern struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry);
 #else
 static inline
-struct vfsmount *nfs_do_refmount(struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
 {
        return ERR_PTR(-ENOENT);
 }
@@ -234,7 +235,6 @@ extern const u32 nfs41_maxwrite_overhead;
 /* nfs4proc.c */
 #ifdef CONFIG_NFS_V4
 extern struct rpc_procinfo nfs4_procedures[];
-void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *);
 #endif
 
 extern int nfs4_init_ds_session(struct nfs_client *clp);
index 1807866bb3ab845098de2a95c695bee5460aaf37..d51868e5683c0b34530c9db38a0cd4c26277c0b8 100644 (file)
@@ -148,66 +148,31 @@ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
        return pseudoflavor;
 }
 
-static int nfs_negotiate_security(const struct dentry *parent,
-                                 const struct dentry *dentry,
-                                 rpc_authflavor_t *flavor)
+static struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
+                                             struct qstr *name,
+                                             struct nfs_fh *fh,
+                                             struct nfs_fattr *fattr)
 {
-       struct page *page;
-       struct nfs4_secinfo_flavors *flavors;
-       int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
-       int ret = -EPERM;
-
-       secinfo = NFS_PROTO(parent->d_inode)->secinfo;
-       if (secinfo != NULL) {
-               page = alloc_page(GFP_KERNEL);
-               if (!page) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               flavors = page_address(page);
-               ret = secinfo(parent->d_inode, &dentry->d_name, flavors);
-               *flavor = nfs_find_best_sec(flavors);
-               put_page(page);
-       }
-
-out:
-       return ret;
-}
-
-static int nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent,
-                              struct dentry *dentry, struct path *path,
-                              struct nfs_fh *fh, struct nfs_fattr *fattr,
-                              rpc_authflavor_t *flavor)
-{
-       struct rpc_clnt *clone;
-       struct rpc_auth *auth;
        int err;
 
-       err = nfs_negotiate_security(parent, path->dentry, flavor);
-       if (err < 0)
-               goto out;
-       clone  = rpc_clone_client(server->client);
-       auth   = rpcauth_create(*flavor, clone);
-       if (!auth) {
-               err = -EIO;
-               goto out_shutdown;
-       }
-       err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode,
-                                                 &path->dentry->d_name,
-                                                 fh, fattr);
-out_shutdown:
-       rpc_shutdown_client(clone);
-out:
-       return err;
+       if (NFS_PROTO(dir)->version == 4)
+               return nfs4_proc_lookup_mountpoint(dir, name, fh, fattr);
+
+       err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
+       if (err)
+               return ERR_PTR(err);
+       return rpc_clone_client(NFS_SERVER(dir)->client);
 }
 #else /* CONFIG_NFS_V4 */
-static inline int nfs_lookup_with_sec(struct nfs_server *server,
-                                     struct dentry *parent, struct dentry *dentry,
-                                     struct path *path, struct nfs_fh *fh,
-                                     struct nfs_fattr *fattr,
-                                     rpc_authflavor_t *flavor)
+static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
+                                                    struct qstr *name,
+                                                    struct nfs_fh *fh,
+                                                    struct nfs_fattr *fattr)
 {
-       return -EPERM;
+       int err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
+       if (err)
+               return ERR_PTR(err);
+       return rpc_clone_client(NFS_SERVER(dir)->client);
 }
 #endif /* CONFIG_NFS_V4 */
 
@@ -226,12 +191,10 @@ static inline int nfs_lookup_with_sec(struct nfs_server *server,
 struct vfsmount *nfs_d_automount(struct path *path)
 {
        struct vfsmount *mnt;
-       struct nfs_server *server = NFS_SERVER(path->dentry->d_inode);
        struct dentry *parent;
        struct nfs_fh *fh = NULL;
        struct nfs_fattr *fattr = NULL;
-       int err;
-       rpc_authflavor_t flavor = RPC_AUTH_UNIX;
+       struct rpc_clnt *client;
 
        dprintk("--> nfs_d_automount()\n");
 
@@ -249,21 +212,19 @@ struct vfsmount *nfs_d_automount(struct path *path)
 
        /* Look it up again to get its attributes */
        parent = dget_parent(path->dentry);
-       err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode,
-                                                 &path->dentry->d_name,
-                                                 fh, fattr);
-       if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL)
-               err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor);
+       client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr);
        dput(parent);
-       if (err != 0) {
-               mnt = ERR_PTR(err);
+       if (IS_ERR(client)) {
+               mnt = ERR_CAST(client);
                goto out;
        }
 
        if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
-               mnt = nfs_do_refmount(path->dentry);
+               mnt = nfs_do_refmount(client, path->dentry);
        else
-               mnt = nfs_do_submount(path->dentry, fh, fattr, flavor);
+               mnt = nfs_do_submount(path->dentry, fh, fattr, client->cl_auth->au_flavor);
+       rpc_shutdown_client(client);
+
        if (IS_ERR(mnt))
                goto out;
 
index 97ecc863dd76b46900e23758d4cbdda2f28f63d0..8d75021020b31f44f0fcb9ec6f1ff05a8b39b313 100644 (file)
@@ -59,6 +59,7 @@ struct nfs_unique_id {
 
 #define NFS_SEQID_CONFIRMED 1
 struct nfs_seqid_counter {
+       ktime_t create_time;
        int owner_id;
        int flags;
        u32 counter;
@@ -204,6 +205,9 @@ struct nfs4_state_maintenance_ops {
 extern const struct dentry_operations nfs4_dentry_operations;
 extern const struct inode_operations nfs4_dir_inode_operations;
 
+/* nfs4namespace.c */
+struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *);
+
 /* nfs4proc.c */
 extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
 extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
@@ -212,8 +216,11 @@ extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
-extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
-               struct nfs4_fs_locations *fs_locations, struct page *page);
+extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *,
+                                 struct nfs4_fs_locations *, struct page *);
+extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *,
+                           struct nfs_fh *, struct nfs_fattr *);
+extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
 extern int nfs4_release_lockowner(struct nfs4_lock_state *);
 extern const struct xattr_handler *nfs4_xattr_handlers[];
 
index a866bbd2890a056b530ebe3ae91cd74b0862f4a1..c9cff9adb2d3f7c832f3e3bc7e6d76ec45a6e692 100644 (file)
@@ -699,7 +699,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_fla
         * GETDEVICEINFO's maxcount
         */
        max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
-       max_pages = max_resp_sz >> PAGE_SHIFT;
+       max_pages = nfs_page_array_len(0, max_resp_sz);
        dprintk("%s inode %p max_resp_sz %u max_pages %d\n",
                __func__, inode, max_resp_sz, max_pages);
 
index 9c8eca315f431199aa481c0eabc6ae3e044f8267..a7f3dedc4ec7bade9df84ed6f0fc7524507b9c21 100644 (file)
@@ -51,6 +51,30 @@ Elong:
        return ERR_PTR(-ENAMETOOLONG);
 }
 
+/*
+ * return the path component of "<server>:<path>"
+ *  nfspath - the "<server>:<path>" string
+ *  end - one past the last char that could contain "<server>:"
+ * returns NULL on failure
+ */
+static char *nfs_path_component(const char *nfspath, const char *end)
+{
+       char *p;
+
+       if (*nfspath == '[') {
+               /* parse [] escaped IPv6 addrs */
+               p = strchr(nfspath, ']');
+               if (p != NULL && ++p < end && *p == ':')
+                       return p + 1;
+       } else {
+               /* otherwise split on first colon */
+               p = strchr(nfspath, ':');
+               if (p != NULL && p < end)
+                       return p + 1;
+       }
+       return NULL;
+}
+
 /*
  * Determine the mount path as a string
  */
@@ -59,9 +83,9 @@ static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
        char *limit;
        char *path = nfs_path(&limit, dentry, buffer, buflen);
        if (!IS_ERR(path)) {
-               char *colon = strchr(path, ':');
-               if (colon && colon < limit)
-                       path = colon + 1;
+               char *path_component = nfs_path_component(path, limit);
+               if (path_component)
+                       return path_component;
        }
        return path;
 }
@@ -108,6 +132,58 @@ static size_t nfs_parse_server_name(char *string, size_t len,
        return ret;
 }
 
+static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name)
+{
+       struct page *page;
+       struct nfs4_secinfo_flavors *flavors;
+       rpc_authflavor_t flavor;
+       int err;
+
+       page = alloc_page(GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
+       flavors = page_address(page);
+
+       err = nfs4_proc_secinfo(inode, name, flavors);
+       if (err < 0) {
+               flavor = err;
+               goto out;
+       }
+
+       flavor = nfs_find_best_sec(flavors);
+
+out:
+       put_page(page);
+       return flavor;
+}
+
+/*
+ * Please call rpc_shutdown_client() when you are done with this client.
+ */
+struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *clnt, struct inode *inode,
+                                       struct qstr *name)
+{
+       struct rpc_clnt *clone;
+       struct rpc_auth *auth;
+       rpc_authflavor_t flavor;
+
+       flavor = nfs4_negotiate_security(inode, name);
+       if (flavor < 0)
+               return ERR_PTR(flavor);
+
+       clone = rpc_clone_client(clnt);
+       if (IS_ERR(clone))
+               return clone;
+
+       auth = rpcauth_create(flavor, clone);
+       if (!auth) {
+               rpc_shutdown_client(clone);
+               clone = ERR_PTR(-EIO);
+       }
+
+       return clone;
+}
+
 static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
                                     char *page, char *page2,
                                     const struct nfs4_fs_location *location)
@@ -224,7 +300,7 @@ out:
  * @dentry - dentry of referral
  *
  */
-struct vfsmount *nfs_do_refmount(struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
 {
        struct vfsmount *mnt = ERR_PTR(-ENOMEM);
        struct dentry *parent;
@@ -250,7 +326,7 @@ struct vfsmount *nfs_do_refmount(struct dentry *dentry)
        dprintk("%s: getting locations for %s/%s\n",
                __func__, parent->d_name.name, dentry->d_name.name);
 
-       err = nfs4_proc_fs_locations(parent->d_inode, &dentry->d_name, fs_locations, page);
+       err = nfs4_proc_fs_locations(client, parent->d_inode, &dentry->d_name, fs_locations, page);
        dput(parent);
        if (err != 0 ||
            fs_locations->nlocations <= 0 ||
index f82bde005a822435fe8c4e7e20e99a60f3a5764c..99650aaf8937a28a52f9fca9946771f61379a8c7 100644 (file)
@@ -838,7 +838,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
        p->o_arg.open_flags = flags;
        p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
        p->o_arg.clientid = server->nfs_client->cl_clientid;
-       p->o_arg.id = sp->so_seqid.owner_id;
+       p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
+       p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
        p->o_arg.name = &dentry->d_name;
        p->o_arg.server = server;
        p->o_arg.bitmask = server->attr_bitmask;
@@ -1466,8 +1467,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
                        goto unlock_no_action;
                rcu_read_unlock();
        }
-       /* Update sequence id. */
-       data->o_arg.id = sp->so_seqid.owner_id;
+       /* Update client id. */
        data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
        if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
                task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
@@ -1954,10 +1954,19 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
        };
        int err;
        do {
-               err = nfs4_handle_exception(server,
-                               _nfs4_do_setattr(inode, cred, fattr, sattr, state),
-                               &exception);
+               err = _nfs4_do_setattr(inode, cred, fattr, sattr, state);
+               switch (err) {
+               case -NFS4ERR_OPENMODE:
+                       if (state && !(state->state & FMODE_WRITE)) {
+                               err = -EBADF;
+                               if (sattr->ia_valid & ATTR_OPEN)
+                                       err = -EACCES;
+                               goto out;
+                       }
+               }
+               err = nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
+out:
        return err;
 }
 
@@ -2368,8 +2377,9 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  * Note that we'll actually follow the referral later when
  * we detect fsid mismatch in inode revalidation
  */
-static int nfs4_get_referral(struct inode *dir, const struct qstr *name,
-                            struct nfs_fattr *fattr, struct nfs_fh *fhandle)
+static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir,
+                            const struct qstr *name, struct nfs_fattr *fattr,
+                            struct nfs_fh *fhandle)
 {
        int status = -ENOMEM;
        struct page *page = NULL;
@@ -2382,7 +2392,7 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name,
        if (locations == NULL)
                goto out;
 
-       status = nfs4_proc_fs_locations(dir, name, locations, page);
+       status = nfs4_proc_fs_locations(client, dir, name, locations, page);
        if (status != 0)
                goto out;
        /* Make sure server returned a different fsid for the referral */
@@ -2519,39 +2529,84 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
        return status;
 }
 
-void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh)
+static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr)
 {
-       memset(fh, 0, sizeof(struct nfs_fh));
-       fattr->fsid.major = 1;
        fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
-               NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT;
+               NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_MOUNTPOINT;
        fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
        fattr->nlink = 2;
 }
 
-static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name,
-                           struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
+                                  struct qstr *name, struct nfs_fh *fhandle,
+                                  struct nfs_fattr *fattr)
 {
        struct nfs4_exception exception = { };
+       struct rpc_clnt *client = *clnt;
        int err;
        do {
-               int status;
-
-               status = _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr);
-               switch (status) {
+               err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr);
+               switch (err) {
                case -NFS4ERR_BADNAME:
-                       return -ENOENT;
+                       err = -ENOENT;
+                       goto out;
                case -NFS4ERR_MOVED:
-                       return nfs4_get_referral(dir, name, fattr, fhandle);
+                       err = nfs4_get_referral(client, dir, name, fattr, fhandle);
+                       goto out;
                case -NFS4ERR_WRONGSEC:
-                       nfs_fixup_secinfo_attributes(fattr, fhandle);
+                       err = -EPERM;
+                       if (client != *clnt)
+                               goto out;
+
+                       client = nfs4_create_sec_client(client, dir, name);
+                       if (IS_ERR(client))
+                               return PTR_ERR(client);
+
+                       exception.retry = 1;
+                       break;
+               default:
+                       err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
                }
-               err = nfs4_handle_exception(NFS_SERVER(dir),
-                               status, &exception);
        } while (exception.retry);
+
+out:
+       if (err == 0)
+               *clnt = client;
+       else if (client != *clnt)
+               rpc_shutdown_client(client);
+
        return err;
 }
 
+static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name,
+                           struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+{
+       int status;
+       struct rpc_clnt *client = NFS_CLIENT(dir);
+
+       status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr);
+       if (client != NFS_CLIENT(dir)) {
+               rpc_shutdown_client(client);
+               nfs_fixup_secinfo_attributes(fattr);
+       }
+       return status;
+}
+
+struct rpc_clnt *
+nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name,
+                           struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+{
+       int status;
+       struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir));
+
+       status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr);
+       if (status < 0) {
+               rpc_shutdown_client(client);
+               return ERR_PTR(status);
+       }
+       return client;
+}
+
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
        struct nfs_server *server = NFS_SERVER(inode);
@@ -3619,16 +3674,16 @@ out:
        return ret;
 }
 
-static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len)
+static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
 {
        struct nfs4_cached_acl *acl;
 
-       if (buf && acl_len <= PAGE_SIZE) {
+       if (pages && acl_len <= PAGE_SIZE) {
                acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
                if (acl == NULL)
                        goto out;
                acl->cached = 1;
-               memcpy(acl->data, buf, acl_len);
+               _copy_from_pages(acl->data, pages, pgbase, acl_len);
        } else {
                acl = kmalloc(sizeof(*acl), GFP_KERNEL);
                if (acl == NULL)
@@ -3661,7 +3716,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
        struct nfs_getaclres res = {
                .acl_len = buflen,
        };
-       void *resp_buf;
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
                .rpc_argp = &args,
@@ -3675,24 +3729,27 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
        if (npages == 0)
                npages = 1;
 
+       /* Add an extra page to handle the bitmap returned */
+       npages++;
+
        for (i = 0; i < npages; i++) {
                pages[i] = alloc_page(GFP_KERNEL);
                if (!pages[i])
                        goto out_free;
        }
-       if (npages > 1) {
-               /* for decoding across pages */
-               res.acl_scratch = alloc_page(GFP_KERNEL);
-               if (!res.acl_scratch)
-                       goto out_free;
-       }
+
+       /* for decoding across pages */
+       res.acl_scratch = alloc_page(GFP_KERNEL);
+       if (!res.acl_scratch)
+               goto out_free;
+
        args.acl_len = npages * PAGE_SIZE;
        args.acl_pgbase = 0;
+
        /* Let decode_getfacl know not to fail if the ACL data is larger than
         * the page we send as a guess */
        if (buf == NULL)
                res.acl_flags |= NFS4_ACL_LEN_REQUEST;
-       resp_buf = page_address(pages[0]);
 
        dprintk("%s  buf %p buflen %zu npages %d args.acl_len %zu\n",
                __func__, buf, buflen, npages, args.acl_len);
@@ -3703,9 +3760,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
 
        acl_len = res.acl_len - res.acl_data_offset;
        if (acl_len > args.acl_len)
-               nfs4_write_cached_acl(inode, NULL, acl_len);
+               nfs4_write_cached_acl(inode, NULL, 0, acl_len);
        else
-               nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset,
+               nfs4_write_cached_acl(inode, pages, res.acl_data_offset,
                                      acl_len);
        if (buf) {
                ret = -ERANGE;
@@ -4558,7 +4615,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
 static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
-       struct nfs4_exception exception = { };
+       struct nfs4_exception exception = {
+               .inode = state->inode,
+       };
        int err;
 
        do {
@@ -4576,7 +4635,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
 static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
-       struct nfs4_exception exception = { };
+       struct nfs4_exception exception = {
+               .inode = state->inode,
+       };
        int err;
 
        err = nfs4_set_lock_state(state, request);
@@ -4676,6 +4737,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *
 {
        struct nfs4_exception exception = {
                .state = state,
+               .inode = state->inode,
        };
        int err;
 
@@ -4721,6 +4783,20 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
 
        if (state == NULL)
                return -ENOLCK;
+       /*
+        * Don't rely on the VFS having checked the file open mode,
+        * since it won't do this for flock() locks.
+        */
+       switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) {
+       case F_RDLCK:
+               if (!(filp->f_mode & FMODE_READ))
+                       return -EBADF;
+               break;
+       case F_WRLCK:
+               if (!(filp->f_mode & FMODE_WRITE))
+                       return -EBADF;
+       }
+
        do {
                status = nfs4_proc_setlk(state, cmd, request);
                if ((status != -EAGAIN) || IS_SETLK(cmd))
@@ -4891,8 +4967,10 @@ static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr)
        fattr->nlink = 2;
 }
 
-int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
-               struct nfs4_fs_locations *fs_locations, struct page *page)
+static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
+                                  const struct qstr *name,
+                                  struct nfs4_fs_locations *fs_locations,
+                                  struct page *page)
 {
        struct nfs_server *server = NFS_SERVER(dir);
        u32 bitmask[2] = {
@@ -4926,11 +5004,26 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
        nfs_fattr_init(&fs_locations->fattr);
        fs_locations->server = server;
        fs_locations->nlocations = 0;
-       status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+       status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0);
        dprintk("%s: returned status = %d\n", __func__, status);
        return status;
 }
 
+int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
+                          const struct qstr *name,
+                          struct nfs4_fs_locations *fs_locations,
+                          struct page *page)
+{
+       struct nfs4_exception exception = { };
+       int err;
+       do {
+               err = nfs4_handle_exception(NFS_SERVER(dir),
+                               _nfs4_proc_fs_locations(client, dir, name, fs_locations, page),
+                               &exception);
+       } while (exception.retry);
+       return err;
+}
+
 static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors)
 {
        int status;
@@ -4953,8 +5046,8 @@ static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct
        return status;
 }
 
-static int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
-               struct nfs4_secinfo_flavors *flavors)
+int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
+                     struct nfs4_secinfo_flavors *flavors)
 {
        struct nfs4_exception exception = { };
        int err;
@@ -5029,10 +5122,9 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
        nfs4_construct_boot_verifier(clp, &verifier);
 
        args.id_len = scnprintf(args.id, sizeof(args.id),
-                               "%s/%s.%s/%u",
+                               "%s/%s/%u",
                                clp->cl_ipaddr,
-                               init_utsname()->nodename,
-                               init_utsname()->domainname,
+                               clp->cl_rpcclient->cl_nodename,
                                clp->cl_rpcclient->cl_auth->au_flavor);
 
        res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL);
index 0f43414eb25a141be336c34bef78cc126cd9039f..7f0fcfc1fe9db51e9bc3748f511163dfed7cdce7 100644 (file)
@@ -393,6 +393,7 @@ nfs4_remove_state_owner_locked(struct nfs4_state_owner *sp)
 static void
 nfs4_init_seqid_counter(struct nfs_seqid_counter *sc)
 {
+       sc->create_time = ktime_get();
        sc->flags = 0;
        sc->counter = 0;
        spin_lock_init(&sc->lock);
@@ -434,13 +435,17 @@ nfs4_alloc_state_owner(struct nfs_server *server,
 static void
 nfs4_drop_state_owner(struct nfs4_state_owner *sp)
 {
-       if (!RB_EMPTY_NODE(&sp->so_server_node)) {
+       struct rb_node *rb_node = &sp->so_server_node;
+
+       if (!RB_EMPTY_NODE(rb_node)) {
                struct nfs_server *server = sp->so_server;
                struct nfs_client *clp = server->nfs_client;
 
                spin_lock(&clp->cl_lock);
-               rb_erase(&sp->so_server_node, &server->state_owners);
-               RB_CLEAR_NODE(&sp->so_server_node);
+               if (!RB_EMPTY_NODE(rb_node)) {
+                       rb_erase(rb_node, &server->state_owners);
+                       RB_CLEAR_NODE(rb_node);
+               }
                spin_unlock(&clp->cl_lock);
        }
 }
@@ -516,6 +521,14 @@ out:
 /**
  * nfs4_put_state_owner - Release a nfs4_state_owner
  * @sp: state owner data to release
+ *
+ * Note that we keep released state owners on an LRU
+ * list.
+ * This caches valid state owners so that they can be
+ * reused, to avoid the OPEN_CONFIRM on minor version 0.
+ * It also pins the uniquifier of dropped state owners for
+ * a while, to ensure that those state owner names are
+ * never reused.
  */
 void nfs4_put_state_owner(struct nfs4_state_owner *sp)
 {
@@ -525,15 +538,9 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
        if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock))
                return;
 
-       if (!RB_EMPTY_NODE(&sp->so_server_node)) {
-               sp->so_expires = jiffies;
-               list_add_tail(&sp->so_lru, &server->state_owners_lru);
-               spin_unlock(&clp->cl_lock);
-       } else {
-               nfs4_remove_state_owner_locked(sp);
-               spin_unlock(&clp->cl_lock);
-               nfs4_free_state_owner(sp);
-       }
+       sp->so_expires = jiffies;
+       list_add_tail(&sp->so_lru, &server->state_owners_lru);
+       spin_unlock(&clp->cl_lock);
 }
 
 /**
index c74fdb114b48af141a719d1facd11ed249c5f5d1..c54aae364beebd38833151f97328c3edfe7c2337 100644 (file)
@@ -74,7 +74,7 @@ static int nfs4_stat_to_errno(int);
 /* lock,open owner id:
  * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT  >> 2)
  */
-#define open_owner_id_maxsz    (1 + 1 + 4)
+#define open_owner_id_maxsz    (1 + 2 + 1 + 1 + 2)
 #define lock_owner_id_maxsz    (1 + 1 + 4)
 #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
 #define compound_encode_hdr_maxsz      (3 + (NFS4_MAXTAGLEN >> 2))
@@ -1340,12 +1340,13 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
  */
        encode_nfs4_seqid(xdr, arg->seqid);
        encode_share_access(xdr, arg->fmode);
-       p = reserve_space(xdr, 32);
+       p = reserve_space(xdr, 36);
        p = xdr_encode_hyper(p, arg->clientid);
-       *p++ = cpu_to_be32(20);
+       *p++ = cpu_to_be32(24);
        p = xdr_encode_opaque_fixed(p, "open id:", 8);
        *p++ = cpu_to_be32(arg->server->s_dev);
-       xdr_encode_hyper(p, arg->id);
+       *p++ = cpu_to_be32(arg->id.uniquifier);
+       xdr_encode_hyper(p, arg->id.create_time);
 }
 
 static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
@@ -4257,8 +4258,6 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
        status = decode_attr_error(xdr, bitmap, &err);
        if (status < 0)
                goto xdr_error;
-       if (err == -NFS4ERR_WRONGSEC)
-               nfs_fixup_secinfo_attributes(fattr, fh);
 
        status = decode_attr_filehandle(xdr, bitmap, fh);
        if (status < 0)
@@ -4901,11 +4900,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
                 bitmap[3] = {0};
        struct kvec *iov = req->rq_rcv_buf.head;
        int status;
+       size_t page_len = xdr->buf->page_len;
 
        res->acl_len = 0;
        if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
                goto out;
+
        bm_p = xdr->p;
+       res->acl_data_offset = be32_to_cpup(bm_p) + 2;
+       res->acl_data_offset <<= 2;
+       /* Check if the acl data starts beyond the allocated buffer */
+       if (res->acl_data_offset > page_len)
+               return -ERANGE;
+
        if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
                goto out;
        if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
@@ -4915,28 +4922,24 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
                return -EIO;
        if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
                size_t hdrlen;
-               u32 recvd;
 
                /* The bitmap (xdr len + bitmaps) and the attr xdr len words
                 * are stored with the acl data to handle the problem of
                 * variable length bitmaps.*/
                xdr->p = bm_p;
-               res->acl_data_offset = be32_to_cpup(bm_p) + 2;
-               res->acl_data_offset <<= 2;
 
                /* We ignore &savep and don't do consistency checks on
                 * the attr length.  Let userspace figure it out.... */
                hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
                attrlen += res->acl_data_offset;
-               recvd = req->rq_rcv_buf.len - hdrlen;
-               if (attrlen > recvd) {
+               if (attrlen > page_len) {
                        if (res->acl_flags & NFS4_ACL_LEN_REQUEST) {
                                /* getxattr interface called with a NULL buf */
                                res->acl_len = attrlen;
                                goto out;
                        }
-                       dprintk("NFS: acl reply: attrlen %u > recvd %u\n",
-                                       attrlen, recvd);
+                       dprintk("NFS: acl reply: attrlen %u > page_len %zu\n",
+                                       attrlen, page_len);
                        return -EINVAL;
                }
                xdr_read_pages(xdr, attrlen);
@@ -5089,16 +5092,13 @@ out_err:
        return -EINVAL;
 }
 
-static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
 {
        struct nfs4_secinfo_flavor *sec_flavor;
        int status;
        __be32 *p;
        int i, num_flavors;
 
-       status = decode_op_hdr(xdr, OP_SECINFO);
-       if (status)
-               goto out;
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                goto out_overflow;
@@ -5124,6 +5124,7 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
                res->flavors->num_flavors++;
        }
 
+       status = 0;
 out:
        return status;
 out_overflow:
@@ -5131,7 +5132,23 @@ out_overflow:
        return -EIO;
 }
 
+static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+{
+       int status = decode_op_hdr(xdr, OP_SECINFO);
+       if (status)
+               return status;
+       return decode_secinfo_common(xdr, res);
+}
+
 #if defined(CONFIG_NFS_V4_1)
+static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+{
+       int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME);
+       if (status)
+               return status;
+       return decode_secinfo_common(xdr, res);
+}
+
 static int decode_exchange_id(struct xdr_stream *xdr,
                              struct nfs41_exchange_id_res *res)
 {
@@ -6816,7 +6833,7 @@ static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp,
        status = decode_putrootfh(xdr);
        if (status)
                goto out;
-       status = decode_secinfo(xdr, res);
+       status = decode_secinfo_no_name(xdr, res);
 out:
        return status;
 }
index 8d45f1c318ce40ac453b7b4a71288e71ba3c6a34..595c5fc21a19d15efaab48bff059336d7762c1b3 100644 (file)
@@ -604,7 +604,6 @@ int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay,
 {
        struct objlayout_deviceinfo *odi;
        struct pnfs_device pd;
-       struct super_block *sb;
        struct page *page, **pages;
        u32 *p;
        int err;
@@ -623,7 +622,6 @@ int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay,
        pd.pglen = PAGE_SIZE;
        pd.mincount = 0;
 
-       sb = pnfslay->plh_inode->i_sb;
        err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd);
        dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err);
        if (err)
index b5d4515869436dc6bd16a483590a433ac04c665c..38512bcd2e98b4c82e3b03e2592061c06897abe5 100644 (file)
@@ -587,7 +587,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
 
        /* allocate pages for xdr post processing */
        max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
-       max_pages = max_resp_sz >> PAGE_SHIFT;
+       max_pages = nfs_page_array_len(0, max_resp_sz);
 
        pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags);
        if (!pages)
index 9a0e8ef4a40948d83d87d7a0898a49d55c3099c1..0a4be28c2ea3c76f57321bf765708924c4a2fdcf 100644 (file)
@@ -322,7 +322,7 @@ out_bad:
        while (!list_empty(res)) {
                data = list_entry(res->next, struct nfs_read_data, list);
                list_del(&data->list);
-               nfs_readdata_free(data);
+               nfs_readdata_release(data);
        }
        nfs_readpage_release(req);
        return -ENOMEM;
index 37412f706b32c83d5e0b3a95ae8665038ef43d68..4ac7fca7e4bf32fc01ac980c26dfcb255325f3b1 100644 (file)
@@ -2428,7 +2428,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
        dprintk("--> nfs_xdev_mount()\n");
 
        /* create a new volume representation */
-       server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+       server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
        if (IS_ERR(server)) {
                error = PTR_ERR(server);
                goto out_err_noserver;
@@ -2767,11 +2767,15 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
        char *root_devname;
        size_t len;
 
-       len = strlen(hostname) + 3;
+       len = strlen(hostname) + 5;
        root_devname = kmalloc(len, GFP_KERNEL);
        if (root_devname == NULL)
                return ERR_PTR(-ENOMEM);
-       snprintf(root_devname, len, "%s:/", hostname);
+       /* Does hostname needs to be enclosed in brackets? */
+       if (strchr(hostname, ':'))
+               snprintf(root_devname, len, "[%s]:/", hostname);
+       else
+               snprintf(root_devname, len, "%s:/", hostname);
        root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
        kfree(root_devname);
        return root_mnt;
@@ -2951,7 +2955,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
        dprintk("--> nfs4_xdev_mount()\n");
 
        /* create a new volume representation */
-       server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+       server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
        if (IS_ERR(server)) {
                error = PTR_ERR(server);
                goto out_err_noserver;
index 2c68818f68ac056b8587c22bf40f8f5d229a6403..c07462320f6b5c41c09ba2ff054e75048951691f 100644 (file)
@@ -682,7 +682,8 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode,
                req->wb_bytes = rqend - req->wb_offset;
 out_unlock:
        spin_unlock(&inode->i_lock);
-       nfs_clear_request_commit(req);
+       if (req)
+               nfs_clear_request_commit(req);
        return req;
 out_flushme:
        spin_unlock(&inode->i_lock);
@@ -1018,7 +1019,7 @@ out_bad:
        while (!list_empty(res)) {
                data = list_entry(res->next, struct nfs_write_data, list);
                list_del(&data->list);
-               nfs_writedata_free(data);
+               nfs_writedata_release(data);
        }
        nfs_redirty_request(req);
        return -ENOMEM;
index 08c6e36ab2eb05d8c28f68394a326573a7f52658..43f46cd9edea84e18040381a2647a54ca59debb0 100644 (file)
@@ -803,13 +803,13 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
        return p;
 }
 
-static int
+static __be32
 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
                const char *name, int namlen)
 {
        struct svc_export       *exp;
        struct dentry           *dparent, *dchild;
-       int rv = 0;
+       __be32 rv = nfserr_noent;
 
        dparent = cd->fh.fh_dentry;
        exp  = cd->fh.fh_export;
@@ -817,26 +817,20 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
        if (isdotent(name, namlen)) {
                if (namlen == 2) {
                        dchild = dget_parent(dparent);
-                       if (dchild == dparent) {
-                               /* filesystem root - cannot return filehandle for ".." */
-                               dput(dchild);
-                               return -ENOENT;
-                       }
+                       /* filesystem root - cannot return filehandle for ".." */
+                       if (dchild == dparent)
+                               goto out;
                } else
                        dchild = dget(dparent);
        } else
                dchild = lookup_one_len(name, dparent, namlen);
        if (IS_ERR(dchild))
-               return -ENOENT;
-       rv = -ENOENT;
+               return rv;
        if (d_mountpoint(dchild))
                goto out;
-       rv = fh_compose(fhp, exp, dchild, &cd->fh);
-       if (rv)
-               goto out;
        if (!dchild->d_inode)
                goto out;
-       rv = 0;
+       rv = fh_compose(fhp, exp, dchild, &cd->fh);
 out:
        dput(dchild);
        return rv;
@@ -845,7 +839,7 @@ out:
 static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
 {
        struct svc_fh   fh;
-       int err;
+       __be32 err;
 
        fh_init(&fh, NFS3_FHSIZE);
        err = compose_entry_fh(cd, &fh, name, namlen);
index 2ed14dfd00a231e9c813b78b3d728bcdfb849b06..987e719fbae8c64f2776f914e7f4104ee04be492 100644 (file)
@@ -235,15 +235,15 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
                 */
                if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
                        open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
-                                               FATTR4_WORD1_TIME_MODIFY);
+                                                       FATTR4_WORD1_TIME_MODIFY);
        } else {
                status = nfsd_lookup(rqstp, current_fh,
                                     open->op_fname.data, open->op_fname.len, resfh);
                fh_unlock(current_fh);
-               if (status)
-                       goto out;
-               status = nfsd_check_obj_isreg(resfh);
        }
+       if (status)
+               goto out;
+       status = nfsd_check_obj_isreg(resfh);
        if (status)
                goto out;
 
@@ -841,6 +841,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
              struct nfsd4_setattr *setattr)
 {
        __be32 status = nfs_ok;
+       int err;
 
        if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
                nfs4_lock_state();
@@ -852,9 +853,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                        return status;
                }
        }
-       status = fh_want_write(&cstate->current_fh);
-       if (status)
-               return status;
+       err = fh_want_write(&cstate->current_fh);
+       if (err)
+               return nfserrno(err);
        status = nfs_ok;
 
        status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
index 4767429264a25b3e6003953c8d3f1e70627b075d..ed3f9206a0ee87c914f133492f1f6011775bdef8 100644 (file)
@@ -577,7 +577,7 @@ cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        struct cld_net *cn = nn->cld_net;
 
        if (mlen != sizeof(*cmsg)) {
-               dprintk("%s: got %lu bytes, expected %lu\n", __func__, mlen,
+               dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen,
                        sizeof(*cmsg));
                return -EINVAL;
        }
index 1841f8bf845e7440bba605f25357a512a8a5b0b0..7f71c69cdcdfdcbd7245a71820b9f13e1a0bb135 100644 (file)
@@ -4211,16 +4211,14 @@ out:
  * vfs_test_lock.  (Arguably perhaps test_lock should be done with an
  * inode operation.)
  */
-static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
+static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
 {
        struct file *file;
-       int err;
-
-       err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
-       if (err)
-               return err;
-       err = vfs_test_lock(file, lock);
-       nfsd_close(file);
+       __be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
+       if (!err) {
+               err = nfserrno(vfs_test_lock(file, lock));
+               nfsd_close(file);
+       }
        return err;
 }
 
@@ -4234,7 +4232,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct inode *inode;
        struct file_lock file_lock;
        struct nfs4_lockowner *lo;
-       int error;
        __be32 status;
 
        if (locks_in_grace())
@@ -4280,12 +4277,10 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        nfs4_transform_lock_offset(&file_lock);
 
-       status = nfs_ok;
-       error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
-       if (error) {
-               status = nfserrno(error);
+       status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
+       if (status)
                goto out;
-       }
+
        if (file_lock.fl_type != F_UNLCK) {
                status = nfserr_denied;
                nfs4_set_lock_denied(&file_lock, &lockt->lt_denied);
index bcd8904ab1e36dd807f26379392000fb114f9bc6..74c00bc92b9af6b01e95e55c119b90d61fbf9d34 100644 (file)
@@ -1392,7 +1392,7 @@ nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_sta
        for (i = 0; i < test_stateid->ts_num_ids; i++) {
                stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL);
                if (!stateid) {
-                       status = PTR_ERR(stateid);
+                       status = nfserrno(-ENOMEM);
                        goto out;
                }
 
@@ -3410,7 +3410,7 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr,
        *p++ = htonl(test_stateid->ts_num_ids);
 
        list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) {
-               *p++ = htonl(stateid->ts_id_status);
+               *p++ = stateid->ts_id_status;
        }
 
        ADJUST_ARGS();
index 296d671654d6a12fbb89567ea6b80cfd26a1829f..568666156ea4f59525d67207551ee8c45a3b730e 100644 (file)
@@ -1458,7 +1458,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                switch (createmode) {
                case NFS3_CREATE_UNCHECKED:
                        if (! S_ISREG(dchild->d_inode->i_mode))
-                               err = nfserr_exist;
+                               goto out;
                        else if (truncp) {
                                /* in nfsv4, we need to treat this case a little
                                 * differently.  we don't want to truncate the
index 3165aebb43c87934b743ecf08e5f02cef586d771..31b9463fba1fb19259da764d94372ffffc0f6008 100644 (file)
@@ -1134,7 +1134,7 @@ static int ocfs2_adjust_rightmost_branch(handle_t *handle,
        }
 
        el = path_leaf_el(path);
-       rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1];
+       rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec) - 1];
 
        ocfs2_adjust_rightmost_records(handle, et, path, rec);
 
index cf782338266421779e5ba8fa165786b006f4c2aa..9f32d7cbb7a3701f1f28d938b17ae4d057dc4e84 100644 (file)
@@ -1036,14 +1036,14 @@ static int ocfs2_get_refcount_cpos_end(struct ocfs2_caching_info *ci,
 
        tmp_el = left_path->p_node[subtree_root].el;
        blkno = left_path->p_node[subtree_root+1].bh->b_blocknr;
-       for (i = 0; i < le32_to_cpu(tmp_el->l_next_free_rec); i++) {
+       for (i = 0; i < le16_to_cpu(tmp_el->l_next_free_rec); i++) {
                if (le64_to_cpu(tmp_el->l_recs[i].e_blkno) == blkno) {
                        *cpos_end = le32_to_cpu(tmp_el->l_recs[i+1].e_cpos);
                        break;
                }
        }
 
-       BUG_ON(i == le32_to_cpu(tmp_el->l_next_free_rec));
+       BUG_ON(i == le16_to_cpu(tmp_el->l_next_free_rec));
 
 out:
        ocfs2_free_path(left_path);
@@ -1468,7 +1468,7 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh,
 
        trace_ocfs2_divide_leaf_refcount_block(
                (unsigned long long)ref_leaf_bh->b_blocknr,
-               le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used));
+               le16_to_cpu(rl->rl_count), le16_to_cpu(rl->rl_used));
 
        /*
         * XXX: Improvement later.
@@ -2411,7 +2411,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
                                rb = (struct ocfs2_refcount_block *)
                                                        prev_bh->b_data;
 
-                               if (le64_to_cpu(rb->rf_records.rl_used) +
+                               if (le16_to_cpu(rb->rf_records.rl_used) +
                                    recs_add >
                                    le16_to_cpu(rb->rf_records.rl_count))
                                        ref_blocks++;
@@ -2476,7 +2476,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
        if (prev_bh) {
                rb = (struct ocfs2_refcount_block *)prev_bh->b_data;
 
-               if (le64_to_cpu(rb->rf_records.rl_used) + recs_add >
+               if (le16_to_cpu(rb->rf_records.rl_used) + recs_add >
                    le16_to_cpu(rb->rf_records.rl_count))
                        ref_blocks++;
 
@@ -3629,7 +3629,7 @@ int ocfs2_refcounted_xattr_delete_need(struct inode *inode,
                         * one will split a refcount rec, so totally we need
                         * clusters * 2 new refcount rec.
                         */
-                       if (le64_to_cpu(rb->rf_records.rl_used) + clusters * 2 >
+                       if (le16_to_cpu(rb->rf_records.rl_used) + clusters * 2 >
                            le16_to_cpu(rb->rf_records.rl_count))
                                ref_blocks++;
 
index ba5d97e4a73e8a43e64fc3cfa55fb9b97d4ec6a5..f169da4624fd07c5964c3d24d3b65e8a0dcd5ed7 100644 (file)
@@ -600,7 +600,7 @@ static void ocfs2_bg_alloc_cleanup(handle_t *handle,
                ret = ocfs2_free_clusters(handle, cluster_ac->ac_inode,
                                          cluster_ac->ac_bh,
                                          le64_to_cpu(rec->e_blkno),
-                                         le32_to_cpu(rec->e_leaf_clusters));
+                                         le16_to_cpu(rec->e_leaf_clusters));
                if (ret)
                        mlog_errno(ret);
                /* Try all the clusters to free */
@@ -1628,7 +1628,7 @@ static int ocfs2_bg_discontig_fix_by_rec(struct ocfs2_suballoc_result *res,
 {
        unsigned int bpc = le16_to_cpu(cl->cl_bpc);
        unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc;
-       unsigned int bitcount = le32_to_cpu(rec->e_leaf_clusters) * bpc;
+       unsigned int bitcount = le16_to_cpu(rec->e_leaf_clusters) * bpc;
 
        if (res->sr_bit_offset < bitoff)
                return 0;
index 25feaa3faac068eba842438f9171f78ff189d7f8..fec5e4ad071a36bb8783bdcc8c40c07c614340a5 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -346,6 +346,16 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
        .get = generic_pipe_buf_get,
 };
 
+static const struct pipe_buf_operations packet_pipe_buf_ops = {
+       .can_merge = 0,
+       .map = generic_pipe_buf_map,
+       .unmap = generic_pipe_buf_unmap,
+       .confirm = generic_pipe_buf_confirm,
+       .release = anon_pipe_buf_release,
+       .steal = generic_pipe_buf_steal,
+       .get = generic_pipe_buf_get,
+};
+
 static ssize_t
 pipe_read(struct kiocb *iocb, const struct iovec *_iov,
           unsigned long nr_segs, loff_t pos)
@@ -407,6 +417,13 @@ redo:
                        ret += chars;
                        buf->offset += chars;
                        buf->len -= chars;
+
+                       /* Was it a packet buffer? Clean up and exit */
+                       if (buf->flags & PIPE_BUF_FLAG_PACKET) {
+                               total_len = chars;
+                               buf->len = 0;
+                       }
+
                        if (!buf->len) {
                                buf->ops = NULL;
                                ops->release(pipe, buf);
@@ -459,6 +476,11 @@ redo:
        return ret;
 }
 
+static inline int is_packetized(struct file *file)
+{
+       return (file->f_flags & O_DIRECT) != 0;
+}
+
 static ssize_t
 pipe_write(struct kiocb *iocb, const struct iovec *_iov,
            unsigned long nr_segs, loff_t ppos)
@@ -593,6 +615,11 @@ redo2:
                        buf->ops = &anon_pipe_buf_ops;
                        buf->offset = 0;
                        buf->len = chars;
+                       buf->flags = 0;
+                       if (is_packetized(filp)) {
+                               buf->ops = &packet_pipe_buf_ops;
+                               buf->flags = PIPE_BUF_FLAG_PACKET;
+                       }
                        pipe->nrbufs = ++bufs;
                        pipe->tmp_page = NULL;
 
@@ -1013,7 +1040,7 @@ struct file *create_write_pipe(int flags)
                goto err_dentry;
        f->f_mapping = inode->i_mapping;
 
-       f->f_flags = O_WRONLY | (flags & O_NONBLOCK);
+       f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
        f->f_version = 0;
 
        return f;
@@ -1057,7 +1084,7 @@ int do_pipe_flags(int *fd, int flags)
        int error;
        int fdw, fdr;
 
-       if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+       if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT))
                return -EINVAL;
 
        fw = create_write_pipe(flags);
index 46a15d8a29ca74d9ca0a68a57e416108e6b599f3..eed44bfc85db7c6ea420233dd09c2e5b9b5f0350 100644 (file)
@@ -115,12 +115,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
        if (IS_ERR(sb))
                return ERR_CAST(sb);
 
+       if (!proc_parse_options(options, ns)) {
+               deactivate_locked_super(sb);
+               return ERR_PTR(-EINVAL);
+       }
+
        if (!sb->s_root) {
                sb->s_flags = flags;
-               if (!proc_parse_options(options, ns)) {
-                       deactivate_locked_super(sb);
-                       return ERR_PTR(-EINVAL);
-               }
                err = proc_fill_super(sb);
                if (err) {
                        deactivate_locked_super(sb);
index 6a0c62d6e4428bf38711d0afcd4d860061f0feb6..64c3b3172367abbd1c1464b9372f33ee4efa7acb 100644 (file)
 #ifndef arch_irq_stat
 #define arch_irq_stat() 0
 #endif
-#ifndef arch_idle_time
-#define arch_idle_time(cpu) 0
-#endif
+
+#ifdef arch_idle_time
+
+static cputime64_t get_idle_time(int cpu)
+{
+       cputime64_t idle;
+
+       idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
+       if (cpu_online(cpu) && !nr_iowait_cpu(cpu))
+               idle += arch_idle_time(cpu);
+       return idle;
+}
+
+static cputime64_t get_iowait_time(int cpu)
+{
+       cputime64_t iowait;
+
+       iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
+       if (cpu_online(cpu) && nr_iowait_cpu(cpu))
+               iowait += arch_idle_time(cpu);
+       return iowait;
+}
+
+#else
 
 static u64 get_idle_time(int cpu)
 {
        u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL);
 
-       if (idle_time == -1ULL) {
+       if (idle_time == -1ULL)
                /* !NO_HZ so we can rely on cpustat.idle */
                idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
-               idle += arch_idle_time(cpu);
-       } else
+       else
                idle = usecs_to_cputime64(idle_time);
 
        return idle;
@@ -49,6 +69,8 @@ static u64 get_iowait_time(int cpu)
        return iowait;
 }
 
+#endif
+
 static int show_stat(struct seq_file *p, void *v)
 {
        int i, j;
index 2b9a7607cbd5496084ec386fcc2377752ab75107..2d60492d6df80c2e97694b066836b6c1377a570a 100644 (file)
@@ -597,9 +597,6 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
                if (!page)
                        continue;
 
-               if (PageReserved(page))
-                       continue;
-
                /* Clear accessed and referenced bits. */
                ptep_test_and_clear_young(vma, addr, pte);
                ClearPageReferenced(page);
index 50952c9bd06c0c460097eeedface267575f11aa5..19507889bb7ff123b3922fa439fc0c8ef1ded913 100644 (file)
@@ -52,12 +52,6 @@ struct pstore_private {
        char    data[];
 };
 
-static int pstore_file_open(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
                                                size_t count, loff_t *ppos)
 {
@@ -67,7 +61,7 @@ static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
 }
 
 static const struct file_operations pstore_file_operations = {
-       .open   = pstore_file_open,
+       .open   = simple_open,
        .read   = pstore_file_read,
        .llseek = default_llseek,
 };
index 5f883de7ef3ad0bd8dfe9392356725660f9a69b3..f8476841eb04e08edc2ad069e97cddc3da242e7f 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/uio.h>
 #include <linux/security.h>
 #include <linux/gfp.h>
+#include <linux/socket.h>
 
 /*
  * Attempt to steal a page from a pipe buffer. This should perhaps go into
@@ -690,7 +691,9 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe,
        if (!likely(file->f_op && file->f_op->sendpage))
                return -EINVAL;
 
-       more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
+       more = (sd->flags & SPLICE_F_MORE) ? MSG_MORE : 0;
+       if (sd->len < sd->total_len)
+               more |= MSG_SENDPAGE_NOTLAST;
        return file->f_op->sendpage(file, buf->page, buf->offset,
                                    sd->len, &pos, more);
 }
index 2a7a3f5d1ca6d69ac5508fa85310867e339615c0..35a36d39fa2cb2af62616918872706794a20d8e1 100644 (file)
@@ -729,6 +729,9 @@ int sysfs_create_dir(struct kobject * kobj)
        else
                parent_sd = &sysfs_root;
 
+       if (!parent_sd)
+               return -ENOENT;
+
        if (sysfs_ns_type(parent_sd))
                ns = kobj->ktype->namespace(kobj);
        type = sysfs_read_ns_type(kobj);
@@ -878,7 +881,6 @@ int sysfs_rename(struct sysfs_dirent *sd,
 
                dup_name = sd->s_name;
                sd->s_name = new_name;
-               sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
        }
 
        /* Move to the appropriate place in the appropriate directories rbtree. */
@@ -886,6 +888,7 @@ int sysfs_rename(struct sysfs_dirent *sd,
        sysfs_get(new_parent_sd);
        sysfs_put(sd->s_parent);
        sd->s_ns = new_ns;
+       sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
        sd->s_parent = new_parent_sd;
        sysfs_link_sibling(sd);
 
index dd1701caecc94bcfe38625052dd7564ded19c379..2df555c66d57d463381042632ae124ad53aecb42 100644 (file)
@@ -67,7 +67,11 @@ static int internal_create_group(struct kobject *kobj, int update,
        /* Updates may happen before the object has been instantiated */
        if (unlikely(update && !kobj->sd))
                return -EINVAL;
-
+       if (!grp->attrs) {
+               WARN(1, "sysfs: attrs not set by subsystem for group: %s/%s\n",
+                       kobj->name, grp->name ? "" : grp->name);
+               return -EINVAL;
+       }
        if (grp->name) {
                error = sysfs_create_subdir(kobj, grp->name, &sd);
                if (error)
index d6dfd247bb2f4425fdfbd9c57b892a07c3922847..3c8c1cc333c7c79dfa105049a62d8b6e1c28661c 100644 (file)
@@ -19,8 +19,9 @@
 #include <linux/export.h>
 #include <linux/fsnotify.h>
 #include <linux/audit.h>
-#include <asm/uaccess.h>
+#include <linux/vmalloc.h>
 
+#include <asm/uaccess.h>
 
 /*
  * Check permissions for extended attribute access.  This is a bit complicated
@@ -320,6 +321,7 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
 {
        int error;
        void *kvalue = NULL;
+       void *vvalue = NULL;    /* If non-NULL, we used vmalloc() */
        char kname[XATTR_NAME_MAX + 1];
 
        if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
@@ -334,13 +336,25 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
        if (size) {
                if (size > XATTR_SIZE_MAX)
                        return -E2BIG;
-               kvalue = memdup_user(value, size);
-               if (IS_ERR(kvalue))
-                       return PTR_ERR(kvalue);
+               kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
+               if (!kvalue) {
+                       vvalue = vmalloc(size);
+                       if (!vvalue)
+                               return -ENOMEM;
+                       kvalue = vvalue;
+               }
+               if (copy_from_user(kvalue, value, size)) {
+                       error = -EFAULT;
+                       goto out;
+               }
        }
 
        error = vfs_setxattr(d, kname, kvalue, size, flags);
-       kfree(kvalue);
+out:
+       if (vvalue)
+               vfree(vvalue);
+       else
+               kfree(kvalue);
        return error;
 }
 
@@ -492,13 +506,18 @@ listxattr(struct dentry *d, char __user *list, size_t size)
 {
        ssize_t error;
        char *klist = NULL;
+       char *vlist = NULL;     /* If non-NULL, we used vmalloc() */
 
        if (size) {
                if (size > XATTR_LIST_MAX)
                        size = XATTR_LIST_MAX;
-               klist = kmalloc(size, GFP_KERNEL);
-               if (!klist)
-                       return -ENOMEM;
+               klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
+               if (!klist) {
+                       vlist = vmalloc(size);
+                       if (!vlist)
+                               return -ENOMEM;
+                       klist = vlist;
+               }
        }
 
        error = vfs_listxattr(d, klist, size);
@@ -510,7 +529,10 @@ listxattr(struct dentry *d, char __user *list, size_t size)
                   than XATTR_LIST_MAX bytes. Not possible. */
                error = -E2BIG;
        }
-       kfree(klist);
+       if (vlist)
+               vfree(vlist);
+       else
+               kfree(klist);
        return error;
 }
 
index eba66043cf1b7d1dccfc1956446ea9bafdbb588c..e8bcc4742e0e9a1f9563a27907871ab6ce727817 100644 (file)
@@ -499,9 +499,10 @@ typedef u64 acpi_integer;
 #define ACPI_STATE_D0                   (u8) 0
 #define ACPI_STATE_D1                   (u8) 1
 #define ACPI_STATE_D2                   (u8) 2
-#define ACPI_STATE_D3                   (u8) 3
-#define ACPI_STATE_D3_COLD              (u8) 4
-#define ACPI_D_STATES_MAX               ACPI_STATE_D3_COLD
+#define ACPI_STATE_D3_HOT               (u8) 3
+#define ACPI_STATE_D3                   (u8) 4
+#define ACPI_STATE_D3_COLD              ACPI_STATE_D3
+#define ACPI_D_STATES_MAX               ACPI_STATE_D3
 #define ACPI_D_STATE_COUNT              5
 
 #define ACPI_STATE_C0                   (u8) 0
index 8a361834dc25887e658107a3bf5dbf5f8142752d..14883026015dc50be00508f8eccf9cf805ea0ef4 100644 (file)
@@ -10,6 +10,7 @@
 #error "Cannot use generic cmpxchg on SMP"
 #endif
 
+#include <linux/types.h>
 #include <linux/irqflags.h>
 
 #ifndef xchg
index 0dd4e87f6fba9bb85dade657f99aa1fbafa2712f..5e5e3865f1edb3df5b928b6d0b2951b91c3dbccc 100644 (file)
@@ -35,6 +35,14 @@ typedef union sigval {
 #define __ARCH_SI_BAND_T long
 #endif
 
+#ifndef __ARCH_SI_CLOCK_T
+#define __ARCH_SI_CLOCK_T __kernel_clock_t
+#endif
+
+#ifndef __ARCH_SI_ATTRIBUTES
+#define __ARCH_SI_ATTRIBUTES
+#endif
+
 #ifndef HAVE_ARCH_SIGINFO_T
 
 typedef struct siginfo {
@@ -72,8 +80,8 @@ typedef struct siginfo {
                        __kernel_pid_t _pid;    /* which child */
                        __ARCH_SI_UID_T _uid;   /* sender's uid */
                        int _status;            /* exit code */
-                       __kernel_clock_t _utime;
-                       __kernel_clock_t _stime;
+                       __ARCH_SI_CLOCK_T _utime;
+                       __ARCH_SI_CLOCK_T _stime;
                } _sigchld;
 
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -91,7 +99,7 @@ typedef struct siginfo {
                        int _fd;
                } _sigpoll;
        } _sifields;
-} siginfo_t;
+} __ARCH_SI_ATTRIBUTES siginfo_t;
 
 #endif
 
index 0fd28e028de1d83130aeb751294159dffc39fa6a..c749af9c0983022876bffacf1aea628c270d4a34 100644 (file)
@@ -15,7 +15,7 @@ typedef __kernel_fsid_t       fsid_t;
  * with a 10' pole.
  */
 #ifndef __statfs_word
-#if BITS_PER_LONG == 64
+#if __BITS_PER_LONG == 64
 #define __statfs_word long
 #else
 #define __statfs_word __u32
index d838c945575a73bf313a809edece47ee27ad16a2..2eba340230a73a63e8a1472a20ff0ed0a451d981 100644 (file)
@@ -31,6 +31,8 @@ static inline void crypto_set_aead_spawn(
        crypto_set_spawn(&spawn->base, inst);
 }
 
+struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask);
+
 int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
                     u32 type, u32 mask);
 
index 3a748a6bf772b25e83e8657024cddea8f40d8026..06e8b32d541c57280edbf06fdd03772a84fa55ff 100644 (file)
@@ -34,6 +34,8 @@ static inline void crypto_set_skcipher_spawn(
 int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
                         u32 type, u32 mask);
 
+struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask);
+
 static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn)
 {
        crypto_drop_spawn(&spawn->base);
index 34a7b89fd0069841463e8089da0b03eb96bfa5b4..64ff02d5b73056f81d03ff2e54b784e3943ba658 100644 (file)
@@ -617,6 +617,17 @@ struct drm_get_cap {
        __u64 value;
 };
 
+#define DRM_CLOEXEC O_CLOEXEC
+struct drm_prime_handle {
+       __u32 handle;
+
+       /** Flags.. only applicable for handle->fd */
+       __u32 flags;
+
+       /** Returned dmabuf file descriptor */
+       __s32 fd;
+};
+
 #include "drm_mode.h"
 
 #define DRM_IOCTL_BASE                 'd'
@@ -673,7 +684,8 @@ struct drm_get_cap {
 #define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, struct drm_lock)
 #define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, struct drm_lock)
 
-#define DRM_IOCTL_GEM_PRIME_OPEN        DRM_IOWR(0x2e, struct drm_gem_open)
+#define DRM_IOCTL_PRIME_HANDLE_TO_FD    DRM_IOWR(0x2d, struct drm_prime_handle)
+#define DRM_IOCTL_PRIME_FD_TO_HANDLE    DRM_IOWR(0x2e, struct drm_prime_handle)
 
 #define DRM_IOCTL_AGP_ACQUIRE          DRM_IO(  0x30)
 #define DRM_IOCTL_AGP_RELEASE          DRM_IO(  0x31)
index 574bd1c81ebddfa3cb410d17178f48bfc0f00994..efd12490376144d195b8798d903c98d3c377f92d 100644 (file)
@@ -91,6 +91,7 @@ struct drm_device;
 #define DRM_UT_CORE            0x01
 #define DRM_UT_DRIVER          0x02
 #define DRM_UT_KMS             0x04
+#define DRM_UT_PRIME           0x08
 /*
  * Three debug levels are defined.
  * drm_core, drm_driver, drm_kms
@@ -150,6 +151,7 @@ int drm_err(const char *func, const char *format, ...);
 #define DRIVER_IRQ_VBL2    0x800
 #define DRIVER_GEM         0x1000
 #define DRIVER_MODESET     0x2000
+#define DRIVER_PRIME       0x4000
 
 #define DRIVER_BUS_PCI 0x1
 #define DRIVER_BUS_PLATFORM 0x2
@@ -215,6 +217,11 @@ int drm_err(const char *func, const char *format, ...);
                drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME,               \
                                         __func__, fmt, ##args);        \
        } while (0)
+#define DRM_DEBUG_PRIME(fmt, args...)                                  \
+       do {                                                            \
+               drm_ut_debug_printk(DRM_UT_PRIME, DRM_NAME,             \
+                                       __func__, fmt, ##args);         \
+       } while (0)
 #define DRM_LOG(fmt, args...)                                          \
        do {                                                            \
                drm_ut_debug_printk(DRM_UT_CORE, NULL,                  \
@@ -238,6 +245,7 @@ int drm_err(const char *func, const char *format, ...);
 #else
 #define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0)
 #define DRM_DEBUG_KMS(fmt, args...)    do { } while (0)
+#define DRM_DEBUG_PRIME(fmt, args...)  do { } while (0)
 #define DRM_DEBUG(fmt, arg...)          do { } while (0)
 #define DRM_LOG(fmt, arg...)           do { } while (0)
 #define DRM_LOG_KMS(fmt, args...) do { } while (0)
@@ -410,6 +418,12 @@ struct drm_pending_event {
        void (*destroy)(struct drm_pending_event *event);
 };
 
+/* initial implementaton using a linked list - todo hashtab */
+struct drm_prime_file_private {
+       struct list_head head;
+       struct mutex lock;
+};
+
 /** File private data */
 struct drm_file {
        int authenticated;
@@ -437,6 +451,8 @@ struct drm_file {
        wait_queue_head_t event_wait;
        struct list_head event_list;
        int event_space;
+
+       struct drm_prime_file_private prime;
 };
 
 /** Wait queue */
@@ -652,6 +668,12 @@ struct drm_gem_object {
        uint32_t pending_write_domain;
 
        void *driver_private;
+
+       /* dma buf exported from this GEM object */
+       struct dma_buf *export_dma_buf;
+
+       /* dma buf attachment backing this object */
+       struct dma_buf_attachment *import_attach;
 };
 
 #include "drm_crtc.h"
@@ -890,6 +912,20 @@ struct drm_driver {
        int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
        void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
 
+       /* prime: */
+       /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */
+       int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
+                               uint32_t handle, uint32_t flags, int *prime_fd);
+       /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */
+       int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv,
+                               int prime_fd, uint32_t *handle);
+       /* export GEM -> dmabuf */
+       struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
+                               struct drm_gem_object *obj, int flags);
+       /* import dmabuf -> GEM */
+       struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
+                               struct dma_buf *dma_buf);
+
        /* vga arb irq handler */
        void (*vgaarb_irq)(struct drm_device *dev, bool state);
 
@@ -1273,8 +1309,8 @@ extern int drm_release(struct inode *inode, struct file *filp);
                                /* Mapping support (drm_vm.h) */
 extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
 extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
-extern void drm_vm_open_locked(struct vm_area_struct *vma);
-extern void drm_vm_close_locked(struct vm_area_struct *vma);
+extern void drm_vm_open_locked(struct drm_device *dev, struct vm_area_struct *vma);
+extern void drm_vm_close_locked(struct drm_device *dev, struct vm_area_struct *vma);
 extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
 
                                /* Memory management support (drm_memory.h) */
@@ -1342,6 +1378,7 @@ extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
 
 /* Cache management (drm_cache.c) */
 void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
+void drm_clflush_virt_range(char *addr, unsigned long length);
 
                                /* Locking IOCTL support (drm_lock.h) */
 extern int drm_lock(struct drm_device *dev, void *data,
@@ -1509,6 +1546,32 @@ extern int drm_vblank_info(struct seq_file *m, void *data);
 extern int drm_clients_info(struct seq_file *m, void* data);
 extern int drm_gem_name_info(struct seq_file *m, void *data);
 
+
+extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
+               struct drm_file *file_priv, uint32_t handle, uint32_t flags,
+               int *prime_fd);
+extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+               struct drm_file *file_priv, int prime_fd, uint32_t *handle);
+
+extern int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
+                                       struct drm_file *file_priv);
+extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
+                                       struct drm_file *file_priv);
+
+extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages);
+extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
+
+
+void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
+void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
+int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
+int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
+void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
+
+int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj);
+int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf,
+                        struct drm_gem_object **obj);
+
 #if DRM_DEBUG_CODE
 extern int drm_vma_info(struct seq_file *m, void *data);
 #endif
index e250eda4e3a894c790d1e8f6ea9e7e57d7400c41..f35e7edd7de2578c630ba4fca7cfb027f452a732 100644 (file)
@@ -1012,10 +1012,11 @@ extern int drm_add_modes_noedid(struct drm_connector *connector,
                                int hdisplay, int vdisplay);
 
 extern int drm_edid_header_is_valid(const u8 *raw_edid);
-extern bool drm_edid_block_valid(u8 *raw_edid);
+extern bool drm_edid_block_valid(u8 *raw_edid, int block);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
-                                          int hsize, int vsize, int fresh);
+                                          int hsize, int vsize, int fresh,
+                                          bool rb);
 
 extern int drm_mode_create_dumb_ioctl(struct drm_device *dev,
                                      void *data, struct drm_file *file_priv);
@@ -1026,4 +1027,9 @@ extern int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
 
 extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
                                 int *bpp);
+extern int drm_format_num_planes(uint32_t format);
+extern int drm_format_plane_cpp(uint32_t format, int plane);
+extern int drm_format_horz_chroma_subsampling(uint32_t format);
+extern int drm_format_vert_chroma_subsampling(uint32_t format);
+
 #endif /* __DRM_CRTC_H__ */
index 37515d1afab31bb4ccca0e2391eac06fe8d2b553..3add00e03388b68cbb53f6e4e2683252ab485599 100644 (file)
@@ -145,6 +145,4 @@ extern void drm_helper_hpd_irq_event(struct drm_device *dev);
 extern void drm_kms_helper_poll_disable(struct drm_device *dev);
 extern void drm_kms_helper_poll_enable(struct drm_device *dev);
 
-extern int drm_format_num_planes(uint32_t format);
-
 #endif
index bcb9a66baa8c948ac4bbe462caa303647cd28d3d..0cac551c5347d44f42904eaf17769fd82de61776 100644 (file)
@@ -90,12 +90,26 @@ struct detailed_data_monitor_range {
        u8 min_hfreq_khz;
        u8 max_hfreq_khz;
        u8 pixel_clock_mhz; /* need to multiply by 10 */
-       __le16 sec_gtf_toggle; /* A000=use above, 20=use below */
-       u8 hfreq_start_khz; /* need to multiply by 2 */
-       u8 c; /* need to divide by 2 */
-       __le16 m;
-       u8 k;
-       u8 j; /* need to divide by 2 */
+       u8 flags;
+       union {
+               struct {
+                       u8 reserved;
+                       u8 hfreq_start_khz; /* need to multiply by 2 */
+                       u8 c; /* need to divide by 2 */
+                       __le16 m;
+                       u8 k;
+                       u8 j; /* need to divide by 2 */
+               } __attribute__((packed)) gtf2;
+               struct {
+                       u8 version;
+                       u8 data1; /* high 6 bits: extra clock resolution */
+                       u8 data2; /* plus low 2 of above: max hactive */
+                       u8 supported_aspects;
+                       u8 flags; /* preferred aspect and blanking support */
+                       u8 supported_scalings;
+                       u8 preferred_refresh;
+               } __attribute__((packed)) cvt;
+       } formula;
 } __attribute__((packed));
 
 struct detailed_data_wpindex {
index 4a08a664ff1f243fd14cdc094215627e7a626605..0ead502e17d27638fef2bb7df81d9118967b2010 100644 (file)
@@ -37,6 +37,7 @@ typedef union dfixed {
 #define dfixed_init(A) { .full = dfixed_const((A)) }
 #define dfixed_init_half(A) { .full = dfixed_const_half((A)) }
 #define dfixed_trunc(A) ((A).full >> 12)
+#define dfixed_frac(A) ((A).full & ((1 << 12) - 1))
 
 static inline u32 dfixed_floor(fixed20_12 A)
 {
index 3963116083aeae56fdb3aa9056e86daf8200ed9c..e478de4e5d564e936302d753e65ac4e52768b3a7 100644 (file)
@@ -85,7 +85,7 @@ struct drm_exynos_gem_mmap {
 struct drm_exynos_vidi_connection {
        unsigned int connection;
        unsigned int extensions;
-       uint64_t *edid;
+       uint64_t edid;
 };
 
 struct drm_exynos_plane_set_zpos {
@@ -96,7 +96,8 @@ struct drm_exynos_plane_set_zpos {
 /* memory type definitions. */
 enum e_drm_exynos_gem_mem_type {
        /* Physically Non-Continuous memory. */
-       EXYNOS_BO_NONCONTIG     = 1 << 0
+       EXYNOS_BO_NONCONTIG     = 1 << 0,
+       EXYNOS_BO_MASK          = EXYNOS_BO_NONCONTIG
 };
 
 #define DRM_EXYNOS_GEM_CREATE          0x00
index da929bb5b7886e3387cd130ab3b0ee5aac2abb71..f3f82242bf1dc9312551c9b2526ce892bcb5ed5b 100644 (file)
@@ -296,7 +296,8 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_EXEC_CONSTANTS   14
 #define I915_PARAM_HAS_RELAXED_DELTA    15
 #define I915_PARAM_HAS_GEN7_SOL_RESET   16
-#define I915_PARAM_HAS_LLC              17
+#define I915_PARAM_HAS_LLC                      17
+#define I915_PARAM_HAS_ALIASING_PPGTT   18
 
 typedef struct drm_i915_getparam {
        int param;
index 0a0001b9dc7853e5fb0d84b1e3b6950429afe7f8..923afb5dcf0c21df155828ec1258e8f383cc0af0 100644 (file)
@@ -44,4 +44,8 @@ void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries,
 /* flag for GFDT type */
 #define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)
 
+#ifdef CONFIG_INTEL_IOMMU
+extern int intel_iommu_gfx_mapped;
+#endif
+
 #endif
index 7c491b4bcf65d2b2682cbb0bed67ee6817ed3abe..58056865b8e9601bc40da73198a82d0bcb406960 100644 (file)
@@ -926,7 +926,6 @@ struct drm_radeon_cs_chunk {
 };
 
 /* drm_radeon_cs_reloc.flags */
-#define RADEON_RELOC_DONT_SYNC         0x01
 
 struct drm_radeon_cs_reloc {
        uint32_t                handle;
index d05df2810354737714bec9f1f897657036ddc150..3c9b616c834a39601247a29f99fe08979317bf25 100644 (file)
@@ -3,6 +3,7 @@ header-y += can/
 header-y += caif/
 header-y += dvb/
 header-y += hdlc/
+header-y += hsi/
 header-y += isdn/
 header-y += mmc/
 header-y += nfsd/
index 7847e197730ac86cc480092d5dd525499d106716..8d54f79457ba54ae2c85ce1a0e03c0ca5a34e8fc 100644 (file)
@@ -30,7 +30,6 @@ struct amba_device {
        struct device           dev;
        struct resource         res;
        struct clk              *pclk;
-       struct regulator        *vcore;
        u64                     dma_mask;
        unsigned int            periphid;
        unsigned int            irq[AMBA_NR_IRQS];
@@ -75,12 +74,6 @@ void amba_release_regions(struct amba_device *);
 #define amba_pclk_disable(d)   \
        do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)
 
-#define amba_vcore_enable(d)   \
-       (IS_ERR((d)->vcore) ? 0 : regulator_enable((d)->vcore))
-
-#define amba_vcore_disable(d)  \
-       do { if (!IS_ERR((d)->vcore)) regulator_disable((d)->vcore); } while (0)
-
 /* Some drivers don't use the struct amba_device */
 #define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
 #define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
index b8c51124ed19b9b8368ebeb631c543b51029d31a..76dd1b199a1b0e55a39e34d34f6f228ea30a0016 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef _SSP_PL022_H
 #define _SSP_PL022_H
 
+#include <linux/types.h>
+
 /**
  * whether SSP is in loopback mode or not
  */
index 606cf339bb561f6b526c2a58ddcf1378c8376bf1..2aa24664a5b53a2b178d1ee52fd3c2731b18aaf0 100644 (file)
@@ -426,14 +426,10 @@ struct request_queue {
                                 (1 << QUEUE_FLAG_SAME_COMP)    |       \
                                 (1 << QUEUE_FLAG_ADD_RANDOM))
 
-static inline int queue_is_locked(struct request_queue *q)
+static inline void queue_lockdep_assert_held(struct request_queue *q)
 {
-#ifdef CONFIG_SMP
-       spinlock_t *lock = q->queue_lock;
-       return lock && spin_is_locked(lock);
-#else
-       return 1;
-#endif
+       if (q->queue_lock)
+               lockdep_assert_held(q->queue_lock);
 }
 
 static inline void queue_flag_set_unlocked(unsigned int flag,
@@ -445,7 +441,7 @@ static inline void queue_flag_set_unlocked(unsigned int flag,
 static inline int queue_flag_test_and_clear(unsigned int flag,
                                            struct request_queue *q)
 {
-       WARN_ON_ONCE(!queue_is_locked(q));
+       queue_lockdep_assert_held(q);
 
        if (test_bit(flag, &q->queue_flags)) {
                __clear_bit(flag, &q->queue_flags);
@@ -458,7 +454,7 @@ static inline int queue_flag_test_and_clear(unsigned int flag,
 static inline int queue_flag_test_and_set(unsigned int flag,
                                          struct request_queue *q)
 {
-       WARN_ON_ONCE(!queue_is_locked(q));
+       queue_lockdep_assert_held(q);
 
        if (!test_bit(flag, &q->queue_flags)) {
                __set_bit(flag, &q->queue_flags);
@@ -470,7 +466,7 @@ static inline int queue_flag_test_and_set(unsigned int flag,
 
 static inline void queue_flag_set(unsigned int flag, struct request_queue *q)
 {
-       WARN_ON_ONCE(!queue_is_locked(q));
+       queue_lockdep_assert_held(q);
        __set_bit(flag, &q->queue_flags);
 }
 
@@ -487,7 +483,7 @@ static inline int queue_in_flight(struct request_queue *q)
 
 static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
 {
-       WARN_ON_ONCE(!queue_is_locked(q));
+       queue_lockdep_assert_held(q);
        __clear_bit(flag, &q->queue_flags);
 }
 
index 1ffdb9856bb9fcc0592a939e98de7447e10266af..a2c819d3c96e3d367b4de11b852efea54a79e80d 100644 (file)
@@ -764,12 +764,6 @@ static inline const struct cpumask *get_cpu_mask(unsigned int cpu)
  *
  */
 #ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
-/* These strip const, as traditionally they weren't const. */
-#define cpu_possible_map       (*(cpumask_t *)cpu_possible_mask)
-#define cpu_online_map         (*(cpumask_t *)cpu_online_mask)
-#define cpu_present_map                (*(cpumask_t *)cpu_present_mask)
-#define cpu_active_map         (*(cpumask_t *)cpu_active_mask)
-
 #define cpumask_of_cpu(cpu) (*get_cpu_mask(cpu))
 
 #define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)
index 532fb58f16bf9a417f869d7fe24149e6283d4ff6..4abf2ea6a88761dd0980cba05553737c769bf72d 100644 (file)
@@ -100,3 +100,6 @@ struct crypto_report_rng {
        char type[CRYPTO_MAX_NAME];
        unsigned int seedsize;
 };
+
+#define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \
+                              sizeof(struct crypto_report_blkcipher))
index 71ad34eca6e3d124f9175e79d536a39379ee02fa..547ab568d3ae83f940e503c6999719f37a73547e 100644 (file)
@@ -13,6 +13,8 @@
 enum dma_attr {
        DMA_ATTR_WRITE_BARRIER,
        DMA_ATTR_WEAK_ORDERING,
+       DMA_ATTR_WRITE_COMBINE,
+       DMA_ATTR_NON_CONSISTENT,
        DMA_ATTR_MAX,
 };
 
index 5a736af3cc7a3623574794554ab510c29c596a30..dfc099e56a66187ba9d223eea924da5650e462bf 100644 (file)
@@ -9,10 +9,15 @@
 #include <linux/scatterlist.h>
 
 struct dma_map_ops {
-       void* (*alloc_coherent)(struct device *dev, size_t size,
-                               dma_addr_t *dma_handle, gfp_t gfp);
-       void (*free_coherent)(struct device *dev, size_t size,
-                             void *vaddr, dma_addr_t dma_handle);
+       void* (*alloc)(struct device *dev, size_t size,
+                               dma_addr_t *dma_handle, gfp_t gfp,
+                               struct dma_attrs *attrs);
+       void (*free)(struct device *dev, size_t size,
+                             void *vaddr, dma_addr_t dma_handle,
+                             struct dma_attrs *attrs);
+       int (*mmap)(struct device *, struct vm_area_struct *,
+                         void *, dma_addr_t, size_t, struct dma_attrs *attrs);
+
        dma_addr_t (*map_page)(struct device *dev, struct page *page,
                               unsigned long offset, size_t size,
                               enum dma_data_direction dir,
index 676f967390aeb8ccfe4983a9fab04285d62ce58d..f9a2e5e67a5423e204389b8d01e0f83d41df1a30 100644 (file)
@@ -974,6 +974,7 @@ int dma_async_device_register(struct dma_device *device);
 void dma_async_device_unregister(struct dma_device *device);
 void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
 struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
+struct dma_chan *net_dma_find_channel(void);
 #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
 
 /* --- Helper iov-locking functions --- */
index 88ec80670d5ff1da744a4a5d9174fb8c6f3512da..ec45ccd8708a85f54a903d769b0b5c2fbaf8bc3f 100644 (file)
@@ -554,7 +554,18 @@ extern int __init efi_setup_pcdp_console(char *);
 #define EFI_VARIABLE_NON_VOLATILE       0x0000000000000001
 #define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
 #define EFI_VARIABLE_RUNTIME_ACCESS     0x0000000000000004
-
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
+#define EFI_VARIABLE_APPEND_WRITE      0x0000000000000040
+
+#define EFI_VARIABLE_MASK      (EFI_VARIABLE_NON_VOLATILE | \
+                               EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+                               EFI_VARIABLE_RUNTIME_ACCESS | \
+                               EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+                               EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+                               EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
+                               EFI_VARIABLE_APPEND_WRITE)
 /*
  * The type of search to perform when calling boottime->locate_handle
  */
index e1d9e0ede3095a080c0a40cefa70799a0654e756..f5647b59a90e6ade8f551096c6e7bc19193156ae 100644 (file)
@@ -896,8 +896,7 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
  *
  * All operations are optional (i.e. the function pointer may be set
  * to %NULL) and callers must take this into account.  Callers must
- * hold the RTNL, except that for @get_drvinfo the caller may or may
- * not hold the RTNL.
+ * hold the RTNL lock.
  *
  * See the structures used by these operations for further documentation.
  *
index 4db7b68f058240ed0611fb0616d5c5ea91e79279..cdc9b719e9c7e285e85878677a64ff4b3d7d3501 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_FIREWIRE_H
 
 #include <linux/completion.h>
+#include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/kref.h>
@@ -64,8 +65,6 @@
 #define CSR_MODEL              0x17
 #define CSR_DIRECTORY_ID       0x20
 
-struct device;
-
 struct fw_csr_iterator {
        const u32 *p;
        const u32 *end;
index 135693e79f2b0d1a86597c27b5003ff57313204d..8de675523e464db26c649928610fb4a69bac7a40 100644 (file)
@@ -1215,6 +1215,7 @@ extern int vfs_setlease(struct file *, long, struct file_lock **);
 extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
+extern void locks_delete_block(struct file_lock *waiter);
 extern void lock_flocks(void);
 extern void unlock_flocks(void);
 #else /* !CONFIG_FILE_LOCKING */
@@ -1359,6 +1360,10 @@ static inline int lock_may_write(struct inode *inode, loff_t start,
        return 1;
 }
 
+static inline void locks_delete_block(struct file_lock *waiter)
+{
+}
+
 static inline void lock_flocks(void)
 {
 }
@@ -2506,6 +2511,7 @@ extern int dcache_readdir(struct file *, void *, filldir_t);
 extern int simple_setattr(struct dentry *, struct iattr *);
 extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int simple_statfs(struct dentry *, struct kstatfs *);
+extern int simple_open(struct inode *inode, struct file *file);
 extern int simple_link(struct dentry *, struct inode *, struct dentry *);
 extern int simple_unlink(struct inode *, struct dentry *);
 extern int simple_rmdir(struct inode *, struct dentry *);
index 8ba2c9460b28fb90bfee024aa8f73601f6c4cf68..8f2ab8fef929f42b81f3d9a75c564b42455dc06e 100644 (file)
@@ -593,7 +593,7 @@ struct fuse_dirent {
        __u64   off;
        __u32   namelen;
        __u32   type;
-       char name[0];
+       char name[];
 };
 
 #define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
index 05071ee34c3f5332ecf0ca9bc4c6766e01ca1d01..d755b28ba63541cc1f803993573c66aa3870eed5 100644 (file)
@@ -13,4 +13,8 @@ extern int pxa_last_gpio;
 
 extern int pxa_irq_to_gpio(int irq);
 
+struct pxa_gpio_platform_data {
+       int (*gpio_set_wake)(unsigned int gpio, unsigned int on);
+};
+
 #endif /* __GPIO_PXA_H */
diff --git a/include/linux/hsi/Kbuild b/include/linux/hsi/Kbuild
new file mode 100644 (file)
index 0000000..271a770
--- /dev/null
@@ -0,0 +1 @@
+header-y += hsi_char.h
diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h
new file mode 100644 (file)
index 0000000..56fae86
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * HSI core header file.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_HSI_H__
+#define __LINUX_HSI_H__
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+
+/* HSI message ttype */
+#define HSI_MSG_READ   0
+#define HSI_MSG_WRITE  1
+
+/* HSI configuration values */
+enum {
+       HSI_MODE_STREAM = 1,
+       HSI_MODE_FRAME,
+};
+
+enum {
+       HSI_FLOW_SYNC,  /* Synchronized flow */
+       HSI_FLOW_PIPE,  /* Pipelined flow */
+};
+
+enum {
+       HSI_ARB_RR,     /* Round-robin arbitration */
+       HSI_ARB_PRIO,   /* Channel priority arbitration */
+};
+
+#define HSI_MAX_CHANNELS       16
+
+/* HSI message status codes */
+enum {
+       HSI_STATUS_COMPLETED,   /* Message transfer is completed */
+       HSI_STATUS_PENDING,     /* Message pending to be read/write (POLL) */
+       HSI_STATUS_PROCEEDING,  /* Message transfer is ongoing */
+       HSI_STATUS_QUEUED,      /* Message waiting to be served */
+       HSI_STATUS_ERROR,       /* Error when message transfer was ongoing */
+};
+
+/* HSI port event codes */
+enum {
+       HSI_EVENT_START_RX,
+       HSI_EVENT_STOP_RX,
+};
+
+/**
+ * struct hsi_config - Configuration for RX/TX HSI modules
+ * @mode: Bit transmission mode (STREAM or FRAME)
+ * @channels: Number of channels to use [1..16]
+ * @speed: Max bit transmission speed (Kbit/s)
+ * @flow: RX flow type (SYNCHRONIZED or PIPELINE)
+ * @arb_mode: Arbitration mode for TX frame (Round robin, priority)
+ */
+struct hsi_config {
+       unsigned int    mode;
+       unsigned int    channels;
+       unsigned int    speed;
+       union {
+               unsigned int    flow;           /* RX only */
+               unsigned int    arb_mode;       /* TX only */
+       };
+};
+
+/**
+ * struct hsi_board_info - HSI client board info
+ * @name: Name for the HSI device
+ * @hsi_id: HSI controller id where the client sits
+ * @port: Port number in the controller where the client sits
+ * @tx_cfg: HSI TX configuration
+ * @rx_cfg: HSI RX configuration
+ * @platform_data: Platform related data
+ * @archdata: Architecture-dependent device data
+ */
+struct hsi_board_info {
+       const char              *name;
+       unsigned int            hsi_id;
+       unsigned int            port;
+       struct hsi_config       tx_cfg;
+       struct hsi_config       rx_cfg;
+       void                    *platform_data;
+       struct dev_archdata     *archdata;
+};
+
+#ifdef CONFIG_HSI_BOARDINFO
+extern int hsi_register_board_info(struct hsi_board_info const *info,
+                                                       unsigned int len);
+#else
+static inline int hsi_register_board_info(struct hsi_board_info const *info,
+                                                       unsigned int len)
+{
+       return 0;
+}
+#endif /* CONFIG_HSI_BOARDINFO */
+
+/**
+ * struct hsi_client - HSI client attached to an HSI port
+ * @device: Driver model representation of the device
+ * @tx_cfg: HSI TX configuration
+ * @rx_cfg: HSI RX configuration
+ * @e_handler: Callback for handling port events (RX Wake High/Low)
+ * @pclaimed: Keeps tracks if the clients claimed its associated HSI port
+ * @nb: Notifier block for port events
+ */
+struct hsi_client {
+       struct device           device;
+       struct hsi_config       tx_cfg;
+       struct hsi_config       rx_cfg;
+       /* private: */
+       void                    (*ehandler)(struct hsi_client *, unsigned long);
+       unsigned int            pclaimed:1;
+       struct notifier_block   nb;
+};
+
+#define to_hsi_client(dev) container_of(dev, struct hsi_client, device)
+
+static inline void hsi_client_set_drvdata(struct hsi_client *cl, void *data)
+{
+       dev_set_drvdata(&cl->device, data);
+}
+
+static inline void *hsi_client_drvdata(struct hsi_client *cl)
+{
+       return dev_get_drvdata(&cl->device);
+}
+
+int hsi_register_port_event(struct hsi_client *cl,
+                       void (*handler)(struct hsi_client *, unsigned long));
+int hsi_unregister_port_event(struct hsi_client *cl);
+
+/**
+ * struct hsi_client_driver - Driver associated to an HSI client
+ * @driver: Driver model representation of the driver
+ */
+struct hsi_client_driver {
+       struct device_driver    driver;
+};
+
+#define to_hsi_client_driver(drv) container_of(drv, struct hsi_client_driver,\
+                                                                       driver)
+
+int hsi_register_client_driver(struct hsi_client_driver *drv);
+
+static inline void hsi_unregister_client_driver(struct hsi_client_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+
+/**
+ * struct hsi_msg - HSI message descriptor
+ * @link: Free to use by the current descriptor owner
+ * @cl: HSI device client that issues the transfer
+ * @sgt: Head of the scatterlist array
+ * @context: Client context data associated to the transfer
+ * @complete: Transfer completion callback
+ * @destructor: Destructor to free resources when flushing
+ * @status: Status of the transfer when completed
+ * @actual_len: Actual length of data transfered on completion
+ * @channel: Channel were to TX/RX the message
+ * @ttype: Transfer type (TX if set, RX otherwise)
+ * @break_frame: if true HSI will send/receive a break frame. Data buffers are
+ *             ignored in the request.
+ */
+struct hsi_msg {
+       struct list_head        link;
+       struct hsi_client       *cl;
+       struct sg_table         sgt;
+       void                    *context;
+
+       void                    (*complete)(struct hsi_msg *msg);
+       void                    (*destructor)(struct hsi_msg *msg);
+
+       int                     status;
+       unsigned int            actual_len;
+       unsigned int            channel;
+       unsigned int            ttype:1;
+       unsigned int            break_frame:1;
+};
+
+struct hsi_msg *hsi_alloc_msg(unsigned int n_frag, gfp_t flags);
+void hsi_free_msg(struct hsi_msg *msg);
+
+/**
+ * struct hsi_port - HSI port device
+ * @device: Driver model representation of the device
+ * @tx_cfg: Current TX path configuration
+ * @rx_cfg: Current RX path configuration
+ * @num: Port number
+ * @shared: Set when port can be shared by different clients
+ * @claimed: Reference count of clients which claimed the port
+ * @lock: Serialize port claim
+ * @async: Asynchronous transfer callback
+ * @setup: Callback to set the HSI client configuration
+ * @flush: Callback to clean the HW state and destroy all pending transfers
+ * @start_tx: Callback to inform that a client wants to TX data
+ * @stop_tx: Callback to inform that a client no longer wishes to TX data
+ * @release: Callback to inform that a client no longer uses the port
+ * @n_head: Notifier chain for signaling port events to the clients.
+ */
+struct hsi_port {
+       struct device                   device;
+       struct hsi_config               tx_cfg;
+       struct hsi_config               rx_cfg;
+       unsigned int                    num;
+       unsigned int                    shared:1;
+       int                             claimed;
+       struct mutex                    lock;
+       int                             (*async)(struct hsi_msg *msg);
+       int                             (*setup)(struct hsi_client *cl);
+       int                             (*flush)(struct hsi_client *cl);
+       int                             (*start_tx)(struct hsi_client *cl);
+       int                             (*stop_tx)(struct hsi_client *cl);
+       int                             (*release)(struct hsi_client *cl);
+       /* private */
+       struct atomic_notifier_head     n_head;
+};
+
+#define to_hsi_port(dev) container_of(dev, struct hsi_port, device)
+#define hsi_get_port(cl) to_hsi_port((cl)->device.parent)
+
+int hsi_event(struct hsi_port *port, unsigned long event);
+int hsi_claim_port(struct hsi_client *cl, unsigned int share);
+void hsi_release_port(struct hsi_client *cl);
+
+static inline int hsi_port_claimed(struct hsi_client *cl)
+{
+       return cl->pclaimed;
+}
+
+static inline void hsi_port_set_drvdata(struct hsi_port *port, void *data)
+{
+       dev_set_drvdata(&port->device, data);
+}
+
+static inline void *hsi_port_drvdata(struct hsi_port *port)
+{
+       return dev_get_drvdata(&port->device);
+}
+
+/**
+ * struct hsi_controller - HSI controller device
+ * @device: Driver model representation of the device
+ * @owner: Pointer to the module owning the controller
+ * @id: HSI controller ID
+ * @num_ports: Number of ports in the HSI controller
+ * @port: Array of HSI ports
+ */
+struct hsi_controller {
+       struct device           device;
+       struct module           *owner;
+       unsigned int            id;
+       unsigned int            num_ports;
+       struct hsi_port         **port;
+};
+
+#define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device)
+
+struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags);
+void hsi_put_controller(struct hsi_controller *hsi);
+int hsi_register_controller(struct hsi_controller *hsi);
+void hsi_unregister_controller(struct hsi_controller *hsi);
+
+static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi,
+                                                               void *data)
+{
+       dev_set_drvdata(&hsi->device, data);
+}
+
+static inline void *hsi_controller_drvdata(struct hsi_controller *hsi)
+{
+       return dev_get_drvdata(&hsi->device);
+}
+
+static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi,
+                                                       unsigned int num)
+{
+       return (num < hsi->num_ports) ? hsi->port[num] : NULL;
+}
+
+/*
+ * API for HSI clients
+ */
+int hsi_async(struct hsi_client *cl, struct hsi_msg *msg);
+
+/**
+ * hsi_id - Get HSI controller ID associated to a client
+ * @cl: Pointer to a HSI client
+ *
+ * Return the controller id where the client is attached to
+ */
+static inline unsigned int hsi_id(struct hsi_client *cl)
+{
+       return  to_hsi_controller(cl->device.parent->parent)->id;
+}
+
+/**
+ * hsi_port_id - Gets the port number a client is attached to
+ * @cl: Pointer to HSI client
+ *
+ * Return the port number associated to the client
+ */
+static inline unsigned int hsi_port_id(struct hsi_client *cl)
+{
+       return  to_hsi_port(cl->device.parent)->num;
+}
+
+/**
+ * hsi_setup - Configure the client's port
+ * @cl: Pointer to the HSI client
+ *
+ * When sharing ports, clients should either relay on a single
+ * client setup or have the same setup for all of them.
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_setup(struct hsi_client *cl)
+{
+       if (!hsi_port_claimed(cl))
+               return -EACCES;
+       return  hsi_get_port(cl)->setup(cl);
+}
+
+/**
+ * hsi_flush - Flush all pending transactions on the client's port
+ * @cl: Pointer to the HSI client
+ *
+ * This function will destroy all pending hsi_msg in the port and reset
+ * the HW port so it is ready to receive and transmit from a clean state.
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_flush(struct hsi_client *cl)
+{
+       if (!hsi_port_claimed(cl))
+               return -EACCES;
+       return hsi_get_port(cl)->flush(cl);
+}
+
+/**
+ * hsi_async_read - Submit a read transfer
+ * @cl: Pointer to the HSI client
+ * @msg: HSI message descriptor of the transfer
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_async_read(struct hsi_client *cl, struct hsi_msg *msg)
+{
+       msg->ttype = HSI_MSG_READ;
+       return hsi_async(cl, msg);
+}
+
+/**
+ * hsi_async_write - Submit a write transfer
+ * @cl: Pointer to the HSI client
+ * @msg: HSI message descriptor of the transfer
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_async_write(struct hsi_client *cl, struct hsi_msg *msg)
+{
+       msg->ttype = HSI_MSG_WRITE;
+       return hsi_async(cl, msg);
+}
+
+/**
+ * hsi_start_tx - Signal the port that the client wants to start a TX
+ * @cl: Pointer to the HSI client
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_start_tx(struct hsi_client *cl)
+{
+       if (!hsi_port_claimed(cl))
+               return -EACCES;
+       return hsi_get_port(cl)->start_tx(cl);
+}
+
+/**
+ * hsi_stop_tx - Signal the port that the client no longer wants to transmit
+ * @cl: Pointer to the HSI client
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_stop_tx(struct hsi_client *cl)
+{
+       if (!hsi_port_claimed(cl))
+               return -EACCES;
+       return hsi_get_port(cl)->stop_tx(cl);
+}
+#endif /* __LINUX_HSI_H__ */
diff --git a/include/linux/hsi/hsi_char.h b/include/linux/hsi/hsi_char.h
new file mode 100644 (file)
index 0000000..76160b4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Part of the HSI character device driver.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Andras Domokos <andras.domokos at nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+#ifndef __HSI_CHAR_H
+#define __HSI_CHAR_H
+
+#define HSI_CHAR_MAGIC         'k'
+#define HSC_IOW(num, dtype)    _IOW(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IOR(num, dtype)    _IOR(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IOWR(num, dtype)   _IOWR(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IO(num)            _IO(HSI_CHAR_MAGIC, num)
+
+#define HSC_RESET              HSC_IO(16)
+#define HSC_SET_PM             HSC_IO(17)
+#define HSC_SEND_BREAK         HSC_IO(18)
+#define HSC_SET_RX             HSC_IOW(19, struct hsc_rx_config)
+#define HSC_GET_RX             HSC_IOW(20, struct hsc_rx_config)
+#define HSC_SET_TX             HSC_IOW(21, struct hsc_tx_config)
+#define HSC_GET_TX             HSC_IOW(22, struct hsc_tx_config)
+
+#define HSC_PM_DISABLE         0
+#define HSC_PM_ENABLE          1
+
+#define HSC_MODE_STREAM                1
+#define HSC_MODE_FRAME         2
+#define HSC_FLOW_SYNC          0
+#define HSC_ARB_RR             0
+#define HSC_ARB_PRIO           1
+
+struct hsc_rx_config {
+       uint32_t mode;
+       uint32_t flow;
+       uint32_t channels;
+};
+
+struct hsc_tx_config {
+       uint32_t mode;
+       uint32_t channels;
+       uint32_t speed;
+       uint32_t arb_mode;
+};
+
+#endif /* __HSI_CHAR_H */
index 2463b61003336b0f176b5ed851aa8776a5202697..1f90de0cfdbe7ed344fccdf9eb04e774c5493adc 100644 (file)
@@ -666,23 +666,11 @@ struct twl4030_codec_data {
        unsigned int check_defaults:1;
        unsigned int reset_registers:1;
        unsigned int hs_extmute:1;
-       u16 hs_left_step;
-       u16 hs_right_step;
-       u16 hf_left_step;
-       u16 hf_right_step;
        void (*set_hs_extmute)(int mute);
 };
 
 struct twl4030_vibra_data {
        unsigned int    coexist;
-
-       /* twl6040 */
-       unsigned int vibldrv_res;       /* left driver resistance */
-       unsigned int vibrdrv_res;       /* right driver resistance */
-       unsigned int viblmotor_res;     /* left motor resistance */
-       unsigned int vibrmotor_res;     /* right motor resistance */
-       int vddvibl_uV;                 /* VDDVIBL volt, set 0 for fixed reg */
-       int vddvibr_uV;                 /* VDDVIBR volt, set 0 for fixed reg */
 };
 
 struct twl4030_audio_data {
index 79c4f268410d2223ee31986cfae0dda8c0442fb4..18a5d02a864410df6b6eba5f8f6a67650150cacc 100644 (file)
@@ -22,7 +22,7 @@
 #define EQL_DEFAULT_SLAVE_PRIORITY 28800
 #define EQL_DEFAULT_MAX_SLAVES     4
 #define EQL_DEFAULT_MTU            576
-#define EQL_DEFAULT_RESCHED_IVAL   100
+#define EQL_DEFAULT_RESCHED_IVAL   HZ
 
 #define EQL_ENSLAVE     (SIOCDEVPRIVATE)
 #define EQL_EMANCIPATE  (SIOCDEVPRIVATE + 1)
index bff29c58da23013e5e1e19f0cdeaf2ad45d602fc..b27cfcfd3a59c15319488580a14de42c18174744 100644 (file)
@@ -49,6 +49,12 @@ typedef      void (*irq_preflow_handler_t)(struct irq_data *data);
  * IRQ_TYPE_LEVEL_LOW          - low level triggered
  * IRQ_TYPE_LEVEL_MASK         - Mask to filter out the level bits
  * IRQ_TYPE_SENSE_MASK         - Mask for all the above bits
+ * IRQ_TYPE_DEFAULT            - For use by some PICs to ask irq_set_type
+ *                               to setup the HW to a sane default (used
+ *                                by irqdomain map() callbacks to synchronize
+ *                                the HW state and SW flags for a newly
+ *                                allocated descriptor).
+ *
  * IRQ_TYPE_PROBE              - Special flag for probing in progress
  *
  * Bits which can be modified via irq_set/clear/modify_status_flags()
@@ -77,6 +83,7 @@ enum {
        IRQ_TYPE_LEVEL_LOW      = 0x00000008,
        IRQ_TYPE_LEVEL_MASK     = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
        IRQ_TYPE_SENSE_MASK     = 0x0000000f,
+       IRQ_TYPE_DEFAULT        = IRQ_TYPE_SENSE_MASK,
 
        IRQ_TYPE_PROBE          = 0x00000010,
 
@@ -263,6 +270,11 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
        d->state_use_accessors &= ~IRQD_IRQ_INPROGRESS;
 }
 
+static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
+{
+       return d->hwirq;
+}
+
 /**
  * struct irq_chip - hardware interrupt chip descriptor
  *
index ead4a4215797b81c7a35baed6b428026d2039e00..c65740d76e663a35da56f3e680835d8349e8f9dd 100644 (file)
@@ -42,12 +42,6 @@ struct of_device_id;
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS     16
 
-/* This type is the placeholder for a hardware interrupt number. It has to
- * be big enough to enclose whatever representation is used by a given
- * platform.
- */
-typedef unsigned long irq_hw_number_t;
-
 /**
  * struct irq_domain_ops - Methods for irq_domain objects
  * @match: Match an interrupt controller device node to a host, returns
@@ -104,6 +98,9 @@ struct irq_domain {
                        unsigned int size;
                        unsigned int *revmap;
                } linear;
+               struct {
+                       unsigned int max_irq;
+               } nomap;
                struct radix_tree_root tree;
        } revmap_data;
        const struct irq_domain_ops *ops;
@@ -126,6 +123,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
                                         const struct irq_domain_ops *ops,
                                         void *host_data);
 struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
+                                        unsigned int max_irq,
                                         const struct irq_domain_ops *ops,
                                         void *host_data);
 struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
@@ -134,7 +132,6 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
 
 extern struct irq_domain *irq_find_host(struct device_node *node);
 extern void irq_set_default_host(struct irq_domain *host);
-extern void irq_set_virq_count(unsigned int count);
 
 static inline struct irq_domain *irq_domain_add_legacy_isa(
                                struct device_node *of_node,
@@ -146,7 +143,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
 }
 extern struct irq_domain *irq_find_host(struct device_node *node);
 extern void irq_set_default_host(struct irq_domain *host);
-extern void irq_set_virq_count(unsigned int count);
 
 
 extern unsigned int irq_create_mapping(struct irq_domain *host,
index 067eda0e4b329cfbfbfcd0e1bb2e88a550c242d8..be342b94c640849f18e669b73f6f418092dc860f 100644 (file)
@@ -4,29 +4,43 @@
 #include <generated/autoconf.h>
 
 /*
- * Helper macros to use CONFIG_ options in C expressions. Note that
+ * Helper macros to use CONFIG_ options in C/CPP expressions. Note that
  * these only work with boolean and tristate options.
  */
 
+/*
+ * Getting something that works in C and CPP for an arg that may or may
+ * not be defined is tricky.  Here, if we have "#define CONFIG_BOOGER 1"
+ * we match on the placeholder define, insert the "0," for arg1 and generate
+ * the triplet (0, 1, 0).  Then the last step cherry picks the 2nd arg (a one).
+ * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
+ * the last step cherry picks the 2nd arg, we get a zero.
+ */
+#define __ARG_PLACEHOLDER_1 0,
+#define config_enabled(cfg) _config_enabled(cfg)
+#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
+#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
+#define ___config_enabled(__ignored, val, ...) val
+
 /*
  * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
  * 0 otherwise.
  *
  */
 #define IS_ENABLED(option) \
-       (__enabled_ ## option || __enabled_ ## option ## _MODULE)
+       (config_enabled(option) || config_enabled(option##_MODULE))
 
 /*
  * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
  * otherwise. For boolean options, this is equivalent to
  * IS_ENABLED(CONFIG_FOO).
  */
-#define IS_BUILTIN(option) __enabled_ ## option
+#define IS_BUILTIN(option) config_enabled(option)
 
 /*
  * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
  * otherwise.
  */
-#define IS_MODULE(option) __enabled_ ## option ## _MODULE
+#define IS_MODULE(option) config_enabled(option##_MODULE)
 
 #endif /* __LINUX_KCONFIG_H */
index fa391835508d9acef3a20cf2d76468a679e35cba..c4d2fc194edec1c07cc5cb3d8fd2fd8059a9cefb 100644 (file)
@@ -63,7 +63,8 @@ enum kgdb_bptype {
        BP_HARDWARE_BREAKPOINT,
        BP_WRITE_WATCHPOINT,
        BP_READ_WATCHPOINT,
-       BP_ACCESS_WATCHPOINT
+       BP_ACCESS_WATCHPOINT,
+       BP_POKE_BREAKPOINT,
 };
 
 enum kgdb_bpstate {
@@ -207,8 +208,8 @@ extern void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc);
 
 /* Optional functions. */
 extern int kgdb_validate_break_address(unsigned long addr);
-extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
-extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
+extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt);
+extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt);
 
 /**
  *     kgdb_arch_late - Perform any architecture specific initalization.
index 9efeae679106ea85a3ff51790e79b86bf501b714..dd99c329e1616ec76af1c9e8b2d11cee08434aea 100644 (file)
@@ -110,12 +110,29 @@ call_usermodehelper(char *path, char **argv, char **envp, int wait)
 
 extern struct ctl_table usermodehelper_table[];
 
+enum umh_disable_depth {
+       UMH_ENABLED = 0,
+       UMH_FREEZING,
+       UMH_DISABLED,
+};
+
 extern void usermodehelper_init(void);
 
-extern int usermodehelper_disable(void);
-extern void usermodehelper_enable(void);
-extern bool usermodehelper_is_disabled(void);
-extern void read_lock_usermodehelper(void);
-extern void read_unlock_usermodehelper(void);
+extern int __usermodehelper_disable(enum umh_disable_depth depth);
+extern void __usermodehelper_set_disable_depth(enum umh_disable_depth depth);
+
+static inline int usermodehelper_disable(void)
+{
+       return __usermodehelper_disable(UMH_DISABLED);
+}
+
+static inline void usermodehelper_enable(void)
+{
+       __usermodehelper_set_disable_depth(UMH_ENABLED);
+}
+
+extern int usermodehelper_read_trylock(void);
+extern long usermodehelper_read_lock_wait(long timeout);
+extern void usermodehelper_read_unlock(void);
 
 #endif /* __LINUX_KMOD_H__ */
index 665a260c7e09948fa3b5e3516efca2890edef840..72cbf08d45fbc878d5198eda807b12dbdffa6268 100644 (file)
@@ -596,6 +596,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
 
 #ifdef CONFIG_IOMMU_API
 int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
 int kvm_iommu_map_guest(struct kvm *kvm);
 int kvm_iommu_unmap_guest(struct kvm *kvm);
 int kvm_assign_device(struct kvm *kvm,
@@ -609,6 +610,11 @@ static inline int kvm_iommu_map_pages(struct kvm *kvm,
        return 0;
 }
 
+static inline void kvm_iommu_unmap_pages(struct kvm *kvm,
+                                        struct kvm_memory_slot *slot)
+{
+}
+
 static inline int kvm_iommu_map_guest(struct kvm *kvm)
 {
        return -ENODEV;
index 42378d637ffbe489c65c0220b8a3a8dc2955f6c9..e926df7b54c963745d043e1041d8876a5a7c65e6 100644 (file)
@@ -996,7 +996,8 @@ extern int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *dev,
 extern void ata_sas_port_destroy(struct ata_port *);
 extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
                                           struct ata_port_info *, struct Scsi_Host *);
-extern int ata_sas_async_port_init(struct ata_port *);
+extern void ata_sas_async_probe(struct ata_port *ap);
+extern int ata_sas_sync_probe(struct ata_port *ap);
 extern int ata_sas_port_init(struct ata_port *);
 extern int ata_sas_port_start(struct ata_port *ap);
 extern void ata_sas_port_stop(struct ata_port *ap);
index eab507f2b1cb649484f9e96028b51c7cce737e12..fad48aab893b846c293046dfdc3991a5e2e26d10 100644 (file)
 #include <linux/key.h>
 #include <linux/skbuff.h>
 
+struct lsm_network_audit {
+       int netif;
+       struct sock *sk;
+       u16 family;
+       __be16 dport;
+       __be16 sport;
+       union {
+               struct {
+                       __be32 daddr;
+                       __be32 saddr;
+               } v4;
+               struct {
+                       struct in6_addr daddr;
+                       struct in6_addr saddr;
+               } v6;
+       } fam;
+};
 
 /* Auxiliary data to use in generating the audit record. */
 struct common_audit_data {
@@ -41,23 +58,7 @@ struct common_audit_data {
                struct path path;
                struct dentry *dentry;
                struct inode *inode;
-               struct {
-                       int netif;
-                       struct sock *sk;
-                       u16 family;
-                       __be16 dport;
-                       __be16 sport;
-                       union {
-                               struct {
-                                       __be32 daddr;
-                                       __be32 saddr;
-                               } v4;
-                               struct {
-                                       struct in6_addr daddr;
-                                       struct in6_addr saddr;
-                               } v6;
-                       } fam;
-               } net;
+               struct lsm_network_audit *net;
                int cap;
                int ipc_id;
                struct task_struct *tsk;
@@ -72,64 +73,15 @@ struct common_audit_data {
        /* this union contains LSM specific data */
        union {
 #ifdef CONFIG_SECURITY_SMACK
-               /* SMACK data */
-               struct smack_audit_data {
-                       const char *function;
-                       char *subject;
-                       char *object;
-                       char *request;
-                       int result;
-               } smack_audit_data;
+               struct smack_audit_data *smack_audit_data;
 #endif
 #ifdef CONFIG_SECURITY_SELINUX
-               /* SELinux data */
-               struct {
-                       u32 ssid;
-                       u32 tsid;
-                       u16 tclass;
-                       u32 requested;
-                       u32 audited;
-                       u32 denied;
-                       /*
-                        * auditdeny is a bit tricky and unintuitive.  See the
-                        * comments in avc.c for it's meaning and usage.
-                        */
-                       u32 auditdeny;
-                       struct av_decision *avd;
-                       int result;
-               } selinux_audit_data;
+               struct selinux_audit_data *selinux_audit_data;
 #endif
 #ifdef CONFIG_SECURITY_APPARMOR
-               struct {
-                       int error;
-                       int op;
-                       int type;
-                       void *profile;
-                       const char *name;
-                       const char *info;
-                       union {
-                               void *target;
-                               struct {
-                                       long pos;
-                                       void *target;
-                               } iface;
-                               struct {
-                                       int rlim;
-                                       unsigned long max;
-                               } rlim;
-                               struct {
-                                       const char *target;
-                                       u32 request;
-                                       u32 denied;
-                                       uid_t ouid;
-                               } fs;
-                       };
-               } apparmor_audit_data;
+               struct apparmor_audit_data *apparmor_audit_data;
 #endif
-       };
-       /* these callback will be implemented by a specific LSM */
-       void (*lsm_pre_audit)(struct audit_buffer *, void *);
-       void (*lsm_post_audit)(struct audit_buffer *, void *);
+       }; /* per LSM data pointer union */
 };
 
 #define v4info fam.v4
@@ -146,6 +98,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
        { memset((_d), 0, sizeof(struct common_audit_data)); \
         (_d)->type = LSM_AUDIT_DATA_##_t; }
 
-void common_lsm_audit(struct common_audit_data *a);
+void common_lsm_audit(struct common_audit_data *a,
+       void (*pre_audit)(struct audit_buffer *, void *),
+       void (*post_audit)(struct audit_buffer *, void *));
 
 #endif
index 9890687f582de0c36cdbcc56cf252a381e82e8ee..5a049dfaf1533174d7293810b132128c5e3f2121 100644 (file)
@@ -8,41 +8,14 @@
 #ifndef __MFD_DB5500_PRCMU_H
 #define __MFD_DB5500_PRCMU_H
 
-#ifdef CONFIG_MFD_DB5500_PRCMU
-
-void db5500_prcmu_early_init(void);
-int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state);
-int db5500_prcmu_set_display_clocks(void);
-int db5500_prcmu_disable_dsipll(void);
-int db5500_prcmu_enable_dsipll(void);
-int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
-void db5500_prcmu_enable_wakeups(u32 wakeups);
-int db5500_prcmu_request_clock(u8 clock, bool enable);
-void db5500_prcmu_config_abb_event_readout(u32 abb_events);
-void db5500_prcmu_get_abb_event_buffer(void __iomem **buf);
-int prcmu_resetout(u8 resoutn, u8 state);
-int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-       bool keep_ap_pll);
-int db5500_prcmu_config_esram0_deep_sleep(u8 state);
-void db5500_prcmu_system_reset(u16 reset_code);
-u16 db5500_prcmu_get_reset_code(void);
-bool db5500_prcmu_is_ac_wake_requested(void);
-int db5500_prcmu_set_arm_opp(u8 opp);
-int db5500_prcmu_get_arm_opp(void);
-
-#else /* !CONFIG_UX500_SOC_DB5500 */
-
-static inline void db5500_prcmu_early_init(void) {}
-
-static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+static inline int prcmu_resetout(u8 resoutn, u8 state)
 {
-       return -ENOSYS;
+       return 0;
 }
 
-static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+static inline int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 {
-       return -ENOSYS;
+       return 0;
 }
 
 static inline int db5500_prcmu_request_clock(u8 clock, bool enable)
@@ -50,69 +23,82 @@ static inline int db5500_prcmu_request_clock(u8 clock, bool enable)
        return 0;
 }
 
-static inline int db5500_prcmu_set_display_clocks(void)
+static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+       bool keep_ap_pll)
 {
        return 0;
 }
 
-static inline int db5500_prcmu_disable_dsipll(void)
+static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state)
 {
        return 0;
 }
 
-static inline int db5500_prcmu_enable_dsipll(void)
+static inline u16 db5500_prcmu_get_reset_code(void)
 {
        return 0;
 }
 
-static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state)
+static inline bool db5500_prcmu_is_ac_wake_requested(void)
 {
        return 0;
 }
 
-static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {}
-
-static inline int prcmu_resetout(u8 resoutn, u8 state)
+static inline int db5500_prcmu_set_arm_opp(u8 opp)
 {
        return 0;
 }
 
-static inline int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state)
+static inline int db5500_prcmu_get_arm_opp(void)
 {
        return 0;
 }
 
-static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
 static inline void db5500_prcmu_config_abb_event_readout(u32 abb_events) {}
 
-static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-       bool keep_ap_pll)
-{
-       return 0;
-}
+static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
 
 static inline void db5500_prcmu_system_reset(u16 reset_code) {}
 
-static inline u16 db5500_prcmu_get_reset_code(void)
+static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {}
+
+#ifdef CONFIG_MFD_DB5500_PRCMU
+
+void db5500_prcmu_early_init(void);
+int db5500_prcmu_set_display_clocks(void);
+int db5500_prcmu_disable_dsipll(void);
+int db5500_prcmu_enable_dsipll(void);
+int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
+#else /* !CONFIG_UX500_SOC_DB5500 */
+
+static inline void db5500_prcmu_early_init(void) {}
+
+static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 {
-       return 0;
+       return -ENOSYS;
 }
 
-static inline bool db5500_prcmu_is_ac_wake_requested(void)
+static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
 {
-       return 0;
+       return -ENOSYS;
 }
 
-static inline int db5500_prcmu_set_arm_opp(u8 opp)
+static inline int db5500_prcmu_set_display_clocks(void)
 {
        return 0;
 }
 
-static inline int db5500_prcmu_get_arm_opp(void)
+static inline int db5500_prcmu_disable_dsipll(void)
 {
        return 0;
 }
 
+static inline int db5500_prcmu_enable_dsipll(void)
+{
+       return 0;
+}
 
 #endif /* CONFIG_MFD_DB5500_PRCMU */
 
index a2c61609d21dbf6ab5ffe386e2721e58ac388ffe..0b64b19d81abf9e89e3d609f020e10e2ac9952b6 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/mutex.h>
 #include <linux/types.h>
+#include <linux/regmap.h>
 
 #define RC5T583_MAX_REGS               0xF8
 
@@ -279,14 +280,44 @@ struct rc5t583_platform_data {
        bool            enable_shutdown;
 };
 
-int rc5t583_write(struct device *dev, u8 reg, uint8_t val);
-int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val);
-int rc5t583_set_bits(struct device *dev, unsigned int reg,
-               unsigned int bit_mask);
-int rc5t583_clear_bits(struct device *dev, unsigned int reg,
-               unsigned int bit_mask);
-int rc5t583_update(struct device *dev, unsigned int reg,
-               unsigned int val, unsigned int mask);
+static inline int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_write(rc5t583->regmap, reg, val);
+}
+
+static inline int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       unsigned int ival;
+       int ret;
+       ret = regmap_read(rc5t583->regmap, reg, &ival);
+       if (!ret)
+               *val = (uint8_t)ival;
+       return ret;
+}
+
+static inline int rc5t583_set_bits(struct device *dev, unsigned int reg,
+                       unsigned int bit_mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
+}
+
+static inline int rc5t583_clear_bits(struct device *dev, unsigned int reg,
+                       unsigned int bit_mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
+}
+
+static inline int rc5t583_update(struct device *dev, unsigned int reg,
+               unsigned int val, unsigned int mask)
+{
+       struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+       return regmap_update_bits(rc5t583->regmap, reg, mask, val);
+}
+
 int rc5t583_ext_power_req_config(struct device *dev, int deepsleep_id,
        int ext_pwr_req, int deepsleep_slot_nr);
 int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base);
index 9bc9ac651dad9bf2be544961c18e06fd1bfbd119..b15b5f03f5c44c74473f30e46411876000bf5863 100644 (file)
 #define TWL6040_SYSCLK_SEL_LPPLL       0
 #define TWL6040_SYSCLK_SEL_HPPLL       1
 
+struct twl6040_codec_data {
+       u16 hs_left_step;
+       u16 hs_right_step;
+       u16 hf_left_step;
+       u16 hf_right_step;
+};
+
+struct twl6040_vibra_data {
+       unsigned int vibldrv_res;       /* left driver resistance */
+       unsigned int vibrdrv_res;       /* right driver resistance */
+       unsigned int viblmotor_res;     /* left motor resistance */
+       unsigned int vibrmotor_res;     /* right motor resistance */
+       int vddvibl_uV;                 /* VDDVIBL volt, set 0 for fixed reg */
+       int vddvibr_uV;                 /* VDDVIBR volt, set 0 for fixed reg */
+};
+
+struct twl6040_platform_data {
+       int audpwron_gpio;      /* audio power-on gpio */
+       unsigned int irq_base;
+
+       struct twl6040_codec_data *codec;
+       struct twl6040_vibra_data *vibra;
+};
+
+struct regmap;
+
 struct twl6040 {
        struct device *dev;
+       struct regmap *regmap;
        struct mutex mutex;
        struct mutex io_mutex;
        struct mutex irq_mutex;
index d8738a464b94a71822f191bdd45bcac29b01814c..74aa71bea1e4ff6bf0bd7a43dfdff37c870438ee 100644 (file)
@@ -1393,29 +1393,20 @@ extern int install_special_mapping(struct mm_struct *mm,
 
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
-extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
-       unsigned long len, unsigned long prot,
-       unsigned long flag, unsigned long pgoff);
 extern unsigned long mmap_region(struct file *file, unsigned long addr,
        unsigned long len, unsigned long flags,
        vm_flags_t vm_flags, unsigned long pgoff);
-
-static inline unsigned long do_mmap(struct file *file, unsigned long addr,
-       unsigned long len, unsigned long prot,
-       unsigned long flag, unsigned long offset)
-{
-       unsigned long ret = -EINVAL;
-       if ((offset + PAGE_ALIGN(len)) < offset)
-               goto out;
-       if (!(offset & ~PAGE_MASK))
-               ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
-out:
-       return ret;
-}
-
+extern unsigned long do_mmap(struct file *, unsigned long,
+        unsigned long, unsigned long,
+        unsigned long, unsigned long);
 extern int do_munmap(struct mm_struct *, unsigned long, size_t);
 
-extern unsigned long do_brk(unsigned long, unsigned long);
+/* These take the mm semaphore themselves */
+extern unsigned long vm_brk(unsigned long, unsigned long);
+extern int vm_munmap(unsigned long, size_t);
+extern unsigned long vm_mmap(struct file *, unsigned long,
+        unsigned long, unsigned long,
+        unsigned long, unsigned long);
 
 /* truncate.c */
 extern void truncate_inode_pages(struct address_space *, loff_t);
index 01beae78f07935e45d1a04ac544e8826ad90618a..629b823f88362b44001cf09dc1559d1e86780dad 100644 (file)
@@ -481,7 +481,7 @@ struct mmc_driver {
        struct device_driver drv;
        int (*probe)(struct mmc_card *);
        void (*remove)(struct mmc_card *);
-       int (*suspend)(struct mmc_card *, pm_message_t);
+       int (*suspend)(struct mmc_card *);
        int (*resume)(struct mmc_card *);
 };
 
index 1f77540bdc95495ab1bc13edf9f6ac0332a649ae..5cbaa20f16596858f08916103f99377a658b3d3d 100644 (file)
@@ -2604,8 +2604,6 @@ extern void               net_disable_timestamp(void);
 extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);
 extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
 extern void dev_seq_stop(struct seq_file *seq, void *v);
-extern int dev_seq_open_ops(struct inode *inode, struct file *file,
-                           const struct seq_operations *ops);
 #endif
 
 extern int netdev_class_create_file(struct class_attribute *class_attr);
index c0405ac928701a7d234986576baa69624ec1b71c..e3a9978f259f55425202664754e13c5504ed579e 100644 (file)
@@ -58,8 +58,8 @@ struct xt_set_info_target_v1 {
 struct xt_set_info_target_v2 {
        struct xt_set_info add_set;
        struct xt_set_info del_set;
-       u32 flags;
-       u32 timeout;
+       __u32 flags;
+       __u32 timeout;
 };
 
 #endif /*_XT_SET_H*/
index 0ddd161f3b060c2e2ec0d665c1ddc719213443f7..31d2844e6572be34ed104e1a92fafd48abc0bf76 100644 (file)
@@ -104,9 +104,18 @@ struct bridge_skb_cb {
        } daddr;
 };
 
+static inline void br_drop_fake_rtable(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb_dst(skb);
+
+       if (dst && (dst->flags & DST_FAKE_RTABLE))
+               skb_dst_drop(skb);
+}
+
 #else
 #define nf_bridge_maybe_copy_header(skb)       (0)
 #define nf_bridge_pad(skb)                     (0)
+#define br_drop_fake_rtable(skb)               do { } while (0)
 #endif /* CONFIG_BRIDGE_NETFILTER */
 
 #endif /* __KERNEL__ */
index f549adccc94c569801f4181bacd84e87f0743725..1bc898b14a8070ba0c8aab847157fbe90e8ca619 100644 (file)
@@ -287,7 +287,17 @@ extern unsigned int ip6t_do_table(struct sk_buff *skb,
                                  struct xt_table *table);
 
 /* Check for an extension */
-extern int ip6t_ext_hdr(u8 nexthdr);
+static inline int
+ip6t_ext_hdr(u8 nexthdr)
+{      return (nexthdr == IPPROTO_HOPOPTS) ||
+              (nexthdr == IPPROTO_ROUTING) ||
+              (nexthdr == IPPROTO_FRAGMENT) ||
+              (nexthdr == IPPROTO_ESP) ||
+              (nexthdr == IPPROTO_AH) ||
+              (nexthdr == IPPROTO_NONE) ||
+              (nexthdr == IPPROTO_DSTOPTS);
+}
+
 /* find specified header and get offset to it */
 extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                         int target, unsigned short *fragoff);
index bfd0d1bf67072e9a5a6f6c143e80f56fcc6238aa..7ba3551a0414a867cffe38e52cc720004e32592e 100644 (file)
@@ -312,6 +312,11 @@ struct nfs4_layoutreturn {
        int rpc_status;
 };
 
+struct stateowner_id {
+       __u64   create_time;
+       __u32   uniquifier;
+};
+
 /*
  * Arguments to the open call.
  */
@@ -321,7 +326,7 @@ struct nfs_openargs {
        int                     open_flags;
        fmode_t                 fmode;
        __u64                   clientid;
-       __u64                   id;
+       struct stateowner_id    id;
        union {
                struct {
                        struct iattr *  attrs;    /* UNCHECKED, GUARDED */
index b8d4001212b30bbd94f7a8d47a3afe32e5dd229e..5b7d84ac954a2c7a5e0b7f19f3529bb01e1a981f 100644 (file)
@@ -1,3 +1,4 @@
+header-y += cld.h
 header-y += debug.h
 header-y += export.h
 header-y += nfsfh.h
index cfaaa6949b8b03687b4be0074fc35b1165b245ed..efa26b4da8d2b9d2479284bc9cbaeff61913d634 100644 (file)
@@ -426,7 +426,7 @@ static inline int fault_in_pages_writeable(char __user *uaddr, int size)
                 */
                if (((unsigned long)uaddr & PAGE_MASK) !=
                                ((unsigned long)end & PAGE_MASK))
-                       ret = __put_user(0, end);
+                       ret = __put_user(0, end);
        }
        return ret;
 }
@@ -445,13 +445,73 @@ static inline int fault_in_pages_readable(const char __user *uaddr, int size)
 
                if (((unsigned long)uaddr & PAGE_MASK) !=
                                ((unsigned long)end & PAGE_MASK)) {
-                       ret = __get_user(c, end);
+                       ret = __get_user(c, end);
                        (void)c;
                }
        }
        return ret;
 }
 
+/*
+ * Multipage variants of the above prefault helpers, useful if more than
+ * PAGE_SIZE of data needs to be prefaulted. These are separate from the above
+ * functions (which only handle up to PAGE_SIZE) to avoid clobbering the
+ * filemap.c hotpaths.
+ */
+static inline int fault_in_multipages_writeable(char __user *uaddr, int size)
+{
+       int ret;
+       char __user *end = uaddr + size - 1;
+
+       if (unlikely(size == 0))
+               return 0;
+
+       /*
+        * Writing zeroes into userspace here is OK, because we know that if
+        * the zero gets there, we'll be overwriting it.
+        */
+       while (uaddr <= end) {
+               ret = __put_user(0, uaddr);
+               if (ret != 0)
+                       return ret;
+               uaddr += PAGE_SIZE;
+       }
+
+       /* Check whether the range spilled into the next page. */
+       if (((unsigned long)uaddr & PAGE_MASK) ==
+                       ((unsigned long)end & PAGE_MASK))
+               ret = __put_user(0, end);
+
+       return ret;
+}
+
+static inline int fault_in_multipages_readable(const char __user *uaddr,
+                                              int size)
+{
+       volatile char c;
+       int ret;
+       const char __user *end = uaddr + size - 1;
+
+       if (unlikely(size == 0))
+               return 0;
+
+       while (uaddr <= end) {
+               ret = __get_user(c, uaddr);
+               if (ret != 0)
+                       return ret;
+               uaddr += PAGE_SIZE;
+       }
+
+       /* Check whether the range spilled into the next page. */
+       if (((unsigned long)uaddr & PAGE_MASK) ==
+                       ((unsigned long)end & PAGE_MASK)) {
+               ret = __get_user(c, end);
+               (void)c;
+       }
+
+       return ret;
+}
+
 int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
                                pgoff_t index, gfp_t gfp_mask);
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
index fee4349364f77ed971fac838bf95391e0097f585..e4d1de742502f6230fc9d9dd94c707949409cf45 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef __LINUX_PINCTRL_MACHINE_H
 #define __LINUX_PINCTRL_MACHINE_H
 
+#include <linux/bug.h>
+
 #include "pinctrl-state.h"
 
 enum pinctrl_map_type {
@@ -148,7 +150,7 @@ struct pinctrl_map {
 #define PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(dev, grp, cfgs)              \
        PIN_MAP_CONFIGS_GROUP(dev, PINCTRL_STATE_DEFAULT, dev, grp, cfgs)
 
-#ifdef CONFIG_PINMUX
+#ifdef CONFIG_PINCTRL
 
 extern int pinctrl_register_mappings(struct pinctrl_map const *map,
                                unsigned num_maps);
index 6d626ff0cfd065f8446370902240a865a312ee00..e1ac1ce16fb0b60f07ec961b3ec8f1b7fb0763d0 100644 (file)
@@ -6,6 +6,7 @@
 #define PIPE_BUF_FLAG_LRU      0x01    /* page is on the LRU */
 #define PIPE_BUF_FLAG_ATOMIC   0x02    /* was atomically mapped */
 #define PIPE_BUF_FLAG_GIFT     0x04    /* page is a gift */
+#define PIPE_BUF_FLAG_PACKET   0x08    /* read() as a packet */
 
 /**
  *     struct pipe_buffer - a linux kernel pipe buffer
index d056263545b118b09854cc9e5702a682ebc23886..b0f2c56a8ea26c454f3d8cc71661821ec87f38de 100644 (file)
@@ -4,8 +4,8 @@
  * GPL v2 Only
  */
 
-#ifndef __ATMEL_NAND_H__
-#define __ATMEL_NAND_H__
+#ifndef __ATMEL_H__
+#define __ATMEL_H__
 
 #include <linux/mtd/nand.h>
 
@@ -24,4 +24,4 @@ struct atmel_nand_data {
        unsigned int    num_parts;
 };
 
-#endif /* __ATMEL_NAND_H__ */
+#endif /* __ATMEL_H__ */
index 2e9191a712f301574a6109541358b3a2d3ae9e52..233149cb19f4ae8af9ad35b7f6d2d5ab5929e288 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/notifier.h>
 #include <linux/miscdevice.h>
 #include <linux/device.h>
+#include <linux/workqueue.h>
 
 enum {
        PM_QOS_RESERVED = 0,
@@ -29,6 +30,7 @@ enum {
 struct pm_qos_request {
        struct plist_node node;
        int pm_qos_class;
+       struct delayed_work work; /* for pm_qos_update_request_timeout */
 };
 
 struct dev_pm_qos_request {
@@ -73,6 +75,8 @@ void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class,
                        s32 value);
 void pm_qos_update_request(struct pm_qos_request *req,
                           s32 new_value);
+void pm_qos_update_request_timeout(struct pm_qos_request *req,
+                                  s32 new_value, unsigned long timeout_us);
 void pm_qos_remove_request(struct pm_qos_request *req);
 
 int pm_qos_request(int pm_qos_class);
index 7abb160933122bfc1ff334b5503398a5fe757ac4..b02108446be756cc1c216271e21ac3cbf7a132d8 100644 (file)
@@ -71,7 +71,7 @@ struct regulator_state {
  * @uV_offset: Offset applied to voltages from consumer to compensate for
  *             voltage drops.
  *
- * @min_uA: Smallest consumers consumers may set.
+ * @min_uA: Smallest current consumers may set.
  * @max_uA: Largest current consumers may set.
  *
  * @valid_modes_mask: Mask of modes which may be configured by consumers.
@@ -134,10 +134,8 @@ struct regulation_constraints {
 /**
  * struct regulator_consumer_supply - supply -> device mapping
  *
- * This maps a supply name to a device.  Only one of dev or dev_name
- * can be specified.  Use of dev_name allows support for buses which
- * make struct device available late such as I2C and is the preferred
- * form.
+ * This maps a supply name to a device. Use of dev_name allows support for
+ * buses which make struct device available late such as I2C.
  *
  * @dev_name: Result of dev_name() for the consumer.
  * @supply: Name for the supply.
index c6db9fb33c448f28197ffb6d135689daf58625b6..600060e25ec6cb644fd4141f48e2493490305c8a 100644 (file)
@@ -141,7 +141,7 @@ static inline unsigned __read_seqcount_begin(const seqcount_t *s)
        unsigned ret;
 
 repeat:
-       ret = s->sequence;
+       ret = ACCESS_ONCE(s->sequence);
        if (unlikely(ret & 1)) {
                cpu_relax();
                goto repeat;
@@ -165,6 +165,27 @@ static inline unsigned read_seqcount_begin(const seqcount_t *s)
        return ret;
 }
 
+/**
+ * raw_seqcount_begin - begin a seq-read critical section
+ * @s: pointer to seqcount_t
+ * Returns: count to be passed to read_seqcount_retry
+ *
+ * raw_seqcount_begin opens a read critical section of the given seqcount.
+ * Validity of the critical section is tested by checking read_seqcount_retry
+ * function.
+ *
+ * Unlike read_seqcount_begin(), this function will not wait for the count
+ * to stabilize. If a writer is active when we begin, we will fail the
+ * read_seqcount_retry() instead of stabilizing at the beginning of the
+ * critical section.
+ */
+static inline unsigned raw_seqcount_begin(const seqcount_t *s)
+{
+       unsigned ret = ACCESS_ONCE(s->sequence);
+       smp_rmb();
+       return ret & ~1;
+}
+
 /**
  * __read_seqcount_retry - end a seq-read critical section (without barrier)
  * @s: pointer to seqcount_t
index f51bf2e70c69605d8e298929a251490dbcf23bd2..2db407a400513efcc39ced42b6e94859fb7f417f 100644 (file)
@@ -357,7 +357,7 @@ struct uart_port {
 #define UPF_CONS_FLOW          ((__force upf_t) (1 << 23))
 #define UPF_SHARE_IRQ          ((__force upf_t) (1 << 24))
 #define UPF_EXAR_EFR           ((__force upf_t) (1 << 25))
-#define UPF_IIR_ONCE           ((__force upf_t) (1 << 26))
+#define UPF_BUG_THRE           ((__force upf_t) (1 << 26))
 /* The exact UART type is known and should not be probed.  */
 #define UPF_FIXED_TYPE         ((__force upf_t) (1 << 27))
 #define UPF_BOOT_AUTOCONF      ((__force upf_t) (1 << 28))
index 33370271b8b2c43ac65925619d15305d27a7018c..111f26b6e28b992bbebbe645819712bf8c07ab63 100644 (file)
@@ -238,11 +238,12 @@ enum {
 /*
  * The callback notifies userspace to release buffers when skb DMA is done in
  * lower device, the skb last reference should be 0 when calling this.
- * The desc is used to track userspace buffer index.
+ * The ctx field is used to track device context.
+ * The desc field is used to track userspace buffer index.
  */
 struct ubuf_info {
-       void (*callback)(void *);
-       void *arg;
+       void (*callback)(struct ubuf_info *);
+       void *ctx;
        unsigned long desc;
 };
 
@@ -481,6 +482,7 @@ struct sk_buff {
        union {
                __u32           mark;
                __u32           dropcount;
+               __u32           avail_size;
        };
 
        sk_buff_data_t          transport_header;
@@ -1018,7 +1020,7 @@ static inline void skb_queue_splice(const struct sk_buff_head *list,
 }
 
 /**
- *     skb_queue_splice - join two skb lists and reinitialise the emptied list
+ *     skb_queue_splice_init - join two skb lists and reinitialise the emptied list
  *     @list: the new list to add
  *     @head: the place to add it in the first list
  *
@@ -1049,7 +1051,7 @@ static inline void skb_queue_splice_tail(const struct sk_buff_head *list,
 }
 
 /**
- *     skb_queue_splice_tail - join two skb lists and reinitialise the emptied list
+ *     skb_queue_splice_tail_init - join two skb lists and reinitialise the emptied list
  *     @list: the new list to add
  *     @head: the place to add it in the first list
  *
@@ -1365,6 +1367,18 @@ static inline int skb_tailroom(const struct sk_buff *skb)
        return skb_is_nonlinear(skb) ? 0 : skb->end - skb->tail;
 }
 
+/**
+ *     skb_availroom - bytes at buffer end
+ *     @skb: buffer to check
+ *
+ *     Return the number of bytes of free space at the tail of an sk_buff
+ *     allocated by sk_stream_alloc()
+ */
+static inline int skb_availroom(const struct sk_buff *skb)
+{
+       return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len;
+}
+
 /**
  *     skb_reserve - adjust headroom
  *     @skb: buffer to alter
index da2d3e2543f31cbd1464d40609dac996379c1449..b84bbd48b874b22d40d22c3cc8d57cc58346b86f 100644 (file)
@@ -265,7 +265,7 @@ struct ucred {
 #define MSG_NOSIGNAL   0x4000  /* Do not generate SIGPIPE */
 #define MSG_MORE       0x8000  /* Sender will send more */
 #define MSG_WAITFORONE 0x10000 /* recvmmsg(): block until 1+ packets avail */
-
+#define MSG_SENDPAGE_NOTLAST 0x20000 /* sendpage() internal : not the last page */
 #define MSG_EOF         MSG_FIN
 
 #define MSG_CMSG_CLOEXEC 0x40000000    /* Set close_on_exit for file
index 98679b061b6382cbdffd0d979eb5e1e7dea61ea5..fa702aeb5038d40b096e61cc65ba1b8d54d7ef39 100644 (file)
@@ -254,7 +254,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *     driver is finished with this message, it must call
  *     spi_finalize_current_message() so the subsystem can issue the next
  *     transfer
- * @prepare_transfer_hardware: there are currently no more messages on the
+ * @unprepare_transfer_hardware: there are currently no more messages on the
  *     queue so the subsystem notifies the driver that it may relax the
  *     hardware by issuing this call
  *
index 6a40c76bdcf1a7732d71675d888e722aa0dc578c..1747b6787b9e90375827a9af75148bf420caf386 100644 (file)
@@ -3,14 +3,10 @@
 
 #include <linux/compiler.h>
 
+#ifdef __KERNEL__
+
 #undef NULL
-#if defined(__cplusplus)
-#define NULL 0
-#else
 #define NULL ((void *)0)
-#endif
-
-#ifdef __KERNEL__
 
 enum {
        false   = 0,
index 8dc0ea7caf02baa404e8896d13351577a177547a..b1fd5c7925feab91948ee46f0b5140b4c0ae5399 100644 (file)
@@ -305,6 +305,13 @@ static inline int mem_cgroup_swappiness(struct mem_cgroup *mem)
        return vm_swappiness;
 }
 #endif
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
+extern void mem_cgroup_uncharge_swap(swp_entry_t ent);
+#else
+static inline void mem_cgroup_uncharge_swap(swp_entry_t ent)
+{
+}
+#endif
 #ifdef CONFIG_SWAP
 /* linux/mm/page_io.c */
 extern int swap_readpage(struct page *);
@@ -375,13 +382,6 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 {
 }
 #endif
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
-extern void mem_cgroup_uncharge_swap(swp_entry_t ent);
-#else
-static inline void mem_cgroup_uncharge_swap(swp_entry_t ent)
-{
-}
-#endif
 
 #else /* CONFIG_SWAP */
 
index e5fa50345516837d035650183aebefc7f0633d8b..7f480db60231a714b9e520f3a16856c5d4e4a5e1 100644 (file)
@@ -210,6 +210,12 @@ typedef u32 phys_addr_t;
 
 typedef phys_addr_t resource_size_t;
 
+/*
+ * This type is the placeholder for a hardware interrupt number. It has to be
+ * big enough to enclose whatever representation is used by a given platform.
+ */
+typedef unsigned long irq_hw_number_t;
+
 typedef struct {
        int counter;
 } atomic_t;
index 5de415707c234f0e54939195062b5dc39f0a1c06..d28cc78a38e442e75e435c0dede140291c57ce2c 100644 (file)
@@ -126,6 +126,8 @@ struct usb_hcd {
        unsigned                wireless:1;     /* Wireless USB HCD */
        unsigned                authorized_default:1;
        unsigned                has_tt:1;       /* Integrated TT in root hub */
+       unsigned                broken_pci_sleep:1;     /* Don't put the
+                       controller in PCI-D3 for system sleep */
 
        unsigned int            irq;            /* irq allocated */
        void __iomem            *regs;          /* device memory/io */
index f67810f8f21b1e6468af6c61e044923c005e0da4..38ab3f46346ff4852eabc4e0bbfc3fc2d5e2e793 100644 (file)
@@ -94,6 +94,7 @@ struct usb_phy {
 
        struct usb_otg          *otg;
 
+       struct device           *io_dev;
        struct usb_phy_io_ops   *io_ops;
        void __iomem            *io_priv;
 
index fbb666b1b67008ef38d9f7c2b0e9682e924fbae7..4742838882332ac766a97ddc9c582afde6127457 100644 (file)
 /* parity check flag */
 #define RELEVANT_IFLAG(iflag)  (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 
-enum port_dev_state {
-       PORT_UNREGISTERED,
-       PORT_REGISTERING,
-       PORT_REGISTERED,
-       PORT_UNREGISTERING,
-};
-
 /* USB serial flags */
 #define USB_SERIAL_WRITE_BUSY  0
 
@@ -124,7 +117,6 @@ struct usb_serial_port {
        char                    throttle_req;
        unsigned long           sysrq; /* sysrq timeout */
        struct device           dev;
-       enum port_dev_state     dev_state;
 };
 #define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
 
index 4b9a7f596f929cfb48a909f29ceb3422efb83b3f..b455c7c212eb6de26716a44ec3674eb2ebcfc270 100644 (file)
@@ -28,13 +28,19 @@ struct vga_switcheroo_handler {
        int (*get_client_id)(struct pci_dev *pdev);
 };
 
+struct vga_switcheroo_client_ops {
+       void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state);
+       void (*reprobe)(struct pci_dev *dev);
+       bool (*can_switch)(struct pci_dev *dev);
+};
 
 #if defined(CONFIG_VGA_SWITCHEROO)
 void vga_switcheroo_unregister_client(struct pci_dev *dev);
 int vga_switcheroo_register_client(struct pci_dev *dev,
-                                  void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state),
-                                  void (*reprobe)(struct pci_dev *dev),
-                                  bool (*can_switch)(struct pci_dev *dev));
+                                  const struct vga_switcheroo_client_ops *ops);
+int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
+                                        const struct vga_switcheroo_client_ops *ops,
+                                        int id, bool active);
 
 void vga_switcheroo_client_fb_set(struct pci_dev *dev,
                                  struct fb_info *info);
@@ -48,11 +54,12 @@ int vga_switcheroo_process_delayed_switch(void);
 
 static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
 static inline int vga_switcheroo_register_client(struct pci_dev *dev,
-                                         void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state),
-                                         void (*reprobe)(struct pci_dev *dev),
-                                         bool (*can_switch)(struct pci_dev *dev)) { return 0; }
+               const struct vga_switcheroo_client_ops *ops) { return 0; }
 static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {}
 static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; }
+static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
+       const struct vga_switcheroo_client_ops *ops,
+       int id, bool active) { return 0; }
 static inline void vga_switcheroo_unregister_handler(void) {}
 static inline int vga_switcheroo_process_delayed_switch(void) { return 0; }
 
index 9c3120dca294ddc41d2a131540d8135cf001de89..0ee42d9acdc0f605dc0264b071834cb53dcd95e9 100644 (file)
@@ -31,6 +31,7 @@
 #ifndef LINUX_VGA_H
 #define LINUX_VGA_H
 
+#include <video/vga.h>
 
 /* Legacy VGA regions */
 #define VGA_RSRC_NONE         0x00
@@ -47,6 +48,8 @@
  */
 #define VGA_DEFAULT_DEVICE     (NULL)
 
+struct pci_dev;
+
 /* For use by clients */
 
 /**
@@ -180,7 +183,13 @@ extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
  */
 
 #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
+#ifdef CONFIG_VGA_ARB
 extern struct pci_dev *vga_default_device(void);
+extern void vga_set_default_device(struct pci_dev *pdev);
+#else
+static inline struct pci_dev *vga_default_device(void) { return NULL; };
+static inline void vga_set_default_device(struct pci_dev *pdev) { };
+#endif
 #endif
 
 /**
index 03b90cdc1921aa7737427817066b8917edd0a808..06f8e38582512eb7be8713f5579887cdd559a813 100644 (file)
@@ -26,13 +26,14 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                PGFREE, PGACTIVATE, PGDEACTIVATE,
                PGFAULT, PGMAJFAULT,
                FOR_ALL_ZONES(PGREFILL),
-               FOR_ALL_ZONES(PGSTEAL),
+               FOR_ALL_ZONES(PGSTEAL_KSWAPD),
+               FOR_ALL_ZONES(PGSTEAL_DIRECT),
                FOR_ALL_ZONES(PGSCAN_KSWAPD),
                FOR_ALL_ZONES(PGSCAN_DIRECT),
 #ifdef CONFIG_NUMA
                PGSCAN_ZONE_RECLAIM_FAILED,
 #endif
-               PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL,
+               PGINODESTEAL, SLABS_SCANNED, KSWAPD_INODESTEAL,
                KSWAPD_LOW_WMARK_HIT_QUICKLY, KSWAPD_HIGH_WMARK_HIT_QUICKLY,
                KSWAPD_SKIP_CONGESTION_WAIT,
                PAGEOUTRUN, ALLOCSTALL, PGROTATED,
index 344b0f972828f4167393948c4263a628309ca7c6..d47e523c9d83387460f905414952d81c54b8361e 100644 (file)
@@ -92,6 +92,7 @@ enum {
        HCI_SERVICE_CACHE,
        HCI_LINK_KEYS,
        HCI_DEBUG_KEYS,
+       HCI_UNREGISTER,
 
        HCI_LE_SCAN,
        HCI_SSP_ENABLED,
@@ -1327,8 +1328,8 @@ struct sockaddr_hci {
 #define HCI_DEV_NONE   0xffff
 
 #define HCI_CHANNEL_RAW                0
-#define HCI_CHANNEL_CONTROL    1
 #define HCI_CHANNEL_MONITOR    2
+#define HCI_CHANNEL_CONTROL    3
 
 struct hci_filter {
        unsigned long type_mask;
index daefaac511311348ac2772eeeed9d2f9ca0c7679..db1c5df45224d1635d7de925c51e5cb585e5346a 100644 (file)
@@ -314,6 +314,7 @@ struct hci_conn {
 
        __u8            remote_cap;
        __u8            remote_auth;
+       bool            flush_key;
 
        unsigned int    sent;
 
@@ -427,7 +428,7 @@ enum {
 static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
 {
        struct hci_dev *hdev = conn->hdev;
-       return (test_bit(HCI_SSP_ENABLED, &hdev->flags) &&
+       return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
                                test_bit(HCI_CONN_SSP_ENABLED, &conn->flags));
 }
 
@@ -907,11 +908,13 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
 
 static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
 {
-       u8 field_len;
-       size_t parsed;
+       size_t parsed = 0;
 
-       for (parsed = 0; parsed < data_len - 1; parsed += field_len) {
-               field_len = data[0];
+       if (data_len < 2)
+               return false;
+
+       while (parsed < data_len - 1) {
+               u8 field_len = data[0];
 
                if (field_len == 0)
                        break;
@@ -978,7 +981,7 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
 int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
 int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
 int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
-                     u8 persistent);
+                     bool persistent);
 int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
                          u8 addr_type, u32 flags, u8 *name, u8 name_len,
                          u8 *dev_class);
index ffc1377e092eb2a9b15b91a799e4e18672b10bb6..ebfd91fc20f804437241614418e7505ac15c83a0 100644 (file)
@@ -117,7 +117,7 @@ struct mgmt_mode {
 #define MGMT_OP_SET_DISCOVERABLE       0x0006
 struct mgmt_cp_set_discoverable {
        __u8    val;
-       __u16   timeout;
+       __le16  timeout;
 } __packed;
 #define MGMT_SET_DISCOVERABLE_SIZE     3
 
index 248fb05feb639aef5ae8d099a3e651d129ea2d14..83d800c31e3cf4b6a8829df75ff3d627ee826542 100644 (file)
@@ -620,8 +620,10 @@ struct sta_bss_parameters {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
- * @signal: signal strength of last received packet in dBm
- * @signal_avg: signal strength average in dBm
+ * @signal: the signal strength, type depends on the wiphy's signal_type
+       NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @signal_avg: avg signal strength, type depends on the wiphy's signal_type
+       NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
  * @txrate: current unicast bitrate from this station
  * @rxrate: current unicast bitrate to this station
  * @rx_packets: packets received from this station
index 59c5d18cc3857da85690627b085e1065eeeb78ad..bed833d9796aed86bac5ca7d45ad53cde3447e52 100644 (file)
@@ -36,7 +36,11 @@ struct dst_entry {
        struct net_device       *dev;
        struct  dst_ops         *ops;
        unsigned long           _metrics;
-       unsigned long           expires;
+       union {
+               unsigned long           expires;
+               /* point to where the dst_entry copied from */
+               struct dst_entry        *from;
+       };
        struct dst_entry        *path;
        struct neighbour __rcu  *_neighbour;
 #ifdef CONFIG_XFRM
@@ -55,6 +59,7 @@ struct dst_entry {
 #define DST_NOCACHE            0x0010
 #define DST_NOCOUNT            0x0020
 #define DST_NOPEER             0x0040
+#define DST_FAKE_RTABLE                0x0080
 
        short                   error;
        short                   obsolete;
index b26bb810198169c9b0d10462c282d284a6ad1bca..0ae759a6c76ef7f2b58ba28588195223443ca352 100644 (file)
@@ -123,6 +123,54 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
        return ((struct rt6_info *)dst)->rt6i_idev;
 }
 
+static inline void rt6_clean_expires(struct rt6_info *rt)
+{
+       if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
+               dst_release(rt->dst.from);
+
+       rt->rt6i_flags &= ~RTF_EXPIRES;
+       rt->dst.from = NULL;
+}
+
+static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
+{
+       if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
+               dst_release(rt->dst.from);
+
+       rt->rt6i_flags |= RTF_EXPIRES;
+       rt->dst.expires = expires;
+}
+
+static inline void rt6_update_expires(struct rt6_info *rt, int timeout)
+{
+       if (!(rt->rt6i_flags & RTF_EXPIRES)) {
+               if (rt->dst.from)
+                       dst_release(rt->dst.from);
+               /* dst_set_expires relies on expires == 0 
+                * if it has not been set previously.
+                */
+               rt->dst.expires = 0;
+       }
+
+       dst_set_expires(&rt->dst, timeout);
+       rt->rt6i_flags |= RTF_EXPIRES;
+}
+
+static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
+{
+       struct dst_entry *new = (struct dst_entry *) from;
+
+       if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) {
+               if (new == rt->dst.from)
+                       return;
+               dst_release(rt->dst.from);
+       }
+
+       rt->rt6i_flags &= ~RTF_EXPIRES;
+       rt->dst.from = new;
+       dst_hold(new);
+}
+
 struct fib6_walker_t {
        struct list_head lh;
        struct fib6_node *root, *node;
index 2bdee51ba30d29f1ccd296fdbdcd06a709a5b4c4..72522f0873757ae08507671667cc7bc7cc849110 100644 (file)
@@ -393,7 +393,7 @@ struct ip_vs_protocol {
 
        void (*exit)(struct ip_vs_protocol *pp);
 
-       void (*init_netns)(struct net *net, struct ip_vs_proto_data *pd);
+       int (*init_netns)(struct net *net, struct ip_vs_proto_data *pd);
 
        void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd);
 
@@ -1203,6 +1203,8 @@ ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
 
 extern int ip_vs_use_count_inc(void);
 extern void ip_vs_use_count_dec(void);
+extern int ip_vs_register_nl_ioctl(void);
+extern void ip_vs_unregister_nl_ioctl(void);
 extern int ip_vs_control_init(void);
 extern void ip_vs_control_cleanup(void);
 extern struct ip_vs_dest *
index 87d203ff7a8ad4d43ae97bcd91116529934b4ef7..9210bdc7bd8d417b94cf721b9ac671f7f2e700ed 100644 (file)
@@ -1327,7 +1327,7 @@ static inline struct ieee80211_rate *
 ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
                      const struct ieee80211_tx_info *c)
 {
-       if (WARN_ON(c->control.rates[0].idx < 0))
+       if (WARN_ON_ONCE(c->control.rates[0].idx < 0))
                return NULL;
        return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx];
 }
index 7e1544e8f70d36599205fd821f1cdc34705d1676..9d9756cca0132bbc603c313b0ecb18670fef3bb0 100644 (file)
@@ -47,7 +47,7 @@ static void sb_close(struct sbuff *m)
        if (likely(m != &emergency))
                kfree(m);
        else {
-               xchg(&emergency_ptr, m);
+               emergency_ptr = m;
                local_bh_enable();
        }
 }
index 77d4c3745cb5be169f87507a34349cd853e8da10..ef46058d35bf0de1fdabf80915594f9d201a0a5c 100644 (file)
@@ -245,7 +245,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms
         *
         * dummy packets as a burst after idle time, i.e.
         *
-        *      p->qavg *= (1-W)^m
+        *      v->qavg *= (1-W)^m
         *
         * This is an apparently overcomplicated solution (f.e. we have to
         * precompute a table to make this calculation in reasonable time)
@@ -279,7 +279,7 @@ static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p
                                                       unsigned int backlog)
 {
        /*
-        * NOTE: p->qavg is fixed point number with point at Wlog.
+        * NOTE: v->qavg is fixed point number with point at Wlog.
         * The formula below is equvalent to floating point
         * version:
         *
@@ -390,7 +390,7 @@ static inline void red_adaptative_algo(struct red_parms *p, struct red_vars *v)
        if (red_is_idling(v))
                qavg = red_calc_qavg_from_idle_time(p, v);
 
-       /* p->qavg is fixed point number with point at Wlog */
+       /* v->qavg is fixed point number with point at Wlog */
        qavg >>= p->Wlog;
 
        if (qavg > p->target_max && p->max_P <= MAX_P_MAX)
index a6ba1f8871fda3077183717a1e099cd5161b555c..5a0a58ac4126c47517ea5a4da0fdb051cc88daba 100644 (file)
@@ -246,6 +246,7 @@ struct cg_proto;
   *    @sk_user_data: RPC layer private data
   *    @sk_sndmsg_page: cached page for sendmsg
   *    @sk_sndmsg_off: cached offset for sendmsg
+  *    @sk_peek_off: current peek_offset value
   *    @sk_send_head: front of stuff to transmit
   *    @sk_security: used by security modules
   *    @sk_mark: generic packet mark
@@ -1128,9 +1129,9 @@ sk_sockets_allocated_read_positive(struct sock *sk)
        struct proto *prot = sk->sk_prot;
 
        if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
-               return percpu_counter_sum_positive(sk->sk_cgrp->sockets_allocated);
+               return percpu_counter_read_positive(sk->sk_cgrp->sockets_allocated);
 
-       return percpu_counter_sum_positive(prot->sockets_allocated);
+       return percpu_counter_read_positive(prot->sockets_allocated);
 }
 
 static inline int
index 5f5ed1b8b41bb7d28886895e7742cb80e16f6a8b..f4f1c96dca726ff2f00211994dcf7381ef55b5b0 100644 (file)
@@ -217,11 +217,29 @@ struct domain_device {
        struct kref kref;
 };
 
-struct sas_discovery_event {
+struct sas_work {
+       struct list_head drain_node;
        struct work_struct work;
+};
+
+static inline void INIT_SAS_WORK(struct sas_work *sw, void (*fn)(struct work_struct *))
+{
+       INIT_WORK(&sw->work, fn);
+       INIT_LIST_HEAD(&sw->drain_node);
+}
+
+struct sas_discovery_event {
+       struct sas_work work;
        struct asd_sas_port *port;
 };
 
+static inline struct sas_discovery_event *to_sas_discovery_event(struct work_struct *work)
+{
+       struct sas_discovery_event *ev = container_of(work, typeof(*ev), work.work);
+
+       return ev;
+}
+
 struct sas_discovery {
        struct sas_discovery_event disc_work[DISC_NUM_EVENTS];
        unsigned long    pending;
@@ -244,7 +262,7 @@ struct asd_sas_port {
        struct list_head destroy_list;
        enum   sas_linkrate linkrate;
 
-       struct work_struct work;
+       struct sas_work work;
 
 /* public: */
        int id;
@@ -270,10 +288,17 @@ struct asd_sas_port {
 };
 
 struct asd_sas_event {
-       struct work_struct work;
+       struct sas_work work;
        struct asd_sas_phy *phy;
 };
 
+static inline struct asd_sas_event *to_asd_sas_event(struct work_struct *work)
+{
+       struct asd_sas_event *ev = container_of(work, typeof(*ev), work.work);
+
+       return ev;
+}
+
 /* The phy pretty much is controlled by the LLDD.
  * The class only reads those fields.
  */
@@ -333,10 +358,17 @@ struct scsi_core {
 };
 
 struct sas_ha_event {
-       struct work_struct work;
+       struct sas_work work;
        struct sas_ha_struct *ha;
 };
 
+static inline struct sas_ha_event *to_sas_ha_event(struct work_struct *work)
+{
+       struct sas_ha_event *ev = container_of(work, typeof(*ev), work.work);
+
+       return ev;
+}
+
 enum sas_ha_state {
        SAS_HA_REGISTERED,
        SAS_HA_DRAINING,
index cdccd2eb7b6cd759003ecd11903d397a166bc87a..77670e823ed8e7926c617c6a736f6c427f3b437e 100644 (file)
@@ -37,7 +37,7 @@ static inline int dev_is_sata(struct domain_device *dev)
 }
 
 int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy);
-int sas_ata_init_host_and_port(struct domain_device *found_dev);
+int sas_ata_init(struct domain_device *dev);
 void sas_ata_task_abort(struct sas_task *task);
 void sas_ata_strategy_handler(struct Scsi_Host *shost);
 void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
@@ -52,7 +52,7 @@ static inline int dev_is_sata(struct domain_device *dev)
 {
        return 0;
 }
-static inline int sas_ata_init_host_and_port(struct domain_device *found_dev)
+static inline int sas_ata_init(struct domain_device *dev)
 {
        return 0;
 }
index 377df4a28512bd7d97aad68b9a72d1f449f2cba8..1e1198546c725d43a7ff6baa657c25ef364d73ee 100644 (file)
@@ -134,6 +134,9 @@ struct scsi_cmnd {
 
 static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
 {
+       if (!cmd->request->rq_disk)
+               return NULL;
+
        return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
 }
 
index fbc7b1ad929bd007940233e3e1bd9a4e9eb31829..ea7a2035456d4f913e15b9997696ab5ca4934ad1 100644 (file)
@@ -295,7 +295,7 @@ TRACE_EVENT(sched_process_exec,
        TP_fast_assign(
                __assign_str(filename, bprm->filename);
                __entry->pid            = p->pid;
-               __entry->old_pid        = p->pid;
+               __entry->old_pid        = old_pid;
        ),
 
        TP_printk("filename=%s pid=%d old_pid=%d", __get_str(filename),
index 2ea2fdc79c161eb2a63b948068a1bb599335ef62..4f4d449f00f6b98644be40b85f108667c4cb1642 100644 (file)
@@ -7,11 +7,13 @@ extern void xen_swiotlb_init(int verbose);
 
 extern void
 *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
-                           dma_addr_t *dma_handle, gfp_t flags);
+                           dma_addr_t *dma_handle, gfp_t flags,
+                           struct dma_attrs *attrs);
 
 extern void
 xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
-                         void *vaddr, dma_addr_t dma_handle);
+                         void *vaddr, dma_addr_t dma_handle,
+                         struct dma_attrs *attrs);
 
 extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
                                       unsigned long offset, size_t size,
index 72f33faca44fbef6734cdce724090c917ccf52b9..6cfd71d064637a0335677e7e2f7d73d941c50fe4 100644 (file)
@@ -1414,8 +1414,8 @@ endif # MODULES
 config INIT_ALL_POSSIBLE
        bool
        help
-         Back when each arch used to define their own cpu_online_map and
-         cpu_possible_map, some of them chose to initialize cpu_possible_map
+         Back when each arch used to define their own cpu_online_mask and
+         cpu_possible_mask, some of them chose to initialize cpu_possible_mask
          with all 1s, and others with all 0s.  When they were centralised,
          it was better to provide this option than to break all the archs
          and have several arch maintainers pursuing me down dark alleys.
index 0e93f92a0345a09a2aa84608a3bca34153a2eabb..42b0707c348108b98f6ce05ae1a98ad4f64a0e86 100644 (file)
@@ -472,7 +472,7 @@ void __init change_floppy(char *fmt, ...)
 void __init mount_root(void)
 {
 #ifdef CONFIG_ROOT_NFS
-       if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+       if (ROOT_DEV == Root_NFS) {
                if (mount_nfs_root())
                        return;
 
index 9d454f09f3b1522c850b99d31f517641e47a8503..44b2433334c749ed92d7e42e5938f840efd843c0 100644 (file)
@@ -225,13 +225,9 @@ static int __init loglevel(char *str)
 
 early_param("loglevel", loglevel);
 
-/*
- * Unknown boot options get handed to init, unless they look like
- * unused parameters (modprobe will find them in /proc/cmdline).
- */
-static int __init unknown_bootoption(char *param, char *val)
+/* Change NUL term back to "=", to make "param" the whole string. */
+static int __init repair_env_string(char *param, char *val)
 {
-       /* Change NUL term back to "=", to make "param" the whole string. */
        if (val) {
                /* param=val or param="val"? */
                if (val == param+strlen(param)+1)
@@ -243,6 +239,16 @@ static int __init unknown_bootoption(char *param, char *val)
                } else
                        BUG();
        }
+       return 0;
+}
+
+/*
+ * Unknown boot options get handed to init, unless they look like
+ * unused parameters (modprobe will find them in /proc/cmdline).
+ */
+static int __init unknown_bootoption(char *param, char *val)
+{
+       repair_env_string(param, val);
 
        /* Handle obsolete-style parameters */
        if (obsolete_checksetup(param))
@@ -732,11 +738,6 @@ static char *initcall_level_names[] __initdata = {
        "late parameters",
 };
 
-static int __init ignore_unknown_bootoption(char *param, char *val)
-{
-       return 0;
-}
-
 static void __init do_initcall_level(int level)
 {
        extern const struct kernel_param __start___param[], __stop___param[];
@@ -747,7 +748,7 @@ static void __init do_initcall_level(int level)
                   static_command_line, __start___param,
                   __stop___param - __start___param,
                   level, level,
-                  ignore_unknown_bootoption);
+                  repair_env_string);
 
        for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
                do_one_initcall(*fn);
index b96ad75b7e64c6474b02d4d91534659bc43eb252..14f7070b4ba280ee353b84ccda1faa841ecd1ead 100644 (file)
@@ -270,11 +270,11 @@ static struct file_system_type cpuset_fs_type = {
  * are online.  If none are online, walk up the cpuset hierarchy
  * until we find one that does have some online cpus.  If we get
  * all the way to the top and still haven't found any online cpus,
- * return cpu_online_map.  Or if passed a NULL cs from an exit'ing
- * task, return cpu_online_map.
+ * return cpu_online_mask.  Or if passed a NULL cs from an exit'ing
+ * task, return cpu_online_mask.
  *
  * One way or another, we guarantee to return some non-empty subset
- * of cpu_online_map.
+ * of cpu_online_mask.
  *
  * Call with callback_mutex held.
  */
@@ -867,7 +867,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
        int retval;
        int is_load_balanced;
 
-       /* top_cpuset.cpus_allowed tracks cpu_online_map; it's read-only */
+       /* top_cpuset.cpus_allowed tracks cpu_online_mask; it's read-only */
        if (cs == &top_cpuset)
                return -EACCES;
 
@@ -2149,7 +2149,7 @@ void __init cpuset_init_smp(void)
  *
  * Description: Returns the cpumask_var_t cpus_allowed of the cpuset
  * attached to the specified @tsk.  Guaranteed to return some non-empty
- * subset of cpu_online_map, even if this means going outside the
+ * subset of cpu_online_mask, even if this means going outside the
  * tasks cpuset.
  **/
 
index 97b36eeca4c90b51cf9fa0abcd81af72e1dfb715..e70683d9ec32f00bf58a0ea2dc64be2d74fb8415 100644 (file)
@@ -386,6 +386,8 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
        struct cred *new;
        int ret;
 
+       p->replacement_session_keyring = NULL;
+
        if (
 #ifdef CONFIG_KEYS
                !p->cred->thread_keyring &&
index 1dc53bae56e1f6974a7f7cdb7f9d82815d85a22c..0557f24c6bca0d1da04f620c163a70010930737e 100644 (file)
@@ -160,37 +160,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup);
  * Weak aliases for breakpoint management,
  * can be overriden by architectures when needed:
  */
-int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
+int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
        int err;
 
-       err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE);
+       err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+                               BREAK_INSTR_SIZE);
        if (err)
                return err;
-
-       return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
-                                 BREAK_INSTR_SIZE);
+       err = probe_kernel_write((char *)bpt->bpt_addr,
+                                arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+       return err;
 }
 
-int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
+int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 {
-       return probe_kernel_write((char *)addr,
-                                 (char *)bundle, BREAK_INSTR_SIZE);
+       return probe_kernel_write((char *)bpt->bpt_addr,
+                                 (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
 
 int __weak kgdb_validate_break_address(unsigned long addr)
 {
-       char tmp_variable[BREAK_INSTR_SIZE];
+       struct kgdb_bkpt tmp;
        int err;
-       /* Validate setting the breakpoint and then removing it.  In the
+       /* Validate setting the breakpoint and then removing it.  If the
         * remove fails, the kernel needs to emit a bad message because we
         * are deep trouble not being able to put things back the way we
         * found them.
         */
-       err = kgdb_arch_set_breakpoint(addr, tmp_variable);
+       tmp.bpt_addr = addr;
+       err = kgdb_arch_set_breakpoint(&tmp);
        if (err)
                return err;
-       err = kgdb_arch_remove_breakpoint(addr, tmp_variable);
+       err = kgdb_arch_remove_breakpoint(&tmp);
        if (err)
                printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
                   "memory destroyed at: %lx", addr);
@@ -234,7 +236,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr)
  */
 int dbg_activate_sw_breakpoints(void)
 {
-       unsigned long addr;
        int error;
        int ret = 0;
        int i;
@@ -243,16 +244,15 @@ int dbg_activate_sw_breakpoints(void)
                if (kgdb_break[i].state != BP_SET)
                        continue;
 
-               addr = kgdb_break[i].bpt_addr;
-               error = kgdb_arch_set_breakpoint(addr,
-                               kgdb_break[i].saved_instr);
+               error = kgdb_arch_set_breakpoint(&kgdb_break[i]);
                if (error) {
                        ret = error;
-                       printk(KERN_INFO "KGDB: BP install failed: %lx", addr);
+                       printk(KERN_INFO "KGDB: BP install failed: %lx",
+                              kgdb_break[i].bpt_addr);
                        continue;
                }
 
-               kgdb_flush_swbreak_addr(addr);
+               kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
                kgdb_break[i].state = BP_ACTIVE;
        }
        return ret;
@@ -301,7 +301,6 @@ int dbg_set_sw_break(unsigned long addr)
 
 int dbg_deactivate_sw_breakpoints(void)
 {
-       unsigned long addr;
        int error;
        int ret = 0;
        int i;
@@ -309,15 +308,14 @@ int dbg_deactivate_sw_breakpoints(void)
        for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
                if (kgdb_break[i].state != BP_ACTIVE)
                        continue;
-               addr = kgdb_break[i].bpt_addr;
-               error = kgdb_arch_remove_breakpoint(addr,
-                                       kgdb_break[i].saved_instr);
+               error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
                if (error) {
-                       printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr);
+                       printk(KERN_INFO "KGDB: BP remove failed: %lx\n",
+                              kgdb_break[i].bpt_addr);
                        ret = error;
                }
 
-               kgdb_flush_swbreak_addr(addr);
+               kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
                kgdb_break[i].state = BP_SET;
        }
        return ret;
@@ -351,7 +349,6 @@ int kgdb_isremovedbreak(unsigned long addr)
 
 int dbg_remove_all_break(void)
 {
-       unsigned long addr;
        int error;
        int i;
 
@@ -359,12 +356,10 @@ int dbg_remove_all_break(void)
        for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
                if (kgdb_break[i].state != BP_ACTIVE)
                        goto setundefined;
-               addr = kgdb_break[i].bpt_addr;
-               error = kgdb_arch_remove_breakpoint(addr,
-                               kgdb_break[i].saved_instr);
+               error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
                if (error)
                        printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
-                          addr);
+                              kgdb_break[i].bpt_addr);
 setundefined:
                kgdb_break[i].state = BP_UNDEFINED;
        }
index 9b5f17da1c560e65fe945a9ab580f4de87ccb1ac..bb9520f0f6ff8e607d0b08b2561efa62f4ba3b8d 100644 (file)
@@ -743,7 +743,7 @@ kdb_printit:
                kdb_input_flush();
                c = console_drivers;
 
-               if (!dbg_io_ops->is_console) {
+               if (dbg_io_ops && !dbg_io_ops->is_console) {
                        len = strlen(moreprompt);
                        cp = moreprompt;
                        while (len--) {
index a6a9ec4cd8f583d640ab0da9e4941b19fe8fd990..fd126f82b57cc77db01c5fd42e3e30b230d98a30 100644 (file)
@@ -3183,7 +3183,7 @@ static void perf_event_for_each(struct perf_event *event,
        perf_event_for_each_child(event, func);
        func(event);
        list_for_each_entry(sibling, &event->sibling_list, group_entry)
-               perf_event_for_each_child(event, func);
+               perf_event_for_each_child(sibling, func);
        mutex_unlock(&ctx->mutex);
 }
 
index cf1a4a68ce444f03218ea0adbbd1f0ea178cc4d0..d1a758bc972afcb3f7c0103de781fa5720bea126 100644 (file)
@@ -62,7 +62,7 @@ config IRQ_DOMAIN_DEBUG
        help
          This option will show the mapping relationship between hardware irq
          numbers and Linux irq numbers. The mapping is exposed via debugfs
-         in the file "virq_mapping".
+         in the file "irq_domain_mapping".
 
          If you don't know what this means you don't need it.
 
index 97a8bfadc88a0cec4192bd457e18a54aca159cf0..e75e29e4434a9073b0d05f39903df2cf7f4c2d10 100644 (file)
@@ -4,10 +4,10 @@
 
 #include <linux/kallsyms.h>
 
-#define P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
-#define PS(f) if (desc->istate & f) printk("%14s set\n", #f)
+#define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
+#define ___PS(f) if (desc->istate & f) printk("%14s set\n", #f)
 /* FIXME */
-#define PD(f) do { } while (0)
+#define ___PD(f) do { } while (0)
 
 static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
 {
@@ -23,23 +23,23 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
                print_symbol("%s\n", (unsigned long)desc->action->handler);
        }
 
-       P(IRQ_LEVEL);
-       P(IRQ_PER_CPU);
-       P(IRQ_NOPROBE);
-       P(IRQ_NOREQUEST);
-       P(IRQ_NOTHREAD);
-       P(IRQ_NOAUTOEN);
+       ___P(IRQ_LEVEL);
+       ___P(IRQ_PER_CPU);
+       ___P(IRQ_NOPROBE);
+       ___P(IRQ_NOREQUEST);
+       ___P(IRQ_NOTHREAD);
+       ___P(IRQ_NOAUTOEN);
 
-       PS(IRQS_AUTODETECT);
-       PS(IRQS_REPLAY);
-       PS(IRQS_WAITING);
-       PS(IRQS_PENDING);
+       ___PS(IRQS_AUTODETECT);
+       ___PS(IRQS_REPLAY);
+       ___PS(IRQS_WAITING);
+       ___PS(IRQS_PENDING);
 
-       PD(IRQS_INPROGRESS);
-       PD(IRQS_DISABLED);
-       PD(IRQS_MASKED);
+       ___PD(IRQS_INPROGRESS);
+       ___PD(IRQS_DISABLED);
+       ___PD(IRQS_MASKED);
 }
 
-#undef P
-#undef PS
-#undef PD
+#undef ___P
+#undef ___PS
+#undef ___PD
index 3601f3fbf67c8808cb0223206713b1d1aeeb31bb..0e0ba5f840b26c84affc8fe813ce4a89b51753bf 100644 (file)
@@ -23,7 +23,6 @@ static LIST_HEAD(irq_domain_list);
 static DEFINE_MUTEX(irq_domain_mutex);
 
 static DEFINE_MUTEX(revmap_trees_mutex);
-static unsigned int irq_virq_count = NR_IRQS;
 static struct irq_domain *irq_default_domain;
 
 /**
@@ -184,13 +183,16 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
 }
 
 struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
+                                        unsigned int max_irq,
                                         const struct irq_domain_ops *ops,
                                         void *host_data)
 {
        struct irq_domain *domain = irq_domain_alloc(of_node,
                                        IRQ_DOMAIN_MAP_NOMAP, ops, host_data);
-       if (domain)
+       if (domain) {
+               domain->revmap_data.nomap.max_irq = max_irq ? max_irq : ~0;
                irq_domain_add(domain);
+       }
        return domain;
 }
 
@@ -262,22 +264,6 @@ void irq_set_default_host(struct irq_domain *domain)
        irq_default_domain = domain;
 }
 
-/**
- * irq_set_virq_count() - Set the maximum number of linux irqs
- * @count: number of linux irqs, capped with NR_IRQS
- *
- * This is mainly for use by platforms like iSeries who want to program
- * the virtual irq number in the controller to avoid the reverse mapping
- */
-void irq_set_virq_count(unsigned int count)
-{
-       pr_debug("irq: Trying to set virq count to %d\n", count);
-
-       BUG_ON(count < NUM_ISA_INTERRUPTS);
-       if (count < NR_IRQS)
-               irq_virq_count = count;
-}
-
 static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
                            irq_hw_number_t hwirq)
 {
@@ -320,13 +306,12 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
                pr_debug("irq: create_direct virq allocation failed\n");
                return 0;
        }
-       if (virq >= irq_virq_count) {
+       if (virq >= domain->revmap_data.nomap.max_irq) {
                pr_err("ERROR: no free irqs available below %i maximum\n",
-                       irq_virq_count);
+                       domain->revmap_data.nomap.max_irq);
                irq_free_desc(virq);
                return 0;
        }
-
        pr_debug("irq: create_direct obtained virq %d\n", virq);
 
        if (irq_setup_virq(domain, virq, virq)) {
@@ -350,7 +335,8 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
 unsigned int irq_create_mapping(struct irq_domain *domain,
                                irq_hw_number_t hwirq)
 {
-       unsigned int virq, hint;
+       unsigned int hint;
+       int virq;
 
        pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
 
@@ -377,13 +363,13 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
                return irq_domain_legacy_revmap(domain, hwirq);
 
        /* Allocate a virtual interrupt number */
-       hint = hwirq % irq_virq_count;
+       hint = hwirq % nr_irqs;
        if (hint == 0)
                hint++;
        virq = irq_alloc_desc_from(hint, 0);
-       if (!virq)
+       if (virq <= 0)
                virq = irq_alloc_desc_from(1, 0);
-       if (!virq) {
+       if (virq <= 0) {
                pr_debug("irq: -> virq allocation failed\n");
                return 0;
        }
@@ -515,7 +501,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
                              irq_hw_number_t hwirq)
 {
        unsigned int i;
-       unsigned int hint = hwirq % irq_virq_count;
+       unsigned int hint = hwirq % nr_irqs;
 
        /* Look for default domain if nececssary */
        if (domain == NULL)
@@ -536,7 +522,7 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
                if (data && (data->domain == domain) && (data->hwirq == hwirq))
                        return i;
                i++;
-               if (i >= irq_virq_count)
+               if (i >= nr_irqs)
                        i = 1;
        } while(i != hint);
        return 0;
@@ -642,8 +628,9 @@ static int virq_debug_show(struct seq_file *m, void *private)
        void *data;
        int i;
 
-       seq_printf(m, "%-5s  %-7s  %-15s  %-18s  %s\n", "virq", "hwirq",
-                     "chip name", "chip data", "domain name");
+       seq_printf(m, "%-5s  %-7s  %-15s  %-*s  %s\n", "irq", "hwirq",
+                     "chip name", (int)(2 * sizeof(void *) + 2), "chip data",
+                     "domain name");
 
        for (i = 1; i < nr_irqs; i++) {
                desc = irq_to_desc(i);
@@ -666,7 +653,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
                        seq_printf(m, "%-15s  ", p);
 
                        data = irq_desc_get_chip_data(desc);
-                       seq_printf(m, "0x%16p  ", data);
+                       seq_printf(m, data ? "0x%p  " : "  %p  ", data);
 
                        if (desc->irq_data.domain && desc->irq_data.domain->of_node)
                                p = desc->irq_data.domain->of_node->full_name;
index c3c46c72046e37898ebbedb567b7eede3d67ae60..1588e3b2871b9e28a68316f91ca418d44a75cba2 100644 (file)
@@ -5,11 +5,13 @@
  * context. The enqueueing is NMI-safe.
  */
 
+#include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/irq_work.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/irqflags.h>
 #include <asm/processor.h>
 
 /*
index 22000c3db0dd53e28b01fc05a302316e02d1d221..8d262b4675738d21bea752d65a47117c3d8ae514 100644 (file)
@@ -284,8 +284,12 @@ SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,
        if (value) {
                if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
                        return -EFAULT;
-       } else
-               memset((char *) &set_buffer, 0, sizeof(set_buffer));
+       } else {
+               memset(&set_buffer, 0, sizeof(set_buffer));
+               printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer."
+                           " Misfeature support will be removed\n",
+                           current->comm);
+       }
 
        error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL);
        if (error || !ovalue)
index 957a7aab8ebc2b4d1527763c2666298be1dc419c..05698a7415fea66ea604b87959bde93f5b2673a3 100644 (file)
@@ -322,7 +322,7 @@ static void __call_usermodehelper(struct work_struct *work)
  * land has been frozen during a system-wide hibernation or suspend operation).
  * Should always be manipulated under umhelper_sem acquired for write.
  */
-static int usermodehelper_disabled = 1;
+static enum umh_disable_depth usermodehelper_disabled = UMH_DISABLED;
 
 /* Number of helpers running */
 static atomic_t running_helpers = ATOMIC_INIT(0);
@@ -333,33 +333,111 @@ static atomic_t running_helpers = ATOMIC_INIT(0);
  */
 static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
 
+/*
+ * Used by usermodehelper_read_lock_wait() to wait for usermodehelper_disabled
+ * to become 'false'.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq);
+
 /*
  * Time to wait for running_helpers to become zero before the setting of
  * usermodehelper_disabled in usermodehelper_disable() fails
  */
 #define RUNNING_HELPERS_TIMEOUT        (5 * HZ)
 
-void read_lock_usermodehelper(void)
+int usermodehelper_read_trylock(void)
 {
+       DEFINE_WAIT(wait);
+       int ret = 0;
+
        down_read(&umhelper_sem);
+       for (;;) {
+               prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
+                               TASK_INTERRUPTIBLE);
+               if (!usermodehelper_disabled)
+                       break;
+
+               if (usermodehelper_disabled == UMH_DISABLED)
+                       ret = -EAGAIN;
+
+               up_read(&umhelper_sem);
+
+               if (ret)
+                       break;
+
+               schedule();
+               try_to_freeze();
+
+               down_read(&umhelper_sem);
+       }
+       finish_wait(&usermodehelper_disabled_waitq, &wait);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usermodehelper_read_trylock);
+
+long usermodehelper_read_lock_wait(long timeout)
+{
+       DEFINE_WAIT(wait);
+
+       if (timeout < 0)
+               return -EINVAL;
+
+       down_read(&umhelper_sem);
+       for (;;) {
+               prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
+                               TASK_UNINTERRUPTIBLE);
+               if (!usermodehelper_disabled)
+                       break;
+
+               up_read(&umhelper_sem);
+
+               timeout = schedule_timeout(timeout);
+               if (!timeout)
+                       break;
+
+               down_read(&umhelper_sem);
+       }
+       finish_wait(&usermodehelper_disabled_waitq, &wait);
+       return timeout;
 }
-EXPORT_SYMBOL_GPL(read_lock_usermodehelper);
+EXPORT_SYMBOL_GPL(usermodehelper_read_lock_wait);
 
-void read_unlock_usermodehelper(void)
+void usermodehelper_read_unlock(void)
 {
        up_read(&umhelper_sem);
 }
-EXPORT_SYMBOL_GPL(read_unlock_usermodehelper);
+EXPORT_SYMBOL_GPL(usermodehelper_read_unlock);
 
 /**
- * usermodehelper_disable - prevent new helpers from being started
+ * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled.
+ * depth: New value to assign to usermodehelper_disabled.
+ *
+ * Change the value of usermodehelper_disabled (under umhelper_sem locked for
+ * writing) and wakeup tasks waiting for it to change.
  */
-int usermodehelper_disable(void)
+void __usermodehelper_set_disable_depth(enum umh_disable_depth depth)
+{
+       down_write(&umhelper_sem);
+       usermodehelper_disabled = depth;
+       wake_up(&usermodehelper_disabled_waitq);
+       up_write(&umhelper_sem);
+}
+
+/**
+ * __usermodehelper_disable - Prevent new helpers from being started.
+ * @depth: New value to assign to usermodehelper_disabled.
+ *
+ * Set usermodehelper_disabled to @depth and wait for running helpers to exit.
+ */
+int __usermodehelper_disable(enum umh_disable_depth depth)
 {
        long retval;
 
+       if (!depth)
+               return -EINVAL;
+
        down_write(&umhelper_sem);
-       usermodehelper_disabled = 1;
+       usermodehelper_disabled = depth;
        up_write(&umhelper_sem);
 
        /*
@@ -374,31 +452,10 @@ int usermodehelper_disable(void)
        if (retval)
                return 0;
 
-       down_write(&umhelper_sem);
-       usermodehelper_disabled = 0;
-       up_write(&umhelper_sem);
+       __usermodehelper_set_disable_depth(UMH_ENABLED);
        return -EAGAIN;
 }
 
-/**
- * usermodehelper_enable - allow new helpers to be started again
- */
-void usermodehelper_enable(void)
-{
-       down_write(&umhelper_sem);
-       usermodehelper_disabled = 0;
-       up_write(&umhelper_sem);
-}
-
-/**
- * usermodehelper_is_disabled - check if new helpers are allowed to be started
- */
-bool usermodehelper_is_disabled(void)
-{
-       return usermodehelper_disabled;
-}
-EXPORT_SYMBOL_GPL(usermodehelper_is_disabled);
-
 static void helper_lock(void)
 {
        atomic_inc(&running_helpers);
index 6f10eb285ece5136177345ba368493a3b66932a9..89fe3d1b9efbc1f34351e5752dd730db3c5bbab4 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * padata.c - generic interface to process data streams in parallel
  *
+ * See Documentation/padata.txt for an api documentation.
+ *
  * Copyright (C) 2008, 2009 secunet Security Networks AG
  * Copyright (C) 2008, 2009 Steffen Klassert <steffen.klassert@secunet.com>
  *
@@ -354,13 +356,13 @@ static int padata_setup_cpumasks(struct parallel_data *pd,
        if (!alloc_cpumask_var(&pd->cpumask.pcpu, GFP_KERNEL))
                return -ENOMEM;
 
-       cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_active_mask);
+       cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_online_mask);
        if (!alloc_cpumask_var(&pd->cpumask.cbcpu, GFP_KERNEL)) {
                free_cpumask_var(pd->cpumask.cbcpu);
                return -ENOMEM;
        }
 
-       cpumask_and(pd->cpumask.cbcpu, cbcpumask, cpu_active_mask);
+       cpumask_and(pd->cpumask.cbcpu, cbcpumask, cpu_online_mask);
        return 0;
 }
 
@@ -564,7 +566,7 @@ EXPORT_SYMBOL(padata_unregister_cpumask_notifier);
 static bool padata_validate_cpumask(struct padata_instance *pinst,
                                    const struct cpumask *cpumask)
 {
-       if (!cpumask_intersects(cpumask, cpu_active_mask)) {
+       if (!cpumask_intersects(cpumask, cpu_online_mask)) {
                pinst->flags |= PADATA_INVALID;
                return false;
        }
@@ -678,7 +680,7 @@ static int __padata_add_cpu(struct padata_instance *pinst, int cpu)
 {
        struct parallel_data *pd;
 
-       if (cpumask_test_cpu(cpu, cpu_active_mask)) {
+       if (cpumask_test_cpu(cpu, cpu_online_mask)) {
                pd = padata_alloc_pd(pinst, pinst->cpumask.pcpu,
                                     pinst->cpumask.cbcpu);
                if (!pd)
@@ -746,6 +748,9 @@ static int __padata_remove_cpu(struct padata_instance *pinst, int cpu)
                        return -ENOMEM;
 
                padata_replace(pinst, pd);
+
+               cpumask_clear_cpu(cpu, pd->cpumask.cbcpu);
+               cpumask_clear_cpu(cpu, pd->cpumask.pcpu);
        }
 
        return 0;
index 80aed44e345abc648f7ac3d0e7560a05e453c7fd..8ed89a175d79376600dfbfd777f06ed3c24665a5 100644 (file)
@@ -97,7 +97,7 @@ void panic(const char *fmt, ...)
        /*
         * Avoid nested stack-dumping if a panic occurs during oops processing
         */
-       if (!oops_in_progress)
+       if (!test_taint(TAINT_DIE) && oops_in_progress <= 1)
                dump_stack();
 #endif
 
index 0a186cfde7884e6b4f0f3d09e1b3d549e29dafb8..e09dfbfeecee43ca7fff59c327f213f9605ef0f4 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/async.h>
-#include <linux/kmod.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
@@ -611,14 +610,10 @@ int hibernate(void)
        if (error)
                goto Exit;
 
-       error = usermodehelper_disable();
-       if (error)
-               goto Exit;
-
        /* Allocate memory management structures */
        error = create_basic_memory_bitmaps();
        if (error)
-               goto Enable_umh;
+               goto Exit;
 
        printk(KERN_INFO "PM: Syncing filesystems ... ");
        sys_sync();
@@ -661,8 +656,6 @@ int hibernate(void)
 
  Free_bitmaps:
        free_basic_memory_bitmaps();
- Enable_umh:
-       usermodehelper_enable();
  Exit:
        pm_notifier_call_chain(PM_POST_HIBERNATION);
        pm_restore_console();
@@ -777,15 +770,9 @@ static int software_resume(void)
        if (error)
                goto close_finish;
 
-       error = usermodehelper_disable();
-       if (error)
-               goto close_finish;
-
        error = create_basic_memory_bitmaps();
-       if (error) {
-               usermodehelper_enable();
+       if (error)
                goto close_finish;
-       }
 
        pr_debug("PM: Preparing processes for restore.\n");
        error = freeze_processes();
@@ -806,7 +793,6 @@ static int software_resume(void)
        thaw_processes();
  Done:
        free_basic_memory_bitmaps();
-       usermodehelper_enable();
  Finish:
        pm_notifier_call_chain(PM_POST_RESTORE);
        pm_restore_console();
index 0d2aeb2261082f52d4ead619f352f03c03c35001..19db29f67558fef712764d78d7feccc0318ed650 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/kmod.h>
 
 /* 
  * Timeout for stopping processes
@@ -122,6 +123,10 @@ int freeze_processes(void)
 {
        int error;
 
+       error = __usermodehelper_disable(UMH_FREEZING);
+       if (error)
+               return error;
+
        if (!pm_freezing)
                atomic_inc(&system_freezing_cnt);
 
@@ -130,6 +135,7 @@ int freeze_processes(void)
        error = try_to_freeze_tasks(true);
        if (!error) {
                printk("done.");
+               __usermodehelper_set_disable_depth(UMH_DISABLED);
                oom_killer_disable();
        }
        printk("\n");
@@ -187,6 +193,8 @@ void thaw_processes(void)
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
 
+       usermodehelper_enable();
+
        schedule();
        printk("done.\n");
 }
index d6d6dbd1ecc09f673d987600981c549e5332ad50..6a031e684026f99507946c371544cbae34a35b48 100644 (file)
@@ -229,6 +229,21 @@ int pm_qos_request_active(struct pm_qos_request *req)
 }
 EXPORT_SYMBOL_GPL(pm_qos_request_active);
 
+/**
+ * pm_qos_work_fn - the timeout handler of pm_qos_update_request_timeout
+ * @work: work struct for the delayed work (timeout)
+ *
+ * This cancels the timeout request by falling back to the default at timeout.
+ */
+static void pm_qos_work_fn(struct work_struct *work)
+{
+       struct pm_qos_request *req = container_of(to_delayed_work(work),
+                                                 struct pm_qos_request,
+                                                 work);
+
+       pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE);
+}
+
 /**
  * pm_qos_add_request - inserts new qos request into the list
  * @req: pointer to a preallocated handle
@@ -253,6 +268,7 @@ void pm_qos_add_request(struct pm_qos_request *req,
                return;
        }
        req->pm_qos_class = pm_qos_class;
+       INIT_DELAYED_WORK(&req->work, pm_qos_work_fn);
        pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints,
                             &req->node, PM_QOS_ADD_REQ, value);
 }
@@ -279,6 +295,9 @@ void pm_qos_update_request(struct pm_qos_request *req,
                return;
        }
 
+       if (delayed_work_pending(&req->work))
+               cancel_delayed_work_sync(&req->work);
+
        if (new_value != req->node.prio)
                pm_qos_update_target(
                        pm_qos_array[req->pm_qos_class]->constraints,
@@ -286,6 +305,34 @@ void pm_qos_update_request(struct pm_qos_request *req,
 }
 EXPORT_SYMBOL_GPL(pm_qos_update_request);
 
+/**
+ * pm_qos_update_request_timeout - modifies an existing qos request temporarily.
+ * @req : handle to list element holding a pm_qos request to use
+ * @new_value: defines the temporal qos request
+ * @timeout_us: the effective duration of this qos request in usecs.
+ *
+ * After timeout_us, this qos request is cancelled automatically.
+ */
+void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value,
+                                  unsigned long timeout_us)
+{
+       if (!req)
+               return;
+       if (WARN(!pm_qos_request_active(req),
+                "%s called for unknown object.", __func__))
+               return;
+
+       if (delayed_work_pending(&req->work))
+               cancel_delayed_work_sync(&req->work);
+
+       if (new_value != req->node.prio)
+               pm_qos_update_target(
+                       pm_qos_array[req->pm_qos_class]->constraints,
+                       &req->node, PM_QOS_UPDATE_REQ, new_value);
+
+       schedule_delayed_work(&req->work, usecs_to_jiffies(timeout_us));
+}
+
 /**
  * pm_qos_remove_request - modifies an existing qos request
  * @req: handle to request list element
@@ -305,6 +352,9 @@ void pm_qos_remove_request(struct pm_qos_request *req)
                return;
        }
 
+       if (delayed_work_pending(&req->work))
+               cancel_delayed_work_sync(&req->work);
+
        pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints,
                             &req->node, PM_QOS_REMOVE_REQ,
                             PM_QOS_DEFAULT_VALUE);
index 88e5c967370d31e359cbd06f23914735c11f15b2..396d262b8fd01381a99de04d2d310be787b37565 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/kmod.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
@@ -102,17 +101,12 @@ static int suspend_prepare(void)
        if (error)
                goto Finish;
 
-       error = usermodehelper_disable();
-       if (error)
-               goto Finish;
-
        error = suspend_freeze_processes();
        if (!error)
                return 0;
 
        suspend_stats.failed_freeze++;
        dpm_save_failed_step(SUSPEND_FREEZE);
-       usermodehelper_enable();
  Finish:
        pm_notifier_call_chain(PM_POST_SUSPEND);
        pm_restore_console();
@@ -259,7 +253,6 @@ int suspend_devices_and_enter(suspend_state_t state)
 static void suspend_finish(void)
 {
        suspend_thaw_processes();
-       usermodehelper_enable();
        pm_notifier_call_chain(PM_POST_SUSPEND);
        pm_restore_console();
 }
index 8742fd013a94e3b56efdbf91cf27c709679615e4..eef311a58a649821f60532602a085f2a79b014bc 100644 (file)
 
 #define MAP_PAGE_ENTRIES       (PAGE_SIZE / sizeof(sector_t) - 1)
 
+/*
+ * Number of free pages that are not high.
+ */
+static inline unsigned long low_free_pages(void)
+{
+       return nr_free_pages() - nr_free_highpages();
+}
+
+/*
+ * Number of pages required to be kept free while writing the image. Always
+ * half of all available low pages before the writing starts.
+ */
+static inline unsigned long reqd_free_pages(void)
+{
+       return low_free_pages() / 2;
+}
+
 struct swap_map_page {
        sector_t entries[MAP_PAGE_ENTRIES];
        sector_t next_swap;
@@ -72,7 +89,7 @@ struct swap_map_handle {
        sector_t cur_swap;
        sector_t first_sector;
        unsigned int k;
-       unsigned long nr_free_pages, written;
+       unsigned long reqd_free_pages;
        u32 crc32;
 };
 
@@ -316,8 +333,7 @@ static int get_swap_writer(struct swap_map_handle *handle)
                goto err_rel;
        }
        handle->k = 0;
-       handle->nr_free_pages = nr_free_pages() >> 1;
-       handle->written = 0;
+       handle->reqd_free_pages = reqd_free_pages();
        handle->first_sector = handle->cur_swap;
        return 0;
 err_rel:
@@ -352,11 +368,11 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
                handle->cur_swap = offset;
                handle->k = 0;
        }
-       if (bio_chain && ++handle->written > handle->nr_free_pages) {
+       if (bio_chain && low_free_pages() <= handle->reqd_free_pages) {
                error = hib_wait_on_bio_chain(bio_chain);
                if (error)
                        goto out;
-               handle->written = 0;
+               handle->reqd_free_pages = reqd_free_pages();
        }
  out:
        return error;
@@ -618,7 +634,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
         * Adjust number of free pages after all allocations have been done.
         * We don't want to run out of pages when writing.
         */
-       handle->nr_free_pages = nr_free_pages() >> 1;
+       handle->reqd_free_pages = reqd_free_pages();
 
        /*
         * Start the CRC32 thread.
index 33c4329205af0e88da9e80ee98e9ff0e1259bf7d..91b0fd021a95d08eef106b3e0b86a41e3a135055 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/suspend.h>
 #include <linux/syscalls.h>
 #include <linux/reboot.h>
-#include <linux/kmod.h>
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/miscdevice.h>
@@ -222,14 +221,8 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                sys_sync();
                printk("done.\n");
 
-               error = usermodehelper_disable();
-               if (error)
-                       break;
-
                error = freeze_processes();
-               if (error)
-                       usermodehelper_enable();
-               else
+               if (!error)
                        data->frozen = 1;
                break;
 
@@ -238,7 +231,6 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                        break;
                pm_restore_gfp_mask();
                thaw_processes();
-               usermodehelper_enable();
                data->frozen = 0;
                break;
 
index 1050d6d3922c182f09bfe602ee07e3a185f4be80..d0c5baf1ab18a254753f2d3c2eb5ba2cf56202b6 100644 (file)
@@ -1820,7 +1820,6 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
         * a quiescent state betweentimes.
         */
        local_irq_save(flags);
-       WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
        rdp = this_cpu_ptr(rsp->rda);
 
        /* Add the callback to our list. */
index 4603b9d8f30a362d15dc60e4bd0cd659fd7c3f89..0533a688ce22fc378dc66a02e901132049ee8efd 100644 (file)
@@ -6405,16 +6405,26 @@ static void __sdt_free(const struct cpumask *cpu_map)
                struct sd_data *sdd = &tl->data;
 
                for_each_cpu(j, cpu_map) {
-                       struct sched_domain *sd = *per_cpu_ptr(sdd->sd, j);
-                       if (sd && (sd->flags & SD_OVERLAP))
-                               free_sched_groups(sd->groups, 0);
-                       kfree(*per_cpu_ptr(sdd->sd, j));
-                       kfree(*per_cpu_ptr(sdd->sg, j));
-                       kfree(*per_cpu_ptr(sdd->sgp, j));
+                       struct sched_domain *sd;
+
+                       if (sdd->sd) {
+                               sd = *per_cpu_ptr(sdd->sd, j);
+                               if (sd && (sd->flags & SD_OVERLAP))
+                                       free_sched_groups(sd->groups, 0);
+                               kfree(*per_cpu_ptr(sdd->sd, j));
+                       }
+
+                       if (sdd->sg)
+                               kfree(*per_cpu_ptr(sdd->sg, j));
+                       if (sdd->sgp)
+                               kfree(*per_cpu_ptr(sdd->sgp, j));
                }
                free_percpu(sdd->sd);
+               sdd->sd = NULL;
                free_percpu(sdd->sg);
+               sdd->sg = NULL;
                free_percpu(sdd->sgp);
+               sdd->sgp = NULL;
        }
 }
 
index 0d97ebdc58f078f821a59c29965509a5e47f02f5..e9553640c1c3b679b6ae80b6ff4446b05b486c4b 100644 (file)
@@ -784,7 +784,7 @@ account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
                update_load_add(&rq_of(cfs_rq)->load, se->load.weight);
 #ifdef CONFIG_SMP
        if (entity_is_task(se))
-               list_add_tail(&se->group_node, &rq_of(cfs_rq)->cfs_tasks);
+               list_add(&se->group_node, &rq_of(cfs_rq)->cfs_tasks);
 #endif
        cfs_rq->nr_running++;
 }
@@ -3215,6 +3215,8 @@ static int move_one_task(struct lb_env *env)
 
 static unsigned long task_h_load(struct task_struct *p);
 
+static const unsigned int sched_nr_migrate_break = 32;
+
 /*
  * move_tasks tries to move up to load_move weighted load from busiest to
  * this_rq, as part of a balancing operation within domain "sd".
@@ -3242,7 +3244,7 @@ static int move_tasks(struct lb_env *env)
 
                /* take a breather every nr_migrate tasks */
                if (env->loop > env->loop_break) {
-                       env->loop_break += sysctl_sched_nr_migrate;
+                       env->loop_break += sched_nr_migrate_break;
                        env->flags |= LBF_NEED_BREAK;
                        break;
                }
@@ -3252,7 +3254,7 @@ static int move_tasks(struct lb_env *env)
 
                load = task_h_load(p);
 
-               if (load < 16 && !env->sd->nr_balance_failed)
+               if (sched_feat(LB_MIN) && load < 16 && !env->sd->nr_balance_failed)
                        goto next;
 
                if ((load / 2) > env->load_move)
@@ -4407,7 +4409,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
                .dst_cpu        = this_cpu,
                .dst_rq         = this_rq,
                .idle           = idle,
-               .loop_break     = sysctl_sched_nr_migrate,
+               .loop_break     = sched_nr_migrate_break,
        };
 
        cpumask_copy(cpus, cpu_active_mask);
@@ -4445,10 +4447,10 @@ redo:
                 * correctly treated as an imbalance.
                 */
                env.flags |= LBF_ALL_PINNED;
-               env.load_move = imbalance;
-               env.src_cpu = busiest->cpu;
-               env.src_rq = busiest;
-               env.loop_max = busiest->nr_running;
+               env.load_move   = imbalance;
+               env.src_cpu     = busiest->cpu;
+               env.src_rq      = busiest;
+               env.loop_max    = min_t(unsigned long, sysctl_sched_nr_migrate, busiest->nr_running);
 
 more_balance:
                local_irq_save(flags);
index e61fd73913d0613d7fc66a3f8e7dec5c6a55b58b..de00a486c5c693ac7038fa3c5dd139e642a1c307 100644 (file)
@@ -68,3 +68,4 @@ SCHED_FEAT(TTWU_QUEUE, true)
 
 SCHED_FEAT(FORCE_SD_OVERLAP, false)
 SCHED_FEAT(RT_RUNTIME_SHARE, true)
+SCHED_FEAT(LB_MIN, false)
index 52b3a06a02f8406c4f78eb06cfaad89f51910a21..4ab11879aeb4d15baa3d8d25fa753725084ed809 100644 (file)
@@ -170,7 +170,7 @@ static int proc_taint(struct ctl_table *table, int write,
 #endif
 
 #ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
                                void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
@@ -703,7 +703,7 @@ static struct ctl_table kern_table[] = {
                .data           = &dmesg_restrict,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
+               .proc_handler   = proc_dointvec_minmax_sysadmin,
                .extra1         = &zero,
                .extra2         = &one,
        },
@@ -712,7 +712,7 @@ static struct ctl_table kern_table[] = {
                .data           = &kptr_restrict,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dmesg_restrict,
+               .proc_handler   = proc_dointvec_minmax_sysadmin,
                .extra1         = &zero,
                .extra2         = &two,
        },
@@ -1943,7 +1943,7 @@ static int proc_taint(struct ctl_table *table, int write,
 }
 
 #ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
                                void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        if (write && !capable(CAP_SYS_ADMIN))
index 2cf9cc7aa103bff9d40267eb862484ec3052e1de..a20dc8a3c9499e5631102ec869d67d6148c63ea6 100644 (file)
@@ -1,6 +1,10 @@
 #
 # Timer subsystem related configuration options
 #
+
+# Core internal switch. Selected by NO_HZ / HIGH_RES_TIMERS. This is
+# only related to the tick functionality. Oneshot clockevent devices
+# are supported independ of this.
 config TICK_ONESHOT
        bool
 
index e883f57a3cd39f33796f5a91856d30d5573f0543..f113755695e2351ad9f32b7e38a808e98c0ad5f4 100644 (file)
@@ -346,7 +346,8 @@ int tick_resume_broadcast(void)
                                                     tick_get_broadcast_mask());
                        break;
                case TICKDEV_MODE_ONESHOT:
-                       broadcast = tick_resume_broadcast_oneshot(bc);
+                       if (!cpumask_empty(tick_get_broadcast_mask()))
+                               broadcast = tick_resume_broadcast_oneshot(bc);
                        break;
                }
        }
@@ -373,6 +374,9 @@ static int tick_broadcast_set_event(ktime_t expires, int force)
 {
        struct clock_event_device *bc = tick_broadcast_device.evtdev;
 
+       if (bc->mode != CLOCK_EVT_MODE_ONESHOT)
+               clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+
        return clockevents_program_event(bc, expires, force);
 }
 
@@ -531,7 +535,6 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
                int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
 
                bc->event_handler = tick_handle_oneshot_broadcast;
-               clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
 
                /* Take the do_timer update */
                tick_do_timer_cpu = cpu;
@@ -549,6 +552,7 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
                           to_cpumask(tmpmask));
 
                if (was_periodic && !cpumask_empty(to_cpumask(tmpmask))) {
+                       clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
                        tick_broadcast_init_next_event(to_cpumask(tmpmask),
                                                       tick_next_period);
                        tick_broadcast_set_event(tick_next_period, 1);
@@ -575,15 +579,12 @@ void tick_broadcast_switch_to_oneshot(void)
        unsigned long flags;
 
        raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
-       if (cpumask_empty(tick_get_broadcast_mask()))
-               goto end;
 
        tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT;
        bc = tick_broadcast_device.evtdev;
        if (bc)
                tick_broadcast_setup_oneshot(bc);
 
-end:
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
index 3526038f28361b7e4241818cafb8a9a978310e0c..6a3a5b9ff56176c2951256edf7ef9601a0f49106 100644 (file)
@@ -534,9 +534,9 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
                                hrtimer_get_expires(&ts->sched_timer), 0))
                                break;
                }
-               /* Update jiffies and reread time */
-               tick_do_update_jiffies64(now);
+               /* Reread time and update jiffies */
                now = ktime_get();
+               tick_do_update_jiffies64(now);
        }
 }
 
index cdea7b56b0c94e54075d7982ed8967360f0e1ea7..c0bd0308741ca1a343a9cbc0b551b4a12438ddd7 100644 (file)
@@ -311,13 +311,6 @@ int blk_trace_remove(struct request_queue *q)
 }
 EXPORT_SYMBOL_GPL(blk_trace_remove);
 
-static int blk_dropped_open(struct inode *inode, struct file *filp)
-{
-       filp->private_data = inode->i_private;
-
-       return 0;
-}
-
 static ssize_t blk_dropped_read(struct file *filp, char __user *buffer,
                                size_t count, loff_t *ppos)
 {
@@ -331,18 +324,11 @@ static ssize_t blk_dropped_read(struct file *filp, char __user *buffer,
 
 static const struct file_operations blk_dropped_fops = {
        .owner =        THIS_MODULE,
-       .open =         blk_dropped_open,
+       .open =         simple_open,
        .read =         blk_dropped_read,
        .llseek =       default_llseek,
 };
 
-static int blk_msg_open(struct inode *inode, struct file *filp)
-{
-       filp->private_data = inode->i_private;
-
-       return 0;
-}
-
 static ssize_t blk_msg_write(struct file *filp, const char __user *buffer,
                                size_t count, loff_t *ppos)
 {
@@ -371,7 +357,7 @@ static ssize_t blk_msg_write(struct file *filp, const char __user *buffer,
 
 static const struct file_operations blk_msg_fops = {
        .owner =        THIS_MODULE,
-       .open =         blk_msg_open,
+       .open =         simple_open,
        .write =        blk_msg_write,
        .llseek =       noop_llseek,
 };
index ed7b5d1e12f468168178b1a3c144d9736e0b4614..2a22255c10101c7a55939955a04a9834bbbb940a 100644 (file)
@@ -4629,7 +4629,8 @@ static ssize_t
 rb_simple_read(struct file *filp, char __user *ubuf,
               size_t cnt, loff_t *ppos)
 {
-       struct ring_buffer *buffer = filp->private_data;
+       struct trace_array *tr = filp->private_data;
+       struct ring_buffer *buffer = tr->buffer;
        char buf[64];
        int r;
 
@@ -4647,7 +4648,8 @@ static ssize_t
 rb_simple_write(struct file *filp, const char __user *ubuf,
                size_t cnt, loff_t *ppos)
 {
-       struct ring_buffer *buffer = filp->private_data;
+       struct trace_array *tr = filp->private_data;
+       struct ring_buffer *buffer = tr->buffer;
        unsigned long val;
        int ret;
 
@@ -4734,7 +4736,7 @@ static __init int tracer_init_debugfs(void)
                          &trace_clock_fops);
 
        trace_create_file("tracing_on", 0644, d_tracer,
-                           global_trace.buffer, &rb_simple_fops);
+                           &global_trace, &rb_simple_fops);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
        trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
index 95059f091a242abcfd60bbe9169131e7870e4a2c..f95d65da6db8acaba3498616bbac09643d48ed47 100644 (file)
@@ -836,11 +836,11 @@ extern const char *__stop___trace_bprintk_fmt[];
                     filter)
 #include "trace_entries.h"
 
-#ifdef CONFIG_FUNCTION_TRACER
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_FUNCTION_TRACER)
 int perf_ftrace_event_register(struct ftrace_event_call *call,
                               enum trace_reg type, void *data);
 #else
 #define perf_ftrace_event_register NULL
-#endif /* CONFIG_FUNCTION_TRACER */
+#endif
 
 #endif /* _LINUX_KERNEL_TRACE_H */
index 859fae6b18253e9d31331222c138e318397ab0d1..df611a0e76c55b0d47febf4312874e839114bb13 100644 (file)
@@ -652,6 +652,8 @@ int trace_print_lat_context(struct trace_iterator *iter)
 {
        u64 next_ts;
        int ret;
+       /* trace_find_next_entry will reset ent_size */
+       int ent_size = iter->ent_size;
        struct trace_seq *s = &iter->seq;
        struct trace_entry *entry = iter->ent,
                           *next_entry = trace_find_next_entry(iter, NULL,
@@ -660,6 +662,9 @@ int trace_print_lat_context(struct trace_iterator *iter)
        unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start);
        unsigned long rel_usecs;
 
+       /* Restore the original ent_size */
+       iter->ent_size = ent_size;
+
        if (!next_entry)
                next_ts = iter->ts;
        rel_usecs = ns2usecs(next_ts - iter->ts);
index 21dee7c19afd8e9c493bec8585869f098545f4ff..aeefa8bc8b1c2dac1493703ff2f209ce894938f9 100644 (file)
@@ -192,14 +192,14 @@ static int kobject_add_internal(struct kobject *kobj)
 
                /* be noisy on error issues */
                if (error == -EEXIST)
-                       printk(KERN_ERR "%s failed for %s with "
-                              "-EEXIST, don't try to register things with "
-                              "the same name in the same directory.\n",
-                              __func__, kobject_name(kobj));
+                       WARN(1, "%s failed for %s with "
+                            "-EEXIST, don't try to register things with "
+                            "the same name in the same directory.\n",
+                            __func__, kobject_name(kobj));
                else
-                       printk(KERN_ERR "%s failed for %s (%d)\n",
-                              __func__, kobject_name(kobj), error);
-               dump_stack();
+                       WARN(1, "%s failed for %s (error: %d parent: %s)\n",
+                            __func__, kobject_name(kobj), error,
+                            parent ? kobject_name(parent) : "'none'");
        } else
                kobj->state_in_sysfs = 1;
 
index 2f526627e4f575c50468b51015270c35d2179721..0c505361da197a9a46c8b2665af7b5520ad11974 100644 (file)
@@ -177,8 +177,8 @@ int mpi_rshift(MPI x, MPI a, unsigned n)
  */
 int mpi_lshift_limbs(MPI a, unsigned int count)
 {
-       mpi_ptr_t ap = a->d;
-       int n = a->nlimbs;
+       const int n = a->nlimbs;
+       mpi_ptr_t ap;
        int i;
 
        if (!count || !n)
@@ -187,6 +187,7 @@ int mpi_lshift_limbs(MPI a, unsigned int count)
        if (RESIZE_IF_NEEDED(a, n + count) < 0)
                return -ENOMEM;
 
+       ap = a->d;
        for (i = n - 1; i >= 0; i--)
                ap[i + count] = ap[i];
        for (i = 0; i < count; i++)
index b8ce6f450956e6e3a9191cbf92afd1d490a32c9d..5a16423a512c4a7f0192d0f10af806473c25b0b9 100644 (file)
@@ -532,7 +532,7 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
                                struct vm_area_struct *vma,
                                unsigned long address, int avoid_reserve)
 {
-       struct page *page;
+       struct page *page = NULL;
        struct mempolicy *mpol;
        nodemask_t *nodemask;
        struct zonelist *zonelist;
@@ -2791,6 +2791,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
         * so no worry about deadlock.
         */
        page = pte_page(entry);
+       get_page(page);
        if (page != pagecache_page)
                lock_page(page);
 
@@ -2822,6 +2823,7 @@ out_page_table_lock:
        }
        if (page != pagecache_page)
                unlock_page(page);
+       put_page(page);
 
 out_mutex:
        mutex_unlock(&hugetlb_instantiation_mutex);
index 99f285599501482e8b48c77eb768a62981811cf6..a44eab3157f8dc4b25e686b643ccacbc8449e041 100644 (file)
@@ -330,6 +330,9 @@ static int __init_memblock memblock_add_region(struct memblock_type *type,
        phys_addr_t end = base + memblock_cap_size(base, &size);
        int i, nr_new;
 
+       if (!size)
+               return 0;
+
        /* special case for empty array */
        if (type->regions[0].size == 0) {
                WARN_ON(type->cnt != 1 || type->total_size);
@@ -430,6 +433,9 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,
 
        *start_rgn = *end_rgn = 0;
 
+       if (!size)
+               return 0;
+
        /* we'll create at most two more regions */
        while (type->cnt + 2 > type->max)
                if (memblock_double_array(type) < 0)
@@ -514,7 +520,6 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
                     (unsigned long long)base,
                     (unsigned long long)base + size,
                     (void *)_RET_IP_);
-       BUG_ON(0 == size);
 
        return memblock_add_region(_rgn, base, size, MAX_NUMNODES);
 }
index 7d698df4a067ce591fd661f45e098610e1a027db..31ab9c3f0178d3f7193d5e2b6e6935926cf1d48d 100644 (file)
@@ -2165,7 +2165,7 @@ static int __cpuinit memcg_cpu_hotplug_callback(struct notifier_block *nb,
        if (action == CPU_ONLINE)
                return NOTIFY_OK;
 
-       if ((action != CPU_DEAD) || action != CPU_DEAD_FROZEN)
+       if (action != CPU_DEAD && action != CPU_DEAD_FROZEN)
                return NOTIFY_OK;
 
        for_each_mem_cgroup(iter)
@@ -2476,10 +2476,10 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
 static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
                                       struct page *page,
                                       unsigned int nr_pages,
-                                      struct page_cgroup *pc,
                                       enum charge_type ctype,
                                       bool lrucare)
 {
+       struct page_cgroup *pc = lookup_page_cgroup(page);
        struct zone *uninitialized_var(zone);
        bool was_on_lru = false;
        bool anon;
@@ -2716,7 +2716,6 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
 {
        struct mem_cgroup *memcg = NULL;
        unsigned int nr_pages = 1;
-       struct page_cgroup *pc;
        bool oom = true;
        int ret;
 
@@ -2730,11 +2729,10 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
                oom = false;
        }
 
-       pc = lookup_page_cgroup(page);
        ret = __mem_cgroup_try_charge(mm, gfp_mask, nr_pages, &memcg, oom);
        if (ret == -ENOMEM)
                return ret;
-       __mem_cgroup_commit_charge(memcg, page, nr_pages, pc, ctype, false);
+       __mem_cgroup_commit_charge(memcg, page, nr_pages, ctype, false);
        return 0;
 }
 
@@ -2831,16 +2829,13 @@ static void
 __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg,
                                        enum charge_type ctype)
 {
-       struct page_cgroup *pc;
-
        if (mem_cgroup_disabled())
                return;
        if (!memcg)
                return;
        cgroup_exclude_rmdir(&memcg->css);
 
-       pc = lookup_page_cgroup(page);
-       __mem_cgroup_commit_charge(memcg, page, 1, pc, ctype, true);
+       __mem_cgroup_commit_charge(memcg, page, 1, ctype, true);
        /*
         * Now swap is on-memory. This means this page may be
         * counted both as mem and swap....double count.
@@ -3298,14 +3293,13 @@ int mem_cgroup_prepare_migration(struct page *page,
         * page. In the case new page is migrated but not remapped, new page's
         * mapcount will be finally 0 and we call uncharge in end_migration().
         */
-       pc = lookup_page_cgroup(newpage);
        if (PageAnon(page))
                ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED;
        else if (page_is_file_cache(page))
                ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
        else
                ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
-       __mem_cgroup_commit_charge(memcg, newpage, 1, pc, ctype, false);
+       __mem_cgroup_commit_charge(memcg, newpage, 1, ctype, false);
        return ret;
 }
 
@@ -3392,7 +3386,7 @@ void mem_cgroup_replace_page_cache(struct page *oldpage,
         * the newpage may be on LRU(or pagevec for LRU) already. We lock
         * LRU while we overwrite pc->mem_cgroup.
         */
-       __mem_cgroup_commit_charge(memcg, newpage, 1, pc, type, true);
+       __mem_cgroup_commit_charge(memcg, newpage, 1, type, true);
 }
 
 #ifdef CONFIG_DEBUG_VM
@@ -3763,7 +3757,7 @@ move_account:
                        goto try_to_free;
                cond_resched();
        /* "ret" should also be checked to ensure all lists are empty. */
-       } while (memcg->res.usage > 0 || ret);
+       } while (res_counter_read_u64(&memcg->res, RES_USAGE) > 0 || ret);
 out:
        css_put(&memcg->css);
        return ret;
@@ -3778,7 +3772,7 @@ try_to_free:
        lru_add_drain_all();
        /* try to free all pages in this cgroup */
        shrink = 1;
-       while (nr_retries && memcg->res.usage > 0) {
+       while (nr_retries && res_counter_read_u64(&memcg->res, RES_USAGE) > 0) {
                int progress;
 
                if (signal_pending(current)) {
index cfb6c8678754fdb3baf411e2331e87ea64766fb2..b19569137529221163e6b51bd96e3a161805a97f 100644 (file)
@@ -1361,11 +1361,14 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
 
        mm = get_task_mm(task);
        put_task_struct(task);
-       if (mm)
-               err = do_migrate_pages(mm, old, new,
-                       capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);
-       else
+
+       if (!mm) {
                err = -EINVAL;
+               goto out;
+       }
+
+       err = do_migrate_pages(mm, old, new,
+               capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);
 
        mmput(mm);
 out:
index 51c08a0c6f68ac6e78d09568bd270ad95aac7622..11072383ae12e5698498be5b3da5b8d991192535 100644 (file)
@@ -1388,14 +1388,14 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages,
        mm = get_task_mm(task);
        put_task_struct(task);
 
-       if (mm) {
-               if (nodes)
-                       err = do_pages_move(mm, task_nodes, nr_pages, pages,
-                                           nodes, status, flags);
-               else
-                       err = do_pages_stat(mm, nr_pages, pages, status);
-       else
-               err = -EINVAL;
+       if (!mm)
+               return -EINVAL;
+
+       if (nodes)
+               err = do_pages_move(mm, task_nodes, nr_pages, pages,
+                                   nodes, status, flags);
+       else
+               err = do_pages_stat(mm, nr_pages, pages, status);
 
        mmput(mm);
        return err;
index a7bf6a31c9f62be11cb8e5819322565b7cf2c266..848ef52d96031f5061bc86582aa0120ccd0394e8 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -240,6 +240,8 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
        return next;
 }
 
+static unsigned long do_brk(unsigned long addr, unsigned long len);
+
 SYSCALL_DEFINE1(brk, unsigned long, brk)
 {
        unsigned long rlim, retval;
@@ -951,7 +953,7 @@ static inline unsigned long round_hint_to_min(unsigned long hint)
  * The caller must hold down_write(&current->mm->mmap_sem).
  */
 
-unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
+static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
                        unsigned long len, unsigned long prot,
                        unsigned long flags, unsigned long pgoff)
 {
@@ -1087,7 +1089,32 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 
        return mmap_region(file, addr, len, flags, vm_flags, pgoff);
 }
-EXPORT_SYMBOL(do_mmap_pgoff);
+
+unsigned long do_mmap(struct file *file, unsigned long addr,
+       unsigned long len, unsigned long prot,
+       unsigned long flag, unsigned long offset)
+{
+       if (unlikely(offset + PAGE_ALIGN(len) < offset))
+               return -EINVAL;
+       if (unlikely(offset & ~PAGE_MASK))
+               return -EINVAL;
+       return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
+}
+EXPORT_SYMBOL(do_mmap);
+
+unsigned long vm_mmap(struct file *file, unsigned long addr,
+       unsigned long len, unsigned long prot,
+       unsigned long flag, unsigned long offset)
+{
+       unsigned long ret;
+       struct mm_struct *mm = current->mm;
+
+       down_write(&mm->mmap_sem);
+       ret = do_mmap(file, addr, len, prot, flag, offset);
+       up_write(&mm->mmap_sem);
+       return ret;
+}
+EXPORT_SYMBOL(vm_mmap);
 
 SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
                unsigned long, prot, unsigned long, flags,
@@ -2105,21 +2132,25 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
 
        return 0;
 }
-
 EXPORT_SYMBOL(do_munmap);
 
-SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+int vm_munmap(unsigned long start, size_t len)
 {
        int ret;
        struct mm_struct *mm = current->mm;
 
-       profile_munmap(addr);
-
        down_write(&mm->mmap_sem);
-       ret = do_munmap(mm, addr, len);
+       ret = do_munmap(mm, start, len);
        up_write(&mm->mmap_sem);
        return ret;
 }
+EXPORT_SYMBOL(vm_munmap);
+
+SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+{
+       profile_munmap(addr);
+       return vm_munmap(addr, len);
+}
 
 static inline void verify_mm_writelocked(struct mm_struct *mm)
 {
@@ -2136,7 +2167,7 @@ static inline void verify_mm_writelocked(struct mm_struct *mm)
  *  anonymous maps.  eventually we may be able to do some
  *  brk-specific accounting here.
  */
-unsigned long do_brk(unsigned long addr, unsigned long len)
+static unsigned long do_brk(unsigned long addr, unsigned long len)
 {
        struct mm_struct * mm = current->mm;
        struct vm_area_struct * vma, * prev;
@@ -2232,7 +2263,17 @@ out:
        return addr;
 }
 
-EXPORT_SYMBOL(do_brk);
+unsigned long vm_brk(unsigned long addr, unsigned long len)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long ret;
+
+       down_write(&mm->mmap_sem);
+       ret = do_brk(addr, len);
+       up_write(&mm->mmap_sem);
+       return ret;
+}
+EXPORT_SYMBOL(vm_brk);
 
 /* Release all mmaps. */
 void exit_mmap(struct mm_struct *mm)
index 24f0fc1a56d60ebbbacf1950ac0ebec7067dbf41..e53bb8a256b196018c26899427897a0f471d8193 100644 (file)
@@ -298,13 +298,19 @@ void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
        if (WARN_ON_ONCE(slab_is_available()))
                return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
 
+again:
        ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
                                         goal, -1ULL);
        if (ptr)
                return ptr;
 
-       return __alloc_memory_core_early(MAX_NUMNODES, size, align,
-                                        goal, -1ULL);
+       ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align,
+                                       goal, -1ULL);
+       if (!ptr && goal) {
+               goal = 0;
+               goto again;
+       }
+       return ptr;
 }
 
 void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
index f59e170fceb4e01046a339d8878f5030dea8a4f9..bb8f4f004a82ce57abb0653a9a8ed72d533f5c45 100644 (file)
@@ -1233,7 +1233,7 @@ enomem:
 /*
  * handle mapping creation for uClinux
  */
-unsigned long do_mmap_pgoff(struct file *file,
+static unsigned long do_mmap_pgoff(struct file *file,
                            unsigned long addr,
                            unsigned long len,
                            unsigned long prot,
@@ -1470,7 +1470,32 @@ error_getting_region:
        show_free_areas(0);
        return -ENOMEM;
 }
-EXPORT_SYMBOL(do_mmap_pgoff);
+
+unsigned long do_mmap(struct file *file, unsigned long addr,
+       unsigned long len, unsigned long prot,
+       unsigned long flag, unsigned long offset)
+{
+       if (unlikely(offset + PAGE_ALIGN(len) < offset))
+               return -EINVAL;
+       if (unlikely(offset & ~PAGE_MASK))
+               return -EINVAL;
+       return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
+}
+EXPORT_SYMBOL(do_mmap);
+
+unsigned long vm_mmap(struct file *file, unsigned long addr,
+       unsigned long len, unsigned long prot,
+       unsigned long flag, unsigned long offset)
+{
+       unsigned long ret;
+       struct mm_struct *mm = current->mm;
+
+       down_write(&mm->mmap_sem);
+       ret = do_mmap(file, addr, len, prot, flag, offset);
+       up_write(&mm->mmap_sem);
+       return ret;
+}
+EXPORT_SYMBOL(vm_mmap);
 
 SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
                unsigned long, prot, unsigned long, flags,
@@ -1709,16 +1734,22 @@ erase_whole_vma:
 }
 EXPORT_SYMBOL(do_munmap);
 
-SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+int vm_munmap(unsigned long addr, size_t len)
 {
-       int ret;
        struct mm_struct *mm = current->mm;
+       int ret;
 
        down_write(&mm->mmap_sem);
        ret = do_munmap(mm, addr, len);
        up_write(&mm->mmap_sem);
        return ret;
 }
+EXPORT_SYMBOL(vm_munmap);
+
+SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+{
+       return vm_munmap(addr, len);
+}
 
 /*
  * release all the mappings made in a process's VM space
@@ -1744,7 +1775,7 @@ void exit_mmap(struct mm_struct *mm)
        kleave("");
 }
 
-unsigned long do_brk(unsigned long addr, unsigned long len)
+unsigned long vm_brk(unsigned long addr, unsigned long len)
 {
        return -ENOMEM;
 }
index 9d3dd3763cf763460b0f4f17b7ff630e5c8115c0..4c5ff7f284d9b299d7ea9cf3b7bfe374550ce5ca 100644 (file)
@@ -26,7 +26,7 @@
  */
 static const struct address_space_operations swap_aops = {
        .writepage      = swap_writepage,
-       .set_page_dirty = __set_page_dirty_nobuffers,
+       .set_page_dirty = __set_page_dirty_no_writeback,
        .migratepage    = migrate_page,
 };
 
index 33c332bbab738231105cc7c3cfacf80e5297ed6e..33dc256033b5020c3679a4578af854c640fc826a 100644 (file)
@@ -1568,9 +1568,14 @@ shrink_inactive_list(unsigned long nr_to_scan, struct mem_cgroup_zone *mz,
        reclaim_stat->recent_scanned[0] += nr_anon;
        reclaim_stat->recent_scanned[1] += nr_file;
 
-       if (current_is_kswapd())
-               __count_vm_events(KSWAPD_STEAL, nr_reclaimed);
-       __count_zone_vm_events(PGSTEAL, zone, nr_reclaimed);
+       if (global_reclaim(sc)) {
+               if (current_is_kswapd())
+                       __count_zone_vm_events(PGSTEAL_KSWAPD, zone,
+                                              nr_reclaimed);
+               else
+                       __count_zone_vm_events(PGSTEAL_DIRECT, zone,
+                                              nr_reclaimed);
+       }
 
        putback_inactive_pages(mz, &page_list);
 
@@ -2107,12 +2112,7 @@ restart:
                 * with multiple processes reclaiming pages, the total
                 * freeing target can get unreasonably large.
                 */
-               if (nr_reclaimed >= nr_to_reclaim)
-                       nr_to_reclaim = 0;
-               else
-                       nr_to_reclaim -= nr_reclaimed;
-
-               if (!nr_to_reclaim && priority < DEF_PRIORITY)
+               if (nr_reclaimed >= nr_to_reclaim && priority < DEF_PRIORITY)
                        break;
        }
        blk_finish_plug(&plug);
index f600557a76596231ef659fdff0c9f2ea8aed71ae..7db1b9bab4929d13b3b23dbe7b08c2c782e66ab1 100644 (file)
@@ -738,7 +738,8 @@ const char * const vmstat_text[] = {
        "pgmajfault",
 
        TEXTS_FOR_ZONES("pgrefill")
-       TEXTS_FOR_ZONES("pgsteal")
+       TEXTS_FOR_ZONES("pgsteal_kswapd")
+       TEXTS_FOR_ZONES("pgsteal_direct")
        TEXTS_FOR_ZONES("pgscan_kswapd")
        TEXTS_FOR_ZONES("pgscan_direct")
 
@@ -747,7 +748,6 @@ const char * const vmstat_text[] = {
 #endif
        "pginodesteal",
        "slabs_scanned",
-       "kswapd_steal",
        "kswapd_inodesteal",
        "kswapd_low_wmark_hit_quickly",
        "kswapd_high_wmark_hit_quickly",
index 8e21b6db3981cc93cb5e4e00e30b820c9ff97af1..a5c2248304397ae3d738eba7435d7dfaeb555976 100644 (file)
@@ -167,7 +167,8 @@ static struct garp_attr *garp_attr_lookup(const struct garp_applicant *app,
        return NULL;
 }
 
-static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new)
+static struct garp_attr *garp_attr_create(struct garp_applicant *app,
+                                         const void *data, u8 len, u8 type)
 {
        struct rb_node *parent = NULL, **p = &app->gid.rb_node;
        struct garp_attr *attr;
@@ -176,21 +177,16 @@ static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new)
        while (*p) {
                parent = *p;
                attr = rb_entry(parent, struct garp_attr, node);
-               d = garp_attr_cmp(attr, new->data, new->dlen, new->type);
+               d = garp_attr_cmp(attr, data, len, type);
                if (d < 0)
                        p = &parent->rb_left;
                else if (d > 0)
                        p = &parent->rb_right;
+               else {
+                       /* The attribute already exists; re-use it. */
+                       return attr;
+               }
        }
-       rb_link_node(&new->node, parent, p);
-       rb_insert_color(&new->node, &app->gid);
-}
-
-static struct garp_attr *garp_attr_create(struct garp_applicant *app,
-                                         const void *data, u8 len, u8 type)
-{
-       struct garp_attr *attr;
-
        attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
        if (!attr)
                return attr;
@@ -198,7 +194,9 @@ static struct garp_attr *garp_attr_create(struct garp_applicant *app,
        attr->type  = type;
        attr->dlen  = len;
        memcpy(attr->data, data, len);
-       garp_attr_insert(app, attr);
+
+       rb_link_node(&attr->node, parent, p);
+       rb_insert_color(&attr->node, &app->gid);
        return attr;
 }
 
index 0906c194a4139b1cf56e368876c7ba463e911c5b..9d9a6a3edbd58584fdceffdf680de6e28dc72c90 100644 (file)
@@ -2011,16 +2011,17 @@ static void __exit ax25_exit(void)
        proc_net_remove(&init_net, "ax25_route");
        proc_net_remove(&init_net, "ax25");
        proc_net_remove(&init_net, "ax25_calls");
-       ax25_rt_free();
-       ax25_uid_free();
-       ax25_dev_free();
 
-       ax25_unregister_sysctl();
        unregister_netdevice_notifier(&ax25_dev_notifier);
+       ax25_unregister_sysctl();
 
        dev_remove_pack(&ax25_packet_type);
 
        sock_unregister(PF_AX25);
        proto_unregister(&ax25_proto);
+
+       ax25_rt_free();
+       ax25_uid_free();
+       ax25_dev_free();
 }
 module_exit(ax25_exit);
index e33af63a884a476e689af34a3a56003d2f485f2f..edfd61addceca4b269891734646fedbe6fbe8606 100644 (file)
@@ -665,6 +665,11 @@ int hci_dev_open(__u16 dev)
 
        hci_req_lock(hdev);
 
+       if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
+               ret = -ENODEV;
+               goto done;
+       }
+
        if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
                ret = -ERFKILL;
                goto done;
@@ -1210,40 +1215,40 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
        return NULL;
 }
 
-static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
+static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
                                                u8 key_type, u8 old_key_type)
 {
        /* Legacy key */
        if (key_type < 0x03)
-               return 1;
+               return true;
 
        /* Debug keys are insecure so don't store them persistently */
        if (key_type == HCI_LK_DEBUG_COMBINATION)
-               return 0;
+               return false;
 
        /* Changed combination key and there's no previous one */
        if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
-               return 0;
+               return false;
 
        /* Security mode 3 case */
        if (!conn)
-               return 1;
+               return true;
 
        /* Neither local nor remote side had no-bonding as requirement */
        if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
-               return 1;
+               return true;
 
        /* Local side had dedicated bonding as requirement */
        if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
-               return 1;
+               return true;
 
        /* Remote side had dedicated bonding as requirement */
        if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
-               return 1;
+               return true;
 
        /* If none of the above criteria match, then don't store the key
         * persistently */
-       return 0;
+       return false;
 }
 
 struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
@@ -1280,7 +1285,8 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
                     bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
 {
        struct link_key *key, *old_key;
-       u8 old_key_type, persistent;
+       u8 old_key_type;
+       bool persistent;
 
        old_key = hci_find_link_key(hdev, bdaddr);
        if (old_key) {
@@ -1323,10 +1329,8 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
 
        mgmt_new_link_key(hdev, key, persistent);
 
-       if (!persistent) {
-               list_del(&key->list);
-               kfree(key);
-       }
+       if (conn)
+               conn->flush_key = !persistent;
 
        return 0;
 }
@@ -1849,6 +1853,8 @@ void hci_unregister_dev(struct hci_dev *hdev)
 
        BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
 
+       set_bit(HCI_UNREGISTER, &hdev->dev_flags);
+
        write_lock(&hci_dev_list_lock);
        list_del(&hdev->list);
        write_unlock(&hci_dev_list_lock);
index b37531094c4999a6b9224056e4d5f283a9bdcece..6c065254afc03dcfbd11bad037791561b7f99f45 100644 (file)
@@ -1901,6 +1901,8 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
        }
 
        if (ev->status == 0) {
+               if (conn->type == ACL_LINK && conn->flush_key)
+                       hci_remove_link_key(hdev, &conn->dst);
                hci_proto_disconn_cfm(conn, ev->reason);
                hci_conn_del(conn);
        }
@@ -2311,6 +2313,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 
        case HCI_OP_USER_PASSKEY_NEG_REPLY:
                hci_cc_user_passkey_neg_reply(hdev, skb);
+               break;
 
        case HCI_OP_LE_SET_SCAN_PARAM:
                hci_cc_le_set_scan_param(hdev, skb);
index b8e17e4dac8b4179d9ac82ad916baf28ed333662..94552b33d528447eea4b604b996c7d90ba0ab036 100644 (file)
@@ -1308,6 +1308,7 @@ static void l2cap_monitor_timeout(struct work_struct *work)
        if (chan->retry_count >= chan->remote_max_tx) {
                l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
                l2cap_chan_unlock(chan);
+               l2cap_chan_put(chan);
                return;
        }
 
@@ -1316,6 +1317,7 @@ static void l2cap_monitor_timeout(struct work_struct *work)
 
        l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
        l2cap_chan_unlock(chan);
+       l2cap_chan_put(chan);
 }
 
 static void l2cap_retrans_timeout(struct work_struct *work)
@@ -1335,6 +1337,7 @@ static void l2cap_retrans_timeout(struct work_struct *work)
        l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
 
        l2cap_chan_unlock(chan);
+       l2cap_chan_put(chan);
 }
 
 static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
index c4fe583b0af65f0a2bccfa9b3ee6e9d459f1c245..29122ed28ea96965433fb6086756244d9eabd508 100644 (file)
@@ -82,7 +82,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
        }
 
        if (la.l2_cid)
-               err = l2cap_add_scid(chan, la.l2_cid);
+               err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid));
        else
                err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm);
 
@@ -123,7 +123,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
        if (la.l2_cid && la.l2_psm)
                return -EINVAL;
 
-       err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr);
+       err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
+                               &la.l2_bdaddr);
        if (err)
                return err;
 
index 7fcff888713171cb760296726fdcfca19f72aaca..4bb03b111122ca6c911ee1c7e74fbd8c03f22d30 100644 (file)
@@ -2523,13 +2523,18 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
 
        if (cp->val) {
                type = PAGE_SCAN_TYPE_INTERLACED;
-               acp.interval = 0x0024;  /* 22.5 msec page scan interval */
+
+               /* 22.5 msec page scan interval */
+               acp.interval = __constant_cpu_to_le16(0x0024);
        } else {
                type = PAGE_SCAN_TYPE_STANDARD; /* default */
-               acp.interval = 0x0800;  /* default 1.28 sec page scan */
+
+               /* default 1.28 sec page scan */
+               acp.interval = __constant_cpu_to_le16(0x0800);
        }
 
-       acp.window = 0x0012;    /* default 11.25 msec page scan window */
+       /* default 11.25 msec page scan window */
+       acp.window = __constant_cpu_to_le16(0x0012);
 
        err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp),
                           &acp);
@@ -2879,7 +2884,7 @@ int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
        return 0;
 }
 
-int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, u8 persistent)
+int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, bool persistent)
 {
        struct mgmt_ev_new_link_key ev;
 
@@ -2936,7 +2941,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
                                          name, name_len);
 
        if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
-               eir_len = eir_append_data(&ev->eir[eir_len], eir_len,
+               eir_len = eir_append_data(ev->eir, eir_len,
                                          EIR_CLASS_OF_DEV, dev_class, 3);
 
        put_unaligned_le16(eir_len, &ev->eir_len);
index 61f65344e711fc4b87856889c8d83e89d0d911d6..a2098e3de500d4ab34c3d3b14435eddb5089b354 100644 (file)
@@ -47,6 +47,7 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
                kfree_skb(skb);
        } else {
                skb_push(skb, ETH_HLEN);
+               br_drop_fake_rtable(skb);
                dev_queue_xmit(skb);
        }
 
index 702a1ae9220b79bd9e60cc25732201fe8750dcd2..27ca25ed70216979790ffd6c555baaf88bf4e7a4 100644 (file)
@@ -241,7 +241,6 @@ static void br_multicast_group_expired(unsigned long data)
        hlist_del_rcu(&mp->hlist[mdb->ver]);
        mdb->size--;
 
-       del_timer(&mp->query_timer);
        call_rcu_bh(&mp->rcu, br_multicast_free_group);
 
 out:
@@ -271,7 +270,6 @@ static void br_multicast_del_pg(struct net_bridge *br,
                rcu_assign_pointer(*pp, p->next);
                hlist_del_init(&p->mglist);
                del_timer(&p->timer);
-               del_timer(&p->query_timer);
                call_rcu_bh(&p->rcu, br_multicast_free_pg);
 
                if (!mp->ports && !mp->mglist &&
@@ -507,74 +505,6 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
        return NULL;
 }
 
-static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp)
-{
-       struct net_bridge *br = mp->br;
-       struct sk_buff *skb;
-
-       skb = br_multicast_alloc_query(br, &mp->addr);
-       if (!skb)
-               goto timer;
-
-       netif_rx(skb);
-
-timer:
-       if (++mp->queries_sent < br->multicast_last_member_count)
-               mod_timer(&mp->query_timer,
-                         jiffies + br->multicast_last_member_interval);
-}
-
-static void br_multicast_group_query_expired(unsigned long data)
-{
-       struct net_bridge_mdb_entry *mp = (void *)data;
-       struct net_bridge *br = mp->br;
-
-       spin_lock(&br->multicast_lock);
-       if (!netif_running(br->dev) || !mp->mglist ||
-           mp->queries_sent >= br->multicast_last_member_count)
-               goto out;
-
-       br_multicast_send_group_query(mp);
-
-out:
-       spin_unlock(&br->multicast_lock);
-}
-
-static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg)
-{
-       struct net_bridge_port *port = pg->port;
-       struct net_bridge *br = port->br;
-       struct sk_buff *skb;
-
-       skb = br_multicast_alloc_query(br, &pg->addr);
-       if (!skb)
-               goto timer;
-
-       br_deliver(port, skb);
-
-timer:
-       if (++pg->queries_sent < br->multicast_last_member_count)
-               mod_timer(&pg->query_timer,
-                         jiffies + br->multicast_last_member_interval);
-}
-
-static void br_multicast_port_group_query_expired(unsigned long data)
-{
-       struct net_bridge_port_group *pg = (void *)data;
-       struct net_bridge_port *port = pg->port;
-       struct net_bridge *br = port->br;
-
-       spin_lock(&br->multicast_lock);
-       if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) ||
-           pg->queries_sent >= br->multicast_last_member_count)
-               goto out;
-
-       br_multicast_send_port_group_query(pg);
-
-out:
-       spin_unlock(&br->multicast_lock);
-}
-
 static struct net_bridge_mdb_entry *br_multicast_get_group(
        struct net_bridge *br, struct net_bridge_port *port,
        struct br_ip *group, int hash)
@@ -690,8 +620,6 @@ rehash:
        mp->addr = *group;
        setup_timer(&mp->timer, br_multicast_group_expired,
                    (unsigned long)mp);
-       setup_timer(&mp->query_timer, br_multicast_group_query_expired,
-                   (unsigned long)mp);
 
        hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);
        mdb->size++;
@@ -746,8 +674,6 @@ static int br_multicast_add_group(struct net_bridge *br,
        hlist_add_head(&p->mglist, &port->mglist);
        setup_timer(&p->timer, br_multicast_port_group_expired,
                    (unsigned long)p);
-       setup_timer(&p->query_timer, br_multicast_port_group_query_expired,
-                   (unsigned long)p);
 
        rcu_assign_pointer(*pp, p);
 
@@ -1291,9 +1217,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
                     time_after(mp->timer.expires, time) :
                     try_to_del_timer_sync(&mp->timer) >= 0)) {
                        mod_timer(&mp->timer, time);
-
-                       mp->queries_sent = 0;
-                       mod_timer(&mp->query_timer, now);
                }
 
                goto out;
@@ -1310,9 +1233,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
                     time_after(p->timer.expires, time) :
                     try_to_del_timer_sync(&p->timer) >= 0)) {
                        mod_timer(&p->timer, time);
-
-                       p->queries_sent = 0;
-                       mod_timer(&p->query_timer, now);
                }
 
                break;
@@ -1681,7 +1601,6 @@ void br_multicast_stop(struct net_bridge *br)
                hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i],
                                          hlist[ver]) {
                        del_timer(&mp->timer);
-                       del_timer(&mp->query_timer);
                        call_rcu_bh(&mp->rcu, br_multicast_free_group);
                }
        }
index dec4f3817133c879b524a65f0919b5dabcff46ea..d7f49b63ab0fd17b82828f60278b5f8a99664a1d 100644 (file)
@@ -156,7 +156,7 @@ void br_netfilter_rtable_init(struct net_bridge *br)
        rt->dst.dev = br->dev;
        rt->dst.path = &rt->dst;
        dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
-       rt->dst.flags   = DST_NOXFRM | DST_NOPEER;
+       rt->dst.flags   = DST_NOXFRM | DST_NOPEER | DST_FAKE_RTABLE;
        rt->dst.ops = &fake_dst_ops;
 }
 
@@ -694,11 +694,7 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb,
                                   const struct net_device *out,
                                   int (*okfn)(struct sk_buff *))
 {
-       struct rtable *rt = skb_rtable(skb);
-
-       if (rt && rt == bridge_parent_rtable(in))
-               skb_dst_drop(skb);
-
+       br_drop_fake_rtable(skb);
        return NF_ACCEPT;
 }
 
index 0b67a63ad7a870e550c9d23d03ed7eb52ef854bf..e1d882257877374e21c7a314740a7ee7f76f4ccc 100644 (file)
@@ -82,9 +82,7 @@ struct net_bridge_port_group {
        struct hlist_node               mglist;
        struct rcu_head                 rcu;
        struct timer_list               timer;
-       struct timer_list               query_timer;
        struct br_ip                    addr;
-       u32                             queries_sent;
 };
 
 struct net_bridge_mdb_entry
@@ -94,10 +92,8 @@ struct net_bridge_mdb_entry
        struct net_bridge_port_group __rcu *ports;
        struct rcu_head                 rcu;
        struct timer_list               timer;
-       struct timer_list               query_timer;
        struct br_ip                    addr;
        bool                            mglist;
-       u32                             queries_sent;
 };
 
 struct net_bridge_mdb_htable
index 20618dd3088b79e0f1528436c7b1c9359f9c9cd6..d09340e1523f64d0aa1f7ba71cf0d0626c22036a 100644 (file)
@@ -103,6 +103,7 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
                skb->protocol = htons(ETH_P_IPV6);
                break;
        default:
+               kfree_skb(skb);
                priv->netdev->stats.rx_errors++;
                return -EINVAL;
        }
@@ -220,14 +221,16 @@ static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (skb->len > priv->netdev->mtu) {
                pr_warn("Size of skb exceeded MTU\n");
+               kfree_skb(skb);
                dev->stats.tx_errors++;
-               return -ENOSPC;
+               return NETDEV_TX_OK;
        }
 
        if (!priv->flowenabled) {
                pr_debug("dropping packets flow off\n");
+               kfree_skb(skb);
                dev->stats.tx_dropped++;
-               return NETDEV_TX_BUSY;
+               return NETDEV_TX_OK;
        }
 
        if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP)
@@ -242,7 +245,7 @@ static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
        result = priv->chnl.dn->transmit(priv->chnl.dn, pkt);
        if (result) {
                dev->stats.tx_dropped++;
-               return result;
+               return NETDEV_TX_OK;
        }
 
        /* Update statistics. */
index 5d59155adf2a27a8f54b7cbe09210dedf22efb6e..9bb8f87c4cdad35481e6fc2389090d32a6d5b917 100644 (file)
@@ -1409,14 +1409,34 @@ EXPORT_SYMBOL(register_netdevice_notifier);
  *     register_netdevice_notifier(). The notifier is unlinked into the
  *     kernel structures and may then be reused. A negative errno code
  *     is returned on a failure.
+ *
+ *     After unregistering unregister and down device events are synthesized
+ *     for all devices on the device list to the removed notifier to remove
+ *     the need for special case cleanup code.
  */
 
 int unregister_netdevice_notifier(struct notifier_block *nb)
 {
+       struct net_device *dev;
+       struct net *net;
        int err;
 
        rtnl_lock();
        err = raw_notifier_chain_unregister(&netdev_chain, nb);
+       if (err)
+               goto unlock;
+
+       for_each_net(net) {
+               for_each_netdev(net, dev) {
+                       if (dev->flags & IFF_UP) {
+                               nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
+                               nb->notifier_call(nb, NETDEV_DOWN, dev);
+                       }
+                       nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+                       nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);
+               }
+       }
+unlock:
        rtnl_unlock();
        return err;
 }
@@ -1596,6 +1616,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
                kfree_skb(skb);
                return NET_RX_DROP;
        }
+       skb->skb_iif = 0;
        skb_set_dev(skb, dev);
        skb->tstamp.tv64 = 0;
        skb->pkt_type = PACKET_HOST;
@@ -4027,54 +4048,41 @@ static int dev_ifconf(struct net *net, char __user *arg)
 
 #ifdef CONFIG_PROC_FS
 
-#define BUCKET_SPACE (32 - NETDEV_HASHBITS)
-
-struct dev_iter_state {
-       struct seq_net_private p;
-       unsigned int pos; /* bucket << BUCKET_SPACE + offset */
-};
+#define BUCKET_SPACE (32 - NETDEV_HASHBITS - 1)
 
 #define get_bucket(x) ((x) >> BUCKET_SPACE)
 #define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1))
 #define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
 
-static inline struct net_device *dev_from_same_bucket(struct seq_file *seq)
+static inline struct net_device *dev_from_same_bucket(struct seq_file *seq, loff_t *pos)
 {
-       struct dev_iter_state *state = seq->private;
        struct net *net = seq_file_net(seq);
        struct net_device *dev;
        struct hlist_node *p;
        struct hlist_head *h;
-       unsigned int count, bucket, offset;
+       unsigned int count = 0, offset = get_offset(*pos);
 
-       bucket = get_bucket(state->pos);
-       offset = get_offset(state->pos);
-       h = &net->dev_name_head[bucket];
-       count = 0;
+       h = &net->dev_name_head[get_bucket(*pos)];
        hlist_for_each_entry_rcu(dev, p, h, name_hlist) {
-               if (count++ == offset) {
-                       state->pos = set_bucket_offset(bucket, count);
+               if (++count == offset)
                        return dev;
-               }
        }
 
        return NULL;
 }
 
-static inline struct net_device *dev_from_new_bucket(struct seq_file *seq)
+static inline struct net_device *dev_from_bucket(struct seq_file *seq, loff_t *pos)
 {
-       struct dev_iter_state *state = seq->private;
        struct net_device *dev;
        unsigned int bucket;
 
-       bucket = get_bucket(state->pos);
        do {
-               dev = dev_from_same_bucket(seq);
+               dev = dev_from_same_bucket(seq, pos);
                if (dev)
                        return dev;
 
-               bucket++;
-               state->pos = set_bucket_offset(bucket, 0);
+               bucket = get_bucket(*pos) + 1;
+               *pos = set_bucket_offset(bucket, 1);
        } while (bucket < NETDEV_HASHENTRIES);
 
        return NULL;
@@ -4087,33 +4095,20 @@ static inline struct net_device *dev_from_new_bucket(struct seq_file *seq)
 void *dev_seq_start(struct seq_file *seq, loff_t *pos)
        __acquires(RCU)
 {
-       struct dev_iter_state *state = seq->private;
-
        rcu_read_lock();
        if (!*pos)
                return SEQ_START_TOKEN;
 
-       /* check for end of the hash */
-       if (state->pos == 0 && *pos > 1)
+       if (get_bucket(*pos) >= NETDEV_HASHENTRIES)
                return NULL;
 
-       return dev_from_new_bucket(seq);
+       return dev_from_bucket(seq, pos);
 }
 
 void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       struct net_device *dev;
-
        ++*pos;
-
-       if (v == SEQ_START_TOKEN)
-               return dev_from_new_bucket(seq);
-
-       dev = dev_from_same_bucket(seq);
-       if (dev)
-               return dev;
-
-       return dev_from_new_bucket(seq);
+       return dev_from_bucket(seq, pos);
 }
 
 void dev_seq_stop(struct seq_file *seq, void *v)
@@ -4212,13 +4207,7 @@ static const struct seq_operations dev_seq_ops = {
 static int dev_seq_open(struct inode *inode, struct file *file)
 {
        return seq_open_net(inode, file, &dev_seq_ops,
-                           sizeof(struct dev_iter_state));
-}
-
-int dev_seq_open_ops(struct inode *inode, struct file *file,
-                    const struct seq_operations *ops)
-{
-       return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state));
+                           sizeof(struct seq_net_private));
 }
 
 static const struct file_operations dev_seq_fops = {
index 29c07fef922847aaabf4cd24c91f91d477c4edc0..626698f0db8b4624ee2f18c5e1856227fe9c67ed 100644 (file)
@@ -696,7 +696,8 @@ static const struct seq_operations dev_mc_seq_ops = {
 
 static int dev_mc_seq_open(struct inode *inode, struct file *file)
 {
-       return dev_seq_open_ops(inode, file, &dev_mc_seq_ops);
+       return seq_open_net(inode, file, &dev_mc_seq_ops,
+                           sizeof(struct seq_net_private));
 }
 
 static const struct file_operations dev_mc_seq_fops = {
index 7f36b38e060fcfbf98ed35cd1dff84067f75d11c..a7cad741df012a2b7790246d6c2d569bac38bda4 100644 (file)
@@ -42,13 +42,14 @@ static void send_dm_alert(struct work_struct *unused);
  * netlink alerts
  */
 static int trace_state = TRACE_OFF;
-static DEFINE_SPINLOCK(trace_state_lock);
+static DEFINE_MUTEX(trace_state_mutex);
 
 struct per_cpu_dm_data {
        struct work_struct dm_alert_work;
-       struct sk_buff *skb;
+       struct sk_buff __rcu *skb;
        atomic_t dm_hit_count;
        struct timer_list send_timer;
+       int cpu;
 };
 
 struct dm_hw_stat_delta {
@@ -79,29 +80,53 @@ static void reset_per_cpu_data(struct per_cpu_dm_data *data)
        size_t al;
        struct net_dm_alert_msg *msg;
        struct nlattr *nla;
+       struct sk_buff *skb;
+       struct sk_buff *oskb = rcu_dereference_protected(data->skb, 1);
 
        al = sizeof(struct net_dm_alert_msg);
        al += dm_hit_limit * sizeof(struct net_dm_drop_point);
        al += sizeof(struct nlattr);
 
-       data->skb = genlmsg_new(al, GFP_KERNEL);
-       genlmsg_put(data->skb, 0, 0, &net_drop_monitor_family,
-                       0, NET_DM_CMD_ALERT);
-       nla = nla_reserve(data->skb, NLA_UNSPEC, sizeof(struct net_dm_alert_msg));
-       msg = nla_data(nla);
-       memset(msg, 0, al);
-       atomic_set(&data->dm_hit_count, dm_hit_limit);
+       skb = genlmsg_new(al, GFP_KERNEL);
+
+       if (skb) {
+               genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
+                               0, NET_DM_CMD_ALERT);
+               nla = nla_reserve(skb, NLA_UNSPEC,
+                                 sizeof(struct net_dm_alert_msg));
+               msg = nla_data(nla);
+               memset(msg, 0, al);
+       } else
+               schedule_work_on(data->cpu, &data->dm_alert_work);
+
+       /*
+        * Don't need to lock this, since we are guaranteed to only
+        * run this on a single cpu at a time.
+        * Note also that we only update data->skb if the old and new skb
+        * pointers don't match.  This ensures that we don't continually call
+        * synchornize_rcu if we repeatedly fail to alloc a new netlink message.
+        */
+       if (skb != oskb) {
+               rcu_assign_pointer(data->skb, skb);
+
+               synchronize_rcu();
+
+               atomic_set(&data->dm_hit_count, dm_hit_limit);
+       }
+
 }
 
 static void send_dm_alert(struct work_struct *unused)
 {
        struct sk_buff *skb;
-       struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+       struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
+
+       WARN_ON_ONCE(data->cpu != smp_processor_id());
 
        /*
         * Grab the skb we're about to send
         */
-       skb = data->skb;
+       skb = rcu_dereference_protected(data->skb, 1);
 
        /*
         * Replace it with a new one
@@ -111,8 +136,10 @@ static void send_dm_alert(struct work_struct *unused)
        /*
         * Ship it!
         */
-       genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
+       if (skb)
+               genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
 
+       put_cpu_var(dm_cpu_data);
 }
 
 /*
@@ -123,9 +150,11 @@ static void send_dm_alert(struct work_struct *unused)
  */
 static void sched_send_work(unsigned long unused)
 {
-       struct per_cpu_dm_data *data =  &__get_cpu_var(dm_cpu_data);
+       struct per_cpu_dm_data *data =  &get_cpu_var(dm_cpu_data);
+
+       schedule_work_on(smp_processor_id(), &data->dm_alert_work);
 
-       schedule_work(&data->dm_alert_work);
+       put_cpu_var(dm_cpu_data);
 }
 
 static void trace_drop_common(struct sk_buff *skb, void *location)
@@ -134,8 +163,15 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
        struct nlmsghdr *nlh;
        struct nlattr *nla;
        int i;
-       struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+       struct sk_buff *dskb;
+       struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
+
+
+       rcu_read_lock();
+       dskb = rcu_dereference(data->skb);
 
+       if (!dskb)
+               goto out;
 
        if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) {
                /*
@@ -144,12 +180,13 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
                goto out;
        }
 
-       nlh = (struct nlmsghdr *)data->skb->data;
+       nlh = (struct nlmsghdr *)dskb->data;
        nla = genlmsg_data(nlmsg_data(nlh));
        msg = nla_data(nla);
        for (i = 0; i < msg->entries; i++) {
                if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) {
                        msg->points[i].count++;
+                       atomic_inc(&data->dm_hit_count);
                        goto out;
                }
        }
@@ -157,7 +194,7 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
        /*
         * We need to create a new entry
         */
-       __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_drop_point));
+       __nla_reserve_nohdr(dskb, sizeof(struct net_dm_drop_point));
        nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point));
        memcpy(msg->points[msg->entries].pc, &location, sizeof(void *));
        msg->points[msg->entries].count = 1;
@@ -169,6 +206,8 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
        }
 
 out:
+       rcu_read_unlock();
+       put_cpu_var(dm_cpu_data);
        return;
 }
 
@@ -213,7 +252,7 @@ static int set_all_monitor_traces(int state)
        struct dm_hw_stat_delta *new_stat = NULL;
        struct dm_hw_stat_delta *temp;
 
-       spin_lock(&trace_state_lock);
+       mutex_lock(&trace_state_mutex);
 
        if (state == trace_state) {
                rc = -EAGAIN;
@@ -252,7 +291,7 @@ static int set_all_monitor_traces(int state)
                rc = -EINPROGRESS;
 
 out_unlock:
-       spin_unlock(&trace_state_lock);
+       mutex_unlock(&trace_state_mutex);
 
        return rc;
 }
@@ -295,12 +334,12 @@ static int dropmon_net_event(struct notifier_block *ev_block,
 
                new_stat->dev = dev;
                new_stat->last_rx = jiffies;
-               spin_lock(&trace_state_lock);
+               mutex_lock(&trace_state_mutex);
                list_add_rcu(&new_stat->list, &hw_stats_list);
-               spin_unlock(&trace_state_lock);
+               mutex_unlock(&trace_state_mutex);
                break;
        case NETDEV_UNREGISTER:
-               spin_lock(&trace_state_lock);
+               mutex_lock(&trace_state_mutex);
                list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) {
                        if (new_stat->dev == dev) {
                                new_stat->dev = NULL;
@@ -311,7 +350,7 @@ static int dropmon_net_event(struct notifier_block *ev_block,
                                }
                        }
                }
-               spin_unlock(&trace_state_lock);
+               mutex_unlock(&trace_state_mutex);
                break;
        }
 out:
@@ -367,13 +406,15 @@ static int __init init_net_drop_monitor(void)
 
        for_each_present_cpu(cpu) {
                data = &per_cpu(dm_cpu_data, cpu);
-               reset_per_cpu_data(data);
+               data->cpu = cpu;
                INIT_WORK(&data->dm_alert_work, send_dm_alert);
                init_timer(&data->send_timer);
                data->send_timer.data = cpu;
                data->send_timer.function = sched_send_work;
+               reset_per_cpu_data(data);
        }
 
+
        goto out;
 
 out_unreg:
index cf4989ac503bcc8163f90ee0e3e9610155845551..6f755cca45206934444464da8b8bcb0289921717 100644 (file)
 #include <linux/reciprocal_div.h>
 #include <linux/ratelimit.h>
 
-/* No hurry in this branch */
-static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size)
+/* No hurry in this branch
+ *
+ * Exported for the bpf jit load helper.
+ */
+void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, unsigned int size)
 {
        u8 *ptr = NULL;
 
@@ -59,7 +62,7 @@ static inline void *load_pointer(const struct sk_buff *skb, int k,
 {
        if (k >= 0)
                return skb_header_pointer(skb, k, size, buffer);
-       return __load_pointer(skb, k, size);
+       return bpf_internal_load_pointer_neg_helper(skb, k, size);
 }
 
 /**
index 0e950fda9a0abc88ffaa9e3e62b2a11c023a7b8b..31a5ae51a45c8770136ac1b60b76da842d9803df 100644 (file)
@@ -83,21 +83,29 @@ assign:
 
 static int ops_init(const struct pernet_operations *ops, struct net *net)
 {
-       int err;
+       int err = -ENOMEM;
+       void *data = NULL;
+
        if (ops->id && ops->size) {
-               void *data = kzalloc(ops->size, GFP_KERNEL);
+               data = kzalloc(ops->size, GFP_KERNEL);
                if (!data)
-                       return -ENOMEM;
+                       goto out;
 
                err = net_assign_generic(net, *ops->id, data);
-               if (err) {
-                       kfree(data);
-                       return err;
-               }
+               if (err)
+                       goto cleanup;
        }
+       err = 0;
        if (ops->init)
-               return ops->init(net);
-       return 0;
+               err = ops->init(net);
+       if (!err)
+               return 0;
+
+cleanup:
+       kfree(data);
+
+out:
+       return err;
 }
 
 static void ops_free(const struct pernet_operations *ops, struct net *net)
@@ -448,12 +456,7 @@ static void __unregister_pernet_operations(struct pernet_operations *ops)
 static int __register_pernet_operations(struct list_head *list,
                                        struct pernet_operations *ops)
 {
-       int err = 0;
-       err = ops_init(ops, &init_net);
-       if (err)
-               ops_free(ops, &init_net);
-       return err;
-       
+       return ops_init(ops, &init_net);
 }
 
 static void __unregister_pernet_operations(struct pernet_operations *ops)
index f223cdc75da6af27a688430ee98c0743608ea822..e59840010d45c9bc25f521fe1ef0717d2de984af 100644 (file)
@@ -952,9 +952,11 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
                goto adjust_others;
        }
 
-       data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
+       data = kmalloc(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
+                      gfp_mask);
        if (!data)
                goto nodata;
+       size = SKB_WITH_OVERHEAD(ksize(data));
 
        /* Copy only real data... and, alas, header. This should be
         * optimized for the cases when header is void.
@@ -3161,6 +3163,8 @@ static void sock_rmem_free(struct sk_buff *skb)
  */
 int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
 {
+       int len = skb->len;
+
        if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
            (unsigned)sk->sk_rcvbuf)
                return -ENOMEM;
@@ -3175,7 +3179,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
 
        skb_queue_tail(&sk->sk_error_queue, skb);
        if (!sock_flag(sk, SOCK_DEAD))
-               sk->sk_data_ready(sk, skb->len);
+               sk->sk_data_ready(sk, len);
        return 0;
 }
 EXPORT_SYMBOL(sock_queue_err_skb);
index 36851588536861bb5fe67f61c69829807e599fb4..840821b90bcd7e11c79c14dd44bcc02aedcedf23 100644 (file)
@@ -1044,6 +1044,24 @@ static void lowpan_dev_free(struct net_device *dev)
        free_netdev(dev);
 }
 
+static struct wpan_phy *lowpan_get_phy(const struct net_device *dev)
+{
+       struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+       return ieee802154_mlme_ops(real_dev)->get_phy(real_dev);
+}
+
+static u16 lowpan_get_pan_id(const struct net_device *dev)
+{
+       struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+       return ieee802154_mlme_ops(real_dev)->get_pan_id(real_dev);
+}
+
+static u16 lowpan_get_short_addr(const struct net_device *dev)
+{
+       struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+       return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev);
+}
+
 static struct header_ops lowpan_header_ops = {
        .create = lowpan_header_create,
 };
@@ -1053,6 +1071,12 @@ static const struct net_device_ops lowpan_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
+static struct ieee802154_mlme_ops lowpan_mlme = {
+       .get_pan_id = lowpan_get_pan_id,
+       .get_phy = lowpan_get_phy,
+       .get_short_addr = lowpan_get_short_addr,
+};
+
 static void lowpan_setup(struct net_device *dev)
 {
        pr_debug("(%s)\n", __func__);
@@ -1070,6 +1094,7 @@ static void lowpan_setup(struct net_device *dev)
 
        dev->netdev_ops         = &lowpan_netdev_ops;
        dev->header_ops         = &lowpan_header_ops;
+       dev->ml_priv            = &lowpan_mlme;
        dev->destructor         = lowpan_dev_free;
 }
 
@@ -1143,6 +1168,8 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
        list_add_tail(&entry->list, &lowpan_devices);
        mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
 
+       spin_lock_init(&flist_lock);
+
        register_netdevice(dev);
 
        return 0;
@@ -1152,11 +1179,20 @@ static void lowpan_dellink(struct net_device *dev, struct list_head *head)
 {
        struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
        struct net_device *real_dev = lowpan_dev->real_dev;
-       struct lowpan_dev_record *entry;
-       struct lowpan_dev_record *tmp;
+       struct lowpan_dev_record *entry, *tmp;
+       struct lowpan_fragment *frame, *tframe;
 
        ASSERT_RTNL();
 
+       spin_lock(&flist_lock);
+       list_for_each_entry_safe(frame, tframe, &lowpan_fragments, list) {
+               del_timer(&frame->timer);
+               list_del(&frame->list);
+               dev_kfree_skb(frame->skb);
+               kfree(frame);
+       }
+       spin_unlock(&flist_lock);
+
        mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
        list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
                if (entry->ldev == dev) {
index 8d25a1c557eb50f012761227634d0ae7155c7180..8f8db724bfafe5f744a8f956dc7e710a67dc7faa 100644 (file)
@@ -141,7 +141,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                        goto rtattr_failure;
 
        if (icsk == NULL) {
-               r->idiag_rqueue = r->idiag_wqueue = 0;
+               handler->idiag_get_info(sk, r, NULL);
                goto out;
        }
 
index de9da21113a11be6c9f57b15a97b3936a574e512..cf73cc70ed2d2e1bfe1a5c837bc9993358e9904e 100644 (file)
@@ -74,16 +74,24 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
 
        iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
        if (iph == NULL)
-               return -NF_DROP;
+               return -NF_ACCEPT;
 
        /* Conntrack defragments packets, we might still see fragments
         * inside ICMP packets though. */
        if (iph->frag_off & htons(IP_OFFSET))
-               return -NF_DROP;
+               return -NF_ACCEPT;
 
        *dataoff = nhoff + (iph->ihl << 2);
        *protonum = iph->protocol;
 
+       /* Check bogus IP headers */
+       if (*dataoff > skb->len) {
+               pr_debug("nf_conntrack_ipv4: bogus IPv4 packet: "
+                        "nhoff %u, ihl %u, skblen %u\n",
+                        nhoff, iph->ihl << 2, skb->len);
+               return -NF_ACCEPT;
+       }
+
        return NF_ACCEPT;
 }
 
index 4dc1c104c942204882acadcf73e709683ebaafd6..167ea10b521a8267b95bff128011b53d5cbb32c2 100644 (file)
@@ -2041,7 +2041,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                if (err < 0)
                        goto e_err;
        }
-       rth = rt_dst_alloc(init_net.loopback_dev,
+       rth = rt_dst_alloc(dev_net(dev)->loopback_dev,
                           IN_DEV_CONF_GET(in_dev, NOPOLICY), false);
        if (!rth)
                goto e_nobufs;
index cfd7edda0a8eb6e8dd908a1bc5c309225c4ce495..1272a88c2a6331bb749d3a016710de649c1de057 100644 (file)
@@ -701,11 +701,12 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp)
        skb = alloc_skb_fclone(size + sk->sk_prot->max_header, gfp);
        if (skb) {
                if (sk_wmem_schedule(sk, skb->truesize)) {
+                       skb_reserve(skb, sk->sk_prot->max_header);
                        /*
                         * Make sure that we have exactly size bytes
                         * available to the caller, no more, no less.
                         */
-                       skb_reserve(skb, skb_tailroom(skb) - size);
+                       skb->avail_size = size;
                        return skb;
                }
                __kfree_skb(skb);
@@ -860,7 +861,7 @@ wait_for_memory:
        }
 
 out:
-       if (copied)
+       if (copied && !(flags & MSG_SENDPAGE_NOTLAST))
                tcp_push(sk, flags, mss_now, tp->nonagle);
        return copied;
 
@@ -995,10 +996,9 @@ new_segment:
                                copy = seglen;
 
                        /* Where to copy to? */
-                       if (skb_tailroom(skb) > 0) {
+                       if (skb_availroom(skb) > 0) {
                                /* We have some space in skb head. Superb! */
-                               if (copy > skb_tailroom(skb))
-                                       copy = skb_tailroom(skb);
+                               copy = min_t(int, copy, skb_availroom(skb));
                                err = skb_add_data_nocache(sk, skb, from, copy);
                                if (err)
                                        goto do_fault;
@@ -1452,7 +1452,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                if ((available < target) &&
                    (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
                    !sysctl_tcp_low_latency &&
-                   dma_find_channel(DMA_MEMCPY)) {
+                   net_dma_find_channel()) {
                        preempt_enable_no_resched();
                        tp->ucopy.pinned_list =
                                        dma_pin_iovec_pages(msg->msg_iov, len);
@@ -1667,7 +1667,7 @@ do_prequeue:
                if (!(flags & MSG_TRUNC)) {
 #ifdef CONFIG_NET_DMA
                        if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
-                               tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
+                               tp->ucopy.dma_chan = net_dma_find_channel();
 
                        if (tp->ucopy.dma_chan) {
                                tp->ucopy.dma_cookie = dma_skb_copy_datagram_iovec(
@@ -3243,7 +3243,7 @@ void __init tcp_init(void)
 {
        struct sk_buff *skb = NULL;
        unsigned long limit;
-       int max_share, cnt;
+       int max_rshare, max_wshare, cnt;
        unsigned int i;
        unsigned long jiffy = jiffies;
 
@@ -3302,17 +3302,17 @@ void __init tcp_init(void)
 
        tcp_init_mem(&init_net);
        /* Set per-socket limits to no more than 1/128 the pressure threshold */
-       limit = nr_free_buffer_pages() << (PAGE_SHIFT - 10);
-       limit = max(limit, 128UL);
-       max_share = min(4UL*1024*1024, limit);
+       limit = nr_free_buffer_pages() << (PAGE_SHIFT - 7);
+       max_wshare = min(4UL*1024*1024, limit);
+       max_rshare = min(6UL*1024*1024, limit);
 
        sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
        sysctl_tcp_wmem[1] = 16*1024;
-       sysctl_tcp_wmem[2] = max(64*1024, max_share);
+       sysctl_tcp_wmem[2] = max(64*1024, max_wshare);
 
        sysctl_tcp_rmem[0] = SK_MEM_QUANTUM;
        sysctl_tcp_rmem[1] = 87380;
-       sysctl_tcp_rmem[2] = max(87380, max_share);
+       sysctl_tcp_rmem[2] = max(87380, max_rshare);
 
        pr_info("Hash tables configured (established %u bind %u)\n",
                tcp_hashinfo.ehash_mask + 1, tcp_hashinfo.bhash_size);
index e886e2f7fa8d03edc8644179a6f1ef7ca6a374f6..257b61789eeba9fd064470c91e3a8bffb8d1812d 100644 (file)
@@ -85,7 +85,7 @@ int sysctl_tcp_ecn __read_mostly = 2;
 EXPORT_SYMBOL(sysctl_tcp_ecn);
 int sysctl_tcp_dsack __read_mostly = 1;
 int sysctl_tcp_app_win __read_mostly = 31;
-int sysctl_tcp_adv_win_scale __read_mostly = 2;
+int sysctl_tcp_adv_win_scale __read_mostly = 1;
 EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
 
 int sysctl_tcp_stdurg __read_mostly;
@@ -335,6 +335,7 @@ static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb)
                        incr = __tcp_grow_window(sk, skb);
 
                if (incr) {
+                       incr = max_t(int, incr, 2 * skb->len);
                        tp->rcv_ssthresh = min(tp->rcv_ssthresh + incr,
                                               tp->window_clamp);
                        inet_csk(sk)->icsk_ack.quick |= 1;
@@ -474,8 +475,11 @@ static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep)
                if (!win_dep) {
                        m -= (new_sample >> 3);
                        new_sample += m;
-               } else if (m < new_sample)
-                       new_sample = m << 3;
+               } else {
+                       m <<= 3;
+                       if (m < new_sample)
+                               new_sample = m;
+               }
        } else {
                /* No previous measure. */
                new_sample = m << 3;
@@ -491,7 +495,7 @@ static inline void tcp_rcv_rtt_measure(struct tcp_sock *tp)
                goto new_measure;
        if (before(tp->rcv_nxt, tp->rcv_rtt_est.seq))
                return;
-       tcp_rcv_rtt_update(tp, jiffies - tp->rcv_rtt_est.time, 1);
+       tcp_rcv_rtt_update(tp, tcp_time_stamp - tp->rcv_rtt_est.time, 1);
 
 new_measure:
        tp->rcv_rtt_est.seq = tp->rcv_nxt + tp->rcv_wnd;
@@ -2864,11 +2868,14 @@ static inline void tcp_complete_cwr(struct sock *sk)
 
        /* Do not moderate cwnd if it's already undone in cwr or recovery. */
        if (tp->undo_marker) {
-               if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR)
+               if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR) {
                        tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
-               else /* PRR */
+                       tp->snd_cwnd_stamp = tcp_time_stamp;
+               } else if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH) {
+                       /* PRR algorithm. */
                        tp->snd_cwnd = tp->snd_ssthresh;
-               tp->snd_cwnd_stamp = tcp_time_stamp;
+                       tp->snd_cwnd_stamp = tcp_time_stamp;
+               }
        }
        tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR);
 }
@@ -5225,7 +5232,7 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb,
                return 0;
 
        if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
-               tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
+               tp->ucopy.dma_chan = net_dma_find_channel();
 
        if (tp->ucopy.dma_chan && skb_csum_unnecessary(skb)) {
 
index 3a25cf743f8ba5a70d72dd9b068e42fe52675026..0cb86ceb652ff66432ba584fedef8231d94decc6 100644 (file)
@@ -1730,7 +1730,7 @@ process:
 #ifdef CONFIG_NET_DMA
                struct tcp_sock *tp = tcp_sk(sk);
                if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
-                       tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
+                       tp->ucopy.dma_chan = net_dma_find_channel();
                if (tp->ucopy.dma_chan)
                        ret = tcp_v4_do_rcv(sk, skb);
                else
index 364784a91939c50eff90f8d8f29a174e1f63bafe..7ac6423117adfb333f433cc1b86356d38cb995ea 100644 (file)
@@ -1096,6 +1096,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
        eat = min_t(int, len, skb_headlen(skb));
        if (eat) {
                __skb_pull(skb, eat);
+               skb->avail_size -= eat;
                len -= eat;
                if (!len)
                        return;
@@ -2060,7 +2061,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
                /* Punt if not enough space exists in the first SKB for
                 * the data in the second
                 */
-               if (skb->len > skb_tailroom(to))
+               if (skb->len > skb_availroom(to))
                        break;
 
                if (after(TCP_SKB_CB(skb)->end_seq, tcp_wnd_end(tp)))
index 8a949f19deb6dc93542396138004a5a6b2bfeeab..a7f86a3cd5023e2a7489167fcdd84df0d75a26a0 100644 (file)
@@ -146,9 +146,17 @@ static int udp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh,
        return udp_dump_one(&udp_table, in_skb, nlh, req);
 }
 
+static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
+               void *info)
+{
+       r->idiag_rqueue = sk_rmem_alloc_get(sk);
+       r->idiag_wqueue = sk_wmem_alloc_get(sk);
+}
+
 static const struct inet_diag_handler udp_diag_handler = {
        .dump            = udp_diag_dump,
        .dump_one        = udp_diag_dump_one,
+       .idiag_get_info  = udp_diag_get_info,
        .idiag_type      = IPPROTO_UDP,
 };
 
@@ -167,6 +175,7 @@ static int udplite_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *
 static const struct inet_diag_handler udplite_diag_handler = {
        .dump            = udplite_diag_dump,
        .dump_one        = udplite_diag_dump_one,
+       .idiag_get_info  = udp_diag_get_info,
        .idiag_type      = IPPROTO_UDPLITE,
 };
 
index 6a3bb6077e19715bf2732bbce3d1c09d06aed104..7d5cb975cc6f8e6c22581daaa638b6b3df5a52d2 100644 (file)
@@ -803,8 +803,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
                                ip6_del_rt(rt);
                                rt = NULL;
                        } else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
-                               rt->dst.expires = expires;
-                               rt->rt6i_flags |= RTF_EXPIRES;
+                               rt6_set_expires(rt, expires);
                        }
                }
                dst_release(&rt->dst);
@@ -1887,11 +1886,9 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
                                rt = NULL;
                        } else if (addrconf_finite_timeout(rt_expires)) {
                                /* not infinity */
-                               rt->dst.expires = jiffies + rt_expires;
-                               rt->rt6i_flags |= RTF_EXPIRES;
+                               rt6_set_expires(rt, jiffies + rt_expires);
                        } else {
-                               rt->rt6i_flags &= ~RTF_EXPIRES;
-                               rt->dst.expires = 0;
+                               rt6_clean_expires(rt);
                        }
                } else if (valid_lft) {
                        clock_t expires = 0;
index 5b27fbcae346677a28db262c5ffc1a272e1b1cd5..93717435013e0a146c10bc8cf3ea4cbddb627f9b 100644 (file)
@@ -673,11 +673,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                                            &rt->rt6i_gateway)) {
                                if (!(iter->rt6i_flags & RTF_EXPIRES))
                                        return -EEXIST;
-                               iter->dst.expires = rt->dst.expires;
-                               if (!(rt->rt6i_flags & RTF_EXPIRES)) {
-                                       iter->rt6i_flags &= ~RTF_EXPIRES;
-                                       iter->dst.expires = 0;
-                               }
+                               if (!(rt->rt6i_flags & RTF_EXPIRES))
+                                       rt6_clean_expires(iter);
+                               else
+                                       rt6_set_expires(iter, rt->dst.expires);
                                return -EEXIST;
                        }
                }
index 16c33e308121da59c61629a13fa239dada189874..b2869cab2092ae2d08e6b090c98fbe6aece35e75 100644 (file)
@@ -2044,7 +2044,7 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
                if (!delta)
                        pmc->mca_sfcount[sfmode]--;
                for (j=0; j<i; j++)
-                       (void) ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]);
+                       ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]);
        } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
                struct ip6_sf_list *psf;
 
index 3dcdb81ec3e8abdb934627cd243aed0e5ce3b5a3..176b469322acd0b63b6e8d7ad0f095129b165868 100644 (file)
@@ -1264,8 +1264,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
        }
 
        if (rt)
-               rt->dst.expires = jiffies + (HZ * lifetime);
-
+               rt6_set_expires(rt, jiffies + (HZ * lifetime));
        if (ra_msg->icmph.icmp6_hop_limit) {
                in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
                if (rt)
index 94874b0bdcdcf9835fe0b0b53fd088c12db93305..9d4e155593190d81b99af8988899a0204a73ec80 100644 (file)
@@ -78,19 +78,6 @@ EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table);
 
    Hence the start of any table is given by get_table() below.  */
 
-/* Check for an extension */
-int
-ip6t_ext_hdr(u8 nexthdr)
-{
-       return  (nexthdr == IPPROTO_HOPOPTS)   ||
-               (nexthdr == IPPROTO_ROUTING)   ||
-               (nexthdr == IPPROTO_FRAGMENT)  ||
-               (nexthdr == IPPROTO_ESP)       ||
-               (nexthdr == IPPROTO_AH)        ||
-               (nexthdr == IPPROTO_NONE)      ||
-               (nexthdr == IPPROTO_DSTOPTS);
-}
-
 /* Returns whether matches rule or not. */
 /* Performance critical - called for every packet */
 static inline bool
@@ -2366,7 +2353,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 EXPORT_SYMBOL(ip6t_register_table);
 EXPORT_SYMBOL(ip6t_unregister_table);
 EXPORT_SYMBOL(ip6t_do_table);
-EXPORT_SYMBOL(ip6t_ext_hdr);
 EXPORT_SYMBOL(ipv6_find_hdr);
 
 module_init(ip6_tables_init);
index 496b62712fe8c9c42f15e59d86cfd94bc936e59b..bc4888d902b2ed904f0ca767ac3e4d9cd35c252c 100644 (file)
@@ -62,7 +62,7 @@
 #include <linux/sysctl.h>
 #endif
 
-static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
+static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                                    const struct in6_addr *dest);
 static struct dst_entry        *ip6_dst_check(struct dst_entry *dst, u32 cookie);
 static unsigned int     ip6_default_advmss(const struct dst_entry *dst);
@@ -285,6 +285,10 @@ static void ip6_dst_destroy(struct dst_entry *dst)
                rt->rt6i_idev = NULL;
                in6_dev_put(idev);
        }
+
+       if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from)
+               dst_release(dst->from);
+
        if (peer) {
                rt->rt6i_peer = NULL;
                inet_putpeer(peer);
@@ -329,8 +333,17 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 
 static __inline__ int rt6_check_expired(const struct rt6_info *rt)
 {
-       return (rt->rt6i_flags & RTF_EXPIRES) &&
-               time_after(jiffies, rt->dst.expires);
+       struct rt6_info *ort = NULL;
+
+       if (rt->rt6i_flags & RTF_EXPIRES) {
+               if (time_after(jiffies, rt->dst.expires))
+                       return 1;
+       } else if (rt->dst.from) {
+               ort = (struct rt6_info *) rt->dst.from;
+               return (ort->rt6i_flags & RTF_EXPIRES) &&
+                       time_after(jiffies, ort->dst.expires);
+       }
+       return 0;
 }
 
 static inline int rt6_need_strict(const struct in6_addr *daddr)
@@ -620,12 +633,11 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
                                 (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
 
        if (rt) {
-               if (!addrconf_finite_timeout(lifetime)) {
-                       rt->rt6i_flags &= ~RTF_EXPIRES;
-               } else {
-                       rt->dst.expires = jiffies + HZ * lifetime;
-                       rt->rt6i_flags |= RTF_EXPIRES;
-               }
+               if (!addrconf_finite_timeout(lifetime))
+                       rt6_clean_expires(rt);
+               else
+                       rt6_set_expires(rt, jiffies + HZ * lifetime);
+
                dst_release(&rt->dst);
        }
        return 0;
@@ -730,7 +742,7 @@ int ip6_ins_rt(struct rt6_info *rt)
        return __ip6_ins_rt(rt, &info);
 }
 
-static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort,
+static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort,
                                      const struct in6_addr *daddr,
                                      const struct in6_addr *saddr)
 {
@@ -881,6 +893,16 @@ static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *
        return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
 }
 
+static struct dst_entry *ip6_route_input_lookup(struct net *net,
+                                               struct net_device *dev,
+                                               struct flowi6 *fl6, int flags)
+{
+       if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG)
+               flags |= RT6_LOOKUP_F_IFACE;
+
+       return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input);
+}
+
 void ip6_route_input(struct sk_buff *skb)
 {
        const struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -895,10 +917,7 @@ void ip6_route_input(struct sk_buff *skb)
                .flowi6_proto = iph->nexthdr,
        };
 
-       if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG)
-               flags |= RT6_LOOKUP_F_IFACE;
-
-       skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input));
+       skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags));
 }
 
 static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
@@ -947,10 +966,10 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
                rt->rt6i_idev = ort->rt6i_idev;
                if (rt->rt6i_idev)
                        in6_dev_hold(rt->rt6i_idev);
-               rt->dst.expires = 0;
 
                rt->rt6i_gateway = ort->rt6i_gateway;
-               rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
+               rt->rt6i_flags = ort->rt6i_flags;
+               rt6_clean_expires(rt);
                rt->rt6i_metric = 0;
 
                memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
@@ -1012,10 +1031,9 @@ static void ip6_link_failure(struct sk_buff *skb)
 
        rt = (struct rt6_info *) skb_dst(skb);
        if (rt) {
-               if (rt->rt6i_flags & RTF_CACHE) {
-                       dst_set_expires(&rt->dst, 0);
-                       rt->rt6i_flags |= RTF_EXPIRES;
-               } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT))
+               if (rt->rt6i_flags & RTF_CACHE)
+                       rt6_update_expires(rt, 0);
+               else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT))
                        rt->rt6i_node->fn_sernum = -1;
        }
 }
@@ -1282,9 +1300,12 @@ int ip6_route_add(struct fib6_config *cfg)
        }
 
        rt->dst.obsolete = -1;
-       rt->dst.expires = (cfg->fc_flags & RTF_EXPIRES) ?
-                               jiffies + clock_t_to_jiffies(cfg->fc_expires) :
-                               0;
+
+       if (cfg->fc_flags & RTF_EXPIRES)
+               rt6_set_expires(rt, jiffies +
+                               clock_t_to_jiffies(cfg->fc_expires));
+       else
+               rt6_clean_expires(rt);
 
        if (cfg->fc_protocol == RTPROT_UNSPEC)
                cfg->fc_protocol = RTPROT_BOOT;
@@ -1729,8 +1750,8 @@ again:
                        features |= RTAX_FEATURE_ALLFRAG;
                        dst_metric_set(&rt->dst, RTAX_FEATURES, features);
                }
-               dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
-               rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
+               rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires);
+               rt->rt6i_flags |= RTF_MODIFIED;
                goto out;
        }
 
@@ -1758,9 +1779,8 @@ again:
                 * which is 10 mins. After 10 mins the decreased pmtu is expired
                 * and detecting PMTU increase will be automatically happened.
                 */
-               dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
-               nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
-
+               rt6_update_expires(nrt, net->ipv6.sysctl.ip6_rt_mtu_expires);
+               nrt->rt6i_flags |= RTF_DYNAMIC;
                ip6_ins_rt(nrt);
        }
 out:
@@ -1792,7 +1812,7 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad
  *     Misc support functions
  */
 
-static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
+static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                                    const struct in6_addr *dest)
 {
        struct net *net = dev_net(ort->dst.dev);
@@ -1812,10 +1832,14 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
                if (rt->rt6i_idev)
                        in6_dev_hold(rt->rt6i_idev);
                rt->dst.lastuse = jiffies;
-               rt->dst.expires = 0;
 
                rt->rt6i_gateway = ort->rt6i_gateway;
-               rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
+               rt->rt6i_flags = ort->rt6i_flags;
+               if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
+                   (RTF_DEFAULT | RTF_ADDRCONF))
+                       rt6_set_from(rt, ort);
+               else
+                       rt6_clean_expires(rt);
                rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES
@@ -2537,7 +2561,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
        struct sk_buff *skb;
        struct rtmsg *rtm;
        struct flowi6 fl6;
-       int err, iif = 0;
+       int err, iif = 0, oif = 0;
 
        err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
        if (err < 0)
@@ -2564,15 +2588,29 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
                iif = nla_get_u32(tb[RTA_IIF]);
 
        if (tb[RTA_OIF])
-               fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]);
+               oif = nla_get_u32(tb[RTA_OIF]);
 
        if (iif) {
                struct net_device *dev;
+               int flags = 0;
+
                dev = __dev_get_by_index(net, iif);
                if (!dev) {
                        err = -ENODEV;
                        goto errout;
                }
+
+               fl6.flowi6_iif = iif;
+
+               if (!ipv6_addr_any(&fl6.saddr))
+                       flags |= RT6_LOOKUP_F_HAS_SADDR;
+
+               rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
+                                                              flags);
+       } else {
+               fl6.flowi6_oif = oif;
+
+               rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
        }
 
        skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
@@ -2587,7 +2625,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
        skb_reset_mac_header(skb);
        skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
 
-       rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6);
        skb_dst_set(skb, &rt->dst);
 
        err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
index 12c6ece67f396a2d01f641b7a0e0d728fcab3337..98256cf72f9dbca22dc80b3405ac80ec4fdb158f 100644 (file)
@@ -1383,6 +1383,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        tcp_mtup_init(newsk);
        tcp_sync_mss(newsk, dst_mtu(dst));
        newtp->advmss = dst_metric_advmss(dst);
+       if (tcp_sk(sk)->rx_opt.user_mss &&
+           tcp_sk(sk)->rx_opt.user_mss < newtp->advmss)
+               newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
+
        tcp_initialize_rcv_mss(newsk);
        if (tcp_rsk(req)->snt_synack)
                tcp_valid_rtt_meas(newsk,
@@ -1645,7 +1649,7 @@ process:
 #ifdef CONFIG_NET_DMA
                struct tcp_sock *tp = tcp_sk(sk);
                if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
-                       tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
+                       tp->ucopy.dma_chan = net_dma_find_channel();
                if (tp->ucopy.dma_chan)
                        ret = tcp_v6_do_rcv(sk, skb);
                else
index 11dbb2255ccbce3f1e34c34f35a56a9ebd9428c1..7e5d927b576f79b8163b765ff5dcb6f6e0c4be43 100644 (file)
@@ -3480,7 +3480,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
 
        /* Addresses to be used by KM for negotiation, if ext is available */
        if (k != NULL && (set_sadb_kmaddress(skb, k) < 0))
-               return -EINVAL;
+               goto err;
 
        /* selector src */
        set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel);
index 55670ec3cd0f916143759cbc73320cf85b7ef196..6274f0be82b0c3445f6288f7fb8c7612d5325d69 100644 (file)
@@ -232,7 +232,7 @@ static void l2tp_ip_close(struct sock *sk, long timeout)
 {
        write_lock_bh(&l2tp_ip_lock);
        hlist_del_init(&sk->sk_bind_node);
-       hlist_del_init(&sk->sk_node);
+       sk_del_node_init(sk);
        write_unlock_bh(&l2tp_ip_lock);
        sk_common_release(sk);
 }
@@ -271,7 +271,8 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
            chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
                goto out;
 
-       inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr;
+       if (addr->l2tp_addr.s_addr)
+               inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr;
        if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
                inet->inet_saddr = 0;  /* Use device */
        sk_dst_reset(sk);
@@ -441,8 +442,9 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
 
                daddr = lip->l2tp_addr.s_addr;
        } else {
+               rc = -EDESTADDRREQ;
                if (sk->sk_state != TCP_ESTABLISHED)
-                       return -EDESTADDRREQ;
+                       goto out;
 
                daddr = inet->inet_daddr;
                connected = 1;
index 1068f668ac4ec3434b1524624df98c5bf08e5074..64d3ce5ea1a0787c22891a984d2e030ac0671937 100644 (file)
@@ -49,6 +49,8 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
                container_of(h, struct tid_ampdu_rx, rcu_head);
        int i;
 
+       del_timer_sync(&tid_rx->reorder_timer);
+
        for (i = 0; i < tid_rx->buf_size; i++)
                dev_kfree_skb(tid_rx->reorder_buf[i]);
        kfree(tid_rx->reorder_buf);
@@ -91,7 +93,6 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
                                     tid, WLAN_BACK_RECIPIENT, reason);
 
        del_timer_sync(&tid_rx->session_timer);
-       del_timer_sync(&tid_rx->reorder_timer);
 
        call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
 }
index cc5b7a6e7e0b084d2e8cb7e2f06d0e3f392eabc1..778e5916d7c3e140ccc3cb98012b39204e3003c7 100644 (file)
 #include "rate.h"
 #include "debugfs.h"
 
-int mac80211_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 #define DEBUGFS_FORMAT_BUFFER_SIZE 100
 
 int mac80211_format_buffer(char __user *userbuf, size_t count,
@@ -50,7 +44,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,  \
 #define DEBUGFS_READONLY_FILE_OPS(name)                        \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
-       .open = mac80211_open_file_generic,                             \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -93,7 +87,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf,
 
 static const struct file_operations reset_ops = {
        .write = reset_write,
-       .open = mac80211_open_file_generic,
+       .open = simple_open,
        .llseek = noop_llseek,
 };
 
@@ -254,7 +248,7 @@ static ssize_t stats_ ##name## _read(struct file *file,                     \
                                                                        \
 static const struct file_operations stats_ ##name## _ops = {           \
        .read = stats_ ##name## _read,                                  \
-       .open = mac80211_open_file_generic,                             \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
index 7c87529630f55eabd2ba45721d73f138dad7401a..9be4e6d71d00d736db7eeee2f24a645b1c41b2bb 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef CONFIG_MAC80211_DEBUGFS
 extern void debugfs_hw_add(struct ieee80211_local *local);
-extern int mac80211_open_file_generic(struct inode *inode, struct file *file);
 extern int mac80211_format_buffer(char __user *userbuf, size_t count,
                                  loff_t *ppos, char *fmt, ...);
 #else
index 59edcd95a58dbcec31833568f9d5f8bd8893da09..7932767bb482415f9b50ec0043c0c56246476f04 100644 (file)
@@ -30,7 +30,7 @@ static ssize_t key_##name##_read(struct file *file,                   \
 #define KEY_OPS(name)                                                  \
 static const struct file_operations key_ ##name## _ops = {             \
        .read = key_##name##_read,                                      \
-       .open = mac80211_open_file_generic,                             \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 }
 
@@ -45,7 +45,7 @@ static const struct file_operations key_ ##name## _ops = {            \
 #define KEY_CONF_OPS(name)                                             \
 static const struct file_operations key_ ##name## _ops = {             \
        .read = key_conf_##name##_read,                                 \
-       .open = mac80211_open_file_generic,                             \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 }
 
index a32eeda04aa3f1bb980066f0183615c2acffd8df..30f99c344847c0802a9dd21c820a06bd99371a7e 100644 (file)
@@ -135,7 +135,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file,          \
 static const struct file_operations name##_ops = {                     \
        .read = ieee80211_if_read_##name,                               \
        .write = (_write),                                              \
-       .open = mac80211_open_file_generic,                             \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 }
 
index 6d45804d09bc0a26ef9025c8751355ffebd13b8f..832b2da5e4cd8955b11920e9fe4537e7e0981687 100644 (file)
@@ -33,7 +33,7 @@ static ssize_t sta_ ##name## _read(struct file *file,                 \
 #define STA_OPS(name)                                                  \
 static const struct file_operations sta_ ##name## _ops = {             \
        .read = sta_##name##_read,                                      \
-       .open = mac80211_open_file_generic,                             \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 }
 
@@ -41,7 +41,7 @@ static const struct file_operations sta_ ##name## _ops = {            \
 static const struct file_operations sta_ ##name## _ops = {             \
        .read = sta_##name##_read,                                      \
        .write = sta_##name##_write,                                    \
-       .open = mac80211_open_file_generic,                             \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 }
 
index 33fd8d9f714ec05db8aeba88d0bb5c6bf97e8fd0..cef7c29214a8492b3e67f62c4248e5c89dfe7daf 100644 (file)
@@ -457,8 +457,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                         * fall back to HT20 if we don't use or use
                         * the other extension channel
                         */
-                       if ((channel_type == NL80211_CHAN_HT40MINUS ||
-                            channel_type == NL80211_CHAN_HT40PLUS) &&
+                       if (!(channel_type == NL80211_CHAN_HT40MINUS ||
+                             channel_type == NL80211_CHAN_HT40PLUS) ||
                            channel_type != sdata->u.ibss.channel_type)
                                sta_ht_cap_new.cap &=
                                        ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
index d9798a307f20dabdeea69179e76008bccf144673..db8fae51714c54f35310777bb61a7052fa532297 100644 (file)
@@ -1210,7 +1210,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                                  struct sk_buff *skb);
 void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
-void ieee80211_mgd_teardown(struct ieee80211_sub_if_data *sdata);
+void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
 
 /* IBSS code */
 void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
index 401c01f0731e996e5c22435f0066b53c97529559..c20051b7ffcd8518e6dd8e01c042b3fbf6981677 100644 (file)
@@ -486,6 +486,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                /* free all potentially still buffered bcast frames */
                local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
                skb_queue_purge(&sdata->u.ap.ps_bc_buf);
+       } else if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+               ieee80211_mgd_stop(sdata);
        }
 
        if (going_down)
@@ -644,8 +646,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
 
        if (ieee80211_vif_is_mesh(&sdata->vif))
                mesh_rmc_free(sdata);
-       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
-               ieee80211_mgd_teardown(sdata);
 
        flushed = sta_info_flush(local, sdata);
        WARN_ON(flushed);
index b581a24fa15c43739538ea8d4ae0b4a843feedce..16336480c631a6bd61d47d1137d57ba80ce7aca4 100644 (file)
@@ -102,9 +102,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 
        might_sleep();
 
-       /* If this off-channel logic ever changes,  ieee80211_on_oper_channel
-        * may need to change as well.
-        */
        offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
        if (local->scan_channel) {
                chan = local->scan_channel;
index 576fb25456dd7479a0ed51c50efad9c6a238c3d1..20c680bfc3ae0fd52f502c9c920a0ea4c0f20f86 100644 (file)
@@ -3387,8 +3387,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
                 */
                printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
                       sdata->name, ifmgd->bssid);
-               assoc_data->timeout = jiffies +
-                               TU_TO_EXP_TIME(req->bss->beacon_interval);
+               assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
        } else {
                assoc_data->have_beacon = true;
                assoc_data->sent_assoc = false;
@@ -3498,7 +3497,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-void ieee80211_mgd_teardown(struct ieee80211_sub_if_data *sdata)
+void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
index b4f7600a3e36c010f6d428ad0461db2324087dc3..3313c117b322a928d17586c766c66bb698ca17bf 100644 (file)
@@ -145,7 +145,7 @@ static ssize_t rcname_read(struct file *file, char __user *userbuf,
 
 static const struct file_operations rcname_ops = {
        .read = rcname_read,
-       .open = mac80211_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 #endif
index bcfe8c77c8392dae5e730d8b76c0c18bb9720622..d64e285400aaab3245c31af4ec6401cd1e77b294 100644 (file)
@@ -103,7 +103,7 @@ static void
 ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                                 struct sk_buff *skb,
                                 struct ieee80211_rate *rate,
-                                int rtap_len)
+                                int rtap_len, bool has_fcs)
 {
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_radiotap_header *rthdr;
@@ -134,7 +134,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        }
 
        /* IEEE80211_RADIOTAP_FLAGS */
-       if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
+       if (has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))
                *pos |= IEEE80211_RADIOTAP_F_FCS;
        if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
                *pos |= IEEE80211_RADIOTAP_F_BADFCS;
@@ -294,7 +294,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
        }
 
        /* prepend radiotap information */
-       ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom);
+       ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
+                                        true);
 
        skb_reset_mac_header(skb);
        skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2571,7 +2572,8 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
                goto out_free_skb;
 
        /* prepend radiotap information */
-       ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom);
+       ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
+                                        false);
 
        skb_set_mac_header(skb, 0);
        skb->ip_summed = CHECKSUM_UNNECESSARY;
index 33cd169013781321a813e10ebfb474c9595bd857..c70e176771359b5e9371df1da486b29a157084f7 100644 (file)
@@ -370,7 +370,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
         */
        drv_sw_scan_start(local);
 
-       local->leave_oper_channel_time = 0;
+       local->leave_oper_channel_time = jiffies;
        local->next_scan_state = SCAN_DECISION;
        local->scan_channel_idx = 0;
 
index 782a60198df46977754c8720f101ed8016b928e5..e76facc69e952c9aedb835bbfeedbb7fbea0d5ea 100644 (file)
@@ -1158,7 +1158,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
                tx->sta = rcu_dereference(sdata->u.vlan.sta);
                if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
                        return TX_DROP;
-       } else if (info->flags & IEEE80211_TX_CTL_INJECTED) {
+       } else if (info->flags & IEEE80211_TX_CTL_INJECTED ||
+                  tx->sdata->control_port_protocol == tx->skb->protocol) {
                tx->sta = sta_info_get_bss(sdata, hdr->addr1);
        }
        if (!tx->sta)
index 2555816e778827250e5aec0d33eaa2fa9512addc..00bdb1d9d690b5acb100fe38c2e455a110d8f09b 100644 (file)
@@ -1924,6 +1924,7 @@ protocol_fail:
 control_fail:
        ip_vs_estimator_net_cleanup(net);
 estimator_fail:
+       net->ipvs = NULL;
        return -ENOMEM;
 }
 
@@ -1936,6 +1937,7 @@ static void __net_exit __ip_vs_cleanup(struct net *net)
        ip_vs_control_net_cleanup(net);
        ip_vs_estimator_net_cleanup(net);
        IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
+       net->ipvs = NULL;
 }
 
 static void __net_exit __ip_vs_dev_cleanup(struct net *net)
@@ -1993,10 +1995,18 @@ static int __init ip_vs_init(void)
                goto cleanup_dev;
        }
 
+       ret = ip_vs_register_nl_ioctl();
+       if (ret < 0) {
+               pr_err("can't register netlink/ioctl.\n");
+               goto cleanup_hooks;
+       }
+
        pr_info("ipvs loaded.\n");
 
        return ret;
 
+cleanup_hooks:
+       nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
 cleanup_dev:
        unregister_pernet_device(&ipvs_core_dev_ops);
 cleanup_sub:
@@ -2012,6 +2022,7 @@ exit:
 
 static void __exit ip_vs_cleanup(void)
 {
+       ip_vs_unregister_nl_ioctl();
        nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
        unregister_pernet_device(&ipvs_core_dev_ops);
        unregister_pernet_subsys(&ipvs_core_ops);       /* free ip_vs struct */
index b3afe189af61880464ef6562c568016509957293..f5589987fc80d59a8d1fc5ec1e546d72562521fa 100644 (file)
@@ -3680,7 +3680,7 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net)
        return 0;
 }
 
-void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net)
+void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -3692,7 +3692,7 @@ void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net)
 #else
 
 int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; }
-void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) { }
+void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { }
 
 #endif
 
@@ -3750,21 +3750,10 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
        free_percpu(ipvs->tot_stats.cpustats);
 }
 
-int __init ip_vs_control_init(void)
+int __init ip_vs_register_nl_ioctl(void)
 {
-       int idx;
        int ret;
 
-       EnterFunction(2);
-
-       /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
-       for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++)  {
-               INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
-               INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
-       }
-
-       smp_wmb();      /* Do we really need it now ? */
-
        ret = nf_register_sockopt(&ip_vs_sockopts);
        if (ret) {
                pr_err("cannot register sockopt.\n");
@@ -3776,28 +3765,47 @@ int __init ip_vs_control_init(void)
                pr_err("cannot register Generic Netlink interface.\n");
                goto err_genl;
        }
-
-       ret = register_netdevice_notifier(&ip_vs_dst_notifier);
-       if (ret < 0)
-               goto err_notf;
-
-       LeaveFunction(2);
        return 0;
 
-err_notf:
-       ip_vs_genl_unregister();
 err_genl:
        nf_unregister_sockopt(&ip_vs_sockopts);
 err_sock:
        return ret;
 }
 
+void ip_vs_unregister_nl_ioctl(void)
+{
+       ip_vs_genl_unregister();
+       nf_unregister_sockopt(&ip_vs_sockopts);
+}
+
+int __init ip_vs_control_init(void)
+{
+       int idx;
+       int ret;
+
+       EnterFunction(2);
+
+       /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
+       for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
+               INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
+               INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
+       }
+
+       smp_wmb();      /* Do we really need it now ? */
+
+       ret = register_netdevice_notifier(&ip_vs_dst_notifier);
+       if (ret < 0)
+               return ret;
+
+       LeaveFunction(2);
+       return 0;
+}
+
 
 void ip_vs_control_cleanup(void)
 {
        EnterFunction(2);
        unregister_netdevice_notifier(&ip_vs_dst_notifier);
-       ip_vs_genl_unregister();
-       nf_unregister_sockopt(&ip_vs_sockopts);
        LeaveFunction(2);
 }
index 538d74ee4f68bc18e7bb379d7432388aba305425..e39f693dd3e49b9595ced939bd0531c07acdd159 100644 (file)
@@ -439,6 +439,8 @@ static int __net_init __ip_vs_ftp_init(struct net *net)
        struct ip_vs_app *app;
        struct netns_ipvs *ipvs = net_ipvs(net);
 
+       if (!ipvs)
+               return -ENOENT;
        app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL);
        if (!app)
                return -ENOMEM;
index 0f16283fd05854fccc68fad349c7f29509926252..caa43704e55ead5f5c6c2287e78c818cacb038e4 100644 (file)
@@ -551,6 +551,9 @@ static int __net_init __ip_vs_lblc_init(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
+       if (!ipvs)
+               return -ENOENT;
+
        if (!net_eq(net, &init_net)) {
                ipvs->lblc_ctl_table = kmemdup(vs_vars_table,
                                                sizeof(vs_vars_table),
index eec797f8cce705a1676caeb3c3078053ddcdf523..548bf37aa29e07ebd53eaa760dbcadf844edfa13 100644 (file)
@@ -745,6 +745,9 @@ static int __net_init __ip_vs_lblcr_init(struct net *net)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
+       if (!ipvs)
+               return -ENOENT;
+
        if (!net_eq(net, &init_net)) {
                ipvs->lblcr_ctl_table = kmemdup(vs_vars_table,
                                                sizeof(vs_vars_table),
index f843a88332509edc9ac7ed509cba6d679685664f..ed835e67a07e07598408b130f64fbafd85a33679 100644 (file)
@@ -59,9 +59,6 @@ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
        return 0;
 }
 
-#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP) || \
-    defined(CONFIG_IP_VS_PROTO_SCTP) || defined(CONFIG_IP_VS_PROTO_AH) || \
-    defined(CONFIG_IP_VS_PROTO_ESP)
 /*
  *     register an ipvs protocols netns related data
  */
@@ -81,12 +78,18 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp)
        ipvs->proto_data_table[hash] = pd;
        atomic_set(&pd->appcnt, 0);     /* Init app counter */
 
-       if (pp->init_netns != NULL)
-               pp->init_netns(net, pd);
+       if (pp->init_netns != NULL) {
+               int ret = pp->init_netns(net, pd);
+               if (ret) {
+                       /* unlink an free proto data */
+                       ipvs->proto_data_table[hash] = pd->next;
+                       kfree(pd);
+                       return ret;
+               }
+       }
 
        return 0;
 }
-#endif
 
 /*
  *     unregister an ipvs protocol
@@ -316,22 +319,35 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
  */
 int __net_init ip_vs_protocol_net_init(struct net *net)
 {
+       int i, ret;
+       static struct ip_vs_protocol *protos[] = {
 #ifdef CONFIG_IP_VS_PROTO_TCP
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
+        &ip_vs_protocol_tcp,
 #endif
 #ifdef CONFIG_IP_VS_PROTO_UDP
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_udp);
+       &ip_vs_protocol_udp,
 #endif
 #ifdef CONFIG_IP_VS_PROTO_SCTP
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_sctp);
+       &ip_vs_protocol_sctp,
 #endif
 #ifdef CONFIG_IP_VS_PROTO_AH
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_ah);
+       &ip_vs_protocol_ah,
 #endif
 #ifdef CONFIG_IP_VS_PROTO_ESP
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_esp);
+       &ip_vs_protocol_esp,
 #endif
+       };
+
+       for (i = 0; i < ARRAY_SIZE(protos); i++) {
+               ret = register_ip_vs_proto_netns(net, protos[i]);
+               if (ret < 0)
+                       goto cleanup;
+       }
        return 0;
+
+cleanup:
+       ip_vs_protocol_net_cleanup(net);
+       return ret;
 }
 
 void __net_exit ip_vs_protocol_net_cleanup(struct net *net)
index 1fbf7a2816f5ade317a747737840588d41621bf0..9f3fb751c49154bac37fa4baa84853a2c0dd0c06 100644 (file)
@@ -1090,7 +1090,7 @@ out:
  *   timeouts is netns related now.
  * ---------------------------------------------
  */
-static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -1098,6 +1098,9 @@ static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
        spin_lock_init(&ipvs->sctp_app_lock);
        pd->timeout_table = ip_vs_create_timeout_table((int *)sctp_timeouts,
                                                        sizeof(sctp_timeouts));
+       if (!pd->timeout_table)
+               return -ENOMEM;
+       return 0;
 }
 
 static void __ip_vs_sctp_exit(struct net *net, struct ip_vs_proto_data *pd)
index ef8641f7af8300efae329a3a74cb4325eba1761f..cd609cc62721095baf50475d14e80384089f280a 100644 (file)
@@ -677,7 +677,7 @@ void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp)
  *   timeouts is netns related now.
  * ---------------------------------------------
  */
-static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -685,7 +685,10 @@ static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
        spin_lock_init(&ipvs->tcp_app_lock);
        pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts,
                                                        sizeof(tcp_timeouts));
+       if (!pd->timeout_table)
+               return -ENOMEM;
        pd->tcp_state_table =  tcp_states;
+       return 0;
 }
 
 static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd)
index f4b7262896bbd272fb8d3cff5298455b1deff703..2fedb2dcb3d1f5e831546b59480eceee14e59a84 100644 (file)
@@ -467,7 +467,7 @@ udp_state_transition(struct ip_vs_conn *cp, int direction,
        cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
 }
 
-static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __udp_init(struct net *net, struct ip_vs_proto_data *pd)
 {
        struct netns_ipvs *ipvs = net_ipvs(net);
 
@@ -475,6 +475,9 @@ static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
        spin_lock_init(&ipvs->udp_app_lock);
        pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts,
                                                        sizeof(udp_timeouts));
+       if (!pd->timeout_table)
+               return -ENOMEM;
+       return 0;
 }
 
 static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd)
index cbdb754dbb10d9a88ab4eef9e1ddf4ff8b3362a6..729f157a0efa690cf877dbd9dbb94dd1b09f1be6 100644 (file)
@@ -735,6 +735,7 @@ __nf_conntrack_alloc(struct net *net, u16 zone,
 
 #ifdef CONFIG_NF_CONNTRACK_ZONES
 out_free:
+       atomic_dec(&net->ct.count);
        kmem_cache_free(net->ct.nf_conntrack_cachep, ct);
        return ERR_PTR(-ENOMEM);
 #endif
@@ -1591,7 +1592,7 @@ static int nf_conntrack_init_net(struct net *net)
        return 0;
 
 err_timeout:
-       nf_conntrack_timeout_fini(net);
+       nf_conntrack_ecache_fini(net);
 err_ecache:
        nf_conntrack_tstamp_fini(net);
 err_tstamp:
index 361eade62a09e58e06194fb78d8c6b07333f015a..0d07a1dcf60504758aace258dd0347f06f305797 100644 (file)
@@ -584,8 +584,8 @@ static bool tcp_in_window(const struct nf_conn *ct,
                         * Let's try to use the data from the packet.
                         */
                        sender->td_end = end;
-                       win <<= sender->td_scale;
-                       sender->td_maxwin = (win == 0 ? 1 : win);
+                       swin = win << sender->td_scale;
+                       sender->td_maxwin = (swin == 0 ? 1 : swin);
                        sender->td_maxend = end + sender->td_maxwin;
                        /*
                         * We haven't seen traffic in the other direction yet
index 3eb348bfc4fb11112d24d0c169c580f5e70b04e7..d98c868c148b6cff5f05f555a20547c76ca19f91 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
+#include <linux/atomic.h>
 #include <linux/netlink.h>
 #include <linux/rculist.h>
 #include <linux/slab.h>
@@ -17,7 +18,6 @@
 #include <linux/errno.h>
 #include <net/netlink.h>
 #include <net/sock.h>
-#include <asm/atomic.h>
 
 #include <linux/netfilter.h>
 #include <linux/netfilter/nfnetlink.h>
index 0c8e43810ce363190c2c49477a3490ee6a077191..3746d8b9a47868694be0848fc0d09013a0a5b282 100644 (file)
@@ -150,6 +150,17 @@ err1:
        return ret;
 }
 
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout)
+{
+       typeof(nf_ct_timeout_put_hook) timeout_put;
+
+       timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
+       if (timeout_put)
+               timeout_put(timeout);
+}
+#endif
+
 static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
 {
        struct xt_ct_target_info_v1 *info = par->targinfo;
@@ -158,7 +169,9 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
        struct nf_conn *ct;
        int ret = 0;
        u8 proto;
-
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+       struct ctnl_timeout *timeout;
+#endif
        if (info->flags & ~XT_CT_NOTRACK)
                return -EINVAL;
 
@@ -214,9 +227,8 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
        }
 
 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
-       if (info->timeout) {
+       if (info->timeout[0]) {
                typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
-               struct ctnl_timeout *timeout;
                struct nf_conn_timeout *timeout_ext;
 
                rcu_read_lock();
@@ -245,7 +257,7 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
                                pr_info("Timeout policy `%s' can only be "
                                        "used by L3 protocol number %d\n",
                                        info->timeout, timeout->l3num);
-                               goto err4;
+                               goto err5;
                        }
                        /* Make sure the timeout policy matches any existing
                         * protocol tracker, otherwise default to generic.
@@ -258,13 +270,13 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
                                        "used by L4 protocol number %d\n",
                                        info->timeout,
                                        timeout->l4proto->l4proto);
-                               goto err4;
+                               goto err5;
                        }
                        timeout_ext = nf_ct_timeout_ext_add(ct, timeout,
-                                                           GFP_KERNEL);
+                                                           GFP_ATOMIC);
                        if (timeout_ext == NULL) {
                                ret = -ENOMEM;
-                               goto err4;
+                               goto err5;
                        }
                } else {
                        ret = -ENOENT;
@@ -281,8 +293,12 @@ out:
        info->ct = ct;
        return 0;
 
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+err5:
+       __xt_ct_tg_timeout_put(timeout);
 err4:
        rcu_read_unlock();
+#endif
 err3:
        nf_conntrack_free(ct);
 err2:
index 32bb75324e76d0141c99df87449f3013b5c5a060..faa48f70b7c9b132bfaf3c8ce561982e82c4c7b6 100644 (file)
@@ -829,12 +829,19 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
        return 0;
 }
 
-int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
+static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb)
 {
        int len = skb->len;
 
        skb_queue_tail(&sk->sk_receive_queue, skb);
        sk->sk_data_ready(sk, len);
+       return len;
+}
+
+int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
+{
+       int len = __netlink_sendskb(sk, skb);
+
        sock_put(sk);
        return len;
 }
@@ -957,8 +964,7 @@ static int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb)
        if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
            !test_bit(0, &nlk->state)) {
                skb_set_owner_r(skb, sk);
-               skb_queue_tail(&sk->sk_receive_queue, skb);
-               sk->sk_data_ready(sk, skb->len);
+               __netlink_sendskb(sk, skb);
                return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
        }
        return -1;
@@ -1698,10 +1704,8 @@ static int netlink_dump(struct sock *sk)
 
                if (sk_filter(sk, skb))
                        kfree_skb(skb);
-               else {
-                       skb_queue_tail(&sk->sk_receive_queue, skb);
-                       sk->sk_data_ready(sk, skb->len);
-               }
+               else
+                       __netlink_sendskb(sk, skb);
                return 0;
        }
 
@@ -1715,10 +1719,8 @@ static int netlink_dump(struct sock *sk)
 
        if (sk_filter(sk, skb))
                kfree_skb(skb);
-       else {
-               skb_queue_tail(&sk->sk_receive_queue, skb);
-               sk->sk_data_ready(sk, skb->len);
-       }
+       else
+               __netlink_sendskb(sk, skb);
 
        if (cb->done)
                cb->done(cb);
index 7b76eb7192f37fc50167d39ff6d2a1d7ffc400e4..ef10ffcb4b6ffb5ed79eecdc8005dccc0de34575 100644 (file)
@@ -474,7 +474,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
 
        while (remaining_len > 0) {
 
-               frag_len = min_t(u16, local->remote_miu, remaining_len);
+               frag_len = min_t(size_t, local->remote_miu, remaining_len);
 
                pr_debug("Fragment %zd bytes remaining %zd",
                         frag_len, remaining_len);
@@ -497,7 +497,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
                release_sock(sk);
 
                remaining_len -= frag_len;
-               msg_ptr += len;
+               msg_ptr += frag_len;
        }
 
        kfree(msg_data);
index 9f60008740e32875fb80d64b070cdf7262366650..9726fe684ab8a35ded1f1acb9ae4ea0dbdbe6b12 100644 (file)
@@ -1130,6 +1130,9 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk,
        int flags = msg->msg_flags;
        int err, done;
 
+       if (len > USHRT_MAX)
+               return -EMSGSIZE;
+
        if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|
                                MSG_CMSG_COMPAT)) ||
                        !(msg->msg_flags & MSG_EOR))
index 9b9a85ecc4c79d70c88db78a12e5d54309e28d43..bf5cf69c820a285be318ecb3dab044530f2c8bc2 100644 (file)
@@ -331,23 +331,6 @@ static int __net_init phonet_init_net(struct net *net)
 
 static void __net_exit phonet_exit_net(struct net *net)
 {
-       struct phonet_net *pnn = phonet_pernet(net);
-       struct net_device *dev;
-       unsigned i;
-
-       rtnl_lock();
-       for_each_netdev(net, dev)
-               phonet_device_destroy(dev);
-
-       for (i = 0; i < 64; i++) {
-               dev = pnn->routes.table[i];
-               if (dev) {
-                       rtm_phonet_notify(RTM_DELROUTE, dev, i);
-                       dev_put(dev);
-               }
-       }
-       rtnl_unlock();
-
        proc_net_remove(net, "phonet");
 }
 
@@ -361,7 +344,7 @@ static struct pernet_operations phonet_net_ops = {
 /* Initialize Phonet devices list */
 int __init phonet_device_init(void)
 {
-       int err = register_pernet_device(&phonet_net_ops);
+       int err = register_pernet_subsys(&phonet_net_ops);
        if (err)
                return err;
 
@@ -377,7 +360,7 @@ void phonet_device_exit(void)
 {
        rtnl_unregister_all(PF_PHONET);
        unregister_netdevice_notifier(&phonet_device_notifier);
-       unregister_pernet_device(&phonet_net_ops);
+       unregister_pernet_subsys(&phonet_net_ops);
        proc_net_remove(&init_net, "pnresource");
 }
 
index 1ab8689726ec994644b4342772007a26cbcbba01..906cc05bba638bf9eba0dc70d4f04c06bf540ea6 100644 (file)
@@ -95,11 +95,11 @@ static int rose_set_mac_address(struct net_device *dev, void *addr)
        struct sockaddr *sa = addr;
        int err;
 
-       if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len))
+       if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))
                return 0;
 
        if (dev->flags & IFF_UP) {
-               err = rose_add_loopback_node((rose_address *)dev->dev_addr);
+               err = rose_add_loopback_node((rose_address *)sa->sa_data);
                if (err)
                        return err;
 
index 0b15236be7b609251199a36b5fdd0f9b6075b18f..8179494c269a205467da62e5c97c125a1a6b09c6 100644 (file)
@@ -565,11 +565,8 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
                opt.packets     = q->packetsin;
                opt.bytesin     = q->bytesin;
 
-               if (gred_wred_mode(table)) {
-                       q->vars.qidlestart =
-                               table->tab[table->def]->vars.qidlestart;
-                       q->vars.qavg = table->tab[table->def]->vars.qavg;
-               }
+               if (gred_wred_mode(table))
+                       gred_load_wred_set(table, q);
 
                opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg);
 
index 5da548fa7ae9d46de78f5b75152e1a84b99ca9a7..ebd22966f7480aaacb49ca892c774ac23c477acb 100644 (file)
@@ -408,10 +408,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
                if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
                    (skb->ip_summed == CHECKSUM_PARTIAL &&
-                    skb_checksum_help(skb))) {
-                       sch->qstats.drops++;
-                       return NET_XMIT_DROP;
-               }
+                    skb_checksum_help(skb)))
+                       return qdisc_drop(skb, sch);
 
                skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
        }
index 06b42b7f5a0237c054403c3b695aea26dcae036b..92ba71dfe080125b58bc01cd40e7a2d158c9ab61 100644 (file)
@@ -4133,9 +4133,10 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
 static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
                                  int __user *optlen)
 {
-       if (len < sizeof(struct sctp_event_subscribe))
+       if (len <= 0)
                return -EINVAL;
-       len = sizeof(struct sctp_event_subscribe);
+       if (len > sizeof(struct sctp_event_subscribe))
+               len = sizeof(struct sctp_event_subscribe);
        if (put_user(len, optlen))
                return -EFAULT;
        if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len))
index 484cc6953fc61ebcb049604e5dbdb57a4ffcd385..851edcd6b0982d5a820da29e2145be75bddcff9c 100644 (file)
@@ -811,9 +811,9 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
 
        sock = file->private_data;
 
-       flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
-       if (more)
-               flags |= MSG_MORE;
+       flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
+       /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
+       flags |= more;
 
        return kernel_sendpage(sock, page, offset, size, flags);
 }
index 67972462a543d1bad6326ec214c73bc9dce17d0b..adf2990acebfd2ff7513f2344f0a143c326eb6ef 100644 (file)
@@ -176,16 +176,22 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name)
        return 0;
 }
 
-static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
-                               struct super_block *sb)
+static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
+{
+       if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) ||
+           ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry))
+               return 1;
+       return 0;
+}
+
+static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
+                                  struct super_block *sb)
 {
        struct dentry *dentry;
        int err = 0;
 
        switch (event) {
        case RPC_PIPEFS_MOUNT:
-               if (clnt->cl_program->pipe_dir_name == NULL)
-                       break;
                dentry = rpc_setup_pipedir_sb(sb, clnt,
                                              clnt->cl_program->pipe_dir_name);
                BUG_ON(dentry == NULL);
@@ -208,6 +214,20 @@ static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
        return err;
 }
 
+static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
+                               struct super_block *sb)
+{
+       int error = 0;
+
+       for (;; clnt = clnt->cl_parent) {
+               if (!rpc_clnt_skip_event(clnt, event))
+                       error = __rpc_clnt_handle_event(clnt, event, sb);
+               if (error || clnt == clnt->cl_parent)
+                       break;
+       }
+       return error;
+}
+
 static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
 {
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
@@ -215,10 +235,12 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
 
        spin_lock(&sn->rpc_client_lock);
        list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
-               if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) ||
-                   ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry))
+               if (clnt->cl_program->pipe_dir_name == NULL)
+                       break;
+               if (rpc_clnt_skip_event(clnt, event))
+                       continue;
+               if (atomic_inc_not_zero(&clnt->cl_count) == 0)
                        continue;
-               atomic_inc(&clnt->cl_count);
                spin_unlock(&sn->rpc_client_lock);
                return clnt;
        }
@@ -257,6 +279,14 @@ void rpc_clients_notifier_unregister(void)
        return rpc_pipefs_notifier_unregister(&rpc_clients_block);
 }
 
+static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
+{
+       clnt->cl_nodelen = strlen(nodename);
+       if (clnt->cl_nodelen > UNX_MAXNODENAME)
+               clnt->cl_nodelen = UNX_MAXNODENAME;
+       memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen);
+}
+
 static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
 {
        const struct rpc_program *program = args->program;
@@ -337,10 +367,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
        }
 
        /* save the nodename */
-       clnt->cl_nodelen = strlen(init_utsname()->nodename);
-       if (clnt->cl_nodelen > UNX_MAXNODENAME)
-               clnt->cl_nodelen = UNX_MAXNODENAME;
-       memcpy(clnt->cl_nodename, init_utsname()->nodename, clnt->cl_nodelen);
+       rpc_clnt_set_nodename(clnt, utsname()->nodename);
        rpc_register_client(clnt);
        return clnt;
 
@@ -499,6 +526,7 @@ rpc_clone_client(struct rpc_clnt *clnt)
        err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
        if (err != 0)
                goto out_no_path;
+       rpc_clnt_set_nodename(new, utsname()->nodename);
        if (new->cl_auth)
                atomic_inc(&new->cl_auth->au_count);
        atomic_inc(&clnt->cl_count);
index 0af37fc468181e9a6917c695d8f60dd381734e78..3b62cf2880316bfb9942960e1fc34e39c64f92bf 100644 (file)
@@ -1126,19 +1126,20 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOMEM;
        dprintk("RPC:   sending pipefs MOUNT notification for net %p%s\n", net,
                                                                NET_NAME(net));
+       sn->pipefs_sb = sb;
        err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
                                           RPC_PIPEFS_MOUNT,
                                           sb);
        if (err)
                goto err_depopulate;
        sb->s_fs_info = get_net(net);
-       sn->pipefs_sb = sb;
        return 0;
 
 err_depopulate:
        blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
                                           RPC_PIPEFS_UMOUNT,
                                           sb);
+       sn->pipefs_sb = NULL;
        __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
        return err;
 }
index 8adfc88e793a72308f72012bd30e447cd40dd6bf..3d6498af9adc1a1035005c735ee932de6488bee3 100644 (file)
@@ -75,19 +75,20 @@ static struct pernet_operations sunrpc_net_ops = {
 static int __init
 init_sunrpc(void)
 {
-       int err = register_rpc_pipefs();
+       int err = rpc_init_mempool();
        if (err)
                goto out;
-       err = rpc_init_mempool();
-       if (err)
-               goto out2;
        err = rpcauth_init_module();
        if (err)
-               goto out3;
+               goto out2;
 
        cache_initialize();
 
        err = register_pernet_subsys(&sunrpc_net_ops);
+       if (err)
+               goto out3;
+
+       err = register_rpc_pipefs();
        if (err)
                goto out4;
 #ifdef RPC_DEBUG
@@ -98,11 +99,11 @@ init_sunrpc(void)
        return 0;
 
 out4:
-       rpcauth_remove_module();
+       unregister_pernet_subsys(&sunrpc_net_ops);
 out3:
-       rpc_destroy_mempool();
+       rpcauth_remove_module();
 out2:
-       unregister_rpc_pipefs();
+       rpc_destroy_mempool();
 out:
        return err;
 }
index 39765bcfb472c7299d0bb45dd0c6dc1627fc283c..920cabe0461b30cd7c5ef9d59e0f010a3bfa4297 100644 (file)
 #include "core.h"
 #include "debugfs.h"
 
-static int cfg80211_open_file_generic(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)             \
 static ssize_t name## _read(struct file *file, char __user *userbuf,   \
                            size_t count, loff_t *ppos)                 \
@@ -33,7 +27,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf,  \
                                                                        \
 static const struct file_operations name## _ops = {                    \
        .read = name## _read,                                           \
-       .open = cfg80211_open_file_generic,                             \
+       .open = simple_open,                                            \
        .llseek = generic_file_llseek,                                  \
 };
 
@@ -102,7 +96,7 @@ static ssize_t ht40allow_map_read(struct file *file,
 
 static const struct file_operations ht40allow_map_ops = {
        .read = ht40allow_map_read,
-       .open = cfg80211_open_file_generic,
+       .open = simple_open,
        .llseek = default_llseek,
 };
 
index 4c1eb9472ddb322793f382035b76d760862e0f3f..f432c57af05d03addc5f856bfff8a784c19f19a1 100644 (file)
@@ -1294,6 +1294,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                        goto bad_res;
                }
 
+               if (!netif_running(netdev)) {
+                       result = -ENETDOWN;
+                       goto bad_res;
+               }
+
                nla_for_each_nested(nl_txq_params,
                                    info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
                                    rem_txq_params) {
@@ -2386,7 +2391,9 @@ nla_put_failure:
 }
 
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
-                               int flags, struct net_device *dev,
+                               int flags,
+                               struct cfg80211_registered_device *rdev,
+                               struct net_device *dev,
                                const u8 *mac_addr, struct station_info *sinfo)
 {
        void *hdr;
@@ -2425,12 +2432,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
        if (sinfo->filled & STATION_INFO_PLINK_STATE)
                NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
                            sinfo->plink_state);
-       if (sinfo->filled & STATION_INFO_SIGNAL)
-               NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
-                          sinfo->signal);
-       if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
-               NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
-                          sinfo->signal_avg);
+       switch (rdev->wiphy.signal_type) {
+       case CFG80211_SIGNAL_TYPE_MBM:
+               if (sinfo->filled & STATION_INFO_SIGNAL)
+                       NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+                                  sinfo->signal);
+               if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
+                       NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
+                                  sinfo->signal_avg);
+               break;
+       default:
+               break;
+       }
        if (sinfo->filled & STATION_INFO_TX_BITRATE) {
                if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
                                          NL80211_STA_INFO_TX_BITRATE))
@@ -2523,7 +2536,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
                if (nl80211_send_station(skb,
                                NETLINK_CB(cb->skb).pid,
                                cb->nlh->nlmsg_seq, NLM_F_MULTI,
-                               netdev, mac_addr,
+                               dev, netdev, mac_addr,
                                &sinfo) < 0)
                        goto out;
 
@@ -2568,7 +2581,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
                return -ENOMEM;
 
        if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
-                                dev, mac_addr, &sinfo) < 0) {
+                                rdev, dev, mac_addr, &sinfo) < 0) {
                nlmsg_free(msg);
                return -ENOBUFS;
        }
@@ -6376,7 +6389,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_get_key,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6408,7 +6421,7 @@ static struct genl_ops nl80211_ops[] = {
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
                .doit = nl80211_set_beacon,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6416,7 +6429,7 @@ static struct genl_ops nl80211_ops[] = {
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
                .doit = nl80211_start_ap,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6424,7 +6437,7 @@ static struct genl_ops nl80211_ops[] = {
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
                .doit = nl80211_stop_ap,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6440,7 +6453,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_set_station,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6456,7 +6469,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_del_station,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6489,7 +6502,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_del_mpath,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6497,7 +6510,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_set_bss,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6523,7 +6536,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_get_mesh_config,
                .policy = nl80211_policy,
                /* can be retrieved by unprivileged users */
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6656,7 +6669,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_setdel_pmksa,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6664,7 +6677,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_setdel_pmksa,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6672,7 +6685,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_flush_pmksa,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6832,7 +6845,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_probe_client,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -7596,7 +7609,8 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev,
        if (!msg)
                return;
 
-       if (nl80211_send_station(msg, 0, 0, 0, dev, mac_addr, sinfo) < 0) {
+       if (nl80211_send_station(msg, 0, 0, 0,
+                                rdev, dev, mac_addr, sinfo) < 0) {
                nlmsg_free(msg);
                return;
        }
index 1b7a08df933c79bf4ffe62455747464468c84bdb..957f2562161753fcec3b8789734bc0a36afebb84 100644 (file)
@@ -989,7 +989,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
                        if (rdev->wiphy.software_iftypes & BIT(iftype))
                                continue;
                        for (j = 0; j < c->n_limits; j++) {
-                               if (!(limits[j].types & iftype))
+                               if (!(limits[j].types & BIT(iftype)))
                                        continue;
                                if (limits[j].max < num[iftype])
                                        goto cont;
index 0af7f54e4f617f04c7dbab24e09a6b53fc4c9dd2..af648e08e61b7f279dd99b8e87797148d746dd2a 100644 (file)
@@ -780,8 +780,10 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
                if (cmd == SIOCSIWENCODEEXT) {
                        struct iw_encode_ext *ee = (void *) extra;
 
-                       if (iwp->length < sizeof(*ee) + ee->key_len)
-                               return -EFAULT;
+                       if (iwp->length < sizeof(*ee) + ee->key_len) {
+                               err = -EFAULT;
+                               goto out;
+                       }
                }
        }
 
index de639eeeed506b76b54220e7e7f86ed879af02a1..faea0ec612bfed2932ca5dc25868fe00888a5afc 100755 (executable)
@@ -1869,12 +1869,6 @@ sub process {
                            "No space is necessary after a cast\n" . $hereprev);
                }
 
-               if ($rawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
-                   $prevrawline =~ /^\+[ \t]*$/) {
-                       CHK("BLOCK_COMMENT_STYLE",
-                           "Don't begin block comments with only a /* line, use /* comment...\n" . $hereprev);
-               }
-
 # check for spaces at the beginning of a line.
 # Exceptions:
 #  1) within comments
diff --git a/scripts/coccinelle/api/simple_open.cocci b/scripts/coccinelle/api/simple_open.cocci
new file mode 100644 (file)
index 0000000..05962f7
--- /dev/null
@@ -0,0 +1,70 @@
+/// This removes an open coded simple_open() function
+/// and replaces file operations references to the function
+/// with simple_open() instead.
+///
+// Confidence: High
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+virtual report
+
+@ open depends on patch @
+identifier open_f != simple_open;
+identifier i, f;
+@@
+-int open_f(struct inode *i, struct file *f)
+-{
+(
+-if (i->i_private)
+-f->private_data = i->i_private;
+|
+-f->private_data = i->i_private;
+)
+-return 0;
+-}
+
+@ has_open depends on open @
+identifier fops;
+identifier open.open_f;
+@@
+struct file_operations fops = {
+...,
+-.open = open_f,
++.open = simple_open,
+...
+};
+
+@ openr depends on report @
+identifier open_f != simple_open;
+identifier i, f;
+position p;
+@@
+int open_f@p(struct inode *i, struct file *f)
+{
+(
+if (i->i_private)
+f->private_data = i->i_private;
+|
+f->private_data = i->i_private;
+)
+return 0;
+}
+
+@ has_openr depends on openr @
+identifier fops;
+identifier openr.open_f;
+position p;
+@@
+struct file_operations fops = {
+...,
+.open = open_f@p,
+...
+};
+
+@script:python@
+pf << openr.p;
+ps << has_openr.p;
+@@
+
+coccilib.report.print_report(pf[0],"WARNING opportunity for simple_open, see also structure on line %s"%(ps[0].line))
index 0586085136d1304eebaa43142be468e4a7f40c8c..52577f052bc12d06503aa9d6459eaa578fb0fd4b 100644 (file)
@@ -539,35 +539,6 @@ static struct conf_printer header_printer_cb =
        .print_comment = header_print_comment,
 };
 
-/*
- * Generate the __enabled_CONFIG_* and __enabled_CONFIG_*_MODULE macros for
- * use by the IS_{ENABLED,BUILTIN,MODULE} macros. The _MODULE variant is
- * generated even for booleans so that the IS_ENABLED() macro works.
- */
-static void
-header_print__enabled_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-{
-
-       switch (sym->type) {
-       case S_BOOLEAN:
-       case S_TRISTATE: {
-               fprintf(fp, "#define __enabled_" CONFIG_ "%s %d\n",
-                   sym->name, (*value == 'y'));
-               fprintf(fp, "#define __enabled_" CONFIG_ "%s_MODULE %d\n",
-                   sym->name, (*value == 'm'));
-               break;
-       }
-       default:
-               break;
-       }
-}
-
-static struct conf_printer header__enabled_printer_cb =
-{
-       .print_symbol = header_print__enabled_symbol,
-       .print_comment = header_print_comment,
-};
-
 /*
  * Tristate printer
  *
@@ -949,16 +920,11 @@ int conf_write_autoconf(void)
        conf_write_heading(out_h, &header_printer_cb, NULL);
 
        for_all_symbols(i, sym) {
-               if (!sym->name)
-                       continue;
-
                sym_calc_value(sym);
-
-               conf_write_symbol(out_h, sym, &header__enabled_printer_cb, NULL);
-
-               if (!(sym->flags & SYMBOL_WRITE))
+               if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
                        continue;
 
+               /* write symbol to auto.conf, tristate and header files */
                conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
 
                conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
index 8e730ccc3f2b22d55e7b716cf20298da4e9b7475..44ddaa542db6fbb6612560ac312b65ffca330b4c 100644 (file)
@@ -1100,6 +1100,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
        if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
                return;
 
+       /* We're looking for an object */
+       if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
+               return;
+
        /* All our symbols are of form <prefix>__mod_XXX_device_table. */
        name = strstr(symname, "__mod_");
        if (!name)
index 3f01fd9087308bb84564358101c5761b38368e1c..c4e7d1510f9dfd3136d80e63684b8dc764794950 100644 (file)
@@ -132,8 +132,10 @@ static struct module *new_module(char *modname)
        /* strip trailing .o */
        s = strrchr(p, '.');
        if (s != NULL)
-               if (strcmp(s, ".o") == 0)
+               if (strcmp(s, ".o") == 0) {
                        *s = '\0';
+                       mod->is_dot_o = 1;
+               }
 
        /* add to list */
        mod->name = p;
@@ -587,7 +589,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
        unsigned int crc;
        enum export export;
 
-       if (!is_vmlinux(mod->name) && strncmp(symname, "__ksymtab", 9) == 0)
+       if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
+           strncmp(symname, "__ksymtab", 9) == 0)
                export = export_from_secname(info, get_secindex(info, sym));
        else
                export = export_from_sec(info, get_secindex(info, sym));
index 2031119080dce2ac5d8ca63aeb967f0505cc5f74..51207e4d5f8bcae0add675e31cf579f28763d1d4 100644 (file)
@@ -113,6 +113,7 @@ struct module {
        int has_cleanup;
        struct buffer dev_table_buf;
        char         srcversion[25];
+       int is_dot_o;
 };
 
 struct elf_info {
index 0d6004e20658e27b519874ac01c2499572906175..cf7b12fee573174c8aaf00ee75aa9d21c056d61d 100755 (executable)
@@ -254,6 +254,6 @@ case "$1" in
 esac
 
 # Remove structure forward declarations.
-if [ -n $remove_structs ]; then
+if [ -n "$remove_structs" ]; then
     LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' $1
 fi
index 17a5798c29dae96a19a5804b90512390c1df332c..7a2d372f4885a479bff7c97140b45124950c9e19 100644 (file)
@@ -12,8 +12,8 @@
 BCJ=
 LZMA2OPTS=
 
-case $ARCH in
-       x86|x86_64)     BCJ=--x86 ;;
+case $SRCARCH in
+       x86)            BCJ=--x86 ;;
        powerpc)        BCJ=--powerpc ;;
        ia64)           BCJ=--ia64; LZMA2OPTS=pb=4 ;;
        arm)            BCJ=--arm ;;
index 5ff67776a5ada1f69dd53ad2f88a9c3b3eeb9f44..cc3520d39a78dbc3b8283fa195138ad6786f6071 100644 (file)
@@ -115,23 +115,23 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
 
        if (aa_g_audit_header) {
                audit_log_format(ab, "apparmor=");
-               audit_log_string(ab, aa_audit_type[sa->aad.type]);
+               audit_log_string(ab, aa_audit_type[sa->aad->type]);
        }
 
-       if (sa->aad.op) {
+       if (sa->aad->op) {
                audit_log_format(ab, " operation=");
-               audit_log_string(ab, op_table[sa->aad.op]);
+               audit_log_string(ab, op_table[sa->aad->op]);
        }
 
-       if (sa->aad.info) {
+       if (sa->aad->info) {
                audit_log_format(ab, " info=");
-               audit_log_string(ab, sa->aad.info);
-               if (sa->aad.error)
-                       audit_log_format(ab, " error=%d", sa->aad.error);
+               audit_log_string(ab, sa->aad->info);
+               if (sa->aad->error)
+                       audit_log_format(ab, " error=%d", sa->aad->error);
        }
 
-       if (sa->aad.profile) {
-               struct aa_profile *profile = sa->aad.profile;
+       if (sa->aad->profile) {
+               struct aa_profile *profile = sa->aad->profile;
                pid_t pid;
                rcu_read_lock();
                pid = rcu_dereference(tsk->real_parent)->pid;
@@ -145,9 +145,9 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
                audit_log_untrustedstring(ab, profile->base.hname);
        }
 
-       if (sa->aad.name) {
+       if (sa->aad->name) {
                audit_log_format(ab, " name=");
-               audit_log_untrustedstring(ab, sa->aad.name);
+               audit_log_untrustedstring(ab, sa->aad->name);
        }
 }
 
@@ -159,10 +159,8 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
 void aa_audit_msg(int type, struct common_audit_data *sa,
                  void (*cb) (struct audit_buffer *, void *))
 {
-       sa->aad.type = type;
-       sa->lsm_pre_audit = audit_pre;
-       sa->lsm_post_audit = cb;
-       common_lsm_audit(sa);
+       sa->aad->type = type;
+       common_lsm_audit(sa, audit_pre, cb);
 }
 
 /**
@@ -184,7 +182,7 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
        BUG_ON(!profile);
 
        if (type == AUDIT_APPARMOR_AUTO) {
-               if (likely(!sa->aad.error)) {
+               if (likely(!sa->aad->error)) {
                        if (AUDIT_MODE(profile) != AUDIT_ALL)
                                return 0;
                        type = AUDIT_APPARMOR_AUDIT;
@@ -196,21 +194,21 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
        if (AUDIT_MODE(profile) == AUDIT_QUIET ||
            (type == AUDIT_APPARMOR_DENIED &&
             AUDIT_MODE(profile) == AUDIT_QUIET))
-               return sa->aad.error;
+               return sa->aad->error;
 
        if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
                type = AUDIT_APPARMOR_KILL;
 
        if (!unconfined(profile))
-               sa->aad.profile = profile;
+               sa->aad->profile = profile;
 
        aa_audit_msg(type, sa, cb);
 
-       if (sa->aad.type == AUDIT_APPARMOR_KILL)
+       if (sa->aad->type == AUDIT_APPARMOR_KILL)
                (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
 
-       if (sa->aad.type == AUDIT_APPARMOR_ALLOWED)
-               return complain_error(sa->aad.error);
+       if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
+               return complain_error(sa->aad->error);
 
-       return sa->aad.error;
+       return sa->aad->error;
 }
index 9982c48def4e2a7f237e235548b679d6bdb7935e..088dba3bf7dcbcc9a716c3559842d88819c4ef01 100644 (file)
@@ -64,11 +64,13 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task,
        struct audit_cache *ent;
        int type = AUDIT_APPARMOR_AUTO;
        struct common_audit_data sa;
+       struct apparmor_audit_data aad = {0,};
        COMMON_AUDIT_DATA_INIT(&sa, CAP);
+       sa.aad = &aad;
        sa.tsk = task;
        sa.u.cap = cap;
-       sa.aad.op = OP_CAPABLE;
-       sa.aad.error = error;
+       sa.aad->op = OP_CAPABLE;
+       sa.aad->error = error;
 
        if (likely(!error)) {
                /* test if auditing is being forced */
index 5d176f2530c9820873d57c082ff787c5eca38de5..2f8fcba9ce4be5503bb198304100d450e8f31ff5 100644 (file)
@@ -67,22 +67,22 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
        struct common_audit_data *sa = va;
        uid_t fsuid = current_fsuid();
 
-       if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
+       if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
                audit_log_format(ab, " requested_mask=");
-               audit_file_mask(ab, sa->aad.fs.request);
+               audit_file_mask(ab, sa->aad->fs.request);
        }
-       if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) {
+       if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) {
                audit_log_format(ab, " denied_mask=");
-               audit_file_mask(ab, sa->aad.fs.denied);
+               audit_file_mask(ab, sa->aad->fs.denied);
        }
-       if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
+       if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
                audit_log_format(ab, " fsuid=%d", fsuid);
-               audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid);
+               audit_log_format(ab, " ouid=%d", sa->aad->fs.ouid);
        }
 
-       if (sa->aad.fs.target) {
+       if (sa->aad->fs.target) {
                audit_log_format(ab, " target=");
-               audit_log_untrustedstring(ab, sa->aad.fs.target);
+               audit_log_untrustedstring(ab, sa->aad->fs.target);
        }
 }
 
@@ -107,45 +107,47 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
 {
        int type = AUDIT_APPARMOR_AUTO;
        struct common_audit_data sa;
+       struct apparmor_audit_data aad = {0,};
        COMMON_AUDIT_DATA_INIT(&sa, NONE);
-       sa.aad.op = op,
-       sa.aad.fs.request = request;
-       sa.aad.name = name;
-       sa.aad.fs.target = target;
-       sa.aad.fs.ouid = ouid;
-       sa.aad.info = info;
-       sa.aad.error = error;
-
-       if (likely(!sa.aad.error)) {
+       sa.aad = &aad;
+       aad.op = op,
+       aad.fs.request = request;
+       aad.name = name;
+       aad.fs.target = target;
+       aad.fs.ouid = ouid;
+       aad.info = info;
+       aad.error = error;
+
+       if (likely(!sa.aad->error)) {
                u32 mask = perms->audit;
 
                if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
                        mask = 0xffff;
 
                /* mask off perms that are not being force audited */
-               sa.aad.fs.request &= mask;
+               sa.aad->fs.request &= mask;
 
-               if (likely(!sa.aad.fs.request))
+               if (likely(!sa.aad->fs.request))
                        return 0;
                type = AUDIT_APPARMOR_AUDIT;
        } else {
                /* only report permissions that were denied */
-               sa.aad.fs.request = sa.aad.fs.request & ~perms->allow;
+               sa.aad->fs.request = sa.aad->fs.request & ~perms->allow;
 
-               if (sa.aad.fs.request & perms->kill)
+               if (sa.aad->fs.request & perms->kill)
                        type = AUDIT_APPARMOR_KILL;
 
                /* quiet known rejects, assumes quiet and kill do not overlap */
-               if ((sa.aad.fs.request & perms->quiet) &&
+               if ((sa.aad->fs.request & perms->quiet) &&
                    AUDIT_MODE(profile) != AUDIT_NOQUIET &&
                    AUDIT_MODE(profile) != AUDIT_ALL)
-                       sa.aad.fs.request &= ~perms->quiet;
+                       sa.aad->fs.request &= ~perms->quiet;
 
-               if (!sa.aad.fs.request)
-                       return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
+               if (!sa.aad->fs.request)
+                       return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
        }
 
-       sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow;
+       sa.aad->fs.denied = sa.aad->fs.request & ~perms->allow;
        return aa_audit(type, profile, gfp, &sa, file_audit_cb);
 }
 
index 4ba78c203af1a98f4de541a60db7d7c64b8cac13..3868b1e5d5baa729b8ff0fcfd1d89060b8cf71c5 100644 (file)
@@ -103,7 +103,33 @@ enum aa_ops {
 };
 
 
-/* define a short hand for apparmor_audit_data portion of common_audit_data */
+struct apparmor_audit_data {
+       int error;
+       int op;
+       int type;
+       void *profile;
+       const char *name;
+       const char *info;
+       union {
+               void *target;
+               struct {
+                       long pos;
+                       void *target;
+               } iface;
+               struct {
+                       int rlim;
+                       unsigned long max;
+               } rlim;
+               struct {
+                       const char *target;
+                       u32 request;
+                       u32 denied;
+                       uid_t ouid;
+               } fs;
+       };
+};
+
+/* define a short hand for apparmor_audit_data structure */
 #define aad apparmor_audit_data
 
 void aa_audit_msg(int type, struct common_audit_data *sa,
index 7ee05c6f3c64ff313708a68f288479b2726ff7b6..c3da93a5150de4a077aba32796c4f0fec9caf488 100644 (file)
@@ -26,7 +26,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
 {
        struct common_audit_data *sa = va;
        audit_log_format(ab, " target=");
-       audit_log_untrustedstring(ab, sa->aad.target);
+       audit_log_untrustedstring(ab, sa->aad->target);
 }
 
 /**
@@ -41,10 +41,12 @@ static int aa_audit_ptrace(struct aa_profile *profile,
                           struct aa_profile *target, int error)
 {
        struct common_audit_data sa;
+       struct apparmor_audit_data aad = {0,};
        COMMON_AUDIT_DATA_INIT(&sa, NONE);
-       sa.aad.op = OP_PTRACE;
-       sa.aad.target = target;
-       sa.aad.error = error;
+       sa.aad = &aad;
+       aad.op = OP_PTRACE;
+       aad.target = target;
+       aad.error = error;
 
        return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
                        audit_cb);
index 9516948041adee7bc4c32c7a5e699346b6f5bc0f..e75829ba0ff91f771d37e8dd6f7554748c8a1988 100644 (file)
@@ -65,8 +65,10 @@ void aa_info_message(const char *str)
 {
        if (audit_enabled) {
                struct common_audit_data sa;
+               struct apparmor_audit_data aad = {0,};
                COMMON_AUDIT_DATA_INIT(&sa, NONE);
-               sa.aad.info = str;
+               sa.aad = &aad;
+               aad.info = str;
                aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
        }
        printk(KERN_INFO "AppArmor: %s\n", str);
index 97ce8fae49b3bd063a78fd5d9a6cc3eb80254cf1..ad05d391974dc1b83e67f7297324fc260a9a99da 100644 (file)
@@ -588,10 +588,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
                        error = aa_setprocattr_permipc(args);
                } else {
                        struct common_audit_data sa;
+                       struct apparmor_audit_data aad = {0,};
                        COMMON_AUDIT_DATA_INIT(&sa, NONE);
-                       sa.aad.op = OP_SETPROCATTR;
-                       sa.aad.info = name;
-                       sa.aad.error = -EINVAL;
+                       sa.aad = &aad;
+                       aad.op = OP_SETPROCATTR;
+                       aad.info = name;
+                       aad.error = -EINVAL;
                        return aa_audit(AUDIT_APPARMOR_DENIED,
                                        __aa_current_profile(), GFP_KERNEL,
                                        &sa, NULL);
index 9064143830229eb17cc9a560effd6ebe34c773b1..f1f7506a464d6b45044e5d079eaa1ac8310853fc 100644 (file)
@@ -964,11 +964,13 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
                        int error)
 {
        struct common_audit_data sa;
+       struct apparmor_audit_data aad = {0,};
        COMMON_AUDIT_DATA_INIT(&sa, NONE);
-       sa.aad.op = op;
-       sa.aad.name = name;
-       sa.aad.info = info;
-       sa.aad.error = error;
+       sa.aad = &aad;
+       aad.op = op;
+       aad.name = name;
+       aad.info = info;
+       aad.error = error;
 
        return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
                        &sa, NULL);
index 25fd51edc8dae85e530ffabd1edf74a013f0a32c..deab7c7e8dc065b4f30a01bca3d4e7c5630f1f45 100644 (file)
@@ -70,13 +70,13 @@ struct aa_ext {
 static void audit_cb(struct audit_buffer *ab, void *va)
 {
        struct common_audit_data *sa = va;
-       if (sa->aad.iface.target) {
-               struct aa_profile *name = sa->aad.iface.target;
+       if (sa->aad->iface.target) {
+               struct aa_profile *name = sa->aad->iface.target;
                audit_log_format(ab, " name=");
                audit_log_untrustedstring(ab, name->base.hname);
        }
-       if (sa->aad.iface.pos)
-               audit_log_format(ab, " offset=%ld", sa->aad.iface.pos);
+       if (sa->aad->iface.pos)
+               audit_log_format(ab, " offset=%ld", sa->aad->iface.pos);
 }
 
 /**
@@ -94,13 +94,15 @@ static int audit_iface(struct aa_profile *new, const char *name,
 {
        struct aa_profile *profile = __aa_current_profile();
        struct common_audit_data sa;
+       struct apparmor_audit_data aad = {0,};
        COMMON_AUDIT_DATA_INIT(&sa, NONE);
+       sa.aad = &aad;
        if (e)
-               sa.aad.iface.pos = e->pos - e->start;
-       sa.aad.iface.target = new;
-       sa.aad.name = name;
-       sa.aad.info = info;
-       sa.aad.error = error;
+               aad.iface.pos = e->pos - e->start;
+       aad.iface.target = new;
+       aad.name = name;
+       aad.info = info;
+       aad.error = error;
 
        return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
                        audit_cb);
index 72c25a4f2cfdb94cb80c728f905d21e647972c7a..2fe8613efe33704c668d5f895204e8f05f32fc56 100644 (file)
@@ -34,7 +34,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
        struct common_audit_data *sa = va;
 
        audit_log_format(ab, " rlimit=%s value=%lu",
-                        rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max);
+                        rlim_names[sa->aad->rlim.rlim], sa->aad->rlim.max);
 }
 
 /**
@@ -50,12 +50,14 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource,
                          unsigned long value, int error)
 {
        struct common_audit_data sa;
+       struct apparmor_audit_data aad = {0,};
 
        COMMON_AUDIT_DATA_INIT(&sa, NONE);
-       sa.aad.op = OP_SETRLIMIT,
-       sa.aad.rlim.rlim = resource;
-       sa.aad.rlim.max = value;
-       sa.aad.error = error;
+       sa.aad = &aad;
+       aad.op = OP_SETRLIMIT,
+       aad.rlim.rlim = resource;
+       aad.rlim.max = value;
+       aad.error = error;
        return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
                        audit_cb);
 }
index 0cf4b53480a778ffeacd46149aa785c63db81c07..71a166a05975bfef1ea92f68473dc147063b4a7b 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/securebits.h>
 #include <linux/user_namespace.h>
 #include <linux/binfmts.h>
+#include <linux/personality.h>
 
 /*
  * If a non-root user executes a setuid-root binary in
@@ -505,6 +506,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
        }
 skip:
 
+       /* if we have fs caps, clear dangerous personality flags */
+       if (!cap_issubset(new->cap_permitted, old->cap_permitted))
+               bprm->per_clear |= PER_CLEAR_ON_SETID;
+
+
        /* Don't let someone trace a set[ug]id/setpcap binary with the revised
         * credentials unless they have the appropriate permit
         */
index 8b8f0902f6e57f744a8f50d774b84a617df12f67..90c129b0102f5cbe43129695bde3c3b924b84987 100644 (file)
@@ -49,8 +49,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
        if (ih == NULL)
                return -EINVAL;
 
-       ad->u.net.v4info.saddr = ih->saddr;
-       ad->u.net.v4info.daddr = ih->daddr;
+       ad->u.net->v4info.saddr = ih->saddr;
+       ad->u.net->v4info.daddr = ih->daddr;
 
        if (proto)
                *proto = ih->protocol;
@@ -64,8 +64,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
                if (th == NULL)
                        break;
 
-               ad->u.net.sport = th->source;
-               ad->u.net.dport = th->dest;
+               ad->u.net->sport = th->source;
+               ad->u.net->dport = th->dest;
                break;
        }
        case IPPROTO_UDP: {
@@ -73,8 +73,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
                if (uh == NULL)
                        break;
 
-               ad->u.net.sport = uh->source;
-               ad->u.net.dport = uh->dest;
+               ad->u.net->sport = uh->source;
+               ad->u.net->dport = uh->dest;
                break;
        }
        case IPPROTO_DCCP: {
@@ -82,16 +82,16 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
                if (dh == NULL)
                        break;
 
-               ad->u.net.sport = dh->dccph_sport;
-               ad->u.net.dport = dh->dccph_dport;
+               ad->u.net->sport = dh->dccph_sport;
+               ad->u.net->dport = dh->dccph_dport;
                break;
        }
        case IPPROTO_SCTP: {
                struct sctphdr *sh = sctp_hdr(skb);
                if (sh == NULL)
                        break;
-               ad->u.net.sport = sh->source;
-               ad->u.net.dport = sh->dest;
+               ad->u.net->sport = sh->source;
+               ad->u.net->dport = sh->dest;
                break;
        }
        default:
@@ -119,8 +119,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
        ip6 = ipv6_hdr(skb);
        if (ip6 == NULL)
                return -EINVAL;
-       ad->u.net.v6info.saddr = ip6->saddr;
-       ad->u.net.v6info.daddr = ip6->daddr;
+       ad->u.net->v6info.saddr = ip6->saddr;
+       ad->u.net->v6info.daddr = ip6->daddr;
        ret = 0;
        /* IPv6 can have several extension header before the Transport header
         * skip them */
@@ -140,8 +140,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
                if (th == NULL)
                        break;
 
-               ad->u.net.sport = th->source;
-               ad->u.net.dport = th->dest;
+               ad->u.net->sport = th->source;
+               ad->u.net->dport = th->dest;
                break;
        }
        case IPPROTO_UDP: {
@@ -151,8 +151,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
                if (uh == NULL)
                        break;
 
-               ad->u.net.sport = uh->source;
-               ad->u.net.dport = uh->dest;
+               ad->u.net->sport = uh->source;
+               ad->u.net->dport = uh->dest;
                break;
        }
        case IPPROTO_DCCP: {
@@ -162,8 +162,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
                if (dh == NULL)
                        break;
 
-               ad->u.net.sport = dh->dccph_sport;
-               ad->u.net.dport = dh->dccph_dport;
+               ad->u.net->sport = dh->dccph_sport;
+               ad->u.net->dport = dh->dccph_dport;
                break;
        }
        case IPPROTO_SCTP: {
@@ -172,8 +172,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
                sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
                if (sh == NULL)
                        break;
-               ad->u.net.sport = sh->source;
-               ad->u.net.dport = sh->dest;
+               ad->u.net->sport = sh->source;
+               ad->u.net->dport = sh->dest;
                break;
        }
        default:
@@ -281,8 +281,8 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                }
                break;
        case LSM_AUDIT_DATA_NET:
-               if (a->u.net.sk) {
-                       struct sock *sk = a->u.net.sk;
+               if (a->u.net->sk) {
+                       struct sock *sk = a->u.net->sk;
                        struct unix_sock *u;
                        int len = 0;
                        char *p = NULL;
@@ -330,29 +330,29 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                        }
                }
 
-               switch (a->u.net.family) {
+               switch (a->u.net->family) {
                case AF_INET:
-                       print_ipv4_addr(ab, a->u.net.v4info.saddr,
-                                       a->u.net.sport,
+                       print_ipv4_addr(ab, a->u.net->v4info.saddr,
+                                       a->u.net->sport,
                                        "saddr", "src");
-                       print_ipv4_addr(ab, a->u.net.v4info.daddr,
-                                       a->u.net.dport,
+                       print_ipv4_addr(ab, a->u.net->v4info.daddr,
+                                       a->u.net->dport,
                                        "daddr", "dest");
                        break;
                case AF_INET6:
-                       print_ipv6_addr(ab, &a->u.net.v6info.saddr,
-                                       a->u.net.sport,
+                       print_ipv6_addr(ab, &a->u.net->v6info.saddr,
+                                       a->u.net->sport,
                                        "saddr", "src");
-                       print_ipv6_addr(ab, &a->u.net.v6info.daddr,
-                                       a->u.net.dport,
+                       print_ipv6_addr(ab, &a->u.net->v6info.daddr,
+                                       a->u.net->dport,
                                        "daddr", "dest");
                        break;
                }
-               if (a->u.net.netif > 0) {
+               if (a->u.net->netif > 0) {
                        struct net_device *dev;
 
                        /* NOTE: we always use init's namespace */
-                       dev = dev_get_by_index(&init_net, a->u.net.netif);
+                       dev = dev_get_by_index(&init_net, a->u.net->netif);
                        if (dev) {
                                audit_log_format(ab, " netif=%s", dev->name);
                                dev_put(dev);
@@ -378,11 +378,15 @@ static void dump_common_audit_data(struct audit_buffer *ab,
 /**
  * common_lsm_audit - generic LSM auditing function
  * @a:  auxiliary audit data
+ * @pre_audit: lsm-specific pre-audit callback
+ * @post_audit: lsm-specific post-audit callback
  *
  * setup the audit buffer for common security information
  * uses callback to print LSM specific information
  */
-void common_lsm_audit(struct common_audit_data *a)
+void common_lsm_audit(struct common_audit_data *a,
+       void (*pre_audit)(struct audit_buffer *, void *),
+       void (*post_audit)(struct audit_buffer *, void *))
 {
        struct audit_buffer *ab;
 
@@ -394,13 +398,13 @@ void common_lsm_audit(struct common_audit_data *a)
        if (ab == NULL)
                return;
 
-       if (a->lsm_pre_audit)
-               a->lsm_pre_audit(ab, a);
+       if (pre_audit)
+               pre_audit(ab, a);
 
        dump_common_audit_data(ab, a);
 
-       if (a->lsm_post_audit)
-               a->lsm_post_audit(ab, a);
+       if (post_audit)
+               post_audit(ab, a);
 
        audit_log_end(ab);
 }
index 1a70fa26da72683c4bd3fe343baa83117f5ed285..8ee42b2a5f19d0b93c1d6fe4fbe3cdda3670376c 100644 (file)
@@ -436,9 +436,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
 {
        struct common_audit_data *ad = a;
        audit_log_format(ab, "avc:  %s ",
-                        ad->selinux_audit_data.denied ? "denied" : "granted");
-       avc_dump_av(ab, ad->selinux_audit_data.tclass,
-                       ad->selinux_audit_data.audited);
+                        ad->selinux_audit_data->slad->denied ? "denied" : "granted");
+       avc_dump_av(ab, ad->selinux_audit_data->slad->tclass,
+                       ad->selinux_audit_data->slad->audited);
        audit_log_format(ab, " for ");
 }
 
@@ -452,22 +452,25 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
 {
        struct common_audit_data *ad = a;
        audit_log_format(ab, " ");
-       avc_dump_query(ab, ad->selinux_audit_data.ssid,
-                          ad->selinux_audit_data.tsid,
-                          ad->selinux_audit_data.tclass);
+       avc_dump_query(ab, ad->selinux_audit_data->slad->ssid,
+                          ad->selinux_audit_data->slad->tsid,
+                          ad->selinux_audit_data->slad->tclass);
 }
 
 /* This is the slow part of avc audit with big stack footprint */
 static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
                u32 requested, u32 audited, u32 denied,
-               struct av_decision *avd, struct common_audit_data *a,
+               struct common_audit_data *a,
                unsigned flags)
 {
        struct common_audit_data stack_data;
+       struct selinux_audit_data sad = {0,};
+       struct selinux_late_audit_data slad;
 
        if (!a) {
                a = &stack_data;
                COMMON_AUDIT_DATA_INIT(a, NONE);
+               a->selinux_audit_data = &sad;
        }
 
        /*
@@ -481,15 +484,15 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
            (flags & MAY_NOT_BLOCK))
                return -ECHILD;
 
-       a->selinux_audit_data.tclass = tclass;
-       a->selinux_audit_data.requested = requested;
-       a->selinux_audit_data.ssid = ssid;
-       a->selinux_audit_data.tsid = tsid;
-       a->selinux_audit_data.audited = audited;
-       a->selinux_audit_data.denied = denied;
-       a->lsm_pre_audit = avc_audit_pre_callback;
-       a->lsm_post_audit = avc_audit_post_callback;
-       common_lsm_audit(a);
+       slad.tclass = tclass;
+       slad.requested = requested;
+       slad.ssid = ssid;
+       slad.tsid = tsid;
+       slad.audited = audited;
+       slad.denied = denied;
+
+       a->selinux_audit_data->slad = &slad;
+       common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback);
        return 0;
 }
 
@@ -523,7 +526,7 @@ inline int avc_audit(u32 ssid, u32 tsid,
        if (unlikely(denied)) {
                audited = denied & avd->auditdeny;
                /*
-                * a->selinux_audit_data.auditdeny is TRICKY!  Setting a bit in
+                * a->selinux_audit_data->auditdeny is TRICKY!  Setting a bit in
                 * this field means that ANY denials should NOT be audited if
                 * the policy contains an explicit dontaudit rule for that
                 * permission.  Take notice that this is unrelated to the
@@ -532,15 +535,15 @@ inline int avc_audit(u32 ssid, u32 tsid,
                 *
                 * denied == READ
                 * avd.auditdeny & ACCESS == 0 (not set means explicit rule)
-                * selinux_audit_data.auditdeny & ACCESS == 1
+                * selinux_audit_data->auditdeny & ACCESS == 1
                 *
                 * We will NOT audit the denial even though the denied
                 * permission was READ and the auditdeny checks were for
                 * ACCESS
                 */
                if (a &&
-                   a->selinux_audit_data.auditdeny &&
-                   !(a->selinux_audit_data.auditdeny & avd->auditdeny))
+                   a->selinux_audit_data->auditdeny &&
+                   !(a->selinux_audit_data->auditdeny & avd->auditdeny))
                        audited = 0;
        } else if (result)
                audited = denied = requested;
@@ -551,7 +554,7 @@ inline int avc_audit(u32 ssid, u32 tsid,
 
        return slow_avc_audit(ssid, tsid, tclass,
                requested, audited, denied,
-               avd, a, flags);
+               a, flags);
 }
 
 /**
index 28482f9e15b89101c0a0cf90dfc94d53a6639ee5..d85b793c9321c5866a2f6bd2ce60cb5aaff42e17 100644 (file)
@@ -1420,6 +1420,7 @@ static int cred_has_capability(const struct cred *cred,
                               int cap, int audit)
 {
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        struct av_decision avd;
        u16 sclass;
        u32 sid = cred_sid(cred);
@@ -1427,6 +1428,7 @@ static int cred_has_capability(const struct cred *cred,
        int rc;
 
        COMMON_AUDIT_DATA_INIT(&ad, CAP);
+       ad.selinux_audit_data = &sad;
        ad.tsk = current;
        ad.u.cap = cap;
 
@@ -1492,9 +1494,11 @@ static int inode_has_perm_noadp(const struct cred *cred,
                                unsigned flags)
 {
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
 
        COMMON_AUDIT_DATA_INIT(&ad, INODE);
        ad.u.inode = inode;
+       ad.selinux_audit_data = &sad;
        return inode_has_perm(cred, inode, perms, &ad, flags);
 }
 
@@ -1507,9 +1511,11 @@ static inline int dentry_has_perm(const struct cred *cred,
 {
        struct inode *inode = dentry->d_inode;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
        ad.u.dentry = dentry;
+       ad.selinux_audit_data = &sad;
        return inode_has_perm(cred, inode, av, &ad, 0);
 }
 
@@ -1522,9 +1528,11 @@ static inline int path_has_perm(const struct cred *cred,
 {
        struct inode *inode = path->dentry->d_inode;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
 
        COMMON_AUDIT_DATA_INIT(&ad, PATH);
        ad.u.path = *path;
+       ad.selinux_audit_data = &sad;
        return inode_has_perm(cred, inode, av, &ad, 0);
 }
 
@@ -1543,11 +1551,13 @@ static int file_has_perm(const struct cred *cred,
        struct file_security_struct *fsec = file->f_security;
        struct inode *inode = file->f_path.dentry->d_inode;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = cred_sid(cred);
        int rc;
 
        COMMON_AUDIT_DATA_INIT(&ad, PATH);
        ad.u.path = file->f_path;
+       ad.selinux_audit_data = &sad;
 
        if (sid != fsec->sid) {
                rc = avc_has_perm(sid, fsec->sid,
@@ -1577,6 +1587,7 @@ static int may_create(struct inode *dir,
        struct superblock_security_struct *sbsec;
        u32 sid, newsid;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        int rc;
 
        dsec = dir->i_security;
@@ -1587,6 +1598,7 @@ static int may_create(struct inode *dir,
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
        ad.u.dentry = dentry;
+       ad.selinux_audit_data = &sad;
 
        rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
                          DIR__ADD_NAME | DIR__SEARCH,
@@ -1631,6 +1643,7 @@ static int may_link(struct inode *dir,
 {
        struct inode_security_struct *dsec, *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        u32 av;
        int rc;
@@ -1640,6 +1653,7 @@ static int may_link(struct inode *dir,
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
        ad.u.dentry = dentry;
+       ad.selinux_audit_data = &sad;
 
        av = DIR__SEARCH;
        av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
@@ -1674,6 +1688,7 @@ static inline int may_rename(struct inode *old_dir,
 {
        struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        u32 av;
        int old_is_dir, new_is_dir;
@@ -1685,6 +1700,7 @@ static inline int may_rename(struct inode *old_dir,
        new_dsec = new_dir->i_security;
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.selinux_audit_data = &sad;
 
        ad.u.dentry = old_dentry;
        rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
@@ -1970,6 +1986,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
        struct task_security_struct *new_tsec;
        struct inode_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        struct inode *inode = bprm->file->f_path.dentry->d_inode;
        int rc;
 
@@ -2009,6 +2026,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
        }
 
        COMMON_AUDIT_DATA_INIT(&ad, PATH);
+       ad.selinux_audit_data = &sad;
        ad.u.path = bprm->file->f_path;
 
        if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
@@ -2098,6 +2116,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                                            struct files_struct *files)
 {
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        struct file *file, *devnull = NULL;
        struct tty_struct *tty;
        struct fdtable *fdt;
@@ -2135,6 +2154,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
        /* Revalidate access to inherited open files. */
 
        COMMON_AUDIT_DATA_INIT(&ad, INODE);
+       ad.selinux_audit_data = &sad;
 
        spin_lock(&files->file_lock);
        for (;;) {
@@ -2472,6 +2492,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        int rc;
 
        rc = superblock_doinit(sb, data);
@@ -2483,6 +2504,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
                return 0;
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.selinux_audit_data = &sad;
        ad.u.dentry = sb->s_root;
        return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
 }
@@ -2491,8 +2513,10 @@ static int selinux_sb_statfs(struct dentry *dentry)
 {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.selinux_audit_data = &sad;
        ad.u.dentry = dentry->d_sb->s_root;
        return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
@@ -2656,6 +2680,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
 {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 perms;
        bool from_access;
        unsigned flags = mask & MAY_NOT_BLOCK;
@@ -2668,10 +2693,11 @@ static int selinux_inode_permission(struct inode *inode, int mask)
                return 0;
 
        COMMON_AUDIT_DATA_INIT(&ad, INODE);
+       ad.selinux_audit_data = &sad;
        ad.u.inode = inode;
 
        if (from_access)
-               ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS;
+               ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
 
        perms = file_mask_to_av(inode->i_mode, mask);
 
@@ -2737,6 +2763,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
        struct inode_security_struct *isec = inode->i_security;
        struct superblock_security_struct *sbsec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 newsid, sid = current_sid();
        int rc = 0;
 
@@ -2751,6 +2778,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
                return -EPERM;
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.selinux_audit_data = &sad;
        ad.u.dentry = dentry;
 
        rc = avc_has_perm(sid, isec->sid, isec->sclass,
@@ -3345,10 +3373,12 @@ static int selinux_kernel_module_request(char *kmod_name)
 {
        u32 sid;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
 
        sid = task_sid(current);
 
        COMMON_AUDIT_DATA_INIT(&ad, KMOD);
+       ad.selinux_audit_data = &sad;
        ad.u.kmod_name = kmod_name;
 
        return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
@@ -3487,8 +3517,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
        if (ihlen < sizeof(_iph))
                goto out;
 
-       ad->u.net.v4info.saddr = ih->saddr;
-       ad->u.net.v4info.daddr = ih->daddr;
+       ad->u.net->v4info.saddr = ih->saddr;
+       ad->u.net->v4info.daddr = ih->daddr;
        ret = 0;
 
        if (proto)
@@ -3506,8 +3536,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                if (th == NULL)
                        break;
 
-               ad->u.net.sport = th->source;
-               ad->u.net.dport = th->dest;
+               ad->u.net->sport = th->source;
+               ad->u.net->dport = th->dest;
                break;
        }
 
@@ -3522,8 +3552,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                if (uh == NULL)
                        break;
 
-               ad->u.net.sport = uh->source;
-               ad->u.net.dport = uh->dest;
+               ad->u.net->sport = uh->source;
+               ad->u.net->dport = uh->dest;
                break;
        }
 
@@ -3538,8 +3568,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                if (dh == NULL)
                        break;
 
-               ad->u.net.sport = dh->dccph_sport;
-               ad->u.net.dport = dh->dccph_dport;
+               ad->u.net->sport = dh->dccph_sport;
+               ad->u.net->dport = dh->dccph_dport;
                break;
        }
 
@@ -3566,8 +3596,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
        if (ip6 == NULL)
                goto out;
 
-       ad->u.net.v6info.saddr = ip6->saddr;
-       ad->u.net.v6info.daddr = ip6->daddr;
+       ad->u.net->v6info.saddr = ip6->saddr;
+       ad->u.net->v6info.daddr = ip6->daddr;
        ret = 0;
 
        nexthdr = ip6->nexthdr;
@@ -3587,8 +3617,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
                if (th == NULL)
                        break;
 
-               ad->u.net.sport = th->source;
-               ad->u.net.dport = th->dest;
+               ad->u.net->sport = th->source;
+               ad->u.net->dport = th->dest;
                break;
        }
 
@@ -3599,8 +3629,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
                if (uh == NULL)
                        break;
 
-               ad->u.net.sport = uh->source;
-               ad->u.net.dport = uh->dest;
+               ad->u.net->sport = uh->source;
+               ad->u.net->dport = uh->dest;
                break;
        }
 
@@ -3611,8 +3641,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
                if (dh == NULL)
                        break;
 
-               ad->u.net.sport = dh->dccph_sport;
-               ad->u.net.dport = dh->dccph_dport;
+               ad->u.net->sport = dh->dccph_sport;
+               ad->u.net->dport = dh->dccph_dport;
                break;
        }
 
@@ -3632,13 +3662,13 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
        char *addrp;
        int ret;
 
-       switch (ad->u.net.family) {
+       switch (ad->u.net->family) {
        case PF_INET:
                ret = selinux_parse_skb_ipv4(skb, ad, proto);
                if (ret)
                        goto parse_error;
-               addrp = (char *)(src ? &ad->u.net.v4info.saddr :
-                                      &ad->u.net.v4info.daddr);
+               addrp = (char *)(src ? &ad->u.net->v4info.saddr :
+                                      &ad->u.net->v4info.daddr);
                goto okay;
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -3646,8 +3676,8 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
                ret = selinux_parse_skb_ipv6(skb, ad, proto);
                if (ret)
                        goto parse_error;
-               addrp = (char *)(src ? &ad->u.net.v6info.saddr :
-                                      &ad->u.net.v6info.daddr);
+               addrp = (char *)(src ? &ad->u.net->v6info.saddr :
+                                      &ad->u.net->v6info.daddr);
                goto okay;
 #endif /* IPV6 */
        default:
@@ -3721,13 +3751,17 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
 {
        struct sk_security_struct *sksec = sk->sk_security;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        u32 tsid = task_sid(task);
 
        if (sksec->sid == SECINITSID_KERNEL)
                return 0;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.sk = sk;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->sk = sk;
 
        return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
 }
@@ -3805,6 +3839,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                char *addrp;
                struct sk_security_struct *sksec = sk->sk_security;
                struct common_audit_data ad;
+               struct selinux_audit_data sad = {0,};
+               struct lsm_network_audit net = {0,};
                struct sockaddr_in *addr4 = NULL;
                struct sockaddr_in6 *addr6 = NULL;
                unsigned short snum;
@@ -3831,8 +3867,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                                if (err)
                                        goto out;
                                COMMON_AUDIT_DATA_INIT(&ad, NET);
-                               ad.u.net.sport = htons(snum);
-                               ad.u.net.family = family;
+                               ad.selinux_audit_data = &sad;
+                               ad.u.net = &net;
+                               ad.u.net->sport = htons(snum);
+                               ad.u.net->family = family;
                                err = avc_has_perm(sksec->sid, sid,
                                                   sksec->sclass,
                                                   SOCKET__NAME_BIND, &ad);
@@ -3864,13 +3902,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                        goto out;
 
                COMMON_AUDIT_DATA_INIT(&ad, NET);
-               ad.u.net.sport = htons(snum);
-               ad.u.net.family = family;
+               ad.selinux_audit_data = &sad;
+               ad.u.net = &net;
+               ad.u.net->sport = htons(snum);
+               ad.u.net->family = family;
 
                if (family == PF_INET)
-                       ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
+                       ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
                else
-                       ad.u.net.v6info.saddr = addr6->sin6_addr;
+                       ad.u.net->v6info.saddr = addr6->sin6_addr;
 
                err = avc_has_perm(sksec->sid, sid,
                                   sksec->sclass, node_perm, &ad);
@@ -3897,6 +3937,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
        if (sksec->sclass == SECCLASS_TCP_SOCKET ||
            sksec->sclass == SECCLASS_DCCP_SOCKET) {
                struct common_audit_data ad;
+               struct selinux_audit_data sad = {0,};
+               struct lsm_network_audit net = {0,};
                struct sockaddr_in *addr4 = NULL;
                struct sockaddr_in6 *addr6 = NULL;
                unsigned short snum;
@@ -3922,8 +3964,10 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
                       TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
 
                COMMON_AUDIT_DATA_INIT(&ad, NET);
-               ad.u.net.dport = htons(snum);
-               ad.u.net.family = sk->sk_family;
+               ad.selinux_audit_data = &sad;
+               ad.u.net = &net;
+               ad.u.net->dport = htons(snum);
+               ad.u.net->family = sk->sk_family;
                err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
                if (err)
                        goto out;
@@ -4012,10 +4056,14 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
        struct sk_security_struct *sksec_other = other->sk_security;
        struct sk_security_struct *sksec_new = newsk->sk_security;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        int err;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.sk = other;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->sk = other;
 
        err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
                           sksec_other->sclass,
@@ -4042,9 +4090,13 @@ static int selinux_socket_unix_may_send(struct socket *sock,
        struct sk_security_struct *ssec = sock->sk->sk_security;
        struct sk_security_struct *osec = other->sk->sk_security;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.sk = other->sk;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->sk = other->sk;
 
        return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
                            &ad);
@@ -4080,11 +4132,15 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
        struct sk_security_struct *sksec = sk->sk_security;
        u32 sk_sid = sksec->sid;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        char *addrp;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = skb->skb_iif;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = skb->skb_iif;
+       ad.u.net->family = family;
        err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
        if (err)
                return err;
@@ -4111,6 +4167,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
        u16 family = sk->sk_family;
        u32 sk_sid = sksec->sid;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        char *addrp;
        u8 secmark_active;
        u8 peerlbl_active;
@@ -4135,8 +4193,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                return 0;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = skb->skb_iif;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = skb->skb_iif;
+       ad.u.net->family = family;
        err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
        if (err)
                return err;
@@ -4471,6 +4531,8 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
        char *addrp;
        u32 peer_sid;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        u8 secmark_active;
        u8 netlbl_active;
        u8 peerlbl_active;
@@ -4488,8 +4550,10 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
                return NF_DROP;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = ifindex;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = ifindex;
+       ad.u.net->family = family;
        if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
                return NF_DROP;
 
@@ -4576,6 +4640,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
        struct sock *sk = skb->sk;
        struct sk_security_struct *sksec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        char *addrp;
        u8 proto;
 
@@ -4584,8 +4650,10 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
        sksec = sk->sk_security;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = ifindex;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = ifindex;
+       ad.u.net->family = family;
        if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
                return NF_DROP;
 
@@ -4607,6 +4675,8 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
        u32 peer_sid;
        struct sock *sk;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        char *addrp;
        u8 secmark_active;
        u8 peerlbl_active;
@@ -4653,8 +4723,10 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
        }
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = ifindex;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = ifindex;
+       ad.u.net->family = family;
        if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
                return NF_DROP;
 
@@ -4769,11 +4841,13 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
 
        isec = ipc_perms->security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = ipc_perms->key;
 
        return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
@@ -4794,6 +4868,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
 
@@ -4804,6 +4879,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
        isec = msq->q_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = msq->q_perm.key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4824,11 +4900,13 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
 
        isec = msq->q_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = msq->q_perm.key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4868,6 +4946,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
        struct ipc_security_struct *isec;
        struct msg_security_struct *msec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
 
@@ -4889,6 +4968,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
        }
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = msq->q_perm.key;
 
        /* Can this process write to the queue? */
@@ -4913,6 +4993,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
        struct ipc_security_struct *isec;
        struct msg_security_struct *msec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = task_sid(target);
        int rc;
 
@@ -4920,6 +5001,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
        msec = msg->security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = msq->q_perm.key;
 
        rc = avc_has_perm(sid, isec->sid,
@@ -4935,6 +5017,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
 
@@ -4945,6 +5028,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
        isec = shp->shm_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = shp->shm_perm.key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -4965,11 +5049,13 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
 
        isec = shp->shm_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = shp->shm_perm.key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -5027,6 +5113,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
 
@@ -5037,6 +5124,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
        isec = sma->sem_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = sma->sem_perm.key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@ -5057,11 +5145,13 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
 
        isec = sma->sem_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = sma->sem_perm.key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
index 005a91bcb200d0d12ac6c7727f516743ae330439..1931370233d7b2123dad2947c930c0ecb9722ac5 100644 (file)
@@ -46,6 +46,31 @@ struct avc_cache_stats {
        unsigned int frees;
 };
 
+/*
+ * We only need this data after we have decided to send an audit message.
+ */
+struct selinux_late_audit_data {
+       u32 ssid;
+       u32 tsid;
+       u16 tclass;
+       u32 requested;
+       u32 audited;
+       u32 denied;
+       int result;
+};
+
+/*
+ * We collect this at the beginning or during an selinux security operation
+ */
+struct selinux_audit_data {
+       /*
+        * auditdeny is a bit tricky and unintuitive.  See the
+        * comments in avc.c for it's meaning and usage.
+        */
+       u32 auditdeny;
+       struct selinux_late_audit_data *slad;
+};
+
 /*
  * AVC operations
  */
index 2ad00657b80198f3cd9f8acbd20a5eed31f0f218..4ede719922edbf3b0f89deb1041168a52bf0e5ce 100644 (file)
@@ -185,6 +185,15 @@ struct smack_known {
  */
 #define SMK_NUM_ACCESS_TYPE 5
 
+/* SMACK data */
+struct smack_audit_data {
+       const char *function;
+       char *subject;
+       char *object;
+       char *request;
+       int result;
+};
+
 /*
  * Smack audit data; is empty if CONFIG_AUDIT not set
  * to save some stack
@@ -192,6 +201,7 @@ struct smack_known {
 struct smk_audit_info {
 #ifdef CONFIG_AUDIT
        struct common_audit_data a;
+       struct smack_audit_data sad;
 #endif
 };
 /*
@@ -311,7 +321,16 @@ static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
 {
        memset(a, 0, sizeof(*a));
        a->a.type = type;
-       a->a.smack_audit_data.function = func;
+       a->a.smack_audit_data = &a->sad;
+       a->a.smack_audit_data->function = func;
+}
+
+static inline void smk_ad_init_net(struct smk_audit_info *a, const char *func,
+                                  char type, struct lsm_network_audit *net)
+{
+       smk_ad_init(a, func, type);
+       memset(net, 0, sizeof(*net));
+       a->a.u.net = net;
 }
 
 static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
@@ -337,7 +356,7 @@ static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
 static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
                                            struct sock *sk)
 {
-       a->a.u.net.sk = sk;
+       a->a.u.net->sk = sk;
 }
 
 #else /* no AUDIT */
index cc7cb6edba081acaab825c1e6a93fb078234bcf3..c8115f7308f843969ce60d5b1be16f71166eaebf 100644 (file)
@@ -275,9 +275,9 @@ static inline void smack_str_from_perm(char *string, int access)
 static void smack_log_callback(struct audit_buffer *ab, void *a)
 {
        struct common_audit_data *ad = a;
-       struct smack_audit_data *sad = &ad->smack_audit_data;
+       struct smack_audit_data *sad = ad->smack_audit_data;
        audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
-                        ad->smack_audit_data.function,
+                        ad->smack_audit_data->function,
                         sad->result ? "denied" : "granted");
        audit_log_format(ab, " subject=");
        audit_log_untrustedstring(ab, sad->subject);
@@ -310,19 +310,19 @@ void smack_log(char *subject_label, char *object_label, int request,
        if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
                return;
 
-       if (a->smack_audit_data.function == NULL)
-               a->smack_audit_data.function = "unknown";
+       sad = a->smack_audit_data;
+
+       if (sad->function == NULL)
+               sad->function = "unknown";
 
        /* end preparing the audit data */
-       sad = &a->smack_audit_data;
        smack_str_from_perm(request_buffer, request);
        sad->subject = subject_label;
        sad->object  = object_label;
        sad->request = request_buffer;
        sad->result  = result;
-       a->lsm_pre_audit = smack_log_callback;
 
-       common_lsm_audit(a);
+       common_lsm_audit(a, smack_log_callback, NULL);
 }
 #else /* #ifdef CONFIG_AUDIT */
 void smack_log(char *subject_label, char *object_label, int request,
index cd667b4089a52ace663ce24f86f939c80c21dbbf..45c32f074166b270fe5434cfcc24ffa076f8b7a3 100644 (file)
@@ -1943,13 +1943,15 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
        rcu_read_lock();
        hostsp = smack_host_label(sap);
        if (hostsp != NULL) {
-               sk_lbl = SMACK_UNLABELED_SOCKET;
 #ifdef CONFIG_AUDIT
-               smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
-               ad.a.u.net.family = sap->sin_family;
-               ad.a.u.net.dport = sap->sin_port;
-               ad.a.u.net.v4info.daddr = sap->sin_addr.s_addr;
+               struct lsm_network_audit net;
+
+               smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+               ad.a.u.net->family = sap->sin_family;
+               ad.a.u.net->dport = sap->sin_port;
+               ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
 #endif
+               sk_lbl = SMACK_UNLABELED_SOCKET;
                rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad);
        } else {
                sk_lbl = SMACK_CIPSO_SOCKET;
@@ -2810,8 +2812,12 @@ static int smack_unix_stream_connect(struct sock *sock,
        struct smk_audit_info ad;
        int rc = 0;
 
-       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+#ifdef CONFIG_AUDIT
+       struct lsm_network_audit net;
+
+       smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
        smk_ad_setfield_u_net_sk(&ad, other);
+#endif
 
        if (!capable(CAP_MAC_OVERRIDE))
                rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
@@ -2842,8 +2848,12 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
        struct smk_audit_info ad;
        int rc = 0;
 
-       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+#ifdef CONFIG_AUDIT
+       struct lsm_network_audit net;
+
+       smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
        smk_ad_setfield_u_net_sk(&ad, other->sk);
+#endif
 
        if (!capable(CAP_MAC_OVERRIDE))
                rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
@@ -2990,6 +3000,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
        char *csp;
        int rc;
        struct smk_audit_info ad;
+#ifdef CONFIG_AUDIT
+       struct lsm_network_audit net;
+#endif
        if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
                return 0;
 
@@ -3007,9 +3020,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
        netlbl_secattr_destroy(&secattr);
 
 #ifdef CONFIG_AUDIT
-       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
-       ad.a.u.net.family = sk->sk_family;
-       ad.a.u.net.netif = skb->skb_iif;
+       smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+       ad.a.u.net->family = sk->sk_family;
+       ad.a.u.net->netif = skb->skb_iif;
        ipv4_skb_to_auditdata(skb, &ad.a, NULL);
 #endif
        /*
@@ -3152,6 +3165,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
        char *sp;
        int rc;
        struct smk_audit_info ad;
+#ifdef CONFIG_AUDIT
+       struct lsm_network_audit net;
+#endif
 
        /* handle mapped IPv4 packets arriving via IPv6 sockets */
        if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
@@ -3166,9 +3182,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
        netlbl_secattr_destroy(&secattr);
 
 #ifdef CONFIG_AUDIT
-       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
-       ad.a.u.net.family = family;
-       ad.a.u.net.netif = skb->skb_iif;
+       smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+       ad.a.u.net->family = family;
+       ad.a.u.net->netif = skb->skb_iif;
        ipv4_skb_to_auditdata(skb, &ad.a, NULL);
 #endif
        /*
@@ -3624,8 +3640,38 @@ struct security_operations smack_ops = {
 };
 
 
-static __init void init_smack_know_list(void)
+static __init void init_smack_known_list(void)
 {
+       /*
+        * Initialize CIPSO locks
+        */
+       spin_lock_init(&smack_known_huh.smk_cipsolock);
+       spin_lock_init(&smack_known_hat.smk_cipsolock);
+       spin_lock_init(&smack_known_star.smk_cipsolock);
+       spin_lock_init(&smack_known_floor.smk_cipsolock);
+       spin_lock_init(&smack_known_invalid.smk_cipsolock);
+       spin_lock_init(&smack_known_web.smk_cipsolock);
+       /*
+        * Initialize rule list locks
+        */
+       mutex_init(&smack_known_huh.smk_rules_lock);
+       mutex_init(&smack_known_hat.smk_rules_lock);
+       mutex_init(&smack_known_floor.smk_rules_lock);
+       mutex_init(&smack_known_star.smk_rules_lock);
+       mutex_init(&smack_known_invalid.smk_rules_lock);
+       mutex_init(&smack_known_web.smk_rules_lock);
+       /*
+        * Initialize rule lists
+        */
+       INIT_LIST_HEAD(&smack_known_huh.smk_rules);
+       INIT_LIST_HEAD(&smack_known_hat.smk_rules);
+       INIT_LIST_HEAD(&smack_known_star.smk_rules);
+       INIT_LIST_HEAD(&smack_known_floor.smk_rules);
+       INIT_LIST_HEAD(&smack_known_invalid.smk_rules);
+       INIT_LIST_HEAD(&smack_known_web.smk_rules);
+       /*
+        * Create the known labels list
+        */
        list_add(&smack_known_huh.list, &smack_known_list);
        list_add(&smack_known_hat.list, &smack_known_list);
        list_add(&smack_known_star.list, &smack_known_list);
@@ -3660,16 +3706,8 @@ static __init int smack_init(void)
        cred = (struct cred *) current->cred;
        cred->security = tsp;
 
-       /* initialize the smack_know_list */
-       init_smack_know_list();
-       /*
-        * Initialize locks
-        */
-       spin_lock_init(&smack_known_huh.smk_cipsolock);
-       spin_lock_init(&smack_known_hat.smk_cipsolock);
-       spin_lock_init(&smack_known_star.smk_cipsolock);
-       spin_lock_init(&smack_known_floor.smk_cipsolock);
-       spin_lock_init(&smack_known_invalid.smk_cipsolock);
+       /* initialize the smack_known_list */
+       init_smack_known_list();
 
        /*
         * Register with LSM
index 5c32f36ff70618dfb08e3040c94060238dfa44da..038811cb7e625eb48e331c351d079232248dfb83 100644 (file)
@@ -1614,20 +1614,6 @@ static int __init init_smk_fs(void)
        smk_cipso_doi();
        smk_unlbl_ambient(NULL);
 
-       mutex_init(&smack_known_floor.smk_rules_lock);
-       mutex_init(&smack_known_hat.smk_rules_lock);
-       mutex_init(&smack_known_huh.smk_rules_lock);
-       mutex_init(&smack_known_invalid.smk_rules_lock);
-       mutex_init(&smack_known_star.smk_rules_lock);
-       mutex_init(&smack_known_web.smk_rules_lock);
-
-       INIT_LIST_HEAD(&smack_known_floor.smk_rules);
-       INIT_LIST_HEAD(&smack_known_hat.smk_rules);
-       INIT_LIST_HEAD(&smack_known_huh.smk_rules);
-       INIT_LIST_HEAD(&smack_known_invalid.smk_rules);
-       INIT_LIST_HEAD(&smack_known_star.smk_rules);
-       INIT_LIST_HEAD(&smack_known_web.smk_rules);
-
        return err;
 }
 
index 88168044375f9d7fba0b41d7567ee30c263e698e..5ca0939e4223b6104893fd77ccb3e1f5f982bd6c 100644 (file)
@@ -2,8 +2,8 @@
 
 config SND_TEA575X
        tristate
-       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2
-       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2
+       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO
+       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO
 
 menuconfig SND_PCI
        bool "PCI sound devices"
index 6508e8b790bb16076d3539261db7df43032438e4..59d8efaa17e96eec921774fad61fd149884f2241 100644 (file)
@@ -57,7 +57,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_TPA6130A2 if I2C
        select SND_SOC_TLV320DAC33 if I2C
        select SND_SOC_TWL4030 if TWL4030_CORE
-       select SND_SOC_TWL6040 if TWL4030_CORE
+       select SND_SOC_TWL6040 if TWL6040_CORE
        select SND_SOC_UDA134X
        select SND_SOC_UDA1380 if I2C
        select SND_SOC_WL1273 if MFD_WL1273_CORE
@@ -276,7 +276,6 @@ config SND_SOC_TWL4030
        tristate
 
 config SND_SOC_TWL6040
-       select TWL6040_CORE
        tristate
 
 config SND_SOC_UDA134X
index 2d8c6b825e57b9ecd17253c5de57432260ecdaab..dc7509b9d53aa27f4580c923bfe81b2baa7fbff6 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/pm.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/i2c/twl.h>
 #include <linux/mfd/twl6040.h>
 
 #include <sound/core.h>
@@ -1528,7 +1527,7 @@ static int twl6040_resume(struct snd_soc_codec *codec)
 static int twl6040_probe(struct snd_soc_codec *codec)
 {
        struct twl6040_data *priv;
-       struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev);
+       struct twl6040_codec_data *pdata = dev_get_platdata(codec->dev);
        struct platform_device *pdev = container_of(codec->dev,
                                                   struct platform_device, dev);
        int ret = 0;
index afbabf427f27dcb72b01e9be5a96dc0c8540176e..3fea5a15ffe8c6c64e6d86b9587f7cf776f4fedd 100644 (file)
@@ -58,9 +58,9 @@ static int mpc8610_hpcd_machine_probe(struct snd_soc_card *card)
 {
        struct mpc8610_hpcd_data *machine_data =
                container_of(card, struct mpc8610_hpcd_data, card);
-       struct ccsr_guts_86xx __iomem *guts;
+       struct ccsr_guts __iomem *guts;
 
-       guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
        if (!guts) {
                dev_err(card->dev, "could not map global utilities\n");
                return -ENOMEM;
@@ -142,9 +142,9 @@ static int mpc8610_hpcd_machine_remove(struct snd_soc_card *card)
 {
        struct mpc8610_hpcd_data *machine_data =
                container_of(card, struct mpc8610_hpcd_data, card);
-       struct ccsr_guts_86xx __iomem *guts;
+       struct ccsr_guts __iomem *guts;
 
-       guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
        if (!guts) {
                dev_err(card->dev, "could not map global utilities\n");
                return -ENOMEM;
index 46623405a2ce29ea00ae80080a4c88edc0a9e37b..982a1c94498344af320b3ce18798f24215474a9a 100644 (file)
@@ -46,7 +46,7 @@
  * ch: The channel on the DMA controller (0, 1, 2, or 3)
  * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
  */
-static inline void guts_set_dmuxcr(struct ccsr_guts_85xx __iomem *guts,
+static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts,
        unsigned int co, unsigned int ch, unsigned int device)
 {
        unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
@@ -90,9 +90,9 @@ static int p1022_ds_machine_probe(struct snd_soc_card *card)
 {
        struct machine_data *mdata =
                container_of(card, struct machine_data, card);
-       struct ccsr_guts_85xx __iomem *guts;
+       struct ccsr_guts __iomem *guts;
 
-       guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
        if (!guts) {
                dev_err(card->dev, "could not map global utilities\n");
                return -ENOMEM;
@@ -164,9 +164,9 @@ static int p1022_ds_machine_remove(struct snd_soc_card *card)
 {
        struct machine_data *mdata =
                container_of(card, struct machine_data, card);
-       struct ccsr_guts_85xx __iomem *guts;
+       struct ccsr_guts __iomem *guts;
 
-       guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
        if (!guts) {
                dev_err(card->dev, "could not map global utilities\n");
                return -ENOMEM;
index 0fe66c3dde1225fcabb51ef58d227bda21b76bc2..f23700359c672372f84a58df8701176b57e6d475 100644 (file)
@@ -40,12 +40,6 @@ static void __iomem *audmux_base;
 #ifdef CONFIG_DEBUG_FS
 static struct dentry *audmux_debugfs_root;
 
-static int audmux_open_file(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 /* There is an annoying discontinuity in the SSI numbering with regard
  * to the Linux number of the devices */
 static const char *audmux_port_string(int port)
@@ -145,7 +139,7 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
 }
 
 static const struct file_operations audmux_debugfs_fops = {
-       .open = audmux_open_file,
+       .open = simple_open,
        .read = audmux_read_file,
        .llseek = default_llseek,
 };
index e00dd0b1139ca17144048a41148fb2a656b2db7c..deafbfaacdbf13644d72009ddeadd18c5eb81eea 100644 (file)
@@ -97,7 +97,7 @@ config SND_OMAP_SOC_SDP3430
 
 config SND_OMAP_SOC_OMAP_ABE_TWL6040
        tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
-       depends on TWL4030_CORE && SND_OMAP_SOC && ARCH_OMAP4
+       depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4
        select SND_OMAP_SOC_DMIC
        select SND_OMAP_SOC_MCPDM
        select SND_SOC_TWL6040
index b390f00b4e9946a1b3526048de0e608035ff569f..c88d9741b9e7942e60ba17e3d98231136b607dc9 100644 (file)
@@ -201,12 +201,6 @@ static ssize_t pmdown_time_set(struct device *dev,
 static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set);
 
 #ifdef CONFIG_DEBUG_FS
-static int codec_reg_open_file(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
                                   size_t count, loff_t *ppos)
 {
@@ -264,7 +258,7 @@ static ssize_t codec_reg_write_file(struct file *file,
 }
 
 static const struct file_operations codec_reg_fops = {
-       .open = codec_reg_open_file,
+       .open = simple_open,
        .read = codec_reg_read_file,
        .write = codec_reg_write_file,
        .llseek = default_llseek,
index dc7dbfe61cd0d704fbcb4f3e9b130657c87c568d..1bb6d4a63cd8630854ae2b82f47a70057cdd753a 100644 (file)
@@ -1546,12 +1546,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 }
 
 #ifdef CONFIG_DEBUG_FS
-static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t dapm_widget_power_read_file(struct file *file,
                                           char __user *user_buf,
                                           size_t count, loff_t *ppos)
@@ -1615,17 +1609,11 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 }
 
 static const struct file_operations dapm_widget_power_fops = {
-       .open = dapm_widget_power_open_file,
+       .open = simple_open,
        .read = dapm_widget_power_read_file,
        .llseek = default_llseek,
 };
 
-static int dapm_bias_open_file(struct inode *inode, struct file *file)
-{
-       file->private_data = inode->i_private;
-       return 0;
-}
-
 static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
                                   size_t count, loff_t *ppos)
 {
@@ -1656,7 +1644,7 @@ static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
 }
 
 static const struct file_operations dapm_bias_fops = {
-       .open = dapm_bias_open_file,
+       .open = simple_open,
        .read = dapm_bias_read_file,
        .llseek = default_llseek,
 };
index 416684be0ad308a6df2a69d22f41409de05f7466..26b823b61aa175f2f0d8a475e6574a8615ae0e32 100644 (file)
@@ -19,3 +19,5 @@ TAGS
 cscope*
 config.mak
 config.mak.autogen
+*-bison.*
+*-flex.*
index 820371f10d1b1b96e1be9332d454f6ee053aaf34..9bf3fc759344031d05cb915c97d770cddef5a756 100644 (file)
@@ -234,24 +234,23 @@ endif
 
 export PERL_PATH
 
-FLEX = $(CROSS_COMPILE)flex
-BISON= $(CROSS_COMPILE)bison
+FLEX = flex
+BISON= bison
 
-event-parser:
-       $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c
+$(OUTPUT)util/parse-events-flex.c: util/parse-events.l
        $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
 
-$(OUTPUT)util/parse-events-flex.c: event-parser
-$(OUTPUT)util/parse-events-bison.c: event-parser
+$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
+       $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c
 
-pmu-parser:
-       $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c
+$(OUTPUT)util/pmu-flex.c: util/pmu.l
        $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
 
-$(OUTPUT)util/pmu-flex.c: pmu-parser
-$(OUTPUT)util/pmu-bison.c: pmu-parser
+$(OUTPUT)util/pmu-bison.c: util/pmu.y
+       $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c
 
-$(OUTPUT)util/parse-events.o: event-parser pmu-parser
+$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
+$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
 
 LIB_FILE=$(OUTPUT)libperf.a
 
@@ -527,7 +526,7 @@ else
 endif
 
 ifdef NO_GTK2
-       BASIC_CFLAGS += -DNO_GTK2
+       BASIC_CFLAGS += -DNO_GTK2_SUPPORT
 else
        FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0)
        ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
@@ -852,8 +851,6 @@ help:
        @echo '  html           - make html documentation'
        @echo '  info           - make GNU info documentation (access with info <foo>)'
        @echo '  pdf            - make pdf documentation'
-       @echo '  event-parser   - make event parser code'
-       @echo '  pmu-parser     - make pmu format parser code'
        @echo '  TAGS           - use etags to make tag information for source browsing'
        @echo '  tags           - use ctags to make tag information for source browsing'
        @echo '  cscope - use cscope to make interactive browsing database'
index 2e317438980b4767bbca4fdc3512cbd55d4ad1d2..cdae9b2db1cc0ed270e536e6c3b368a353cd780a 100644 (file)
@@ -374,16 +374,23 @@ static int __cmd_report(struct perf_report *rep)
            (kernel_map->dso->hit &&
             (kernel_kmap->ref_reloc_sym == NULL ||
              kernel_kmap->ref_reloc_sym->addr == 0))) {
-               const struct dso *kdso = kernel_map->dso;
+               const char *desc =
+                   "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
+                   "can't be resolved.";
+
+               if (kernel_map) {
+                       const struct dso *kdso = kernel_map->dso;
+                       if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) {
+                               desc = "If some relocation was applied (e.g. "
+                                      "kexec) symbols may be misresolved.";
+                       }
+               }
 
                ui__warning(
 "Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
 "Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
 "Samples in kernel modules can't be resolved as well.\n\n",
-                           RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION]) ?
-"As no suitable kallsyms nor vmlinux was found, kernel samples\n"
-"can't be resolved." :
-"If some relocation was applied (e.g. kexec) symbols may be misresolved.");
+               desc);
        }
 
        if (dump_trace) {
index fb8b5f83b4a0ae77736fbffe6a6736d56813eed6..1cad3af4bf4c9ff0f1813ba1cb826f18d3993a42 100644 (file)
@@ -17,6 +17,7 @@
 #include "util/debug.h"
 
 #include <sys/prctl.h>
+#include <sys/resource.h>
 
 #include <semaphore.h>
 #include <pthread.h>
index 1c5b9801ac6115547039599ff1424048efefd0e7..223ffdcc0fd8a730079f09205c45ecb4fbf5d341 100644 (file)
@@ -851,6 +851,28 @@ static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
        return test__checkevent_symbolic_name(evlist);
 }
 
+static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = list_entry(evlist->entries.next,
+                                             struct perf_evsel, node);
+
+       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
+
+       return test__checkevent_symbolic_name(evlist);
+}
+
+static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = list_entry(evlist->entries.next,
+                                             struct perf_evsel, node);
+
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
+       TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+
+       return test__checkevent_symbolic_name(evlist);
+}
+
 static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -1091,6 +1113,14 @@ static struct test__event_st {
                .name  = "r1,syscalls:sys_enter_open:k,1:1:hp",
                .check = test__checkevent_list,
        },
+       {
+               .name  = "instructions:G",
+               .check = test__checkevent_exclude_host_modifier,
+       },
+       {
+               .name  = "instructions:H",
+               .check = test__checkevent_exclude_guest_modifier,
+       },
 };
 
 #define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
index e3c63aef8efc6a334728ee9864c8243415c478be..8ef59f8262bb37a28c2e83724dbe62b88df349e7 100644 (file)
@@ -42,6 +42,7 @@
 #include "util/debug.h"
 
 #include <assert.h>
+#include <elf.h>
 #include <fcntl.h>
 
 #include <stdio.h>
@@ -59,6 +60,7 @@
 #include <sys/prctl.h>
 #include <sys/wait.h>
 #include <sys/uio.h>
+#include <sys/utsname.h>
 #include <sys/mman.h>
 
 #include <linux/unistd.h>
@@ -162,12 +164,40 @@ static void __zero_source_counters(struct hist_entry *he)
        symbol__annotate_zero_histograms(sym);
 }
 
+static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
+{
+       struct utsname uts;
+       int err = uname(&uts);
+
+       ui__warning("Out of bounds address found:\n\n"
+                   "Addr:   %" PRIx64 "\n"
+                   "DSO:    %s %c\n"
+                   "Map:    %" PRIx64 "-%" PRIx64 "\n"
+                   "Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n"
+                   "Arch:   %s\n"
+                   "Kernel: %s\n"
+                   "Tools:  %s\n\n"
+                   "Not all samples will be on the annotation output.\n\n"
+                   "Please report to linux-kernel@vger.kernel.org\n",
+                   ip, map->dso->long_name, dso__symtab_origin(map->dso),
+                   map->start, map->end, sym->start, sym->end,
+                   sym->binding == STB_GLOBAL ? 'g' :
+                   sym->binding == STB_LOCAL  ? 'l' : 'w', sym->name,
+                   err ? "[unknown]" : uts.machine,
+                   err ? "[unknown]" : uts.release, perf_version_string);
+       if (use_browser <= 0)
+               sleep(5);
+       
+       map->erange_warned = true;
+}
+
 static void perf_top__record_precise_ip(struct perf_top *top,
                                        struct hist_entry *he,
                                        int counter, u64 ip)
 {
        struct annotation *notes;
        struct symbol *sym;
+       int err;
 
        if (he == NULL || he->ms.sym == NULL ||
            ((top->sym_filter_entry == NULL ||
@@ -189,9 +219,12 @@ static void perf_top__record_precise_ip(struct perf_top *top,
        }
 
        ip = he->ms.map->map_ip(he->ms.map, ip);
-       symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
+       err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
 
        pthread_mutex_unlock(&notes->lock);
+
+       if (err == -ERANGE && !he->ms.map->erange_warned)
+               ui__warn_map_erange(he->ms.map, sym, ip);
 }
 
 static void perf_top__show_details(struct perf_top *top)
@@ -615,6 +648,7 @@ process_hotkey:
 
 /* Tag samples to be skipped. */
 static const char *skip_symbols[] = {
+       "intel_idle",
        "default_idle",
        "native_safe_halt",
        "cpu_idle",
index 677e59d62a8dc3ae0475ab31d8c78acaeca50e51..95b6f8b6177a98e45bc295bf4096b753aab70696 100644 (file)
@@ -29,13 +29,14 @@ if [ ! -s $BUILDIDS ] ; then
 fi
 
 MANIFEST=$(mktemp /tmp/perf-archive-manifest.XXXXXX)
+PERF_BUILDID_LINKDIR=$(readlink -f $PERF_BUILDID_DIR)/
 
 cut -d ' ' -f 1 $BUILDIDS | \
 while read build_id ; do
        linkname=$PERF_BUILDID_DIR.build-id/${build_id:0:2}/${build_id:2}
        filename=$(readlink -f $linkname)
        echo ${linkname#$PERF_BUILDID_DIR} >> $MANIFEST
-       echo ${filename#$PERF_BUILDID_DIR} >> $MANIFEST
+       echo ${filename#$PERF_BUILDID_LINKDIR} >> $MANIFEST
 done
 
 tar cfj $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST
index 199f69ec656f7a77c5c490e2f1195c9e09226e98..08c6d138a655c09398f05c6b1c4affdf1cb0ec56 100644 (file)
@@ -64,8 +64,8 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 
        pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
 
-       if (addr > sym->end)
-               return 0;
+       if (addr < sym->start || addr > sym->end)
+               return -ERANGE;
 
        offset = addr - sym->start;
        h = annotation__histogram(notes, evidx);
@@ -561,16 +561,12 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
 {
        struct annotation *notes = symbol__annotation(sym);
        struct sym_hist *h = annotation__histogram(notes, evidx);
-       struct objdump_line *pos;
-       int len = sym->end - sym->start;
+       int len = sym->end - sym->start, offset;
 
        h->sum = 0;
-
-       list_for_each_entry(pos, &notes->src->source, node) {
-               if (pos->offset != -1 && pos->offset < len) {
-                       h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
-                       h->sum += h->addr[pos->offset];
-               }
+       for (offset = 0; offset < len; ++offset) {
+               h->addr[offset] = h->addr[offset] * 7 / 8;
+               h->sum += h->addr[offset];
        }
 }
 
index 2ec4b60aff6c1efa5929c53e3c572b1d6504cfbd..9f6d630d53161e6f314e2efd51a90c3cb329521e 100644 (file)
@@ -256,6 +256,18 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
                if (!cmp) {
                        he->period += period;
                        ++he->nr_events;
+
+                       /* If the map of an existing hist_entry has
+                        * become out-of-date due to an exec() or
+                        * similar, update it.  Otherwise we will
+                        * mis-adjust symbol addresses when computing
+                        * the history counter to increment.
+                        */
+                       if (he->ms.map != entry->ms.map) {
+                               he->ms.map = entry->ms.map;
+                               if (he->ms.map)
+                                       he->ms.map->referenced = true;
+                       }
                        goto out;
                }
 
index dea6d1c1a95471018cdde36d0a4c23e20c8f64a1..35ae56864e4f59625369941886b196438f107c99 100644 (file)
@@ -38,6 +38,7 @@ void map__init(struct map *self, enum map_type type,
        RB_CLEAR_NODE(&self->rb_node);
        self->groups   = NULL;
        self->referenced = false;
+       self->erange_warned = false;
 }
 
 struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
index b100c20b7f94f653448eaafcfb70e61e314f9e22..81371bad4ef0e43e1121b5b8c4367fe4d6b212d8 100644 (file)
@@ -33,6 +33,7 @@ struct map {
        u64                     end;
        u8 /* enum map_type */  type;
        bool                    referenced;
+       bool                    erange_warned;
        u32                     priv;
        u64                     pgoff;
 
index 05d766e3ecb571732e7ce873e24c22bac391845c..1fcf1bbc5458e4a8d626f671a6455348a2225f1f 100644 (file)
@@ -54,7 +54,7 @@ num_dec               [0-9]+
 num_hex                0x[a-fA-F0-9]+
 num_raw_hex    [a-fA-F0-9]+
 name           [a-zA-Z_*?][a-zA-Z0-9_*?]*
-modifier_event [ukhp]{1,5}
+modifier_event [ukhpGH]{1,8}
 modifier_bp    [rwx]
 
 %%
index 9412e3b05f6888c9504c7ab6b3dd0effe73de627..1efd3bee6336bd6f1052ee76684e25cd489fa163 100644 (file)
@@ -826,8 +826,16 @@ static struct machine *
 {
        const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
-       if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
-               return perf_session__find_machine(session, event->ip.pid);
+       if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
+               u32 pid;
+
+               if (event->header.type == PERF_RECORD_MMAP)
+                       pid = event->mmap.pid;
+               else
+                       pid = event->ip.pid;
+
+               return perf_session__find_machine(session, pid);
+       }
 
        return perf_session__find_host_machine(session);
 }
@@ -868,11 +876,11 @@ static int perf_session_deliver_event(struct perf_session *session,
                dump_sample(session, event, sample);
                if (evsel == NULL) {
                        ++session->hists.stats.nr_unknown_id;
-                       return -1;
+                       return 0;
                }
                if (machine == NULL) {
                        ++session->hists.stats.nr_unprocessable_samples;
-                       return -1;
+                       return 0;
                }
                return tool->sample(tool, event, sample, evsel, machine);
        case PERF_RECORD_MMAP:
index c0a028c3ebaf35905e99e69f4cef76e5e343f44f..ab9867b2b433c97dd5bbd63f4079acdc2fceeaba 100644 (file)
@@ -977,8 +977,9 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
  * And always look at the original dso, not at debuginfo packages, that
  * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
  */
-static int dso__synthesize_plt_symbols(struct  dso *dso, struct map *map,
-                                      symbol_filter_t filter)
+static int
+dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map,
+                           symbol_filter_t filter)
 {
        uint32_t nr_rel_entries, idx;
        GElf_Sym sym;
@@ -993,10 +994,7 @@ static int dso__synthesize_plt_symbols(struct  dso *dso, struct map *map,
        char sympltname[1024];
        Elf *elf;
        int nr = 0, symidx, fd, err = 0;
-       char name[PATH_MAX];
 
-       snprintf(name, sizeof(name), "%s%s",
-                symbol_conf.symfs, dso->long_name);
        fd = open(name, O_RDONLY);
        if (fd < 0)
                goto out;
@@ -1703,8 +1701,9 @@ restart:
                        continue;
 
                if (ret > 0) {
-                       int nr_plt = dso__synthesize_plt_symbols(dso, map,
-                                                                filter);
+                       int nr_plt;
+
+                       nr_plt = dso__synthesize_plt_symbols(dso, name, map, filter);
                        if (nr_plt > 0)
                                ret += nr_plt;
                        break;
index d7a1c4afe28b9089ab09bbf5b7abce623e46a544..2f83e5dc996706a005dcdc9c1cac3cb88d38b94d 100644 (file)
@@ -125,6 +125,9 @@ static int callchain__count_rows(struct rb_root *chain)
 
 static bool map_symbol__toggle_fold(struct map_symbol *self)
 {
+       if (!self)
+               return false;
+
        if (!self->has_children)
                return false;
 
index 95d6a6f7c33aa7971c50f9b107f0c8474a16d70a..4915408f6a98c0c6d970a7ef341da7733fa8e6bc 100755 (executable)
@@ -183,6 +183,9 @@ my %force_config;
 # do not force reboots on config problems
 my $no_reboot = 1;
 
+# reboot on success
+my $reboot_success = 0;
+
 my %option_map = (
     "MACHINE"                  => \$machine,
     "SSH_USER"                 => \$ssh_user,
@@ -2192,7 +2195,7 @@ sub run_bisect {
     }
 
     # Are we looking for where it worked, not failed?
-    if ($reverse_bisect) {
+    if ($reverse_bisect && $ret >= 0) {
        $ret = !$ret;
     }
 
@@ -3469,6 +3472,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
     # Do not reboot on failing test options
     $no_reboot = 1;
+    $reboot_success = 0;
 
     $iteration = $i;
 
@@ -3554,9 +3558,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
            die "failed to checkout $checkout";
     }
 
+    $no_reboot = 0;
+
     # A test may opt to not reboot the box
     if ($reboot_on_success) {
-       $no_reboot = 0;
+       $reboot_success = 1;
     }
 
     if ($test_type eq "bisect") {
@@ -3600,7 +3606,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
 if ($opt{"POWEROFF_ON_SUCCESS"}) {
     halt;
-} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
+} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
     reboot_to_good;
 } elsif (defined($switch_to_good)) {
     # still need to get to the good kernel
index a457d2138f49ac8ed860507de8c9068566368889..e9fff9830bf0bf6f2229603516ebdd633996fd20 100644 (file)
@@ -240,9 +240,13 @@ int kvm_iommu_map_guest(struct kvm *kvm)
                return -ENODEV;
        }
 
+       mutex_lock(&kvm->slots_lock);
+
        kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type);
-       if (!kvm->arch.iommu_domain)
-               return -ENOMEM;
+       if (!kvm->arch.iommu_domain) {
+               r = -ENOMEM;
+               goto out_unlock;
+       }
 
        if (!allow_unsafe_assigned_interrupts &&
            !iommu_domain_has_cap(kvm->arch.iommu_domain,
@@ -253,17 +257,16 @@ int kvm_iommu_map_guest(struct kvm *kvm)
                       " module option.\n", __func__);
                iommu_domain_free(kvm->arch.iommu_domain);
                kvm->arch.iommu_domain = NULL;
-               return -EPERM;
+               r = -EPERM;
+               goto out_unlock;
        }
 
        r = kvm_iommu_map_memslots(kvm);
        if (r)
-               goto out_unmap;
-
-       return 0;
+               kvm_iommu_unmap_memslots(kvm);
 
-out_unmap:
-       kvm_iommu_unmap_memslots(kvm);
+out_unlock:
+       mutex_unlock(&kvm->slots_lock);
        return r;
 }
 
@@ -310,6 +313,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
        }
 }
 
+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+       kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages);
+}
+
 static int kvm_iommu_unmap_memslots(struct kvm *kvm)
 {
        int idx;
@@ -320,7 +328,7 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm)
        slots = kvm_memslots(kvm);
 
        kvm_for_each_memslot(memslot, slots)
-               kvm_iommu_put_pages(kvm, memslot->base_gfn, memslot->npages);
+               kvm_iommu_unmap_pages(kvm, memslot);
 
        srcu_read_unlock(&kvm->srcu, idx);
 
@@ -335,7 +343,11 @@ int kvm_iommu_unmap_guest(struct kvm *kvm)
        if (!domain)
                return 0;
 
+       mutex_lock(&kvm->slots_lock);
        kvm_iommu_unmap_memslots(kvm);
+       kvm->arch.iommu_domain = NULL;
+       mutex_unlock(&kvm->slots_lock);
+
        iommu_domain_free(domain);
        return 0;
 }
index 42b73930a6de6b2210708aca55903f87a9bab459..9739b533ca2e6954f75c98fc1bb307e641aedf94 100644 (file)
@@ -808,12 +808,13 @@ int __kvm_set_memory_region(struct kvm *kvm,
        if (r)
                goto out_free;
 
-       /* map the pages in iommu page table */
+       /* map/unmap the pages in iommu page table */
        if (npages) {
                r = kvm_iommu_map_pages(kvm, &new);
                if (r)
                        goto out_free;
-       }
+       } else
+               kvm_iommu_unmap_pages(kvm, &old);
 
        r = -ENOMEM;
        slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),