]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/kernel-video.git/commitdiff
Merge branch 'connectivity-ti-linux-3.14.y' of git://git.ti.com/connectivity-integrat...
authorDan Murphy <dmurphy@ti.com>
Tue, 16 Jun 2015 13:49:33 +0000 (08:49 -0500)
committerDan Murphy <dmurphy@ti.com>
Tue, 16 Jun 2015 13:49:33 +0000 (08:49 -0500)
TI-Feature: connectivity
TI-Tree: git://git.ti.com/connectivity-integration-tree/connectivity-ti-linux-kernel.git
TI-Branch: connectivity-ti-linux-3.14.y

* 'connectivity-ti-linux-3.14.y' of git://git.ti.com/connectivity-integration-tree/connectivity-ti-linux-kernel:
  ARM: DRA7: GMAC: Apply Errata i877
  ARM: OMAP2+: GMAC: Fix clock domain flags
  ARM: OMAP2+: hwmod: Introduce ti,no-idle dt property

Signed-off-by: Dan Murphy <dmurphy@ti.com>
681 files changed:
Documentation/devicetree/bindings/arm/omap/dmm.txt
Documentation/devicetree/bindings/arm/omap/l3-noc.txt
Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt
Documentation/devicetree/bindings/gpio/gpio.txt
Documentation/devicetree/bindings/media/i2c/ov1063x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/ti-cal.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/video-interfaces.txt
Documentation/devicetree/bindings/remoteproc/omap-remoteproc.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Makefile
arch/alpha/mm/fault.c
arch/arc/include/asm/processor.h
arch/arc/kernel/signal.c
arch/arc/kernel/stacktrace.c
arch/arc/mm/fault.c
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-bone-common.dtsi
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am437x-sk-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/am57xx-beagle-x15.dts
arch/arm/boot/dts/am57xx-evm.dts
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/dra7-evm-lcd7.dts [deleted file]
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra72-evm-lcd7.dts [deleted file]
arch/arm/boot/dts/dra72-evm.dts
arch/arm/boot/dts/dra74x.dtsi
arch/arm/boot/dts/dra7xx-clocks.dtsi
arch/arm/boot/dts/dra7xx-evm-lcd7.dtsi [deleted file]
arch/arm/boot/dts/imx23-olinuxino.dts
arch/arm/boot/dts/imx25.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/ste-dbx5x0.dtsi
arch/arm/boot/dts/ste-href.dtsi
arch/arm/boot/dts/ste-snowball.dts
arch/arm/common/edma.c
arch/arm/crypto/aesbs-core.S_shipped
arch/arm/crypto/bsaes-armv7.pl
arch/arm/include/asm/elf.h
arch/arm/include/asm/kvm_arm.h
arch/arm/include/asm/kvm_asm.h
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/kvm_mmu.h
arch/arm/include/asm/pgtable-3level-hwdef.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/pgtable.h
arch/arm/kernel/asm-offsets.c
arch/arm/kvm/coproc.c
arch/arm/kvm/coproc.h
arch/arm/kvm/coproc_a15.c
arch/arm/kvm/coproc_a7.c
arch/arm/kvm/guest.c
arch/arm/kvm/interrupts_head.S
arch/arm/kvm/mmu.c
arch/arm/mach-at91/pm.h
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clockdomains7xx_data.c
arch/arm/mach-omap2/cminst44xx.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/omap-iommu.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/pm33xx.c
arch/arm/mach-omap2/pm33xx.h
arch/arm/mach-omap2/prm33xx.c
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/sleep33xx.S
arch/arm/mach-omap2/sleep43xx.S
arch/arm/mach-omap2/timer.c
arch/arm/mach-s3c64xx/crag6410.h
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mm/proc-v7-3level.S
arch/arm/net/bpf_jit_32.c
arch/arm/plat-omap/dmtimer.c
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/mmu_context.h
arch/arm64/kernel/vdso/Makefile
arch/arm64/kvm/hyp.S
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/sys_regs.h
arch/arm64/mm/dma-mapping.c
arch/avr32/mm/fault.c
arch/c6x/kernel/time.c
arch/cris/mm/fault.c
arch/frv/mm/fault.c
arch/ia64/mm/fault.c
arch/m32r/mm/fault.c
arch/m68k/mm/fault.c
arch/metag/mm/fault.c
arch/microblaze/mm/fault.c
arch/mips/include/asm/suspend.h [deleted file]
arch/mips/kvm/trace.h
arch/mips/mm/fault.c
arch/mips/power/cpu.c
arch/mips/power/hibernate.S
arch/mn10300/mm/fault.c
arch/openrisc/mm/fault.c
arch/parisc/mm/fault.c
arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi
arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi
arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi
arch/powerpc/kernel/cacheinfo.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/suspend.c
arch/powerpc/mm/fault.c
arch/powerpc/perf/callchain.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/spu_fault.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/pseries/mobility.c
arch/s390/kernel/suspend.c
arch/s390/kvm/priv.c
arch/s390/mm/fault.c
arch/score/mm/fault.c
arch/sh/include/asm/sections.h
arch/sh/mm/fault.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/lib/memmove.S
arch/sparc/mm/fault_32.c
arch/sparc/mm/fault_64.c
arch/sparc/mm/srmmu.c
arch/sparc/power/hibernate.c
arch/tile/mm/fault.c
arch/um/kernel/trap.c
arch/unicore32/include/mach/pm.h
arch/unicore32/kernel/hibernate.c
arch/x86/crypto/aesni-intel_glue.c
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/mwait.h
arch/x86/kernel/entry_64.S
arch/x86/kernel/process.c
arch/x86/kernel/reboot.c
arch/x86/kernel/xsave.c
arch/x86/kvm/emulate.c
arch/x86/mm/fault.c
arch/x86/power/hibernate_32.c
arch/x86/power/hibernate_64.c
arch/x86/vdso/vdso32/sigreturn.S
arch/xtensa/Kconfig
arch/xtensa/include/uapi/asm/unistd.h
arch/xtensa/mm/fault.c
arch/xtensa/platforms/iss/network.c
arch/xtensa/platforms/xtfpga/Makefile
arch/xtensa/platforms/xtfpga/include/platform/hardware.h
arch/xtensa/platforms/xtfpga/include/platform/lcd.h
arch/xtensa/platforms/xtfpga/lcd.c
crypto/tcrypt.c
crypto/tcrypt.h
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/exdump.c
drivers/acpi/acpica/exfldio.c
drivers/acpi/acpica/exregion.c
drivers/acpi/acpica/hwvalid.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbprint.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/tbxfload.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/acpica/utaddress.c
drivers/acpi/processor_idle.c
drivers/acpi/scan.c
drivers/acpi/video.c
drivers/base/bus.c
drivers/base/regmap/regcache-rbtree.c
drivers/block/nbd.c
drivers/block/rbd.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/bus/omap_l3_noc.c
drivers/bus/omap_l3_noc.h
drivers/char/tpm/tpm_ibmvtpm.c
drivers/char/tpm/tpm_ibmvtpm.h
drivers/char/virtio_console.c
drivers/clk/clk-divider.c
drivers/clk/clk-gate.c
drivers/clk/qcom/clk-rcg2.c
drivers/clk/sunxi/clk-factors.c
drivers/clk/sunxi/clk-factors.h
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/tegra/clk.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/divider.c
drivers/clk/ti/dpll.c
drivers/clk/ti/gate.c
drivers/clk/zynq/clkc.c
drivers/clocksource/time-efm32.c
drivers/clocksource/timer-sun5i.c
drivers/cpufreq/cpufreq_opp.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/sysfs.c
drivers/crypto/Makefile
drivers/crypto/omap-aes-gcm.c [new file with mode: 0644]
drivers/crypto/omap-aes.c
drivers/crypto/omap-aes.h [new file with mode: 0644]
drivers/crypto/omap-des.c
drivers/crypto/omap-sham.c
drivers/dma/dw/platform.c
drivers/dma/edma.c
drivers/dma/omap-dma.c
drivers/edac/sb_edac.c
drivers/firmware/efi/runtime-map.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/msm/adreno/a3xx_gpu.c
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_dmm_priv.h
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/gpu/drm/omapdrm/omap_drv.h
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/omapdrm/omap_gem.c
drivers/gpu/drm/omapdrm/omap_plane.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/kv_dpm.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rv770d.h
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/radeon/uvd_v1_0.c
drivers/gpu/drm/radeon/uvd_v2_2.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/hid/hid-input.c
drivers/hv/channel.c
drivers/hv/channel_mgmt.c
drivers/i2c/i2c-core.c
drivers/iio/adc/mcp3422.c
drivers/iio/dac/ad5686.c
drivers/iio/imu/adis16400_core.c
drivers/iio/imu/adis_trigger.c
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/ucma.c
drivers/infiniband/core/umem.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/qib/qib.h
drivers/infiniband/hw/qib/qib_eeprom.c
drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_iba7220.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/qib/qib_init.c
drivers/infiniband/hw/qib/qib_sysfs.c
drivers/input/mouse/elantech.c
drivers/input/mouse/elantech.h
drivers/input/tablet/wacom_wac.c
drivers/iommu/omap-iommu.c
drivers/iommu/omap-iommu.h
drivers/mailbox/omap-mailbox.c
drivers/md/dm-io.c
drivers/md/dm-raid1.c
drivers/md/dm-snap.c
drivers/md/dm.c
drivers/md/raid0.c
drivers/media/i2c/Kconfig
drivers/media/i2c/Makefile
drivers/media/i2c/mt9t11x.c
drivers/media/i2c/ov1063x.c [new file with mode: 0644]
drivers/media/i2c/ov1063x_regs.h [new file with mode: 0644]
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/s5p-mfc/s5p_mfc_common.h
drivers/media/platform/sh_veu.c
drivers/media/platform/ti-vpe/Makefile
drivers/media/platform/ti-vpe/cal.c [new file with mode: 0644]
drivers/media/platform/ti-vpe/cal_regs.h [new file with mode: 0644]
drivers/media/platform/ti-vpe/sc.c
drivers/media/platform/ti-vpe/sc.h
drivers/media/platform/ti-vpe/vip.c
drivers/media/platform/ti-vpe/vip.h
drivers/media/platform/ti-vpe/vpdma.c
drivers/media/platform/ti-vpe/vpdma.h
drivers/media/platform/ti-vpe/vpdma_priv.h
drivers/media/platform/ti-vpe/vpe.c
drivers/media/usb/stk1160/stk1160-v4l.c
drivers/media/v4l2-core/v4l2-of.c
drivers/memstick/core/mspro_block.c
drivers/mfd/kempld-core.c
drivers/mfd/tps65218.c
drivers/misc/mei/init.c
drivers/misc/ti-st/st_core.c
drivers/misc/ti-st/st_kim.c
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/card/queue.h
drivers/mmc/core/core.c
drivers/mmc/host/sh_mmcif.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/ubi/attach.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/wl.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/ethernet/amd/pcnet32.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/8139too.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/macvtap.c
drivers/net/phy/phy.c
drivers/net/team/team.c
drivers/net/usb/cx82310_eth.c
drivers/net/usb/plusb.c
drivers/net/wireless/ath/ath5k/reset.c
drivers/net/wireless/ath/ath6kl/hif.h
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/iwlwifi/dvm/dev.h
drivers/net/wireless/iwlwifi/dvm/ucode.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/ti/wl18xx/debugfs.c
drivers/net/wireless/ti/wlcore/debugfs.h
drivers/of/irq.c
drivers/pci/pcie/aer/aerdrv_errprint.c
drivers/phy/phy-core.c
drivers/pinctrl/core.c
drivers/pinctrl/core.h
drivers/pinctrl/devicetree.c
drivers/platform/x86/compal-laptop.c
drivers/power/lp8788-charger.c
drivers/power/twl4030_madc_battery.c
drivers/regulator/core.c
drivers/regulator/of_regulator.c
drivers/regulator/palmas-regulator.c
drivers/regulator/tps65218-regulator.c
drivers/remoteproc/omap_remoteproc.c
drivers/remoteproc/omap_remoteproc.h
drivers/remoteproc/pruss_remoteproc.c
drivers/rpmsg/rpmsg_rpc.c
drivers/rpmsg/rpmsg_rpc_dmabuf.c
drivers/rtc/rtc-omap.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-9xxx.h
drivers/scsi/3w-sas.c
drivers/scsi/3w-sas.h
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.h
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/bfa/bfa_ioc.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/scsi_lib.c
drivers/scsi/sg.c
drivers/scsi/storvsc_drv.c
drivers/spi/spi-atmel.c
drivers/spi/spi-pl022.c
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/staging/comedi/comedi_compat32.c
drivers/staging/comedi/drivers/cb_pcidas64.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/lustre/lustre/llite/dcache.c
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/llite/namei.c
drivers/staging/lustre/lustre/llite/vvp_io.c
drivers/staging/panel/panel.c
drivers/staging/vt6655/rf.c
drivers/staging/vt6656/rf.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_device.c
drivers/target/target_core_file.c
drivers/target/target_core_pr.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_sbc.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_io.c
drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
drivers/thermal/ti-soc-thermal/ti-bandgap.c
drivers/thermal/ti-soc-thermal/ti-bandgap.h
drivers/tty/hvc/hvc_xen.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/of_serial.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/devio.c
drivers/usb/core/hub.c
drivers/usb/dwc2/hcd.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/legacy/printer.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/fotg210-hcd.c
drivers/usb/host/fusbh200-hcd.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/oxu210hp-hcd.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/uhci-hub.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_virthub.c
drivers/usb/phy/phy.c
drivers/usb/serial/bus.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/generic.c
drivers/usb/serial/mxuport.c
drivers/video/fbdev/omap2/displays-new/Kconfig
drivers/video/fbdev/omap2/displays-new/dra7-evm-encoder-tpd12s015.c
drivers/video/fbdev/omap2/displays-new/encoder-sii9022-audio.c
drivers/video/fbdev/omap2/displays-new/encoder-sii9022-video.c
drivers/video/fbdev/omap2/dss/dispc-compat.c
drivers/video/fbdev/omap2/dss/dispc.c
drivers/video/fbdev/omap2/dss/hdmi4.c
drivers/video/fbdev/omap2/dss/hdmi4_core.c
drivers/video/fbdev/omap2/dss/hdmi5.c
drivers/video/fbdev/omap2/dss/hdmi5_core.c
drivers/video/fbdev/omap2/dss/hdmi_wp.c
drivers/xen/events/events_2l.c
drivers/xen/events/events_base.c
drivers/xen/xen-pciback/conf_space.c
drivers/xen/xen-pciback/conf_space.h
drivers/xen/xen-pciback/conf_space_header.c
fs/affs/amigaffs.c
fs/aio.c
fs/autofs4/dev-ioctl.c
fs/autofs4/expire.c
fs/autofs4/root.c
fs/binfmt_elf.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/tree-log.c
fs/btrfs/xattr.c
fs/ceph/dir.c
fs/ceph/inode.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb2ops.c
fs/coda/cache.c
fs/dcache.c
fs/debugfs/inode.c
fs/exec.c
fs/exportfs/expfs.c
fs/ext4/extents_status.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/fuse/dev.c
fs/hfsplus/brec.c
fs/libfs.c
fs/namei.c
fs/namespace.c
fs/ncpfs/dir.c
fs/ncpfs/ncplib_kernel.h
fs/nfs/delegation.c
fs/nfs/getroot.c
fs/nilfs2/btree.c
fs/nilfs2/segment.c
fs/notify/fsnotify.c
fs/ocfs2/dcache.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/file.c
fs/open.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/task_mmu.c
include/acpi/acpixf.h
include/acpi/actypes.h
include/acpi/platform/acenv.h
include/asm-generic/sections.h
include/dt-bindings/pinctrl/am43xx.h
include/linux/blk_types.h
include/linux/clk/ti.h
include/linux/cpuidle.h
include/linux/crypto.h
include/linux/dcache.h
include/linux/mfd/palmas.h
include/linux/mfd/tps65218.h
include/linux/mm.h
include/linux/netdevice.h
include/linux/nilfs2_fs.h
include/linux/omap-iommu.h
include/linux/platform_data/iommu-omap.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/usb.h
include/linux/workqueue.h
include/media/v4l2-of.h
include/net/ip.h
include/net/ip6_route.h
include/net/sock.h
include/sound/emu10k1.h
include/sound/soc-dapm.h
include/target/target_core_base.h
include/trace/events/kmem.h
kernel/cgroup.c
kernel/cpuset.c
kernel/events/core.c
kernel/printk/console_cmdline.h
kernel/printk/printk.c
kernel/ptrace.c
kernel/sched/core.c
kernel/softirq.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/workqueue.c
lib/lz4/lz4_decompress.c
lib/string.c
mm/compaction.c
mm/hugetlb.c
mm/ksm.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/mmap.c
mm/nommu.c
mm/page-writeback.c
mm/page_alloc.c
net/caif/caif_socket.c
net/can/af_can.c
net/compat.c
net/core/dev.c
net/core/gen_stats.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/core/sysctl_net_core.c
net/ipv4/inet_diag.c
net/ipv4/ip_forward.c
net/ipv4/ip_fragment.c
net/ipv4/ip_output.c
net/ipv4/ping.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_output.c
net/ipv6/ndisc.c
net/ipv6/ping.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/irda/ircomm/ircomm_tty.c
net/llc/sysctl_net_llc.c
net/mac80211/ieee80211_i.h
net/mac80211/rx.c
net/mac80211/tx.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_conntrack_proto_generic.c
net/netfilter/nft_compat.c
net/netfilter/xt_socket.c
net/netlink/af_netlink.c
net/rds/iw_rdma.c
net/rds/sysctl.c
net/rpmsg/rpmsg_proto.c
net/rxrpc/ar-recvmsg.c
net/sched/ematch.c
net/sunrpc/cache.c
net/wireless/nl80211.c
samples/rpmsg/rpmsg_client_sample.c
scripts/dtc/checks.c
scripts/dtc/data.c
scripts/dtc/dtc-lexer.l
scripts/dtc/dtc-lexer.lex.c_shipped
scripts/dtc/dtc-parser.tab.c_shipped
scripts/dtc/dtc-parser.tab.h_shipped
scripts/dtc/dtc-parser.y
scripts/dtc/dtc.c
scripts/dtc/dtc.h
scripts/dtc/flattree.c
scripts/dtc/fstree.c
scripts/dtc/livetree.c
scripts/dtc/srcpos.c
scripts/dtc/srcpos.h
scripts/dtc/treesource.c
scripts/dtc/update-dtc-source.sh [new file with mode: 0755]
scripts/dtc/util.c
scripts/dtc/util.h
scripts/dtc/version_gen.h
security/selinux/selinuxfs.c
sound/core/control.c
sound/core/pcm_native.c
sound/oss/sequencer.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_callback.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/memory.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/thinkpad_helper.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/ak4641.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/pcm1681.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/tas5086.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8960.c
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/jz4740/Makefile
sound/soc/omap/omap-hdmi-audio.c
sound/soc/omap/omap-pcm.c
sound/synth/emux/emux_oss.c
sound/synth/emux/emux_seq.c
sound/usb/mixer_quirks.c
sound/usb/quirks-table.h
ti_config_fragments/baseport.cfg
tools/lib/traceevent/kbuffer-parse.c
tools/power/x86/turbostat/Makefile
virt/kvm/arm/vgic.c
virt/kvm/kvm_main.c

index 8bd6d0a238a88ff243ed7478679e830f6423a989..e5fc2eb7f4da788f66128a15e58185c20a84680c 100644 (file)
@@ -8,7 +8,8 @@ translation for initiators which need contiguous dma bus addresses.
 
 Required properties:
 - compatible:  Should contain "ti,omap4-dmm" for OMAP4 family
-               Should contain "ti,omap5-dmm" for OMAP5 and DRA7x family
+               Should contain "ti,omap5-dmm" for OMAP5 family
+               Should contain "ti,dra7-dmm" for DRA7x family
 - reg:         Contains DMM register address range (base address and length)
 - interrupts:  Should contain an interrupt-specifier for DMM_IRQ.
 - ti,hwmods:   Name of the hwmod associated to DMM, which is typically "dmm"
index 974624ea68f67d3f16df404bccb57f587ac8a82e..161448da959d26edeb19de7db2561564c4c473dc 100644 (file)
@@ -6,6 +6,7 @@ provided by Arteris.
 Required properties:
 - compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
                Should be "ti,omap4-l3-noc" for OMAP4 family
+               Should be "ti,omap5-l3-noc" for OMAP5 family
               Should be "ti,dra7-l3-noc" for DRA7 family
                Should be "ti,am4372-l3-noc" for AM43 family
 - reg: Contains L3 register address range for each noc domain.
index a4873e5e3e36de172c49f59108360e32aca9fefd..e30e184f50c727aa84d2284914581ce9927dba1c 100644 (file)
@@ -38,7 +38,7 @@ dma_apbx: dma-apbx@80024000 {
                      80 81 68 69
                      70 71 72 73
                      74 75 76 77>;
-       interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+       interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
                          "saif0", "saif1", "i2c0", "i2c1",
                          "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
                          "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
index 0c85bb6e3a80282edce785cad57468c6e11cfae0..04fae969e5016b0c62b5caa1d18862e2947b1894 100644 (file)
@@ -59,6 +59,29 @@ and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
 Every GPIO controller node must both an empty "gpio-controller"
 property, and have #gpio-cells contain the size of the gpio-specifier.
 
+The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism
+providing automatic GPIO request and configuration as part of the
+gpio-controller's driver probe function.
+
+Each GPIO hog definition is represented as a child node of the GPIO controller.
+Required properties:
+- gpio-hog:   A property specifying that this child node represent a GPIO hog.
+- gpios:      Store the GPIO information (id, flags, ...). Shall contain the
+             number of cells specified in its parent node (GPIO controller
+             node).
+Only one of the following properties scanned in the order shown below.
+This means that when multiple properties are present they will be searched
+in the order presented below and the first match is taken as the intended
+configuration.
+- input:      A property specifying to set the GPIO direction as input.
+- output-low  A property specifying to set the GPIO direction as output with
+             the value low.
+- output-high A property specifying to set the GPIO direction as output with
+             the value high.
+
+Optional properties:
+- line-name:  The GPIO label name. If not present the node name is used.
+
 Example of two SOC GPIO banks defined as gpio-controller nodes:
 
        qe_pio_a: gpio-controller@1400 {
@@ -66,6 +89,13 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
                compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
                reg = <0x1400 0x18>;
                gpio-controller;
+
+               line_b {
+                       gpio-hog;
+                       gpios = <6 0>;
+                       output-low;
+                       line-name = "foo-bar-gpio";
+               };
        };
 
        qe_pio_e: gpio-controller@1460 {
diff --git a/Documentation/devicetree/bindings/media/i2c/ov1063x.txt b/Documentation/devicetree/bindings/media/i2c/ov1063x.txt
new file mode 100644 (file)
index 0000000..6649e20
--- /dev/null
@@ -0,0 +1,40 @@
+* OmniVision 8/10 bit digital camera
+
+The Omnivision digital camera is a 720p camera which is configurable at 8/10bit
+YUYV output and can be configured for various resolutions.
+
+Required Properties:
+- compatible : Must be one of the following
+  - "ovti,ov10633": For OV10633 camera
+  - "ovti,ov10635": For OV10635 camera
+
+Optional Properties:
+- gpios : A list of gpios with active high/low flags for enabling the sensor.
+         This may contain gpios for power, board muxes, etc. Driver would
+         set all of them as specified by the active high/low flag
+
+  There are no custom optional properties supported for this device.
+  Although all the endpoint properties documented in
+  Documentation/devicetree/bindings/media/video-interfaces.txt are supported.
+
+Example:
+
+       &i2c2 {
+               ...
+               ...
+               ovcamera@30 {
+                       compatible = "ovti,ov10635";
+                       reg = <0x30>;
+
+                       mux-gpios = <&pcf_hdmi 3    GPIO_ACTIVE_LOW>;
+
+                       port {
+                               onboard_cam: endpoint {
+                                       hsync-active = <1>;
+                                       vsync-active = <1>;
+                                       pclk-sample = <1>;
+                               };
+                       };
+               };
+               ...
+       };
diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt
new file mode 100644 (file)
index 0000000..680efad
--- /dev/null
@@ -0,0 +1,70 @@
+Texas Instruments DRA72x CAMERA ADAPTATION LAYER (CAL)
+------------------------------------------------------
+
+The Camera Adaptation Layer (CAL) is a key component for image capture
+applications. The capture module provides the system interface and the
+processing capability to connect CSI2 image-sensor modules to the
+DRA72x device.
+
+Required properties:
+- compatible: must be "ti,cal"
+- reg: physical base address and length of the registers set for the 4
+       memory regions required;
+- reg-names: name associated with the memory regions described is <reg>;
+- interrupts: should contain IRQ line for the CAL;
+
+CAL supports 2 camera port nodes on MIPI bus. Each CSI2 camera port nodes
+should contain a 'port' child node with child 'endpoint' node. Please
+refer to the bindings defined in
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+       cal: cal@4845b000 {
+               compatible = "ti,cal";
+               ti,hwmods = "cal";
+               reg = <0x4845B000 0x400>,
+                     <0x4845B800 0x40>,
+                     <0x4845B900 0x40>,
+                     <0x4A002e94 0x4>;
+               reg-names = "cal_top",
+                           "cal_rx_core0",
+                           "cal_rx_core1",
+                           "camerrx_control";
+               interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               csi2_0: port@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0>;
+                       endpoint {
+                               slave-mode;
+                               remote-endpoint = <&ar0330_1>;
+                       };
+               };
+               csi2_1: port@1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <1>;
+               };
+       };
+
+       i2c5: i2c@4807c000 {
+               ar0330@10 {
+                       compatible = "ti,ar0330";
+                       reg = <0x10>;
+
+                       port {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               ar0330_1: endpoint {
+                                       reg = <0>;
+                                       clock-lanes = <1>;
+                                       data-lanes = <0 2 3 4>;
+                                       remote-endpoint = <&csi2_0>;
+                               };
+                       };
+               };
+       };
index 3810fc724557b57c7e3c2d9fbdcb7e1ee9a2a84c..7d2d8792a83e5cf0dfa0d40e1484219abe841368 100644 (file)
@@ -105,6 +105,12 @@ Optional endpoint properties
   array contains only one entry.
 - clock-noncontinuous: a boolean property to allow MIPI CSI-2 non-continuous
   clock mode.
+- lane-polarities: an array of polarities of the lanes starting from the clock
+  lane and followed by the data lanes in the same order as in data-lanes.
+  Valid values are 0 (normal) and 1 (inverted). The length of the array
+  should be the combined length of data-lanes and clock-lanes properties.
+  If the lane-polarities property is omitted, the value must be interpreted
+  as 0 (normal). This property is valid for serial busses only.
 
 
 Example
index cbeb7e185befcb9871c9953fb03b3ffd50aadfba..68a8054fe9d5f2d7aa248959c0f0a9af3db8ea6a 100644 (file)
@@ -100,6 +100,11 @@ The following are the optional properties:
                        The timers to be used should match with the watchdog
                        timers used in the firmware image.
 
+- ti,rproc-standby-info: Standby data for the remote processor. This is
+                        mandatory to support Power Management for the OMAP
+                        remoteprocs, and should contain the address containing
+                        the module standby status.
+
 Example:
 --------
 
@@ -110,6 +115,7 @@ ocp {
                ti,hwmods = "dsp";
                iommus = <&mmu_dsp>;
                mboxes = <&mailbox &mbox_dsp>;
+               ti,rproc-standby-info = <0x4a004420>;
                status = "disabled";
        };
 };
index d2324b7bdfb43f238fa6f91f06556e9db5783d52..01202445f7392040e0f8f67519257799d55cc94e 100644 (file)
@@ -62,6 +62,7 @@ nintendo      Nintendo
 nvidia NVIDIA
 nxp    NXP Semiconductors
 onnn   ON Semiconductor Corp.
+ovti   OmniVision Technologies, Inc
 panasonic      Panasonic Corporation
 phytec PHYTEC Messtechnik GmbH
 picochip       Picochip Ltd
index 9720e863c06f1554ce6c9028b39520633cd5a543..ae5f1e62812fd5ad24e3ce6b389da35aca92f883 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 14
-SUBLEVEL = 35
+SUBLEVEL = 43
 EXTRAVERSION =
 NAME = Remembering Coco
 
index 98838a05ba6d89f0459742131010f57c38cbed05..9d0ac091a52a7d16cf1f78f402ab48c511924a24 100644 (file)
@@ -156,6 +156,8 @@ retry:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 15334ab66b56e110ac67152bac96317c3f8368ff..fb95aa8072155d63c1be5fd75056082d76945012 100644 (file)
@@ -69,18 +69,19 @@ unsigned long thread_saved_pc(struct task_struct *t);
 #define release_segments(mm)        do { } while (0)
 
 #define KSTK_EIP(tsk)   (task_pt_regs(tsk)->ret)
+#define KSTK_ESP(tsk)   (task_pt_regs(tsk)->sp)
 
 /*
  * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode.
  * Look in process.c for details of kernel stack layout
  */
-#define KSTK_ESP(tsk)   (tsk->thread.ksp)
+#define TSK_K_ESP(tsk)         (tsk->thread.ksp)
 
-#define KSTK_REG(tsk, off)     (*((unsigned int *)(KSTK_ESP(tsk) + \
+#define TSK_K_REG(tsk, off)    (*((unsigned int *)(TSK_K_ESP(tsk) + \
                                        sizeof(struct callee_regs) + off)))
 
-#define KSTK_BLINK(tsk) KSTK_REG(tsk, 4)
-#define KSTK_FP(tsk)    KSTK_REG(tsk, 0)
+#define TSK_K_BLINK(tsk)       TSK_K_REG(tsk, 4)
+#define TSK_K_FP(tsk)          TSK_K_REG(tsk, 0)
 
 /*
  * Do necessary setup to start up a newly executed thread.
index 7e95e1a86510fee2f2e1511f8bc7b63f8fb48122..a0c63fc48457db4aa58d58a674a7e0568db0b46f 100644 (file)
@@ -67,7 +67,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
               sigset_t *set)
 {
        int err;
-       err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs,
+       err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), regs,
                             sizeof(sf->uc.uc_mcontext.regs.scratch));
        err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));
 
@@ -83,7 +83,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
        if (!err)
                set_current_blocked(&set);
 
-       err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs),
+       err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs.scratch),
                                sizeof(sf->uc.uc_mcontext.regs.scratch));
 
        return err;
@@ -131,6 +131,15 @@ SYSCALL_DEFINE0(rt_sigreturn)
        /* Don't restart from sigreturn */
        syscall_wont_restart(regs);
 
+       /*
+        * Ensure that sigreturn always returns to user mode (in case the
+        * regs saved on user stack got fudged between save and sigreturn)
+        * Otherwise it is easy to panic the kernel with a custom
+        * signal handler and/or restorer which clobberes the status32/ret
+        * to return to a bogus location in kernel mode.
+        */
+       regs->status32 |= STATUS_U_MASK;
+
        return regs->r0;
 
 badframe:
@@ -234,8 +243,11 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
 
        /*
         * handler returns using sigreturn stub provided already by userpsace
+        * If not, nuke the process right away
         */
-       BUG_ON(!(ka->sa.sa_flags & SA_RESTORER));
+       if(!(ka->sa.sa_flags & SA_RESTORER))
+               return 1;
+
        regs->blink = (unsigned long)ka->sa.sa_restorer;
 
        /* User Stack for signal handler will be above the frame just carved */
@@ -302,12 +314,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
              struct pt_regs *regs)
 {
        sigset_t *oldset = sigmask_to_save();
-       int ret;
+       int failed;
 
        /* Set up the stack frame */
-       ret = setup_rt_frame(sig, ka, info, oldset, regs);
+       failed = setup_rt_frame(sig, ka, info, oldset, regs);
 
-       if (ret)
+       if (failed)
                force_sigsegv(sig, current);
        else
                signal_delivered(sig, info, ka, regs, 0);
index 9ce47cfe23037fa12f463a350819731422aadd9b..fb98769b6a985d718b50fd209874b812d43126b0 100644 (file)
@@ -64,9 +64,9 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
 
                frame_info->task = tsk;
 
-               frame_info->regs.r27 = KSTK_FP(tsk);
-               frame_info->regs.r28 = KSTK_ESP(tsk);
-               frame_info->regs.r31 = KSTK_BLINK(tsk);
+               frame_info->regs.r27 = TSK_K_FP(tsk);
+               frame_info->regs.r28 = TSK_K_ESP(tsk);
+               frame_info->regs.r31 = TSK_K_BLINK(tsk);
                frame_info->regs.r63 = (unsigned int)__switch_to;
 
                /* In the prologue of __switch_to, first FP is saved on stack
index 9c69552350c49754ee056ab854a5971b460fe5f8..01e18b58dfa4cce7f3f79a22bbbf8512d0b7f2fa 100644 (file)
@@ -162,6 +162,8 @@ good_area:
        /* TBD: switch to pagefault_out_of_memory() */
        if (fault & VM_FAULT_OOM)
                goto out_of_memory;
+       else if (fault & VM_FAULT_SIGSEGV)
+               goto bad_area;
        else if (fault & VM_FAULT_SIGBUS)
                goto do_sigbus;
 
index d63e325c9fa1edb201cab227e71dc5f1989fca77..87ed4c9d4cbb1870b1d7c3de87a56752f1766968 100644 (file)
@@ -240,10 +240,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
        am437x-gp-evm-hdmi.dtb \
        am437x-sk-evm.dtb \
        dra7-evm.dtb \
-       dra7-evm-lcd7.dtb \
        dra7-evm-lcd10.dtb \
        dra72-evm.dtb \
-       dra72-evm-lcd7.dtb \
        dra72-evm-lcd10.dtb \
        am57xx-beagle-x15.dtb \
        am57xx-evm.dtb
index 9b65c271c080df0df0964e1940ec8e568c14fe11..d53e9aa49d35f60b349bee48d4493e7ce2b311e9 100644 (file)
 &wkup_m3 {
        ti,scale-data-fw = "am335x-bone-scale-data.bin";
 };
+
+&rtc {
+       ti,system-power-controller;
+};
index 8b7c8577e2195e73f0489887c8bc2103a10fb5dd..0ff1735db237c64b0105197c306fead445c21038 100644 (file)
                compatible = "ti,wlcore";
                reg = <2>;
                interrupt-parent = <&gpio3>;
-               interrupts = <17 IRQ_TYPE_NONE>;
+               interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
        };
 };
 
        pinctrl-names = "default";
        pinctrl-0 = <&dcan1_pins_default>;
 };
+
+&rtc {
+       ti,system-power-controller;
+};
index 95de1125672e771b5325b43e336b182d3e0cec6d..522a782e28c0de960f5c139e693b34b3c2b31349 100644 (file)
                        ti,timer-pwm;
                };
 
-               rtc@44e3e000 {
+               rtc: rtc@44e3e000 {
                        compatible = "ti,am3352-rtc";
                        reg = <0x44e3e000 0x1000>;
                        interrupts = <75
index 667aceafcf240f5533764b8805710f56385150f5..43327844b17cbc22f453ca12584d041888daea85 100644 (file)
                dcdc3: regulator-dcdc3 {
                        compatible = "ti,tps65218-dcdc3";
                        regulator-name = "vdcdc3";
-                       regulator-suspend-enable;
                        regulator-min-microvolt = <1500000>;
                        regulator-max-microvolt = <1500000>;
                        regulator-boot-on;
                        regulator-always-on;
+                       regulator-state-mem {
+                               regulator-on-in-suspend;
+                       };
+                       regulator-state-disk {
+                               regulator-off-in-suspend;
+                       };
                };
 
                dcdc5: regulator-dcdc5 {
                        regulator-name = "v1_0bat";
                        regulator-min-microvolt = <1000000>;
                        regulator-max-microvolt = <1000000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+                       regulator-state-mem {
+                               regulator-on-in-suspend;
+                       };
                };
 
                dcdc6: regulator-dcdc6 {
                        regulator-name = "v1_8bat";
                        regulator-min-microvolt = <1800000>;
                        regulator-max-microvolt = <1800000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+                       regulator-state-mem {
+                               regulator-on-in-suspend;
+                       };
                };
 
                ldo1: regulator-ldo1 {
                compatible = "ti,wlcore";
                reg = <2>;
                interrupt-parent = <&gpio1>;
-               interrupts = <23 IRQ_TYPE_NONE>;
+               interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
        };
 };
 
index 41df4f18d7b568a12e9cc1d9b4b5b3655498cc0d..6ffbb925fc97a375c2808038b4d9b0c9070ad692 100644 (file)
        };
 
        lcd0: display {
-               compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+               compatible = "newhaven,nhd-4.3-480272ef-atxl", "panel-dpi";
                label = "lcd";
 
                pinctrl-names = "default";
                        clock-frequency = <9000000>;
                        hactive = <480>;
                        vactive = <272>;
-                       hfront-porch = <8>;
-                       hback-porch = <43>;
-                       hsync-len = <4>;
-                       vback-porch = <12>;
-                       vfront-porch = <4>;
+                       hfront-porch = <2>;
+                       hback-porch = <2>;
+                       hsync-len = <41>;
+                       vfront-porch = <2>;
+                       vback-porch = <2>;
                        vsync-len = <10>;
                        hsync-active = <0>;
                        vsync-active = <0>;
 
        lcd_pins: lcd_pins {
                pinctrl-single,pins = <
-                       /* GPIO 5_8 to select LCD / HDMI */
-                       0x238 (PIN_OUTPUT_PULLUP | MUX_MODE7)
+                       0x1c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpcm_ad7.gpio1_7 */
                >;
        };
 
                        regulator-max-microvolt = <1500000>;
                        regulator-boot-on;
                        regulator-always-on;
+                       regulator-state-mem {
+                               regulator-on-in-suspend;
+                       };
+                       regulator-state-disk {
+                               regulator-off-in-suspend;
+                       };
                };
 
                dcdc4: regulator-dcdc4 {
                        regulator-always-on;
                };
 
+               dcdc5: regulator-dcdc5 {
+                       compatible = "ti,tps65218-dcdc5";
+                       regulator-name = "v1_0bat";
+                       regulator-min-microvolt = <1000000>;
+                       regulator-max-microvolt = <1000000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+                       regulator-state-mem {
+                               regulator-on-in-suspend;
+                       };
+               };
+
+               dcdc6: regulator-dcdc6 {
+                       compatible = "ti,tps65218-dcdc6";
+                       regulator-name = "v1_8bat";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+                       regulator-state-mem {
+                               regulator-on-in-suspend;
+                       };
+               };
+
                ldo1: regulator-ldo1 {
                        compatible = "ti,tps65218-ldo1";
                        regulator-name = "v1_8d";
index 021a6c0d379d3ae1c3c997a31f39c674efab5d26..e735d3b5588fd95ce1402805539d2c7fc921f283 100644 (file)
                compatible = "ti,wlcore";
                reg = <2>;
                interrupt-parent = <&gpio0>;
-               interrupts = <31 IRQ_TYPE_NONE>;
+               interrupts = <31 IRQ_TYPE_LEVEL_HIGH>;
        };
 };
 
index d13f6f40f132bbde54c22083766ee0cc12e2605c..9d4fe5a1e342f7b5f1f7ea63e64291b6d7182576 100644 (file)
        memory-region = <&ipu1_cma_pool>;
        mboxes = <&mailbox5 &mbox_ipu1_legacy>;
        timers = <&timer11>;
+       watchdog-timers = <&timer7>, <&timer8>;
 };
 
 &dsp1 {
        memory-region = <&dsp1_cma_pool>;
        mboxes = <&mailbox5 &mbox_dsp1_legacy>;
        timers = <&timer5>;
+       watchdog-timers = <&timer10>;
 };
 
 &dsp2 {
index c4d4a4ca7c076c6da913c369338b5bb7f53b0bd9..8c54b1a6ae5ea216555a688b4f2e8a4c9211a43e 100644 (file)
        };
 };
 
-&dra7_pmx_core {
-       bt_uart8_pins: pinmux_uart8_pins {
-               pinctrl-single,pins = <
-                       0x334 (PIN_INPUT  | MUX_MODE3)          /* mcasp4_aclkx.uart8_rxd */
-                       0x338 (PIN_OUTPUT | MUX_MODE3)          /* mcasp4_fsx.uart8_txd */
-                       0x33c (PIN_INPUT  | MUX_MODE3)          /* mcasp4_axr0.uart8_ctsn */
-                       0x340 (PIN_OUTPUT | MUX_MODE3)          /* mcasp4_axr1.uart8_rtsn */
-                       0x2bc (PIN_OUTPUT | MUX_MODE14)         /* mcasp1_axr2.gpio5_4 - BT_EN */
-               >;
-       };
-
-       wlan_pins: pinmux_wlan_pins {
-               pinctrl-single,pins = <
-                       0x37C (PIN_INPUT | MUX_MODE0)           /* mmc3_clk.clk */
-                       0x380 (PIN_INPUT | MUX_MODE0)           /* mmc3_cmd.cmd */
-                       0x384 (PIN_INPUT | MUX_MODE0)           /* mmc3_dat0.dat0 */
-                       0x388 (PIN_INPUT | MUX_MODE0)           /* mmc3_dat1.dat1 */
-                       0x38C (PIN_INPUT | MUX_MODE0)           /* mmc3_dat2.dat2 */
-                       0x390 (PIN_INPUT | MUX_MODE0)           /* mmc3_dat3.dat3 */
-                       0x2cc (PIN_OUTPUT | MUX_MODE14)         /* mcasp1_axr6.gpio5_8 - WLAN_EN */
-               >;
-       };
-
-       wlirq_pins: pinmux_wlirq_pins {
-               pinctrl-single,pins = <
-                       0x2c8 (PIN_INPUT_PULLUP | MUX_MODE14 )  /* mcasp1_axr5.gpio5_7 - WLAN_IRQ */
-               >;
-       };
-};
-
 &i2c5 {
        status = "okay";
        clock-frequency = <400000>;
                                remote-endpoint = <&vin3a>;
                                hsync-active = <1>;
                                vsync-active = <1>;
-                               pclk-sample = <1>;
+                               pclk-sample = <0>;
                                input-clock-freq = <32000000>;
                                pixel-clock-freq = <96000000>;
                        };
 
 &uart8 {
        status = "okay";
-       pinctrl-names = "default";
-       pinctrl-0 = <&bt_uart8_pins>;
 };
 
 &mmc3 {
        status = "okay";
        vmmc-supply = <&vmmcwl_fixed>;
        bus-width = <4>;
-       pinctrl-names = "default";
-       pinctrl-0 = <&wlan_pins &wlirq_pins>;
        cap-power-off-card;
        keep-power-in-suspend;
        ti,non-removable;
index 1c6bd83bde5e55c7d6f80028feba98af75c91263..2ade35703d72da28f63c7f262534e1b728726c3b 100644 (file)
                };
 
                internal-regs {
+                       rtc@10300 {
+                               /* No crystal connected to the internal RTC */
+                               status = "disabled";
+                       };
                        serial@12000 {
                                clock-frequency = <250000000>;
                                status = "okay";
index 187fd46b7b5ef018c2985e7db5298784338f0507..355117cbbf4ac9ff3d10f6bc581462a1a845a598 100644 (file)
 
                        uart2: serial@12200 {
                                compatible = "ns16550a";
-                               reg = <0x12000 0x100>;
+                               reg = <0x12200 0x100>;
                                reg-shift = <2>;
                                interrupts = <9>;
                                clocks = <&core_clk 0>;
 
                        uart3: serial@12300 {
                                compatible = "ns16550a";
-                               reg = <0x12100 0x100>;
+                               reg = <0x12300 0x100>;
                                reg-shift = <2>;
                                interrupts = <10>;
                                clocks = <&core_clk 0>;
diff --git a/arch/arm/boot/dts/dra7-evm-lcd7.dts b/arch/arm/boot/dts/dra7-evm-lcd7.dts
deleted file mode 100644 (file)
index 4ed8ebe..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "dra7-evm.dts"
-#include "dra7xx-evm-lcd7.dtsi"
index f585b5b94fe3bcc60044b851bd2b4d7341bf6c4c..23bdb38f4fb96245553fc4894a92442ce3acf8b5 100644 (file)
        tpd12s015: encoder@1 {
                compatible = "ti,dra7evm-tpd12s015";
 
+               pinctrl-names = "i2c", "ddc";
+               pinctrl-0 = <&hdmi_i2c_sel_pin &hdmi_i2c_pins_i2c>;
+               pinctrl-1 = <&hdmi_i2c_sel_pin &hdmi_i2c_pins_ddc>;
+
+               ddc-i2c-bus = <&i2c2>;
+               mcasp-gpio = <&mcasp8>;
+
                gpios = <&pcf_hdmi 4 0>,        /* P4, CT CP HPD */
                        <&pcf_hdmi 5 0>,        /* P5, LS OE */
                        <&gpio7 12 0>;  /* gpio7_12/sp1_cs2, HPD */
 };
 
 &dra7_pmx_core {
-       wlan_pins: pinmux_wlan_pins {
+       hdmi_i2c_sel_pin: pinmux_hdmi_i2c_sel_pin {
                pinctrl-single,pins = <
-                       0x3e8 (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart1_ctsn.mmc4_clk */
-                       0x3ec (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart1_rtsn.mmc4_cmd */
-                       0x3f0 (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart2_rxd.mmc4_dat0 */
-                       0x3f4 (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart2_txd.mmc4_dat1 */
-                       0x3f8 (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart2_ctsn.mmc4_dat2 */
-                       0x3fc (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart2_rtsn.mmc4_dat3 */
-                       0x2cc (PIN_OUTPUT | MUX_MODE14)         /* mcasp1_axr6.gpio5_8 - WLAN_EN */
+                       /* this pin is used as a GPIO via mcasp */
+                       0x2fc   (PIN_OUTPUT | MUX_MODE1) /* mcasp8_axr2 */
                >;
        };
 
-       wlirq_pins: pinmux_wlirq_pins {
+       hdmi_i2c_pins_i2c: pinmux_hdmi_i2c_pins_default {
                pinctrl-single,pins = <
-                       0x2c8 (PIN_INPUT_PULLUP | WAKEUP_EN | MUX_MODE14 ) /* mcasp1_axr5.gpio5_7 - WLAN_IRQ */
+                       0x408   (PIN_INPUT | MUX_MODE0) /* i2c2_sda.i2c2_sda */
+                       0x40c   (PIN_INPUT | MUX_MODE0) /* i2c2_scl.i2c2_scl */
+               >;
+       };
+
+       hdmi_i2c_pins_ddc: pinmux_hdmi_i2c_pins_ddc {
+               pinctrl-single,pins = <
+                       0x408   (PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */
+                       0x40c   (PIN_INPUT | MUX_MODE1) /* i2c2_scl.hdmi1_ddc_sda */
                >;
        };
 
                #interrupt-cells = <2>;
        };
 
-       mxt244: touchscreen@4a {
-               compatible = "atmel,mXT244";
-               status = "okay";
-               reg = <0x4a>;
-               interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-
-               atmel,config = <
-                       /* MXT244_GEN_COMMAND(6) */
-                       0x00 0x00 0x00 0x00 0x00 0x00
-                       /* MXT244_GEN_POWER(7) */
-                       0x20 0xff 0x32
-                       /* MXT244_GEN_ACQUIRE(8) */
-                       0x0a 0x00 0x05 0x00 0x00 0x00 0x09 0x23
-                       /* MXT244_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
-                       /* MXT244_TOUCH_KEYARRAY(15) */
-                       0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-                       0x00
-                       /* MXT244_COMMSCONFIG_T18(2) */
-                       0x00 0x00
-                       /* MXT244_SPT_GPIOPWM(19) */
-                       0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-                       0x00 0x00 0x00 0x00 0x00 0x00
-                       /* MXT244_PROCI_GRIPFACE(20) */
-                       0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x50 0x28 0x04
-                       0x0f 0x0a
-                       /* MXT244_PROCG_NOISE(22) */
-                       0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x03 0x23 0x00
-                       0x00 0x05 0x0f 0x19 0x23 0x2d 0x03
-                       /* MXT244_TOUCH_PROXIMITY(23) */
-                       0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-                       0x00 0x00 0x00 0x00 0x00
-                       /* MXT244_PROCI_ONETOUCH(24) */
-                       0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-                       0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-                       /* MXT244_SPT_SELFTEST(25) */
-                       0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-                       0x00 0x00 0x00 0x00
-                       /* MXT244_PROCI_TWOTOUCH(27) */
-                       0x00 0x00 0x00 0x00 0x00 0x00 0x00
-                       /* MXT244_SPT_CTECONFIG(28) */
-                       0x00 0x00 0x02 0x08 0x10 0x00
-               >;
-
-               atmel,x_line = <18>;
-               atmel,y_line = <12>;
-               atmel,x_size = <800>;
-               atmel,y_size = <480>;
-               atmel,blen = <0x01>;
-               atmel,threshold = <30>;
-               atmel,voltage = <2800000>;
-               atmel,orient = <0x4>;
-       };
-
        tlv320aic3106: tlv320aic3106@18 {
                compatible = "ti,tlv320aic3106";
                reg = <0x18>;
                gpio-controller;
                #gpio-cells = <2>;
        };
+
+       ov10633@37 {
+               compatible = "ovti,ov10633";
+               reg = <0x37>;
+
+               mux-gpios = <&pcf_hdmi 3        GPIO_ACTIVE_LOW>; /* CAM_FPD_MUX_S0 */
+               port {
+                       onboardLI: endpoint {
+                               remote-endpoint = <&vin1a>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               pclk-sample = <0>;
+                       };
+               };
+       };
 };
 
 &i2c3 {
        status = "okay";
        vmmc-supply = <&vmmcwl_fixed>;
        bus-width = <4>;
-       pinctrl-names = "default";
-       pinctrl-0 = <&wlan_pins &wlirq_pins>;
        cap-power-off-card;
        keep-power-in-suspend;
        ti,non-removable;
                compatible = "ti,wlcore";
                reg = <2>;
                interrupt-parent = <&gpio5>;
-               interrupts = <7 IRQ_TYPE_NONE>;
+               interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
        };
 };
 
        memory-region = <&ipu1_cma_pool>;
        mboxes = <&mailbox5 &mbox_ipu1_legacy>;
        timers = <&timer11>;
+       watchdog-timers = <&timer7>, <&timer8>;
 };
 
 &dsp1 {
        memory-region = <&dsp1_cma_pool>;
        mboxes = <&mailbox5 &mbox_dsp1_legacy>;
        timers = <&timer5>;
+       watchdog-timers = <&timer10>;
 };
 
 &dsp2 {
        >;
 };
 
+&mcasp8 {
+       /* not used for audio. only the AXR2 pin is used as GPIO */
+       status = "okay";
+};
+
 &usb2_phy1 {
        phy-supply = <&ldousb_reg>;
 };
 &usb2_phy2 {
        phy-supply = <&ldousb_reg>;
 };
+
+&vip1 {
+       status = "okay";
+};
+
+&vin1a {
+       endpoint@0 {
+               slave-mode;
+               remote-endpoint = <&onboardLI>;
+       };
+};
index 5a96023151ff28a086d28843dfa767ba1493b1f7..3dcc00d0eec11ae5547f0455e515d092696dd476 100644 (file)
                        reg = <0x48820000 0x80>;
                        interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer5";
-                       ti,timer-dsp;
                };
 
                timer6: timer@48822000 {
                        reg = <0x48822000 0x80>;
                        interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer6";
-                       ti,timer-dsp;
-                       ti,timer-pwm;
                };
 
                timer7: timer@48824000 {
                        reg = <0x48824000 0x80>;
                        interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer7";
-                       ti,timer-dsp;
                };
 
                timer8: timer@48826000 {
                        reg = <0x48826000 0x80>;
                        interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer8";
-                       ti,timer-dsp;
-                       ti,timer-pwm;
                };
 
                timer9: timer@4803e000 {
                        reg = <0x48088000 0x80>;
                        interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer11";
-                       ti,timer-pwm;
+               };
+
+               timer12: timer@4ae20000 {
+                       compatible = "ti,omap5430-timer";
+                       reg = <0x4ae20000 0x80>;
+                       interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+                       ti,hwmods = "timer12";
+                       ti,timer-alwon;
+                       ti,timer-secure;
+                       status = "disabled";
                };
 
                timer13: timer@48828000 {
                };
 
                dmm@4e000000 {
-                       compatible = "ti,omap5-dmm";
+                       compatible = "ti,dra7-dmm", "ti,omap5-dmm";
                        reg = <0x4e000000 0x800>;
                        interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "dmm";
                        reg-names = "l2ram";
                        ti,hwmods = "ipu1";
                        iommus = <&mmu_ipu1>;
+                       ti,rproc-standby-info = <0x4a005520>;
                        status = "disabled";
                };
 
                        reg-names = "l2ram";
                        ti,hwmods = "ipu2";
                        iommus = <&mmu_ipu2>;
+                       ti,rproc-standby-info = <0x4a008920>;
                        status = "disabled";
                };
 
                        reg-names = "l2ram";
                        ti,hwmods = "dsp1";
                        iommus = <&mmu0_dsp1>, <&mmu1_dsp1>;
+                       ti,rproc-standby-info = <0x4a005420>;
                        status = "disabled";
                };
 
                        ti,hwmods = "pruss1";
                        reg = <0x4b200000 0x2000>,
                              <0x4b202000 0x2000>,
-                             <0x4b210000 0x10000>,
+                             <0x4b210000 0x8000>,
                              <0x4b220000 0x2000>,
                              <0x4b226000 0x2000>;
                        reg-names = "dram0", "dram1", "shrdram2", "intc", "cfg";
                        ti,clock-cycles = <16>;
 
                        reg = <0x4ae07ddc 0x4>, <0x4ae07de0 0x4>,
-                             <0x4ae06014 0x4>, <0x4a003b20 0x8>,
+                             <0x4ae06014 0x4>, <0x4a003b20 0xc>,
                              <0x4ae0c158 0x4>;
                        reg-names = "setup-address", "control-address",
                                    "int-address", "efuse-address",
                        ti,clock-cycles = <16>;
 
                        reg = <0x4ae07e34 0x4>, <0x4ae07e24 0x4>,
-                             <0x4ae06010 0x4>, <0x4a0025cc 0x8>,
+                             <0x4ae06010 0x4>, <0x4a0025cc 0xc>,
                              <0x4a002470 0x4>;
                        reg-names = "setup-address", "control-address",
                                    "int-address", "efuse-address",
                        ti,clock-cycles = <16>;
 
                        reg = <0x4ae07e30 0x4>, <0x4ae07e20 0x4>,
-                             <0x4ae06010 0x4>, <0x4a0025e0 0x8>,
+                             <0x4ae06010 0x4>, <0x4a0025e0 0xc>,
                              <0x4a00246c 0x4>;
                        reg-names = "setup-address", "control-address",
                                    "int-address", "efuse-address",
                        ti,clock-cycles = <16>;
 
                        reg = <0x4ae07de4 0x4>, <0x4ae07de8 0x4>,
-                             <0x4ae06010 0x4>, <0x4a003b08 0x8>,
+                             <0x4ae06010 0x4>, <0x4a003b08 0xc>,
                              <0x4ae0c154 0x4>;
                        reg-names = "setup-address", "control-address",
                                    "int-address", "efuse-address",
                        compatible = "ti,omap5-voltdm";
                        #voltdm-cells = <0>;
                        vbb-supply = <&abb_mpu>;
-                       reg = <0x4a003b20 0x8>;
+                       reg = <0x4a003b20 0xc>;
                        ti,efuse-settings = <
                        /* uV   offset */
                        1060000 0x0
                        compatible = "ti,omap5-voltdm";
                        #voltdm-cells = <0>;
                        vbb-supply = <&abb_ivahd>;
-                       reg = <0x4a0025cc 0x8>;
+                       reg = <0x4a0025cc 0xc>;
                        ti,efuse-settings = <
                        /* uV   offset */
                        1055000 0x0
                        compatible = "ti,omap5-voltdm";
                        #voltdm-cells = <0>;
                        vbb-supply = <&abb_dspeve>;
-                       reg = <0x4a0025e0 0x8>;
+                       reg = <0x4a0025e0 0xc>;
                        ti,efuse-settings = <
                        /* uV   offset */
                        1055000 0x0
                        compatible = "ti,omap5-voltdm";
                        #voltdm-cells = <0>;
                        vbb-supply = <&abb_gpu>;
-                       reg = <0x4a003b08 0x8>;
+                       reg = <0x4a003b08 0xc>;
                        ti,efuse-settings = <
                        /* uV   offset */
                        1090000 0x0
                        };
                };
 
-               aes: aes@4b500000 {
+               aes1: aes@4b500000 {
                        compatible = "ti,omap4-aes";
-                       ti,hwmods = "aes";
+                       ti,hwmods = "aes1";
                        reg = <0x4b500000 0xa0>;
                        interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
                        dmas = <&sdma 111 &dmacb>, <&sdma 110 &dmacb>;
                        clock-names = "fck";
                };
 
+               aes2: aes@4b700000 {
+                       compatible = "ti,omap4-aes";
+                       ti,hwmods = "aes2";
+                       reg = <0x4b700000 0xa0>;
+                       interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+                       dmas = <&sdma 114 &dmacb>, <&sdma 113 &dmacb>;
+                       dma-names = "tx", "rx";
+                       clocks = <&l3_iclk_div>;
+                       clock-names = "fck";
+               };
+
                des: des@480a5000 {
                        compatible = "ti,omap4-des";
                        ti,hwmods = "des";
                        status = "disabled";
                };
 
+               mcasp8: mcasp@4847c000 {
+                       compatible = "ti,dra7-mcasp-audio";
+                       ti,hwmods = "mcasp8";
+                       reg = <0x4847c000 0x2000>,
+                             <0x48454000 0x1000>;
+                       reg-names = "mpu","dat";
+                       interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "tx", "rx";
+                       dmas = <&sdma 143 &dmacb>, <&sdma 142 &dmacb>;
+                       dma-names = "tx", "rx";
+                       clocks = <&mcasp8_ahclkx_mux>;
+                       clock-names = "fck";
+                       status = "disabled";
+               };
+
                vip1: vip@0x48970000 {
                         compatible = "ti,vip1";
                        reg = <0x48970000 0x10000>,
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
+                       csi2_0: port@0 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0>;
+                       };
+                       csi2_1: port@1 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <1>;
+                       };
                };
 
                epwmss0: epwmss@4843e000 {
diff --git a/arch/arm/boot/dts/dra72-evm-lcd7.dts b/arch/arm/boot/dts/dra72-evm-lcd7.dts
deleted file mode 100644 (file)
index 6a8dba8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "dra72-evm.dts"
-#include "dra7xx-evm-lcd7.dtsi"
-
-&dss {
-       pinctrl-names = "default";
-       pinctrl-0 = <&vout1_pins>;
-};
index e8680421ba0c34e11e7a436d8cbbcd2f94fc380e..aeb08ea3f561d27265a8413cb488751e216bb900 100644 (file)
                        "LINE1L",               "Line In",
                        "LINE1R",               "Line In";
        };
+
+       vmmcwl_fixed: fixedregulator-mmcwl {
+               compatible = "regulator-fixed";
+               regulator-name = "vmmcwl_fixed";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               gpio = <&gpio5 8 GPIO_ACTIVE_HIGH>; /* gpio5_8 */
+               enable-active-high;
+       };
+
+       kim {
+               compatible = "kim";
+               nshutdown_gpio = <132>;
+               dev_name = "/dev/ttyS2";
+               flow_cntrl = <1>;
+               baud_rate = <3686400>;
+       };
+
+       btwilink {
+               compatible = "btwilink";
+       };
 };
 
 &dra7_pmx_core {
                        0x418   (MUX_MODE15 | PULL_UP)  /* wakeup0.off */
                >;
        };
+
+       wlan_pins: pinmux_wlan_pins {
+               pinctrl-single,pins = <
+                       0x3e8 (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart1_ctsn.mmc4_clk */
+                       0x3ec (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart1_rtsn.mmc4_cmd */
+                       0x3f0 (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart2_rxd.mmc4_dat0 */
+                       0x3f4 (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart2_txd.mmc4_dat1 */
+                       0x3f8 (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart2_ctsn.mmc4_dat2 */
+                       0x3fc (PIN_INPUT_PULLUP | MUX_MODE3)    /* uart2_rtsn.mmc4_dat3 */
+                       0x2cc (PIN_OUTPUT | MUX_MODE14)         /* mcasp1_axr6.gpio5_8 - WLAN_EN */
+               >;
+       };
+
+       wlirq_pins: pinmux_wlirq_pins {
+               pinctrl-single,pins = <
+                       0x2c8 (PIN_INPUT_PULLUP | WAKEUP_EN | MUX_MODE14 ) /* mcasp1_axr5.gpio5_7 - WLAN_IRQ */
+               >;
+       };
+
+       vin1a_pins: pinmux_vin1a_pins {
+               pinctrl-single,pins = <
+                       0x0DC   (PIN_INPUT | MUX_MODE0) /* vin1a_clk0 */
+                       0x0E4   (PIN_INPUT | MUX_MODE0) /* vin1a_de0 */
+                       0x0E8   (PIN_INPUT | MUX_MODE0) /* vin1a_fld0 */
+                       0x0EC   (PIN_INPUT | MUX_MODE0) /* vin1a_hsync0 */
+                       0x0F0   (PIN_INPUT | MUX_MODE0) /* vin1a_vsync0 */
+                       0x0F4   (PIN_INPUT | MUX_MODE0) /* vin1a_d0 */
+                       0x0F8   (PIN_INPUT | MUX_MODE0) /* vin1a_d1 */
+                       0x0FC   (PIN_INPUT | MUX_MODE0) /* vin1a_d2 */
+                       0x100   (PIN_INPUT | MUX_MODE0) /* vin1a_d3 */
+                       0x104   (PIN_INPUT | MUX_MODE0) /* vin1a_d4 */
+                       0x108   (PIN_INPUT | MUX_MODE0) /* vin1a_d5 */
+                       0x10C   (PIN_INPUT | MUX_MODE0) /* vin1a_d6 */
+                       0x110   (PIN_INPUT | MUX_MODE0) /* vin1a_d7 */
+                       0x114   (PIN_INPUT | MUX_MODE0) /* vin1a_d8 */
+                       0x118   (PIN_INPUT | MUX_MODE0) /* vin1a_d9 */
+                       0x11C   (PIN_INPUT | MUX_MODE0) /* vin1a_d10 */
+                       0x120   (PIN_INPUT | MUX_MODE0) /* vin1a_d11 */
+                       0x124   (PIN_INPUT | MUX_MODE0) /* vin1a_d12 */
+                       0x128   (PIN_INPUT | MUX_MODE0) /* vin1a_d13 */
+                       0x12C   (PIN_INPUT | MUX_MODE0) /* vin1a_d14 */
+                       0x130   (PIN_INPUT | MUX_MODE0) /* vin1a_d15 */
+               >;
+       };
+
+       vin1a_d16_d23_pins: pinmux_vin1a_d16_d23_pins {
+               pinctrl-single,pins = <
+                       0x134   (PIN_INPUT | MUX_MODE0) /* vin1a_d16 */
+                       0x138   (PIN_INPUT | MUX_MODE0) /* vin1a_d17 */
+                       0x13C   (PIN_INPUT | MUX_MODE0) /* vin1a_d18 */
+                       0x140   (PIN_INPUT | MUX_MODE0) /* vin1a_d19 */
+                       0x144   (PIN_INPUT | MUX_MODE0) /* vin1a_d20 */
+                       0x148   (PIN_INPUT | MUX_MODE0) /* vin1a_d21 */
+                       0x14C   (PIN_INPUT | MUX_MODE0) /* vin1a_d22 */
+                       0x150   (PIN_INPUT | MUX_MODE0) /* vin1a_d23 */
+
+               >;
+       };
+
+       vin2a_pins: pinmux_vin2a_pins {
+               pinctrl-single,pins = <
+                       0x154   (PIN_INPUT | MUX_MODE0) /* vin2a_clk0 */
+                       0x160   (PIN_INPUT | MUX_MODE0) /* vin2a_hsync0 */
+                       0x164   (PIN_INPUT | MUX_MODE0) /* vin2a_vsync0 */
+                       0x168   (PIN_INPUT | MUX_MODE0) /* vin2a_d0 */
+                       0x16c   (PIN_INPUT | MUX_MODE0) /* vin2a_d1 */
+                       0x170   (PIN_INPUT | MUX_MODE0) /* vin2a_d2 */
+                       0x174   (PIN_INPUT | MUX_MODE0) /* vin2a_d3 */
+                       0x178   (PIN_INPUT | MUX_MODE0) /* vin2a_d4 */
+                       0x17c   (PIN_INPUT | MUX_MODE0) /* vin2a_d5 */
+                       0x180   (PIN_INPUT | MUX_MODE0) /* vin2a_d6 */
+                       0x184   (PIN_INPUT | MUX_MODE0) /* vin2a_d7 */
+               >;
+       };
+
 };
 
 &i2c1 {
                 */
                lines-initial-states = <0x0f2b>;
        };
+
+       ov10633@37 {
+               compatible = "ovti,ov10633";
+               reg = <0x37>;
+
+               mux-gpios = <&pcf_hdmi 2        GPIO_ACTIVE_HIGH>, /* VIN2_S0 */
+                           <&pcf_hdmi 6        GPIO_ACTIVE_LOW>; /* VIN2_S2 */
+               port {
+                       onboardLI: endpoint {
+                               remote-endpoint = <&vin2a>;
+                               hsync-active = <1>;
+                               vsync-active = <1>;
+                               pclk-sample = <0>;
+                       };
+               };
+       };
 };
 
 &uart1 {
        status = "okay";
 };
 
+&uart3 {
+       status = "okay";
+       gpios = <&pcf_gpio_21 14 GPIO_ACTIVE_LOW>;
+};
+
 &mmc1 {
        /* Using default configured pins */
        status = "okay";
        max-frequency = <192000000>;
 };
 
+&mmc4 {
+       status = "okay";
+       vmmc-supply = <&vmmcwl_fixed>;
+       bus-width = <4>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&wlan_pins &wlirq_pins>;
+       cap-power-off-card;
+       keep-power-in-suspend;
+       ti,non-removable;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@0 {
+               compatible = "ti,wlcore";
+               reg = <2>;
+               interrupt-parent = <&gpio5>;
+               interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
+       };
+};
+
 &mac {
        status = "okay";
        pinctrl-names = "default", "sleep";
        memory-region = <&ipu1_cma_pool>;
        mboxes = <&mailbox5 &mbox_ipu1_legacy>;
        timers = <&timer11>;
+       watchdog-timers = <&timer7>, <&timer8>;
 };
 
 &dsp1 {
        memory-region = <&dsp1_cma_pool>;
        mboxes = <&mailbox5 &mbox_dsp1_legacy>;
        timers = <&timer5>;
+       watchdog-timers = <&timer10>;
 };
 
 &atl {
        pinctrl-0 = <&dcan1_pins_default>;
        pinctrl-1 = <&dcan1_pins_sleep>;
 };
+
+&vip1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&vin2a_pins>;
+       status = "okay";
+};
+
+&vin2a {
+       endpoint@0 {
+               slave-mode;
+               remote-endpoint = <&onboardLI>;
+       };
+};
+
+&cal {
+       status = "okay";
+};
index c6ae2148a6cef3ae9fb2a9f3103fb9297b3bdfd3..1849cc26f60751d2ad23f9dba9ee3d215c4ab398 100644 (file)
@@ -99,6 +99,7 @@
                        reg-names = "l2ram";
                        ti,hwmods = "dsp2";
                        iommus = <&mmu0_dsp2>, <&mmu1_dsp2>;
+                       ti,rproc-standby-info = <0x4a005620>;
                        status = "disabled";
                };
        };
index 36bcf3fdad0438e4e41f49453c1e92c7178dbf3a..f1fc0af45ece27bcd9bcf3cc07449ef91b26800f 100644 (file)
                compatible = "ti,omap4-dpll-m4xen-clock";
                clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
                reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
+               ti,sink-clkdm = <&atl_clkdm>;
        };
 
        dpll_abe_x2_ck: dpll_abe_x2_ck {
                compatible = "ti,omap4-dpll-clock";
                clocks = <&sys_clkin1>, <&dpll_dsp_byp_mux>;
                reg = <0x0234>, <0x0238>, <0x0240>, <0x023c>;
+               ti,sink-clkdm = <&dsp1_clkdm>;
        };
 
        dpll_dsp_m2_ck: dpll_dsp_m2_ck {
                compatible = "ti,omap4-dpll-clock";
                clocks = <&sys_clkin1>, <&dpll_iva_byp_mux>;
                reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>;
+               ti,sink-clkdm = <&iva_clkdm>;
        };
 
        dpll_iva_m2_ck: dpll_iva_m2_ck {
                compatible = "ti,omap4-dpll-clock";
                clocks = <&sys_clkin1>, <&dpll_gpu_byp_mux>;
                reg = <0x02d8>, <0x02dc>, <0x02e4>, <0x02e0>;
+               ti,sink-clkdm = <&gpu_clkdm>;
        };
 
        dpll_gpu_m2_ck: dpll_gpu_m2_ck {
                compatible = "ti,omap4-dpll-clock";
                clocks = <&sys_clkin1>, <&dpll_gmac_byp_mux>;
                reg = <0x02a8>, <0x02ac>, <0x02b4>, <0x02b0>;
+               ti,sink-clkdm = <&gmac_clkdm>;
        };
 
        dpll_gmac_m2_ck: dpll_gmac_m2_ck {
                compatible = "ti,omap4-dpll-clock";
                clocks = <&sys_clkin1>, <&dpll_eve_byp_mux>;
                reg = <0x0284>, <0x0288>, <0x0290>, <0x028c>;
+               ti,sink-clkdm = <&eve1_clkdm>;
        };
 
        dpll_eve_m2_ck: dpll_eve_m2_ck {
                compatible = "ti,omap4-dpll-clock";
                clocks = <&sys_clkin1>, <&sys_clkin1>;
                reg = <0x0200>, <0x0204>, <0x020c>, <0x0208>;
+               ti,sink-clkdm = <&pcie_clkdm>;
        };
 
        dpll_pcie_ref_m2ldo_ck: dpll_pcie_ref_m2ldo_ck {
                compatible = "ti,omap4-dpll-j-type-clock";
                clocks = <&sys_clkin1>, <&dpll_usb_byp_mux>;
                reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>;
+               ti,sink-clkdm = <&l3init_clkdm>;
        };
 
        dpll_usb_m2_ck: dpll_usb_m2_ck {
                reg = <0x1908>;
        };
 
-       mcasp8_ahclk_mux: mcasp8_ahclk_mux {
+       mcasp8_ahclkx_mux: mcasp8_ahclkx_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
                clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                compatible = "ti,clockdomain";
                clocks = <&dpll_usb_ck>;
        };
+
+       gpu_clkdm: gpu_clkdm {
+               compatible = "ti,clockdomain";
+       };
+
+       pcie_clkdm: pcie_clkdm {
+               compatible = "ti,clockdomain";
+       };
+
+       iva_clkdm: iva_clkdm {
+               compatible = "ti,clockdomain";
+       };
+
+       dsp1_clkdm: dsp1_clkdm {
+               compatible = "ti,clockdomain";
+       };
+
+       gmac_clkdm: gmac_clkdm {
+               compatible = "ti,clockdomain";
+       };
+
+       l3init_clkdm: l3init_clkdm {
+               compatible = "ti,clockdomain";
+       };
+
+       eve1_clkdm: eve1_clkdm {
+               compatible = "ti,clockdomain";
+       };
+
+       atl_clkdm: atl_clkdm {
+               compatible = "ti,clockdomain";
+       };
 };
 
 &ctrl_core_clocks {
diff --git a/arch/arm/boot/dts/dra7xx-evm-lcd7.dtsi b/arch/arm/boot/dts/dra7xx-evm-lcd7.dtsi
deleted file mode 100644 (file)
index ded5ea5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "dra7xx-evm-lcd10.dtsi"
-
-&tlc59108 {
-       compatible = "ti,tlc59108-tfcs9700";
-};
index 526bfdbd87f9f84f08747c6c045c059a657d2cbc..f8922fb9bf507d70750687bca626b9035bd11f54 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "imx23.dtsi"
 
 / {
@@ -93,6 +94,7 @@
 
        ahb@80080000 {
                usb0: usb@80080000 {
+                       dr_mode = "host";
                        vbus-supply = <&reg_usb0_vbus>;
                        status = "okay";
                };
 
                user {
                        label = "green";
-                       gpios = <&gpio2 1 1>;
+                       gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
                };
        };
 };
index cf3300a3071dac7b9a6d073a7ae071e57f21087c..bfc327ff70af3c25f52036e80c62398e451a1b5a 100644 (file)
 
                        pwm4: pwm@53fc8000 {
                                compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+                               #pwm-cells = <2>;
                                reg = <0x53fc8000 0x4000>;
                                clocks = <&clks 108>, <&clks 52>;
                                clock-names = "ipg", "per";
index f8e9b20f69820c6948bd84b11a14166db6b4bdd3..ee1a4da35cc40b3be8ddff43be4195c9bd7440c8 100644 (file)
                                              80 81 68 69
                                              70 71 72 73
                                              74 75 76 77>;
-                               interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+                               interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
                                                  "saif0", "saif1", "i2c0", "i2c1",
                                                  "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
                                                  "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
index f6b7e4f850b3f72974480dcfd34417c235199be3..38fd6b84c41f7dfdbfda38f53c6f62996c39d933 100644 (file)
                        ti,hwmods = "dsp";
                        iommus = <&mmu_dsp>;
                        mboxes = <&mailbox &mbox_dsp>;
+                       ti,rproc-standby-info = <0x4a004420>;
                        status = "disabled";
                };
 
                        ti,hwmods = "ipu";
                        iommus = <&mmu_ipu>;
                        mboxes = <&mailbox &mbox_ipu>;
+                       ti,rproc-standby-info = <0x4a008920>;
                        status = "disabled";
                };
 
index b92d17330d9f6d93d238617781c7d556523583c8..941c097156c2ac78da277c0212c3a95d14a9f504 100644 (file)
         * hierarchy.
         */
        ocp {
-               compatible = "ti,omap4-l3-noc", "simple-bus";
+               compatible = "ti,omap5-l3-noc", "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
                ranges;
                        ti,hwmods = "dsp";
                        iommus = <&mmu_dsp>;
                        mboxes = <&mailbox &mbox_dsp>;
+                       ti,rproc-standby-info = <0x4a004420>;
                        status = "disabled";
                };
 
                        ti,hwmods = "ipu";
                        iommus = <&mmu_ipu>;
                        mboxes = <&mailbox &mbox_ipu>;
+                       ti,rproc-standby-info = <0x4a008920>;
                        status = "disabled";
                };
 
index e0853ea02df2296dc78c997123f3173754df48a8..75e748efa9c252094614155855d0d2073c49e57e 100644 (file)
                        status = "disabled";
                };
 
-               vmmci: regulator-gpio {
-                       compatible = "regulator-gpio";
-
-                       regulator-min-microvolt = <1800000>;
-                       regulator-max-microvolt = <2900000>;
-                       regulator-name = "mmci-reg";
-                       regulator-type = "voltage";
-
-                       startup-delay-us = <100>;
-                       enable-active-high;
-
-                       states = <1800000 0x1
-                                 2900000 0x0>;
-
-                       status = "disabled";
-               };
-
                mcde@a0350000 {
                        compatible = "stericsson,mcde";
                        reg = <0xa0350000 0x1000>, /* MCDE */
index 6cb9b68e2188a59fecb89e750023551a17c0334f..0b668f87dd4031bac5889b4b6ea0f1c020ca8670 100644 (file)
                        pinctrl-1 = <&i2c3_sleep_mode>;
                };
 
+               vmmci: regulator-gpio {
+                       compatible = "regulator-gpio";
+
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <2900000>;
+                       regulator-name = "mmci-reg";
+                       regulator-type = "voltage";
+
+                       startup-delay-us = <100>;
+                       enable-active-high;
+
+                       states = <1800000 0x1
+                                 2900000 0x0>;
+               };
+
                // External Micro SD slot
                sdi0_per1@80126000 {
                        arm,primecell-periphid = <0x10480180>;
index 97d5d21b7db7c2bdb416c064ef389b3425f82b41..5deaf3c1292fb6d81e589bb7ca6dd8841bf30527 100644 (file)
                };
 
                vmmci: regulator-gpio {
+                       compatible = "regulator-gpio";
+
                        gpios = <&gpio7 4 0x4>;
                        enable-gpio = <&gpio6 25 0x4>;
+
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <2900000>;
+                       regulator-name = "mmci-reg";
+                       regulator-type = "voltage";
+
+                       startup-delay-us = <100>;
+                       enable-active-high;
+
+                       states = <1800000 0x1
+                                 2900000 0x0>;
                };
 
                // External Micro SD slot
index 67586c51361fb17c1de80e236d91aa7645580848..1baa939a1383a2cac53cc14ab04b1a7d39d5ef02 100644 (file)
@@ -435,8 +435,11 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data)
        if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
            (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
            (edma_read(ctlr, EDMA_QEMR) == 0) &&
-           (edma_read(ctlr, EDMA_CCERR) == 0))
+           (edma_read(ctlr, EDMA_CCERR) == 0)) {
+               dev_err(data, "%s: unmanaged event occured\n", __func__);
+               edma_write(ctlr, EDMA_EEVAL, 1);
                return IRQ_NONE;
+       }
 
        while (1) {
                int j = -1;
@@ -1350,6 +1353,9 @@ void edma_stop(unsigned channel)
                edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
                edma_write_array(ctlr, EDMA_EMCR, j, mask);
 
+               /* clear possibly pending completion interrupt */
+               edma_shadow0_write_array(ctlr, SH_ICR, j, mask);
+
                pr_debug("EDMA: EER%d %08x\n", j,
                                edma_shadow0_read_array(ctlr, SH_EER, j));
 
index 71e5fc7cfb18f489f3adadb20c6f8049421fb079..1d1800f71c5b3d372d33ec1e43acdaa35e17d3be 100644 (file)
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__  7
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
 #endif
 
 #ifdef __thumb__
 # define adrl adr
 #endif
 
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
+.arch  armv7-a
+.fpu   neon
+
 .text
 .syntax        unified         @ ARMv7-capable assembler is expected to handle this
 #ifdef __thumb2__
@@ -74,8 +78,6 @@
 .code   32
 #endif
 
-.fpu   neon
-
 .type  _bsaes_decrypt8,%function
 .align 4
 _bsaes_decrypt8:
@@ -2095,9 +2097,11 @@ bsaes_xts_decrypt:
        vld1.8  {q8}, [r0]                      @ initial tweak
        adr     r2, .Lxts_magic
 
+#ifndef        XTS_CHAIN_TWEAK
        tst     r9, #0xf                        @ if not multiple of 16
        it      ne                              @ Thumb2 thing, sanity check in ARM
        subne   r9, #0x10                       @ subtract another 16 bytes
+#endif
        subs    r9, #0x80
 
        blo     .Lxts_dec_short
index be068db960ee0006ac1aa25a4e69b95265404844..a4d3856e7d2477ec6379f1f10a9121e32f36a974 100644 (file)
@@ -701,14 +701,18 @@ $code.=<<___;
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__  7
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_MAX_ARCH__ 7
 #endif
 
 #ifdef __thumb__
 # define adrl adr
 #endif
 
-#if __ARM_ARCH__>=7
+#if __ARM_MAX_ARCH__>=7
+.arch  armv7-a
+.fpu   neon
+
 .text
 .syntax        unified         @ ARMv7-capable assembler is expected to handle this
 #ifdef __thumb2__
@@ -717,8 +721,6 @@ $code.=<<___;
 .code   32
 #endif
 
-.fpu   neon
-
 .type  _bsaes_decrypt8,%function
 .align 4
 _bsaes_decrypt8:
@@ -2076,9 +2078,11 @@ bsaes_xts_decrypt:
        vld1.8  {@XMM[8]}, [r0]                 @ initial tweak
        adr     $magic, .Lxts_magic
 
+#ifndef        XTS_CHAIN_TWEAK
        tst     $len, #0xf                      @ if not multiple of 16
        it      ne                              @ Thumb2 thing, sanity check in ARM
        subne   $len, #0x10                     @ subtract another 16 bytes
+#endif
        subs    $len, #0x80
 
        blo     .Lxts_dec_short
index f4b46d39b9cfb12756050a992262367ce575f90b..051b7269e639911210b631e544b026324e4e7d5d 100644 (file)
@@ -114,7 +114,7 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE        (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE        (TASK_SIZE / 3 * 2)
 
 /* When the program starts, a1 contains a pointer to a function to be 
    registered with atexit, as per the SVR4 ABI.  A value of 0 means we 
index 1d3153c7eb41c54d1e97fcd6078057fe5735a7dd..816db0bf2dd8addbd9844488b5a72d4495be72c7 100644 (file)
@@ -55,6 +55,7 @@
  * The bits we set in HCR:
  * TAC:                Trap ACTLR
  * TSC:                Trap SMC
+ * TVM:                Trap VM ops (until MMU and caches are on)
  * TSW:                Trap cache operations by set/way
  * TWI:                Trap WFI
  * TWE:                Trap WFE
@@ -68,8 +69,7 @@
  */
 #define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \
                        HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \
-                       HCR_TWE | HCR_SWIO | HCR_TIDCP)
-#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
+                       HCR_TVM | HCR_TWE | HCR_SWIO | HCR_TIDCP)
 
 /* System Control Register (SCTLR) bits */
 #define SCTLR_TE       (1 << 30)
index 661da11f76f4a5eca006850396c7760034fab48f..53b3c4a50d5c16fcac649852b399392a11ed0692 100644 (file)
@@ -48,7 +48,9 @@
 #define c13_TID_URO    26      /* Thread ID, User R/O */
 #define c13_TID_PRIV   27      /* Thread ID, Privileged */
 #define c14_CNTKCTL    28      /* Timer Control Register (PL1) */
-#define NR_CP15_REGS   29      /* Number of regs (incl. invalid) */
+#define c10_AMAIR0     29      /* Auxilary Memory Attribute Indirection Reg0 */
+#define c10_AMAIR1     30      /* Auxilary Memory Attribute Indirection Reg1 */
+#define NR_CP15_REGS   31      /* Number of regs (incl. invalid) */
 
 #define ARM_EXCEPTION_RESET      0
 #define ARM_EXCEPTION_UNDEFINED   1
index 098f7dd6d56414cf40c0f7df4589956537a12106..09af14999c9b2458adee96fc9a9c8ff621a720ca 100644 (file)
@@ -101,6 +101,12 @@ struct kvm_vcpu_arch {
        /* The CPU type we expose to the VM */
        u32 midr;
 
+       /* HYP trapping configuration */
+       u32 hcr;
+
+       /* Interrupt related fields */
+       u32 irq_lines;          /* IRQ and FIQ levels */
+
        /* Exception Information */
        struct kvm_vcpu_fault_info fault;
 
@@ -128,9 +134,6 @@ struct kvm_vcpu_arch {
        /* IO related fields */
        struct kvm_decode mmio_decode;
 
-       /* Interrupt related fields */
-       u32 irq_lines;          /* IRQ and FIQ levels */
-
        /* Cache some mmu pages needed inside spinlock regions */
        struct kvm_mmu_memory_cache mmu_page_cache;
 
index 2d122adcdb22108984a46f8483b5d2ed6b37b811..7b362bc9c09ad46eb30c84fb26c8d09513ec4b3d 100644 (file)
@@ -114,11 +114,34 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
        pmd_val(*pmd) |= L_PMD_S2_RDWR;
 }
 
+/* Open coded p*d_addr_end that can deal with 64bit addresses */
+#define kvm_pgd_addr_end(addr, end)                                    \
+({     u64 __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK;            \
+       (__boundary - 1 < (end) - 1)? __boundary: (end);                \
+})
+
+#define kvm_pud_addr_end(addr,end)             (end)
+
+#define kvm_pmd_addr_end(addr, end)                                    \
+({     u64 __boundary = ((addr) + PMD_SIZE) & PMD_MASK;                \
+       (__boundary - 1 < (end) - 1)? __boundary: (end);                \
+})
+
 struct kvm;
 
-static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva,
-                                             unsigned long size)
+#define kvm_flush_dcache_to_poc(a,l)   __cpuc_flush_dcache_area((a), (l))
+
+static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
 {
+       return (vcpu->arch.cp15[c1_SCTLR] & 0b101) == 0b101;
+}
+
+static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
+                                            unsigned long size)
+{
+       if (!vcpu_has_cache_enabled(vcpu))
+               kvm_flush_dcache_to_poc((void *)hva, size);
+
        /*
         * If we are going to insert an instruction page and the icache is
         * either VIPT or PIPT, there is a potential problem where the host
@@ -139,9 +162,10 @@ static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva,
        }
 }
 
-#define kvm_flush_dcache_to_poc(a,l)   __cpuc_flush_dcache_area((a), (l))
 #define kvm_virt_to_phys(x)            virt_to_idmap((unsigned long)(x))
 
+void stage2_flush_vm(struct kvm *kvm);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __ARM_KVM_MMU_H__ */
index 626989fec4d334ef8c01f707f87de6a25c1d8a8e..9fd61c72a33a1417704881274239e2fd29053cce 100644 (file)
@@ -43,7 +43,7 @@
 #define PMD_SECT_BUFFERABLE    (_AT(pmdval_t, 1) << 2)
 #define PMD_SECT_CACHEABLE     (_AT(pmdval_t, 1) << 3)
 #define PMD_SECT_USER          (_AT(pmdval_t, 1) << 6)         /* AP[1] */
-#define PMD_SECT_RDONLY                (_AT(pmdval_t, 1) << 7)         /* AP[2] */
+#define PMD_SECT_AP2           (_AT(pmdval_t, 1) << 7)         /* read only */
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
 #define PMD_SECT_AF            (_AT(pmdval_t, 1) << 10)
 #define PMD_SECT_nG            (_AT(pmdval_t, 1) << 11)
@@ -72,6 +72,7 @@
 #define PTE_TABLE_BIT          (_AT(pteval_t, 1) << 1)
 #define PTE_BUFFERABLE         (_AT(pteval_t, 1) << 2)         /* AttrIndx[0] */
 #define PTE_CACHEABLE          (_AT(pteval_t, 1) << 3)         /* AttrIndx[1] */
+#define PTE_AP2                        (_AT(pteval_t, 1) << 7)         /* AP[2] */
 #define PTE_EXT_SHARED         (_AT(pteval_t, 3) << 8)         /* SH[1:0], inner shareable */
 #define PTE_EXT_AF             (_AT(pteval_t, 1) << 10)        /* Access Flag */
 #define PTE_EXT_NG             (_AT(pteval_t, 1) << 11)        /* nG */
index 85c60adc8b60bd04a68c3012b0c22ec7c1bf9bba..06e0bc0f8b00b2c7f9fe9f6dac97c81b00b803bb 100644 (file)
 #define L_PTE_PRESENT          (_AT(pteval_t, 3) << 0)         /* Present */
 #define L_PTE_FILE             (_AT(pteval_t, 1) << 2)         /* only when !PRESENT */
 #define L_PTE_USER             (_AT(pteval_t, 1) << 6)         /* AP[1] */
-#define L_PTE_RDONLY           (_AT(pteval_t, 1) << 7)         /* AP[2] */
 #define L_PTE_SHARED           (_AT(pteval_t, 3) << 8)         /* SH[1:0], inner shareable */
 #define L_PTE_YOUNG            (_AT(pteval_t, 1) << 10)        /* AF */
 #define L_PTE_XN               (_AT(pteval_t, 1) << 54)        /* XN */
-#define L_PTE_DIRTY            (_AT(pteval_t, 1) << 55)        /* unused */
-#define L_PTE_SPECIAL          (_AT(pteval_t, 1) << 56)        /* unused */
+#define L_PTE_DIRTY            (_AT(pteval_t, 1) << 55)
+#define L_PTE_SPECIAL          (_AT(pteval_t, 1) << 56)
 #define L_PTE_NONE             (_AT(pteval_t, 1) << 57)        /* PROT_NONE */
+#define L_PTE_RDONLY           (_AT(pteval_t, 1) << 58)        /* READ ONLY */
 
-#define PMD_SECT_VALID         (_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_DIRTY         (_AT(pmdval_t, 1) << 55)
-#define PMD_SECT_SPLITTING     (_AT(pmdval_t, 1) << 56)
-#define PMD_SECT_NONE          (_AT(pmdval_t, 1) << 57)
+#define L_PMD_SECT_VALID       (_AT(pmdval_t, 1) << 0)
+#define L_PMD_SECT_DIRTY       (_AT(pmdval_t, 1) << 55)
+#define L_PMD_SECT_SPLITTING   (_AT(pmdval_t, 1) << 56)
+#define L_PMD_SECT_NONE                (_AT(pmdval_t, 1) << 57)
+#define L_PMD_SECT_RDONLY      (_AT(pteval_t, 1) << 58)
 
 /*
  * To be used in assembly code with the upper page attributes.
@@ -207,27 +208,32 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 #define pte_huge(pte)          (pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT))
 #define pte_mkhuge(pte)                (__pte(pte_val(pte) & ~PTE_TABLE_BIT))
 
-#define pmd_young(pmd)         (pmd_val(pmd) & PMD_SECT_AF)
+#define pmd_isset(pmd, val)    ((u32)(val) == (val) ? pmd_val(pmd) & (val) \
+                                               : !!(pmd_val(pmd) & (val)))
+#define pmd_isclear(pmd, val)  (!(pmd_val(pmd) & (val)))
+
+#define pmd_young(pmd)         (pmd_isset((pmd), PMD_SECT_AF))
 
 #define __HAVE_ARCH_PMD_WRITE
-#define pmd_write(pmd)         (!(pmd_val(pmd) & PMD_SECT_RDONLY))
+#define pmd_write(pmd)         (pmd_isclear((pmd), L_PMD_SECT_RDONLY))
+#define pmd_dirty(pmd)         (pmd_isset((pmd), L_PMD_SECT_DIRTY))
 
 #define pmd_hugewillfault(pmd) (!pmd_young(pmd) || !pmd_write(pmd))
 #define pmd_thp_or_huge(pmd)   (pmd_huge(pmd) || pmd_trans_huge(pmd))
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define pmd_trans_huge(pmd)    (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
-#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
+#define pmd_trans_huge(pmd)    (pmd_val(pmd) && !pmd_table(pmd))
+#define pmd_trans_splitting(pmd) (pmd_isset((pmd), L_PMD_SECT_SPLITTING))
 #endif
 
 #define PMD_BIT_FUNC(fn,op) \
 static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
 
-PMD_BIT_FUNC(wrprotect,        |= PMD_SECT_RDONLY);
+PMD_BIT_FUNC(wrprotect,        |= L_PMD_SECT_RDONLY);
 PMD_BIT_FUNC(mkold,    &= ~PMD_SECT_AF);
-PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
-PMD_BIT_FUNC(mkwrite,   &= ~PMD_SECT_RDONLY);
-PMD_BIT_FUNC(mkdirty,   |= PMD_SECT_DIRTY);
+PMD_BIT_FUNC(mksplitting, |= L_PMD_SECT_SPLITTING);
+PMD_BIT_FUNC(mkwrite,   &= ~L_PMD_SECT_RDONLY);
+PMD_BIT_FUNC(mkdirty,   |= L_PMD_SECT_DIRTY);
 PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
 
 #define pmd_mkhuge(pmd)                (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
@@ -241,8 +247,8 @@ PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
 {
-       const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY |
-                               PMD_SECT_VALID | PMD_SECT_NONE;
+       const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | L_PMD_SECT_RDONLY |
+                               L_PMD_SECT_VALID | L_PMD_SECT_NONE;
        pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
        return pmd;
 }
@@ -253,8 +259,13 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
        BUG_ON(addr >= TASK_SIZE);
 
        /* create a faulting entry if PROT_NONE protected */
-       if (pmd_val(pmd) & PMD_SECT_NONE)
-               pmd_val(pmd) &= ~PMD_SECT_VALID;
+       if (pmd_val(pmd) & L_PMD_SECT_NONE)
+               pmd_val(pmd) &= ~L_PMD_SECT_VALID;
+
+       if (pmd_write(pmd) && pmd_dirty(pmd))
+               pmd_val(pmd) &= ~PMD_SECT_AP2;
+       else
+               pmd_val(pmd) |= PMD_SECT_AP2;
 
        *pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG);
        flush_pmd_entry(pmdp);
index 7d59b524f2af3c48480762a9b41f36fefb04e546..89dba131703b6e7181a3dd20a9cdf954c126acab 100644 (file)
@@ -214,12 +214,16 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 
 #define pte_clear(mm,addr,ptep)        set_pte_ext(ptep, __pte(0), 0)
 
+#define pte_isset(pte, val)    ((u32)(val) == (val) ? pte_val(pte) & (val) \
+                                               : !!(pte_val(pte) & (val)))
+#define pte_isclear(pte, val)  (!(pte_val(pte) & (val)))
+
 #define pte_none(pte)          (!pte_val(pte))
-#define pte_present(pte)       (pte_val(pte) & L_PTE_PRESENT)
-#define pte_write(pte)         (!(pte_val(pte) & L_PTE_RDONLY))
-#define pte_dirty(pte)         (pte_val(pte) & L_PTE_DIRTY)
-#define pte_young(pte)         (pte_val(pte) & L_PTE_YOUNG)
-#define pte_exec(pte)          (!(pte_val(pte) & L_PTE_XN))
+#define pte_present(pte)       (pte_isset((pte), L_PTE_PRESENT))
+#define pte_write(pte)         (pte_isclear((pte), L_PTE_RDONLY))
+#define pte_dirty(pte)         (pte_isset((pte), L_PTE_DIRTY))
+#define pte_young(pte)         (pte_isset((pte), L_PTE_YOUNG))
+#define pte_exec(pte)          (pte_isclear((pte), L_PTE_XN))
 #define pte_special(pte)       (0)
 
 #define pte_present_user(pte)  (pte_present(pte) && (pte_val(pte) & L_PTE_USER))
index ded041711beb55fea6b8489996a0ada3e1c8d6c0..85598b5d1efdd6343a81fc3b4fa073b174de723c 100644 (file)
@@ -174,6 +174,7 @@ int main(void)
   DEFINE(VCPU_FIQ_REGS,                offsetof(struct kvm_vcpu, arch.regs.fiq_regs));
   DEFINE(VCPU_PC,              offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc));
   DEFINE(VCPU_CPSR,            offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr));
+  DEFINE(VCPU_HCR,             offsetof(struct kvm_vcpu, arch.hcr));
   DEFINE(VCPU_IRQ_LINES,       offsetof(struct kvm_vcpu, arch.irq_lines));
   DEFINE(VCPU_HSR,             offsetof(struct kvm_vcpu, arch.fault.hsr));
   DEFINE(VCPU_HxFAR,           offsetof(struct kvm_vcpu, arch.fault.hxfar));
index 78c0885d65015df28ea7554a5e97a85b588e9fb1..c58a35116f6307781064761f919dcd2112e22c20 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/kvm_host.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_mmu.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <trace/events/kvm.h>
@@ -204,6 +205,44 @@ done:
        return true;
 }
 
+/*
+ * Generic accessor for VM registers. Only called as long as HCR_TVM
+ * is set.
+ */
+static bool access_vm_reg(struct kvm_vcpu *vcpu,
+                         const struct coproc_params *p,
+                         const struct coproc_reg *r)
+{
+       BUG_ON(!p->is_write);
+
+       vcpu->arch.cp15[r->reg] = *vcpu_reg(vcpu, p->Rt1);
+       if (p->is_64bit)
+               vcpu->arch.cp15[r->reg + 1] = *vcpu_reg(vcpu, p->Rt2);
+
+       return true;
+}
+
+/*
+ * SCTLR accessor. Only called as long as HCR_TVM is set.  If the
+ * guest enables the MMU, we stop trapping the VM sys_regs and leave
+ * it in complete control of the caches.
+ *
+ * Used by the cpu-specific code.
+ */
+bool access_sctlr(struct kvm_vcpu *vcpu,
+                 const struct coproc_params *p,
+                 const struct coproc_reg *r)
+{
+       access_vm_reg(vcpu, p, r);
+
+       if (vcpu_has_cache_enabled(vcpu)) {     /* MMU+Caches enabled? */
+               vcpu->arch.hcr &= ~HCR_TVM;
+               stage2_flush_vm(vcpu->kvm);
+       }
+
+       return true;
+}
+
 /*
  * We could trap ID_DFR0 and tell the guest we don't support performance
  * monitoring.  Unfortunately the patch to make the kernel check ID_DFR0 was
@@ -261,33 +300,36 @@ static const struct coproc_reg cp15_regs[] = {
        { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32,
                        NULL, reset_val, c1_CPACR, 0x00000000 },
 
-       /* TTBR0/TTBR1: swapped by interrupt.S. */
-       { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
-       { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
-
-       /* TTBCR: swapped by interrupt.S. */
+       /* TTBR0/TTBR1/TTBCR: swapped by interrupt.S. */
+       { CRm64( 2), Op1( 0), is64, access_vm_reg, reset_unknown64, c2_TTBR0 },
+       { CRn(2), CRm( 0), Op1( 0), Op2( 0), is32,
+                       access_vm_reg, reset_unknown, c2_TTBR0 },
+       { CRn(2), CRm( 0), Op1( 0), Op2( 1), is32,
+                       access_vm_reg, reset_unknown, c2_TTBR1 },
        { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
-                       NULL, reset_val, c2_TTBCR, 0x00000000 },
+                       access_vm_reg, reset_val, c2_TTBCR, 0x00000000 },
+       { CRm64( 2), Op1( 1), is64, access_vm_reg, reset_unknown64, c2_TTBR1 },
+
 
        /* DACR: swapped by interrupt.S. */
        { CRn( 3), CRm( 0), Op1( 0), Op2( 0), is32,
-                       NULL, reset_unknown, c3_DACR },
+                       access_vm_reg, reset_unknown, c3_DACR },
 
        /* DFSR/IFSR/ADFSR/AIFSR: swapped by interrupt.S. */
        { CRn( 5), CRm( 0), Op1( 0), Op2( 0), is32,
-                       NULL, reset_unknown, c5_DFSR },
+                       access_vm_reg, reset_unknown, c5_DFSR },
        { CRn( 5), CRm( 0), Op1( 0), Op2( 1), is32,
-                       NULL, reset_unknown, c5_IFSR },
+                       access_vm_reg, reset_unknown, c5_IFSR },
        { CRn( 5), CRm( 1), Op1( 0), Op2( 0), is32,
-                       NULL, reset_unknown, c5_ADFSR },
+                       access_vm_reg, reset_unknown, c5_ADFSR },
        { CRn( 5), CRm( 1), Op1( 0), Op2( 1), is32,
-                       NULL, reset_unknown, c5_AIFSR },
+                       access_vm_reg, reset_unknown, c5_AIFSR },
 
        /* DFAR/IFAR: swapped by interrupt.S. */
        { CRn( 6), CRm( 0), Op1( 0), Op2( 0), is32,
-                       NULL, reset_unknown, c6_DFAR },
+                       access_vm_reg, reset_unknown, c6_DFAR },
        { CRn( 6), CRm( 0), Op1( 0), Op2( 2), is32,
-                       NULL, reset_unknown, c6_IFAR },
+                       access_vm_reg, reset_unknown, c6_IFAR },
 
        /* PAR swapped by interrupt.S */
        { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
@@ -324,9 +366,15 @@ static const struct coproc_reg cp15_regs[] = {
 
        /* PRRR/NMRR (aka MAIR0/MAIR1): swapped by interrupt.S. */
        { CRn(10), CRm( 2), Op1( 0), Op2( 0), is32,
-                       NULL, reset_unknown, c10_PRRR},
+                       access_vm_reg, reset_unknown, c10_PRRR},
        { CRn(10), CRm( 2), Op1( 0), Op2( 1), is32,
-                       NULL, reset_unknown, c10_NMRR},
+                       access_vm_reg, reset_unknown, c10_NMRR},
+
+       /* AMAIR0/AMAIR1: swapped by interrupt.S. */
+       { CRn(10), CRm( 3), Op1( 0), Op2( 0), is32,
+                       access_vm_reg, reset_unknown, c10_AMAIR0},
+       { CRn(10), CRm( 3), Op1( 0), Op2( 1), is32,
+                       access_vm_reg, reset_unknown, c10_AMAIR1},
 
        /* VBAR: swapped by interrupt.S. */
        { CRn(12), CRm( 0), Op1( 0), Op2( 0), is32,
@@ -334,7 +382,7 @@ static const struct coproc_reg cp15_regs[] = {
 
        /* CONTEXTIDR/TPIDRURW/TPIDRURO/TPIDRPRW: swapped by interrupt.S. */
        { CRn(13), CRm( 0), Op1( 0), Op2( 1), is32,
-                       NULL, reset_val, c13_CID, 0x00000000 },
+                       access_vm_reg, reset_val, c13_CID, 0x00000000 },
        { CRn(13), CRm( 0), Op1( 0), Op2( 2), is32,
                        NULL, reset_unknown, c13_TID_URW },
        { CRn(13), CRm( 0), Op1( 0), Op2( 3), is32,
@@ -443,7 +491,7 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
        struct coproc_params params;
 
-       params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf;
+       params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf;
        params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf;
        params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0);
        params.is_64bit = true;
@@ -451,7 +499,7 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
        params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 16) & 0xf;
        params.Op2 = 0;
        params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
-       params.CRn = 0;
+       params.CRm = 0;
 
        return emulate_cp15(vcpu, &params);
 }
index 0461d5c8d3de4f99c3ecfef669340ec6fa8e0411..1a44bbe39643f519ec986d43dcd3e416881d13a9 100644 (file)
@@ -58,8 +58,8 @@ static inline void print_cp_instr(const struct coproc_params *p)
 {
        /* Look, we even formatted it for you to paste into the table! */
        if (p->is_64bit) {
-               kvm_pr_unimpl(" { CRm(%2lu), Op1(%2lu), is64, func_%s },\n",
-                             p->CRm, p->Op1, p->is_write ? "write" : "read");
+               kvm_pr_unimpl(" { CRm64(%2lu), Op1(%2lu), is64, func_%s },\n",
+                             p->CRn, p->Op1, p->is_write ? "write" : "read");
        } else {
                kvm_pr_unimpl(" { CRn(%2lu), CRm(%2lu), Op1(%2lu), Op2(%2lu), is32,"
                              " func_%s },\n",
@@ -135,13 +135,13 @@ static inline int cmp_reg(const struct coproc_reg *i1,
                return -1;
        if (i1->CRn != i2->CRn)
                return i1->CRn - i2->CRn;
-       if (i1->is_64 != i2->is_64)
-               return i2->is_64 - i1->is_64;
        if (i1->CRm != i2->CRm)
                return i1->CRm - i2->CRm;
        if (i1->Op1 != i2->Op1)
                return i1->Op1 - i2->Op1;
-       return i1->Op2 - i2->Op2;
+       if (i1->Op2 != i2->Op2)
+               return i1->Op2 - i2->Op2;
+       return i2->is_64 - i1->is_64;
 }
 
 
@@ -153,4 +153,8 @@ static inline int cmp_reg(const struct coproc_reg *i1,
 #define is64           .is_64 = true
 #define is32           .is_64 = false
 
+bool access_sctlr(struct kvm_vcpu *vcpu,
+                 const struct coproc_params *p,
+                 const struct coproc_reg *r);
+
 #endif /* __ARM_KVM_COPROC_LOCAL_H__ */
index bb0cac1410ccf3f2bf6c6e4ff8436e8750036357..e6f4ae48bda968f8cac7caf6c94ffd1413631436 100644 (file)
@@ -34,7 +34,7 @@
 static const struct coproc_reg a15_regs[] = {
        /* SCTLR: swapped by interrupt.S. */
        { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
-                       NULL, reset_val, c1_SCTLR, 0x00C50078 },
+                       access_sctlr, reset_val, c1_SCTLR, 0x00C50078 },
 };
 
 static struct kvm_coproc_target_table a15_target_table = {
index 1df76733158893d83d1eaa64767be99a10f348d0..17fc7cd479d3e75d322c207ffa35d42f8785d7ee 100644 (file)
@@ -37,7 +37,7 @@
 static const struct coproc_reg a7_regs[] = {
        /* SCTLR: swapped by interrupt.S. */
        { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
-                       NULL, reset_val, c1_SCTLR, 0x00C50878 },
+                       access_sctlr, reset_val, c1_SCTLR, 0x00C50878 },
 };
 
 static struct kvm_coproc_target_table a7_target_table = {
index 2786eae10c0d4aec26b0c810ddd9b3ca42b9a8dd..b23a59c1c52255cc808d4fbaff6ffb3be2a5abb7 100644 (file)
@@ -38,6 +38,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.hcr = HCR_GUEST_MASK;
        return 0;
 }
 
index 6f18695a09cb5b50d8d849c9f2b486e8a01529c9..76af930255743724c0dd6cf26882968adcfbd959 100644 (file)
@@ -303,13 +303,17 @@ vcpu      .req    r0              @ vcpu pointer always in r0
 
        mrc     p15, 0, r2, c14, c1, 0  @ CNTKCTL
        mrrc    p15, 0, r4, r5, c7      @ PAR
+       mrc     p15, 0, r6, c10, c3, 0  @ AMAIR0
+       mrc     p15, 0, r7, c10, c3, 1  @ AMAIR1
 
        .if \store_to_vcpu == 0
-       push    {r2,r4-r5}
+       push    {r2,r4-r7}
        .else
        str     r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)]
        add     r12, vcpu, #CP15_OFFSET(c7_PAR)
        strd    r4, r5, [r12]
+       str     r6, [vcpu, #CP15_OFFSET(c10_AMAIR0)]
+       str     r7, [vcpu, #CP15_OFFSET(c10_AMAIR1)]
        .endif
 .endm
 
@@ -322,15 +326,19 @@ vcpu      .req    r0              @ vcpu pointer always in r0
  */
 .macro write_cp15_state read_from_vcpu
        .if \read_from_vcpu == 0
-       pop     {r2,r4-r5}
+       pop     {r2,r4-r7}
        .else
        ldr     r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)]
        add     r12, vcpu, #CP15_OFFSET(c7_PAR)
        ldrd    r4, r5, [r12]
+       ldr     r6, [vcpu, #CP15_OFFSET(c10_AMAIR0)]
+       ldr     r7, [vcpu, #CP15_OFFSET(c10_AMAIR1)]
        .endif
 
        mcr     p15, 0, r2, c14, c1, 0  @ CNTKCTL
        mcrr    p15, 0, r4, r5, c7      @ PAR
+       mcr     p15, 0, r6, c10, c3, 0  @ AMAIR0
+       mcr     p15, 0, r7, c10, c3, 1  @ AMAIR1
 
        .if \read_from_vcpu == 0
        pop     {r2-r12}
@@ -597,17 +605,14 @@ vcpu      .req    r0              @ vcpu pointer always in r0
 
 /* Enable/Disable: stage-2 trans., trap interrupts, trap wfi, trap smc */
 .macro configure_hyp_role operation
-       mrc     p15, 4, r2, c1, c1, 0   @ HCR
-       bic     r2, r2, #HCR_VIRT_EXCP_MASK
-       ldr     r3, =HCR_GUEST_MASK
        .if \operation == vmentry
-       orr     r2, r2, r3
+       ldr     r2, [vcpu, #VCPU_HCR]
        ldr     r3, [vcpu, #VCPU_IRQ_LINES]
        orr     r2, r2, r3
        .else
-       bic     r2, r2, r3
+       mov     r2, #0
        .endif
-       mcr     p15, 4, r2, c1, c1, 0
+       mcr     p15, 4, r2, c1, c1, 0   @ HCR
 .endm
 
 .macro load_vcpu
index 575d7904305b47e135bcec030cc6831b9ebd1e3a..c93ef38f9cb0d973f00e1b2cea4d09f2436959d6 100644 (file)
@@ -147,7 +147,7 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
                pgd = pgdp + pgd_index(addr);
                pud = pud_offset(pgd, addr);
                if (pud_none(*pud)) {
-                       addr = pud_addr_end(addr, end);
+                       addr = kvm_pud_addr_end(addr, end);
                        continue;
                }
 
@@ -157,13 +157,13 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
                         * move on.
                         */
                        clear_pud_entry(kvm, pud, addr);
-                       addr = pud_addr_end(addr, end);
+                       addr = kvm_pud_addr_end(addr, end);
                        continue;
                }
 
                pmd = pmd_offset(pud, addr);
                if (pmd_none(*pmd)) {
-                       addr = pmd_addr_end(addr, end);
+                       addr = kvm_pmd_addr_end(addr, end);
                        continue;
                }
 
@@ -178,10 +178,10 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
                 */
                if (kvm_pmd_huge(*pmd) || page_empty(pte)) {
                        clear_pmd_entry(kvm, pmd, addr);
-                       next = pmd_addr_end(addr, end);
+                       next = kvm_pmd_addr_end(addr, end);
                        if (page_empty(pmd) && !page_empty(pud)) {
                                clear_pud_entry(kvm, pud, addr);
-                               next = pud_addr_end(addr, end);
+                               next = kvm_pud_addr_end(addr, end);
                        }
                }
 
@@ -189,6 +189,99 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
        }
 }
 
+static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
+                             phys_addr_t addr, phys_addr_t end)
+{
+       pte_t *pte;
+
+       pte = pte_offset_kernel(pmd, addr);
+       do {
+               if (!pte_none(*pte)) {
+                       hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT);
+                       kvm_flush_dcache_to_poc((void*)hva, PAGE_SIZE);
+               }
+       } while (pte++, addr += PAGE_SIZE, addr != end);
+}
+
+static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud,
+                             phys_addr_t addr, phys_addr_t end)
+{
+       pmd_t *pmd;
+       phys_addr_t next;
+
+       pmd = pmd_offset(pud, addr);
+       do {
+               next = kvm_pmd_addr_end(addr, end);
+               if (!pmd_none(*pmd)) {
+                       if (kvm_pmd_huge(*pmd)) {
+                               hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT);
+                               kvm_flush_dcache_to_poc((void*)hva, PMD_SIZE);
+                       } else {
+                               stage2_flush_ptes(kvm, pmd, addr, next);
+                       }
+               }
+       } while (pmd++, addr = next, addr != end);
+}
+
+static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd,
+                             phys_addr_t addr, phys_addr_t end)
+{
+       pud_t *pud;
+       phys_addr_t next;
+
+       pud = pud_offset(pgd, addr);
+       do {
+               next = kvm_pud_addr_end(addr, end);
+               if (!pud_none(*pud)) {
+                       if (pud_huge(*pud)) {
+                               hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT);
+                               kvm_flush_dcache_to_poc((void*)hva, PUD_SIZE);
+                       } else {
+                               stage2_flush_pmds(kvm, pud, addr, next);
+                       }
+               }
+       } while (pud++, addr = next, addr != end);
+}
+
+static void stage2_flush_memslot(struct kvm *kvm,
+                                struct kvm_memory_slot *memslot)
+{
+       phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT;
+       phys_addr_t end = addr + PAGE_SIZE * memslot->npages;
+       phys_addr_t next;
+       pgd_t *pgd;
+
+       pgd = kvm->arch.pgd + pgd_index(addr);
+       do {
+               next = kvm_pgd_addr_end(addr, end);
+               stage2_flush_puds(kvm, pgd, addr, next);
+       } while (pgd++, addr = next, addr != end);
+}
+
+/**
+ * stage2_flush_vm - Invalidate cache for pages mapped in stage 2
+ * @kvm: The struct kvm pointer
+ *
+ * Go through the stage 2 page tables and invalidate any cache lines
+ * backing memory already mapped to the VM.
+ */
+void stage2_flush_vm(struct kvm *kvm)
+{
+       struct kvm_memslots *slots;
+       struct kvm_memory_slot *memslot;
+       int idx;
+
+       idx = srcu_read_lock(&kvm->srcu);
+       spin_lock(&kvm->mmu_lock);
+
+       slots = kvm_memslots(kvm);
+       kvm_for_each_memslot(memslot, slots)
+               stage2_flush_memslot(kvm, memslot);
+
+       spin_unlock(&kvm->mmu_lock);
+       srcu_read_unlock(&kvm->srcu, idx);
+}
+
 /**
  * free_boot_hyp_pgd - free HYP boot page tables
  *
@@ -717,7 +810,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                        kvm_set_s2pmd_writable(&new_pmd);
                        kvm_set_pfn_dirty(pfn);
                }
-               coherent_icache_guest_page(kvm, hva & PMD_MASK, PMD_SIZE);
+               coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE);
                ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
        } else {
                pte_t new_pte = pfn_pte(pfn, PAGE_S2);
@@ -725,7 +818,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                        kvm_set_s2pte_writable(&new_pte);
                        kvm_set_pfn_dirty(pfn);
                }
-               coherent_icache_guest_page(kvm, hva, PAGE_SIZE);
+               coherent_cache_guest_page(vcpu, hva, PAGE_SIZE);
                ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, false);
        }
 
index c5101dcb4fb04d8d9af68bea524043feb3c289a9..1d4df3b70ebcac418b8c7eb99c6e6c38d1bab3a7 100644 (file)
@@ -45,7 +45,7 @@ static inline void at91rm9200_standby(void)
                "    mcr    p15, 0, %0, c7, c0, 4\n\t"
                "    str    %5, [%1, %2]"
                :
-               : "r" (0), "r" (AT91_BASE_SYS), "r" (AT91RM9200_SDRAMC_LPR),
+               : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91RM9200_SDRAMC_LPR),
                  "r" (1), "r" (AT91RM9200_SDRAMC_SRR),
                  "r" (lpr));
 }
index bf06214e22ecf9e4b3b968b46639033c89c60bca..2cb8a000c9088081574152611568dc9d9d45a53a 100644 (file)
@@ -95,6 +95,7 @@ config SOC_DRA7XX
        select HAVE_ARM_ARCH_TIMER
        select IRQ_CROSSBAR
        select OMAP_DMA_CROSSBAR if DMA_OMAP
+       select ARM_ERRATA_798181 if SMP
 
 config ARCH_OMAP2PLUS
        bool
index 477e7efb12f1c30640a41bb838ff6306445760bc..60fabedb10c85677d54e45c8cce9278bc3abe9ab 100644 (file)
@@ -90,7 +90,7 @@ ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)               += pm24xx.o
 obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o
 obj-$(CONFIG_ARCH_OMAP3)               += pm34xx.o sleep34xx.o
-omap-4-5-pm-common                             =  pm44xx.o omap-mpuss-lowpower.o
+omap-4-5-pm-common                     =  pm44xx.o omap-mpuss-lowpower.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(omap-4-5-pm-common)
 obj-$(CONFIG_SOC_OMAP5)                        += $(omap-4-5-pm-common)
 obj-$(CONFIG_SOC_DRA7XX)               += $(omap-4-5-pm-common)
index 591581a665321c09fafbe78fd9c5bdbcae53c5a4..251d9288f666300561c998ccf71ff3ef1be3840d 100644 (file)
@@ -210,6 +210,25 @@ void omap2_init_clk_clkdm(struct clk_hw *hw)
        }
 }
 
+/**
+ * omap2_init_dpll_clkdm - setup DPLL sink clockdomain
+ * @dd: DPLL data pointer
+ * @np: device node pointer describing the DPLL
+ *
+ * Sets up DPLL sink clkdm, if available. This is only required for
+ * fixing J6 errata i810. No return value.
+ */
+void omap2_init_dpll_clkdm(struct dpll_data *dd, struct device_node *np)
+{
+       struct device_node *clkdm;
+
+       clkdm = of_parse_phandle(np, "ti,sink-clkdm", 0);
+       if (!clkdm)
+               return;
+
+       dd->sink_clkdm = clkdm_lookup(clkdm->name);
+}
+
 /**
  * omap2_clk_disable_clkdm_control - disable clkdm control on clk enable/disable
  *
index 13b12b0b53c5f60a7855419dffdc4be04085625e..b3cbd09e21ef9e080e6cb65aa7a3ebe8c373fdc2 100644 (file)
@@ -373,7 +373,7 @@ static struct clockdomain ipu1_7xx_clkdm = {
        .dep_bit          = DRA7XX_IPU1_STATDEP_SHIFT,
        .wkdep_srcs       = ipu1_wkup_sleep_deps,
        .sleepdep_srcs    = ipu1_wkup_sleep_deps,
-       .flags            = CLKDM_CAN_SWSUP,
+       .flags            = CLKDM_CAN_HWSUP_SWSUP,
 };
 
 static struct clockdomain ipu2_7xx_clkdm = {
@@ -461,7 +461,7 @@ static struct clockdomain ipu_7xx_clkdm = {
        .cm_inst          = DRA7XX_CM_CORE_AON_IPU_INST,
        .clkdm_offs       = DRA7XX_CM_CORE_AON_IPU_IPU_CDOFFS,
        .dep_bit          = DRA7XX_IPU_STATDEP_SHIFT,
-       .flags            = CLKDM_CAN_HWSUP_SWSUP,
+       .flags            = CLKDM_CAN_SWSUP,
 };
 
 static struct clockdomain mpu1_7xx_clkdm = {
index 82984b2f27154f7f8d96c28b5b2e7a3900aad6dd..8b6584b3dbeb37f0c928cea5793523ab173b1eed 100644 (file)
@@ -485,6 +485,35 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
        return 0;
 }
 
+static int omap4_clkdm_save_context(struct clockdomain *clkdm)
+{
+       clkdm->context = omap4_cminst_read_inst_reg(clkdm->prcm_partition,
+                                                   clkdm->cm_inst,
+                                                   clkdm->clkdm_offs +
+                                                   OMAP4_CM_CLKSTCTRL);
+       clkdm->context &= OMAP4430_MODULEMODE_MASK;
+       return 0;
+}
+
+static int omap4_clkdm_restore_context(struct clockdomain *clkdm)
+{
+       switch (clkdm->context) {
+       case OMAP34XX_CLKSTCTRL_DISABLE_AUTO:
+               omap4_clkdm_deny_idle(clkdm);
+               break;
+       case OMAP34XX_CLKSTCTRL_FORCE_SLEEP:
+               omap4_clkdm_sleep(clkdm);
+               break;
+       case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP:
+               omap4_clkdm_wakeup(clkdm);
+               break;
+       case OMAP34XX_CLKSTCTRL_ENABLE_AUTO:
+               omap4_clkdm_allow_idle(clkdm);
+               break;
+       }
+       return 0;
+}
+
 struct clkdm_ops omap4_clkdm_operations = {
        .clkdm_add_wkdep        = omap4_clkdm_add_wkup_sleep_dep,
        .clkdm_del_wkdep        = omap4_clkdm_del_wkup_sleep_dep,
@@ -509,4 +538,6 @@ struct clkdm_ops am43xx_clkdm_operations = {
        .clkdm_deny_idle        = omap4_clkdm_deny_idle,
        .clkdm_clk_enable       = omap4_clkdm_clk_enable,
        .clkdm_clk_disable      = omap4_clkdm_clk_disable,
+       .clkdm_save_context     = omap4_clkdm_save_context,
+       .clkdm_restore_context  = omap4_clkdm_restore_context,
 };
index 520e0f13dcbaf781e8c6dbd94780630f39d1178a..d3db4ae2b92af268edd68f8c867f6c74e3145b98 100644 (file)
@@ -306,6 +306,9 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
        /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
        _omap3_noncore_dpll_bypass(clk);
 
+       if (dd->sink_clkdm)
+               clkdm_clk_enable(dd->sink_clkdm, clk->hw.clk);
+
        /*
         * Set jitter correction. Jitter correction applicable for OMAP343X
         * only since freqsel field is no longer present on other devices.
@@ -374,6 +377,9 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 
        _omap3_noncore_dpll_lock(clk);
 
+       if (dd->sink_clkdm)
+               clkdm_clk_disable(dd->sink_clkdm, clk->hw.clk);
+
        return 0;
 }
 
index f1fab5684a24b1fc26a20b180305398be5165c65..346860ce040b373a2f0d7f428f421d7b42c8cd35 100644 (file)
 #include "soc.h"
 #include "omap_hwmod.h"
 #include "omap_device.h"
+#include "powerdomain.h"
+
+int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
+                                   u8 *pwrst)
+{
+       struct powerdomain *pwrdm;
+       struct omap_device *od;
+       u8 next_pwrst;
+
+       od = to_omap_device(pdev);
+       if (!od)
+               return -ENODEV;
+
+       if (od->hwmods_cnt != 1)
+               return -EINVAL;
+
+       pwrdm = omap_hwmod_get_pwrdm(od->hwmods[0]);
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (request)
+               *pwrst = pwrdm_read_next_pwrst(pwrdm);
+
+       if (*pwrst > PWRDM_POWER_RET)
+               return 0;
+
+       next_pwrst = request ? PWRDM_POWER_ON : *pwrst;
+
+       return pwrdm_set_next_pwrst(pwrdm, next_pwrst);
+}
 
 static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
 {
@@ -42,6 +72,8 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
                pdata->assert_reset = omap_device_assert_hardreset;
                pdata->deassert_reset = omap_device_deassert_hardreset;
        }
+       pdata->device_enable = omap_device_enable,
+       pdata->device_idle = omap_device_idle,
 
        pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata));
 
index bd31b5f7f3d03535d903a5eab5a1d04913b24728..af26d974e125f826550066f31fea3387af33b460 100644 (file)
@@ -3275,6 +3275,22 @@ static int _am33xx_is_hardreset_asserted(struct omap_hwmod *oh,
                                oh->prcm.omap4.rstctrl_offs);
 }
 
+/**
+ * _reidle - enable then idle a single hwmod
+ *
+ * enables and then immediately reidles an hwmod, as certain hwmods may
+ * not have their sysconfig registers programmed in an idle friendly state
+ * by default
+ */
+static void _reidle(struct omap_hwmod *oh)
+{
+       pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
+
+       omap_hwmod_enable(oh);
+       omap_hwmod_softreset(oh);
+       omap_hwmod_idle(oh);
+}
+
 /**
  * _reidle_all - enable then idle all hwmods in oh_reidle_list
  *
@@ -3286,8 +3302,7 @@ static int _reidle_all(void)
        struct omap_hwmod_list *oh_list_item = NULL;
 
        list_for_each_entry(oh_list_item, &oh_reidle_list, oh_list) {
-               omap_hwmod_enable(oh_list_item->oh);
-               omap_hwmod_idle(oh_list_item->oh);
+               _reidle(oh_list_item->oh);
        }
 
        return 0;
@@ -4447,14 +4462,16 @@ static int omap_hwmod_restore_context(struct omap_hwmod *oh, void *unused)
        for (i = 0; i < oh->rst_lines_cnt; i++)
                if (oh->rst_lines[i].context)
                        _assert_hardreset(oh, oh->rst_lines[i].name);
-               else if (oh->_state == _HWMOD_STATE_ENABLED)
+               else
                        _deassert_hardreset(oh, oh->rst_lines[i].name);
 
        if (oh->_state == _HWMOD_STATE_ENABLED) {
                if (soc_ops.enable_module)
                        soc_ops.enable_module(oh);
        } else {
-               if (soc_ops.disable_module)
+               if (oh->flags & HWMOD_NEEDS_REIDLE)
+                       _reidle(oh);
+               else if (soc_ops.disable_module)
                        soc_ops.disable_module(oh);
        }
 
index 1ca926893e3478a8d82cbd29d40c37d834b84485..97594e6abda5f5b677ffd0b78cc851e7e312f740 100644 (file)
@@ -772,6 +772,7 @@ struct omap_hwmod am33xx_gpmc_hwmod = {
        .name           = "gpmc",
        .class          = &am33xx_gpmc_hwmod_class,
        .clkdm_name     = "l3s_clkdm",
+       .flags          = HWMOD_NEEDS_REIDLE,
        .main_clk       = "l3s_gclk",
        .prcm           = {
                .omap4  = {
index effc16f5364dfc892b1001853359994b876d047d..d0967a0846a84dd5f8f96c5417ad3b44d51bbdff 100644 (file)
@@ -927,9 +927,9 @@ static struct omap_hwmod_class dra7xx_aes_hwmod_class = {
        .rev    = 2,
 };
 
-/* AES */
-static struct omap_hwmod dra7xx_aes_hwmod = {
-       .name           = "aes",
+/* AES1 */
+static struct omap_hwmod dra7xx_aes1_hwmod = {
+       .name           = "aes1",
        .class          = &dra7xx_aes_hwmod_class,
        .clkdm_name     = "l4sec_clkdm",
        .main_clk       = "l3_iclk_div",
@@ -942,6 +942,21 @@ static struct omap_hwmod dra7xx_aes_hwmod = {
        },
 };
 
+/* AES2 */
+static struct omap_hwmod dra7xx_aes2_hwmod = {
+       .name           = "aes2",
+       .class          = &dra7xx_aes_hwmod_class,
+       .clkdm_name     = "l4sec_clkdm",
+       .main_clk       = "l3_iclk_div",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4SEC_AES2_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4SEC_AES2_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_HWCTRL,
+               },
+       },
+};
+
 /* sha0 HIB2 (the 'P' (public) device) */
 static struct omap_hwmod_class_sysconfig dra7xx_sha0_sysc = {
        .rev_offs       = 0x100,
@@ -1230,8 +1245,7 @@ static struct omap_hwmod_class_sysconfig dra7xx_gpmc_sysc = {
        .syss_offs      = 0x0014,
        .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
                           SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
+       .idlemodes      = SIDLE_FORCE | SIDLE_NO | SIDLE_SMART,
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -1246,8 +1260,6 @@ static struct omap_hwmod dra7xx_gpmc_hwmod = {
        .name           = "gpmc",
        .class          = &dra7xx_gpmc_hwmod_class,
        .clkdm_name     = "l3main1_clkdm",
-       .flags          = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET |
-                          HWMOD_SWSUP_SIDLE),
        .main_clk       = "l3_iclk_div",
        .prcm = {
                .omap4 = {
@@ -1781,6 +1793,22 @@ static struct omap_hwmod dra7xx_mcasp3_hwmod = {
        },
 };
 
+/* mcasp8 */
+static struct omap_hwmod dra7xx_mcasp8_hwmod = {
+       .name           = "mcasp8",
+       .class          = &dra7xx_mcasp_hwmod_class,
+       .clkdm_name     = "l4per2_clkdm",
+       .main_clk       = "mcasp8_ahclkx_mux",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER2_MCASP8_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER2_MCASP8_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
 /*
  * 'mmc' class
  *
@@ -2502,7 +2530,7 @@ static struct omap_hwmod dra7xx_timer3_hwmod = {
 /* timer4 */
 static struct omap_hwmod dra7xx_timer4_hwmod = {
        .name           = "timer4",
-       .class          = &dra7xx_timer_secure_hwmod_class,
+       .class          = &dra7xx_timer_hwmod_class,
        .clkdm_name     = "l4per_clkdm",
        .main_clk       = "timer4_gfclk_mux",
        .prcm = {
@@ -2619,6 +2647,80 @@ static struct omap_hwmod dra7xx_timer11_hwmod = {
        },
 };
 
+/* timer12 */
+static struct omap_hwmod dra7xx_timer12_hwmod = {
+       .name           = "timer12",
+       .class          = &dra7xx_timer_secure_hwmod_class,
+       .clkdm_name     = "wkupaon_clkdm",
+       .main_clk       = "secure_32k_clk_src_ck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_WKUPAON_TIMER12_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_WKUPAON_TIMER12_CONTEXT_OFFSET,
+               },
+       },
+};
+
+/* timer13 */
+static struct omap_hwmod dra7xx_timer13_hwmod = {
+       .name           = "timer13",
+       .class          = &dra7xx_timer_hwmod_class,
+       .clkdm_name     = "l4per3_clkdm",
+       .main_clk       = "timer13_gfclk_mux",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER3_TIMER13_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER3_TIMER13_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* timer14 */
+static struct omap_hwmod dra7xx_timer14_hwmod = {
+       .name           = "timer14",
+       .class          = &dra7xx_timer_hwmod_class,
+       .clkdm_name     = "l4per3_clkdm",
+       .main_clk       = "timer14_gfclk_mux",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER3_TIMER14_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER3_TIMER14_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* timer15 */
+static struct omap_hwmod dra7xx_timer15_hwmod = {
+       .name           = "timer15",
+       .class          = &dra7xx_timer_hwmod_class,
+       .clkdm_name     = "l4per3_clkdm",
+       .main_clk       = "timer15_gfclk_mux",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER3_TIMER15_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER3_TIMER15_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* timer16 */
+static struct omap_hwmod dra7xx_timer16_hwmod = {
+       .name           = "timer16",
+       .class          = &dra7xx_timer_hwmod_class,
+       .clkdm_name     = "l4per3_clkdm",
+       .main_clk       = "timer16_gfclk_mux",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER3_TIMER16_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER3_TIMER16_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
 /*
  * 'uart' class
  *
@@ -3338,10 +3440,18 @@ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__hdmi = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l3_main_1 -> aes */
-static struct omap_hwmod_ocp_if dra7xx_l3_main_1__aes = {
+/* l3_main_1 -> aes1 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__aes1 = {
        .master         = &dra7xx_l3_main_1_hwmod,
-       .slave          = &dra7xx_aes_hwmod,
+       .slave          = &dra7xx_aes1_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> aes2 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__aes2 = {
+       .master         = &dra7xx_l3_main_1_hwmod,
+       .slave          = &dra7xx_aes2_hwmod,
        .clk            = "l3_iclk_div",
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
@@ -3362,6 +3472,14 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp3 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per2 -> mcasp8 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp8 = {
+       .master         = &dra7xx_l4_per2_hwmod,
+       .slave          = &dra7xx_mcasp8_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_addr_space dra7xx_elm_addrs[] = {
        {
                .pa_start       = 0x48078000,
@@ -4047,6 +4165,46 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__timer11 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_wkup -> timer12 */
+static struct omap_hwmod_ocp_if dra7xx_l4_wkup__timer12 = {
+       .master         = &dra7xx_l4_wkup_hwmod,
+       .slave          = &dra7xx_timer12_hwmod,
+       .clk            = "wkupaon_iclk_mux",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> timer13 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer13 = {
+       .master         = &dra7xx_l4_per3_hwmod,
+       .slave          = &dra7xx_timer13_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> timer14 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer14 = {
+       .master         = &dra7xx_l4_per3_hwmod,
+       .slave          = &dra7xx_timer14_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> timer15 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer15 = {
+       .master         = &dra7xx_l4_per3_hwmod,
+       .slave          = &dra7xx_timer15_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> timer16 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer16 = {
+       .master         = &dra7xx_l4_per3_hwmod,
+       .slave          = &dra7xx_timer16_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per1 -> uart1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart1 = {
        .master         = &dra7xx_l4_per1_hwmod,
@@ -4280,9 +4438,11 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l3_main_1__dispc,
        &dra7xx_dsp1__l3_main_1,
        &dra7xx_l3_main_1__hdmi,
-       &dra7xx_l3_main_1__aes,
+       &dra7xx_l3_main_1__aes1,
+       &dra7xx_l3_main_1__aes2,
        &dra7xx_l3_main_1__sha0,
        &dra7xx_l4_per2__mcasp3,
+       &dra7xx_l4_per2__mcasp8,
        &dra7xx_l4_per1__elm,
        &dra7xx_l4_wkup__gpio1,
        &dra7xx_l4_per1__gpio2,
@@ -4352,6 +4512,11 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l4_per1__timer9,
        &dra7xx_l4_per1__timer10,
        &dra7xx_l4_per1__timer11,
+       &dra7xx_l4_wkup__timer12,
+       &dra7xx_l4_per3__timer13,
+       &dra7xx_l4_per3__timer14,
+       &dra7xx_l4_per3__timer15,
+       &dra7xx_l4_per3__timer16,
        &dra7xx_l4_per1__uart1,
        &dra7xx_l4_per1__uart2,
        &dra7xx_l4_per1__uart3,
index 7079114b4e08b59727a7cd94d59ef90e40f8d3cd..b9c8348671440234baffaf9abc949826abfea7ab 100644 (file)
@@ -41,6 +41,17 @@ struct pdata_init {
 struct of_dev_auxdata omap_auxdata_lookup[];
 static struct twl4030_gpio_platform_data twl_gpio_auxdata;
 
+#if IS_ENABLED(CONFIG_OMAP_IOMMU)
+int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
+                                   u8 *pwrst);
+#else
+static inline int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev,
+                                                 bool request, u8 *pwrst)
+{
+       return 0;
+}
+#endif
+
 #if IS_ENABLED(CONFIG_WL12XX)
 
 static struct wl12xx_platform_data wl12xx __initdata;
@@ -99,6 +110,13 @@ static struct iommu_platform_data omap3_iommu_pdata = {
        .reset_name = "mmu",
        .assert_reset = omap_device_assert_hardreset,
        .deassert_reset = omap_device_deassert_hardreset,
+       .device_enable = omap_device_enable,
+       .device_idle = omap_device_idle,
+};
+
+static struct iommu_platform_data omap3_iommu_isp_pdata = {
+       .device_enable = omap_device_enable,
+       .device_idle = omap_device_idle,
 };
 
 static int omap3_sbc_t3730_twl_callback(struct device *dev,
@@ -236,6 +254,8 @@ static struct iommu_platform_data omap4_iommu_pdata = {
        .reset_name = "mmu_cache",
        .assert_reset = omap_device_assert_hardreset,
        .deassert_reset = omap_device_deassert_hardreset,
+       .device_enable = omap_device_enable,
+       .device_idle = omap_device_idle,
 };
 
 static struct omap_rproc_pdata omap4_ipu_pdata = {
@@ -255,6 +275,20 @@ static struct omap_rproc_pdata omap4_dsp_pdata = {
 #endif
 
 #ifdef CONFIG_SOC_DRA7XX
+static struct iommu_platform_data dra7_dsp_mmu_edma_pdata = {
+       .device_enable = omap_device_enable,
+       .device_idle = omap_device_idle,
+};
+
+static struct iommu_platform_data dra7_ipu1_iommu_pdata = {
+       .reset_name = "mmu_cache",
+       .assert_reset = omap_device_assert_hardreset,
+       .deassert_reset = omap_device_deassert_hardreset,
+       .device_enable = omap_device_enable,
+       .device_idle = omap_device_idle,
+       .set_pwrdm_constraint = omap_iommu_set_pwrdm_constraint,
+};
+
 static struct omap_rproc_pdata dra7_dsp1_pdata = {
        .device_enable = omap_rproc_device_enable,
        .device_shutdown = omap_rproc_device_shutdown,
@@ -382,6 +416,8 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002a00, "48002a00.pinmux", &pcs_pdata),
        OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu",
                       &omap3_iommu_pdata),
+       OF_DEV_AUXDATA("ti,omap2-iommu", 0x480bd400, "480bd400.mmu",
+                      &omap3_iommu_isp_pdata),
        /* Only on am3517 */
        OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
        OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
@@ -430,12 +466,16 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("ti,dra7-padconf", 0x4a003400, "4a003400.pinmux", &pcs_pdata),
        OF_DEV_AUXDATA("ti,dra7-iommu", 0x40d01000, "40d01000.mmu",
                       &omap4_iommu_pdata),
+       OF_DEV_AUXDATA("ti,dra7-iommu", 0x40d02000, "40d02000.mmu",
+                      &dra7_dsp_mmu_edma_pdata),
        OF_DEV_AUXDATA("ti,dra7-iommu", 0x41501000, "41501000.mmu",
                       &omap4_iommu_pdata),
+       OF_DEV_AUXDATA("ti,dra7-iommu", 0x41502000, "41502000.mmu",
+                      &dra7_dsp_mmu_edma_pdata),
        OF_DEV_AUXDATA("ti,dra7-iommu", 0x55082000, "55082000.mmu",
                       &omap4_iommu_pdata),
        OF_DEV_AUXDATA("ti,dra7-iommu", 0x58882000, "58882000.mmu",
-                      &omap4_iommu_pdata),
+                      &dra7_ipu1_iommu_pdata),
        OF_DEV_AUXDATA("ti,dra7-rproc-ipu", 0x55020000, "55020000.ipu",
                       &omap4_ipu_pdata),
        OF_DEV_AUXDATA("ti,dra7-rproc-ipu", 0x58820000, "58820000.ipu",
index a17a680a5eec2cc78a9304dac47ebade210557f2..ddddadfa7d12ffc3f11528691cff0353894df272 100644 (file)
@@ -60,6 +60,7 @@ static struct omap_hwmod *rtc_oh;
 static struct pinctrl_dev *pmx_dev;
 static u32 rtc_magic_val;
 static int retrigger_irq;
+static int rtc_only_idle;
 
 #define RTC_SCRATCH_RESUME_REG         0
 #define RTC_SCRATCH_MAGIC_REG          1
@@ -133,21 +134,27 @@ static int am33xx_do_sram_idle(unsigned long int arg)
        return 0;
 }
 
-static struct wkup_m3_wakeup_src rtc_wakeups[] = {
-       {.irq_nr = 0, .src = "Unknown"},
-       {.irq_nr = 0, .src = "Unknown"},
-       {.irq_nr = 108, .src = "RTC Alarm"},
-       {.irq_nr = 0, .src = "Ext wakeup"},
+static struct wkup_m3_wakeup_src rtc_alarm_wakeup = {
+       .irq_nr = 108, .src = "RTC Alarm",
+};
+
+static struct wkup_m3_wakeup_src rtc_ext_wakeup = {
+       .irq_nr = 0, .src = "Ext wakeup",
 };
 
 struct wkup_m3_wakeup_src rtc_wake_src(void)
 {
        u32 i;
 
-       i = __raw_readl(susp_params.rtc_base + 0x98) >> 17;
-       retrigger_irq = rtc_wakeups[i].irq_nr;
+       i = __raw_readl(susp_params.rtc_base + 0x44) & 0x40;
 
-       return rtc_wakeups[i];
+       if (i) {
+               retrigger_irq = rtc_alarm_wakeup.irq_nr;
+               return rtc_alarm_wakeup;
+       } else {
+               retrigger_irq = rtc_ext_wakeup.irq_nr;
+               return rtc_ext_wakeup;
+       }
 }
 
 static void common_save_context(void)
@@ -210,7 +217,6 @@ static void am43xx_restore_context(void)
 
 int am33xx_rtc_only_idle(long unsigned int unused)
 {
-       rtc_write_scratch(omap_rtc, RTC_SCRATCH_MAGIC_REG, rtc_magic_val);
        omap_rtc_power_off_program();
        am33xx_do_wfi_sram(&susp_params);
        return 0;
@@ -220,7 +226,6 @@ static int am33xx_pm_suspend(unsigned int state)
 {
        int i, ret = 0;
        int status = 0;
-       int rtc_only_idle = 0;
        struct wkup_m3_wakeup_src wakeup_src = {.irq_nr = 0,
                                                .src = "Unknown",};
 
@@ -228,9 +233,6 @@ static int am33xx_pm_suspend(unsigned int state)
 
        am33xx_pm->ops->pre_suspend(state);
 
-       if (state == PM_SUSPEND_MEM && enable_off_mode && rtc_magic_val)
-               rtc_only_idle = 1;
-
        if (rtc_only_idle) {
                omap_hwmod_enable(rtc_oh);
                am33xx_pm->ops->save_context();
@@ -339,6 +341,14 @@ static int am33xx_pm_begin(suspend_state_t state)
 
        cpu_idle_poll_ctrl(true);
 
+       if (state == PM_SUSPEND_MEM && enable_off_mode && rtc_magic_val) {
+               rtc_write_scratch(omap_rtc, RTC_SCRATCH_MAGIC_REG,
+                                 rtc_magic_val);
+               rtc_only_idle = 1;
+       } else {
+               rtc_only_idle = 0;
+       }
+
        switch (state) {
        case PM_SUSPEND_MEM:
                am33xx_pm->ipc.reg1     = IPC_CMD_DS0;
@@ -380,6 +390,9 @@ static void am33xx_pm_end(void)
                writel_relaxed(1 << (retrigger_irq & 31),
                               gic_dist_base + 0x200 + retrigger_irq / 32 * 4);
 
+       if (rtc_only_idle)
+               rtc_write_scratch(omap_rtc, RTC_SCRATCH_MAGIC_REG, 0);
+
        cpu_idle_poll_ctrl(false);
 }
 
index 8c4f45995b630519991dbb95fb822c5c0f5e00eb..7b6a6f7164baa495644c73a501345b9e0943a715 100644 (file)
@@ -65,7 +65,7 @@ void __iomem *omap_rtc_get_base_addr(void);
 #define IPC_CMD_RTC_ONLY               0x1
 #define        IPC_CMD_DS0                     0x4
 #define        IPC_CMD_STANDBY                 0xc
-#define        IPC_CMD_IDLE                    0xd
+#define        IPC_CMD_IDLE                    0x10
 #define IPC_CMD_RESET                  0xe
 #define DS_IPC_DEFAULT                 0xffffffff
 #define M3_VERSION_UNKNOWN             0x0000ffff
index 40c4f7f370b521d89ef7fb16bd9b044882214d12..53f9a55d02d723fe1deead099f23de2ffabd5e99 100644 (file)
@@ -339,9 +339,20 @@ static void am33xx_pwrdm_save_context(struct powerdomain *pwrdm)
 
 static void am33xx_pwrdm_restore_context(struct powerdomain *pwrdm)
 {
+       int st, ctrl;
+
+       st = am33xx_prm_read_reg(pwrdm->prcm_offs,
+                                pwrdm->pwrstst_offs);
+
        am33xx_prm_write_reg(pwrdm->context, pwrdm->prcm_offs,
                             pwrdm->pwrstctrl_offs);
-       am33xx_pwrdm_wait_transition(pwrdm);
+
+       /* Make sure we only wait for a transition if there is one */
+       st &= OMAP_POWERSTATEST_MASK;
+       ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
+
+       if (st != ctrl)
+               am33xx_pwrdm_wait_transition(pwrdm);
 }
 
 struct prm_register {
index 3e0e4c1ba7d410bacfe254759563c12e30fc785c..04ef016dbfe82f0128805fa799a91fc8426400a6 100644 (file)
@@ -673,6 +673,40 @@ static int omap4_check_vcvp(void)
        return 1;
 }
 
+static void omap4_pwrdm_save_context(struct powerdomain *pwrdm)
+{
+       pwrdm->context = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
+                                                    pwrdm->prcm_offs,
+                                                    pwrdm->pwrstctrl_offs);
+
+       /*
+        * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request,
+        * reading back a 1 indicates a request in progress.
+        */
+       pwrdm->context &= ~OMAP4430_LOWPOWERSTATECHANGE_MASK;
+}
+
+static void omap4_pwrdm_restore_context(struct powerdomain *pwrdm)
+{
+       int st, ctrl;
+
+       st = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
+                                        pwrdm->prcm_offs,
+                                        pwrdm->pwrstctrl_offs);
+
+       omap4_prminst_write_inst_reg(pwrdm->context,
+                                    pwrdm->prcm_partition,
+                                    pwrdm->prcm_offs,
+                                    pwrdm->pwrstctrl_offs);
+
+       /* Make sure we only wait for a transition if there is one */
+       st &= OMAP_POWERSTATEST_MASK;
+       ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
+
+       if (st != ctrl)
+               omap4_pwrdm_wait_transition(pwrdm);
+}
+
 struct pwrdm_ops omap4_pwrdm_operations = {
        .pwrdm_set_next_pwrst   = omap4_pwrdm_set_next_pwrst,
        .pwrdm_read_next_pwrst  = omap4_pwrdm_read_next_pwrst,
@@ -691,6 +725,8 @@ struct pwrdm_ops omap4_pwrdm_operations = {
        .pwrdm_set_mem_retst    = omap4_pwrdm_set_mem_retst,
        .pwrdm_wait_transition  = omap4_pwrdm_wait_transition,
        .pwrdm_has_voltdm       = omap4_check_vcvp,
+       .pwrdm_save_context     = omap4_pwrdm_save_context,
+       .pwrdm_restore_context  = omap4_pwrdm_restore_context,
 };
 
 static int omap44xx_prm_late_init(void);
index ad496cdd7548f0d756918d1dbd78b925d65bb2ee..d1e9561da91e1bf9059f747733c8405c1e64d7fe 100644 (file)
@@ -38,6 +38,9 @@
 #define RTC_SECONDS_REG                        0x0
 #define RTC_PMIC_REG                   0x98
 #define RTC_PMIC_POWER_EN              (1 << 16)
+#define RTC_PMIC_EXT_WAKEUP_STS                (1 << 12)
+#define RTC_PMIC_EXT_WAKEUP_POL                (1 << 4)
+#define RTC_PMIC_EXT_WAKEUP_EN         (1 << 0)
 
        .text
        .align 3
@@ -161,6 +164,9 @@ skip_sr:
 
        ldr     r1, rtc_base_addr
        ldr     r0, [r1, #RTC_PMIC_REG]
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_STS
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_EN
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_POL
        orr     r0, r0, #RTC_PMIC_POWER_EN
        str     r0, [r1, #RTC_PMIC_REG]
        ldr     r0, [r1, #RTC_PMIC_REG]
@@ -240,7 +246,6 @@ skip_m3:
        movne   r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
        strne   r2, [r1]
 
-re_enable_emif:
        ldr     r2, wfi_flags
        tst     r2, #WFI_SELF_REFRESH
        beq     skip_reenable_emif
@@ -248,6 +253,7 @@ re_enable_emif:
        tst     r2, #WFI_DISABLE_EMIF
        beq     skip_emif_enable
 
+re_enable_emif:
        /* Re-enable EMIF */
        ldr     r1, virt_emif_clkctrl
        mov     r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
index e0aba1ca11f2a7a98bb88fe86a2bdf59dc6cfb58..a8ae0f3c7dc7b695210b64385efd2859dec5393f 100644 (file)
@@ -53,6 +53,9 @@
 #define RTC_SECONDS_REG                                        0x0
 #define RTC_PMIC_REG                                   0x98
 #define RTC_PMIC_POWER_EN                              (1 << 16)
+#define RTC_PMIC_EXT_WAKEUP_STS                                (1 << 12)
+#define RTC_PMIC_EXT_WAKEUP_POL                                (1 << 4)
+#define RTC_PMIC_EXT_WAKEUP_EN                         (1 << 0)
 
        .text
        .align 3
@@ -272,6 +275,9 @@ wait_emif_disable:
 
        ldr     r1, rtc_base_addr
        ldr     r0, [r1, #RTC_PMIC_REG]
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_STS
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_EN
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_POL
        orr     r0, r0, #RTC_PMIC_POWER_EN
        str     r0, [r1, #RTC_PMIC_REG]
        ldr     r0, [r1, #RTC_PMIC_REG]
index c2b3b1fad6fcb560bba8766f092b2c1e4f8771f5..1ee3cb6482ddc0f4aa966a502c3ef8801b7cd1a0 100644 (file)
@@ -237,8 +237,8 @@ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
 /**
  * omap_dmtimer_init - initialisation function when device tree is used
  *
- * For secure OMAP3 devices, timers with device type "timer-secure" cannot
- * be used by the kernel as they are reserved. Therefore, to prevent the
+ * For secure OMAP3/DRA7xx devices, timers with device type "timer-secure"
+ * cannot be used by the kernel as they are reserved. Therefore, to prevent the
  * kernel registering these devices remove them dynamically from the device
  * tree on boot.
  */
@@ -246,7 +246,7 @@ static void __init omap_dmtimer_init(void)
 {
        struct device_node *np;
 
-       if (!cpu_is_omap34xx())
+       if (!cpu_is_omap34xx() && !soc_is_dra7xx())
                return;
 
        /* If we are a secure device, remove any secure timer nodes */
index 7bc66682687efa4f240a5557618278d38c39e4b1..dcbe17f5e5f8054ee7fd1e796197eb88d78e97a8 100644 (file)
@@ -14,6 +14,7 @@
 #include <mach/gpio-samsung.h>
 
 #define GLENFARCLAS_PMIC_IRQ_BASE      IRQ_BOARD_START
+#define BANFF_PMIC_IRQ_BASE            (IRQ_BOARD_START + 64)
 
 #define PCA935X_GPIO_BASE              GPIO_BOARD_START
 #define CODEC_GPIO_BASE                        (GPIO_BOARD_START + 8)
index 3df3c372ee1f9aa1f1685913e2b00ba123339513..66b95c46649756ff8d509d9df6f68650f4c1810c 100644 (file)
@@ -555,6 +555,7 @@ static struct wm831x_touch_pdata touch_pdata = {
 
 static struct wm831x_pdata crag_pmic_pdata = {
        .wm831x_num = 1,
+       .irq_base = BANFF_PMIC_IRQ_BASE,
        .gpio_base = BANFF_PMIC_GPIO_BASE,
        .soft_shutdown = true,
 
index 22e3ad63500c0e79f4eaf54555ca6c7aa13c57ff..eb81123a845dc1aa0733a89997a51b66bb9d3b88 100644 (file)
@@ -86,8 +86,13 @@ ENTRY(cpu_v7_set_pte_ext)
        tst     rh, #1 << (57 - 32)             @ L_PTE_NONE
        bicne   rl, #L_PTE_VALID
        bne     1f
-       tst     rh, #1 << (55 - 32)             @ L_PTE_DIRTY
-       orreq   rl, #L_PTE_RDONLY
+
+       eor     ip, rh, #1 << (55 - 32) @ toggle L_PTE_DIRTY in temp reg to
+                                       @ test for !L_PTE_DIRTY || L_PTE_RDONLY
+       tst     ip, #1 << (55 - 32) | 1 << (58 - 32)
+       orrne   rl, #PTE_AP2
+       biceq   rl, #PTE_AP2
+
 1:     strd    r2, r3, [r0]
        ALT_SMP(W(nop))
        ALT_UP (mcr     p15, 0, r0, c7, c10, 1)         @ flush_pte
index 271b5e9715682ab40869a1ea8a02c9696eaebf07..6adf5913a7ac4e34a047325baeef75060b25f257 100644 (file)
@@ -449,10 +449,21 @@ static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
                return;
        }
 #endif
-       if (rm != ARM_R0)
-               emit(ARM_MOV_R(ARM_R0, rm), ctx);
+
+       /*
+        * For BPF_ALU | BPF_DIV | BPF_K instructions, rm is ARM_R4
+        * (r_A) and rn is ARM_R0 (r_scratch) so load rn first into
+        * ARM_R1 to avoid accidentally overwriting ARM_R0 with rm
+        * before using it as a source for ARM_R1.
+        *
+        * For BPF_ALU | BPF_DIV | BPF_X rm is ARM_R4 (r_A) and rn is
+        * ARM_R5 (r_X) so there is no particular register overlap
+        * issues.
+        */
        if (rn != ARM_R1)
                emit(ARM_MOV_R(ARM_R1, rn), ctx);
+       if (rm != ARM_R0)
+               emit(ARM_MOV_R(ARM_R0, rm), ctx);
 
        ctx->seen |= SEEN_CALL;
        emit_mov_i(ARM_R3, (u32)jit_udiv, ctx);
index 869254cebf842fd39de14d6a7932976b8b1bae87..23769298c9f09c7cafc9cbd856c24dfcab89fc40 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/device.h>
@@ -485,6 +486,10 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
        struct clk *parent;
        struct dmtimer_platform_data *pdata;
 
+       /* Check if the clock has parents if not no point checking */
+       if (!__clk_get_num_parents(timer->fclk))
+               return 0;
+
        if (unlikely(!timer))
                return -EINVAL;
 
@@ -799,6 +804,7 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        const struct of_device_id *match;
        const struct dmtimer_platform_data *pdata;
+       int ret;
 
        match = of_match_device(of_match_ptr(omap_timer_match), dev);
        pdata = match ? match->data : dev->platform_data;
@@ -860,7 +866,12 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
        }
 
        if (!timer->reserved) {
-               pm_runtime_get_sync(dev);
+               ret = pm_runtime_get_sync(dev);
+               if (ret < 0) {
+                       dev_err(dev, "%s: pm_runtime_get_sync failed!\n",
+                               __func__);
+                       goto err_get_sync;
+               }
                __omap_dm_timer_init_regs(timer);
                pm_runtime_put(dev);
        }
@@ -873,6 +884,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
        dev_dbg(dev, "Device Probed.\n");
 
        return 0;
+
+err_get_sync:
+       pm_runtime_put_noidle(dev);
+       pm_runtime_disable(dev);
+       return ret;
 }
 
 /**
@@ -899,6 +915,8 @@ static int omap_dm_timer_remove(struct platform_device *pdev)
                }
        spin_unlock_irqrestore(&dm_timer_lock, flags);
 
+       pm_runtime_disable(&pdev->dev);
+
        return ret;
 }
 
index 0eb39865537839c202879251fbb60f919328d58e..00fbaa75dc7bcf55541c7bf00af609dfb63529a9 100644 (file)
@@ -62,6 +62,7 @@
  * RW:         64bit by default, can be overriden for 32bit VMs
  * TAC:                Trap ACTLR
  * TSC:                Trap SMC
+ * TVM:                Trap VM ops (until M+C set in SCTLR_EL1)
  * TSW:                Trap cache operations by set/way
  * TWE:                Trap WFE
  * TWI:                Trap WFI
@@ -74,7 +75,7 @@
  * SWIO:       Turn set/way invalidates into set/way clean+invalidate
  */
 #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
-                        HCR_BSU_IS | HCR_FB | HCR_TAC | \
+                        HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
                         HCR_AMO | HCR_IMO | HCR_FMO | \
                         HCR_SWIO | HCR_TIDCP | HCR_RW)
 #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
index b25763bc0ec4977a4eca6139ef7d84b3a15eeea0..9fcd54b1e16d8800ffec64a249cb55739c88b058 100644 (file)
@@ -79,7 +79,8 @@
 #define c13_TID_URW    (TPIDR_EL0 * 2) /* Thread ID, User R/W */
 #define c13_TID_URO    (TPIDRRO_EL0 * 2)/* Thread ID, User R/O */
 #define c13_TID_PRIV   (TPIDR_EL1 * 2) /* Thread ID, Privileged */
-#define c10_AMAIR      (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */
+#define c10_AMAIR0     (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */
+#define c10_AMAIR1     (c10_AMAIR0 + 1)/* Aux Memory Attr Indirection Reg */
 #define c14_CNTKCTL    (CNTKCTL_EL1 * 2) /* Timer Control Register (PL1) */
 #define NR_CP15_REGS   (NR_SYS_REGS * 2)
 
index 7f1f9408ff66e897e8988d0b844ab9a3e8f903a0..7d29847a893b89b4edf6460599d0d9e9ff720127 100644 (file)
@@ -106,7 +106,6 @@ static inline bool kvm_is_write_fault(unsigned long esr)
        return true;
 }
 
-static inline void kvm_clean_dcache_area(void *addr, size_t size) {}
 static inline void kvm_clean_pgd(pgd_t *pgd) {}
 static inline void kvm_clean_pmd_entry(pmd_t *pmd) {}
 static inline void kvm_clean_pte(pte_t *pte) {}
@@ -122,11 +121,25 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
        pmd_val(*pmd) |= PMD_S2_RDWR;
 }
 
+#define kvm_pgd_addr_end(addr, end)    pgd_addr_end(addr, end)
+#define kvm_pud_addr_end(addr, end)    pud_addr_end(addr, end)
+#define kvm_pmd_addr_end(addr, end)    pmd_addr_end(addr, end)
+
 struct kvm;
 
-static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva,
-                                             unsigned long size)
+#define kvm_flush_dcache_to_poc(a,l)   __flush_dcache_area((a), (l))
+
+static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
 {
+       return (vcpu_sys_reg(vcpu, SCTLR_EL1) & 0b101) == 0b101;
+}
+
+static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
+                                            unsigned long size)
+{
+       if (!vcpu_has_cache_enabled(vcpu))
+               kvm_flush_dcache_to_poc((void *)hva, size);
+
        if (!icache_is_aliasing()) {            /* PIPT */
                flush_icache_range(hva, hva + size);
        } else if (!icache_is_aivivt()) {       /* non ASID-tagged VIVT */
@@ -135,8 +148,9 @@ static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva,
        }
 }
 
-#define kvm_flush_dcache_to_poc(a,l)   __flush_dcache_area((a), (l))
 #define kvm_virt_to_phys(x)            __virt_to_phys((unsigned long)(x))
 
+void stage2_flush_vm(struct kvm *kvm);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ARM64_KVM_MMU_H__ */
index a9eee33dfa62dc031ab8262c275eba79f8609bac..101a42bde728a8b9547bca989b696d473dcd7e42 100644 (file)
@@ -151,6 +151,15 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 {
        unsigned int cpu = smp_processor_id();
 
+       /*
+        * init_mm.pgd does not contain any user mappings and it is always
+        * active for kernel addresses in TTBR1. Just set the reserved TTBR0.
+        */
+       if (next == &init_mm) {
+               cpu_set_reserved_ttbr0();
+               return;
+       }
+
        if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next)
                check_and_switch_context(next, tsk);
 }
index 6d20b7d162d834da4f9364e340e81d6014ec566a..a268a9af0c2d8f2c5ac62581181e123a3a912330 100644 (file)
@@ -43,7 +43,7 @@ $(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
        $(call if_changed,vdsosym)
 
 # Assembly rules for the .S files
-$(obj-vdso): %.o: %.S
+$(obj-vdso): %.o: %.S FORCE
        $(call if_changed_dep,vdsoas)
 
 # Actual build commands
index 2c56012cb2d2c8d82588063058f4444e188d13f6..b0d1512acf08fcf57fc2e39d5305b9ffa9e46a14 100644 (file)
@@ -630,9 +630,15 @@ ENTRY(__kvm_tlb_flush_vmid_ipa)
         * whole of Stage-1. Weep...
         */
        tlbi    ipas2e1is, x1
-       dsb     sy
+       /*
+        * We have to ensure completion of the invalidation at Stage-2,
+        * since a table walk on another CPU could refill a TLB with a
+        * complete (S1 + S2) walk based on the old Stage-2 mapping if
+        * the Stage-1 invalidation happened first.
+        */
+       dsb     ish
        tlbi    vmalle1is
-       dsb     sy
+       dsb     ish
        isb
 
        msr     vttbr_el2, xzr
@@ -643,7 +649,7 @@ ENTRY(__kvm_flush_vm_context)
        dsb     ishst
        tlbi    alle1is
        ic      ialluis
-       dsb     sy
+       dsb     ish
        ret
 ENDPROC(__kvm_flush_vm_context)
 
index 02e9d09e1d804b4e9344427037dd5a2b88d378ba..03244582bc555af4b303fca4370890e278114d16 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/kvm_host.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_mmu.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <trace/events/kvm.h>
@@ -120,6 +121,48 @@ done:
        return true;
 }
 
+/*
+ * Generic accessor for VM registers. Only called as long as HCR_TVM
+ * is set.
+ */
+static bool access_vm_reg(struct kvm_vcpu *vcpu,
+                         const struct sys_reg_params *p,
+                         const struct sys_reg_desc *r)
+{
+       unsigned long val;
+
+       BUG_ON(!p->is_write);
+
+       val = *vcpu_reg(vcpu, p->Rt);
+       if (!p->is_aarch32) {
+               vcpu_sys_reg(vcpu, r->reg) = val;
+       } else {
+               vcpu_cp15(vcpu, r->reg) = val & 0xffffffffUL;
+               if (!p->is_32bit)
+                       vcpu_cp15(vcpu, r->reg + 1) = val >> 32;
+       }
+       return true;
+}
+
+/*
+ * SCTLR_EL1 accessor. Only called as long as HCR_TVM is set.  If the
+ * guest enables the MMU, we stop trapping the VM sys_regs and leave
+ * it in complete control of the caches.
+ */
+static bool access_sctlr(struct kvm_vcpu *vcpu,
+                        const struct sys_reg_params *p,
+                        const struct sys_reg_desc *r)
+{
+       access_vm_reg(vcpu, p, r);
+
+       if (vcpu_has_cache_enabled(vcpu)) {     /* MMU+Caches enabled? */
+               vcpu->arch.hcr_el2 &= ~HCR_TVM;
+               stage2_flush_vm(vcpu->kvm);
+       }
+
+       return true;
+}
+
 /*
  * We could trap ID_DFR0 and tell the guest we don't support performance
  * monitoring.  Unfortunately the patch to make the kernel check ID_DFR0 was
@@ -185,32 +228,32 @@ static const struct sys_reg_desc sys_reg_descs[] = {
          NULL, reset_mpidr, MPIDR_EL1 },
        /* SCTLR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b000),
-         NULL, reset_val, SCTLR_EL1, 0x00C50078 },
+         access_sctlr, reset_val, SCTLR_EL1, 0x00C50078 },
        /* CPACR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b010),
          NULL, reset_val, CPACR_EL1, 0 },
        /* TTBR0_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b000),
-         NULL, reset_unknown, TTBR0_EL1 },
+         access_vm_reg, reset_unknown, TTBR0_EL1 },
        /* TTBR1_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b001),
-         NULL, reset_unknown, TTBR1_EL1 },
+         access_vm_reg, reset_unknown, TTBR1_EL1 },
        /* TCR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b010),
-         NULL, reset_val, TCR_EL1, 0 },
+         access_vm_reg, reset_val, TCR_EL1, 0 },
 
        /* AFSR0_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0001), Op2(0b000),
-         NULL, reset_unknown, AFSR0_EL1 },
+         access_vm_reg, reset_unknown, AFSR0_EL1 },
        /* AFSR1_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0001), Op2(0b001),
-         NULL, reset_unknown, AFSR1_EL1 },
+         access_vm_reg, reset_unknown, AFSR1_EL1 },
        /* ESR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0010), Op2(0b000),
-         NULL, reset_unknown, ESR_EL1 },
+         access_vm_reg, reset_unknown, ESR_EL1 },
        /* FAR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000),
-         NULL, reset_unknown, FAR_EL1 },
+         access_vm_reg, reset_unknown, FAR_EL1 },
        /* PAR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000),
          NULL, reset_unknown, PAR_EL1 },
@@ -224,17 +267,17 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
        /* MAIR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0010), Op2(0b000),
-         NULL, reset_unknown, MAIR_EL1 },
+         access_vm_reg, reset_unknown, MAIR_EL1 },
        /* AMAIR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0011), Op2(0b000),
-         NULL, reset_amair_el1, AMAIR_EL1 },
+         access_vm_reg, reset_amair_el1, AMAIR_EL1 },
 
        /* VBAR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b0000), Op2(0b000),
          NULL, reset_val, VBAR_EL1, 0 },
        /* CONTEXTIDR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
-         NULL, reset_val, CONTEXTIDR_EL1, 0 },
+         access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
        /* TPIDR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b100),
          NULL, reset_unknown, TPIDR_EL1 },
@@ -305,14 +348,32 @@ static const struct sys_reg_desc sys_reg_descs[] = {
          NULL, reset_val, FPEXC32_EL2, 0x70 },
 };
 
-/* Trapped cp15 registers */
+/*
+ * Trapped cp15 registers. TTBR0/TTBR1 get a double encoding,
+ * depending on the way they are accessed (as a 32bit or a 64bit
+ * register).
+ */
 static const struct sys_reg_desc cp15_regs[] = {
+       { Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
+       { Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_sctlr, NULL, c1_SCTLR },
+       { Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
+       { Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
+       { Op1( 0), CRn( 2), CRm( 0), Op2( 2), access_vm_reg, NULL, c2_TTBCR },
+       { Op1( 0), CRn( 3), CRm( 0), Op2( 0), access_vm_reg, NULL, c3_DACR },
+       { Op1( 0), CRn( 5), CRm( 0), Op2( 0), access_vm_reg, NULL, c5_DFSR },
+       { Op1( 0), CRn( 5), CRm( 0), Op2( 1), access_vm_reg, NULL, c5_IFSR },
+       { Op1( 0), CRn( 5), CRm( 1), Op2( 0), access_vm_reg, NULL, c5_ADFSR },
+       { Op1( 0), CRn( 5), CRm( 1), Op2( 1), access_vm_reg, NULL, c5_AIFSR },
+       { Op1( 0), CRn( 6), CRm( 0), Op2( 0), access_vm_reg, NULL, c6_DFAR },
+       { Op1( 0), CRn( 6), CRm( 0), Op2( 2), access_vm_reg, NULL, c6_IFAR },
+
        /*
         * DC{C,I,CI}SW operations:
         */
        { Op1( 0), CRn( 7), CRm( 6), Op2( 2), access_dcsw },
        { Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw },
        { Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw },
+
        { Op1( 0), CRn( 9), CRm(12), Op2( 0), pm_fake },
        { Op1( 0), CRn( 9), CRm(12), Op2( 1), pm_fake },
        { Op1( 0), CRn( 9), CRm(12), Op2( 2), pm_fake },
@@ -326,6 +387,14 @@ static const struct sys_reg_desc cp15_regs[] = {
        { Op1( 0), CRn( 9), CRm(14), Op2( 0), pm_fake },
        { Op1( 0), CRn( 9), CRm(14), Op2( 1), pm_fake },
        { Op1( 0), CRn( 9), CRm(14), Op2( 2), pm_fake },
+
+       { Op1( 0), CRn(10), CRm( 2), Op2( 0), access_vm_reg, NULL, c10_PRRR },
+       { Op1( 0), CRn(10), CRm( 2), Op2( 1), access_vm_reg, NULL, c10_NMRR },
+       { Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 },
+       { Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 },
+       { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID },
+
+       { Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 },
 };
 
 /* Target specific emulation tables */
@@ -437,6 +506,8 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
        u32 hsr = kvm_vcpu_get_hsr(vcpu);
        int Rt2 = (hsr >> 10) & 0xf;
 
+       params.is_aarch32 = true;
+       params.is_32bit = false;
        params.CRm = (hsr >> 1) & 0xf;
        params.Rt = (hsr >> 5) & 0xf;
        params.is_write = ((hsr & 1) == 0);
@@ -480,6 +551,8 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
        struct sys_reg_params params;
        u32 hsr = kvm_vcpu_get_hsr(vcpu);
 
+       params.is_aarch32 = true;
+       params.is_32bit = true;
        params.CRm = (hsr >> 1) & 0xf;
        params.Rt  = (hsr >> 5) & 0xf;
        params.is_write = ((hsr & 1) == 0);
@@ -549,6 +622,8 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
        struct sys_reg_params params;
        unsigned long esr = kvm_vcpu_get_hsr(vcpu);
 
+       params.is_aarch32 = false;
+       params.is_32bit = false;
        params.Op0 = (esr >> 20) & 3;
        params.Op1 = (esr >> 14) & 0x7;
        params.CRn = (esr >> 10) & 0xf;
index d50d3722998ef1365ab0b5400735acccc7b4197a..d411e251412c316bb28b7d971b4dbc0c6e996ee3 100644 (file)
@@ -30,6 +30,8 @@ struct sys_reg_params {
        u8      Op2;
        u8      Rt;
        bool    is_write;
+       bool    is_aarch32;
+       bool    is_32bit;       /* Only valid if is_aarch32 is true */
 };
 
 struct sys_reg_desc {
index fbd76785c5db640bf511a9647380ebb1ae29b3ef..3974881388bbbe24be2f4c4822ac5adbd30c634a 100644 (file)
@@ -44,6 +44,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
                flags |= GFP_DMA32;
        if (IS_ENABLED(CONFIG_DMA_CMA)) {
                struct page *page;
+               void *addr;
 
                size = PAGE_ALIGN(size);
                page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
@@ -52,7 +53,10 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
                        return NULL;
 
                *dma_handle = phys_to_dma(dev, page_to_phys(page));
-               return page_address(page);
+               addr = page_address(page);
+               if (flags & __GFP_ZERO)
+                       memset(addr, 0, size);
+               return addr;
        } else {
                return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
        }
index 0eca93327195077ec16bdfd99efd7294c6ab2de6..d223a8b57c1eaad282289e75089654153ab598d6 100644 (file)
@@ -142,6 +142,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 356ee84cad95aef68e6e9aca6f88b42e0eb931ec..04845aaf59858f81feebeeca6c45096b48c313d8 100644 (file)
@@ -49,7 +49,7 @@ u64 sched_clock(void)
        return (tsc * sched_clock_multiplier) >> SCHED_CLOCK_SHIFT;
 }
 
-void time_init(void)
+void __init time_init(void)
 {
        u64 tmp = (u64)NSEC_PER_SEC << SCHED_CLOCK_SHIFT;
 
index 1790f22e71a21a859b2b7b1942cbbc503c2d557e..2686a7aa8ec82c50f29592840185b519522c53a7 100644 (file)
@@ -176,6 +176,8 @@ retry:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 9a66372fc7c76019ca874a9c3780c2fc8392266c..ec4917ddf67872aa46b60c6b067b0a67ec5417a4 100644 (file)
@@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 7225dad87094d81e89459e5a61909fa5b2d10ca0..ba5ba7accd0d6bb4dbab34f7fc307c4306347f4a 100644 (file)
@@ -172,6 +172,8 @@ retry:
                 */
                if (fault & VM_FAULT_OOM) {
                        goto out_of_memory;
+               } else if (fault & VM_FAULT_SIGSEGV) {
+                       goto bad_area;
                } else if (fault & VM_FAULT_SIGBUS) {
                        signal = SIGBUS;
                        goto bad_area;
index e9c6a8014bd647eec50a66afb5bc75b076b35e4d..e3d4d4890104cc27e2eb9de2f22cb6f53f939c90 100644 (file)
@@ -200,6 +200,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 2bd7487440c455802dac6470ec05ac138148bfcb..b2f04aee46ecc2f7a5fb1db26d8e4279f6b6ea2e 100644 (file)
@@ -145,6 +145,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto map_err;
                else if (fault & VM_FAULT_SIGBUS)
                        goto bus_err;
                BUG();
index 332680e5ebf23c7909b796c415c2273efd77ba3c..2de5dc695a87fa96d41a83e127166a7126d10df0 100644 (file)
@@ -141,6 +141,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index fa4cf52aa7a6d386711690005a314ece7d67fc53..d46a5ebb7570e07869ea03b9b995374aa3bff82e 100644 (file)
@@ -224,6 +224,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
diff --git a/arch/mips/include/asm/suspend.h b/arch/mips/include/asm/suspend.h
deleted file mode 100644 (file)
index 3adac3b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_SUSPEND_H
-#define __ASM_SUSPEND_H
-
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
-#endif /* __ASM_SUSPEND_H */
index bc9e0f406c088e4bebac1f119151021f3b044817..e51621e36152b2f9d1b105c7da0703dca51c25e0 100644 (file)
@@ -26,18 +26,18 @@ TRACE_EVENT(kvm_exit,
            TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason),
            TP_ARGS(vcpu, reason),
            TP_STRUCT__entry(
-                       __field(struct kvm_vcpu *, vcpu)
+                       __field(unsigned long, pc)
                        __field(unsigned int, reason)
            ),
 
            TP_fast_assign(
-                       __entry->vcpu = vcpu;
+                       __entry->pc = vcpu->arch.pc;
                        __entry->reason = reason;
            ),
 
            TP_printk("[%s]PC: 0x%08lx",
                      kvm_mips_exit_types_str[__entry->reason],
-                     __entry->vcpu->arch.pc)
+                     __entry->pc)
 );
 
 #endif /* _TRACE_KVM_H */
index becc42bb18495adf98389bd039bc111c1893cedd..70ab5d664332694e92305331f13ed15a35ab1956 100644 (file)
@@ -158,6 +158,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 521e5963df05f4f67038f52dd3b321851fa0e551..2129e67723ff38b6a1ef8fea8401886a063c8402 100644 (file)
@@ -7,7 +7,7 @@
  * Author: Hu Hongbing <huhb@lemote.com>
  *        Wu Zhangjin <wuzhangjin@gmail.com>
  */
-#include <asm/suspend.h>
+#include <asm/sections.h>
 #include <asm/fpu.h>
 #include <asm/dsp.h>
 
index 32a7c828f073be90c228756e3e0712c8ea6c195e..e7567c8a9e79659ac1420375d77c12623a630188 100644 (file)
@@ -30,6 +30,8 @@ LEAF(swsusp_arch_suspend)
 END(swsusp_arch_suspend)
 
 LEAF(swsusp_arch_resume)
+       /* Avoid TLB mismatch during and after kernel resume */
+       jal local_flush_tlb_all
        PTR_L t0, restore_pblist
 0:
        PTR_L t1, PBE_ADDRESS(t0)   /* source */
@@ -43,7 +45,6 @@ LEAF(swsusp_arch_resume)
        bne t1, t3, 1b
        PTR_L t0, PBE_NEXT(t0)
        bnez t0, 0b
-       jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */
        PTR_LA t0, saved_regs
        PTR_L ra, PT_R31(t0)
        PTR_L sp, PT_R29(t0)
index 3516cbdf1ee93acb82ebef6428f79df9af104514..0c2cc5d39c8e37ce1cfe5be191902bc435c41090 100644 (file)
@@ -262,6 +262,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 0703acf7d3276811919fd3d398ada99b1b9c6d50..230ac20ae7944f71636e5083fdaf3f034eb10af2 100644 (file)
@@ -171,6 +171,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index d72197f0ddb863999f1bfb62a2a81c6d60038445..d27e38874e812be462ce7a9e17892a878e607d1f 100644 (file)
@@ -256,6 +256,8 @@ good_area:
                 */
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto bad_area;
                BUG();
index 1382fec9e8c5f82f4c5bff8bcf22184d28cc7c5b..7fcb1ac0f2325fd73903066953430fb1fa5af64f 100644 (file)
@@ -50,6 +50,7 @@ ethernet@b0000 {
        fsl,num_tx_queues = <0x8>;
        fsl,magic-packet;
        local-mac-address = [ 00 00 00 00 00 00 ];
+       ranges;
 
        queue-group@b0000 {
                #address-cells = <1>;
index 221cd2ea5b3124260e411f697b861da19a9c9920..9f25427c152785c36ed83fee53a5c846820b3f2c 100644 (file)
@@ -50,6 +50,7 @@ ethernet@b1000 {
        fsl,num_tx_queues = <0x8>;
        fsl,magic-packet;
        local-mac-address = [ 00 00 00 00 00 00 ];
+       ranges;
 
        queue-group@b1000 {
                #address-cells = <1>;
index 61456c317609ce751b0551a45e26e0b117a29f4e..cd7c318ab131afac65198ab9556067ca59be04bf 100644 (file)
@@ -49,6 +49,7 @@ ethernet@b2000 {
        fsl,num_tx_queues = <0x8>;
        fsl,magic-packet;
        local-mac-address = [ 00 00 00 00 00 00 ];
+       ranges;
 
        queue-group@b2000 {
                #address-cells = <1>;
index 2912b8787aa46b4b28b0e84a2e5c068afc2f5ea2..3eb36cea324c13a9f65e7695905f66c575954286 100644 (file)
@@ -61,11 +61,21 @@ struct cache_type_info {
 };
 
 /* These are used to index the cache_type_info array. */
-#define CACHE_TYPE_UNIFIED     0
-#define CACHE_TYPE_INSTRUCTION 1
-#define CACHE_TYPE_DATA        2
+#define CACHE_TYPE_UNIFIED     0 /* cache-size, cache-block-size, etc. */
+#define CACHE_TYPE_UNIFIED_D   1 /* d-cache-size, d-cache-block-size, etc */
+#define CACHE_TYPE_INSTRUCTION 2
+#define CACHE_TYPE_DATA        3
 
 static const struct cache_type_info cache_type_info[] = {
+       {
+               /* Embedded systems that use cache-size, cache-block-size,
+                * etc. for the Unified (typically L2) cache. */
+               .name            = "Unified",
+               .size_prop       = "cache-size",
+               .line_size_props = { "cache-line-size",
+                                    "cache-block-size", },
+               .nr_sets_prop    = "cache-sets",
+       },
        {
                /* PowerPC Processor binding says the [di]-cache-*
                 * must be equal on unified caches, so just use
@@ -293,7 +303,8 @@ static struct cache *cache_find_first_sibling(struct cache *cache)
 {
        struct cache *iter;
 
-       if (cache->type == CACHE_TYPE_UNIFIED)
+       if (cache->type == CACHE_TYPE_UNIFIED ||
+           cache->type == CACHE_TYPE_UNIFIED_D)
                return cache;
 
        list_for_each_entry(iter, &cache_list, list)
@@ -324,16 +335,29 @@ static bool cache_node_is_unified(const struct device_node *np)
        return of_get_property(np, "cache-unified", NULL);
 }
 
-static struct cache *cache_do_one_devnode_unified(struct device_node *node,
-                                                 int level)
+/*
+ * Unified caches can have two different sets of tags.  Most embedded
+ * use cache-size, etc. for the unified cache size, but open firmware systems
+ * use d-cache-size, etc.   Check on initialization for which type we have, and
+ * return the appropriate structure type.  Assume it's embedded if it isn't
+ * open firmware.  If it's yet a 3rd type, then there will be missing entries
+ * in /sys/devices/system/cpu/cpu0/cache/index2/, and this code will need
+ * to be extended further.
+ */
+static int cache_is_unified_d(const struct device_node *np)
 {
-       struct cache *cache;
+       return of_get_property(np,
+               cache_type_info[CACHE_TYPE_UNIFIED_D].size_prop, NULL) ?
+               CACHE_TYPE_UNIFIED_D : CACHE_TYPE_UNIFIED;
+}
 
+/*
+ */
+static struct cache *cache_do_one_devnode_unified(struct device_node *node, int level)
+{
        pr_debug("creating L%d ucache for %s\n", level, node->full_name);
 
-       cache = new_cache(CACHE_TYPE_UNIFIED, level, node);
-
-       return cache;
+       return new_cache(cache_is_unified_d(node), level, node);
 }
 
 static struct cache *cache_do_one_devnode_split(struct device_node *node,
index 38d507306a111dc40f06028c90d5014e2fedd817..5193116eadc05b4d42f0c11a9678dabf654d0b10 100644 (file)
@@ -1422,7 +1422,7 @@ machine_check_handle_early:
        bne     9f                      /* continue in V mode if we are. */
 
 5:
-#ifdef CONFIG_KVM_BOOK3S_64_HV
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
        /*
         * We are coming from kernel context. Check if we are coming from
         * guest. if yes, then we can continue. We will fall through
index 0167d53da30cbbbb1e61c8cdb8768db35e4b3e7a..a531154cc0f3a43f06edbba75e3207ab92b105d5 100644 (file)
@@ -9,9 +9,7 @@
 
 #include <linux/mm.h>
 #include <asm/page.h>
-
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
+#include <asm/sections.h>
 
 /*
  *     pfn_is_nosave - check if given pfn is in the 'nosave' section
index 51ab9e7e6c391b9497a08730a7b5e4c625c96304..010fabf3828c03757d5a063554125431222df965 100644 (file)
@@ -432,6 +432,8 @@ good_area:
         */
        fault = handle_mm_fault(mm, vma, address, flags);
        if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
+               if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                rc = mm_fault_error(regs, address, fault);
                if (rc >= MM_FAULT_RETURN)
                        goto bail;
index 2396dda282cdef0ed5c11c6ab7c3f4f479d0ac04..ead55351b2542accc663c496be8592b9c3942b08 100644 (file)
@@ -243,7 +243,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
        sp = regs->gpr[1];
        perf_callchain_store(entry, next_ip);
 
-       for (;;) {
+       while (entry->nr < PERF_MAX_STACK_DEPTH) {
                fp = (unsigned long __user *) sp;
                if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp))
                        return;
index 2b90ff8a93bea7542fee7d89f99d3439bf9e0d13..59ef76c5f4f4a4eb5340323a17435bfde19bfc38 100644 (file)
@@ -197,7 +197,7 @@ static int tce_build_cell(struct iommu_table *tbl, long index, long npages,
 
        io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
 
-       for (i = 0; i < npages; i++, uaddr += tbl->it_page_shift)
+       for (i = 0; i < npages; i++, uaddr += (1 << tbl->it_page_shift))
                io_pte[i] = base_pte | (__pa(uaddr) & CBE_IOPTE_RPN_Mask);
 
        mb();
index 641e7273d75ae687335716c5b4e87c9afcdb98c7..62f3e4e48a0b235a0bfe6ad577feccc8a3dc36aa 100644 (file)
@@ -75,7 +75,7 @@ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
                if (*flt & VM_FAULT_OOM) {
                        ret = -ENOMEM;
                        goto out_unlock;
-               } else if (*flt & VM_FAULT_SIGBUS) {
+               } else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
                        ret = -EFAULT;
                        goto out_unlock;
                }
index 87ba7cf99cd754590ffaf2f038926ae9098f4ca9..65d633f20d37f4c7fc4efb45952e8cd9c7742f15 100644 (file)
@@ -164,7 +164,7 @@ static void spufs_prune_dir(struct dentry *dir)
        struct dentry *dentry, *tmp;
 
        mutex_lock(&dir->d_inode->i_mutex);
-       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
                spin_lock(&dentry->d_lock);
                if (!(d_unhashed(dentry)) && dentry->d_inode) {
                        dget_dlock(dentry);
index cde4e0a095ae25bb208ff5d11c30c22c733f783f..bf3829242afff3b4e839975e36ef2928dc47dcec 100644 (file)
 static struct kobject *mobility_kobj;
 
 struct update_props_workarea {
-       u32 phandle;
-       u32 state;
-       u64 reserved;
-       u32 nprops;
+       __be32 phandle;
+       __be32 state;
+       __be64 reserved;
+       __be32 nprops;
 } __packed;
 
 #define NODE_ACTION_MASK       0xff000000
@@ -53,11 +53,11 @@ static int mobility_rtas_call(int token, char *buf, s32 scope)
        return rc;
 }
 
-static int delete_dt_node(u32 phandle)
+static int delete_dt_node(__be32 phandle)
 {
        struct device_node *dn;
 
-       dn = of_find_node_by_phandle(phandle);
+       dn = of_find_node_by_phandle(be32_to_cpu(phandle));
        if (!dn)
                return -ENOENT;
 
@@ -126,7 +126,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
        return 0;
 }
 
-static int update_dt_node(u32 phandle, s32 scope)
+static int update_dt_node(__be32 phandle, s32 scope)
 {
        struct update_props_workarea *upwa;
        struct device_node *dn;
@@ -135,6 +135,7 @@ static int update_dt_node(u32 phandle, s32 scope)
        char *prop_data;
        char *rtas_buf;
        int update_properties_token;
+       u32 nprops;
        u32 vd;
 
        update_properties_token = rtas_token("ibm,update-properties");
@@ -145,7 +146,7 @@ static int update_dt_node(u32 phandle, s32 scope)
        if (!rtas_buf)
                return -ENOMEM;
 
-       dn = of_find_node_by_phandle(phandle);
+       dn = of_find_node_by_phandle(be32_to_cpu(phandle));
        if (!dn) {
                kfree(rtas_buf);
                return -ENOENT;
@@ -161,6 +162,7 @@ static int update_dt_node(u32 phandle, s32 scope)
                        break;
 
                prop_data = rtas_buf + sizeof(*upwa);
+               nprops = be32_to_cpu(upwa->nprops);
 
                /* On the first call to ibm,update-properties for a node the
                 * the first property value descriptor contains an empty
@@ -169,17 +171,17 @@ static int update_dt_node(u32 phandle, s32 scope)
                 */
                if (*prop_data == 0) {
                        prop_data++;
-                       vd = *(u32 *)prop_data;
+                       vd = be32_to_cpu(*(__be32 *)prop_data);
                        prop_data += vd + sizeof(vd);
-                       upwa->nprops--;
+                       nprops--;
                }
 
-               for (i = 0; i < upwa->nprops; i++) {
+               for (i = 0; i < nprops; i++) {
                        char *prop_name;
 
                        prop_name = prop_data;
                        prop_data += strlen(prop_name) + 1;
-                       vd = *(u32 *)prop_data;
+                       vd = be32_to_cpu(*(__be32 *)prop_data);
                        prop_data += sizeof(vd);
 
                        switch (vd) {
@@ -211,13 +213,13 @@ static int update_dt_node(u32 phandle, s32 scope)
        return 0;
 }
 
-static int add_dt_node(u32 parent_phandle, u32 drc_index)
+static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
 {
        struct device_node *dn;
        struct device_node *parent_dn;
        int rc;
 
-       parent_dn = of_find_node_by_phandle(parent_phandle);
+       parent_dn = of_find_node_by_phandle(be32_to_cpu(parent_phandle));
        if (!parent_dn)
                return -ENOENT;
 
@@ -236,7 +238,7 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index)
 int pseries_devicetree_update(s32 scope)
 {
        char *rtas_buf;
-       u32 *data;
+       __be32 *data;
        int update_nodes_token;
        int rc;
 
@@ -253,17 +255,17 @@ int pseries_devicetree_update(s32 scope)
                if (rc && rc != 1)
                        break;
 
-               data = (u32 *)rtas_buf + 4;
-               while (*data & NODE_ACTION_MASK) {
+               data = (__be32 *)rtas_buf + 4;
+               while (be32_to_cpu(*data) & NODE_ACTION_MASK) {
                        int i;
-                       u32 action = *data & NODE_ACTION_MASK;
-                       int node_count = *data & NODE_COUNT_MASK;
+                       u32 action = be32_to_cpu(*data) & NODE_ACTION_MASK;
+                       u32 node_count = be32_to_cpu(*data) & NODE_COUNT_MASK;
 
                        data++;
 
                        for (i = 0; i < node_count; i++) {
-                               u32 phandle = *data++;
-                               u32 drc_index;
+                               __be32 phandle = *data++;
+                               __be32 drc_index;
 
                                switch (action) {
                                case DELETE_DT_NODE:
index a7a7537ce1e7e415460199098a609b8732de1175..d3236c9e226b87b98323add039a9901df23bcaeb 100644 (file)
 #include <asm/ipl.h>
 #include <asm/cio.h>
 #include <asm/pci.h>
+#include <asm/sections.h>
 #include "entry.h"
 
-/*
- * References to section boundaries
- */
-extern const void __nosave_begin, __nosave_end;
-
 /*
  * The restore of the saved pages in an hibernation image will set
  * the change and referenced bits in the storage key for each page.
@@ -142,6 +138,8 @@ int pfn_is_nosave(unsigned long pfn)
 {
        unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
        unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end));
+       unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1;
+       unsigned long stext_pfn = PFN_DOWN(__pa(&_stext));
 
        /* Always save lowcore pages (LC protection might be enabled). */
        if (pfn <= LC_PAGES)
@@ -149,6 +147,8 @@ int pfn_is_nosave(unsigned long pfn)
        if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn)
                return 1;
        /* Skip memory holes and read-only pages (NSS, DCSS, ...). */
+       if (pfn >= stext_pfn && pfn <= eshared_pfn)
+               return ipl_info.type == IPL_TYPE_NSS ? 1 : 0;
        if (tprot(PFN_PHYS(pfn)))
                return 1;
        return 0;
index 75beea632a10ee7c1bba185d344831e11ec684c5..3588f2f37986af5df448d7e6c97f4885d822329c 100644 (file)
@@ -414,6 +414,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
        for (n = mem->count - 1; n > 0 ; n--)
                memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
 
+       memset(&mem->vm[0], 0, sizeof(mem->vm[0]));
        mem->vm[0].cpus_total = cpus;
        mem->vm[0].cpus_configured = cpus;
        mem->vm[0].cpus_standby = 0;
index d95265b2719f8e7fb0b15305b49a52130069aebd..8e95432cc3b20fd098d4e3b640831bca670efe77 100644 (file)
@@ -239,6 +239,12 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
                                do_no_context(regs);
                        else
                                pagefault_out_of_memory();
+               } else if (fault & VM_FAULT_SIGSEGV) {
+                       /* Kernel mode? Handle exceptions or die */
+                       if (!user_mode(regs))
+                               do_no_context(regs);
+                       else
+                               do_sigsegv(regs, SEGV_MAPERR);
                } else if (fault & VM_FAULT_SIGBUS) {
                        /* Kernel mode? Handle exceptions or die */
                        if (!user_mode(regs))
index 52238983527d605914853fd5415ea39617944ffe..6860beb2a280d0a4a65a67c89ad2201b33513068 100644 (file)
@@ -114,6 +114,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 1b6199740e98ab7e554f1676d615983f451e56a7..7a99e6af637284d3061a96a274f375f2189f2eb2 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <asm-generic/sections.h>
 
-extern long __nosave_begin, __nosave_end;
 extern long __machvec_start, __machvec_end;
 extern char __uncached_start, __uncached_end;
 extern char __start_eh_frame[], __stop_eh_frame[];
index 541dc610150888e706977c7944c42ab1d61d7437..a58fec9b55e016df85cdfb7c214cc385e300479c 100644 (file)
@@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
        } else {
                if (fault & VM_FAULT_SIGBUS)
                        do_sigbus(regs, error_code, address);
+               else if (fault & VM_FAULT_SIGSEGV)
+                       bad_area(regs, error_code, address);
                else
                        BUG();
        }
index 617b9fe33771b72e11204fc3091e3051aa8e34ac..3ccb6777a7e11f5bbdfe0662f5d040a0e58ee7d0 100644 (file)
@@ -960,6 +960,8 @@ out:
        cpuc->pcr[0] |= cpuc->event[0]->hw.config_base;
 }
 
+static void sparc_pmu_start(struct perf_event *event, int flags);
+
 /* On this PMU each PIC has it's own PCR control register.  */
 static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc)
 {
@@ -972,20 +974,13 @@ static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc)
                struct perf_event *cp = cpuc->event[i];
                struct hw_perf_event *hwc = &cp->hw;
                int idx = hwc->idx;
-               u64 enc;
 
                if (cpuc->current_idx[i] != PIC_NO_INDEX)
                        continue;
 
-               sparc_perf_event_set_period(cp, hwc, idx);
                cpuc->current_idx[i] = idx;
 
-               enc = perf_event_get_enc(cpuc->events[i]);
-               cpuc->pcr[idx] &= ~mask_for_index(idx);
-               if (hwc->state & PERF_HES_STOPPED)
-                       cpuc->pcr[idx] |= nop_for_index(idx);
-               else
-                       cpuc->pcr[idx] |= event_encoding(enc, idx);
+               sparc_pmu_start(cp, PERF_EF_RELOAD);
        }
 out:
        for (i = 0; i < cpuc->n_events; i++) {
@@ -1101,7 +1096,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags)
        int i;
 
        local_irq_save(flags);
-       perf_pmu_disable(event->pmu);
 
        for (i = 0; i < cpuc->n_events; i++) {
                if (event == cpuc->event[i]) {
@@ -1127,7 +1121,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags)
                }
        }
 
-       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
 }
 
@@ -1361,7 +1354,6 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags)
        unsigned long flags;
 
        local_irq_save(flags);
-       perf_pmu_disable(event->pmu);
 
        n0 = cpuc->n_events;
        if (n0 >= sparc_pmu->max_hw_events)
@@ -1394,7 +1386,6 @@ nocheck:
 
        ret = 0;
 out:
-       perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
        return ret;
 }
index c6f7113b6e2fb051ceee789f2002baa3ae69938b..1a79d6877981c06ef369d60534d36365fa7483ef 100644 (file)
@@ -281,6 +281,8 @@ void arch_trigger_all_cpu_backtrace(void)
                        printk("             TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n",
                               gp->tpc, gp->o7, gp->i7, gp->rpc);
                }
+
+               touch_nmi_watchdog();
        }
 
        memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
@@ -356,6 +358,8 @@ static void pmu_snapshot_all_cpus(void)
                       (cpu == this_cpu ? '*' : ' '), cpu,
                       pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3],
                       pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]);
+
+               touch_nmi_watchdog();
        }
 
        memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
index beb0b5a5f21ff0cfaf77a48e221932d7a4b060f2..25db14a33d036a64551732561514e09e9f4b2408 100644 (file)
@@ -332,7 +332,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
        long err;
 
        /* No need for backward compatibility. We can start fresh... */
-       if (call <= SEMCTL) {
+       if (call <= SEMTIMEDOP) {
                switch (call) {
                case SEMOP:
                        err = sys_semtimedop(first, ptr,
index b7f6334e159f9d22fc34ccc2f003511009ca9b61..857ad4f8905f942f44ac40770c9277323e4e3c09 100644 (file)
@@ -8,9 +8,11 @@
 
        .text
 ENTRY(memmove) /* o0=dst o1=src o2=len */
-       mov             %o0, %g1
+       brz,pn          %o2, 99f
+        mov            %o0, %g1
+
        cmp             %o0, %o1
-       bleu,pt         %xcc, memcpy
+       bleu,pt         %xcc, 2f
         add            %o1, %o2, %g7
        cmp             %g7, %o0
        bleu,pt         %xcc, memcpy
@@ -24,7 +26,34 @@ ENTRY(memmove) /* o0=dst o1=src o2=len */
        stb             %g7, [%o0]
        bne,pt          %icc, 1b
         sub            %o0, 1, %o0
-
+99:
        retl
         mov            %g1, %o0
+
+       /* We can't just call memcpy for these memmove cases.  On some
+        * chips the memcpy uses cache initializing stores and when dst
+        * and src are close enough, those can clobber the source data
+        * before we've loaded it in.
+        */
+2:     or              %o0, %o1, %g7
+       or              %o2, %g7, %g7
+       andcc           %g7, 0x7, %g0
+       bne,pn          %xcc, 4f
+        nop
+
+3:     ldx             [%o1], %g7
+       add             %o1, 8, %o1
+       subcc           %o2, 8, %o2
+       add             %o0, 8, %o0
+       bne,pt          %icc, 3b
+        stx            %g7, [%o0 - 0x8]
+       ba,a,pt         %xcc, 99b
+
+4:     ldub            [%o1], %g7
+       add             %o1, 1, %o1
+       subcc           %o2, 1, %o2
+       add             %o0, 1, %o0
+       bne,pt          %icc, 4b
+        stb            %g7, [%o0 - 0x1]
+       ba,a,pt         %xcc, 99b
 ENDPROC(memmove)
index 59dbd46457250b050ce84a48370a4f96afa3746d..163c7871211095b12d00592b0d373dd67e136d7f 100644 (file)
@@ -252,6 +252,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 45a413e4380a8f87212204c251088b2eeb524bfc..0d6de79105b6df78c1a6567ae168aa54acaa173c 100644 (file)
@@ -448,6 +448,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index cfbe53c17b0dbb61b25f8ae48c0f3017f307cc6f..09daebdee55210a7469d9604ba0905458d3a0e98 100644 (file)
@@ -460,10 +460,12 @@ static void __init sparc_context_init(int numctx)
 void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
               struct task_struct *tsk)
 {
+       unsigned long flags;
+
        if (mm->context == NO_CONTEXT) {
-               spin_lock(&srmmu_context_spinlock);
+               spin_lock_irqsave(&srmmu_context_spinlock, flags);
                alloc_context(old_mm, mm);
-               spin_unlock(&srmmu_context_spinlock);
+               spin_unlock_irqrestore(&srmmu_context_spinlock, flags);
                srmmu_ctxd_set(&srmmu_context_table[mm->context], mm->pgd);
        }
 
@@ -988,14 +990,15 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 
 void destroy_context(struct mm_struct *mm)
 {
+       unsigned long flags;
 
        if (mm->context != NO_CONTEXT) {
                flush_cache_mm(mm);
                srmmu_ctxd_set(&srmmu_context_table[mm->context], srmmu_swapper_pg_dir);
                flush_tlb_mm(mm);
-               spin_lock(&srmmu_context_spinlock);
+               spin_lock_irqsave(&srmmu_context_spinlock, flags);
                free_context(mm->context);
-               spin_unlock(&srmmu_context_spinlock);
+               spin_unlock_irqrestore(&srmmu_context_spinlock, flags);
                mm->context = NO_CONTEXT;
        }
 }
index 42b0b8ce699a94b295e9ec311de1141531275a14..17bd2e167e07edd934dfe9957c43712b21401c55 100644 (file)
@@ -9,11 +9,9 @@
 #include <asm/hibernate.h>
 #include <asm/visasm.h>
 #include <asm/page.h>
+#include <asm/sections.h>
 #include <asm/tlb.h>
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
 struct saved_context saved_context;
 
 /*
index 6c0571216a9d67f81a09ff331a601d22ae881566..c6d2a76d91a81e3c23d13d6bc101d88c7c3bc461 100644 (file)
@@ -444,6 +444,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 974b87474a9900f1909f845d449eba90dc9b8338..53b832033d9bfc9563651117f7a434df890ab7f3 100644 (file)
@@ -80,6 +80,8 @@ good_area:
                if (unlikely(fault & VM_FAULT_ERROR)) {
                        if (fault & VM_FAULT_OOM) {
                                goto out_of_memory;
+                       } else if (fault & VM_FAULT_SIGSEGV) {
+                               goto out;
                        } else if (fault & VM_FAULT_SIGBUS) {
                                err = -EACCES;
                                goto out;
index 4dcd34ae194cdc54b772a246706ffa5d7460b3f0..77b522694e744b07c4d49b807ebd4c3551ab0bdd 100644 (file)
@@ -36,8 +36,5 @@ extern int puv3_pm_enter(suspend_state_t state);
 /* Defined in hibernate_asm.S */
 extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist);
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
 extern struct pbe *restore_pblist;
 #endif
index d75ef8b6cb5618f28cb2ed0db4192910fcf056e2..9969ec374abb345abcad9ffd5742f155fae36d37 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/sections.h>
 #include <asm/suspend.h>
 
 #include "mach/pm.h"
index 6dfb7d0b139a6beb1afd35a50873909e08ca78c4..6d4fabac779c9caa9f4d40c393c7695a777e8ebb 100644 (file)
@@ -1109,7 +1109,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
                src = kmalloc(req->cryptlen + req->assoclen, GFP_ATOMIC);
                if (!src)
                        return -ENOMEM;
-               assoc = (src + req->cryptlen + auth_tag_len);
+               assoc = (src + req->cryptlen);
                scatterwalk_map_and_copy(src, req->src, 0, req->cryptlen, 0);
                scatterwalk_map_and_copy(assoc, req->assoc, 0,
                        req->assoclen, 0);
@@ -1134,7 +1134,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
                scatterwalk_done(&src_sg_walk, 0, 0);
                scatterwalk_done(&assoc_sg_walk, 0, 0);
        } else {
-               scatterwalk_map_and_copy(dst, req->dst, 0, req->cryptlen, 1);
+               scatterwalk_map_and_copy(dst, req->dst, 0, tempCipherLen, 1);
                kfree(src);
        }
        return retval;
index cea1c76d49bf5b04344bb17c353bab35869cf01a..1ac1c009090d87806e23f0e7dd2db7b4ea2160dc 100644 (file)
@@ -368,7 +368,7 @@ static inline void drop_fpu(struct task_struct *tsk)
        preempt_disable();
        tsk->thread.fpu_counter = 0;
        __drop_fpu(tsk);
-       clear_used_math();
+       clear_stopped_child_used_math(tsk);
        preempt_enable();
 }
 
index 1da25a5f96f92486c8971856123fa000fdc3abc0..3ba047cbcf5bb342b606990722b039903d7cd491 100644 (file)
@@ -30,6 +30,14 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
                     :: "a" (eax), "c" (ecx));
 }
 
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+       trace_hardirqs_on();
+       /* "mwait %eax, %ecx;" */
+       asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
+                    :: "a" (eax), "c" (ecx));
+}
+
 /*
  * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
  * which can obviate IPI to trigger checking of need_resched.
index 02553d6d183d39024ba8bc5d89c616dafb1c08a8..06469ee0f26eae01d1984f15a595fe23d1bb6b47 100644 (file)
@@ -542,11 +542,14 @@ ENTRY(ret_from_fork)
        testl $3, CS-ARGOFFSET(%rsp)            # from kernel_thread?
        jz   1f
 
-       testl $_TIF_IA32, TI_flags(%rcx)        # 32-bit compat task needs IRET
-       jnz  int_ret_from_sys_call
-
-       RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
-       jmp ret_from_sys_call                   # go to the SYSRET fastpath
+       /*
+        * By the time we get here, we have no idea whether our pt_regs,
+        * ti flags, and ti status came from the 64-bit SYSCALL fast path,
+        * the slow path, or one of the ia32entry paths.
+        * Use int_ret_from_sys_call to return, since it can safely handle
+        * all of the above.
+        */
+       jmp  int_ret_from_sys_call
 
 1:
        subq $REST_SKIP, %rsp   # leave space for volatiles
index 3fb8d95ab8b5ea3635ddb1f0d9f9c12e3a348285..1a1ff42094a7b238fb0002d135d4177bb22b427b 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/fpu-internal.h>
 #include <asm/debugreg.h>
 #include <asm/nmi.h>
+#include <asm/mwait.h>
 
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
@@ -398,6 +399,52 @@ static void amd_e400_idle(void)
                default_idle();
 }
 
+/*
+ * Intel Core2 and older machines prefer MWAIT over HALT for C1.
+ * We can't rely on cpuidle installing MWAIT, because it will not load
+ * on systems that support only C1 -- so the boot default must be MWAIT.
+ *
+ * Some AMD machines are the opposite, they depend on using HALT.
+ *
+ * So for default C1, which is used during boot until cpuidle loads,
+ * use MWAIT-C1 on Intel HW that has it, else use HALT.
+ */
+static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
+{
+       if (c->x86_vendor != X86_VENDOR_INTEL)
+               return 0;
+
+       if (!cpu_has(c, X86_FEATURE_MWAIT))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * MONITOR/MWAIT with no hints, used for default default C1 state.
+ * This invokes MWAIT with interrutps enabled and no flags,
+ * which is backwards compatible with the original MWAIT implementation.
+ */
+
+static void mwait_idle(void)
+{
+       if (!current_set_polling_and_test()) {
+               if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) {
+                       mb();
+                       clflush((void *)&current_thread_info()->flags);
+                       mb();
+               }
+
+               __monitor((void *)&current_thread_info()->flags, 0, 0);
+               if (!need_resched())
+                       __sti_mwait(0, 0);
+               else
+                       local_irq_enable();
+       } else
+               local_irq_enable();
+       current_clr_polling();
+}
+
 void select_idle_routine(const struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
@@ -411,6 +458,9 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
                /* E400: APIC timer interrupt does not wake up CPU from C1e */
                pr_info("using AMD E400 aware idle routine\n");
                x86_idle = amd_e400_idle;
+       } else if (prefer_mwait_c1_over_halt(c)) {
+               pr_info("using mwait in idle threads\n");
+               x86_idle = mwait_idle;
        } else
                x86_idle = default_idle;
 }
index c752cb43e52f192f431a5f2ab91b9366e42ef5b0..a6aa91f776547523398d6948ae4f8663b1852da5 100644 (file)
@@ -181,6 +181,16 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                },
        },
 
+       /* ASRock */
+       {       /* Handle problems with rebooting on ASRock Q1900DC-ITX */
+               .callback = set_pci_reboot,
+               .ident = "ASRock Q1900DC-ITX",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ASRock"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Q1900DC-ITX"),
+               },
+       },
+
        /* ASUS */
        {       /* Handle problems with rebooting on ASUS P4S800 */
                .callback = set_bios_reboot,
index dd50e26c58f603bc7427272e12da447519752201..7a09aca4b33ac570dce6f7c890dbc9fac2447cbc 100644 (file)
@@ -375,7 +375,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
                 * thread's fpu state, reconstruct fxstate from the fsave
                 * header. Sanitize the copied state etc.
                 */
-               struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave;
+               struct fpu *fpu = &tsk->thread.fpu;
                struct user_i387_ia32_struct env;
                int err = 0;
 
@@ -389,14 +389,15 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
                 */
                drop_fpu(tsk);
 
-               if (__copy_from_user(xsave, buf_fx, state_size) ||
+               if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) ||
                    __copy_from_user(&env, buf, sizeof(env))) {
+                       fpu_finit(fpu);
                        err = -1;
                } else {
                        sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only);
-                       set_used_math();
                }
 
+               set_used_math();
                if (use_eager_fpu()) {
                        preempt_disable();
                        math_state_restore();
index 38d3751472e451fec11a65552fff180d38e5a085..cf1eeeafdfa35c1580f6fd4d0d6a8626cfdd07c8 100644 (file)
@@ -2258,7 +2258,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
         * Not recognized on AMD in compat mode (but is recognized in legacy
         * mode).
         */
-       if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
+       if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA)
            && !vendor_intel(ctxt))
                return emulate_ud(ctxt);
 
@@ -2271,25 +2271,13 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        setup_syscalls_segments(ctxt, &cs, &ss);
 
        ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
-       switch (ctxt->mode) {
-       case X86EMUL_MODE_PROT32:
-               if ((msr_data & 0xfffc) == 0x0)
-                       return emulate_gp(ctxt, 0);
-               break;
-       case X86EMUL_MODE_PROT64:
-               if (msr_data == 0x0)
-                       return emulate_gp(ctxt, 0);
-               break;
-       default:
-               break;
-       }
+       if ((msr_data & 0xfffc) == 0x0)
+               return emulate_gp(ctxt, 0);
 
        ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
-       cs_sel = (u16)msr_data;
-       cs_sel &= ~SELECTOR_RPL_MASK;
+       cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK;
        ss_sel = cs_sel + 8;
-       ss_sel &= ~SELECTOR_RPL_MASK;
-       if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) {
+       if (efer & EFER_LMA) {
                cs.d = 0;
                cs.l = 1;
        }
@@ -2298,10 +2286,11 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
        ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data);
-       ctxt->_eip = msr_data;
+       ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data;
 
        ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
-       *reg_write(ctxt, VCPU_REGS_RSP) = msr_data;
+       *reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data :
+                                                             (u32)msr_data;
 
        return X86EMUL_CONTINUE;
 }
@@ -4646,7 +4635,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
                if (rc != X86EMUL_CONTINUE)
                        goto done;
        }
-       ctxt->dst.orig_val = ctxt->dst.val;
+       /* Copy full 64-bit value for CMPXCHG8B.  */
+       ctxt->dst.orig_val64 = ctxt->dst.val64;
 
 special_insn:
 
index a10c8c79216187d2faa5add449762710d51c759b..ebc551c8260591f8ab8c47df52c6e1e6df6a55a3 100644 (file)
@@ -833,11 +833,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
          unsigned int fault)
 {
        struct task_struct *tsk = current;
-       struct mm_struct *mm = tsk->mm;
        int code = BUS_ADRERR;
 
-       up_read(&mm->mmap_sem);
-
        /* Kernel mode? Handle exceptions or die: */
        if (!(error_code & PF_USER)) {
                no_context(regs, error_code, address, SIGBUS, BUS_ADRERR);
@@ -868,7 +865,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
               unsigned long address, unsigned int fault)
 {
        if (fatal_signal_pending(current) && !(error_code & PF_USER)) {
-               up_read(&current->mm->mmap_sem);
                no_context(regs, error_code, address, 0, 0);
                return;
        }
@@ -876,14 +872,11 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
        if (fault & VM_FAULT_OOM) {
                /* Kernel mode? Handle exceptions or die: */
                if (!(error_code & PF_USER)) {
-                       up_read(&current->mm->mmap_sem);
                        no_context(regs, error_code, address,
                                   SIGSEGV, SEGV_MAPERR);
                        return;
                }
 
-               up_read(&current->mm->mmap_sem);
-
                /*
                 * We ran out of memory, call the OOM killer, and return the
                 * userspace (which will retry the fault, or kill us if we got
@@ -894,6 +887,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
                if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
                             VM_FAULT_HWPOISON_LARGE))
                        do_sigbus(regs, error_code, address, fault);
+               else if (fault & VM_FAULT_SIGSEGV)
+                       bad_area_nosemaphore(regs, error_code, address);
                else
                        BUG();
        }
@@ -1216,6 +1211,7 @@ good_area:
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
+               up_read(&mm->mmap_sem);
                mm_fault_error(regs, error_code, address, fault);
                return;
        }
index 7d28c885d2385b85c133add5b51176eea8b52af7..291226b952a997f55d3a0be723f15cb9b9b1ab92 100644 (file)
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmzone.h>
+#include <asm/sections.h>
 
 /* Defined in hibernate_asm_32.S */
 extern int restore_image(void);
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
 /* Pointer to the temporary resume page tables */
 pgd_t *resume_pg_dir;
 
index 304fca20d96ee3e1540d7045a9e0e25118c240b0..2276238fde6fb670362d9993b86fb238f84a0b03 100644 (file)
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mtrr.h>
+#include <asm/sections.h>
 #include <asm/suspend.h>
 
-/* References to section boundaries */
-extern __visible const void __nosave_begin, __nosave_end;
-
 /* Defined in hibernate_asm_64.S */
 extern asmlinkage int restore_image(void);
 
index 31776d0efc8c40fa0aa6989731b1ddf23229029c..d7ec4e251c0a2e53572438891508dfeb4a3a016a 100644 (file)
@@ -17,6 +17,7 @@
        .text
        .globl __kernel_sigreturn
        .type __kernel_sigreturn,@function
+       nop /* this guy is needed for .LSTARTFDEDLSI1 below (watch for HACK) */
        ALIGN
 __kernel_sigreturn:
 .LSTART_sigreturn:
index c87ae7c6e5f94636ab576a649ada006b4fb376dc..8879361e477e4de8d32f6aa8fdf6a9d91ee04557 100644 (file)
@@ -336,6 +336,36 @@ menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
 
+config XTFPGA_LCD
+       bool "Enable XTFPGA LCD driver"
+       depends on XTENSA_PLATFORM_XTFPGA
+       default n
+       help
+         There's a 2x16 LCD on most of XTFPGA boards, kernel may output
+         progress messages there during bootup/shutdown. It may be useful
+         during board bringup.
+
+         If unsure, say N.
+
+config XTFPGA_LCD_BASE_ADDR
+       hex "XTFPGA LCD base address"
+       depends on XTFPGA_LCD
+       default "0x0d0c0000"
+       help
+         Base address of the LCD controller inside KIO region.
+         Different boards from XTFPGA family have LCD controller at different
+         addresses. Please consult prototyping user guide for your board for
+         the correct address. Wrong address here may lead to hardware lockup.
+
+config XTFPGA_LCD_8BIT_ACCESS
+       bool "Use 8-bit access to XTFPGA LCD"
+       depends on XTFPGA_LCD
+       default n
+       help
+         LCD may be connected with 4- or 8-bit interface, 8-bit access may
+         only be used with 8-bit interface. Please consult prototyping user
+         guide for your board for the correct interface width.
+
 endmenu
 
 source "net/Kconfig"
index 50084f7c01c825958a3d583bede8d23ed4f5793e..b54fa1bd7f7e9dde2b5bb358afedada439a250bf 100644 (file)
@@ -715,7 +715,7 @@ __SYSCALL(323, sys_process_vm_writev, 6)
 __SYSCALL(324, sys_name_to_handle_at, 5)
 #define __NR_open_by_handle_at                 325
 __SYSCALL(325, sys_open_by_handle_at, 3)
-#define __NR_sync_file_range                   326
+#define __NR_sync_file_range2                  326
 __SYSCALL(326, sys_sync_file_range2, 6)
 #define __NR_perf_event_open                   327
 __SYSCALL(327, sys_perf_event_open, 5)
index b57c4f91f487efdc6b2f3f44fe43cfb12e9a7e0c..9e3571a6535c3b1bbc8535195ee40405fe9c42c0 100644 (file)
@@ -117,6 +117,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index d05f8feeb8d7e16312367e58f52f9d93a175e0cc..17b1ef3232e4833349c2f64ed19e08dede454b52 100644 (file)
@@ -349,8 +349,8 @@ static void iss_net_timer(unsigned long priv)
 {
        struct iss_net_private *lp = (struct iss_net_private *)priv;
 
-       spin_lock(&lp->lock);
        iss_net_poll();
+       spin_lock(&lp->lock);
        mod_timer(&lp->timer, jiffies + lp->timer_val);
        spin_unlock(&lp->lock);
 }
@@ -361,7 +361,7 @@ static int iss_net_open(struct net_device *dev)
        struct iss_net_private *lp = netdev_priv(dev);
        int err;
 
-       spin_lock(&lp->lock);
+       spin_lock_bh(&lp->lock);
 
        err = lp->tp.open(lp);
        if (err < 0)
@@ -376,9 +376,11 @@ static int iss_net_open(struct net_device *dev)
        while ((err = iss_net_rx(dev)) > 0)
                ;
 
-       spin_lock(&opened_lock);
+       spin_unlock_bh(&lp->lock);
+       spin_lock_bh(&opened_lock);
        list_add(&lp->opened_list, &opened);
-       spin_unlock(&opened_lock);
+       spin_unlock_bh(&opened_lock);
+       spin_lock_bh(&lp->lock);
 
        init_timer(&lp->timer);
        lp->timer_val = ISS_NET_TIMER_VALUE;
@@ -387,7 +389,7 @@ static int iss_net_open(struct net_device *dev)
        mod_timer(&lp->timer, jiffies + lp->timer_val);
 
 out:
-       spin_unlock(&lp->lock);
+       spin_unlock_bh(&lp->lock);
        return err;
 }
 
@@ -395,7 +397,7 @@ static int iss_net_close(struct net_device *dev)
 {
        struct iss_net_private *lp = netdev_priv(dev);
        netif_stop_queue(dev);
-       spin_lock(&lp->lock);
+       spin_lock_bh(&lp->lock);
 
        spin_lock(&opened_lock);
        list_del(&opened);
@@ -405,18 +407,17 @@ static int iss_net_close(struct net_device *dev)
 
        lp->tp.close(lp);
 
-       spin_unlock(&lp->lock);
+       spin_unlock_bh(&lp->lock);
        return 0;
 }
 
 static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct iss_net_private *lp = netdev_priv(dev);
-       unsigned long flags;
        int len;
 
        netif_stop_queue(dev);
-       spin_lock_irqsave(&lp->lock, flags);
+       spin_lock_bh(&lp->lock);
 
        len = lp->tp.write(lp, &skb);
 
@@ -438,7 +439,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
                pr_err("%s: %s failed(%d)\n", dev->name, __func__, len);
        }
 
-       spin_unlock_irqrestore(&lp->lock, flags);
+       spin_unlock_bh(&lp->lock);
 
        dev_kfree_skb(skb);
        return NETDEV_TX_OK;
@@ -466,9 +467,9 @@ static int iss_net_set_mac(struct net_device *dev, void *addr)
 
        if (!is_valid_ether_addr(hwaddr->sa_data))
                return -EADDRNOTAVAIL;
-       spin_lock(&lp->lock);
+       spin_lock_bh(&lp->lock);
        memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
-       spin_unlock(&lp->lock);
+       spin_unlock_bh(&lp->lock);
        return 0;
 }
 
@@ -520,11 +521,11 @@ static int iss_net_configure(int index, char *init)
        *lp = (struct iss_net_private) {
                .device_list            = LIST_HEAD_INIT(lp->device_list),
                .opened_list            = LIST_HEAD_INIT(lp->opened_list),
-               .lock                   = __SPIN_LOCK_UNLOCKED(lp.lock),
                .dev                    = dev,
                .index                  = index,
-               };
+       };
 
+       spin_lock_init(&lp->lock);
        /*
         * If this name ends up conflicting with an existing registered
         * netdevice, that is OK, register_netdev{,ice}() will notice this
index b9ae206340cd51012775e22af3391d3839be985e..7839d38b2337885862df5470e06452ea4efce211 100644 (file)
@@ -6,4 +6,5 @@
 #
 # Note 2! The CFLAGS definitions are in the main makefile...
 
-obj-y                  = setup.o lcd.o
+obj-y                  += setup.o
+obj-$(CONFIG_XTFPGA_LCD) += lcd.o
index aeb316b7ff8838f9bcff5d8f29202bac7043823c..e8cc86fbba0977e4b1a1bea298c34f51181d14b7 100644 (file)
@@ -40,9 +40,6 @@
 
 /* UART */
 #define DUART16552_PADDR       (XCHAL_KIO_PADDR + 0x0D050020)
-/* LCD instruction and data addresses. */
-#define LCD_INSTR_ADDR         ((char *)IOADDR(0x0D040000))
-#define LCD_DATA_ADDR          ((char *)IOADDR(0x0D040004))
 
 /* Misc. */
 #define XTFPGA_FPGAREGS_VADDR  IOADDR(0x0D020000)
index 0e435645af5a1ed2043944b6d6fa46647a7a3d86..4c8541ed11396e52bd570cb2cbd0d7bda1782f00 100644 (file)
 #ifndef __XTENSA_XTAVNET_LCD_H
 #define __XTENSA_XTAVNET_LCD_H
 
+#ifdef CONFIG_XTFPGA_LCD
 /* Display string STR at position POS on the LCD. */
 void lcd_disp_at_pos(char *str, unsigned char pos);
 
 /* Shift the contents of the LCD display left or right. */
 void lcd_shiftleft(void);
 void lcd_shiftright(void);
+#else
+static inline void lcd_disp_at_pos(char *str, unsigned char pos)
+{
+}
+
+static inline void lcd_shiftleft(void)
+{
+}
+
+static inline void lcd_shiftright(void)
+{
+}
+#endif
+
 #endif
index 2872301598df266ffe2822f9eb782b0e23b7156c..4dc0c1b43f4bfd917a65fc04b225a790d0fdfeaa 100644 (file)
@@ -1,50 +1,63 @@
 /*
- * Driver for the LCD display on the Tensilica LX60 Board.
+ * Driver for the LCD display on the Tensilica XTFPGA board family.
+ * http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * Copyright (C) 2001, 2006 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  */
 
-/*
- *
- * FIXME: this code is from the examples from the LX60 user guide.
- *
- * The lcd_pause function does busy waiting, which is probably not
- * great. Maybe the code could be changed to use kernel timers, or
- * change the hardware to not need to wait.
- */
-
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
 
 #include <platform/hardware.h>
 #include <platform/lcd.h>
-#include <linux/delay.h>
 
-#define LCD_PAUSE_ITERATIONS   4000
+/* LCD instruction and data addresses. */
+#define LCD_INSTR_ADDR         ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR))
+#define LCD_DATA_ADDR          (LCD_INSTR_ADDR + 4)
+
 #define LCD_CLEAR              0x1
 #define LCD_DISPLAY_ON         0xc
 
 /* 8bit and 2 lines display */
 #define LCD_DISPLAY_MODE8BIT   0x38
+#define LCD_DISPLAY_MODE4BIT   0x28
 #define LCD_DISPLAY_POS                0x80
 #define LCD_SHIFT_LEFT         0x18
 #define LCD_SHIFT_RIGHT                0x1c
 
+static void lcd_put_byte(u8 *addr, u8 data)
+{
+#ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS
+       ACCESS_ONCE(*addr) = data;
+#else
+       ACCESS_ONCE(*addr) = data & 0xf0;
+       ACCESS_ONCE(*addr) = (data << 4) & 0xf0;
+#endif
+}
+
 static int __init lcd_init(void)
 {
-       *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+       ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
        mdelay(5);
-       *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+       ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
        udelay(200);
-       *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+       ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
+       udelay(50);
+#ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS
+       ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT;
+       udelay(50);
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT);
        udelay(50);
-       *LCD_INSTR_ADDR = LCD_DISPLAY_ON;
+#endif
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON);
        udelay(50);
-       *LCD_INSTR_ADDR = LCD_CLEAR;
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR);
        mdelay(10);
        lcd_disp_at_pos("XTENSA LINUX", 0);
        return 0;
@@ -52,10 +65,10 @@ static int __init lcd_init(void)
 
 void lcd_disp_at_pos(char *str, unsigned char pos)
 {
-       *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos;
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos);
        udelay(100);
        while (*str != 0) {
-               *LCD_DATA_ADDR = *str;
+               lcd_put_byte(LCD_DATA_ADDR, *str);
                udelay(200);
                str++;
        }
@@ -63,13 +76,13 @@ void lcd_disp_at_pos(char *str, unsigned char pos)
 
 void lcd_shiftleft(void)
 {
-       *LCD_INSTR_ADDR = LCD_SHIFT_LEFT;
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT);
        udelay(50);
 }
 
 void lcd_shiftright(void)
 {
-       *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT;
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT);
        udelay(50);
 }
 
index 0d9003ae8c61402e027ab4b5bfc933442478b966..359dede01f23afa07f4013ec8a2f00aaebe1e4d3 100644 (file)
@@ -978,6 +978,236 @@ out:
        crypto_free_ahash(tfm);
 }
 
+static inline int do_one_aead_op(struct aead_request *req, int ret)
+{
+       if (ret == -EINPROGRESS || ret == -EBUSY) {
+               struct tcrypt_result *tr = req->base.data;
+
+               ret = wait_for_completion_interruptible(&tr->completion);
+               if (!ret)
+                       ret = tr->err;
+               reinit_completion(&tr->completion);
+       }
+
+       return ret;
+}
+
+static int test_aaead_jiffies(struct aead_request *req, int enc,
+                               int blen, int sec)
+{
+       unsigned long start, end;
+       int bcount;
+       int ret;
+
+       for (start = jiffies, end = start + sec * HZ, bcount = 0;
+            time_before(jiffies, end); bcount++) {
+               if (enc)
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
+               else
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
+
+               if (ret)
+                       return ret;
+       }
+
+       pr_info("%d operations in %d seconds (%ld bytes)\n",
+               bcount, sec, (long)bcount * blen);
+       return 0;
+}
+
+static int test_aaead_cycles(struct aead_request *req, int enc, int blen)
+{
+       unsigned long cycles = 0;
+       int ret = 0;
+       int i;
+
+       /* Warm-up run. */
+       for (i = 0; i < 4; i++) {
+               if (enc)
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
+               else
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
+
+               if (ret)
+                       goto out;
+       }
+
+       /* The real thing. */
+       for (i = 0; i < 8; i++) {
+               cycles_t start, end;
+
+               start = get_cycles();
+               if (enc)
+                       ret = do_one_aead_op(req, crypto_aead_encrypt(req));
+               else
+                       ret = do_one_aead_op(req, crypto_aead_decrypt(req));
+
+               end = get_cycles();
+
+               if (ret)
+                       goto out;
+
+               cycles += end - start;
+       }
+
+out:
+       if (ret == 0)
+               pr_info("1 operation in %lu cycles (%d bytes)\n",
+                       (cycles + 4) / 8, blen);
+
+       return ret;
+}
+
+static void test_aaead_speed(const char *algo, int enc, unsigned int sec,
+                           struct aead_speed_template *template,
+                           unsigned int tcount, u8 authsize,
+                           unsigned int aad_size, u8 *keysize)
+{
+       unsigned int i, j;
+       struct crypto_aead *tfm;
+       int ret = -ENOMEM;
+       const char *key;
+       struct aead_request *req;
+       struct scatterlist *sg;
+       struct scatterlist *asg;
+       struct scatterlist *sgout;
+       const char *e;
+       void *assoc;
+       char iv[MAX_IVLEN];
+       char *xbuf[XBUFSIZE];
+       char *xoutbuf[XBUFSIZE];
+       char *axbuf[XBUFSIZE];
+       unsigned int *b_size;
+       unsigned int iv_len;
+       struct tcrypt_result result;
+
+       if (enc == ENCRYPT)
+               e = "encryption";
+       else
+               e = "decryption";
+
+       if (testmgr_alloc_buf(xbuf))
+               goto out_noxbuf;
+       if (testmgr_alloc_buf(axbuf))
+               goto out_noaxbuf;
+       if (testmgr_alloc_buf(xoutbuf))
+               goto out_nooutbuf;
+
+       sg = kmalloc(sizeof(*sg) * 8 * 3, GFP_KERNEL);
+       if (!sg)
+               goto out_nosg;
+       asg = &sg[8];
+       sgout = &asg[8];
+
+
+       init_completion(&result.completion);
+       pr_info("\ntesting speed of %s %s\n", algo, e);
+
+       tfm = crypto_alloc_aead(algo, 0, 0);
+
+       if (IS_ERR(tfm)) {
+               pr_err("alg: aead: Failed to load transform for %s: %ld\n",
+                      algo, PTR_ERR(tfm));
+               return;
+       }
+
+       req = aead_request_alloc(tfm, GFP_KERNEL);
+       if (!req) {
+               pr_err("alg: aead: Failed to allocate request for %s\n",
+                      algo);
+               goto out;
+       }
+
+       aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                 tcrypt_complete, &result);
+
+       i = 0;
+       do {
+               b_size = aead_sizes;
+               do {
+                       assoc = axbuf[0];
+
+                       if (aad_size < PAGE_SIZE) {
+                               memset(assoc, 0xff, aad_size);
+                       } else {
+                               pr_err("associate data length (%u) too big\n",
+                                      aad_size);
+                               goto out_nosg;
+                       }
+                       sg_init_one(&asg[0], assoc, aad_size);
+
+                       if ((*keysize + *b_size) > TVMEMSIZE * PAGE_SIZE) {
+                               pr_err("template (%u) too big for tvmem (%lu)\n",
+                                      *keysize + *b_size,
+                                       TVMEMSIZE * PAGE_SIZE);
+                               goto out;
+                       }
+
+                       key = tvmem[0];
+                       for (j = 0; j < tcount; j++) {
+                               if (template[j].klen == *keysize) {
+                                       key = template[j].key;
+                                       break;
+                               }
+                       }
+                       ret = crypto_aead_setkey(tfm, key, *keysize);
+                       ret = crypto_aead_setauthsize(tfm, authsize);
+
+                       iv_len = crypto_aead_ivsize(tfm);
+                       if (iv_len)
+                               memset(&iv, 0xff, iv_len);
+
+                       crypto_aead_clear_flags(tfm, ~0);
+                       pr_info("test %u (%d bit key, %d byte blocks): ",
+                               i, *keysize * 8, *b_size);
+
+
+                       memset(tvmem[0], 0xff, PAGE_SIZE);
+
+                       if (ret) {
+                               pr_err("setkey() failed flags=%x\n",
+                                      crypto_aead_get_flags(tfm));
+                               goto out;
+                       }
+
+                       sg_init_aead(&sg[0], xbuf,
+                                    *b_size + (enc ? authsize : 0));
+
+                       sg_init_aead(&sgout[0], xoutbuf,
+                                    *b_size + (enc ? authsize : 0));
+
+                       aead_request_set_crypt(req, sg, sgout, *b_size, iv);
+                       aead_request_set_assoc(req, asg, aad_size);
+
+                       if (sec)
+                               ret = test_aaead_jiffies(req, enc, *b_size,
+                                                        sec);
+                       else
+                               ret = test_aaead_cycles(req, enc, *b_size);
+
+                       if (ret) {
+                               pr_err("%s() failed return code=%d\n", e, ret);
+                               break;
+                       }
+                       b_size++;
+                       i++;
+               } while (*b_size);
+               keysize++;
+       } while (*keysize);
+
+out:
+       crypto_free_aead(tfm);
+       kfree(sg);
+out_nosg:
+       testmgr_free_buf(xoutbuf);
+out_nooutbuf:
+       testmgr_free_buf(axbuf);
+out_noaxbuf:
+       testmgr_free_buf(xbuf);
+out_noxbuf:
+       return;
+}
+
 static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret)
 {
        if (ret == -EINPROGRESS || ret == -EBUSY) {
@@ -2065,6 +2295,12 @@ static int do_test(int m)
                                   speed_template_8_32);
                break;
 
+       case 510:
+               test_aaead_speed("gcm(aes)", ENCRYPT, sec, NULL, 0, 16, 8,
+                                aead_speed_template_16_24_32);
+               break;
+
+
        case 1000:
                test_available();
                break;
index 6c7e21a09f78f170905abf74a897c21dee7a39e9..9810edde49bf873ad77133e3896cf07d2789d2de 100644 (file)
@@ -66,6 +66,7 @@ static u8 speed_template_32_64[] = {32, 64, 0};
  * AEAD speed tests
  */
 static u8 aead_speed_template_20[] = {20, 0};
+static u8 aead_speed_template_16_24_32[] = {16, 24, 32, 0};
 
 /*
  * Digest speed tests
index 2a86c65d873bb6625d3a028b24d299fb2b6101ce..97c7a52dfb4a0993836c2cfb8102b9e84007558d 100644 (file)
 #define ACPI_SET64(ptr, val)            (*ACPI_CAST64 (ptr) = (u64) (val))
 
 /*
- * printf() format helpers
+ * printf() format helper. This macros is a workaround for the difficulties
+ * with emitting 64-bit integers and 64-bit pointers with the same code
+ * for both 32-bit and 64-bit hosts.
  */
 
 /* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */
 
 #define ACPI_FORMAT_UINT64(i)           ACPI_HIDWORD(i), ACPI_LODWORD(i)
 
-#if ACPI_MACHINE_WIDTH == 64
-#define ACPI_FORMAT_NATIVE_UINT(i)      ACPI_FORMAT_UINT64(i)
-#else
-#define ACPI_FORMAT_NATIVE_UINT(i)      0, (i)
-#endif
-
 /*
  * Macros for moving data around to/from buffers that are possibly unaligned.
  * If the hardware supports the transfer of unaligned data, just do the store.
index 5205edcf2c019d1936c81af2d77a8f4e732d9c0d..fe79296fdd9e9a4436c28782566a3d7a57d3e881 100644 (file)
@@ -446,7 +446,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
 
        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
                          obj_desc,
-                         ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
+                         ACPI_FORMAT_UINT64(obj_desc->region.address),
                          obj_desc->region.length));
 
        /* Now the address and length are valid for this opregion */
@@ -539,13 +539,12 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
                return_ACPI_STATUS(AE_NOT_EXIST);
        }
 
-       obj_desc->region.address =
-           (acpi_physical_address) ACPI_TO_INTEGER(table);
+       obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
        obj_desc->region.length = table->length;
 
        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
                          obj_desc,
-                         ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
+                         ACPI_FORMAT_UINT64(obj_desc->region.address),
                          obj_desc->region.length));
 
        /* Now the address and length are valid for this opregion */
index cd4b231ae760b11199f2c3cee3f5b234f85f1c3b..ee8ec4bf0611cea07ba9933cf9f681bf5872c95f 100644 (file)
@@ -272,7 +272,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
        ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                          "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
                          &region_obj->region.handler->address_space, handler,
-                         ACPI_FORMAT_NATIVE_UINT(address),
+                         ACPI_FORMAT_UINT64(address),
                          acpi_ut_get_region_name(region_obj->region.
                                                  space_id)));
 
index 4d046faac48cbb09b2c0aa6c4a0c5e8550333ec5..b64fb68aa5d379f327945e5cb1799f80dbb250e9 100644 (file)
@@ -622,8 +622,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
                        acpi_os_printf("\n");
                } else {
                        acpi_os_printf(" base %8.8X%8.8X Length %X\n",
-                                      ACPI_FORMAT_NATIVE_UINT(obj_desc->region.
-                                                              address),
+                                      ACPI_FORMAT_UINT64(obj_desc->region.
+                                                         address),
                                       obj_desc->region.length);
                }
                break;
index 49fb742d61b98b1f18484f6f1783cba553447555..98af39f0d677962b953aaca3889ea669f512620a 100644 (file)
@@ -263,17 +263,15 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
        }
 
        ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
-                             " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
+                             " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
                              acpi_ut_get_region_name(rgn_desc->region.
                                                      space_id),
                              rgn_desc->region.space_id,
                              obj_desc->common_field.access_byte_width,
                              obj_desc->common_field.base_byte_offset,
-                             field_datum_byte_offset, ACPI_CAST_PTR(void,
-                                                                    (rgn_desc->
-                                                                     region.
-                                                                     address +
-                                                                     region_offset))));
+                             field_datum_byte_offset,
+                             ACPI_FORMAT_UINT64(rgn_desc->region.address +
+                                                region_offset)));
 
        /* Invoke the appropriate address_space/op_region handler */
 
index 9d28867e60dc8b2c907e8cc76c92d10d95caa68e..cf4022359dc730613b2edb047be177a01a92e3f2 100644 (file)
@@ -181,7 +181,7 @@ acpi_ex_system_memory_space_handler(u32 function,
                if (!mem_info->mapped_logical_address) {
                        ACPI_ERROR((AE_INFO,
                                    "Could not map memory at 0x%8.8X%8.8X, size %u",
-                                   ACPI_FORMAT_NATIVE_UINT(address),
+                                   ACPI_FORMAT_UINT64(address),
                                    (u32) map_length));
                        mem_info->mapped_length = 0;
                        return_ACPI_STATUS(AE_NO_MEMORY);
@@ -202,8 +202,7 @@ acpi_ex_system_memory_space_handler(u32 function,
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
-                         bit_width, function,
-                         ACPI_FORMAT_NATIVE_UINT(address)));
+                         bit_width, function, ACPI_FORMAT_UINT64(address)));
 
        /*
         * Perform the memory read or write
@@ -318,8 +317,7 @@ acpi_ex_system_io_space_handler(u32 function,
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
-                         bit_width, function,
-                         ACPI_FORMAT_NATIVE_UINT(address)));
+                         bit_width, function, ACPI_FORMAT_UINT64(address)));
 
        /* Decode the function parameter */
 
index eab70d58852a674fadb1881df67fbc0ad9717aa1..fae57584a182c195b79d0e02e8f5eaba00959b91 100644 (file)
@@ -142,17 +142,17 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
        byte_width = ACPI_DIV_8(bit_width);
        last_address = address + byte_width - 1;
 
-       ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X",
-                         ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void,
-                                                                     last_address),
-                         byte_width));
+       ACPI_DEBUG_PRINT((ACPI_DB_IO,
+                         "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X",
+                         ACPI_FORMAT_UINT64(address),
+                         ACPI_FORMAT_UINT64(last_address), byte_width));
 
        /* Maximum 16-bit address in I/O space */
 
        if (last_address > ACPI_UINT16_MAX) {
                ACPI_ERROR((AE_INFO,
-                           "Illegal I/O port address/length above 64K: %p/0x%X",
-                           ACPI_CAST_PTR(void, address), byte_width));
+                           "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X",
+                           ACPI_FORMAT_UINT64(address), byte_width));
                return_ACPI_STATUS(AE_LIMIT);
        }
 
@@ -181,8 +181,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
 
                        if (acpi_gbl_osi_data >= port_info->osi_dependency) {
                                ACPI_DEBUG_PRINT((ACPI_DB_IO,
-                                                 "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
-                                                 ACPI_CAST_PTR(void, address),
+                                                 "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)",
+                                                 ACPI_FORMAT_UINT64(address),
                                                  byte_width, port_info->name,
                                                  port_info->start,
                                                  port_info->end));
index 48b9c6f1264351b27b7232af13a810c98553eec1..fc82c532090f9931a796c0faa552e5e83a14db6d 100644 (file)
@@ -271,12 +271,11 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
                switch (type) {
                case ACPI_TYPE_PROCESSOR:
 
-                       acpi_os_printf("ID %02X Len %02X Addr %p\n",
+                       acpi_os_printf("ID %02X Len %02X Addr %8.8X%8.8X\n",
                                       obj_desc->processor.proc_id,
                                       obj_desc->processor.length,
-                                      ACPI_CAST_PTR(void,
-                                                    obj_desc->processor.
-                                                    address));
+                                      ACPI_FORMAT_UINT64(obj_desc->processor.
+                                                         address));
                        break;
 
                case ACPI_TYPE_DEVICE:
@@ -347,8 +346,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
                                                               space_id));
                        if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
                                acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n",
-                                              ACPI_FORMAT_NATIVE_UINT
-                                              (obj_desc->region.address),
+                                              ACPI_FORMAT_UINT64(obj_desc->
+                                                                 region.
+                                                                 address),
                                               obj_desc->region.length);
                        } else {
                                acpi_os_printf
index 634357d51fe9b4a30103f5cb1169a97d1da72b7f..c4d097700a867adcf71e7f936ff0ef0e6ba049a0 100644 (file)
@@ -294,8 +294,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
                        ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
                                        "%4.4s %p Attempted physical table override failed",
                                        table_header->signature,
-                                       ACPI_CAST_PTR(void,
-                                                     table_desc->address)));
+                                       ACPI_PHYSADDR_TO_PTR(table_desc->address)));
                        return (NULL);
                }
 
@@ -311,7 +310,7 @@ finish_override:
        ACPI_INFO((AE_INFO,
                   "%4.4s %p %s table override, new table: %p",
                   table_header->signature,
-                  ACPI_CAST_PTR(void, table_desc->address),
+                  ACPI_PHYSADDR_TO_PTR(table_desc->address),
                   override_type, new_table));
 
        /* We can now unmap/delete the original table (if fully mapped) */
index 6866e767ba90947359ca432bcba8643a92c0069d..2957ed50b552eee929cf4b03717a24a05545938f 100644 (file)
@@ -127,16 +127,12 @@ acpi_tb_print_table_header(acpi_physical_address address,
 {
        struct acpi_table_header local_header;
 
-       /*
-        * The reason that the Address is cast to a void pointer is so that we
-        * can use %p which will work properly on both 32-bit and 64-bit hosts.
-        */
        if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) {
 
                /* FACS only has signature and length fields */
 
-               ACPI_INFO((AE_INFO, "%4.4s %p %06X",
-                          header->signature, ACPI_CAST_PTR(void, address),
+               ACPI_INFO((AE_INFO, "%-4.4s 0x%8.8X%8.8X %06X",
+                          header->signature, ACPI_FORMAT_UINT64(address),
                           header->length));
        } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
 
@@ -147,8 +143,8 @@ acpi_tb_print_table_header(acpi_physical_address address,
                                          header)->oem_id, ACPI_OEM_ID_SIZE);
                acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
 
-               ACPI_INFO((AE_INFO, "RSDP %p %06X (v%.2d %6.6s)",
-                          ACPI_CAST_PTR(void, address),
+               ACPI_INFO((AE_INFO, "RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)",
+                          ACPI_FORMAT_UINT64(address),
                           (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
                            revision >
                            0) ? ACPI_CAST_PTR(struct acpi_table_rsdp,
@@ -162,8 +158,9 @@ acpi_tb_print_table_header(acpi_physical_address address,
                acpi_tb_cleanup_table_header(&local_header, header);
 
                ACPI_INFO((AE_INFO,
-                          "%4.4s %p %06X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
-                          local_header.signature, ACPI_CAST_PTR(void, address),
+                          "%-4.4s 0x%8.8X%8.8X"
+                          " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)",
+                          local_header.signature, ACPI_FORMAT_UINT64(address),
                           local_header.length, local_header.revision,
                           local_header.oem_id, local_header.oem_table_id,
                           local_header.oem_revision,
index 1bc879ec83d481bddbcebc830f1325764c10a35f..4cca6b797808048cca48d8be3723e42a89098c97 100644 (file)
@@ -227,8 +227,8 @@ acpi_tb_install_table(acpi_physical_address address,
        table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
        if (!table) {
                ACPI_ERROR((AE_INFO,
-                           "Could not map memory for table [%s] at %p",
-                           signature, ACPI_CAST_PTR(void, address)));
+                           "Could not map memory for table [%s] at %8.8X%8.8X",
+                           signature, ACPI_FORMAT_UINT64(address)));
                return;
        }
 
index 60b5a871833cce325393e516562d2574476d304b..daad59d76e6777f97c5d72542887306a5e1d1650 100644 (file)
@@ -184,11 +184,10 @@ static acpi_status acpi_tb_load_namespace(void)
                 * be useful for debugging ACPI problems on some machines.
                 */
                if (acpi_gbl_disable_ssdt_table_load) {
-                       ACPI_INFO((AE_INFO, "Ignoring %4.4s at %p",
+                       ACPI_INFO((AE_INFO, "Ignoring %4.4s at %8.8X%8.8X",
                                   acpi_gbl_root_table_list.tables[i].signature.
-                                  ascii, ACPI_CAST_PTR(void,
-                                                       acpi_gbl_root_table_list.
-                                                       tables[i].address)));
+                                  ascii, ACPI_FORMAT_UINT64(acpi_gbl_root_table_list.
+                                                            tables[i].address)));
                        continue;
                }
 
index e4e1468877c3a27f2db6899098765ccaa2f42eaa..01bf7ebef7a4bdf6e333e820ae26b072edc35675 100644 (file)
@@ -111,7 +111,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
  *
  ******************************************************************************/
 
-acpi_status __init acpi_find_root_pointer(acpi_size *table_address)
+acpi_status __init acpi_find_root_pointer(acpi_physical_address * table_address)
 {
        u8 *table_ptr;
        u8 *mem_rover;
@@ -169,7 +169,8 @@ acpi_status __init acpi_find_root_pointer(acpi_size *table_address)
                        physical_address +=
                            (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
 
-                       *table_address = physical_address;
+                       *table_address =
+                           (acpi_physical_address) physical_address;
                        return_ACPI_STATUS(AE_OK);
                }
        }
@@ -202,7 +203,7 @@ acpi_status __init acpi_find_root_pointer(acpi_size *table_address)
                    (ACPI_HI_RSDP_WINDOW_BASE +
                     ACPI_PTR_DIFF(mem_rover, table_ptr));
 
-               *table_address = physical_address;
+               *table_address = (acpi_physical_address) physical_address;
                return_ACPI_STATUS(AE_OK);
        }
 
index 2c2b6ae5dfc4ab1fb3dbd20adc670f7214a4a7ed..3a02b65a1d9e6affa9402c0d85c662ee2657933e 100644 (file)
@@ -107,10 +107,10 @@ acpi_ut_add_address_range(acpi_adr_space_type space_id,
        acpi_gbl_address_range_list[space_id] = range_info;
 
        ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-                         "\nAdded [%4.4s] address range: 0x%p-0x%p\n",
+                         "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
                          acpi_ut_get_node_name(range_info->region_node),
-                         ACPI_CAST_PTR(void, address),
-                         ACPI_CAST_PTR(void, range_info->end_address)));
+                         ACPI_FORMAT_UINT64(address),
+                         ACPI_FORMAT_UINT64(range_info->end_address)));
 
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(AE_OK);
@@ -160,15 +160,13 @@ acpi_ut_remove_address_range(acpi_adr_space_type space_id,
                        }
 
                        ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-                                         "\nRemoved [%4.4s] address range: 0x%p-0x%p\n",
+                                         "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
                                          acpi_ut_get_node_name(range_info->
                                                                region_node),
-                                         ACPI_CAST_PTR(void,
-                                                       range_info->
-                                                       start_address),
-                                         ACPI_CAST_PTR(void,
-                                                       range_info->
-                                                       end_address)));
+                                         ACPI_FORMAT_UINT64(range_info->
+                                                            start_address),
+                                         ACPI_FORMAT_UINT64(range_info->
+                                                            end_address)));
 
                        ACPI_FREE(range_info);
                        return_VOID;
@@ -245,16 +243,14 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id,
                                                                  region_node);
 
                                ACPI_WARNING((AE_INFO,
-                                             "%s range 0x%p-0x%p conflicts with OpRegion 0x%p-0x%p (%s)",
+                                             "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)",
                                              acpi_ut_get_region_name(space_id),
-                                             ACPI_CAST_PTR(void, address),
-                                             ACPI_CAST_PTR(void, end_address),
-                                             ACPI_CAST_PTR(void,
-                                                           range_info->
-                                                           start_address),
-                                             ACPI_CAST_PTR(void,
-                                                           range_info->
-                                                           end_address),
+                                             ACPI_FORMAT_UINT64(address),
+                                             ACPI_FORMAT_UINT64(end_address),
+                                             ACPI_FORMAT_UINT64(range_info->
+                                                                start_address),
+                                             ACPI_FORMAT_UINT64(range_info->
+                                                                end_address),
                                              pathname));
                                ACPI_FREE(pathname);
                        }
index 17f9ec501972ef208b505ed881173e2dac0cc2ea..fd8496a92b45ee00b5086742feaf3053fc504f86 100644 (file)
@@ -962,7 +962,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
                return -EINVAL;
 
        drv->safe_state_index = -1;
-       for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+       for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
                drv->states[i].name[0] = '\0';
                drv->states[i].desc[0] = '\0';
        }
index 666beea3bf1c41e2d37d14ec95f72441b3864acf..9498c3d575d40b3fe1e33716d30f97d07b290fe3 100644 (file)
@@ -192,7 +192,11 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
        struct acpi_device_physical_node *pn;
        bool offline = true;
 
-       mutex_lock(&adev->physical_node_lock);
+       /*
+        * acpi_container_offline() calls this for all of the container's
+        * children under the container's physical_node_lock lock.
+        */
+       mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING);
 
        list_for_each_entry(pn, &adev->physical_node_list, node)
                if (device_supports_offline(pn->dev) && !pn->dev->offline) {
index bb0b90461a6b50f6516716c60435e0ae379a4655..997540dc8250871b33173d4d1506a98c01decff1 100644 (file)
@@ -2064,6 +2064,17 @@ EXPORT_SYMBOL(acpi_video_unregister);
 
 static int __init acpi_video_init(void)
 {
+       /*
+        * Let the module load even if ACPI is disabled (e.g. due to
+        * a broken BIOS) so that i915.ko can still be loaded on such
+        * old systems without an AcpiOpRegion.
+        *
+        * acpi_video_register() will report -ENODEV later as well due
+        * to acpi_disabled when i915.ko tries to register itself afterwards.
+        */
+       if (acpi_disabled)
+               return 0;
+
        dmi_check_system(video_dmi_table);
 
        if (intel_opregion_present())
index 45d0fa78981c2cb1b383298a92498c2f47f426c2..12b39dc2ad5c8e679b7dc23291866a54bb6f73bd 100644 (file)
@@ -515,11 +515,11 @@ int bus_add_device(struct device *dev)
                        goto out_put;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
-                       goto out_groups;
+                       goto out_id;
                error = sysfs_create_link(&bus->p->devices_kset->kobj,
                                                &dev->kobj, dev_name(dev));
                if (error)
-                       goto out_id;
+                       goto out_groups;
                error = sysfs_create_link(&dev->kobj,
                                &dev->bus->p->subsys.kobj, "subsystem");
                if (error)
index 930cad4e5df8a10d7af43c42e2b3d0ebee3bf121..2b946bc4212dfb346ab521334277dafc162d7ad2 100644 (file)
@@ -313,7 +313,7 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
        if (pos == 0) {
                memmove(blk + offset * map->cache_word_size,
                        blk, rbnode->blklen * map->cache_word_size);
-               bitmap_shift_right(present, present, offset, blklen);
+               bitmap_shift_left(present, present, offset, blklen);
        }
 
        /* update the rbnode block, its size and the base register */
index 55298db36b2d61a113f25c22905fffb0f22ddd32..d18093681af2de111a2270ea8741625245341eb8 100644 (file)
@@ -814,10 +814,6 @@ static int __init nbd_init(void)
                return -EINVAL;
        }
 
-       nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
-       if (!nbd_dev)
-               return -ENOMEM;
-
        part_shift = 0;
        if (max_part > 0) {
                part_shift = fls(max_part);
@@ -839,6 +835,10 @@ static int __init nbd_init(void)
        if (nbds_max > 1UL << (MINORBITS - part_shift))
                return -EINVAL;
 
+       nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
+       if (!nbd_dev)
+               return -ENOMEM;
+
        for (i = 0; i < nbds_max; i++) {
                struct gendisk *disk = alloc_disk(1 << part_shift);
                if (!disk)
index 275a7dc2b06c70466873a6b03b2ec038713a9e41..63688d3a6ea07b0794bbb7f0577b387bdea90575 100644 (file)
@@ -2084,6 +2084,11 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
                        result, xferred);
                if (!img_request->result)
                        img_request->result = result;
+               /*
+                * Need to end I/O on the entire obj_request worth of
+                * bytes in case of error.
+                */
+               xferred = obj_request->length;
        }
 
        /* Image object requests don't own their page array */
index f667e37394da581f6b65a106ad32b47ca85a728c..26b03e1254ef7ebfc996675085154ed248e4e343 100644 (file)
@@ -62,51 +62,60 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0x3000) },
 
        /* Atheros AR3011 with sflash firmware*/
+       { USB_DEVICE(0x0489, 0xE027) },
+       { USB_DEVICE(0x0489, 0xE03D) },
+       { USB_DEVICE(0x04F2, 0xAFF1) },
+       { USB_DEVICE(0x0930, 0x0215) },
        { USB_DEVICE(0x0CF3, 0x3002) },
        { USB_DEVICE(0x0CF3, 0xE019) },
        { USB_DEVICE(0x13d3, 0x3304) },
-       { USB_DEVICE(0x0930, 0x0215) },
-       { USB_DEVICE(0x0489, 0xE03D) },
-       { USB_DEVICE(0x0489, 0xE027) },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03F0, 0x311D) },
 
        /* Atheros AR3012 with sflash firmware*/
-       { USB_DEVICE(0x0CF3, 0x0036) },
-       { USB_DEVICE(0x0CF3, 0x3004) },
-       { USB_DEVICE(0x0CF3, 0x3008) },
-       { USB_DEVICE(0x0CF3, 0x311D) },
-       { USB_DEVICE(0x0CF3, 0x817a) },
-       { USB_DEVICE(0x13d3, 0x3375) },
+       { USB_DEVICE(0x0489, 0xe04d) },
+       { USB_DEVICE(0x0489, 0xe04e) },
+       { USB_DEVICE(0x0489, 0xe057) },
+       { USB_DEVICE(0x0489, 0xe056) },
+       { USB_DEVICE(0x0489, 0xe05f) },
+       { USB_DEVICE(0x0489, 0xe078) },
+       { USB_DEVICE(0x04c5, 0x1330) },
        { USB_DEVICE(0x04CA, 0x3004) },
        { USB_DEVICE(0x04CA, 0x3005) },
        { USB_DEVICE(0x04CA, 0x3006) },
        { USB_DEVICE(0x04CA, 0x3007) },
        { USB_DEVICE(0x04CA, 0x3008) },
        { USB_DEVICE(0x04CA, 0x300b) },
-       { USB_DEVICE(0x13d3, 0x3362) },
-       { USB_DEVICE(0x0CF3, 0xE004) },
-       { USB_DEVICE(0x0CF3, 0xE005) },
+       { USB_DEVICE(0x04CA, 0x3010) },
        { USB_DEVICE(0x0930, 0x0219) },
        { USB_DEVICE(0x0930, 0x0220) },
-       { USB_DEVICE(0x0489, 0xe057) },
-       { USB_DEVICE(0x13d3, 0x3393) },
-       { USB_DEVICE(0x0489, 0xe04e) },
-       { USB_DEVICE(0x0489, 0xe056) },
-       { USB_DEVICE(0x0489, 0xe04d) },
-       { USB_DEVICE(0x04c5, 0x1330) },
-       { USB_DEVICE(0x13d3, 0x3402) },
+       { USB_DEVICE(0x0930, 0x0227) },
+       { USB_DEVICE(0x0b05, 0x17d0) },
+       { USB_DEVICE(0x0CF3, 0x0036) },
+       { USB_DEVICE(0x0CF3, 0x3004) },
+       { USB_DEVICE(0x0CF3, 0x3008) },
+       { USB_DEVICE(0x0CF3, 0x311D) },
+       { USB_DEVICE(0x0CF3, 0x311E) },
+       { USB_DEVICE(0x0CF3, 0x311F) },
        { USB_DEVICE(0x0cf3, 0x3121) },
+       { USB_DEVICE(0x0CF3, 0x817a) },
        { USB_DEVICE(0x0cf3, 0xe003) },
-       { USB_DEVICE(0x0489, 0xe05f) },
+       { USB_DEVICE(0x0CF3, 0xE004) },
+       { USB_DEVICE(0x0CF3, 0xE005) },
+       { USB_DEVICE(0x13d3, 0x3362) },
+       { USB_DEVICE(0x13d3, 0x3375) },
+       { USB_DEVICE(0x13d3, 0x3393) },
+       { USB_DEVICE(0x13d3, 0x3402) },
+       { USB_DEVICE(0x13d3, 0x3408) },
+       { USB_DEVICE(0x13d3, 0x3432) },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE02C) },
 
        /* Atheros AR5BBU22 with sflash firmware */
-       { USB_DEVICE(0x0489, 0xE03C) },
        { USB_DEVICE(0x0489, 0xE036) },
+       { USB_DEVICE(0x0489, 0xE03C) },
 
        { }     /* Terminating entry */
 };
@@ -119,37 +128,45 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
 static const struct usb_device_id ath3k_blist_tbl[] = {
 
        /* Atheros AR3012 with sflash firmware*/
-       { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU22 with sflash firmware */
-       { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
 
        { }     /* Terminating entry */
 };
index e00c3f84a4cff6b323dd0e91d885515766aa2584..9eb1669962efe7f76f5a484b2a3a48bf228b7cc3 100644 (file)
@@ -49,6 +49,7 @@ static struct usb_driver btusb_driver;
 #define BTUSB_WRONG_SCO_MTU    0x40
 #define BTUSB_ATH3012          0x80
 #define BTUSB_INTEL            0x100
+#define BTUSB_INTEL_BOOT       0x200
 
 static const struct usb_device_id btusb_table[] = {
        /* Generic Bluetooth USB device */
@@ -101,21 +102,31 @@ static const struct usb_device_id btusb_table[] = {
        { USB_DEVICE(0x0c10, 0x0000) },
 
        /* Broadcom BCM20702A0 */
+       { USB_DEVICE(0x0489, 0xe042) },
+       { USB_DEVICE(0x04ca, 0x2003) },
        { USB_DEVICE(0x0b05, 0x17b5) },
        { USB_DEVICE(0x0b05, 0x17cb) },
-       { USB_DEVICE(0x04ca, 0x2003) },
-       { USB_DEVICE(0x0489, 0xe042) },
        { USB_DEVICE(0x413c, 0x8197) },
 
        /* Foxconn - Hon Hai */
        { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
 
-       /*Broadcom devices with vendor specific id */
+       /* Broadcom devices with vendor specific id */
        { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
 
+       /* ASUSTek Computer - Broadcom based */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) },
+
        /* Belkin F8065bf - Broadcom based */
        { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
 
+       /* IMC Networks - Broadcom based */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
+
+       /* Intel Bluetooth USB Bootloader (RAM module) */
+       { USB_DEVICE(0x8087, 0x0a5a),
+         .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
+
        { }     /* Terminating entry */
 };
 
@@ -129,56 +140,65 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
 
        /* Atheros 3011 with sflash firmware */
+       { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
-       { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
-       { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
-       { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
 
        /* Atheros 3012 with sflash firmware */
-       { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
-       { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
 
        /* Atheros AR5BBU12 with sflash firmware */
-       { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
 
        /* Broadcom BCM2035 */
-       { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
-       { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
        { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
+       { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
+       { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
 
        /* Broadcom BCM2045 */
        { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -1491,6 +1511,9 @@ static int btusb_probe(struct usb_interface *intf,
        if (id->driver_info & BTUSB_INTEL)
                hdev->setup = btusb_setup_intel;
 
+       if (id->driver_info & BTUSB_INTEL_BOOT)
+               set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+
        /* Interface numbers are hardcoded in the specification */
        data->isoc = usb_ifnum_to_if(data->udev, 1);
 
index 17d86595951c03a00ab8d0389766bedb5635b45a..88f41b35061697dd2d58980da730585562c50ec1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP L3 Interconnect error handling driver
  *
- * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2011-2015 Texas Instruments Incorporated - http://www.ti.com/
  *     Santosh Shilimkar <santosh.shilimkar@ti.com>
  *     Sricharan <r.sricharan@ti.com>
  *
@@ -233,7 +233,8 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
 }
 
 static const struct of_device_id l3_noc_match[] = {
-       {.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
+       {.compatible = "ti,omap4-l3-noc", .data = &omap4_l3_data},
+       {.compatible = "ti,omap5-l3-noc", .data = &omap5_l3_data},
        {.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
        {.compatible = "ti,am4372-l3-noc", .data = &am4372_l3_data},
        {},
index 551e01061434e723bed922b45ac8ac96cf2b232b..73431f81da28c0036fba33b52a17641eee5e385a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP L3 Interconnect  error handling driver header
  *
- * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2011-2015 Texas Instruments Incorporated - http://www.ti.com/
  *     Santosh Shilimkar <santosh.shilimkar@ti.com>
  *     sricharan <r.sricharan@ti.com>
  *
@@ -175,61 +175,87 @@ static struct l3_flagmux_data omap_l3_flagmux_clk2 = {
 };
 
 
-static struct l3_target_data omap_l3_target_data_clk3[] = {
-       {0x0100, "EMUSS",},
-       {0x0300, "DEBUG SOURCE",},
-       {0x0,   "HOST CLK3",},
+static struct l3_target_data omap4_l3_target_data_clk3[] = {
+       {0x0100, "DEBUGSS",},
 };
 
-static struct l3_flagmux_data omap_l3_flagmux_clk3 = {
+static struct l3_flagmux_data omap4_l3_flagmux_clk3 = {
        .offset = 0x0200,
-       .l3_targ = omap_l3_target_data_clk3,
-       .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk3),
+       .l3_targ = omap4_l3_target_data_clk3,
+       .num_targ_data = ARRAY_SIZE(omap4_l3_target_data_clk3),
 };
 
 static struct l3_masters_data omap_l3_masters[] = {
-       { 0x0 , "MPU"},
-       { 0x10, "CS_ADP"},
-       { 0x14, "xxx"},
-       { 0x20, "DSP"},
-       { 0x30, "IVAHD"},
-       { 0x40, "ISS"},
-       { 0x44, "DucatiM3"},
-       { 0x48, "FaceDetect"},
-       { 0x50, "SDMA_Rd"},
-       { 0x54, "SDMA_Wr"},
-       { 0x58, "xxx"},
-       { 0x5C, "xxx"},
-       { 0x60, "SGX"},
-       { 0x70, "DSS"},
-       { 0x80, "C2C"},
-       { 0x88, "xxx"},
-       { 0x8C, "xxx"},
-       { 0x90, "HSI"},
-       { 0xA0, "MMC1"},
-       { 0xA4, "MMC2"},
-       { 0xA8, "MMC6"},
-       { 0xB0, "UNIPRO1"},
-       { 0xC0, "USBHOSTHS"},
-       { 0xC4, "USBOTGHS"},
-       { 0xC8, "USBHOSTFS"}
-};
-
-static struct l3_flagmux_data *omap_l3_flagmux[] = {
+       { 0x00, "MPU"},
+       { 0x04, "CS_ADP"},
+       { 0x05, "xxx"},
+       { 0x08, "DSP"},
+       { 0x0C, "IVAHD"},
+       { 0x10, "ISS"},
+       { 0x11, "DucatiM3"},
+       { 0x12, "FaceDetect"},
+       { 0x14, "SDMA_Rd"},
+       { 0x15, "SDMA_Wr"},
+       { 0x16, "xxx"},
+       { 0x17, "xxx"},
+       { 0x18, "SGX"},
+       { 0x1C, "DSS"},
+       { 0x20, "C2C"},
+       { 0x22, "xxx"},
+       { 0x23, "xxx"},
+       { 0x24, "HSI"},
+       { 0x28, "MMC1"},
+       { 0x29, "MMC2"},
+       { 0x2A, "MMC6"},
+       { 0x2C, "UNIPRO1"},
+       { 0x30, "USBHOSTHS"},
+       { 0x31, "USBOTGHS"},
+       { 0x32, "USBHOSTFS"}
+};
+
+static struct l3_flagmux_data *omap4_l3_flagmux[] = {
        &omap_l3_flagmux_clk1,
        &omap_l3_flagmux_clk2,
-       &omap_l3_flagmux_clk3,
+       &omap4_l3_flagmux_clk3,
 };
 
-static const struct omap_l3 omap_l3_data = {
-       .l3_flagmux = omap_l3_flagmux,
-       .num_modules = ARRAY_SIZE(omap_l3_flagmux),
+static const struct omap_l3 omap4_l3_data = {
+       .l3_flagmux = omap4_l3_flagmux,
+       .num_modules = ARRAY_SIZE(omap4_l3_flagmux),
        .l3_masters = omap_l3_masters,
        .num_masters = ARRAY_SIZE(omap_l3_masters),
        /* The 6 MSBs of register field used to distinguish initiator */
        .mst_addr_mask = 0xFC,
 };
 
+/* OMAP5 data */
+static struct l3_target_data omap5_l3_target_data_clk3[] = {
+       {0x0100, "L3INSTR",},
+       {0x0300, "DEBUGSS",},
+       {0x0,    "HOSTCLK3",},
+};
+
+static struct l3_flagmux_data omap5_l3_flagmux_clk3 = {
+       .offset = 0x0200,
+       .l3_targ = omap5_l3_target_data_clk3,
+       .num_targ_data = ARRAY_SIZE(omap5_l3_target_data_clk3),
+};
+
+static struct l3_flagmux_data *omap5_l3_flagmux[] = {
+       &omap_l3_flagmux_clk1,
+       &omap_l3_flagmux_clk2,
+       &omap5_l3_flagmux_clk3,
+};
+
+static const struct omap_l3 omap5_l3_data = {
+       .l3_flagmux = omap5_l3_flagmux,
+       .num_modules = ARRAY_SIZE(omap5_l3_flagmux),
+       .l3_masters = omap_l3_masters,
+       .num_masters = ARRAY_SIZE(omap_l3_masters),
+       /* The 6 MSBs of register field used to distinguish initiator */
+       .mst_addr_mask = 0x7E0,
+};
+
 /* DRA7 data */
 static struct l3_target_data dra_l3_target_data_clk1[] = {
        {0x2a00, "AES1",},
@@ -274,7 +300,7 @@ static struct l3_flagmux_data dra_l3_flagmux_clk1 = {
 
 static struct l3_target_data dra_l3_target_data_clk2[] = {
        {0x0,   "HOST CLK1",},
-       {0x0,   "HOST CLK2",},
+       {0x800000, "HOST CLK2",},
        {0xdead, L3_TARGET_NOT_SUPPORTED,},
        {0x3400, "SHA2_2",},
        {0x0900, "BB2D",},
index eff9d587003484098a18752e9aa24166b74f987a..102463ba745dbb6b7586c9790cbac09347bdfbbd 100644 (file)
@@ -124,7 +124,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
 {
        struct ibmvtpm_dev *ibmvtpm;
        struct ibmvtpm_crq crq;
-       u64 *word = (u64 *) &crq;
+       __be64 *word = (__be64 *)&crq;
        int rc;
 
        ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
@@ -145,11 +145,11 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
        memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
        crq.valid = (u8)IBMVTPM_VALID_CMD;
        crq.msg = (u8)VTPM_TPM_COMMAND;
-       crq.len = (u16)count;
-       crq.data = ibmvtpm->rtce_dma_handle;
+       crq.len = cpu_to_be16(count);
+       crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]),
-                             cpu_to_be64(word[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
+                             be64_to_cpu(word[1]));
        if (rc != H_SUCCESS) {
                dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
                rc = 0;
index bd82a791f995d6657f15082bb3f3b957dbc499dc..b2c231b1beec4d9e1378f19fc355839fc956ef5e 100644 (file)
@@ -22,9 +22,9 @@
 struct ibmvtpm_crq {
        u8 valid;
        u8 msg;
-       u16 len;
-       u32 data;
-       u64 reserved;
+       __be16 len;
+       __be32 data;
+       __be64 reserved;
 } __attribute__((packed, aligned(8)));
 
 struct ibmvtpm_crq_queue {
index 6928d094451d607795b4f2a07d7599e01712f824..b08eadb4b1d2a36bac865102b62790f18059a5c1 100644 (file)
@@ -142,6 +142,7 @@ struct ports_device {
         * notification
         */
        struct work_struct control_work;
+       struct work_struct config_work;
 
        struct list_head ports;
 
@@ -1832,10 +1833,21 @@ static void config_intr(struct virtio_device *vdev)
 
        portdev = vdev->priv;
 
+       if (!use_multiport(portdev))
+               schedule_work(&portdev->config_work);
+}
+
+static void config_work_handler(struct work_struct *work)
+{
+       struct ports_device *portdev;
+
+       portdev = container_of(work, struct ports_device, control_work);
        if (!use_multiport(portdev)) {
+               struct virtio_device *vdev;
                struct port *port;
                u16 rows, cols;
 
+               vdev = portdev->vdev;
                virtio_cread(vdev, struct virtio_console_config, cols, &cols);
                virtio_cread(vdev, struct virtio_console_config, rows, &rows);
 
@@ -2024,12 +2036,14 @@ static int virtcons_probe(struct virtio_device *vdev)
        spin_lock_init(&portdev->ports_lock);
        INIT_LIST_HEAD(&portdev->ports);
 
+       INIT_WORK(&portdev->config_work, &config_work_handler);
+       INIT_WORK(&portdev->control_work, &control_work_handler);
+
        if (multiport) {
                unsigned int nr_added_bufs;
 
                spin_lock_init(&portdev->c_ivq_lock);
                spin_lock_init(&portdev->c_ovq_lock);
-               INIT_WORK(&portdev->control_work, &control_work_handler);
 
                nr_added_bufs = fill_queue(portdev->c_ivq,
                                           &portdev->c_ivq_lock);
@@ -2097,6 +2111,8 @@ static void virtcons_remove(struct virtio_device *vdev)
        /* Finish up work that's lined up */
        if (use_multiport(portdev))
                cancel_work_sync(&portdev->control_work);
+       else
+               cancel_work_sync(&portdev->config_work);
 
        list_for_each_entry_safe(port, port2, &portdev->ports, list)
                unplug_port(port);
@@ -2148,6 +2164,7 @@ static int virtcons_freeze(struct virtio_device *vdev)
 
        virtqueue_disable_cb(portdev->c_ivq);
        cancel_work_sync(&portdev->control_work);
+       cancel_work_sync(&portdev->config_work);
        /*
         * Once more: if control_work_handler() was running, it would
         * enable the cb as the last step.
index 06be844a5848a3554d9d471a3d5c5f993c4599fc..4854699dd3fa451463b31df568cbf552721ec1b5 100644 (file)
@@ -243,34 +243,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        return 0;
 }
 
-int clk_divider_save_context(struct clk_hw *hw)
-{
-       struct clk_divider *divider = to_clk_divider(hw);
-       u32 val;
-
-       val = ti_clk_ll_ops->clk_readl(divider->reg) >> divider->shift;
-       divider->context = val & div_mask(divider);
-
-       return 0;
-}
-
-void clk_divider_restore_context(struct clk_hw *hw)
-{
-       struct clk_divider *divider = to_clk_divider(hw);
-       u32 val;
-
-       val = ti_clk_ll_ops->clk_readl(divider->reg);
-       val &= ~(div_mask(divider) << divider->shift);
-       val |= divider->context << divider->shift;
-       ti_clk_ll_ops->clk_writel(val, divider->reg);
-}
-
 const struct clk_ops clk_divider_ops = {
        .recalc_rate = clk_divider_recalc_rate,
        .round_rate = clk_divider_round_rate,
        .set_rate = clk_divider_set_rate,
-       .save_context = clk_divider_save_context,
-       .restore_context = clk_divider_restore_context,
 };
 EXPORT_SYMBOL_GPL(clk_divider_ops);
 
index 225ebfdc7989ac75bc03b5d23ed5fba3c0301bcd..797bab97cea651eee086ecc911ff30955eac742f 100644 (file)
@@ -104,7 +104,6 @@ const struct clk_ops clk_gate_ops = {
        .enable = clk_gate_enable,
        .disable = clk_gate_disable,
        .is_enabled = clk_gate_is_enabled,
-       .restore_context = clk_dflt_restore_context,
 };
 EXPORT_SYMBOL_GPL(clk_gate_ops);
 
@@ -129,7 +128,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
        struct clk_init_data init;
 
        if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
-               if (bit_idx > 16) {
+               if (bit_idx > 15) {
                        pr_err("gate bit exceeds LOWORD field\n");
                        return ERR_PTR(-EINVAL);
                }
index 0996a3a398550f36acdfc2320d70e64075e2afe5..a9dd21aff6bbd73e1ba478e27f8859ff6f70083e 100644 (file)
@@ -257,7 +257,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
        mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK;
        cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
        cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
-       if (rcg->mnd_width && f->n)
+       if (rcg->mnd_width && f->n && (f->m != f->n))
                cfg |= CFG_MODE_DUAL_EDGE;
        ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask,
                        cfg);
index 9e232644f07edfac55e29bb2f8d69185ea214357..ea4db844aee339ff4b934414f823198feffa435a 100644 (file)
@@ -62,7 +62,7 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw,
                p = FACTOR_GET(config->pshift, config->pwidth, reg);
 
        /* Calculate the rate */
-       rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
+       rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1);
 
        return rate;
 }
index 02e1a43ebac7d99f3808307b416c5572ee0539b5..d2d0efa39379985f284387d87bba2159627480b1 100644 (file)
@@ -15,6 +15,7 @@ struct clk_factors_config {
        u8 mwidth;
        u8 pshift;
        u8 pwidth;
+       u8 n_start;
 };
 
 struct clk_factors {
index abb6c5ac8a10297505a8a7f1cb1cb0d5f8eccf16..06a14b808683441248d885778f85238b6ef76159 100644 (file)
@@ -407,6 +407,7 @@ static struct clk_factors_config sun6i_a31_pll1_config = {
        .kwidth = 2,
        .mshift = 0,
        .mwidth = 2,
+       .n_start = 1,
 };
 
 static struct clk_factors_config sun4i_pll5_config = {
index c0a7d77235105472d225d6f528c81e675866fd3c..a90af1780cf2a437f391490b50e4d8913ef3cd70 100644 (file)
@@ -266,7 +266,7 @@ void __init tegra_add_of_provider(struct device_node *np)
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
        rst_ctlr.of_node = np;
-       rst_ctlr.nr_resets = clk_num * 32;
+       rst_ctlr.nr_resets = periph_banks * 32;
        reset_controller_register(&rst_ctlr);
 }
 
index 7886f02f5e0a83f8d78e1a3c84396770f234ef03..f2759a5fced691c07177a785e2ba4f8ad2713d7e 100644 (file)
@@ -23,6 +23,7 @@
 #define DRA7_DPLL_EVE_GCLK_NOMFREQ                     400000000
 
 #define DRA7_ATL_DEFFREQ                               5644800
+#define DRA7_DPLL_USB_DEFFREQ                          960000000
 
 static struct ti_dt_clk dra7xx_clks[] = {
        DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"),
@@ -227,7 +228,7 @@ static struct ti_dt_clk dra7xx_clks[] = {
        DT_CLK(NULL, "mcasp6_aux_gfclk_mux", "mcasp6_aux_gfclk_mux"),
        DT_CLK(NULL, "mcasp7_ahclkx_mux", "mcasp7_ahclkx_mux"),
        DT_CLK(NULL, "mcasp7_aux_gfclk_mux", "mcasp7_aux_gfclk_mux"),
-       DT_CLK(NULL, "mcasp8_ahclk_mux", "mcasp8_ahclk_mux"),
+       DT_CLK(NULL, "mcasp8_ahclkx_mux", "mcasp8_ahclkx_mux"),
        DT_CLK(NULL, "mcasp8_aux_gfclk_mux", "mcasp8_aux_gfclk_mux"),
        DT_CLK(NULL, "mmc1_fclk_mux", "mmc1_fclk_mux"),
        DT_CLK(NULL, "mmc1_fclk_div", "mmc1_fclk_div"),
@@ -293,17 +294,21 @@ static struct ti_dt_clk dra7xx_clks[] = {
        DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"),
        DT_CLK("omap_wdt", "ick", "dummy_ck"),
        DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
-       DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("4ae18000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48032000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48034000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48036000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("4803e000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48086000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48088000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("48820000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("48822000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("48824000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("48826000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48828000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("4882a000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("4882c000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("4882e000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("4843e200.ehrpwm", "tbclk", "ehrpwm0_tbclk"),
        DT_CLK("48440200.ehrpwm", "tbclk", "ehrpwm1_tbclk"),
        DT_CLK("48442200.ehrpwm", "tbclk", "ehrpwm2_tbclk"),
@@ -388,5 +393,15 @@ int __init dra7xx_dt_clk_init(void)
        if (rc)
                pr_err("%s: failed to set atl_clkin1_ck\n", __func__);
 
+       dpll_ck = clk_get_sys(NULL, "dpll_usb_ck");
+       rc = clk_set_rate(dpll_ck, DRA7_DPLL_USB_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
+       dpll_ck = clk_get_sys(NULL, "dpll_usb_m2_ck");
+       rc = clk_set_rate(dpll_ck, DRA7_DPLL_USB_DEFFREQ/2);
+       if (rc)
+               pr_err("%s: failed to set USB_DPLL M2 OUT\n", __func__);
+
        return rc;
 }
index e6aa10db7bba1f78116ff6cd0b02a49b65bea857..dda020cde614adc4a1f0187f2b054590fc477ee2 100644 (file)
@@ -240,10 +240,34 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        return 0;
 }
 
+static int clk_divider_save_context(struct clk_hw *hw)
+{
+       struct clk_divider *divider = to_clk_divider(hw);
+       u32 val;
+
+       val = ti_clk_ll_ops->clk_readl(divider->reg) >> divider->shift;
+       divider->context = val & div_mask(divider);
+
+       return 0;
+}
+
+static void clk_divider_restore_context(struct clk_hw *hw)
+{
+       struct clk_divider *divider = to_clk_divider(hw);
+       u32 val;
+
+       val = ti_clk_ll_ops->clk_readl(divider->reg);
+       val &= ~(div_mask(divider) << divider->shift);
+       val |= divider->context << divider->shift;
+       ti_clk_ll_ops->clk_writel(val, divider->reg);
+}
+
 const struct clk_ops ti_clk_divider_ops = {
        .recalc_rate = ti_clk_divider_recalc_rate,
        .round_rate = ti_clk_divider_round_rate,
        .set_rate = ti_clk_divider_set_rate,
+       .save_context = clk_divider_save_context,
+       .restore_context = clk_divider_restore_context,
 };
 
 static struct clk *_register_divider(struct device *dev, const char *name,
index f1a7d9bea4796da4c1bc83230eb446cdcf057ffa..c49da028a2504adee5de61ac452f46f6c77c1d16 100644 (file)
@@ -306,6 +306,8 @@ static void __init of_ti_dpll_setup(struct device_node *node,
        if (of_property_read_bool(node, "ti,lock"))
                dpll_mode |= 1 << DPLL_LOCKED;
 
+       omap2_init_dpll_clkdm(dd, node);
+
        if (dpll_mode)
                dd->modes = dpll_mode;
 
index b326d2797feb23c0ed84fe52be5b9905102f0234..ab2f9ac963c6d70738c442dfd1e41f103d70220e 100644 (file)
@@ -33,6 +33,7 @@ static const struct clk_ops omap_gate_clkdm_clk_ops = {
        .init           = &omap2_init_clk_clkdm,
        .enable         = &omap2_clkops_enable_clkdm,
        .disable        = &omap2_clkops_disable_clkdm,
+       .restore_context = clk_dflt_restore_context,
 };
 
 static const struct clk_ops omap_gate_clk_ops = {
@@ -40,6 +41,7 @@ static const struct clk_ops omap_gate_clk_ops = {
        .enable         = &omap2_dflt_clk_enable,
        .disable        = &omap2_dflt_clk_disable,
        .is_enabled     = &omap2_dflt_clk_is_enabled,
+       .restore_context = clk_dflt_restore_context,
 };
 
 static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = {
@@ -47,6 +49,7 @@ static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = {
        .enable         = &omap36xx_gate_clk_enable_with_hsdiv_restore,
        .disable        = &omap2_dflt_clk_disable,
        .is_enabled     = &omap2_dflt_clk_is_enabled,
+       .restore_context = clk_dflt_restore_context,
 };
 
 /**
index 09dd0173ea0ae616dc4395f2b76724740310522c..5f52f3f626445694bc37e4767f333988ba60a2af 100644 (file)
@@ -300,6 +300,7 @@ static void __init zynq_clk_setup(struct device_node *np)
        clks[cpu_2x] = clk_register_gate(NULL, clk_output_name[cpu_2x],
                        "cpu_2x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL,
                        26, 0, &armclk_lock);
+       clk_prepare_enable(clks[cpu_2x]);
 
        clk = clk_register_fixed_factor(NULL, "cpu_1x_div", "cpu_div", 0, 1,
                        4 + 2 * tmp);
index 1a6205b7bed35e72a809cd883934ae283ef3ce28..35b0161006737183d7e2c4bcab4e0bb5cfb99c2b 100644 (file)
@@ -225,12 +225,12 @@ static int __init efm32_clockevent_init(struct device_node *np)
        clock_event_ddata.base = base;
        clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ);
 
-       setup_irq(irq, &efm32_clock_event_irq);
-
        clockevents_config_and_register(&clock_event_ddata.evtdev,
                                        DIV_ROUND_CLOSEST(rate, 1024),
                                        0xf, 0xffff);
 
+       setup_irq(irq, &efm32_clock_event_irq);
+
        return 0;
 
 err_get_irq:
index deebcd6469fced2c9b131447b75085c887068b6d..4f0f3610371ac0e122b48dae58f5c72303e0ebb0 100644 (file)
@@ -172,10 +172,6 @@ static void __init sun5i_timer_init(struct device_node *node)
 
        ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
 
-       ret = setup_irq(irq, &sun5i_timer_irq);
-       if (ret)
-               pr_warn("failed to setup irq %d\n", irq);
-
        /* Enable timer0 interrupt */
        val = readl(timer_base + TIMER_IRQ_EN_REG);
        writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
@@ -185,6 +181,10 @@ static void __init sun5i_timer_init(struct device_node *node)
 
        clockevents_config_and_register(&sun5i_clockevent, rate,
                                        TIMER_SYNC_TICKS, 0xffffffff);
+
+       ret = setup_irq(irq, &sun5i_timer_irq);
+       if (ret)
+               pr_warn("failed to setup irq %d\n", irq);
 }
 CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
                       sun5i_timer_init);
index c0c6f4a4eccf540aa43a1508cfd10a304674bdea..773bcde893c0472b3ecf8f2e9e3a5356d532a402 100644 (file)
@@ -60,7 +60,7 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
                goto out;
        }
 
-       freq_table = kzalloc(sizeof(*freq_table) * (max_opps + 1), GFP_KERNEL);
+       freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC);
        if (!freq_table) {
                ret = -ENOMEM;
                goto out;
index a55e68f2cfc8bfad02a85957c9d9ddc55823c6fe..e3d2052e75522e73073a9232785c64dacfc752b8 100644 (file)
@@ -252,9 +252,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
        if (!dev->registered)
                return -EINVAL;
 
-       if (!dev->state_count)
-               dev->state_count = drv->state_count;
-
        ret = cpuidle_add_device_sysfs(dev);
        if (ret)
                return ret;
index e918b6d0caf7558025578be747b920003adb2698..dcaae4c8bc086940d22500d3e7bf9b9595adeaaf 100644 (file)
@@ -398,7 +398,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
        /* state statistics */
-       for (i = 0; i < device->state_count; i++) {
+       for (i = 0; i < drv->state_count; i++) {
                kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
                if (!kobj)
                        goto error_state;
@@ -430,9 +430,10 @@ error_state:
  */
 static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
 {
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
        int i;
 
-       for (i = 0; i < device->state_count; i++)
+       for (i = 0; i < drv->state_count; i++)
                cpuidle_free_state_kobj(device, i);
 }
 
index 9a53fb8ceff9b018073e545e0c6f83b30ade4c23..662119175fcf6a38eb4b23aa9094fb8f3410cd8d 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_CRYPTO_DEV_NIAGARA2) += n2_crypto.o
 n2_crypto-y := n2_core.o n2_asm.o
 obj-$(CONFIG_CRYPTO_DEV_NX) += nx/
 obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
+obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes-gcm.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_DES) += omap-des.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
diff --git a/drivers/crypto/omap-aes-gcm.c b/drivers/crypto/omap-aes-gcm.c
new file mode 100644 (file)
index 0000000..9c68ff0
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for OMAP AES GCM HW acceleration.
+ *
+ * Copyright (c) 2015 Texas Instruments Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/omap-dma.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/crypto.h>
+#include <linux/interrupt.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/aes.h>
+#include "omap-aes.h"
+
+static int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd,
+                                    struct aead_request *req);
+
+static void omap_aes_gcm_finish_req(struct omap_aes_dev *dd, int ret)
+{
+       struct aead_request *req = dd->aead_req;
+
+       dd->flags &= ~FLAGS_BUSY;
+       dd->in_sg = NULL;
+       dd->out_sg = NULL;
+
+       req->base.complete(&req->base, ret);
+}
+
+static void omap_aes_gcm_done_task(struct omap_aes_dev *dd)
+{
+       void *buf;
+       u8 *tag;
+       int pages, alen, clen, i, ret = 0, nsg;
+
+       alen = ALIGN(dd->assoc_len, AES_BLOCK_SIZE);
+       clen = ALIGN(dd->total, AES_BLOCK_SIZE);
+
+       nsg = 1 + !!(dd->assoc_len && dd->total);
+
+       if (!dd->pio_only) {
+               dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len,
+                                      DMA_FROM_DEVICE);
+               dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
+               dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
+                            DMA_FROM_DEVICE);
+               omap_aes_crypt_dma_stop(dd);
+       }
+
+       if (dd->sgs_copied & AES_OUT_DATA_COPIED) {
+               buf = sg_virt(&dd->out_sgl);
+               scatterwalk_map_and_copy(buf, dd->orig_out, 0, dd->total, 1);
+
+               pages = get_order(clen);
+               free_pages((unsigned long)buf, pages);
+       }
+
+       if (dd->flags & FLAGS_ENCRYPT)
+               scatterwalk_map_and_copy(dd->ctx->auth_tag, dd->aead_req->dst,
+                                        dd->total, dd->authsize, 1);
+
+       if (dd->sgs_copied & AES_ASSOC_DATA_COPIED) {
+               buf = sg_virt(&dd->in_sgl[0]);
+               pages = get_order(alen);
+               free_pages((unsigned long)buf, pages);
+       }
+       if (dd->sgs_copied & AES_IN_DATA_COPIED) {
+               buf = sg_virt(&dd->in_sgl[nsg - 1]);
+               pages = get_order(clen);
+               free_pages((unsigned long)buf, pages);
+       }
+
+       if (!(dd->flags & FLAGS_ENCRYPT)) {
+               tag = (u8 *)dd->ctx->auth_tag;
+               for (i = 0; i < dd->authsize; i++) {
+                       if (tag[i]) {
+                               dev_err(dd->dev, "GCM decryption: Tag Message is wrong\n");
+                               ret = -EBADMSG;
+                       }
+               }
+       }
+
+       omap_aes_gcm_finish_req(dd, ret);
+       omap_aes_gcm_handle_queue(dd, NULL);
+}
+
+static int omap_aes_gcm_copy_buffers(struct omap_aes_dev *dd,
+                                    struct aead_request *req)
+{
+       void *buf_in;
+       int pages, alen, clen, cryptlen, nsg;
+       struct crypto_aead *aead = crypto_aead_reqtfm(req);
+       unsigned int authlen = crypto_aead_authsize(aead);
+       u32 dec = !(dd->flags & FLAGS_ENCRYPT);
+
+       alen = ALIGN(req->assoclen, AES_BLOCK_SIZE);
+       cryptlen = req->cryptlen - (dec * authlen);
+       clen = ALIGN(cryptlen, AES_BLOCK_SIZE);
+
+       dd->sgs_copied = 0;
+
+       nsg = 1 + !!(req->assoclen && req->cryptlen);
+
+       sg_init_table(dd->in_sgl, nsg);
+       if (req->assoclen) {
+               if (omap_aes_check_aligned(req->assoc, req->assoclen)) {
+                       dd->sgs_copied |= AES_ASSOC_DATA_COPIED;
+                       pages = get_order(alen);
+                       buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
+                       if (!buf_in) {
+                               pr_err("Couldn't allocate for unaligncases.\n");
+                               return -1;
+                       }
+
+                       scatterwalk_map_and_copy(buf_in, req->assoc, 0,
+                                                req->assoclen, 0);
+                       memset(buf_in + req->assoclen, 0, alen - req->assoclen);
+               } else {
+                       buf_in = sg_virt(req->assoc);
+               }
+               sg_set_buf(dd->in_sgl, buf_in, alen);
+       }
+
+       if (req->cryptlen) {
+               if (omap_aes_check_aligned(req->src, req->cryptlen)) {
+                       dd->sgs_copied |= AES_IN_DATA_COPIED;
+                       pages = get_order(clen);
+                       buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
+                       if (!buf_in) {
+                               pr_err("Couldn't allocate for unaligncases.\n");
+                               return -1;
+                       }
+
+                       memset(buf_in + cryptlen, 0, clen - cryptlen);
+                       scatterwalk_map_and_copy(buf_in, req->src, 0, cryptlen,
+                                                0);
+               } else {
+                       buf_in = sg_virt(req->src);
+               }
+               sg_set_buf(&dd->in_sgl[nsg - 1], buf_in, clen);
+       }
+
+       dd->in_sg = dd->in_sgl;
+       dd->total = cryptlen;
+       dd->assoc_len = req->assoclen;
+       dd->authsize = authlen;
+
+       if (omap_aes_check_aligned(req->dst, cryptlen)) {
+               pages = get_order(clen);
+
+               buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
+
+               if (!buf_in) {
+                       pr_err("Couldn't allocate for unaligned cases.\n");
+                       return -1;
+               }
+
+               sg_init_one(&dd->out_sgl, buf_in, clen);
+               dd->out_sg = &dd->out_sgl;
+               dd->orig_out = req->dst;
+               dd->sgs_copied |= AES_OUT_DATA_COPIED;
+       } else {
+               dd->out_sg = req->dst;
+       }
+
+       dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, alen + clen);
+       dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, clen);
+
+       return 0;
+}
+
+static void tcrypt_complete(struct crypto_async_request *req, int err)
+{
+       struct tcrypt_result *res = req->data;
+
+       if (err == -EINPROGRESS)
+               return;
+
+       res->err = err;
+       complete(&res->completion);
+}
+
+static int do_encrypt_iv(struct aead_request *req, u32 *tag)
+{
+       struct scatterlist iv_sg;
+       struct ablkcipher_request *ablk_req;
+       struct crypto_ablkcipher *tfm;
+       struct tcrypt_result result;
+       struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
+       int ret = 0;
+
+       tfm = crypto_alloc_ablkcipher("ctr(aes)", 0, 0);
+       ablk_req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+       if (!ablk_req) {
+               pr_err("skcipher: Failed to allocate request\n");
+               return -1;
+       }
+
+       init_completion(&result.completion);
+
+       sg_init_one(&iv_sg, tag, AES_BLOCK_SIZE);
+       ablkcipher_request_set_callback(ablk_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                       tcrypt_complete, &result);
+       ret = crypto_ablkcipher_setkey(tfm, (u8 *)ctx->key, ctx->keylen);
+       ablkcipher_request_set_crypt(ablk_req, &iv_sg, &iv_sg, AES_BLOCK_SIZE,
+                                    req->iv);
+       ret = crypto_ablkcipher_encrypt(ablk_req);
+       switch (ret) {
+       case 0:
+               break;
+       case -EINPROGRESS:
+       case -EBUSY:
+               ret = wait_for_completion_interruptible(&result.completion);
+               if (!ret) {
+                       ret = result.err;
+                       if (!ret) {
+                               reinit_completion(&result.completion);
+                               break;
+                       }
+               }
+               /* fall through */
+       default:
+               pr_err("Encryptio of IV failed for GCM mode");
+               break;
+       }
+
+       ablkcipher_request_free(ablk_req);
+       crypto_free_ablkcipher(tfm);
+       return ret;
+}
+
+void omap_aes_gcm_dma_out_callback(void *data)
+{
+       struct omap_aes_dev *dd = data;
+       int i, val;
+       u32 *auth_tag, tag[4];
+
+       if (!(dd->flags & FLAGS_ENCRYPT))
+               scatterwalk_map_and_copy(tag, dd->aead_req->src, dd->total,
+                                        dd->authsize, 0);
+
+       auth_tag = dd->ctx->auth_tag;
+       for (i = 0; i < 4; i++) {
+               val = omap_aes_read(dd, AES_REG_TAG_N(dd, i));
+               auth_tag[i] = val ^ auth_tag[i];
+               if (!(dd->flags & FLAGS_ENCRYPT))
+                       auth_tag[i] = auth_tag[i] ^ tag[i];
+       }
+
+       /* dma_lch_out - completed */
+       omap_aes_gcm_done_task(dd);
+}
+
+static int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd,
+                                    struct aead_request *req)
+{
+       struct omap_aes_ctx *ctx;
+       struct crypto_async_request *async_req, *backlog;
+       struct omap_aes_reqctx *rctx;
+       unsigned long flags;
+       int err, ret = 0;
+
+       spin_lock_irqsave(&dd->lock, flags);
+       if (req)
+               ret = crypto_enqueue_request(&dd->aead_queue, &req->base);
+       if (dd->flags & FLAGS_BUSY) {
+               spin_unlock_irqrestore(&dd->lock, flags);
+               return ret;
+       }
+       backlog = crypto_get_backlog(&dd->aead_queue);
+       async_req = crypto_dequeue_request(&dd->aead_queue);
+       if (async_req)
+               dd->flags |= FLAGS_BUSY;
+       spin_unlock_irqrestore(&dd->lock, flags);
+
+       if (!async_req)
+               return ret;
+
+       if (backlog)
+               backlog->complete(backlog, -EINPROGRESS);
+
+       req = aead_request_cast(async_req);
+
+       ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
+       rctx = aead_request_ctx(req);
+
+       dd->ctx = ctx;
+       ctx->dd = dd;
+       dd->aead_req = req;
+
+       rctx->mode &= FLAGS_MODE_MASK;
+       dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
+
+       err = omap_aes_gcm_copy_buffers(dd, req);
+       if (err)
+               return err;
+
+       err = omap_aes_write_ctrl(dd);
+       if (!err)
+               err = omap_aes_crypt_dma_start(dd);
+
+       if (err) {
+               omap_aes_gcm_finish_req(dd, err);
+               omap_aes_gcm_handle_queue(dd, NULL);
+       }
+
+       return ret;
+}
+
+static int omap_aes_gcm_crypt(struct aead_request *req, unsigned long mode)
+{
+       struct omap_aes_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
+       struct omap_aes_reqctx *rctx = aead_request_ctx(req);
+       struct crypto_aead *aead = crypto_aead_reqtfm(req);
+       unsigned int authlen = crypto_aead_authsize(aead);
+       struct omap_aes_dev *dd;
+       __be32 counter = cpu_to_be32(1);
+       int err;
+
+       memset(ctx->auth_tag, 0, sizeof(ctx->auth_tag));
+       memcpy(req->iv + 12, &counter, 4);
+
+       /* Create E(K, IV) */
+       err = do_encrypt_iv(req, ctx->auth_tag);
+       if (err)
+               return err;
+
+       if (req->assoclen + req->cryptlen == 0) {
+               scatterwalk_map_and_copy(ctx->auth_tag, req->dst, 0, authlen,
+                                        1);
+               return 0;
+       }
+
+       dd = omap_aes_find_dev(ctx);
+       if (!dd)
+               return -ENODEV;
+       rctx->mode = mode;
+
+       return omap_aes_gcm_handle_queue(dd, req);
+}
+
+int omap_aes_gcm_encrypt(struct aead_request *req)
+{
+       return omap_aes_gcm_crypt(req, FLAGS_ENCRYPT | FLAGS_GCM);
+}
+
+int omap_aes_gcm_decrypt(struct aead_request *req)
+{
+       return omap_aes_gcm_crypt(req, FLAGS_GCM);
+}
+
+int omap_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
+                       unsigned int keylen)
+{
+       struct omap_aes_ctx *ctx = crypto_aead_ctx(tfm);
+
+       if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
+           keylen != AES_KEYSIZE_256)
+               return -EINVAL;
+
+       memcpy(ctx->key, key, keylen);
+       ctx->keylen = keylen;
+
+       return 0;
+}
index dde41f1df6080a0e067a35d5dad2302c0ba6eb98..85bf869c4ee3caa2e317da8944f19a4f85b0f22d 100644 (file)
 #include <linux/interrupt.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/aes.h>
-
-#define DST_MAXBURST                   4
-#define DMA_MIN                                (DST_MAXBURST * sizeof(u32))
-
-#define _calc_walked(inout) (dd->inout##_walk.offset - dd->inout##_sg->offset)
-
-/* OMAP TRM gives bitfields as start:end, where start is the higher bit
-   number. For example 7:0 */
-#define FLD_MASK(start, end)   (((1 << ((start) - (end) + 1)) - 1) << (end))
-#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
-
-#define AES_REG_KEY(dd, x)             ((dd)->pdata->key_ofs - \
-                                               ((x ^ 0x01) * 0x04))
-#define AES_REG_IV(dd, x)              ((dd)->pdata->iv_ofs + ((x) * 0x04))
-
-#define AES_REG_CTRL(dd)               ((dd)->pdata->ctrl_ofs)
-#define AES_REG_CTRL_CTR_WIDTH_MASK    (3 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_32              (0 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_64              (1 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_96              (2 << 7)
-#define AES_REG_CTRL_CTR_WIDTH_128             (3 << 7)
-#define AES_REG_CTRL_CTR               (1 << 6)
-#define AES_REG_CTRL_CBC               (1 << 5)
-#define AES_REG_CTRL_KEY_SIZE          (3 << 3)
-#define AES_REG_CTRL_DIRECTION         (1 << 2)
-#define AES_REG_CTRL_INPUT_READY       (1 << 1)
-#define AES_REG_CTRL_OUTPUT_READY      (1 << 0)
-
-#define AES_REG_DATA_N(dd, x)          ((dd)->pdata->data_ofs + ((x) * 0x04))
-
-#define AES_REG_REV(dd)                        ((dd)->pdata->rev_ofs)
-
-#define AES_REG_MASK(dd)               ((dd)->pdata->mask_ofs)
-#define AES_REG_MASK_SIDLE             (1 << 6)
-#define AES_REG_MASK_START             (1 << 5)
-#define AES_REG_MASK_DMA_OUT_EN                (1 << 3)
-#define AES_REG_MASK_DMA_IN_EN         (1 << 2)
-#define AES_REG_MASK_SOFTRESET         (1 << 1)
-#define AES_REG_AUTOIDLE               (1 << 0)
-
-#define AES_REG_LENGTH_N(x)            (0x54 + ((x) * 0x04))
-
-#define AES_REG_IRQ_STATUS(dd)         ((dd)->pdata->irq_status_ofs)
-#define AES_REG_IRQ_ENABLE(dd)         ((dd)->pdata->irq_enable_ofs)
-#define AES_REG_IRQ_DATA_IN            BIT(1)
-#define AES_REG_IRQ_DATA_OUT           BIT(2)
-#define DEFAULT_TIMEOUT                (5*HZ)
-
-#define FLAGS_MODE_MASK                0x000f
-#define FLAGS_ENCRYPT          BIT(0)
-#define FLAGS_CBC              BIT(1)
-#define FLAGS_GIV              BIT(2)
-#define FLAGS_CTR              BIT(3)
-
-#define FLAGS_INIT             BIT(4)
-#define FLAGS_FAST             BIT(5)
-#define FLAGS_BUSY             BIT(6)
-
-#define AES_BLOCK_WORDS                (AES_BLOCK_SIZE >> 2)
-
-struct omap_aes_ctx {
-       struct omap_aes_dev *dd;
-
-       int             keylen;
-       u32             key[AES_KEYSIZE_256 / sizeof(u32)];
-       unsigned long   flags;
-};
-
-struct omap_aes_reqctx {
-       unsigned long mode;
-};
-
-#define OMAP_AES_QUEUE_LENGTH  1
-#define OMAP_AES_CACHE_SIZE    0
-
-struct omap_aes_algs_info {
-       struct crypto_alg       *algs_list;
-       unsigned int            size;
-       unsigned int            registered;
-};
-
-struct omap_aes_pdata {
-       struct omap_aes_algs_info       *algs_info;
-       unsigned int    algs_info_size;
-
-       void            (*trigger)(struct omap_aes_dev *dd, int length);
-
-       u32             key_ofs;
-       u32             iv_ofs;
-       u32             ctrl_ofs;
-       u32             data_ofs;
-       u32             rev_ofs;
-       u32             mask_ofs;
-       u32             irq_enable_ofs;
-       u32             irq_status_ofs;
-
-       u32             dma_enable_in;
-       u32             dma_enable_out;
-       u32             dma_start;
-
-       u32             major_mask;
-       u32             major_shift;
-       u32             minor_mask;
-       u32             minor_shift;
-};
-
-struct omap_aes_dev {
-       struct list_head        list;
-       unsigned long           phys_base;
-       void __iomem            *io_base;
-       struct omap_aes_ctx     *ctx;
-       struct device           *dev;
-       unsigned long           flags;
-       int                     err;
-
-       spinlock_t              lock;
-       struct crypto_queue     queue;
-
-       struct tasklet_struct   done_task;
-       struct tasklet_struct   queue_task;
-
-       struct ablkcipher_request       *req;
-
-       /*
-        * total is used by PIO mode for book keeping so introduce
-        * variable total_save as need it to calc page_order
-        */
-       size_t                          total;
-       size_t                          total_save;
-
-       struct scatterlist              *in_sg;
-       struct scatterlist              *out_sg;
-
-       /* Buffers for copying for unaligned cases */
-       struct scatterlist              in_sgl;
-       struct scatterlist              out_sgl;
-       struct scatterlist              *orig_out;
-       int                             sgs_copied;
-
-       struct scatter_walk             in_walk;
-       struct scatter_walk             out_walk;
-       int                     dma_in;
-       struct dma_chan         *dma_lch_in;
-       int                     dma_out;
-       struct dma_chan         *dma_lch_out;
-       int                     in_sg_len;
-       int                     out_sg_len;
-       int                     pio_only;
-       const struct omap_aes_pdata     *pdata;
-};
+#include "omap-aes.h"
 
 /* keep registered devices data here */
 static LIST_HEAD(dev_list);
@@ -201,7 +52,7 @@ static DEFINE_SPINLOCK(list_lock);
        _read_ret;                                              \
 })
 #else
-static inline u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset)
+inline u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset)
 {
        return __raw_readl(dd->io_base + offset);
 }
@@ -215,7 +66,7 @@ static inline u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset)
                __raw_writel(value, dd->io_base + offset);              \
        } while (0)
 #else
-static inline void omap_aes_write(struct omap_aes_dev *dd, u32 offset,
+inline void omap_aes_write(struct omap_aes_dev *dd, u32 offset,
                                  u32 value)
 {
        __raw_writel(value, dd->io_base + offset);
@@ -250,11 +101,11 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
        return 0;
 }
 
-static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+int omap_aes_write_ctrl(struct omap_aes_dev *dd)
 {
        unsigned int key32;
        int i, err;
-       u32 val, mask = 0;
+       u32 val;
 
        err = omap_aes_hw_init(dd);
        if (err)
@@ -262,7 +113,11 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
 
        key32 = dd->ctx->keylen / sizeof(u32);
 
-       /* it seems a key should always be set even if it has not changed */
+       /* RESET the key as previous HASH keys should not get affected*/
+       if (dd->flags & FLAGS_GCM)
+               for (i = 0; i < 0x40; i = i + 4)
+                       omap_aes_write(dd, i, 0x0);
+
        for (i = 0; i < key32; i++) {
                omap_aes_write(dd, AES_REG_KEY(dd, i),
                        __le32_to_cpu(dd->ctx->key[i]));
@@ -271,20 +126,24 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
        if ((dd->flags & (FLAGS_CBC | FLAGS_CTR)) && dd->req->info)
                omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4);
 
+       if ((dd->flags & (FLAGS_GCM)) && dd->aead_req->iv)
+               omap_aes_write_n(dd, AES_REG_IV(dd, 0),
+                                (u32 *)dd->aead_req->iv, 4);
+
        val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
        if (dd->flags & FLAGS_CBC)
                val |= AES_REG_CTRL_CBC;
-       if (dd->flags & FLAGS_CTR) {
+
+       if (dd->flags & (FLAGS_CTR | FLAGS_GCM))
                val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_128;
-               mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK;
-       }
+
+       if (dd->flags & FLAGS_GCM)
+               val |= AES_REG_CTRL_GCM;
+
        if (dd->flags & FLAGS_ENCRYPT)
                val |= AES_REG_CTRL_DIRECTION;
 
-       mask |= AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
-                       AES_REG_CTRL_KEY_SIZE;
-
-       omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask);
+       omap_aes_write(dd, AES_REG_CTRL(dd), val);
 
        return 0;
 }
@@ -311,6 +170,8 @@ static void omap_aes_dma_trigger_omap4(struct omap_aes_dev *dd, int length)
 {
        omap_aes_write(dd, AES_REG_LENGTH_N(0), length);
        omap_aes_write(dd, AES_REG_LENGTH_N(1), 0);
+       if (dd->flags & FLAGS_GCM)
+               omap_aes_write(dd, AES_REG_A_LEN, dd->assoc_len);
 
        omap_aes_dma_trigger_omap2(dd, length);
 }
@@ -325,22 +186,14 @@ static void omap_aes_dma_stop(struct omap_aes_dev *dd)
        omap_aes_write_mask(dd, AES_REG_MASK(dd), 0, mask);
 }
 
-static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
+struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
 {
-       struct omap_aes_dev *dd = NULL, *tmp;
+       struct omap_aes_dev *dd;
 
        spin_lock_bh(&list_lock);
-       if (!ctx->dd) {
-               list_for_each_entry(tmp, &dev_list, list) {
-                       /* FIXME: take fist available aes core */
-                       dd = tmp;
-                       break;
-               }
-               ctx->dd = dd;
-       } else {
-               /* already found before */
-               dd = ctx->dd;
-       }
+       dd = list_first_entry(&dev_list, struct omap_aes_dev, list);
+       list_move_tail(&dd->list, &dev_list);
+       ctx->dd = dd;
        spin_unlock_bh(&list_lock);
 
        return dd;
@@ -413,12 +266,10 @@ static void sg_copy_buf(void *buf, struct scatterlist *sg,
        scatterwalk_done(&walk, out, 0);
 }
 
-static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
+static int omap_aes_crypt_dma(struct omap_aes_dev *dd,
                struct scatterlist *in_sg, struct scatterlist *out_sg,
                int in_sg_len, int out_sg_len)
 {
-       struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
-       struct omap_aes_dev *dd = ctx->dd;
        struct dma_async_tx_descriptor *tx_in, *tx_out;
        struct dma_slave_config cfg;
        int ret;
@@ -479,7 +330,10 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
                return -EINVAL;
        }
 
-       tx_out->callback = omap_aes_dma_out_callback;
+       if (dd->flags & FLAGS_GCM)
+               tx_out->callback = omap_aes_gcm_dma_out_callback;
+       else
+               tx_out->callback = omap_aes_dma_out_callback;
        tx_out->callback_param = dd;
 
        dmaengine_submit(tx_in);
@@ -494,10 +348,8 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
        return 0;
 }
 
-static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
 {
-       struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
-                                       crypto_ablkcipher_reqtfm(dd->req));
        int err;
 
        pr_debug("total: %d\n", dd->total);
@@ -518,7 +370,7 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
                }
        }
 
-       err = omap_aes_crypt_dma(tfm, dd->in_sg, dd->out_sg, dd->in_sg_len,
+       err = omap_aes_crypt_dma(dd, dd->in_sg, dd->out_sg, dd->in_sg_len,
                                 dd->out_sg_len);
        if (err && !dd->pio_only) {
                dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
@@ -540,7 +392,7 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
        req->base.complete(&req->base, err);
 }
 
-static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
+int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
 {
        int err = 0;
 
@@ -554,24 +406,36 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
        return err;
 }
 
-static int omap_aes_check_aligned(struct scatterlist *sg)
+int omap_aes_check_aligned(struct scatterlist *sg, int total)
 {
+       int len = 0;
+
+       if (!IS_ALIGNED(total, AES_BLOCK_SIZE))
+               return -1;
+
        while (sg) {
                if (!IS_ALIGNED(sg->offset, 4))
                        return -1;
                if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE))
                        return -1;
+
+               len += sg->length;
                sg = sg_next(sg);
        }
+
+       if (len != total)
+               return -1;
+
        return 0;
 }
 
 static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
 {
        void *buf_in, *buf_out;
-       int pages;
+       int pages, total;
 
-       pages = get_order(dd->total);
+       total = ALIGN(dd->total, AES_BLOCK_SIZE);
+       pages = get_order(total);
 
        buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
        buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
@@ -585,12 +449,12 @@ static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
 
        sg_copy_buf(buf_in, dd->in_sg, 0, dd->total, 0);
 
-       sg_init_table(&dd->in_sgl, 1);
-       sg_set_buf(&dd->in_sgl, buf_in, dd->total);
-       dd->in_sg = &dd->in_sgl;
+       sg_init_table(dd->in_sgl, 1);
+       sg_set_buf(dd->in_sgl, buf_in, total);
+       dd->in_sg = dd->in_sgl;
 
        sg_init_table(&dd->out_sgl, 1);
-       sg_set_buf(&dd->out_sgl, buf_out, dd->total);
+       sg_set_buf(&dd->out_sgl, buf_out, total);
        dd->out_sg = &dd->out_sgl;
 
        return 0;
@@ -603,7 +467,7 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
        struct omap_aes_ctx *ctx;
        struct omap_aes_reqctx *rctx;
        unsigned long flags;
-       int err, ret = 0;
+       int err, ret = 0, len;
 
        spin_lock_irqsave(&dd->lock, flags);
        if (req)
@@ -633,8 +497,8 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
        dd->in_sg = req->src;
        dd->out_sg = req->dst;
 
-       if (omap_aes_check_aligned(dd->in_sg) ||
-           omap_aes_check_aligned(dd->out_sg)) {
+       if (omap_aes_check_aligned(dd->in_sg, dd->total) ||
+           omap_aes_check_aligned(dd->out_sg, dd->total)) {
                if (omap_aes_copy_sgs(dd))
                        pr_err("Failed to copy SGs for unaligned cases\n");
                dd->sgs_copied = 1;
@@ -642,8 +506,9 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
                dd->sgs_copied = 0;
        }
 
-       dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, dd->total);
-       dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, dd->total);
+       len = ALIGN(dd->total, AES_BLOCK_SIZE);
+       dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, len);
+       dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, len);
        BUG_ON(dd->in_sg_len < 0 || dd->out_sg_len < 0);
 
        rctx = ablkcipher_request_ctx(req);
@@ -655,6 +520,7 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
        ctx->dd = dd;
 
        err = omap_aes_write_ctrl(dd);
+
        if (!err)
                err = omap_aes_crypt_dma_start(dd);
        if (err) {
@@ -670,7 +536,7 @@ static void omap_aes_done_task(unsigned long data)
 {
        struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
        void *buf_in, *buf_out;
-       int pages;
+       int pages, len;
 
        pr_debug("enter done_task\n");
 
@@ -684,12 +550,13 @@ static void omap_aes_done_task(unsigned long data)
        }
 
        if (dd->sgs_copied) {
-               buf_in = sg_virt(&dd->in_sgl);
+               buf_in = sg_virt(dd->in_sgl);
                buf_out = sg_virt(&dd->out_sgl);
 
                sg_copy_buf(buf_out, dd->orig_out, 0, dd->total_save, 1);
 
-               pages = get_order(dd->total_save);
+               len = ALIGN(dd->total_save, AES_BLOCK_SIZE);
+               pages = get_order(len);
                free_pages((unsigned long)buf_in, pages);
                free_pages((unsigned long)buf_out, pages);
        }
@@ -718,11 +585,6 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
                  !!(mode & FLAGS_ENCRYPT),
                  !!(mode & FLAGS_CBC));
 
-       if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
-               pr_err("request size is not exact amount of AES blocks\n");
-               return -EINVAL;
-       }
-
        dd = omap_aes_find_dev(ctx);
        if (!dd)
                return -ENODEV;
@@ -786,21 +648,35 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm)
        struct omap_aes_dev *dd = NULL;
        int err;
 
-       /* Find AES device, currently picks the first device */
-       spin_lock_bh(&list_lock);
        list_for_each_entry(dd, &dev_list, list) {
-               break;
+               err = pm_runtime_get_sync(dd->dev);
+               if (err < 0) {
+                       dev_err(dd->dev, "%s: failed to get_sync(%d)\n",
+                               __func__, err);
+                       return err;
+               }
        }
-       spin_unlock_bh(&list_lock);
 
-       err = pm_runtime_get_sync(dd->dev);
-       if (err < 0) {
-               dev_err(dd->dev, "%s: failed to get_sync(%d)\n",
-                       __func__, err);
-               return err;
+       tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx);
+
+       return 0;
+}
+
+static int omap_aes_gcm_cra_init(struct crypto_tfm *tfm)
+{
+       struct omap_aes_dev *dd = NULL;
+       int err;
+
+       list_for_each_entry(dd, &dev_list, list) {
+               err = pm_runtime_get_sync(dd->dev);
+               if (err < 0) {
+                       dev_err(dd->dev, "%s: failed to get_sync(%d)\n",
+                               __func__, err);
+                       return err;
+               }
        }
 
-       tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx);
+       tfm->crt_aead.reqsize = sizeof(struct omap_aes_reqctx);
 
        return 0;
 }
@@ -809,14 +685,10 @@ static void omap_aes_cra_exit(struct crypto_tfm *tfm)
 {
        struct omap_aes_dev *dd = NULL;
 
-       /* Find AES device, currently picks the first device */
-       spin_lock_bh(&list_lock);
        list_for_each_entry(dd, &dev_list, list) {
-               break;
+               pm_runtime_put_sync(dd->dev);
        }
-       spin_unlock_bh(&list_lock);
 
-       pm_runtime_put_sync(dd->dev);
 }
 
 /* ********************** ALGS ************************************ */
@@ -831,7 +703,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
                                  CRYPTO_ALG_ASYNC,
        .cra_blocksize          = AES_BLOCK_SIZE,
        .cra_ctxsize            = sizeof(struct omap_aes_ctx),
-       .cra_alignmask          = 0,
+       .cra_alignmask          = 0xf,
        .cra_type               = &crypto_ablkcipher_type,
        .cra_module             = THIS_MODULE,
        .cra_init               = omap_aes_cra_init,
@@ -853,7 +725,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
                                  CRYPTO_ALG_ASYNC,
        .cra_blocksize          = AES_BLOCK_SIZE,
        .cra_ctxsize            = sizeof(struct omap_aes_ctx),
-       .cra_alignmask          = 0,
+       .cra_alignmask          = 0xf,
        .cra_type               = &crypto_ablkcipher_type,
        .cra_module             = THIS_MODULE,
        .cra_init               = omap_aes_cra_init,
@@ -879,7 +751,7 @@ static struct crypto_alg algs_ctr[] = {
                                  CRYPTO_ALG_ASYNC,
        .cra_blocksize          = AES_BLOCK_SIZE,
        .cra_ctxsize            = sizeof(struct omap_aes_ctx),
-       .cra_alignmask          = 0,
+       .cra_alignmask          = 0xf,
        .cra_type               = &crypto_ablkcipher_type,
        .cra_module             = THIS_MODULE,
        .cra_init               = omap_aes_cra_init,
@@ -893,7 +765,29 @@ static struct crypto_alg algs_ctr[] = {
                .encrypt        = omap_aes_ctr_encrypt,
                .decrypt        = omap_aes_ctr_decrypt,
        }
-} ,
+},
+{
+       .cra_name               = "gcm(aes)",
+       .cra_driver_name        = "gcm-aes-omap",
+       .cra_priority           = 100,
+       .cra_flags              = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC |
+                                 CRYPTO_ALG_KERN_DRIVER_ONLY,
+       .cra_blocksize          = AES_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct omap_aes_ctx),
+       .cra_alignmask          = 0xf,
+       .cra_type               = &crypto_aead_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = omap_aes_gcm_cra_init,
+       .cra_exit               = omap_aes_cra_exit,
+       .cra_u.aead = {
+               .maxauthsize    = AES_BLOCK_SIZE,
+               .geniv          = "eseqiv",
+               .ivsize         = AES_BLOCK_SIZE,
+               .setkey         = omap_aes_gcm_setkey,
+               .encrypt        = omap_aes_gcm_encrypt,
+               .decrypt        = omap_aes_gcm_decrypt,
+       }
+},
 };
 
 static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc[] = {
@@ -1175,6 +1069,7 @@ static int omap_aes_probe(struct platform_device *pdev)
 
        spin_lock_init(&dd->lock);
        crypto_init_queue(&dd->queue, OMAP_AES_QUEUE_LENGTH);
+       crypto_init_queue(&dd->aead_queue, OMAP_AES_QUEUE_LENGTH);
 
        err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) :
                               omap_aes_get_res_pdev(dd, pdev, &res);
@@ -1234,17 +1129,19 @@ static int omap_aes_probe(struct platform_device *pdev)
        spin_unlock(&list_lock);
 
        for (i = 0; i < dd->pdata->algs_info_size; i++) {
-               for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
-                       algp = &dd->pdata->algs_info[i].algs_list[j];
+               if (!dd->pdata->algs_info[i].registered) {
+                       for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
+                               algp = &dd->pdata->algs_info[i].algs_list[j];
 
-                       pr_debug("reg alg: %s\n", algp->cra_name);
-                       INIT_LIST_HEAD(&algp->cra_list);
+                               pr_debug("reg alg: %s\n", algp->cra_name);
+                               INIT_LIST_HEAD(&algp->cra_list);
 
-                       err = crypto_register_alg(algp);
-                       if (err)
-                               goto err_algs;
+                               err = crypto_register_alg(algp);
+                               if (err)
+                                       goto err_algs;
 
-                       dd->pdata->algs_info[i].registered++;
+                               dd->pdata->algs_info[i].registered++;
+                       }
                }
        }
 
diff --git a/drivers/crypto/omap-aes.h b/drivers/crypto/omap-aes.h
new file mode 100644 (file)
index 0000000..676ebce
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for OMAP AES HW ACCELERATOR defines
+ *
+ * Copyright (c) 2015 Texas Instruments Incorporated
+ *
+ * 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 __OMAP_AES_REGS_H__
+#define __OMAP_AES_REGS_H__
+
+#define DST_MAXBURST                   4
+#define DMA_MIN                                (DST_MAXBURST * sizeof(u32))
+
+#define _calc_walked(inout) (dd->inout##_walk.offset - dd->inout##_sg->offset)
+
+/* OMAP TRM gives bitfields as start:end, where start is the higher bit
+   number. For example 7:0 */
+#define FLD_MASK(start, end)   (((1 << ((start) - (end) + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
+
+#define AES_REG_KEY(dd, x)             ((dd)->pdata->key_ofs - \
+                                               ((x ^ 0x01) * 0x04))
+#define AES_REG_IV(dd, x)              ((dd)->pdata->iv_ofs + ((x) * 0x04))
+
+#define AES_REG_CTRL(dd)               ((dd)->pdata->ctrl_ofs)
+#define AES_REG_CTRL_CONTEXT_READY     (1 << 31)
+#define AES_REG_CTRL_CTR_WIDTH_MASK    (3 << 7)
+#define AES_REG_CTRL_CTR_WIDTH_32              (0 << 7)
+#define AES_REG_CTRL_CTR_WIDTH_64              (1 << 7)
+#define AES_REG_CTRL_CTR_WIDTH_96              (2 << 7)
+#define AES_REG_CTRL_CTR_WIDTH_128             (3 << 7)
+#define AES_REG_CTRL_GCM                       (3 << 16)
+#define AES_REG_CTRL_CTR               (1 << 6)
+#define AES_REG_CTRL_CBC               (1 << 5)
+#define AES_REG_CTRL_KEY_SIZE          (3 << 3)
+#define AES_REG_CTRL_DIRECTION         (1 << 2)
+#define AES_REG_CTRL_INPUT_READY       (1 << 1)
+#define AES_REG_CTRL_OUTPUT_READY      (1 << 0)
+
+#define AES_REG_C_LEN_0                        0x54
+#define AES_REG_C_LEN_1                        0x58
+#define AES_REG_A_LEN                  0x5C
+
+#define AES_REG_DATA_N(dd, x)          ((dd)->pdata->data_ofs + ((x) * 0x04))
+#define AES_REG_TAG_N(dd, x)           (0x70 + ((x) * 0x04))
+
+#define AES_REG_REV(dd)                        ((dd)->pdata->rev_ofs)
+
+#define AES_REG_MASK(dd)               ((dd)->pdata->mask_ofs)
+#define AES_REG_MASK_SIDLE             (1 << 6)
+#define AES_REG_MASK_START             (1 << 5)
+#define AES_REG_MASK_DMA_OUT_EN                (1 << 3)
+#define AES_REG_MASK_DMA_IN_EN         (1 << 2)
+#define AES_REG_MASK_SOFTRESET         (1 << 1)
+#define AES_REG_AUTOIDLE               (1 << 0)
+
+#define AES_REG_LENGTH_N(x)            (0x54 + ((x) * 0x04))
+
+#define AES_REG_IRQ_STATUS(dd)         ((dd)->pdata->irq_status_ofs)
+#define AES_REG_IRQ_ENABLE(dd)         ((dd)->pdata->irq_enable_ofs)
+#define AES_REG_IRQ_DATA_IN            BIT(1)
+#define AES_REG_IRQ_DATA_OUT           BIT(2)
+#define DEFAULT_TIMEOUT                (5*HZ)
+
+#define FLAGS_MODE_MASK                0x001f
+#define FLAGS_ENCRYPT          BIT(0)
+#define FLAGS_CBC              BIT(1)
+#define FLAGS_GIV              BIT(2)
+#define FLAGS_CTR              BIT(3)
+#define FLAGS_GCM              BIT(4)
+
+#define FLAGS_INIT             BIT(5)
+#define FLAGS_FAST             BIT(6)
+#define FLAGS_BUSY             BIT(7)
+
+#define AES_ASSOC_DATA_COPIED  BIT(0)
+#define AES_IN_DATA_COPIED     BIT(1)
+#define AES_OUT_DATA_COPIED    BIT(2)
+
+
+#define AES_BLOCK_WORDS                (AES_BLOCK_SIZE >> 2)
+
+struct tcrypt_result {
+       struct completion completion;
+       int err;
+};
+
+struct omap_aes_ctx {
+       struct omap_aes_dev *dd;
+
+       int             keylen;
+       u32             key[AES_KEYSIZE_256 / sizeof(u32)];
+       u32             auth_tag[AES_BLOCK_SIZE / sizeof(u32)];
+       unsigned long   flags;
+};
+
+struct omap_aes_reqctx {
+       unsigned long mode;
+};
+
+#define OMAP_AES_QUEUE_LENGTH  1
+#define OMAP_AES_CACHE_SIZE    0
+
+struct omap_aes_algs_info {
+       struct crypto_alg       *algs_list;
+       unsigned int            size;
+       unsigned int            registered;
+};
+
+struct omap_aes_pdata {
+       struct omap_aes_algs_info       *algs_info;
+       unsigned int    algs_info_size;
+
+       void (*trigger)(struct omap_aes_dev *dd, int length);
+
+       u32             key_ofs;
+       u32             iv_ofs;
+       u32             ctrl_ofs;
+       u32             data_ofs;
+       u32             rev_ofs;
+       u32             mask_ofs;
+       u32             irq_enable_ofs;
+       u32             irq_status_ofs;
+
+       u32             dma_enable_in;
+       u32             dma_enable_out;
+       u32             dma_start;
+
+       u32             major_mask;
+       u32             major_shift;
+       u32             minor_mask;
+       u32             minor_shift;
+};
+
+struct omap_aes_dev {
+       struct list_head        list;
+       unsigned long           phys_base;
+       void __iomem            *io_base;
+       struct omap_aes_ctx     *ctx;
+       struct device           *dev;
+       unsigned long           flags;
+       int                     err;
+
+       /* Lock to acquire omap_aes_dd */
+       spinlock_t              lock;
+       struct crypto_queue     queue;
+       struct crypto_queue     aead_queue;
+
+       struct tasklet_struct   done_task;
+       struct tasklet_struct   queue_task;
+
+       struct ablkcipher_request       *req;
+       struct aead_request             *aead_req;
+
+       /*
+        * total is used by PIO mode for book keeping so introduce
+        * variable total_save as need it to calc page_order
+        */
+       size_t                          total;
+       size_t                          total_save;
+       size_t                          assoc_len;
+       size_t                          authsize;
+
+       struct scatterlist              *in_sg;
+       struct scatterlist              *assoc_sg;
+       struct scatterlist              *out_sg;
+
+       /* Buffers for copying for unaligned cases */
+       struct scatterlist              in_sgl[2];
+       struct scatterlist              out_sgl;
+       struct scatterlist              aead_sgl[2];
+       struct scatterlist              *orig_out;
+       int                             sgs_copied;
+
+       struct scatter_walk             in_walk;
+       struct scatter_walk             out_walk;
+       int                     dma_in;
+       struct dma_chan         *dma_lch_in;
+       int                     dma_out;
+       struct dma_chan         *dma_lch_out;
+       int                     in_sg_len;
+       int                     out_sg_len;
+       int                     pio_only;
+       const struct omap_aes_pdata     *pdata;
+};
+
+u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset);
+void omap_aes_write(struct omap_aes_dev *dd, u32 offset, u32 value);
+struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx);
+int omap_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key,
+                       unsigned int keylen);
+int omap_aes_gcm_encrypt(struct aead_request *req);
+int omap_aes_gcm_decrypt(struct aead_request *req);
+int omap_aes_write_ctrl(struct omap_aes_dev *dd);
+int omap_aes_check_aligned(struct scatterlist *sg, int total);
+int omap_aes_crypt_dma_start(struct omap_aes_dev *dd);
+void omap_aes_gcm_dma_out_callback(void *data);
+int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd);
+
+#endif
index 2e5c3853a44f85084ae4ccd81cb83a0fda5b5d81..8fdacaf7c6e5f2df1f040956d0f1db140140d6e1 100644 (file)
@@ -536,9 +536,6 @@ static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
        dmaengine_terminate_all(dd->dma_lch_in);
        dmaengine_terminate_all(dd->dma_lch_out);
 
-       dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
-       dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE);
-
        return err;
 }
 
index 907e124975b8fb428087a841a5d0db7271a59b6d..848ab327801eab317edfcb7923e56ae1606d8226 100644 (file)
@@ -640,6 +640,7 @@ static size_t omap_sham_append_sg(struct omap_sham_reqctx *ctx)
 
        while (ctx->sg) {
                vaddr = kmap_atomic(sg_page(ctx->sg));
+               vaddr += ctx->sg->offset;
 
                count = omap_sham_append_buffer(ctx,
                                vaddr + ctx->offset,
@@ -1951,6 +1952,7 @@ static int omap_sham_probe(struct platform_device *pdev)
        dd->flags |= dd->pdata->flags;
 
        pm_runtime_enable(dev);
+       pm_runtime_irq_safe(dev);
        pm_runtime_get_sync(dev);
        rev = omap_sham_read(dd, SHA_REG_REV(dd));
        pm_runtime_put_sync(&pdev->dev);
index 453822cc4f9d3a9a9c7b62626c7362c13ee8b931..fe8b0c9915188dcdaccbc7cd55027c88b51ff887 100644 (file)
@@ -48,6 +48,8 @@ static bool dw_dma_of_filter(struct dma_chan *chan, void *param)
        return true;
 }
 
+#define DRV_NAME       "dw_dmac"
+
 static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
                                        struct of_dma *ofdma)
 {
@@ -293,7 +295,7 @@ static struct platform_driver dw_driver = {
        .remove         = dw_remove,
        .shutdown       = dw_shutdown,
        .driver = {
-               .name   = "dw_dmac",
+               .name   = DRV_NAME,
                .pm     = &dw_dev_pm_ops,
                .of_match_table = of_match_ptr(dw_dma_of_id_table),
                .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table),
@@ -314,3 +316,4 @@ module_exit(dw_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver");
+MODULE_ALIAS("platform:" DRV_NAME);
index 59d80f817590669abe132ba797f86887ee19f2de..cb40a7ae386c2e1a875540fa9e0e9aac52de0344 100644 (file)
@@ -256,6 +256,12 @@ static int edma_terminate_all(struct edma_chan *echan)
         */
        if (echan->edesc) {
                int cyclic = echan->edesc->cyclic;
+               /*
+                * free the running request descriptor
+                * since it is not in any of the vdesc lists
+                */
+               edma_desc_free(&echan->edesc->vdesc);
+
                echan->edesc = NULL;
                edma_stop(echan->ch_num);
                /* Move the cyclic channel back to default queue */
@@ -285,8 +291,7 @@ static int edma_slave_config(struct edma_chan *echan,
 
 static int edma_dma_pause(struct edma_chan *echan)
 {
-       /* Pause/Resume only allowed with cyclic mode */
-       if (!echan->edesc || !echan->edesc->cyclic)
+       if (!echan->edesc)
                return -EINVAL;
 
        edma_pause(echan->ch_num);
@@ -295,10 +300,6 @@ static int edma_dma_pause(struct edma_chan *echan)
 
 static int edma_dma_resume(struct edma_chan *echan)
 {
-       /* Pause/Resume only allowed with cyclic mode */
-       if (!echan->edesc->cyclic)
-               return -EINVAL;
-
        edma_resume(echan->ch_num);
        return 0;
 }
index 4f3a9feb7f9b01085c4fe29b8b023b20a0fb7deb..21b3c8a9be69b37d943d4cd3bc1b705dde49a04f 100644 (file)
@@ -1002,6 +1002,7 @@ static int omap_dma_terminate_all(struct omap_chan *c)
         * c->desc is NULL and exit.)
         */
        if (c->desc) {
+               omap_dma_desc_free(&c->desc->vd);
                c->desc = NULL;
                /* Avoid stopping the dma twice */
                if (!c->paused)
index 54e2abe671f70acef2965ec5f74cd8b877ac7089..c611bcc01f7e9e0792aee0d31d18f28f2d6325b7 100644 (file)
@@ -285,8 +285,9 @@ static const u32 correrrthrsld[] = {
  * sbridge structs
  */
 
-#define NUM_CHANNELS   4
-#define MAX_DIMMS      3               /* Max DIMMS per channel */
+#define NUM_CHANNELS           4
+#define MAX_DIMMS              3       /* Max DIMMS per channel */
+#define CHANNEL_UNSPECIFIED    0xf     /* Intel IA32 SDM 15-14 */
 
 enum type {
        SANDY_BRIDGE,
@@ -1750,6 +1751,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
 
        /* FIXME: need support for channel mask */
 
+       if (channel == CHANNEL_UNSPECIFIED)
+               channel = -1;
+
        /* Call the helper to output message */
        edac_mc_handle_error(tp_event, mci, core_err_cnt,
                             m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
index 97cdd16a2169a17e741323cca3adc634c26c966e..c98b101a73aebe93c12ddc379e021efcd6cb0787 100644 (file)
@@ -170,7 +170,7 @@ int __init efi_runtime_map_init(struct kobject *efi_kobj)
 
        return 0;
 out_add_entry:
-       for (j = i - 1; j > 0; j--) {
+       for (j = i - 1; j >= 0; j--) {
                entry = *(map_entries + j);
                kobject_put(&entry->kobj);
        }
index 3b1fd1ce460f258fb0151550f5cb30b1260b4e62..e9d8cf6c2f79cb6b96f5dae0f94f0cf77c286733 100644 (file)
@@ -304,11 +304,13 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
        u32 mask = 1 << (d->irq - gc->irq_base);
 
        irq_gc_lock(gc);
-       gc->mask_cache &= ~mask;
-       writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+       ct->mask_cache_priv &= ~mask;
+
+       writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip));
        irq_gc_unlock(gc);
 }
 
@@ -316,11 +318,13 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
        u32 mask = 1 << (d->irq - gc->irq_base);
 
        irq_gc_lock(gc);
-       gc->mask_cache |= mask;
-       writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+       ct->mask_cache_priv |= mask;
+       writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip));
        irq_gc_unlock(gc);
 }
 
@@ -328,11 +332,13 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
        u32 mask = 1 << (d->irq - gc->irq_base);
 
        irq_gc_lock(gc);
-       gc->mask_cache &= ~mask;
-       writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+       ct->mask_cache_priv &= ~mask;
+       writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip));
        irq_gc_unlock(gc);
 }
 
@@ -340,11 +346,13 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mvebu_gpio_chip *mvchip = gc->private;
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
        u32 mask = 1 << (d->irq - gc->irq_base);
 
        irq_gc_lock(gc);
-       gc->mask_cache |= mask;
-       writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+       ct->mask_cache_priv |= mask;
+       writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip));
        irq_gc_unlock(gc);
 }
 
index d26028cb9eacb17a4c27ed668a260429d861165a..e142c99ebcfae17a18c5fcf04302c59805d5882d 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/slab.h>
 
+#include "gpiolib.h"
+
 struct gpio_desc;
 
 /* Private data structure for of_gpiochip_find_and_xlate */
@@ -102,6 +104,116 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
 }
 EXPORT_SYMBOL(of_get_named_gpiod_flags);
 
+/**
+ * of_get_gpio_hog() - Get a GPIO hog descriptor, names and flags for GPIO API
+ * @np:                device node to get GPIO from
+ * @name:      GPIO line name
+ * @flags:     a flags pointer to fill in
+ *
+ * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
+ * value on the error condition.
+ */
+static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
+                                 const char **name,
+                                 unsigned long *flags)
+{
+       struct device_node *chip_np;
+       enum of_gpio_flags xlate_flags;
+       struct gpio_desc *desc;
+       struct gg_data gg_data = {
+               .flags = &xlate_flags,
+               .out_gpio = NULL,
+       };
+       u32 tmp;
+       int i, ret;
+
+       chip_np = np->parent;
+       if (!chip_np)
+               return ERR_PTR(-EINVAL);
+
+       xlate_flags = 0;
+       *flags = 0;
+
+       ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp);
+       if (ret)
+               return ERR_PTR(ret);
+
+       if (tmp > MAX_PHANDLE_ARGS)
+               return ERR_PTR(-EINVAL);
+
+       gg_data.gpiospec.args_count = tmp;
+       gg_data.gpiospec.np = chip_np;
+       for (i = 0; i < tmp; i++) {
+               ret = of_property_read_u32_index(np, "gpios", i,
+                                          &gg_data.gpiospec.args[i]);
+               if (ret)
+                       return ERR_PTR(ret);
+       }
+
+       gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
+       if (!gg_data.out_gpio) {
+               if (np->parent == np)
+                       return ERR_PTR(-ENXIO);
+               else
+                       return ERR_PTR(-EINVAL);
+       }
+
+       if (xlate_flags & OF_GPIO_ACTIVE_LOW)
+               *flags |= GPIOF_ACTIVE_LOW;
+
+       if (of_property_read_bool(np, "input"))
+               *flags |= GPIOF_DIR_IN;
+       else if (of_property_read_bool(np, "output-low"))
+               ; /* No flag needed for output-low */
+       else if (of_property_read_bool(np, "output-high"))
+               *flags |= GPIOF_INIT_HIGH;
+       else {
+               pr_warn("GPIO line %d (%s): no hogging state specified, bailing out\n",
+                       desc_to_gpio(gg_data.out_gpio), np->name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (name && of_property_read_string(np, "line-name", name))
+               *name = np->name;
+
+       desc = gg_data.out_gpio;
+
+       return desc;
+}
+
+/**
+ * of_gpiochip_scan_hogs - Scan gpio-controller and apply GPIO hog as requested
+ * @chip:      gpio chip to act on
+ *
+ * This is only used by of_gpiochip_add to request/set GPIO initial
+ * configuration.
+ */
+static void of_gpiochip_scan_hogs(struct gpio_chip *chip)
+{
+       struct gpio_desc *desc = NULL;
+       struct device_node *np;
+       const char *name;
+       unsigned long flags = 0;
+
+       if (chip->of_node == NULL) {
+               pr_err("GPIO: chip->label:%s chip->of_node is NULL\n",
+                      chip->label);
+               return;
+       }
+
+       for_each_child_of_node(chip->of_node, np) {
+               if (!of_property_read_bool(np, "gpio-hog"))
+                       continue;
+
+               desc = of_get_gpio_hog(np, &name, &flags);
+               if (IS_ERR(desc))
+                       continue;
+
+               if (gpiod_hog(desc, name, flags))
+                       continue;
+       }
+}
+
 /**
  * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
  * @gc:                pointer to the gpio_chip structure
@@ -294,12 +406,12 @@ void of_gpiochip_add(struct gpio_chip *chip)
 
        of_gpiochip_add_pin_range(chip);
        of_node_get(chip->of_node);
+
+       of_gpiochip_scan_hogs(chip);
 }
 
 void of_gpiochip_remove(struct gpio_chip *chip)
 {
        gpiochip_remove_pin_ranges(chip);
-
-       if (chip->of_node)
-               of_node_put(chip->of_node);
+       of_node_put(chip->of_node);
 }
index af28fd9ae5943e74d2394f69889975fc45a5d4c5..75467df79437558c26f2a5610bd64a15f1b3de8b 100644 (file)
@@ -60,6 +60,7 @@ struct gpio_desc {
 #define FLAG_OPEN_DRAIN        7       /* Gpio is open drain type */
 #define FLAG_OPEN_SOURCE 8     /* Gpio is open source type */
 #define FLAG_USED_AS_IRQ 9     /* GPIO is connected to an IRQ */
+#define FLAG_IS_HOGGED 10      /* GPIO is hogged */
 
 #define ID_SHIFT       16      /* add new flags before this one */
 
@@ -85,6 +86,8 @@ static DEFINE_IDR(dirent_idr);
 static int gpiod_request(struct gpio_desc *desc, const char *label);
 static void gpiod_free(struct gpio_desc *desc);
 
+struct gpio_desc *__must_check gpiod_get_hog_index(struct device *dev,
+                                                  unsigned int idx);
 /* With descriptor prefix */
 
 #ifdef CONFIG_DEBUG_FS
@@ -800,6 +803,7 @@ static struct class gpio_class = {
  */
 int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
 {
+       struct gpio_chip        *chip;
        unsigned long           flags;
        int                     status;
        const char              *ioname = NULL;
@@ -817,8 +821,16 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
                return -EINVAL;
        }
 
+       chip = desc->chip;
+
        mutex_lock(&sysfs_lock);
 
+       /* check if chip is being removed */
+       if (!chip || !chip->exported) {
+               status = -ENODEV;
+               goto fail_unlock;
+       }
+
        spin_lock_irqsave(&gpio_lock, flags);
        if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
             test_bit(FLAG_EXPORT, &desc->flags)) {
@@ -1057,12 +1069,15 @@ static void gpiochip_unexport(struct gpio_chip *chip)
 {
        int                     status;
        struct device           *dev;
+       struct gpio_desc *desc;
+       unsigned int i;
 
        mutex_lock(&sysfs_lock);
        dev = class_find_device(&gpio_class, NULL, chip, match_export);
        if (dev) {
                put_device(dev);
                device_unregister(dev);
+               /* prevent further gpiod exports */
                chip->exported = false;
                status = 0;
        } else
@@ -1071,6 +1086,13 @@ static void gpiochip_unexport(struct gpio_chip *chip)
 
        if (status)
                chip_dbg(chip, "%s: status %d\n", __func__, status);
+
+       /* unregister gpiod class devices owned by sysfs */
+       for (i = 0; i < chip->ngpio; i++) {
+               desc = &chip->desc[i];
+               if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
+                       gpiod_free(desc);
+       }
 }
 
 static int __init gpiolib_sysfs_init(void)
@@ -1253,6 +1275,9 @@ fail:
 }
 EXPORT_SYMBOL_GPL(gpiochip_add);
 
+/* Forward-declaration */
+static void gpiochip_free_hogs(struct gpio_chip *chip);
+
 /**
  * gpiochip_remove() - unregister a gpio_chip
  * @chip: the chip to unregister
@@ -1265,9 +1290,12 @@ int gpiochip_remove(struct gpio_chip *chip)
        int             status = 0;
        unsigned        id;
 
+       gpiochip_unexport(chip);
+
        spin_lock_irqsave(&gpio_lock, flags);
 
        gpiochip_remove_pin_ranges(chip);
+       gpiochip_free_hogs(chip);
        of_gpiochip_remove(chip);
        acpi_gpiochip_remove(chip);
 
@@ -1286,9 +1314,6 @@ int gpiochip_remove(struct gpio_chip *chip)
 
        spin_unlock_irqrestore(&gpio_lock, flags);
 
-       if (status == 0)
-               gpiochip_unexport(chip);
-
        return status;
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
@@ -1552,6 +1577,7 @@ static void gpiod_free(struct gpio_desc *desc)
                clear_bit(FLAG_REQUESTED, &desc->flags);
                clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
                clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
+               clear_bit(FLAG_IS_HOGGED, &desc->flags);
        } else
                WARN_ON(extra_checks);
 
@@ -1957,15 +1983,15 @@ EXPORT_SYMBOL_GPL(gpiod_is_active_low);
  * that the GPIO was actually requested.
  */
 
-static int _gpiod_get_raw_value(const struct gpio_desc *desc)
+static bool _gpiod_get_raw_value(const struct gpio_desc *desc)
 {
        struct gpio_chip        *chip;
-       int value;
+       bool value;
        int offset;
 
        chip = desc->chip;
        offset = gpio_chip_hwgpio(desc);
-       value = chip->get ? chip->get(chip, offset) : 0;
+       value = chip->get ? chip->get(chip, offset) : false;
        trace_gpio_value(desc_to_gpio(desc), 1, value);
        return value;
 }
@@ -2021,7 +2047,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_value);
  * @desc: gpio descriptor whose state need to be set.
  * @value: Non-zero for setting it HIGH otherise it will set to LOW.
  */
-static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)
+static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value)
 {
        int err = 0;
        struct gpio_chip *chip = desc->chip;
@@ -2048,7 +2074,7 @@ static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)
  * @desc: gpio descriptor whose state need to be set.
  * @value: Non-zero for setting it HIGH otherise it will set to LOW.
  */
-static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)
+static void _gpio_set_open_source_value(struct gpio_desc *desc, bool value)
 {
        int err = 0;
        struct gpio_chip *chip = desc->chip;
@@ -2070,7 +2096,7 @@ static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)
                          __func__, err);
 }
 
-static void _gpiod_set_raw_value(struct gpio_desc *desc, int value)
+static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value)
 {
        struct gpio_chip        *chip;
 
@@ -2519,6 +2545,51 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(gpiod_get_index);
 
+/**
+ * gpiod_hog - Hog the specified GPIO desc given the provided flags
+ * @desc:      gpio whose value will be assigned
+ * @name:      gpio line name
+ * @flags:     gpio initialization flags - returned from of_find_gpio() or
+ *             of_get_gpio_hog()
+ *
+ */
+int gpiod_hog(struct gpio_desc *desc, const char *name,
+             unsigned long flags)
+{
+       int status;
+
+       status = gpio_request_one(desc_to_gpio(desc), flags, name);
+       if (status)
+               return status;
+
+       /* Mark GPIO as hogged so it can be identified and removed later */
+       set_bit(FLAG_IS_HOGGED, &desc->flags);
+
+       pr_debug("%s: GPIO:%d (%s) as %s%s\n", __func__,
+                desc_to_gpio(desc), name,
+                (flags&GPIOF_DIR_IN) ? "input" : "output",
+                (flags&GPIOF_DIR_IN) ? "" :
+                (flags&GPIOF_INIT_HIGH) ? "/high" : "/low");
+
+       return 0;
+}
+
+/**
+ * gpiochip_free_hogs - Scan gpio-controller chip and release GPIO hog
+ * @chip:      gpio chip to act on
+ *
+ * This is only used by of_gpiochip_remove to free hogged gpios
+ */
+static void gpiochip_free_hogs(struct gpio_chip *chip)
+{
+       int id;
+
+       for (id = 0; id < chip->ngpio; id++) {
+               if (test_bit(FLAG_IS_HOGGED, &chip->desc[id].flags))
+                       gpiod_free(&chip->desc[id]);
+       }
+}
+
 /**
  * gpiod_put - dispose of a GPIO descriptor
  * @desc:      GPIO descriptor to dispose of
index 82be586c1f90edd8946cf5d9a23e208bc6dbbccc..561a427651b821ff7cd36cfec92016baf7cf2067 100644 (file)
@@ -43,4 +43,6 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
 }
 #endif
 
+int gpiod_hog(struct gpio_desc *desc, const char *name, unsigned long flags);
+
 #endif /* GPIOLIB_H */
index 0c83b3dab58c0142743e46cc4d88c5784f812e3d..5b38bf819b7b64b57cc6123d8af095421bfcb657 100644 (file)
 #define   GMBUS_CYCLE_INDEX    (2<<25)
 #define   GMBUS_CYCLE_STOP     (4<<25)
 #define   GMBUS_BYTE_COUNT_SHIFT 16
+#define   GMBUS_BYTE_COUNT_MAX   256U
 #define   GMBUS_SLAVE_INDEX_SHIFT 8
 #define   GMBUS_SLAVE_ADDR_SHIFT 1
 #define   GMBUS_SLAVE_READ     (1<<0)
index d33b61d0dd3331b6bd073806d0482b19aeb0eb08..1d02970ed395bf793b71aa6ac815b7b2300341b0 100644 (file)
@@ -324,18 +324,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
 }
 
 static int
-gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
-               u32 gmbus1_index)
+gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
+                     unsigned short addr, u8 *buf, unsigned int len,
+                     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) |
+                  (addr << GMBUS_SLAVE_ADDR_SHIFT) |
                   GMBUS_SLAVE_READ | GMBUS_SW_RDY);
        while (len) {
                int ret;
@@ -357,11 +356,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
 }
 
 static int
-gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
+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;
+       unsigned int rx_size = msg->len;
+       unsigned int len;
+       int ret;
+
+       do {
+               len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+
+               ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
+                                           buf, len, gmbus1_index);
+               if (ret)
+                       return ret;
+
+               rx_size -= len;
+               buf += len;
+       } while (rx_size != 0);
+
+       return 0;
+}
+
+static int
+gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
+                      unsigned short addr, u8 *buf, unsigned int len)
+{
+       int reg_offset = dev_priv->gpio_mmio_base;
+       unsigned int chunk_size = len;
        u32 val, loop;
 
        val = loop = 0;
@@ -373,8 +396,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
        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) |
+                  (chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
+                  (addr << GMBUS_SLAVE_ADDR_SHIFT) |
                   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
        while (len) {
                int ret;
@@ -391,6 +414,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
                if (ret)
                        return ret;
        }
+
+       return 0;
+}
+
+static int
+gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
+{
+       u8 *buf = msg->buf;
+       unsigned int tx_size = msg->len;
+       unsigned int len;
+       int ret;
+
+       do {
+               len = min(tx_size, GMBUS_BYTE_COUNT_MAX);
+
+               ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len);
+               if (ret)
+                       return ret;
+
+               buf += len;
+               tx_size -= len;
+       } while (tx_size != 0);
+
        return 0;
 }
 
index af49b24d14cbb56da1fc6e75356b8f162258d4c6..1eb49941faff1db599e69daf556ac6d8784337f0 100644 (file)
@@ -815,12 +815,28 @@ static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
 static const struct dmi_system_id intel_dual_link_lvds[] = {
        {
                .callback = intel_dual_link_lvds_callback,
-               .ident = "Apple MacBook Pro (Core i5/i7 Series)",
+               .ident = "Apple MacBook Pro 15\" (2010)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"),
+               },
+       },
+       {
+               .callback = intel_dual_link_lvds_callback,
+               .ident = "Apple MacBook Pro 15\" (2011)",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
                        DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
                },
        },
+       {
+               .callback = intel_dual_link_lvds_callback,
+               .ident = "Apple MacBook Pro 15\" (2012)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"),
+               },
+       },
        { }     /* terminating entry */
 };
 
index 461df93e825edf81e98d22683cfbf4fe7b4404aa..4f32b34f48d43b83bd62dcf2d5ddf951dab2875f 100644 (file)
@@ -35,8 +35,6 @@
         A3XX_INT0_CP_AHB_ERROR_HALT |     \
         A3XX_INT0_UCHE_OOB_ACCESS)
 
-static struct platform_device *a3xx_pdev;
-
 static void a3xx_me_init(struct msm_gpu *gpu)
 {
        struct msm_ringbuffer *ring = gpu->rb;
@@ -311,7 +309,6 @@ static void a3xx_destroy(struct msm_gpu *gpu)
                ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
 #endif
 
-       put_device(&a3xx_gpu->pdev->dev);
        kfree(a3xx_gpu);
 }
 
@@ -439,7 +436,8 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
        struct a3xx_gpu *a3xx_gpu = NULL;
        struct adreno_gpu *adreno_gpu;
        struct msm_gpu *gpu;
-       struct platform_device *pdev = a3xx_pdev;
+       struct msm_drm_private *priv = dev->dev_private;
+       struct platform_device *pdev = priv->gpu_pdev;
        struct adreno_platform_config *config;
        int ret;
 
@@ -460,7 +458,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
        adreno_gpu = &a3xx_gpu->base;
        gpu = &adreno_gpu->base;
 
-       get_device(&pdev->dev);
        a3xx_gpu->pdev = pdev;
 
        gpu->fast_rate = config->fast_rate;
@@ -522,17 +519,24 @@ fail:
 #  include <mach/kgsl.h>
 #endif
 
-static int a3xx_probe(struct platform_device *pdev)
+static void set_gpu_pdev(struct drm_device *dev,
+               struct platform_device *pdev)
+{
+       struct msm_drm_private *priv = dev->dev_private;
+       priv->gpu_pdev = pdev;
+}
+
+static int a3xx_bind(struct device *dev, struct device *master, void *data)
 {
        static struct adreno_platform_config config = {};
 #ifdef CONFIG_OF
-       struct device_node *child, *node = pdev->dev.of_node;
+       struct device_node *child, *node = dev->of_node;
        u32 val;
        int ret;
 
        ret = of_property_read_u32(node, "qcom,chipid", &val);
        if (ret) {
-               dev_err(&pdev->dev, "could not find chipid: %d\n", ret);
+               dev_err(dev, "could not find chipid: %d\n", ret);
                return ret;
        }
 
@@ -548,7 +552,7 @@ static int a3xx_probe(struct platform_device *pdev)
                        for_each_child_of_node(child, pwrlvl) {
                                ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
                                if (ret) {
-                                       dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret);
+                                       dev_err(dev, "could not find gpu-freq: %d\n", ret);
                                        return ret;
                                }
                                config.fast_rate = max(config.fast_rate, val);
@@ -558,12 +562,12 @@ static int a3xx_probe(struct platform_device *pdev)
        }
 
        if (!config.fast_rate) {
-               dev_err(&pdev->dev, "could not find clk rates\n");
+               dev_err(dev, "could not find clk rates\n");
                return -ENXIO;
        }
 
 #else
-       struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
+       struct kgsl_device_platform_data *pdata = dev->platform_data;
        uint32_t version = socinfo_get_version();
        if (cpu_is_apq8064ab()) {
                config.fast_rate = 450000000;
@@ -609,14 +613,30 @@ static int a3xx_probe(struct platform_device *pdev)
        config.bus_scale_table = pdata->bus_scale_table;
 #  endif
 #endif
-       pdev->dev.platform_data = &config;
-       a3xx_pdev = pdev;
+       dev->platform_data = &config;
+       set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
        return 0;
 }
 
+static void a3xx_unbind(struct device *dev, struct device *master,
+               void *data)
+{
+       set_gpu_pdev(dev_get_drvdata(master), NULL);
+}
+
+static const struct component_ops a3xx_ops = {
+               .bind   = a3xx_bind,
+               .unbind = a3xx_unbind,
+};
+
+static int a3xx_probe(struct platform_device *pdev)
+{
+       return component_add(&pdev->dev, &a3xx_ops);
+}
+
 static int a3xx_remove(struct platform_device *pdev)
 {
-       a3xx_pdev = NULL;
+       component_del(&pdev->dev, &a3xx_ops);
        return 0;
 }
 
@@ -624,7 +644,6 @@ static const struct of_device_id dt_match[] = {
        { .compatible = "qcom,kgsl-3d0" },
        {}
 };
-MODULE_DEVICE_TABLE(of, dt_match);
 
 static struct platform_driver a3xx_driver = {
        .probe = a3xx_probe,
index 6f1588aa9071f8db8642dcb8b32e46642381b38d..8a04a1d206cd50bcdc57f8277f0696c230c7749b 100644 (file)
@@ -17,8 +17,6 @@
 
 #include "hdmi.h"
 
-static struct platform_device *hdmi_pdev;
-
 void hdmi_set_mode(struct hdmi *hdmi, bool power_on)
 {
        uint32_t ctrl = 0;
@@ -75,7 +73,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
 {
        struct hdmi *hdmi = NULL;
        struct msm_drm_private *priv = dev->dev_private;
-       struct platform_device *pdev = hdmi_pdev;
+       struct platform_device *pdev = priv->hdmi_pdev;
        struct hdmi_platform_config *config;
        int i, ret;
 
@@ -95,8 +93,6 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
 
        kref_init(&hdmi->refcount);
 
-       get_device(&pdev->dev);
-
        hdmi->dev = dev;
        hdmi->pdev = pdev;
        hdmi->config = config;
@@ -249,17 +245,24 @@ fail:
 
 #include <linux/of_gpio.h>
 
-static int hdmi_dev_probe(struct platform_device *pdev)
+static void set_hdmi_pdev(struct drm_device *dev,
+               struct platform_device *pdev)
+{
+       struct msm_drm_private *priv = dev->dev_private;
+       priv->hdmi_pdev = pdev;
+}
+
+static int hdmi_bind(struct device *dev, struct device *master, void *data)
 {
        static struct hdmi_platform_config config = {};
 #ifdef CONFIG_OF
-       struct device_node *of_node = pdev->dev.of_node;
+       struct device_node *of_node = dev->of_node;
 
        int get_gpio(const char *name)
        {
                int gpio = of_get_named_gpio(of_node, name, 0);
                if (gpio < 0) {
-                       dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n",
+                       dev_err(dev, "failed to get gpio: %s (%d)\n",
                                        name, gpio);
                        gpio = -1;
                }
@@ -336,14 +339,30 @@ static int hdmi_dev_probe(struct platform_device *pdev)
                config.mux_sel_gpio  = -1;
        }
 #endif
-       pdev->dev.platform_data = &config;
-       hdmi_pdev = pdev;
+       dev->platform_data = &config;
+       set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev));
        return 0;
 }
 
+static void hdmi_unbind(struct device *dev, struct device *master,
+               void *data)
+{
+       set_hdmi_pdev(dev_get_drvdata(master), NULL);
+}
+
+static const struct component_ops hdmi_ops = {
+               .bind   = hdmi_bind,
+               .unbind = hdmi_unbind,
+};
+
+static int hdmi_dev_probe(struct platform_device *pdev)
+{
+       return component_add(&pdev->dev, &hdmi_ops);
+}
+
 static int hdmi_dev_remove(struct platform_device *pdev)
 {
-       hdmi_pdev = NULL;
+       component_del(&pdev->dev, &hdmi_ops);
        return 0;
 }
 
@@ -351,7 +370,6 @@ static const struct of_device_id dt_match[] = {
        { .compatible = "qcom,hdmi-tx" },
        {}
 };
-MODULE_DEVICE_TABLE(of, dt_match);
 
 static struct platform_driver hdmi_driver = {
        .probe = hdmi_dev_probe,
index e6adafc7eff3177b789395f6bc81f4ab62042e11..e79cfd0b2b04592097fb11dbee8b2fb2a4d6b021 100644 (file)
@@ -56,6 +56,10 @@ static char *vram;
 MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
 module_param(vram, charp, 0);
 
+/*
+ * Util/helpers:
+ */
+
 void __iomem *msm_ioremap(struct platform_device *pdev, const char *name,
                const char *dbgname)
 {
@@ -143,6 +147,8 @@ static int msm_unload(struct drm_device *dev)
                                priv->vram.paddr, &attrs);
        }
 
+       component_unbind_all(dev->dev, dev);
+
        dev->dev_private = NULL;
 
        kfree(priv);
@@ -175,6 +181,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
        struct msm_kms *kms;
        int ret;
 
+
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv) {
                dev_err(dev->dev, "failed to allocate private data\n");
@@ -226,6 +233,13 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
                                (uint32_t)(priv->vram.paddr + size));
        }
 
+       platform_set_drvdata(pdev, dev);
+
+       /* Bind all our sub-components: */
+       ret = component_bind_all(dev->dev, dev);
+       if (ret)
+               return ret;
+
        switch (get_mdp_ver(pdev)) {
        case 4:
                kms = mdp4_kms_init(dev);
@@ -281,8 +295,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
                goto fail;
        }
 
-       platform_set_drvdata(pdev, dev);
-
 #ifdef CONFIG_DRM_MSM_FBDEV
        priv->fbdev = msm_fbdev_init(dev);
 #endif
@@ -818,6 +830,98 @@ static const struct dev_pm_ops msm_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(msm_pm_suspend, msm_pm_resume)
 };
 
+/*
+ * Componentized driver support:
+ */
+
+#ifdef CONFIG_OF
+/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx
+ * (or probably any other).. so probably some room for some helpers
+ */
+static int compare_of(struct device *dev, void *data)
+{
+       return dev->of_node == data;
+}
+
+static int msm_drm_add_components(struct device *master, struct master *m)
+{
+       struct device_node *np = master->of_node;
+       unsigned i;
+       int ret;
+
+       for (i = 0; ; i++) {
+               struct device_node *node;
+
+               node = of_parse_phandle(np, "connectors", i);
+               if (!node)
+                       break;
+
+               ret = component_master_add_child(m, compare_of, node);
+               of_node_put(node);
+
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+#else
+static int compare_dev(struct device *dev, void *data)
+{
+       return dev == data;
+}
+
+static int msm_drm_add_components(struct device *master, struct master *m)
+{
+       /* For non-DT case, it kinda sucks.  We don't actually have a way
+        * to know whether or not we are waiting for certain devices (or if
+        * they are simply not present).  But for non-DT we only need to
+        * care about apq8064/apq8060/etc (all mdp4/a3xx):
+        */
+       static const char *devnames[] = {
+                       "hdmi_msm.0", "kgsl-3d0.0",
+       };
+       int i;
+
+       DBG("Adding components..");
+
+       for (i = 0; i < ARRAY_SIZE(devnames); i++) {
+               struct device *dev;
+               int ret;
+
+               dev = bus_find_device_by_name(&platform_bus_type,
+                               NULL, devnames[i]);
+               if (!dev) {
+                       dev_info(master, "still waiting for %s\n", devnames[i]);
+                       return -EPROBE_DEFER;
+               }
+
+               ret = component_master_add_child(m, compare_dev, dev);
+               if (ret) {
+                       DBG("could not add child: %d", ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+#endif
+
+static int msm_drm_bind(struct device *dev)
+{
+       return drm_platform_init(&msm_driver, to_platform_device(dev));
+}
+
+static void msm_drm_unbind(struct device *dev)
+{
+       drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
+}
+
+static const struct component_master_ops msm_drm_ops = {
+               .add_components = msm_drm_add_components,
+               .bind = msm_drm_bind,
+               .unbind = msm_drm_unbind,
+};
+
 /*
  * Platform driver:
  */
@@ -825,12 +929,12 @@ static const struct dev_pm_ops msm_pm_ops = {
 static int msm_pdev_probe(struct platform_device *pdev)
 {
        pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       return drm_platform_init(&msm_driver, pdev);
+       return component_master_add(&pdev->dev, &msm_drm_ops);
 }
 
 static int msm_pdev_remove(struct platform_device *pdev)
 {
-       drm_put_dev(platform_get_drvdata(pdev));
+       component_master_del(&pdev->dev, &msm_drm_ops);
 
        return 0;
 }
index 3d63269c5b29c51e69bc0dfe7714dddae71e4fee..9d10ee0b5aacf9d234de220e93a49fbea786a503 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/clk.h>
 #include <linux/cpufreq.h>
 #include <linux/module.h>
+#include <linux/component.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
@@ -69,6 +70,9 @@ struct msm_drm_private {
 
        struct msm_kms *kms;
 
+       /* subordinate devices, if present: */
+       struct platform_device *hdmi_pdev, *gpu_pdev;
+
        /* when we have more than one 'msm_gpu' these need to be an array: */
        struct msm_gpu *gpu;
        struct msm_file_private *lastctx;
index 5727622887038de03ba45e9119af06644146d5c0..5fe238bd6c4e4ce8793ea269316f286ac870fa84 100644 (file)
@@ -646,6 +646,11 @@ static void set_enabled(struct drm_crtc *crtc, bool enable)
        u32 framedone_irq, vsync_irq;
        int ret;
 
+       if (omap_crtc->mgr->output->output_type == OMAP_DISPLAY_TYPE_HDMI) {
+               dispc_mgr_enable(channel, enable);
+               return;
+       }
+
        if (dispc_mgr_is_enabled(channel) == enable)
                return;
 
index 9f32a83ca5078a587fccda89947f2dd9a05be83d..bb8529a82571bdc02bacf8c7e3bd4ef223998806 100644 (file)
@@ -155,10 +155,12 @@ struct refill_engine {
 
 struct dmm_platform_data {
        uint32_t cpu_cache_flags;
+       bool errata_i878_wa;
 };
 
 struct dmm {
        struct device *dev;
+       u32 phys_base;
        void __iomem *base;
        int irq;
 
@@ -189,6 +191,12 @@ struct dmm {
        struct list_head alloc_head;
 
        const struct dmm_platform_data *plat_data;
+
+       bool dmm_workaround;
+       spinlock_t wa_lock;
+       u32 *wa_dma_data;
+       dma_addr_t wa_dma_handle;
+       int wa_dma_channel;
 };
 
 #endif
index ccf1bf06ceb7cb27867246559645ca1a5f2d93f1..c231a9939eaeb8d8b48c74848718a02e4a11e87b 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/time.h>
 #include <linux/list.h>
 #include <linux/completion.h>
+#include <linux/omap-dma.h>
 
 #include "omap_dmm_tiler.h"
 #include "omap_dmm_priv.h"
@@ -78,6 +79,130 @@ static const uint32_t reg[][4] = {
                                DMM_PAT_DESCR__2, DMM_PAT_DESCR__3},
 };
 
+static int dmm_dma_copy(struct dmm *dmm, u32 src, u32 dst)
+{
+       int count;
+
+       omap_set_dma_src_params(dmm->wa_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, src, 0, 0);
+       omap_set_dma_dest_params(dmm->wa_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, dst, 0, 0);
+
+       omap_start_dma(dmm->wa_dma_channel);
+
+       /* we only copy 4 bytes, so use polling. usually one loop is enough */
+       for (count = 100; count > 0; --count) {
+               if (omap_get_dma_active_status(dmm->wa_dma_channel) == 0)
+                       break;
+       }
+
+       if (count == 0) {
+               omap_stop_dma(dmm->wa_dma_channel);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static u32 dmm_read_wa(struct dmm *dmm, u32 reg)
+{
+       u32 src, dst;
+       int r;
+
+       src = (u32)(dmm->phys_base + reg);
+       dst = (u32)dmm->wa_dma_handle;
+
+       r = dmm_dma_copy(dmm, src, dst);
+       if (r) {
+               dev_err(dmm->dev, "sDMA read transfer timeout\n");
+               return readl(dmm->base + reg);
+       }
+
+       return readl(dmm->wa_dma_data);
+}
+
+static void dmm_write_wa(struct dmm *dmm, u32 val, u32 reg)
+{
+       u32 src, dst;
+       int r;
+
+       writel(val, dmm->wa_dma_data);
+
+       src = (u32)dmm->wa_dma_handle;
+       dst = (u32)(dmm->phys_base + reg);
+
+       r = dmm_dma_copy(dmm, src, dst);
+       if (r) {
+               dev_err(dmm->dev, "sDMA write transfer timeout\n");
+               writel(val, dmm->base + reg);
+       }
+}
+
+static u32 dmm_read(struct dmm *dmm, u32 reg)
+{
+       if (dmm->dmm_workaround) {
+               u32 v;
+               unsigned long flags;
+
+               spin_lock_irqsave(&dmm->wa_lock, flags);
+               v = dmm_read_wa(dmm, reg);
+               spin_unlock_irqrestore(&dmm->wa_lock, flags);
+
+               return v;
+       } else {
+               return readl(dmm->base + reg);
+       }
+}
+
+static void dmm_write(struct dmm *dmm, u32 val, u32 reg)
+{
+       if (dmm->dmm_workaround) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&dmm->wa_lock, flags);
+               dmm_write_wa(dmm, val, reg);
+               spin_unlock_irqrestore(&dmm->wa_lock, flags);
+       } else {
+               writel(val, dmm->base + reg);
+       }
+}
+
+static int dmm_workaround_init(struct dmm *dmm)
+{
+       const int dev_id = 0;
+       const int elem_count = 1;
+       const int frame_count = 1;
+       int r;
+
+       spin_lock_init(&dmm->wa_lock);
+
+       dmm->wa_dma_data = dma_alloc_coherent(dmm->dev, 4, &dmm->wa_dma_handle, GFP_KERNEL);
+       if (!dmm->wa_dma_data)
+               return -ENOMEM;
+
+       r = omap_request_dma(dev_id, "omap_dmm_workaround_dma", NULL, 0,
+               &dmm->wa_dma_channel);
+       if (r < 0) {
+               dma_free_coherent(dmm->dev, 4, dmm->wa_dma_data, dmm->wa_dma_handle);
+               return r;
+       }
+
+       omap_set_dma_transfer_params(dmm->wa_dma_channel, OMAP_DMA_DATA_TYPE_S32,
+                       elem_count, frame_count, OMAP_DMA_SYNC_ELEMENT,
+                       dev_id, 0x0);
+
+       omap_set_dma_src_burst_mode(dmm->wa_dma_channel, OMAP_DMA_DATA_BURST_DIS);
+       omap_set_dma_dest_burst_mode(dmm->wa_dma_channel, OMAP_DMA_DATA_BURST_DIS);
+       omap_set_dma_write_mode(dmm->wa_dma_channel, OMAP_DMA_WRITE_NON_POSTED);
+
+       return 0;
+}
+
+static void dmm_workaround_uninit(struct dmm *dmm)
+{
+       omap_free_dma(dmm->wa_dma_channel);
+
+       dma_free_coherent(dmm->dev, 4, dmm->wa_dma_data, dmm->wa_dma_handle);
+}
+
 /* simple allocator to grab next 16 byte aligned memory from txn */
 static void *alloc_dma(struct dmm_txn *txn, size_t sz, dma_addr_t *pa)
 {
@@ -107,7 +232,7 @@ static int wait_status(struct refill_engine *engine, uint32_t wait_mask)
 
        i = DMM_FIXED_RETRY_COUNT;
        while (true) {
-               r = readl(dmm->base + reg[PAT_STATUS][engine->id]);
+               r = dmm_read(dmm, reg[PAT_STATUS][engine->id]);
                err = r & DMM_PATSTATUS_ERR;
                if (err)
                        return -EFAULT;
@@ -139,11 +264,11 @@ static void release_engine(struct refill_engine *engine)
 static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
 {
        struct dmm *dmm = arg;
-       uint32_t status = readl(dmm->base + DMM_PAT_IRQSTATUS);
+       uint32_t status = dmm_read(dmm, DMM_PAT_IRQSTATUS);
        int i;
 
        /* ack IRQ */
-       writel(status, dmm->base + DMM_PAT_IRQSTATUS);
+       dmm_write(dmm, status, DMM_PAT_IRQSTATUS);
 
        for (i = 0; i < dmm->num_engines; i++) {
                if (status & DMM_IRQSTAT_LST) {
@@ -261,9 +386,20 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
        }
 
        txn->last_pat->next_pa = 0;
+       /* ensure that the written descriptors are visible to DMM */
+       wmb();
+
+       /*
+        * NOTE: the wmb() above should be enough, but there seems to be a bug
+        * in OMAP's memory barrier implementation, which in some rare cases may
+        * cause the writes not to be observable after wmb().
+        */
+
+       /* read back to ensure the data is in RAM */
+       readl(&txn->last_pat->next_pa);
 
        /* write to PAT_DESCR to clear out any pending transaction */
-       writel(0x0, dmm->base + reg[PAT_DESCR][engine->id]);
+       dmm_write(dmm, 0x0, reg[PAT_DESCR][engine->id]);
 
        /* wait for engine ready: */
        ret = wait_status(engine, DMM_PATSTATUS_READY);
@@ -279,12 +415,11 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
        smp_mb();
 
        /* kick reload */
-       writel(engine->refill_pa,
-               dmm->base + reg[PAT_DESCR][engine->id]);
+       dmm_write(dmm, engine->refill_pa, reg[PAT_DESCR][engine->id]);
 
        if (wait) {
                if (!wait_for_completion_timeout(&engine->compl,
-                               msecs_to_jiffies(1))) {
+                               msecs_to_jiffies(100))) {
                        dev_err(dmm->dev, "timed out waiting for done\n");
                        ret = -ETIMEDOUT;
                }
@@ -308,6 +443,12 @@ static int fill(struct tcm_area *area, struct page **pages,
        struct tcm_area slice, area_s;
        struct dmm_txn *txn;
 
+       /*
+        * XXX async wait doesn't work, as it does not handle timeout errors
+        * properly
+        */
+       wait = true;
+
        txn = dmm_txn_init(omap_dmm, area->tcm);
        if (IS_ERR_OR_NULL(txn))
                return -ENOMEM;
@@ -576,6 +717,9 @@ static int omap_dmm_remove(struct platform_device *dev)
                if (omap_dmm->dummy_page)
                        __free_page(omap_dmm->dummy_page);
 
+               if (omap_dmm->dmm_workaround)
+                       dmm_workaround_uninit(omap_dmm);
+
                if (omap_dmm->irq > 0)
                        free_irq(omap_dmm->irq, omap_dmm);
 
@@ -623,6 +767,7 @@ static int omap_dmm_probe(struct platform_device *dev)
                goto fail;
        }
 
+       omap_dmm->phys_base = mem->start;
        omap_dmm->base = ioremap(mem->start, SZ_2K);
 
        if (!omap_dmm->base) {
@@ -638,7 +783,20 @@ static int omap_dmm_probe(struct platform_device *dev)
 
        omap_dmm->dev = &dev->dev;
 
-       hwinfo = readl(omap_dmm->base + DMM_PAT_HWINFO);
+       omap_dmm->dmm_workaround = omap_dmm->plat_data->errata_i878_wa;
+
+       if (omap_dmm->dmm_workaround) {
+               int r;
+               r = dmm_workaround_init(omap_dmm);
+               if (r) {
+                       omap_dmm->dmm_workaround = false;
+                       dev_err(&dev->dev, "failed to initialize work-around, WA not used\n");
+               } else {
+                       dev_info(&dev->dev, "workaround for errata i878 in use\n");
+               }
+       }
+
+       hwinfo = dmm_read(omap_dmm, DMM_PAT_HWINFO);
        omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
        omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
        omap_dmm->container_width = 256;
@@ -647,7 +805,7 @@ static int omap_dmm_probe(struct platform_device *dev)
        atomic_set(&omap_dmm->engine_counter, omap_dmm->num_engines);
 
        /* read out actual LUT width and height */
-       pat_geom = readl(omap_dmm->base + DMM_PAT_GEOMETRY);
+       pat_geom = dmm_read(omap_dmm, DMM_PAT_GEOMETRY);
        omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
        omap_dmm->lut_height = ((pat_geom >> 24) & 0xF) << 5;
 
@@ -657,12 +815,12 @@ static int omap_dmm_probe(struct platform_device *dev)
                omap_dmm->num_lut++;
 
        /* initialize DMM registers */
-       writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__0);
-       writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__1);
-       writel(0x80808080, omap_dmm->base + DMM_PAT_VIEW_MAP__0);
-       writel(0x80000000, omap_dmm->base + DMM_PAT_VIEW_MAP_BASE);
-       writel(0x88888888, omap_dmm->base + DMM_TILER_OR__0);
-       writel(0x88888888, omap_dmm->base + DMM_TILER_OR__1);
+       dmm_write(omap_dmm, 0x88888888, DMM_PAT_VIEW__0);
+       dmm_write(omap_dmm, 0x88888888, DMM_PAT_VIEW__1);
+       dmm_write(omap_dmm, 0x80808080, DMM_PAT_VIEW_MAP__0);
+       dmm_write(omap_dmm, 0x80000000, DMM_PAT_VIEW_MAP_BASE);
+       dmm_write(omap_dmm, 0x88888888, DMM_TILER_OR__0);
+       dmm_write(omap_dmm, 0x88888888, DMM_TILER_OR__1);
 
        ret = request_irq(omap_dmm->irq, omap_dmm_irq_handler, IRQF_SHARED,
                                "omap_dmm_irq_handler", omap_dmm);
@@ -680,7 +838,7 @@ static int omap_dmm_probe(struct platform_device *dev)
         * buffers for accelerated pan/scroll) and FILL_DSC<n> which
         * we just generally don't care about.
         */
-       writel(0x7e7e7e7e, omap_dmm->base + DMM_PAT_IRQENABLE_SET);
+       dmm_write(omap_dmm, 0x7e7e7e7e, DMM_PAT_IRQENABLE_SET);
 
        omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
        if (!omap_dmm->dummy_page) {
@@ -1004,6 +1162,11 @@ static const struct dmm_platform_data dmm_omap5_platform_data = {
        .cpu_cache_flags = OMAP_BO_UNCACHED,
 };
 
+static const struct dmm_platform_data dmm_dra7_platform_data = {
+       .cpu_cache_flags = OMAP_BO_UNCACHED,
+       .errata_i878_wa = true,
+};
+
 static const struct of_device_id dmm_of_match[] = {
        {
                .compatible = "ti,omap4-dmm",
@@ -1013,6 +1176,10 @@ static const struct of_device_id dmm_of_match[] = {
                .compatible = "ti,omap5-dmm",
                .data = &dmm_omap5_platform_data,
        },
+       {
+               .compatible = "ti,dra7-dmm",
+               .data = &dmm_dra7_platform_data,
+       },
        {},
 };
 #endif
index 15e4fe5d0d7ba7203f375abf31279ace133063a4..b0efa83e814de70a642f0dd4d22af58b06ed01ff 100644 (file)
@@ -94,11 +94,38 @@ static void omap_disconnect_dssdevs(void)
                dssdev->driver->disconnect(dssdev);
 }
 
+static bool dssdev_with_alias_exists(const char *alias)
+{
+       struct omap_dss_device *dssdev = NULL;
+
+       for_each_dss_dev(dssdev) {
+               if (strcmp(alias, dssdev->alias) == 0) {
+                       omap_dss_put_device(dssdev);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 static int omap_connect_dssdevs(void)
 {
        int r;
        struct omap_dss_device *dssdev = NULL;
        bool no_displays = true;
+       struct device_node *aliases;
+       struct property *pp;
+
+       aliases = of_find_node_by_path("/aliases");
+       if (aliases) {
+               for_each_property_of_node(aliases, pp) {
+                       if (strncmp(pp->name, "display", 7) != 0)
+                               continue;
+
+                       if (dssdev_with_alias_exists(pp->name) == false)
+                               return -EPROBE_DEFER;
+               }
+       }
 
        for_each_dss_dev(dssdev) {
                r = dssdev->driver->connect(dssdev);
index 2ab710a26a79febd46888f46afbdbe090a50999e..526e714b928cf8e65326decb1825adc23efc5029 100644 (file)
@@ -218,7 +218,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
                struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
 struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p);
 int omap_framebuffer_pin(struct drm_framebuffer *fb);
-int omap_framebuffer_unpin(struct drm_framebuffer *fb);
+void omap_framebuffer_unpin(struct drm_framebuffer *fb);
 void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
                struct omap_drm_window *win, struct omap_overlay_info *info);
 struct drm_connector *omap_framebuffer_get_next_connector(
@@ -254,7 +254,7 @@ void omap_gem_dma_sync(struct drm_gem_object *obj,
                enum dma_data_direction dir);
 int omap_gem_get_paddr(struct drm_gem_object *obj,
                dma_addr_t *paddr, bool remap);
-int omap_gem_put_paddr(struct drm_gem_object *obj);
+void omap_gem_put_paddr(struct drm_gem_object *obj);
 int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages,
                bool remap);
 int omap_gem_put_pages(struct drm_gem_object *obj);
index aa3f1b3fd36cb58a922b56b37aa6be9f41a047b9..ab626d8ef3cc65a9aaf0d811e01ad5fd0c37830a 100644 (file)
@@ -290,28 +290,21 @@ fail:
 }
 
 /* unpin, no longer being scanned out: */
-int omap_framebuffer_unpin(struct drm_framebuffer *fb)
+void omap_framebuffer_unpin(struct drm_framebuffer *fb)
 {
        struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
-       int ret, i, n = drm_format_num_planes(fb->pixel_format);
+       int i, n = drm_format_num_planes(fb->pixel_format);
 
        omap_fb->pin_count--;
 
        if (omap_fb->pin_count > 0)
-               return 0;
+               return;
 
        for (i = 0; i < n; i++) {
                struct plane *plane = &omap_fb->planes[i];
-               ret = omap_gem_put_paddr(plane->bo);
-               if (ret)
-                       goto fail;
+               omap_gem_put_paddr(plane->bo);
                plane->paddr = 0;
        }
-
-       return 0;
-
-fail:
-       return ret;
 }
 
 struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p)
index eaff3b23cb50e6c2aed4580bea1e05ea8d8bbbea..bc9b0e13eee971347a34a66f994d83f4b670bf03 100644 (file)
@@ -813,10 +813,10 @@ fail:
 /* Release physical address, when DMA is no longer being performed.. this
  * could potentially unpin and unmap buffers from TILER
  */
-int omap_gem_put_paddr(struct drm_gem_object *obj)
+void omap_gem_put_paddr(struct drm_gem_object *obj)
 {
        struct omap_gem_object *omap_obj = to_omap_bo(obj);
-       int ret = 0;
+       int ret;
 
        mutex_lock(&obj->dev->struct_mutex);
        if (omap_obj->paddr_cnt > 0) {
@@ -826,7 +826,6 @@ int omap_gem_put_paddr(struct drm_gem_object *obj)
                        if (ret) {
                                dev_err(obj->dev->dev,
                                        "could not unpin pages: %d\n", ret);
-                               goto fail;
                        }
                        ret = tiler_release(omap_obj->block);
                        if (ret) {
@@ -837,9 +836,8 @@ int omap_gem_put_paddr(struct drm_gem_object *obj)
                        omap_obj->block = NULL;
                }
        }
-fail:
+
        mutex_unlock(&obj->dev->struct_mutex);
-       return ret;
 }
 
 /* Get rotated scanout address (only valid if already pinned), at the
@@ -1398,9 +1396,17 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
                 */
                omap_obj->vaddr =  dma_alloc_writecombine(dev->dev, size,
                                &omap_obj->paddr, GFP_KERNEL);
-               if (omap_obj->vaddr)
-                       flags |= OMAP_BO_DMA;
+               if (!omap_obj->vaddr) {
+                       spin_lock(&priv->list_lock);
+                       list_del(&omap_obj->mm_list);
+                       spin_unlock(&priv->list_lock);
+
+                       kfree(omap_obj);
+
+                       return NULL;
+               }
 
+               flags |= OMAP_BO_DMA;
        }
 
        omap_obj->flags = flags;
index e67873daa9d7817621494a6b0047d59a816354a0..bbab4fb23b643e873c78d39eed510ffa6152e27f 100644 (file)
@@ -131,7 +131,9 @@ static void omap_plane_pre_apply(struct omap_drm_apply *apply)
        DBG("%s, enabled=%d", omap_plane->name, enabled);
 
        /* if fb has changed, pin new fb: */
-       update_pin(plane, enabled ? plane->fb : NULL);
+       ret = update_pin(plane, enabled ? plane->fb : NULL);
+       if (ret)
+               enabled = false;
 
        if (!enabled) {
                dispc_ovl_enable(omap_plane->id, false);
@@ -209,6 +211,13 @@ int omap_plane_mode_set(struct drm_plane *plane,
        struct omap_plane *omap_plane = to_omap_plane(plane);
        struct omap_drm_window *win = &omap_plane->win;
        int i;
+       struct drm_display_mode *mode = &crtc->mode;
+
+       if (crtc_x >= mode->hdisplay || crtc_y >= mode->vdisplay)
+               return -EINVAL;
+
+       if (crtc_x + crtc_w > mode->hdisplay || crtc_y + crtc_h > mode->vdisplay)
+               return -EINVAL;
 
        /*
         * Check whether this plane supports the fb pixel format.
@@ -262,12 +271,12 @@ static int omap_plane_update(struct drm_plane *plane,
                uint32_t src_w, uint32_t src_h)
 {
        struct omap_plane *omap_plane = to_omap_plane(plane);
-       omap_plane->enabled = true;
+       struct drm_framebuffer *old_fb;
+       int r;
 
-       if (plane->fb)
-               drm_framebuffer_unreference(plane->fb);
+       omap_plane->enabled = true;
 
-       drm_framebuffer_reference(fb);
+       old_fb = plane->fb;
 
        /* omap_plane_mode_set() takes adjusted src */
        switch (omap_plane->win.rotation & 0xf) {
@@ -277,10 +286,21 @@ static int omap_plane_update(struct drm_plane *plane,
                break;
        }
 
-       return omap_plane_mode_set(plane, crtc, fb,
+       r = omap_plane_mode_set(plane, crtc, fb,
                        crtc_x, crtc_y, crtc_w, crtc_h,
                        src_x, src_y, src_w, src_h,
                        NULL, NULL);
+       if (r)
+               return r;
+
+       /* if new fb was set ok, unref the old fb and ref the new one */
+
+       if (old_fb)
+               drm_framebuffer_unreference(old_fb);
+
+       drm_framebuffer_reference(fb);
+
+       return 0;
 }
 
 static int omap_plane_disable(struct drm_plane *plane)
index 0cca5f24196af8db660d0b584497c166c0ead0e5..0db3e208f02ab2ab6bf3e86859e915852a7f1d9f 100644 (file)
@@ -330,8 +330,10 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
                misc |= ATOM_COMPOSITESYNC;
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                misc |= ATOM_INTERLACE;
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
                misc |= ATOM_DOUBLE_CLOCK_MODE;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
 
        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
        args.ucCRTC = radeon_crtc->crtc_id;
@@ -374,8 +376,10 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
                misc |= ATOM_COMPOSITESYNC;
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                misc |= ATOM_INTERLACE;
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
                misc |= ATOM_DOUBLE_CLOCK_MODE;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
 
        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
        args.ucCRTC = radeon_crtc->crtc_id;
@@ -1306,6 +1310,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
               (x << 16) | y);
        viewport_w = crtc->mode.hdisplay;
        viewport_h = (crtc->mode.vdisplay + 1) & ~1;
+       if ((rdev->family >= CHIP_BONAIRE) &&
+           (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE))
+               viewport_h *= 2;
        WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
               (viewport_w << 16) | viewport_h);
 
index 8ef67cb4ef1ece1153950b9281fcc5410043188f..c3664bc05acf78bb3b126c95aaeac8f7df5d6df0 100644 (file)
@@ -3558,7 +3558,21 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev,
        struct radeon_ring *ring = &rdev->ring[fence->ring];
        u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
 
-       /* EVENT_WRITE_EOP - flush caches, send int */
+       /* Workaround for cache flush problems. First send a dummy EOP
+        * event down the pipe with seq one below.
+        */
+       radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
+       radeon_ring_write(ring, (EOP_TCL1_ACTION_EN |
+                                EOP_TC_ACTION_EN |
+                                EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
+                                EVENT_INDEX(5)));
+       radeon_ring_write(ring, addr & 0xfffffffc);
+       radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
+                               DATA_SEL(1) | INT_SEL(0));
+       radeon_ring_write(ring, fence->seq - 1);
+       radeon_ring_write(ring, 0);
+
+       /* Then send the real EOP event down the pipe. */
        radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
        radeon_ring_write(ring, (EOP_TCL1_ACTION_EN |
                                 EOP_TC_ACTION_EN |
@@ -6809,7 +6823,6 @@ int cik_irq_set(struct radeon_device *rdev)
        u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;
        u32 grbm_int_cntl = 0;
        u32 dma_cntl, dma_cntl1;
-       u32 thermal_int;
 
        if (!rdev->irq.installed) {
                WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
@@ -6846,13 +6859,6 @@ int cik_irq_set(struct radeon_device *rdev)
        cp_m2p2 = RREG32(CP_ME2_PIPE2_INT_CNTL) & ~TIME_STAMP_INT_ENABLE;
        cp_m2p3 = RREG32(CP_ME2_PIPE3_INT_CNTL) & ~TIME_STAMP_INT_ENABLE;
 
-       if (rdev->flags & RADEON_IS_IGP)
-               thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL) &
-                       ~(THERM_INTH_MASK | THERM_INTL_MASK);
-       else
-               thermal_int = RREG32_SMC(CG_THERMAL_INT) &
-                       ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
-
        /* enable CP interrupts on all rings */
        if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
                DRM_DEBUG("cik_irq_set: sw int gfx\n");
@@ -7010,14 +7016,6 @@ int cik_irq_set(struct radeon_device *rdev)
                hpd6 |= DC_HPDx_INT_EN;
        }
 
-       if (rdev->irq.dpm_thermal) {
-               DRM_DEBUG("dpm thermal\n");
-               if (rdev->flags & RADEON_IS_IGP)
-                       thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK;
-               else
-                       thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
-       }
-
        WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
 
        WREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET, dma_cntl);
@@ -7071,10 +7069,8 @@ int cik_irq_set(struct radeon_device *rdev)
        WREG32(DC_HPD5_INT_CONTROL, hpd5);
        WREG32(DC_HPD6_INT_CONTROL, hpd6);
 
-       if (rdev->flags & RADEON_IS_IGP)
-               WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int);
-       else
-               WREG32_SMC(CG_THERMAL_INT, thermal_int);
+       /* posting read */
+       RREG32(SRBM_STATUS);
 
        return 0;
 }
index 7138f3e31b7c01ad40ba22b6d1ace9270a606d73..ee9f0b4e90d6c7290379eab004f776d86a0ec66f 100644 (file)
@@ -4596,6 +4596,9 @@ int evergreen_irq_set(struct radeon_device *rdev)
        WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5);
        WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6);
 
+       /* posting read */
+       RREG32(SRBM_STATUS);
+
        return 0;
 }
 
index 351db361239db1d2800f845b2e9e9d02d541cc2b..c7c7bc5d573ff1a3b56b61f55980590646776dfd 100644 (file)
@@ -1121,6 +1121,19 @@ void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
        }
 }
 
+static void kv_enable_thermal_int(struct radeon_device *rdev, bool enable)
+{
+       u32 thermal_int;
+
+       thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL);
+       if (enable)
+               thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK;
+       else
+               thermal_int &= ~(THERM_INTH_MASK | THERM_INTL_MASK);
+       WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int);
+
+}
+
 int kv_dpm_enable(struct radeon_device *rdev)
 {
        struct kv_power_info *pi = kv_get_pi(rdev);
@@ -1232,8 +1245,7 @@ int kv_dpm_late_enable(struct radeon_device *rdev)
                        DRM_ERROR("kv_set_thermal_temperature_range failed\n");
                        return ret;
                }
-               rdev->irq.dpm_thermal = true;
-               radeon_irq_set(rdev);
+               kv_enable_thermal_int(rdev, true);
        }
 
        /* powerdown unused blocks for now */
@@ -1261,6 +1273,7 @@ void kv_dpm_disable(struct radeon_device *rdev)
        kv_stop_dpm(rdev);
        kv_enable_ulv(rdev, false);
        kv_reset_am(rdev);
+       kv_enable_thermal_int(rdev, false);
 
        kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
 }
index bf6300cfd62d0799deaefbd698027cf8d811dbc6..f8c01b8d15948e557a209db423b6295dbfb06a68 100644 (file)
@@ -1073,12 +1073,12 @@ static void cayman_gpu_init(struct radeon_device *rdev)
 
        if ((rdev->config.cayman.max_backends_per_se == 1) &&
            (rdev->flags & RADEON_IS_IGP)) {
-               if ((disabled_rb_mask & 3) == 1) {
-                       /* RB0 disabled, RB1 enabled */
-                       tmp = 0x11111111;
-               } else {
+               if ((disabled_rb_mask & 3) == 2) {
                        /* RB1 disabled, RB0 enabled */
                        tmp = 0x00000000;
+               } else {
+                       /* RB0 disabled, RB1 enabled */
+                       tmp = 0x11111111;
                }
        } else {
                tmp = gb_addr_config & NUM_PIPES_MASK;
index 07620e198a6d91d53d27efaf63f5c55f3a12aafb..e28de20d469ad783159c86916fa3131a7eb32087 100644 (file)
@@ -742,6 +742,10 @@ int r100_irq_set(struct radeon_device *rdev)
                tmp |= RADEON_FP2_DETECT_MASK;
        }
        WREG32(RADEON_GEN_INT_CNTL, tmp);
+
+       /* read back to post the write */
+       RREG32(RADEON_GEN_INT_CNTL);
+
        return 0;
 }
 
index 788f602e8989f86dd19c8af8806d28b02dbddf3a..74a8a38db4d5390fc0c1add6613b6ff76b473ce1 100644 (file)
@@ -3647,6 +3647,9 @@ int r600_irq_set(struct radeon_device *rdev)
                WREG32(RV770_CG_THERMAL_INT, thermal_int);
        }
 
+       /* posting read */
+       RREG32(R_000E50_SRBM_STATUS);
+
        return 0;
 }
 
index 3334f916945bc1c11b235a3355ff538f7f461bdb..e98108236e04461d2ee0d3581c95db237975298c 100644 (file)
@@ -187,7 +187,7 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                        radeon_crtc = to_radeon_crtc(crtc);
                        if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
-                               vrefresh = radeon_crtc->hw_mode.vrefresh;
+                               vrefresh = drm_mode_vrefresh(&radeon_crtc->hw_mode);
                                break;
                        }
                }
index 64d6cfba99525f3f39e8ec87f62f37e863de1513..d625a14ec038cfe24d0a6704fb500e1ec6d93497 100644 (file)
@@ -1173,7 +1173,7 @@ static struct radeon_asic rs780_asic = {
 static struct radeon_asic_ring rv770_uvd_ring = {
        .ib_execute = &uvd_v1_0_ib_execute,
        .emit_fence = &uvd_v2_2_fence_emit,
-       .emit_semaphore = &uvd_v1_0_semaphore_emit,
+       .emit_semaphore = &uvd_v2_2_semaphore_emit,
        .cs_parse = &radeon_uvd_cs_parse,
        .ring_test = &uvd_v1_0_ring_test,
        .ib_test = &uvd_v1_0_ib_test,
index ae637cfda783285a0f2638435e6620c6026fb534..f6e19edb116635e4d76e89ba04460892c04a161d 100644 (file)
@@ -853,6 +853,10 @@ void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int uvd_v2_2_resume(struct radeon_device *rdev);
 void uvd_v2_2_fence_emit(struct radeon_device *rdev,
                         struct radeon_fence *fence);
+bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev,
+                            struct radeon_ring *ring,
+                            struct radeon_semaphore *semaphore,
+                            bool emit_wait);
 
 /* uvd v3.1 */
 bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
index e2de749327ad19b46272010c0709dea7ba1f2841..2fa3cf615a6795dbb35b221a3e143c96d2ae8208 100644 (file)
@@ -3272,6 +3272,7 @@ int radeon_atom_get_voltage_evv(struct radeon_device *rdev,
 
        args.in.ucVoltageType = VOLTAGE_TYPE_VDDC;
        args.in.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE;
+       args.in.usVoltageLevel = cpu_to_le16(virtual_voltage_id);
        args.in.ulSCLKFreq =
                cpu_to_le32(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk);
 
index 9ab30976287d4c27e0dc94e0cadfa993e6ec77cc..c43335ce8778620666b35cddf6e2f5a71c8dbc82 100644 (file)
@@ -76,7 +76,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
 
 static bool radeon_read_bios(struct radeon_device *rdev)
 {
-       uint8_t __iomem *bios;
+       uint8_t __iomem *bios, val1, val2;
        size_t size;
 
        rdev->bios = NULL;
@@ -86,15 +86,19 @@ static bool radeon_read_bios(struct radeon_device *rdev)
                return false;
        }
 
-       if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+       val1 = readb(&bios[0]);
+       val2 = readb(&bios[1]);
+
+       if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
                pci_unmap_rom(rdev->pdev, bios);
                return false;
        }
-       rdev->bios = kmemdup(bios, size, GFP_KERNEL);
+       rdev->bios = kzalloc(size, GFP_KERNEL);
        if (rdev->bios == NULL) {
                pci_unmap_rom(rdev->pdev, bios);
                return false;
        }
+       memcpy_fromio(rdev->bios, bios, size);
        pci_unmap_rom(rdev->pdev, bios);
        return true;
 }
index 7f2d6c0d11c1f67ba5e170c7bee5db77aebb9204..2f2d2ce347097c6615cd0d6fb1c93f695ba3ff4b 100644 (file)
@@ -179,11 +179,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
        u32 ring = RADEON_CS_RING_GFX;
        s32 priority = 0;
 
+       INIT_LIST_HEAD(&p->validated);
+
        if (!cs->num_chunks) {
                return 0;
        }
+
        /* get chunks */
-       INIT_LIST_HEAD(&p->validated);
        p->idx = 0;
        p->ib.sa_bo = NULL;
        p->ib.semaphore = NULL;
index 414e07928693f25f84fe2ede0db0fe15adea1006..bcfac7624550591f22213454b9733276df362132 100644 (file)
@@ -350,6 +350,29 @@ static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
        return 0;
 }
 
+static int radeon_uvd_validate_codec(struct radeon_cs_parser *p,
+                                    unsigned stream_type)
+{
+       switch (stream_type) {
+       case 0: /* H264 */
+       case 1: /* VC1 */
+               /* always supported */
+               return 0;
+
+       case 3: /* MPEG2 */
+       case 4: /* MPEG4 */
+               /* only since UVD 3 */
+               if (p->rdev->family >= CHIP_PALM)
+                       return 0;
+
+               /* fall through */
+       default:
+               DRM_ERROR("UVD codec not supported by hardware %d!\n",
+                         stream_type);
+               return -EINVAL;
+       }
+}
+
 static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
                             unsigned offset, unsigned buf_sizes[])
 {
@@ -388,50 +411,70 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
                return -EINVAL;
        }
 
-       if (msg_type == 1) {
-               /* it's a decode msg, calc buffer sizes */
-               r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
-               /* calc image size (width * height) */
-               img_size = msg[6] * msg[7];
+       switch (msg_type) {
+       case 0:
+               /* it's a create msg, calc image size (width * height) */
+               img_size = msg[7] * msg[8];
+
+               r = radeon_uvd_validate_codec(p, msg[4]);
+               radeon_bo_kunmap(bo);
+               if (r)
+                       return r;
+
+               /* try to alloc a new handle */
+               for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+                       if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
+                               DRM_ERROR("Handle 0x%x already in use!\n", handle);
+                               return -EINVAL;
+                       }
+
+                       if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
+                               p->rdev->uvd.filp[i] = p->filp;
+                               p->rdev->uvd.img_size[i] = img_size;
+                               return 0;
+                       }
+               }
+
+               DRM_ERROR("No more free UVD handles!\n");
+               return -EINVAL;
+
+       case 1:
+               /* it's a decode msg, validate codec and calc buffer sizes */
+               r = radeon_uvd_validate_codec(p, msg[4]);
+               if (!r)
+                       r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
                radeon_bo_kunmap(bo);
                if (r)
                        return r;
 
-       } else if (msg_type == 2) {
+               /* validate the handle */
+               for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+                       if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
+                               if (p->rdev->uvd.filp[i] != p->filp) {
+                                       DRM_ERROR("UVD handle collision detected!\n");
+                                       return -EINVAL;
+                               }
+                               return 0;
+                       }
+               }
+
+               DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);
+               return -ENOENT;
+
+       case 2:
                /* it's a destroy msg, free the handle */
                for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
                        atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
                radeon_bo_kunmap(bo);
                return 0;
-       } else {
-               /* it's a create msg, calc image size (width * height) */
-               img_size = msg[7] * msg[8];
-               radeon_bo_kunmap(bo);
 
-               if (msg_type != 0) {
-                       DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
-                       return -EINVAL;
-               }
-
-               /* it's a create msg, no special handling needed */
-       }
-
-       /* create or decode, validate the handle */
-       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
-               if (atomic_read(&p->rdev->uvd.handles[i]) == handle)
-                       return 0;
-       }
+       default:
 
-       /* handle not found try to alloc a new one */
-       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
-               if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
-                       p->rdev->uvd.filp[i] = p->filp;
-                       p->rdev->uvd.img_size[i] = img_size;
-                       return 0;
-               }
+               DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
+               return -EINVAL;
        }
 
-       DRM_ERROR("No more free UVD handles!\n");
+       BUG();
        return -EINVAL;
 }
 
index e5619d5e2a303ff913ff0b41d60f05bbd5ccc10a..4261b3865cb06febffd60397c44592d48d4fadd6 100644 (file)
@@ -700,6 +700,10 @@ int rs600_irq_set(struct radeon_device *rdev)
        WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
        if (ASIC_IS_DCE2(rdev))
                WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
+
+       /* posting read */
+       RREG32(R_000040_GEN_INT_CNTL);
+
        return 0;
 }
 
index 3cf1e2921545f9a980569925088d720e347505d1..9ef2064b1c9cdfc0392c6154258366387a1bf95a 100644 (file)
                         ((n) & 0x3FFF) << 16)
 
 /* UVD */
+#define UVD_SEMA_ADDR_LOW                              0xef00
+#define UVD_SEMA_ADDR_HIGH                             0xef04
+#define UVD_SEMA_CMD                                   0xef08
 #define UVD_GPCOM_VCPU_CMD                             0xef0c
 #define UVD_GPCOM_VCPU_DATA0                           0xef10
 #define UVD_GPCOM_VCPU_DATA1                           0xef14
index 52b64ad285d626b85b0528cdc46f5aa436474022..2f2deccb3b781cae5299ce1dc56322c72742b8e0 100644 (file)
@@ -5958,6 +5958,9 @@ int si_irq_set(struct radeon_device *rdev)
 
        WREG32(CG_THERMAL_INT, thermal_int);
 
+       /* posting read */
+       RREG32(SRBM_STATUS);
+
        return 0;
 }
 
@@ -6875,8 +6878,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
        WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
 
        if (!vclk || !dclk) {
-               /* keep the Bypass mode, put PLL to sleep */
-               WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
+               /* keep the Bypass mode */
                return 0;
        }
 
@@ -6892,8 +6894,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
        /* set VCO_MODE to 1 */
        WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK);
 
-       /* toggle UPLL_SLEEP to 1 then back to 0 */
-       WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
+       /* disable sleep mode */
        WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK);
 
        /* deassert UPLL_RESET */
index 35bf2bba69bf429b80cd40847a6e88a5f250e377..11804cc1e11f9af0ea501f34d4cacbc4c1dfaede 100644 (file)
@@ -2913,6 +2913,7 @@ struct si_dpm_quirk {
 static struct si_dpm_quirk si_dpm_quirk_list[] = {
        /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */
        { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
        { 0, 0, 0, 0 },
 };
 
index c310a0aeebb9f90fa46da34c8c88076f42b06813..0fa9009fef64bb8439b6ba04ef2b395c76b1273a 100644 (file)
@@ -365,18 +365,8 @@ bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
                             struct radeon_semaphore *semaphore,
                             bool emit_wait)
 {
-       uint64_t addr = semaphore->gpu_addr;
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
-       radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
-       radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
-
-       radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
-       radeon_ring_write(ring, emit_wait ? 1 : 0);
-
-       return true;
+       /* disable semaphores for UVD V1 hardware */
+       return false;
 }
 
 /**
index d1771004cb52ecee46ae22dc7665bd54adb477b6..19ccb2ae7a5db16079bc8bd46da10660e8197413 100644 (file)
@@ -59,6 +59,35 @@ void uvd_v2_2_fence_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, 2);
 }
 
+/**
+ * uvd_v2_2_semaphore_emit - emit semaphore command
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ * @semaphore: semaphore to emit commands for
+ * @emit_wait: true if we should emit a wait command
+ *
+ * Emit a semaphore command (either wait or signal) to the UVD ring.
+ */
+bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev,
+                            struct radeon_ring *ring,
+                            struct radeon_semaphore *semaphore,
+                            bool emit_wait)
+{
+       uint64_t addr = semaphore->gpu_addr;
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
+       radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
+       radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
+
+       radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
+       radeon_ring_write(ring, emit_wait ? 1 : 0);
+
+       return true;
+}
+
 /**
  * uvd_v2_2_resume - memory controller programming
  *
index cdff621705d9696ff375a5845c4f1eee757a0a01..b68fb182f2544f671d65b56b9f948ee2b5275ca3 100644 (file)
@@ -733,32 +733,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                goto out_err1;
        }
 
-       ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM,
-                            (dev_priv->vram_size >> PAGE_SHIFT));
-       if (unlikely(ret != 0)) {
-               DRM_ERROR("Failed initializing memory manager for VRAM.\n");
-               goto out_err2;
-       }
-
-       dev_priv->has_gmr = true;
-       if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
-           refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR,
-                                        VMW_PL_GMR) != 0) {
-               DRM_INFO("No GMR memory available. "
-                        "Graphics memory resources are very limited.\n");
-               dev_priv->has_gmr = false;
-       }
-
-       if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
-               dev_priv->has_mob = true;
-               if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB,
-                                  VMW_PL_MOB) != 0) {
-                       DRM_INFO("No MOB memory available. "
-                                "3D will be disabled.\n");
-                       dev_priv->has_mob = false;
-               }
-       }
-
        dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start,
                                               dev_priv->mmio_size);
 
@@ -821,6 +795,33 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                goto out_no_fman;
        }
 
+
+       ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM,
+                            (dev_priv->vram_size >> PAGE_SHIFT));
+       if (unlikely(ret != 0)) {
+               DRM_ERROR("Failed initializing memory manager for VRAM.\n");
+               goto out_no_vram;
+       }
+
+       dev_priv->has_gmr = true;
+       if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
+           refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR,
+                                        VMW_PL_GMR) != 0) {
+               DRM_INFO("No GMR memory available. "
+                        "Graphics memory resources are very limited.\n");
+               dev_priv->has_gmr = false;
+       }
+
+       if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
+               dev_priv->has_mob = true;
+               if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB,
+                                  VMW_PL_MOB) != 0) {
+                       DRM_INFO("No MOB memory available. "
+                                "3D will be disabled.\n");
+                       dev_priv->has_mob = false;
+               }
+       }
+
        vmw_kms_save_vga(dev_priv);
 
        /* Start kms and overlay systems, needs fifo. */
@@ -846,6 +847,12 @@ out_no_fifo:
        vmw_kms_close(dev_priv);
 out_no_kms:
        vmw_kms_restore_vga(dev_priv);
+       if (dev_priv->has_mob)
+               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
+       if (dev_priv->has_gmr)
+               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
+       (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
+out_no_vram:
        vmw_fence_manager_takedown(dev_priv->fman);
 out_no_fman:
        if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
@@ -861,12 +868,6 @@ out_err4:
        iounmap(dev_priv->mmio_virt);
 out_err3:
        arch_phys_wc_del(dev_priv->mmio_mtrr);
-       if (dev_priv->has_mob)
-               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
-       if (dev_priv->has_gmr)
-               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
-       (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
-out_err2:
        (void)ttm_bo_device_release(&dev_priv->bdev);
 out_err1:
        vmw_ttm_global_release(dev_priv);
@@ -896,6 +897,13 @@ static int vmw_driver_unload(struct drm_device *dev)
        }
        vmw_kms_close(dev_priv);
        vmw_overlay_close(dev_priv);
+
+       if (dev_priv->has_mob)
+               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
+       if (dev_priv->has_gmr)
+               (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
+       (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
+
        vmw_fence_manager_takedown(dev_priv->fman);
        if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
                drm_irq_uninstall(dev_priv->dev);
@@ -907,11 +915,6 @@ static int vmw_driver_unload(struct drm_device *dev)
        ttm_object_device_release(&dev_priv->tdev);
        iounmap(dev_priv->mmio_virt);
        arch_phys_wc_del(dev_priv->mmio_mtrr);
-       if (dev_priv->has_mob)
-               (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
-       if (dev_priv->has_gmr)
-               (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
-       (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
        (void)ttm_bo_device_release(&dev_priv->bdev);
        vmw_ttm_global_release(dev_priv);
 
index 4b87bb164f301a81e8830af31da2b8c404b5fb6b..a413f76e84d474a4f2de2e9e9e59b3f226d5bff8 100644 (file)
@@ -1066,6 +1066,23 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
                return;
        }
 
+       /*
+        * Ignore reports for absolute data if the data didn't change. This is
+        * not only an optimization but also fixes 'dead' key reports. Some
+        * RollOver implementations for localized keys (like BACKSLASH/PIPE; HID
+        * 0x31 and 0x32) report multiple keys, even though a localized keyboard
+        * can only have one of them physically available. The 'dead' keys
+        * report constant 0. As all map to the same keycode, they'd confuse
+        * the input layer. If we filter the 'dead' keys on the HID level, we
+        * skip the keycode translation and only forward real events.
+        */
+       if (!(field->flags & (HID_MAIN_ITEM_RELATIVE |
+                             HID_MAIN_ITEM_BUFFERED_BYTE)) &&
+                             (field->flags & HID_MAIN_ITEM_VARIABLE) &&
+           usage->usage_index < field->maxusage &&
+           value == field->value[usage->usage_index])
+               return;
+
        /* report the usage code as scancode if the key status has changed */
        if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
                input_event(input, EV_MSC, MSC_SCAN, usage->hid);
index e99e71a6ea59a44e5181b650aaa89156cdb193d2..356f22f90a05fad4cab48a8a4bd72f1e7bf03158 100644 (file)
@@ -134,7 +134,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto error0;
+               goto error_gpadl;
        }
 
        init_completion(&open_info->waitevent);
@@ -150,7 +150,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto error0;
+               goto error_gpadl;
        }
 
        if (userdatalen)
@@ -194,6 +194,9 @@ error1:
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
+error_gpadl:
+       vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
+
 error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
index 505fe29c75b039eea635f4851f8494f8a06fcc9b..8c248818592ed266cc2b43fe4fc3d2b14c0634c3 100644 (file)
@@ -716,7 +716,7 @@ int vmbus_request_offers(void)
 {
        struct vmbus_channel_message_header *msg;
        struct vmbus_channel_msginfo *msginfo;
-       int ret, t;
+       int ret;
 
        msginfo = kmalloc(sizeof(*msginfo) +
                          sizeof(struct vmbus_channel_message_header),
@@ -724,8 +724,6 @@ int vmbus_request_offers(void)
        if (!msginfo)
                return -ENOMEM;
 
-       init_completion(&msginfo->waitevent);
-
        msg = (struct vmbus_channel_message_header *)msginfo->msg;
 
        msg->msgtype = CHANNELMSG_REQUESTOFFERS;
@@ -739,14 +737,6 @@ int vmbus_request_offers(void)
                goto cleanup;
        }
 
-       t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
-       if (t == 0) {
-               ret = -ETIMEDOUT;
-               goto cleanup;
-       }
-
-
-
 cleanup:
        kfree(msginfo);
 
index 5fb80b8962a2ad7d8e78dcee01df68cb639d3602..43fe15a0e5cc8486f544eadfa4b968c737a24e26 100644 (file)
@@ -217,6 +217,7 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
        adap->bus_recovery_info->set_scl(adap, 1);
        return i2c_generic_recovery(adap);
 }
+EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery);
 
 int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
 {
@@ -231,6 +232,7 @@ int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(i2c_generic_gpio_recovery);
 
 int i2c_recover_bus(struct i2c_adapter *adap)
 {
@@ -240,6 +242,7 @@ int i2c_recover_bus(struct i2c_adapter *adap)
        dev_dbg(&adap->dev, "Trying i2c bus recovery\n");
        return adap->bus_recovery_info->recover_bus(adap);
 }
+EXPORT_SYMBOL_GPL(i2c_recover_bus);
 
 static int i2c_device_probe(struct device *dev)
 {
index 47dcb34ff44c47f6317a62c99e025df6eb6b27f6..3a615f3b5d80cbeac7bec24a2c092658b61fea8b 100644 (file)
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
        }
 
-/* LSB is in nV to eliminate floating point */
-static const u32 rates_to_lsb[] = {1000000, 250000, 62500, 15625};
-
-/*
- *  scales calculated as:
- *  rates_to_lsb[sample_rate] / (1 << pga);
- *  pga is 1 for 0, 2
- */
-
 static const int mcp3422_scales[4][4] = {
-       { 1000000, 250000, 62500, 15625 },
-       { 500000 , 125000, 31250, 7812 },
-       { 250000 , 62500 , 15625, 3906 },
-       { 125000 , 31250 , 7812 , 1953 } };
+       { 1000000, 500000, 250000, 125000 },
+       { 250000 , 125000, 62500 , 31250  },
+       { 62500  , 31250 , 15625 , 7812   },
+       { 15625  , 7812  , 3906  , 1953   } };
 
 /* Constant msleep times for data acquisitions */
 static const int mcp3422_read_times[4] = {
index 17aca4d9bd06e5a6f52d51ecc867bb54890ab62f..861ba3d601639e5e758d46b94b27b786f79305e8 100644 (file)
@@ -322,7 +322,7 @@ static int ad5686_probe(struct spi_device *spi)
        st = iio_priv(indio_dev);
        spi_set_drvdata(spi, indio_dev);
 
-       st->reg = devm_regulator_get(&spi->dev, "vcc");
+       st->reg = devm_regulator_get_optional(&spi->dev, "vcc");
        if (!IS_ERR(st->reg)) {
                ret = regulator_enable(st->reg);
                if (ret)
index 7c582f7ae34e15885dc075515de60a2a81be30b3..70753bf23a868ddec1ea559f1bf56847d313d142 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/debugfs.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -447,7 +448,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                mutex_unlock(&indio_dev->mlock);
                if (ret)
                        return ret;
-               val16 = ((val16 & 0xFFF) << 4) >> 4;
+               val16 = sign_extend32(val16, 11);
                *val = val16;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
index e0017c22bb9c6ce3b4f4f9c753a8ce1364621b19..f53e9a803a0e1ec1589a5b0ad25d7aa1f8d54e70 100644 (file)
@@ -60,7 +60,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
        iio_trigger_set_drvdata(adis->trig, adis);
        ret = iio_trigger_register(adis->trig);
 
-       indio_dev->trig = adis->trig;
+       indio_dev->trig = iio_trigger_get(adis->trig);
        if (ret)
                goto error_free_irq;
 
index 429517117eff43d92b86238a284635c8b3b4b8f9..30fce6723e617f37d0733377381d4861c10a2fab 100644 (file)
 #include <linux/poll.h>
 #include "inv_mpu_iio.h"
 
+static void inv_clear_kfifo(struct inv_mpu6050_state *st)
+{
+       unsigned long flags;
+
+       /* take the spin lock sem to avoid interrupt kick in */
+       spin_lock_irqsave(&st->time_stamp_lock, flags);
+       kfifo_reset(&st->timestamps);
+       spin_unlock_irqrestore(&st->time_stamp_lock, flags);
+}
+
 int inv_reset_fifo(struct iio_dev *indio_dev)
 {
        int result;
@@ -51,6 +61,10 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
                                        INV_MPU6050_BIT_FIFO_RST);
        if (result)
                goto reset_fifo_fail;
+
+       /* clear timestamps fifo */
+       inv_clear_kfifo(st);
+
        /* enable interrupt */
        if (st->chip_config.accl_fifo_enable ||
            st->chip_config.gyro_fifo_enable) {
@@ -84,16 +98,6 @@ reset_fifo_fail:
        return result;
 }
 
-static void inv_clear_kfifo(struct inv_mpu6050_state *st)
-{
-       unsigned long flags;
-
-       /* take the spin lock sem to avoid interrupt kick in */
-       spin_lock_irqsave(&st->time_stamp_lock, flags);
-       kfifo_reset(&st->timestamps);
-       spin_unlock_irqrestore(&st->time_stamp_lock, flags);
-}
-
 /**
  * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
  */
@@ -185,7 +189,6 @@ end_session:
 flush_fifo:
        /* Flush HW and SW FIFOs. */
        inv_reset_fifo(indio_dev);
-       inv_clear_kfifo(st);
        mutex_unlock(&indio_dev->mlock);
        iio_trigger_notify_done(indio_dev->trig);
 
index 42c3058e6e9cdbaa406cf682c4c6bb2b064591bd..dbd7d66977c9c0b228437da30612c13640b758b1 100644 (file)
@@ -859,19 +859,27 @@ static void cma_save_ib_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id
        memcpy(&ib->sib_addr, &path->dgid, 16);
 }
 
+static __be16 ss_get_port(const struct sockaddr_storage *ss)
+{
+       if (ss->ss_family == AF_INET)
+               return ((struct sockaddr_in *)ss)->sin_port;
+       else if (ss->ss_family == AF_INET6)
+               return ((struct sockaddr_in6 *)ss)->sin6_port;
+       BUG();
+}
+
 static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id,
                              struct cma_hdr *hdr)
 {
-       struct sockaddr_in *listen4, *ip4;
+       struct sockaddr_in *ip4;
 
-       listen4 = (struct sockaddr_in *) &listen_id->route.addr.src_addr;
        ip4 = (struct sockaddr_in *) &id->route.addr.src_addr;
-       ip4->sin_family = listen4->sin_family;
+       ip4->sin_family = AF_INET;
        ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr;
-       ip4->sin_port = listen4->sin_port;
+       ip4->sin_port = ss_get_port(&listen_id->route.addr.src_addr);
 
        ip4 = (struct sockaddr_in *) &id->route.addr.dst_addr;
-       ip4->sin_family = listen4->sin_family;
+       ip4->sin_family = AF_INET;
        ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr;
        ip4->sin_port = hdr->port;
 }
@@ -879,16 +887,15 @@ static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_i
 static void cma_save_ip6_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id,
                              struct cma_hdr *hdr)
 {
-       struct sockaddr_in6 *listen6, *ip6;
+       struct sockaddr_in6 *ip6;
 
-       listen6 = (struct sockaddr_in6 *) &listen_id->route.addr.src_addr;
        ip6 = (struct sockaddr_in6 *) &id->route.addr.src_addr;
-       ip6->sin6_family = listen6->sin6_family;
+       ip6->sin6_family = AF_INET6;
        ip6->sin6_addr = hdr->dst_addr.ip6;
-       ip6->sin6_port = listen6->sin6_port;
+       ip6->sin6_port = ss_get_port(&listen_id->route.addr.src_addr);
 
        ip6 = (struct sockaddr_in6 *) &id->route.addr.dst_addr;
-       ip6->sin6_family = listen6->sin6_family;
+       ip6->sin6_family = AF_INET6;
        ip6->sin6_addr = hdr->src_addr.ip6;
        ip6->sin6_port = hdr->port;
 }
index 56a4b7ca7ee38ba118796d6d5e3eb770bbebc69a..45d67e9228d75b44d71354d248cf97140dfe37ad 100644 (file)
@@ -1124,6 +1124,9 @@ static int ucma_set_ib_path(struct ucma_context *ctx,
        if (!optlen)
                return -EINVAL;
 
+       memset(&sa_path, 0, sizeof(sa_path));
+       sa_path.vlan_id = 0xffff;
+
        ib_sa_unpack_path(path_data->path_rec, &sa_path);
        ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1);
        if (ret)
index a84112322071015a78b7916bfe70250284f1640e..c1fef27010d45203ef0f87334227ef7535b5d345 100644 (file)
@@ -94,6 +94,17 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
        if (dmasync)
                dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
 
+       if (!size)
+               return ERR_PTR(-EINVAL);
+
+       /*
+        * If the combination of the addr and size requested for this memory
+        * region causes an integer overflow, return error.
+        */
+       if (((addr + size) < addr) ||
+           PAGE_ALIGN(addr + size) < (addr + size))
+               return ERR_PTR(-EINVAL);
+
        if (!can_do_mlock())
                return ERR_PTR(-EPERM);
 
index 23467a2abd6281d92b64e15919bbbeadee62ecba..2adc14372b940e9ced3ba340cdcabb8e7e8a563e 100644 (file)
@@ -1964,20 +1964,21 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
        if (qp->real_qp == qp) {
                ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask);
                if (ret)
-                       goto out;
+                       goto release_qp;
                ret = qp->device->modify_qp(qp, attr,
                        modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
        } else {
                ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
        }
 
-       put_qp_read(qp);
-
        if (ret)
-               goto out;
+               goto release_qp;
 
        ret = in_len;
 
+release_qp:
+       put_qp_read(qp);
+
 out:
        kfree(attr);
 
index 08219fb3338b0652f350da1af864b4cfb355ff3c..7a515c867674ead6dc7da6f77a0ec4ed36dcb612 100644 (file)
@@ -476,6 +476,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
 
        entry->desc.async.element    = element;
        entry->desc.async.event_type = event;
+       entry->desc.async.reserved   = 0;
        entry->counter               = counter;
 
        list_add_tail(&entry->list, &file->async_file->event_list);
index f2a3f48107e71e1d53b0abb61757f1f0ba38bb59..2592ab5f21b1bdfc43a866941433b3a2b51bf943 100644 (file)
@@ -64,6 +64,14 @@ enum {
 #define GUID_TBL_BLK_NUM_ENTRIES 8
 #define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES)
 
+/* Counters should be saturate once they reach their maximum value */
+#define ASSIGN_32BIT_COUNTER(counter, value) do {\
+       if ((value) > U32_MAX)                   \
+               counter = cpu_to_be32(U32_MAX); \
+       else                                     \
+               counter = cpu_to_be32(value);    \
+} while (0)
+
 struct mlx4_mad_rcv_buf {
        struct ib_grh grh;
        u8 payload[256];
@@ -730,10 +738,14 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 static void edit_counter(struct mlx4_counter *cnt,
                                        struct ib_pma_portcounters *pma_cnt)
 {
-       pma_cnt->port_xmit_data = cpu_to_be32((be64_to_cpu(cnt->tx_bytes)>>2));
-       pma_cnt->port_rcv_data  = cpu_to_be32((be64_to_cpu(cnt->rx_bytes)>>2));
-       pma_cnt->port_xmit_packets = cpu_to_be32(be64_to_cpu(cnt->tx_frames));
-       pma_cnt->port_rcv_packets  = cpu_to_be32(be64_to_cpu(cnt->rx_frames));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data,
+                            (be64_to_cpu(cnt->tx_bytes) >> 2));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data,
+                            (be64_to_cpu(cnt->rx_bytes) >> 2));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets,
+                            be64_to_cpu(cnt->tx_frames));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets,
+                            be64_to_cpu(cnt->rx_frames));
 }
 
 static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
index 11f0606792bb9c4ecf571aeb1a6f9663e6bd7632..1a3d924744cc64b062001fc167d3edadf94809af 100644 (file)
@@ -1161,8 +1161,7 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
        struct mlx4_ib_qp *mqp = to_mqp(ibqp);
        u64 reg_id;
        struct mlx4_ib_steering *ib_steering = NULL;
-       enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ?
-               MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6;
+       enum mlx4_protocol prot = MLX4_PROT_IB_IPV6;
 
        if (mdev->dev->caps.steering_mode ==
            MLX4_STEERING_MODE_DEVICE_MANAGED) {
@@ -1175,8 +1174,10 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
                                    !!(mqp->flags &
                                       MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
                                    prot, &reg_id);
-       if (err)
+       if (err) {
+               pr_err("multicast attach op failed, err %d\n", err);
                goto err_malloc;
+       }
 
        err = add_gid_entry(ibqp, gid);
        if (err)
@@ -1224,8 +1225,7 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
        struct net_device *ndev;
        struct mlx4_ib_gid_entry *ge;
        u64 reg_id = 0;
-       enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ?
-               MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6;
+       enum mlx4_protocol prot =  MLX4_PROT_IB_IPV6;
 
        if (mdev->dev->caps.steering_mode ==
            MLX4_STEERING_MODE_DEVICE_MANAGED) {
index d8f4d1fe849430ceb40eab47470d5af033884694..8d7cd98c9671a7567eb3921eb637ef746442e4df 100644 (file)
@@ -2274,8 +2274,7 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
 
        memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
 
-       *lso_hdr_sz  = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
-                                  wr->wr.ud.hlen);
+       *lso_hdr_sz  = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen);
        *lso_seg_len = halign;
        return 0;
 }
index 1946101419a31c0c3066c72d90401639a474d3e3..675d3c796b9f44908f7cc6f3d5ad28f8b4218368 100644 (file)
@@ -1080,12 +1080,6 @@ struct qib_devdata {
        /* control high-level access to EEPROM */
        struct mutex eep_lock;
        uint64_t traffic_wds;
-       /* active time is kept in seconds, but logged in hours */
-       atomic_t active_time;
-       /* Below are nominal shadow of EEPROM, new since last EEPROM update */
-       uint8_t eep_st_errs[QIB_EEP_LOG_CNT];
-       uint8_t eep_st_new_errs[QIB_EEP_LOG_CNT];
-       uint16_t eep_hrs;
        /*
         * masks for which bits of errs, hwerrs that cause
         * each of the counters to increment.
@@ -1307,8 +1301,7 @@ int qib_twsi_blk_rd(struct qib_devdata *dd, int dev, int addr, void *buffer,
 int qib_twsi_blk_wr(struct qib_devdata *dd, int dev, int addr,
                    const void *buffer, int len);
 void qib_get_eeprom_info(struct qib_devdata *);
-int qib_update_eeprom_log(struct qib_devdata *dd);
-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr);
+#define qib_inc_eeprom_err(dd, eidx, incr)
 void qib_dump_lookup_output_queue(struct qib_devdata *);
 void qib_force_pio_avail_update(struct qib_devdata *);
 void qib_clear_symerror_on_linkup(unsigned long opaque);
index 4d5d71aaa2b4e53e319b3c9cc57be37291f3cdd7..e2280b07df02cb07b12a1114de296cf6f4f69311 100644 (file)
@@ -267,190 +267,9 @@ void qib_get_eeprom_info(struct qib_devdata *dd)
                        "Board SN %s did not pass functional test: %s\n",
                        dd->serial, ifp->if_comment);
 
-       memcpy(&dd->eep_st_errs, &ifp->if_errcntp, QIB_EEP_LOG_CNT);
-       /*
-        * Power-on (actually "active") hours are kept as little-endian value
-        * in EEPROM, but as seconds in a (possibly as small as 24-bit)
-        * atomic_t while running.
-        */
-       atomic_set(&dd->active_time, 0);
-       dd->eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8);
-
 done:
        vfree(buf);
 
 bail:;
 }
 
-/**
- * qib_update_eeprom_log - copy active-time and error counters to eeprom
- * @dd: the qlogic_ib device
- *
- * Although the time is kept as seconds in the qib_devdata struct, it is
- * rounded to hours for re-write, as we have only 16 bits in EEPROM.
- * First-cut code reads whole (expected) struct qib_flash, modifies,
- * re-writes. Future direction: read/write only what we need, assuming
- * that the EEPROM had to have been "good enough" for driver init, and
- * if not, we aren't making it worse.
- *
- */
-int qib_update_eeprom_log(struct qib_devdata *dd)
-{
-       void *buf;
-       struct qib_flash *ifp;
-       int len, hi_water;
-       uint32_t new_time, new_hrs;
-       u8 csum;
-       int ret, idx;
-       unsigned long flags;
-
-       /* first, check if we actually need to do anything. */
-       ret = 0;
-       for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
-               if (dd->eep_st_new_errs[idx]) {
-                       ret = 1;
-                       break;
-               }
-       }
-       new_time = atomic_read(&dd->active_time);
-
-       if (ret == 0 && new_time < 3600)
-               goto bail;
-
-       /*
-        * The quick-check above determined that there is something worthy
-        * of logging, so get current contents and do a more detailed idea.
-        * read full flash, not just currently used part, since it may have
-        * been written with a newer definition
-        */
-       len = sizeof(struct qib_flash);
-       buf = vmalloc(len);
-       ret = 1;
-       if (!buf) {
-               qib_dev_err(dd,
-                       "Couldn't allocate memory to read %u bytes from eeprom for logging\n",
-                       len);
-               goto bail;
-       }
-
-       /* Grab semaphore and read current EEPROM. If we get an
-        * error, let go, but if not, keep it until we finish write.
-        */
-       ret = mutex_lock_interruptible(&dd->eep_lock);
-       if (ret) {
-               qib_dev_err(dd, "Unable to acquire EEPROM for logging\n");
-               goto free_bail;
-       }
-       ret = qib_twsi_blk_rd(dd, dd->twsi_eeprom_dev, 0, buf, len);
-       if (ret) {
-               mutex_unlock(&dd->eep_lock);
-               qib_dev_err(dd, "Unable read EEPROM for logging\n");
-               goto free_bail;
-       }
-       ifp = (struct qib_flash *)buf;
-
-       csum = flash_csum(ifp, 0);
-       if (csum != ifp->if_csum) {
-               mutex_unlock(&dd->eep_lock);
-               qib_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
-                           csum, ifp->if_csum);
-               ret = 1;
-               goto free_bail;
-       }
-       hi_water = 0;
-       spin_lock_irqsave(&dd->eep_st_lock, flags);
-       for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
-               int new_val = dd->eep_st_new_errs[idx];
-               if (new_val) {
-                       /*
-                        * If we have seen any errors, add to EEPROM values
-                        * We need to saturate at 0xFF (255) and we also
-                        * would need to adjust the checksum if we were
-                        * trying to minimize EEPROM traffic
-                        * Note that we add to actual current count in EEPROM,
-                        * in case it was altered while we were running.
-                        */
-                       new_val += ifp->if_errcntp[idx];
-                       if (new_val > 0xFF)
-                               new_val = 0xFF;
-                       if (ifp->if_errcntp[idx] != new_val) {
-                               ifp->if_errcntp[idx] = new_val;
-                               hi_water = offsetof(struct qib_flash,
-                                                   if_errcntp) + idx;
-                       }
-                       /*
-                        * update our shadow (used to minimize EEPROM
-                        * traffic), to match what we are about to write.
-                        */
-                       dd->eep_st_errs[idx] = new_val;
-                       dd->eep_st_new_errs[idx] = 0;
-               }
-       }
-       /*
-        * Now update active-time. We would like to round to the nearest hour
-        * but unless atomic_t are sure to be proper signed ints we cannot,
-        * because we need to account for what we "transfer" to EEPROM and
-        * if we log an hour at 31 minutes, then we would need to set
-        * active_time to -29 to accurately count the _next_ hour.
-        */
-       if (new_time >= 3600) {
-               new_hrs = new_time / 3600;
-               atomic_sub((new_hrs * 3600), &dd->active_time);
-               new_hrs += dd->eep_hrs;
-               if (new_hrs > 0xFFFF)
-                       new_hrs = 0xFFFF;
-               dd->eep_hrs = new_hrs;
-               if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) {
-                       ifp->if_powerhour[0] = new_hrs & 0xFF;
-                       hi_water = offsetof(struct qib_flash, if_powerhour);
-               }
-               if ((new_hrs >> 8) != ifp->if_powerhour[1]) {
-                       ifp->if_powerhour[1] = new_hrs >> 8;
-                       hi_water = offsetof(struct qib_flash, if_powerhour) + 1;
-               }
-       }
-       /*
-        * There is a tiny possibility that we could somehow fail to write
-        * the EEPROM after updating our shadows, but problems from holding
-        * the spinlock too long are a much bigger issue.
-        */
-       spin_unlock_irqrestore(&dd->eep_st_lock, flags);
-       if (hi_water) {
-               /* we made some change to the data, uopdate cksum and write */
-               csum = flash_csum(ifp, 1);
-               ret = eeprom_write_with_enable(dd, 0, buf, hi_water + 1);
-       }
-       mutex_unlock(&dd->eep_lock);
-       if (ret)
-               qib_dev_err(dd, "Failed updating EEPROM\n");
-
-free_bail:
-       vfree(buf);
-bail:
-       return ret;
-}
-
-/**
- * qib_inc_eeprom_err - increment one of the four error counters
- * that are logged to EEPROM.
- * @dd: the qlogic_ib device
- * @eidx: 0..3, the counter to increment
- * @incr: how much to add
- *
- * Each counter is 8-bits, and saturates at 255 (0xFF). They
- * are copied to the EEPROM (aka flash) whenever qib_update_eeprom_log()
- * is called, but it can only be called in a context that allows sleep.
- * This function can be called even at interrupt level.
- */
-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr)
-{
-       uint new_val;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dd->eep_st_lock, flags);
-       new_val = dd->eep_st_new_errs[eidx] + incr;
-       if (new_val > 255)
-               new_val = 255;
-       dd->eep_st_new_errs[eidx] = new_val;
-       spin_unlock_irqrestore(&dd->eep_st_lock, flags);
-}
index 84e593d6007b5c31a3ef0cc080c243697de10027..295f6312e6a924535e983bf608468e0629781d86 100644 (file)
@@ -2682,8 +2682,6 @@ static void qib_get_6120_faststats(unsigned long opaque)
        spin_lock_irqsave(&dd->eep_st_lock, flags);
        traffic_wds -= dd->traffic_wds;
        dd->traffic_wds += traffic_wds;
-       if (traffic_wds  >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
-               atomic_add(5, &dd->active_time); /* S/B #define */
        spin_unlock_irqrestore(&dd->eep_st_lock, flags);
 
        qib_chk_6120_errormask(dd);
index 454c2e7668fe71815f80cdabed08bacb35863ec0..c86e71b9e160fc8c5079d06de2f4fc22acc09480 100644 (file)
@@ -3299,8 +3299,6 @@ static void qib_get_7220_faststats(unsigned long opaque)
        spin_lock_irqsave(&dd->eep_st_lock, flags);
        traffic_wds -= dd->traffic_wds;
        dd->traffic_wds += traffic_wds;
-       if (traffic_wds  >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
-               atomic_add(5, &dd->active_time); /* S/B #define */
        spin_unlock_irqrestore(&dd->eep_st_lock, flags);
 done:
        mod_timer(&dd->stats_timer, jiffies + HZ * ACTIVITY_TIMER);
index d1bd21319d7d2ec128442042448ce101111938a3..0f8d1f0bd929236811e6c658085b57ea3d7a6859 100644 (file)
@@ -5191,8 +5191,6 @@ static void qib_get_7322_faststats(unsigned long opaque)
                spin_lock_irqsave(&ppd->dd->eep_st_lock, flags);
                traffic_wds -= ppd->dd->traffic_wds;
                ppd->dd->traffic_wds += traffic_wds;
-               if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
-                       atomic_add(ACTIVITY_TIMER, &ppd->dd->active_time);
                spin_unlock_irqrestore(&ppd->dd->eep_st_lock, flags);
                if (ppd->cpspec->qdr_dfe_on && (ppd->link_speed_active &
                                                QIB_IB_QDR) &&
index 76c3e177164dcdd4f654c33bce9008bea8fe843a..8c9bb6c3583838809f69d25610167b6f87ecd19b 100644 (file)
@@ -922,7 +922,6 @@ static void qib_shutdown_device(struct qib_devdata *dd)
                }
        }
 
-       qib_update_eeprom_log(dd);
 }
 
 /**
index 3c8e4e3caca6240175bbddb35fb304107179920e..b9ccbda7817d17595aa0cbc683a638da8a161755 100644 (file)
@@ -611,28 +611,6 @@ bail:
        return ret < 0 ? ret : count;
 }
 
-static ssize_t show_logged_errs(struct device *device,
-                               struct device_attribute *attr, char *buf)
-{
-       struct qib_ibdev *dev =
-               container_of(device, struct qib_ibdev, ibdev.dev);
-       struct qib_devdata *dd = dd_from_dev(dev);
-       int idx, count;
-
-       /* force consistency with actual EEPROM */
-       if (qib_update_eeprom_log(dd) != 0)
-               return -ENXIO;
-
-       count = 0;
-       for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
-               count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
-                                  dd->eep_st_errs[idx],
-                                  idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' ');
-       }
-
-       return count;
-}
-
 /*
  * Dump tempsense regs. in decimal, to ease shell-scripts.
  */
@@ -679,7 +657,6 @@ static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL);
 static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL);
 static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
 static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
-static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
 static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL);
 static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL);
 static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset);
@@ -693,7 +670,6 @@ static struct device_attribute *qib_attributes[] = {
        &dev_attr_nfreectxts,
        &dev_attr_serial,
        &dev_attr_boardversion,
-       &dev_attr_logged_errors,
        &dev_attr_tempsense,
        &dev_attr_localbus_info,
        &dev_attr_chip_reset,
index 0b75b5764f31514f2486d1398501eb10d4953be0..cfc5a2e6dcce185cd609b309c6f6003daf8ec402 100644 (file)
@@ -813,6 +813,21 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
        return PSMOUSE_FULL_PACKET;
 }
 
+/*
+ * This writes the reg_07 value again to the hardware at the end of every
+ * set_rate call because the register loses its value. reg_07 allows setting
+ * absolute mode on v4 hardware
+ */
+static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse,
+               unsigned int rate)
+{
+       struct elantech_data *etd = psmouse->private;
+
+       etd->original_set_rate(psmouse, rate);
+       if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+               psmouse_err(psmouse, "restoring reg_07 failed\n");
+}
+
 /*
  * Put the touchpad into absolute mode
  */
@@ -1015,6 +1030,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus K53SV              0x450f01        78, 15, 0c      2 hw buttons
  * Asus G46VW              0x460f02        00, 18, 0c      2 hw buttons
  * Asus G750JX             0x360f00        00, 16, 0c      2 hw buttons
+ * Asus TP500LN            0x381f17        10, 14, 0e      clickpad
+ * Asus X750JN             0x381f17        10, 14, 0e      clickpad
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
@@ -1490,6 +1507,11 @@ int elantech_init(struct psmouse *psmouse)
                goto init_fail;
        }
 
+       if (etd->fw_version == 0x381f17) {
+               etd->original_set_rate = psmouse->set_rate;
+               psmouse->set_rate = elantech_set_rate_restore_reg_07;
+       }
+
        if (elantech_set_input_params(psmouse)) {
                psmouse_err(psmouse, "failed to query touchpad range.\n");
                goto init_fail;
index 9e0e2a1f340d52817fc18bf79d849bed6d340932..59263a3a86674cdc7a2db74c56736f37defd2c1d 100644 (file)
@@ -139,6 +139,7 @@ struct elantech_data {
        struct finger_pos mt[ETP_MAX_FINGERS];
        unsigned char parity[256];
        int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param);
+       void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate);
 };
 
 #ifdef CONFIG_MOUSE_PS2_ELANTECH
index 05f371df6c400a882621c13509f6a13a40eed077..d4b0a31ab66b28ec3676fd47d9b02de2331390e4 100644 (file)
@@ -700,6 +700,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        input_report_key(input, BTN_7, (data[4] & 0x40));  /* Left   */
                        input_report_key(input, BTN_8, (data[4] & 0x80));  /* Down   */
                        input_report_key(input, BTN_0, (data[3] & 0x01));  /* Center */
+
+                       if (data[4] | (data[3] & 0x01)) {
+                               input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+                       } else {
+                               input_report_abs(input, ABS_MISC, 0);
+                       }
                } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
                        int i;
 
index 693f23c46a64ed0f69cf057a583a0ba8cc987152..1b2c3ac2fe0d2f08db681403f111092fb2acde49 100644 (file)
@@ -129,6 +129,11 @@ EXPORT_SYMBOL_GPL(omap_uninstall_iommu_arch);
 /**
  * omap_iommu_save_ctx - Save registers for pm off-mode support
  * @dev:       client device
+ *
+ * This should be treated as an deprecated API. It is preserved only
+ * to maintain existing functionality for OMAP3 ISP driver, newer
+ * SoCs will leverage the newer omap_iommu_domain_suspend() API and
+ * associated runtime_suspend callback.
  **/
 void omap_iommu_save_ctx(struct device *dev)
 {
@@ -146,6 +151,11 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
 /**
  * omap_iommu_restore_ctx - Restore registers for pm off-mode support
  * @dev:       client device
+ *
+ * This should be treated as an deprecated API. It is preserved only
+ * to maintain existing functionality for OMAP3 ISP driver, newer
+ * SoCs will leverage the newer omap_iommu_domain_resume() API and
+ * associated runtime_resume callback.
  **/
 void omap_iommu_restore_ctx(struct device *dev)
 {
@@ -162,39 +172,24 @@ EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
 
 static int iommu_enable(struct omap_iommu *obj)
 {
-       int err;
-       struct platform_device *pdev = to_platform_device(obj->dev);
-       struct iommu_platform_data *pdata = pdev->dev.platform_data;
+       int ret;
 
        if (!arch_iommu)
                return -ENODEV;
 
-       if (pdata && pdata->deassert_reset) {
-               err = pdata->deassert_reset(pdev, pdata->reset_name);
-               if (err) {
-                       dev_err(obj->dev, "deassert_reset failed: %d\n", err);
-                       return err;
-               }
-       }
+       ret = pm_runtime_get_sync(obj->dev);
+       if (ret < 0)
+               pm_runtime_put_noidle(obj->dev);
 
-       pm_runtime_get_sync(obj->dev);
-
-       err = arch_iommu->enable(obj);
-
-       return err;
+       return ret < 0 ? ret : 0;
 }
 
 static void iommu_disable(struct omap_iommu *obj)
 {
-       struct platform_device *pdev = to_platform_device(obj->dev);
-       struct iommu_platform_data *pdata = pdev->dev.platform_data;
-
-       arch_iommu->disable(obj);
+       if (!arch_iommu)
+               return;
 
        pm_runtime_put_sync(obj->dev);
-
-       if (pdata && pdata->assert_reset)
-               pdata->assert_reset(pdev, pdata->reset_name);
 }
 
 /*
@@ -913,14 +908,217 @@ static void omap_iommu_detach(struct omap_iommu *obj)
 
        spin_lock(&obj->iommu_lock);
 
-       iommu_disable(obj);
        obj->iopgd = NULL;
+       iommu_disable(obj);
 
        spin_unlock(&obj->iommu_lock);
 
        dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
 }
 
+/**
+ * omap_iommu_domain_suspend - suspend the iommu device
+ * @domain: iommu domain attached to the target iommu device
+ * @auto_suspend: flag to indicate system suspend or runtime suspend
+ *
+ * This API allows the client devices of IOMMU devices to suspend
+ * the IOMMUs they control, after they are idled and suspended all
+ * activity.
+ **/
+int omap_iommu_domain_suspend(struct iommu_domain *domain, bool auto_suspend)
+{
+       struct omap_iommu_domain *omap_domain = domain->priv;
+       struct omap_iommu_device *iommu;
+       struct omap_iommu *oiommu;
+       int i;
+
+       if (!omap_domain->attached)
+               return 0;
+
+       iommu = omap_domain->iommus;
+       iommu += (omap_domain->num_iommus - 1);
+       for (i = 0; i < omap_domain->num_iommus; i++, iommu--) {
+               oiommu = iommu->iommu_dev;
+               if (auto_suspend) {
+                       pm_runtime_put_sync(oiommu->dev);
+               } else {
+                       pm_runtime_put_noidle(oiommu->dev);
+                       pm_generic_runtime_suspend(oiommu->dev);
+                       pm_runtime_disable(oiommu->dev);
+                       pm_runtime_set_suspended(oiommu->dev);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_domain_suspend);
+
+/**
+ * omap_iommu_domain_resume - resume the iommu device
+ * @domain: iommu domain attached to the target iommu device
+ * @auto_suspend: flag to indicate system suspend or runtime suspend
+ *
+ * This API allows the client devices of IOMMU devices to resume
+ * the IOMMUs they control, before they can resume operations.
+ **/
+int omap_iommu_domain_resume(struct iommu_domain *domain, bool auto_suspend)
+{
+       struct omap_iommu_domain *omap_domain = domain->priv;
+       struct omap_iommu_device *iommu;
+       struct omap_iommu *oiommu;
+       int i;
+
+       if (!omap_domain->attached)
+               return 0;
+
+       iommu = omap_domain->iommus;
+       for (i = 0; i < omap_domain->num_iommus; i++, iommu++) {
+               oiommu = iommu->iommu_dev;
+               if (auto_suspend) {
+                       pm_runtime_get_sync(oiommu->dev);
+               } else {
+                       pm_runtime_set_active(oiommu->dev);
+                       pm_runtime_enable(oiommu->dev);
+                       pm_runtime_get_noresume(oiommu->dev);
+                       pm_generic_runtime_resume(oiommu->dev);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(omap_iommu_domain_resume);
+
+static void omap_iommu_save_tlb_entries(struct omap_iommu *obj)
+{
+       struct iotlb_lock lock;
+       struct cr_regs cr;
+       struct cr_regs *tmp;
+       int i;
+
+       /* check if there are any locked tlbs to save */
+       iotlb_lock_get(obj, &lock);
+       obj->num_cr_ctx = lock.base;
+       if (!obj->num_cr_ctx)
+               return;
+
+       tmp = obj->cr_ctx;
+       for_each_iotlb_cr(obj, obj->num_cr_ctx, i, cr)
+               *tmp++ = cr;
+}
+
+static void omap_iommu_restore_tlb_entries(struct omap_iommu *obj)
+{
+       struct iotlb_lock l;
+       struct cr_regs *tmp;
+       int i;
+
+       /* no locked tlbs to restore */
+       if (!obj->num_cr_ctx)
+               return;
+
+       l.base = 0;
+       tmp = obj->cr_ctx;
+       for (i = 0; i < obj->num_cr_ctx; i++, tmp++) {
+               l.vict = i;
+               iotlb_lock_set(obj, &l);
+               iotlb_load_cr(obj, tmp);
+       }
+       l.base = obj->num_cr_ctx;
+       l.vict = i;
+       iotlb_lock_set(obj, &l);
+}
+
+/**
+ * omap_iommu_runtime_suspend - disable an iommu device
+ * @dev:       iommu device
+ *
+ * This function performs all that is necessary to disable an
+ * IOMMU device, either during final detachment from a client
+ * device, or during system/runtime suspend of the device. This
+ * includes programming all the appropriate IOMMU registers, and
+ * managing the associated omap_hwmod's state and the device's
+ * reset line. This function also saves the context of any
+ * locked TLBs if suspending.
+ **/
+static int omap_iommu_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct iommu_platform_data *pdata = dev_get_platdata(dev);
+       struct omap_iommu *obj = to_iommu(dev);
+       int ret;
+
+       /* save the TLBs only during suspend, and not for power down */
+       if (obj->domain && obj->iopgd)
+               omap_iommu_save_tlb_entries(obj);
+
+       if (arch_iommu->disable)
+               arch_iommu->disable(obj);
+
+       if (pdata && pdata->device_idle)
+               pdata->device_idle(pdev);
+
+       if (pdata && pdata->assert_reset)
+               pdata->assert_reset(pdev, pdata->reset_name);
+
+       if (pdata && pdata->set_pwrdm_constraint) {
+               ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst);
+               if (ret) {
+                       dev_warn(dev, "pwrdm_constraint failed to be reset, status = %d\n",
+                                ret);
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * omap_iommu_runtime_resume - enable an iommu device
+ * @dev:       iommu device
+ *
+ * This function performs all that is necessary to enable an
+ * IOMMU device, either during initial attachment to a client
+ * device, or during system/runtime resume of the device. This
+ * includes programming all the appropriate IOMMU registers, and
+ * managing the associated omap_hwmod's state and the device's
+ * reset line. The function also restores any locked TLBs if
+ * resuming after a suspend.
+ **/
+static int omap_iommu_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct iommu_platform_data *pdata = dev_get_platdata(dev);
+       struct omap_iommu *obj = to_iommu(dev);
+       int ret = 0;
+
+       if (pdata && pdata->set_pwrdm_constraint) {
+               ret = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst);
+               if (ret) {
+                       dev_warn(dev, "pwrdm_constraint failed to be set, status = %d\n",
+                                ret);
+               }
+       }
+
+       if (pdata && pdata->deassert_reset) {
+               ret = pdata->deassert_reset(pdev, pdata->reset_name);
+               if (ret) {
+                       dev_err(dev, "deassert_reset failed: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       if (pdata && pdata->device_enable)
+               pdata->device_enable(pdev);
+
+       /* restore the TLBs only during resume, and not for power up */
+       if (obj->domain)
+               omap_iommu_restore_tlb_entries(obj);
+
+       if (arch_iommu->enable)
+               ret = arch_iommu->enable(obj);
+
+       return ret;
+}
+
 static int omap_iommu_dra7_get_dsp_system_cfg(struct platform_device *pdev,
                                              struct omap_iommu *obj,
                                              resource_size_t start)
@@ -977,6 +1175,15 @@ static int omap_iommu_probe(struct platform_device *pdev)
        if (!obj)
                return -ENOMEM;
 
+       /*
+        * self-manage the ordering dependencies between omap_device_enable/idle
+        * and omap_device_assert/deassert_hardreset API
+        */
+       if (pdev->dev.pm_domain) {
+               dev_dbg(&pdev->dev, "device pm_domain is being reset\n");
+               pdev->dev.pm_domain = NULL;
+       }
+
        if (of) {
                obj->name = dev_name(&pdev->dev);
                obj->nr_tlb_entries = 32;
@@ -1006,6 +1213,11 @@ static int omap_iommu_probe(struct platform_device *pdev)
 
        obj->dev = &pdev->dev;
        obj->ctx = (void *)obj + sizeof(*obj);
+       obj->cr_ctx = devm_kzalloc(&pdev->dev,
+                                  sizeof(*obj->cr_ctx) * obj->nr_tlb_entries,
+                                  GFP_KERNEL);
+       if (!obj->cr_ctx)
+               return -ENOMEM;
 
        spin_lock_init(&obj->iommu_lock);
        mutex_init(&obj->mmap_lock);
@@ -1050,6 +1262,11 @@ static int omap_iommu_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct dev_pm_ops omap_iommu_pm_ops = {
+       SET_RUNTIME_PM_OPS(omap_iommu_runtime_suspend,
+                          omap_iommu_runtime_resume, NULL)
+};
+
 static struct of_device_id omap_iommu_of_match[] = {
        { .compatible = "ti,omap2-iommu" },
        { .compatible = "ti,omap4-iommu" },
@@ -1063,6 +1280,7 @@ static struct platform_driver omap_iommu_driver = {
        .remove = omap_iommu_remove,
        .driver = {
                .name   = "omap-iommu",
+               .pm     = &omap_iommu_pm_ops,
                .of_match_table = of_match_ptr(omap_iommu_of_match),
        },
 };
index c1c0d824c79b59cd1c3c1975ce65031bfd3a50f7..5d76c0844a82c2a21a64d838803bea0eb82f3c9b 100644 (file)
@@ -55,8 +55,13 @@ struct omap_iommu {
        u32 da_start;
        u32 da_end;
 
+       struct cr_regs *cr_ctx;
+       u32 num_cr_ctx;
+
        int has_bus_err_back;
        u32 id;
+
+       u8 pwrst;
 };
 
 struct cr_regs {
index 2a657e715ab55c2588d0f7e6876f3e86a3d89a8a..5a42824766a51e2e3aa9be558b5c282675caa04f 100644 (file)
@@ -96,8 +96,10 @@ struct omap_mbox_device {
        struct device *dev;
        struct mutex cfg_lock;
        void __iomem *mbox_base;
+       u32 *irq_ctx;
        u32 num_users;
        u32 num_fifos;
+       u32 intr_type;
        struct omap_mbox **mboxes;
        struct mbox_controller controller;
        struct list_head elem;
@@ -652,6 +654,52 @@ static struct mbox_chan_ops omap_mbox_chan_ops = {
        .shutdown       = omap_mbox_chan_shutdown,
 };
 
+#ifdef CONFIG_PM_SLEEP
+static int omap_mbox_suspend(struct device *dev)
+{
+       struct omap_mbox_device *mdev = dev_get_drvdata(dev);
+       u32 usr, fifo, reg;
+
+       if (pm_runtime_status_suspended(dev))
+               return 0;
+
+       for (fifo = 0; fifo < mdev->num_fifos; fifo++) {
+               if (mbox_read_reg(mdev, MAILBOX_MSGSTATUS(fifo))) {
+                       dev_err(mdev->dev, "fifo %d has unexpected unread messages\n",
+                               fifo);
+                       return -EBUSY;
+               }
+       }
+
+       for (usr = 0; usr < mdev->num_users; usr++) {
+               reg = MAILBOX_IRQENABLE(mdev->intr_type, usr);
+               mdev->irq_ctx[usr] = mbox_read_reg(mdev, reg);
+       }
+
+       return 0;
+}
+
+static int omap_mbox_resume(struct device *dev)
+{
+       struct omap_mbox_device *mdev = dev_get_drvdata(dev);
+       u32 usr, reg;
+
+       if (pm_runtime_status_suspended(dev))
+               return 0;
+
+       for (usr = 0; usr < mdev->num_users; usr++) {
+               reg = MAILBOX_IRQENABLE(mdev->intr_type, usr);
+               mbox_write_reg(mdev, mdev->irq_ctx[usr], reg);
+       }
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops omap_mbox_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(omap_mbox_suspend, omap_mbox_resume)
+};
+
 static const struct of_device_id omap_mailbox_of_match[] = {
        {
                .compatible     = "ti,omap2-mailbox",
@@ -801,6 +849,11 @@ static int omap_mbox_probe(struct platform_device *pdev)
        if (IS_ERR(mdev->mbox_base))
                return PTR_ERR(mdev->mbox_base);
 
+       mdev->irq_ctx = devm_kzalloc(&pdev->dev, num_users * sizeof(u32),
+                                    GFP_KERNEL);
+       if (!mdev->irq_ctx)
+               return -ENOMEM;
+
        /* allocate one extra for marking end of list */
        list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list),
                            GFP_KERNEL);
@@ -853,6 +906,7 @@ static int omap_mbox_probe(struct platform_device *pdev)
        mdev->dev = &pdev->dev;
        mdev->num_users = num_users;
        mdev->num_fifos = num_fifos;
+       mdev->intr_type  = intr_type;
        mdev->mboxes = list;
 
        /* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */
@@ -911,6 +965,7 @@ static struct platform_driver omap_mbox_driver = {
        .driver = {
                .name = "omap-mailbox",
                .owner = THIS_MODULE,
+               .pm = &omap_mbox_pm_ops,
                .of_match_table = of_match_ptr(omap_mailbox_of_match),
        },
 };
index db404a0f7e2c83ead70bbf32e2346ecd60aa2edf..080e767250d3af079aaee71064edb3e9623180d0 100644 (file)
@@ -291,6 +291,19 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
        struct request_queue *q = bdev_get_queue(where->bdev);
        unsigned short logical_block_size = queue_logical_block_size(q);
        sector_t num_sectors;
+       unsigned int uninitialized_var(special_cmd_max_sectors);
+
+       /*
+        * Reject unsupported discard and write same requests.
+        */
+       if (rw & REQ_DISCARD)
+               special_cmd_max_sectors = q->limits.max_discard_sectors;
+       else if (rw & REQ_WRITE_SAME)
+               special_cmd_max_sectors = q->limits.max_write_same_sectors;
+       if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) {
+               dec_count(io, region, -EOPNOTSUPP);
+               return;
+       }
 
        /*
         * where->count may be zero if rw holds a flush and we need to
@@ -313,7 +326,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                store_io_and_region_in_bio(bio, io, region);
 
                if (rw & REQ_DISCARD) {
-                       num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
+                       num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining);
                        bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
                        remaining -= num_sectors;
                } else if (rw & REQ_WRITE_SAME) {
@@ -322,7 +335,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                         */
                        dp->get_page(dp, &page, &len, &offset);
                        bio_add_page(bio, page, logical_block_size, offset);
-                       num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining);
+                       num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining);
                        bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
 
                        offset = 0;
index 7dfdb5c746d6f31960902350c33b7457485caadb..089d62751f7ff2a3aedf7e441cb88bec0d06b8a7 100644 (file)
@@ -604,6 +604,15 @@ static void write_callback(unsigned long error, void *context)
                return;
        }
 
+       /*
+        * If the bio is discard, return an error, but do not
+        * degrade the array.
+        */
+       if (bio->bi_rw & REQ_DISCARD) {
+               bio_endio(bio, -EOPNOTSUPP);
+               return;
+       }
+
        for (i = 0; i < ms->nr_mirrors; i++)
                if (test_bit(i, &error))
                        fail_mirror(ms->mirror + i, DM_RAID1_WRITE_ERROR);
index ebddef5237e4b28e6254e486b3267dbccca9864e..c356a10b9ba5bce27a1329cdc3436e428eb3dd28 100644 (file)
@@ -1440,8 +1440,6 @@ out:
                full_bio->bi_private = pe->full_bio_private;
                atomic_inc(&full_bio->bi_remaining);
        }
-       free_pending_exception(pe);
-
        increment_pending_exceptions_done_count();
 
        up_write(&s->lock);
@@ -1458,6 +1456,8 @@ out:
        }
 
        retry_origin_bios(s, origin_bios);
+
+       free_pending_exception(pe);
 }
 
 static void commit_callback(void *context, int success)
index 65ee3a0d4683a1199efce4a75965c3054060fa22..e400591432726e1389d48a84d5d4e1374bb95113 100644 (file)
@@ -2288,7 +2288,7 @@ int dm_setup_md_queue(struct mapped_device *md)
        return 0;
 }
 
-static struct mapped_device *dm_find_md(dev_t dev)
+struct mapped_device *dm_get_md(dev_t dev)
 {
        struct mapped_device *md;
        unsigned minor = MINOR(dev);
@@ -2299,12 +2299,15 @@ static struct mapped_device *dm_find_md(dev_t dev)
        spin_lock(&_minor_lock);
 
        md = idr_find(&_minor_idr, minor);
-       if (md && (md == MINOR_ALLOCED ||
-                  (MINOR(disk_devt(dm_disk(md))) != minor) ||
-                  dm_deleting_md(md) ||
-                  test_bit(DMF_FREEING, &md->flags))) {
-               md = NULL;
-               goto out;
+       if (md) {
+               if ((md == MINOR_ALLOCED ||
+                    (MINOR(disk_devt(dm_disk(md))) != minor) ||
+                    dm_deleting_md(md) ||
+                    test_bit(DMF_FREEING, &md->flags))) {
+                       md = NULL;
+                       goto out;
+               }
+               dm_get(md);
        }
 
 out:
@@ -2312,16 +2315,6 @@ out:
 
        return md;
 }
-
-struct mapped_device *dm_get_md(dev_t dev)
-{
-       struct mapped_device *md = dm_find_md(dev);
-
-       if (md)
-               dm_get(md);
-
-       return md;
-}
 EXPORT_SYMBOL_GPL(dm_get_md);
 
 void *dm_get_mdptr(struct mapped_device *md)
@@ -2359,10 +2352,16 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
        set_bit(DMF_FREEING, &md->flags);
        spin_unlock(&_minor_lock);
 
+       /*
+        * Take suspend_lock so that presuspend and postsuspend methods
+        * do not race with internal suspend.
+        */
+       mutex_lock(&md->suspend_lock);
        if (!dm_suspended_md(md)) {
                dm_table_presuspend_targets(map);
                dm_table_postsuspend_targets(map);
        }
+       mutex_unlock(&md->suspend_lock);
 
        /* dm_put_live_table must be before msleep, otherwise deadlock is possible */
        dm_put_live_table(md, srcu_idx);
index 407a99e46f6993a770c21fdfff1972b7f64063b6..683e685ed6973f06d091cd47932a4c8161bc4de8 100644 (file)
@@ -320,7 +320,7 @@ static struct strip_zone *find_zone(struct r0conf *conf,
 
 /*
  * remaps the bio to the target device. we separate two flows.
- * power 2 flow and a general flow for the sake of perfromance
+ * power 2 flow and a general flow for the sake of performance
 */
 static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone,
                                sector_t sector, sector_t *sector_offset)
@@ -538,6 +538,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
                        split = bio;
                }
 
+               sector = bio->bi_iter.bi_sector;
                zone = find_zone(mddev->private, &sector);
                tmp_dev = map_sector(mddev, zone, sector, &sector);
                split->bi_bdev = tmp_dev->bdev;
index b8aefe9aee76f271f5b671d1467274e3e3a257a6..70a36cfe43a65f39c8ab6add0f015e0099f7a566 100644 (file)
@@ -511,6 +511,17 @@ config VIDEO_OV9650
          This is a V4L2 sensor-level driver for the Omnivision
          OV9650 and OV9652 camera sensors.
 
+config VIDEO_OV1063X
+       tristate "OmniVision OV1063X sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the OmniVision
+         OV1063X Sensor.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ov1063x.
+
 config VIDEO_VS6624
        tristate "ST VS6624 sensor support"
        depends on VIDEO_V4L2 && I2C
index efb4c38b0c7e15d3d9945e0b56dd84dc68d29277..cd17c1fdaad87965a4f81083f0c631c06c20b08d 100644 (file)
@@ -59,6 +59,7 @@ obj-$(CONFIG_VIDEO_OV2659) += ov2659.o
 obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
 obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
 obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
+obj-$(CONFIG_VIDEO_OV1063X)    += ov1063x.o
 obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
 obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
 obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
index d6509624e8033f11befd141e3a96ab684b7f9466..697e67cecc89733061295162108871c431169393 100644 (file)
@@ -190,6 +190,7 @@ struct mt9t11x_priv {
        struct v4l2_ctrl                *hflip;
        struct v4l2_ctrl                *vflip;
 
+       /* Protects the struct fields below */
        struct mutex                    lock;
        int                             streaming;
        int                             power;
@@ -724,8 +725,9 @@ static inline u32 calc_div(u32 desired, u32 src, u8 *_div)
                div = src / desired;
                if ((src % desired) > 0)
                        div++;
-       } else
+       } else {
                div = 1;
+       }
 
        *_div = (u8)(div - 1);
 
@@ -1181,8 +1183,8 @@ static int mt9t11x_init_camera(const struct i2c_client *client)
        ECHECKER(ret, mt9t11x_continue(client));
 
        ECHECKER(ret, mt9t11x_set_a_frame_size(client,
-                                priv->frame.width,
-                                priv->frame.height));
+                                              priv->frame.width,
+                                              priv->frame.height));
 
        return ret;
 }
@@ -1276,7 +1278,7 @@ static int mt9t11x_s_ctrl(struct v4l2_ctrl *ctrl)
        int ret = -EINVAL;
 
        dev_dbg(&client->dev, "%s: ctrl_id:0x%x (%s), value: %d\n",
-                __func__, ctrl->id, ctrl->name, ctrl->val);
+               __func__, ctrl->id, ctrl->name, ctrl->val);
 
        mutex_lock(&priv->lock);
        /*
@@ -1290,11 +1292,11 @@ static int mt9t11x_s_ctrl(struct v4l2_ctrl *ctrl)
 
        switch (ctrl->id) {
        case V4L2_CID_VFLIP:
-               mt9t11x_set_orientation(client, 0x2, (ctrl->val)?2:0);
+               mt9t11x_set_orientation(client, 0x2, (ctrl->val) ? 2 : 0);
                ret = 0;
                break;
        case V4L2_CID_HFLIP:
-               mt9t11x_set_orientation(client, 0x1, (ctrl->val)?1:0);
+               mt9t11x_set_orientation(client, 0x1, (ctrl->val) ? 1 : 0);
                ret = 0;
                break;
        }
@@ -1413,20 +1415,22 @@ static int mt9t11x_s_stream(struct v4l2_subdev *sd, int enable)
 
        mt9t11x_mcu_write(ret, client, VAR(26, 7), priv->format->fmt);
        mt9t11x_mcu_write(ret, client, VAR(26, 9), priv->format->order);
+
        mt9t11x_mcu_write(ret, client, VAR8(1, 0), 0x06);
 
        if (priv->flags & MT9T11x_FLAG_VFLIP)
                v4l2_ctrl_s_ctrl(priv->vflip, 1);
 
        /* Make sure H/W is consistent with current control settings */
-       ECHECKER(ret, mt9t11x_set_orientation(client, 0x3,
-                               (v4l2_ctrl_g_ctrl(priv->vflip) << 1 |
-                                v4l2_ctrl_g_ctrl(priv->hflip))));
+       ECHECKER(ret,
+                mt9t11x_set_orientation(client, 0x3,
+                                        (v4l2_ctrl_g_ctrl(priv->vflip) << 1 |
+                                         v4l2_ctrl_g_ctrl(priv->hflip))));
 
-       dev_dbg(&client->dev, "format : %d\n", priv->format->code);
+       dev_dbg(&client->dev, "format : %04x\n", priv->format->code);
        dev_dbg(&client->dev, "size   : %d x %d\n",
-                       priv->frame.width,
-                       priv->frame.height);
+               priv->frame.width,
+               priv->frame.height);
 
        priv->streaming = enable;
 
@@ -1637,7 +1641,11 @@ static int mt9t11x_camera_probe(struct i2c_client *client)
        switch (chipid) {
        case 0x2680:
                devname = "mt9t111";
-               priv->num_formats = ARRAY_SIZE(mt9t11x_cfmts);
+               /*
+                * Looks like only uyvy and vyuy are supported
+                * so limiting available formats.
+                */
+               priv->num_formats = 1;
                break;
        case 0x2682:
                devname = "mt9t112";
@@ -1877,9 +1885,9 @@ MODULE_DEVICE_TABLE(i2c, mt9t11x_id);
 
 #if IS_ENABLED(CONFIG_OF)
 static const struct of_device_id mt9t11x_of_match[] = {
-       { .compatible = "aptina,mt9t11x", .data = (void *) MT9T11X_ID},
-       { .compatible = "aptina,mt9t111", .data = (void *) MT9T111_ID},
-       { .compatible = "aptina,mt9t112", .data = (void *) MT9T112_ID},
+       { .compatible = "aptina,mt9t11x", .data = (void *)MT9T11X_ID},
+       { .compatible = "aptina,mt9t111", .data = (void *)MT9T111_ID},
+       { .compatible = "aptina,mt9t112", .data = (void *)MT9T112_ID},
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, mt9t11x_of_match);
diff --git a/drivers/media/i2c/ov1063x.c b/drivers/media/i2c/ov1063x.c
new file mode 100644 (file)
index 0000000..ba10e3e
--- /dev/null
@@ -0,0 +1,1061 @@
+/*
+ * OmniVision OV1063X Camera Driver
+ *
+ * Based on the original driver written by Phil Edworthy.
+ * Copyright (C) 2013 Phil Edworthy
+ * Copyright (C) 2013 Renesas Electronics
+ *
+ * This driver has been tested at QVGA, VGA and 720p, and 1280x800 at up to
+ * 30fps and it should work at any resolution in between and any frame rate
+ * up to 30fps.
+ *
+ * FIXME:
+ *  Horizontal flip (mirroring) does not work correctly. The image is flipped,
+ *  but the colors are wrong.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+
+#include "ov1063x_regs.h"
+
+#include <linux/pm_runtime.h>
+
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
+
+
+/* Register definitions */
+#define        OV1063X_VFLIP                   0x381c
+#define         OV1063X_VFLIP_ON               (0x3 << 6)
+#define         OV1063X_VFLIP_SUBSAMPLE        0x1
+#define        OV1063X_HMIRROR                 0x381d
+#define         OV1063X_HMIRROR_ON             0x3
+#define OV1063X_PID                    0x300a
+#define OV1063X_VER                    0x300b
+
+#define OV1063X_FORMAT_CTRL00          0x4300
+#define   OV1063X_FORMAT_YUYV          0x38
+#define   OV1063X_FORMAT_YYYU          0x39
+#define   OV1063X_FORMAT_UYVY          0x3A
+#define   OV1063X_FORMAT_VYUY          0x3B
+
+
+/* IDs */
+#define OV10633_VERSION_REG            0xa630
+#define OV10635_VERSION_REG            0xa635
+#define OV1063X_VERSION(pid, ver)      (((pid) << 8) | ((ver) & 0xff))
+
+enum ov1063x_model {
+       SENSOR_OV10633,
+       SENSOR_OV10635,
+};
+
+#define OV1063X_SENSOR_WIDTH           1312
+#define OV1063X_SENSOR_HEIGHT          814
+
+#define OV1063X_MAX_WIDTH              1280
+#define OV1063X_MAX_HEIGHT             800
+
+#define MAX_NUM_GPIOS                  20
+
+struct ov1063x_color_format {
+       enum v4l2_mbus_pixelcode code;
+       enum v4l2_colorspace colorspace;
+};
+
+struct ov1063x_priv {
+       struct v4l2_subdev              subdev;
+       struct v4l2_async_subdev        asd;
+       struct v4l2_ctrl_handler        hdl;
+       int                             model;
+       int                             revision;
+       int                             xvclk;
+       int                             fps_numerator;
+       int                             fps_denominator;
+       const struct ov1063x_color_format       *cfmt;
+       int                             width;
+       int                             height;
+
+       struct gpio                     mux_gpios[MAX_NUM_GPIOS];
+       int                             num_gpios;
+};
+
+static int ov1063x_init_gpios(struct i2c_client *client);
+
+/*
+ * supported color format list
+ */
+static const struct ov1063x_color_format ov1063x_cfmts[] = {
+       {
+               .code           = V4L2_MBUS_FMT_YUYV8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+       },
+       {
+               .code           = V4L2_MBUS_FMT_UYVY8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+       },
+       {
+               .code           = V4L2_MBUS_FMT_VYUY8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+       },
+       {
+               .code           = V4L2_MBUS_FMT_YVYU8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+       },
+       {
+               .code           = V4L2_MBUS_FMT_YUYV10_2X10,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+       },
+};
+
+static struct ov1063x_priv *to_ov1063x(const struct i2c_client *client)
+{
+       return container_of(i2c_get_clientdata(client), struct ov1063x_priv,
+                       subdev);
+}
+
+/* read a register */
+static int ov1063x_reg_read(struct i2c_client *client, u16 reg, u8 *val)
+{
+       int ret;
+       u8 data[2] = { reg >> 8, reg & 0xff };
+       struct i2c_msg msg = {
+               .addr   = client->addr,
+               .flags  = 0,
+               .len    = 2,
+               .buf    = data,
+       };
+
+       ret = i2c_transfer(client->adapter, &msg, 1);
+       if (ret < 0)
+               goto err;
+
+       msg.flags = I2C_M_RD;
+       msg.len = 1;
+       msg.buf = &data[0];
+
+       ret = i2c_transfer(client->adapter, &msg, 1);
+       if (ret < 0)
+               goto err;
+
+       *val = data[0];
+       return 0;
+err:
+       dev_err(&client->dev, "Failed reading register 0x%04x!\n", reg);
+       return ret;
+}
+
+/* write a register */
+static int ov1063x_reg_write(struct i2c_client *client, u16 reg, u8 val)
+{
+       int ret;
+       u8 data[3] = { reg >> 8, reg & 0xff, val };
+
+       struct i2c_msg msg = {
+               .addr   = client->addr,
+               .flags  = 0,
+               .len    = 3,
+               .buf    = data,
+       };
+
+       ret = i2c_transfer(client->adapter, &msg, 1);
+       if (ret < 0) {
+               dev_err(&client->dev, "Failed writing register 0x%04x!\n", reg);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ov1063x_reg_write16(struct i2c_client *client, u16 reg, u16 val)
+{
+       int ret;
+
+       ret = ov1063x_reg_write(client, reg, val >> 8);
+       if (ret)
+               return ret;
+
+       ret = ov1063x_reg_write(client, reg + 1, val & 0xff);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+/* Read a register, alter its bits, write it back */
+static int ov1063x_reg_rmw(struct i2c_client *client, u16 reg, u8 set, u8 unset)
+{
+       u8 val;
+       int ret;
+
+       ret = ov1063x_reg_read(client, reg, &val);
+       if (ret) {
+               dev_err(&client->dev,
+                       "[Read]-Modify-Write of register %04x failed!\n", reg);
+               return ret;
+       }
+
+       val |= set;
+       val &= ~unset;
+
+       ret = ov1063x_reg_write(client, reg, val);
+       if (ret)
+               dev_err(&client->dev,
+                       "Read-Modify-[Write] of register %04x failed!\n", reg);
+
+       return ret;
+}
+
+
+/* Start/Stop streaming from the device */
+static int ov1063x_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret;
+
+       ret = ov1063x_init_gpios(client);
+       if (ret) {
+               dev_err(&client->dev, "Failed to request gpios");
+               return ret;
+       }
+
+       ov1063x_reg_write(client, 0x0100, enable);
+
+       if (enable)
+               ov1063x_reg_write(client, 0x301c, 0xf0);
+       else
+               ov1063x_reg_write(client, 0x301c, 0x70);
+
+       return 0;
+}
+
+/* Set status of additional camera capabilities */
+static int ov1063x_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct ov1063x_priv *priv = container_of(ctrl->handler,
+                                       struct ov1063x_priv, hdl);
+       struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               if (ctrl->val)
+                       return ov1063x_reg_rmw(client, OV1063X_VFLIP,
+                               OV1063X_VFLIP_ON, 0);
+               else
+                       return ov1063x_reg_rmw(client, OV1063X_VFLIP,
+                               0, OV1063X_VFLIP_ON);
+               break;
+       case V4L2_CID_HFLIP:
+               if (ctrl->val)
+                       return ov1063x_reg_rmw(client, OV1063X_HMIRROR,
+                               OV1063X_HMIRROR_ON, 0);
+               else
+                       return ov1063x_reg_rmw(client, OV1063X_HMIRROR,
+                               0, OV1063X_HMIRROR_ON);
+               break;
+       }
+
+       return -EINVAL;
+}
+
+/*
+ * Get the best pixel clock (pclk) that meets minimum hts/vts requirements.
+ * xvclk => pre-divider => clk1 => multiplier => clk2 => post-divider => pclk
+ * We try all valid combinations of settings for the 3 blocks to get the pixel
+ * clock, and from that calculate the actual hts/vts to use. The vts is
+ * extended so as to achieve the required frame rate. The function also returns
+ * the PLL register contents needed to set the pixel clock.
+ */
+static int ov1063x_get_pclk(int xvclk, int *htsmin, int *vtsmin,
+                       int fps_numerator, int fps_denominator,
+                       u8 *r3003, u8 *r3004)
+{
+       int pre_divs[] = { 2, 3, 4, 6, 8, 10, 12, 14 };
+       int pclk;
+       int best_pclk = INT_MAX;
+       int best_hts = 0;
+       int i, j, k;
+       int best_i = 0, best_j = 0, best_k = 0;
+       int clk1, clk2;
+       int hts;
+
+       /* Pre-div, reg 0x3004, bits 6:4 */
+       for (i = 0; i < ARRAY_SIZE(pre_divs); i++) {
+               clk1 = (xvclk / pre_divs[i]) * 2;
+
+               if ((clk1 < 3000000) || (clk1 > 27000000))
+                       continue;
+
+               /* Mult = reg 0x3003, bits 5:0 */
+               for (j = 1; j < 32; j++) {
+                       clk2 = (clk1 * j);
+
+                       if ((clk2 < 200000000) || (clk2 > 500000000))
+                               continue;
+
+                       /* Post-div, reg 0x3004, bits 2:0 */
+                       for (k = 0; k < 8; k++) {
+                               pclk = clk2 / (2*(k+1));
+
+                               if (pclk > 96000000)
+                                       continue;
+
+                               hts = *htsmin + 200 + pclk/300000;
+
+                               /* 2 clock cycles for every YUV422 pixel */
+                               if (pclk < (((hts * *vtsmin)/fps_denominator)
+                                       * fps_numerator * 2))
+                                       continue;
+
+                               if (pclk < best_pclk) {
+                                       best_pclk = pclk;
+                                       best_hts = hts;
+                                       best_i = i;
+                                       best_j = j;
+                                       best_k = k;
+                               }
+                       }
+               }
+       }
+
+       /* register contents */
+       *r3003 = (u8)best_j;
+       *r3004 = ((u8)best_i << 4) | (u8)best_k;
+
+       /* Did we get a valid PCLK? */
+       if (best_pclk == INT_MAX)
+               return -1;
+
+       *htsmin = best_hts;
+
+       /* Adjust vts to get as close to the desired frame rate as we can */
+       *vtsmin = best_pclk / ((best_hts/fps_denominator) * fps_numerator * 2);
+
+       return best_pclk;
+}
+
+static int ov1063x_set_regs(struct i2c_client *client,
+       const struct ov1063x_reg *regs, int nr_regs)
+{
+       int i, ret;
+       u8 val;
+
+       for (i = 0; i < nr_regs; i++) {
+               if (regs[i].reg == 0x300c) {
+                       val = ((client->addr * 2) | 0x1);
+
+                       ret = ov1063x_reg_write(client, regs[i].reg, val);
+                       if (ret)
+                               return ret;
+               } else {
+                       ret = ov1063x_reg_write(client, regs[i].reg,
+                                       regs[i].val);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
+/* Setup registers according to resolution and color encoding */
+static int ov1063x_set_params(struct i2c_client *client, u32 *width,
+                       u32 *height, enum v4l2_mbus_pixelcode code)
+{
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       int ret = -EINVAL;
+       int pclk;
+       int hts, vts;
+       u8 r3003, r3004, r4300;
+       int tmp;
+       u32 height_pre_subsample;
+       u32 width_pre_subsample;
+       u8 horiz_crop_mode;
+       int i;
+       int nr_isp_pixels;
+       int vert_sub_sample = 0;
+       int horiz_sub_sample = 0;
+       int sensor_width;
+
+       if ((*width > OV1063X_MAX_WIDTH) || (*height > OV1063X_MAX_HEIGHT))
+               return ret;
+
+       /* select format */
+       priv->cfmt = NULL;
+       for (i = 0; i < ARRAY_SIZE(ov1063x_cfmts); i++) {
+               if (code == ov1063x_cfmts[i].code) {
+                       priv->cfmt = ov1063x_cfmts + i;
+                       break;
+               }
+       }
+       if (!priv->cfmt)
+               goto ov1063x_set_fmt_error;
+
+       priv->width = *width;
+       priv->height = *height;
+
+       /* Vertical sub-sampling? */
+       height_pre_subsample = priv->height;
+       if (priv->height <= 400) {
+               vert_sub_sample = 1;
+               height_pre_subsample <<= 1;
+       }
+
+       /* Horizontal sub-sampling? */
+       width_pre_subsample = priv->width;
+       if (priv->width <= 640) {
+               horiz_sub_sample = 1;
+               width_pre_subsample <<= 1;
+       }
+
+       /* Horizontal cropping */
+       if (width_pre_subsample > 768) {
+               sensor_width = OV1063X_SENSOR_WIDTH;
+               horiz_crop_mode = 0x63;
+       } else if (width_pre_subsample > 656) {
+               sensor_width = 768;
+               horiz_crop_mode = 0x6b;
+       } else {
+               sensor_width = 656;
+               horiz_crop_mode = 0x73;
+       }
+
+       /* minimum values for hts and vts */
+       hts = sensor_width;
+       vts = height_pre_subsample + 50;
+       dev_dbg(&client->dev, "fps=(%d/%d), hts=%d, vts=%d\n",
+               priv->fps_numerator, priv->fps_denominator, hts, vts);
+
+       /* Get the best PCLK & adjust hts,vts accordingly */
+       pclk = ov1063x_get_pclk(priv->xvclk, &hts, &vts, priv->fps_numerator,
+                               priv->fps_denominator, &r3003, &r3004);
+       if (pclk < 0)
+               return ret;
+       dev_dbg(&client->dev, "pclk=%d, hts=%d, vts=%d\n", pclk, hts, vts);
+       dev_dbg(&client->dev, "r3003=0x%X r3004=0x%X\n", r3003, r3004);
+
+       dev_err(&client->dev, "r3003 = %x , r3004 = %x\n", r3003, r3004);
+
+       /* Disable ISP & program all registers that we might modify */
+       ret = ov1063x_set_regs(client, ov1063x_regs_change_mode,
+               ARRAY_SIZE(ov1063x_regs_change_mode));
+       if (ret)
+               return ret;
+
+       /* Set to 1280x720 */
+       ret = ov1063x_reg_write(client, 0x380f, 0x80);
+       if (ret)
+               return ret;
+
+       /* Set PLL */
+       ret = ov1063x_reg_write(client, 0x3003, r3003);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write(client, 0x3004, r3004);
+       if (ret)
+               return ret;
+
+       /* Set HSYNC */
+       ret = ov1063x_reg_write(client, 0x4700, 0x00);
+       if (ret)
+               return ret;
+
+       switch (priv->cfmt->code) {
+       case V4L2_MBUS_FMT_UYVY8_2X8:
+               r4300 = OV1063X_FORMAT_UYVY;
+               break;
+       case V4L2_MBUS_FMT_VYUY8_2X8:
+               r4300 = OV1063X_FORMAT_VYUY;
+               break;
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+               r4300 = OV1063X_FORMAT_YUYV;
+               break;
+       case V4L2_MBUS_FMT_YVYU8_2X8:
+               r4300 = OV1063X_FORMAT_YYYU;
+               break;
+       default:
+               r4300 = OV1063X_FORMAT_UYVY;
+               break;
+       }
+
+       /* Set format to UYVY */
+       ret = ov1063x_reg_write(client, OV1063X_FORMAT_CTRL00, r4300);
+       if (ret)
+               return ret;
+
+       dev_dbg(&client->dev, "r4300=0x%X\n", r4300);
+
+       /* Set output to 8-bit yuv */
+       ret = ov1063x_reg_write(client, 0x4605, 0x08);
+       if (ret)
+               return ret;
+
+       /* Horizontal cropping */
+       ret = ov1063x_reg_write(client, 0x3621, horiz_crop_mode);
+       if (ret)
+               return ret;
+
+       ret = ov1063x_reg_write(client, 0x3702, (pclk+1500000)/3000000);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write(client, 0x3703, (pclk+666666)/1333333);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write(client, 0x3704, (pclk+961500)/1923000);
+       if (ret)
+               return ret;
+
+       /* Vertical cropping */
+       tmp = ((OV1063X_SENSOR_HEIGHT - height_pre_subsample) / 2) & ~0x1;
+       ret = ov1063x_reg_write16(client, 0x3802, tmp);
+       if (ret)
+               return ret;
+       tmp = tmp + height_pre_subsample + 3;
+       ret = ov1063x_reg_write16(client, 0x3806, tmp);
+       if (ret)
+               return ret;
+
+       dev_err(&client->dev, "width x height = %x x %x\n",
+               priv->width, priv->height);
+       /* Output size */
+       ret = ov1063x_reg_write16(client, 0x3808, priv->width);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write16(client, 0x380a, priv->height);
+       if (ret)
+               return ret;
+
+       dev_err(&client->dev, "hts x vts = %x x %x\n", hts, vts);
+
+       ret = ov1063x_reg_write16(client, 0x380c, hts);
+       if (ret)
+               return ret;
+
+       ret = ov1063x_reg_write16(client, 0x380e, vts);
+       if (ret)
+               return ret;
+
+       if (vert_sub_sample) {
+               ret = ov1063x_reg_rmw(client, OV1063X_VFLIP,
+                                       OV1063X_VFLIP_SUBSAMPLE, 0);
+               if (ret)
+                       return ret;
+
+               ret = ov1063x_set_regs(client, ov1063x_regs_vert_sub_sample,
+                       ARRAY_SIZE(ov1063x_regs_vert_sub_sample));
+               if (ret)
+                       return ret;
+       }
+
+       ret = ov1063x_reg_write16(client, 0x4606, 2*hts);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write16(client, 0x460a, 2*(hts-width_pre_subsample));
+       if (ret)
+               return ret;
+
+       tmp = (vts - 8) * 16;
+       ret = ov1063x_reg_write16(client, 0xc488, tmp);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write16(client, 0xc48a, tmp);
+       if (ret)
+               return ret;
+
+       nr_isp_pixels = sensor_width * (priv->height + 4);
+       ret = ov1063x_reg_write16(client, 0xc4cc, nr_isp_pixels/256);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write16(client, 0xc4ce, nr_isp_pixels/256);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write16(client, 0xc512, nr_isp_pixels/16);
+       if (ret)
+               return ret;
+
+       /* Horizontal sub-sampling */
+       if (horiz_sub_sample) {
+               ret = ov1063x_reg_write(client, 0x5005, 0x9);
+               if (ret)
+                       return ret;
+
+               ret = ov1063x_reg_write(client, 0x3007, 0x2);
+               if (ret)
+                       return ret;
+       }
+
+       ret = ov1063x_reg_write16(client, 0xc518, vts);
+       if (ret)
+               return ret;
+       ret = ov1063x_reg_write16(client, 0xc51a, hts);
+       if (ret)
+               return ret;
+
+       /* Enable ISP blocks */
+       ret = ov1063x_set_regs(client, ov1063x_regs_enable,
+               ARRAY_SIZE(ov1063x_regs_enable));
+       if (ret)
+               return ret;
+
+       /* Wait for settings to take effect */
+       mdelay(500);
+
+       if (priv->cfmt->code == V4L2_MBUS_FMT_YUYV8_2X8)
+               dev_dbg(&client->dev, "Using 8-bit BT.656\n");
+       else
+               dev_dbg(&client->dev, "Using 10-bit BT.656\n");
+
+       return 0;
+
+ov1063x_set_fmt_error:
+       dev_err(&client->dev, "Unsupported settings (%dx%d@(%d/%d)fps)\n",
+               *width, *height, priv->fps_numerator, priv->fps_denominator);
+       priv = NULL;
+       priv->cfmt = NULL;
+
+       return ret;
+}
+
+static int ov1063x_g_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_mbus_framefmt *mf)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       enum v4l2_mbus_pixelcode code;
+
+       if (priv->cfmt)
+               code = priv->cfmt->code;
+       else
+               code = V4L2_MBUS_FMT_YUYV8_2X8;
+
+       mf->width       = priv->width;
+       mf->height      = priv->height;
+       mf->code        = priv->cfmt->code;
+       mf->colorspace  = priv->cfmt->colorspace;
+       mf->field       = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+/* set the format we will capture in */
+static int ov1063x_s_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_mbus_framefmt *mf)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       int ret;
+
+       ret = ov1063x_set_params(client, &mf->width, &mf->height,
+                               mf->code);
+       if (!ret)
+               mf->colorspace = priv->cfmt->colorspace;
+
+       return ret;
+}
+
+static int ov1063x_try_fmt(struct v4l2_subdev *sd,
+                       struct v4l2_mbus_framefmt *mf)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       int i;
+
+       /* Note: All sizes are good */
+
+       mf->field = V4L2_FIELD_NONE;
+
+       for (i = 0; i < ARRAY_SIZE(ov1063x_cfmts); i++)
+               if (mf->code == ov1063x_cfmts[i].code) {
+                       mf->colorspace  = ov1063x_cfmts[i].colorspace;
+                       break;
+               }
+
+       if (i == ARRAY_SIZE(ov1063x_cfmts)) {
+               /* Unsupported format requested. Propose either */
+               if (priv->cfmt) {
+                       /* the current one or */
+                       mf->colorspace = priv->cfmt->colorspace;
+                       mf->code = priv->cfmt->code;
+               } else {
+                       /* the default one */
+                       mf->colorspace = ov1063x_cfmts[0].colorspace;
+                       mf->code = ov1063x_cfmts[0].code;
+               }
+       }
+
+       return 0;
+}
+
+static int ov1063x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+                       enum v4l2_mbus_pixelcode *code)
+{
+       if (index >= ARRAY_SIZE(ov1063x_cfmts))
+               return -EINVAL;
+
+       *code = ov1063x_cfmts[index].code;
+
+       return 0;
+}
+
+static int ov1063x_enum_framesizes(struct v4l2_subdev *sd,
+                       struct v4l2_frmsizeenum *f)
+{
+       /* For now, hard coded resolutions for OV10635 sensor */
+       int cam_width[] =       { 1280, 1280, 752, 640, 600, 352, 320 };
+       int cam_height[] =      {  800,  720, 480, 480, 400, 288, 240 };
+
+       if (f->index >= ARRAY_SIZE(cam_width))
+               return -EINVAL;
+
+       f->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+       f->discrete.width = cam_width[f->index];
+       f->discrete.height = cam_height[f->index];
+       return 0;
+}
+
+static int ov1063x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       struct v4l2_captureparm *cp = &parms->parm.capture;
+
+       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memset(cp, 0, sizeof(struct v4l2_captureparm));
+       cp->capability = V4L2_CAP_TIMEPERFRAME;
+       cp->timeperframe.denominator = priv->fps_numerator;
+       cp->timeperframe.numerator = priv->fps_denominator;
+
+       return 0;
+}
+
+static int ov1063x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       struct v4l2_captureparm *cp = &parms->parm.capture;
+       enum v4l2_mbus_pixelcode code;
+       int ret;
+
+       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (cp->extendedmode != 0)
+               return -EINVAL;
+
+       /* FIXME Check we can handle the requested framerate */
+       priv->fps_denominator = cp->timeperframe.numerator;
+       priv->fps_numerator = cp->timeperframe.denominator;
+
+       if (priv->cfmt)
+               code = priv->cfmt->code;
+       else
+               code = V4L2_MBUS_FMT_YUYV8_2X8;
+
+       ret = ov1063x_set_params(client, &priv->width, &priv->height, code);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int ov1063x_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
+{
+       struct v4l2_crop a_writable = *a;
+       struct v4l2_rect *rect = &a_writable.c;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       int ret = -EINVAL;
+       enum v4l2_mbus_pixelcode code;
+
+       if (priv->cfmt)
+               code = priv->cfmt->code;
+       else
+               code = V4L2_MBUS_FMT_YUYV8_2X8;
+
+       ret = ov1063x_set_params(client, &rect->width, &rect->height, code);
+       if (!ret)
+               return -EINVAL;
+
+       rect->width = priv->width;
+       rect->height = priv->height;
+       rect->left = 0;
+       rect->top = 0;
+
+       return ret;
+}
+
+static int ov1063x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov1063x_priv *priv = to_ov1063x(client);
+
+       if (priv) {
+               a->c.width = priv->width;
+               a->c.height = priv->height;
+       } else {
+               a->c.width = OV1063X_MAX_WIDTH;
+               a->c.height = OV1063X_MAX_HEIGHT;
+       }
+
+       a->c.left = 0;
+       a->c.top = 0;
+       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       return 0;
+}
+
+static int ov1063x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+       a->bounds.left = 0;
+       a->bounds.top = 0;
+       a->bounds.width = OV1063X_MAX_WIDTH;
+       a->bounds.height = OV1063X_MAX_HEIGHT;
+       a->defrect = a->bounds;
+       a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       a->pixelaspect.numerator = 1;
+       a->pixelaspect.denominator = 1;
+
+       return 0;
+}
+
+static int ov1063x_init_gpios(struct i2c_client *client)
+{
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       int ret = 0;
+
+       ret = gpio_request_array(priv->mux_gpios, priv->num_gpios);
+       if (ret)
+               goto done;
+       gpio_free_array(priv->mux_gpios, priv->num_gpios);
+
+done:
+       return ret;
+}
+
+static int ov1063x_video_probe(struct i2c_client *client)
+{
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       u8 pid, ver;
+       u16 id;
+       int ret;
+
+       ret = ov1063x_set_regs(client, ov1063x_regs_default,
+               ARRAY_SIZE(ov1063x_regs_default));
+       if (ret)
+               return ret;
+
+       usleep_range(500, 510);
+
+       /* check and show product ID and manufacturer ID */
+       ret = ov1063x_reg_read(client, OV1063X_PID, &pid);
+       if (ret)
+               return ret;
+
+       id = pid << 8;
+       ret = ov1063x_reg_read(client, OV1063X_VER, &ver);
+       if (ret)
+               return ret;
+
+       id |= ver;
+       if (OV1063X_VERSION(pid, ver) == OV10635_VERSION_REG) {
+               priv->model = SENSOR_OV10635;
+               priv->revision = 1;
+       } else if (OV1063X_VERSION(pid, ver) == OV10633_VERSION_REG) {
+               priv->model = SENSOR_OV10633;
+               priv->revision = 1;
+       } else {
+               dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver);
+                               return -ENODEV;
+       }
+
+       dev_info(&client->dev, "ov1063x Product ID %x Manufacturer ID %x\n",
+                pid, ver);
+
+       /* Program all the 'standard' registers */
+
+       return v4l2_ctrl_handler_setup(&priv->hdl);
+}
+
+static const struct v4l2_ctrl_ops ov1063x_ctrl_ops = {
+       .s_ctrl = ov1063x_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops ov1063x_video_ops = {
+       .s_stream       = ov1063x_s_stream,
+       .g_mbus_fmt     = ov1063x_g_fmt,
+       .s_mbus_fmt     = ov1063x_s_fmt,
+       .try_mbus_fmt   = ov1063x_try_fmt,
+       .enum_mbus_fmt  = ov1063x_enum_fmt,
+       .enum_framesizes = ov1063x_enum_framesizes,
+       .cropcap        = ov1063x_cropcap,
+       .g_crop         = ov1063x_g_crop,
+       .s_crop         = ov1063x_s_crop,
+       .g_parm         = ov1063x_g_parm,
+       .s_parm         = ov1063x_s_parm,
+};
+
+static struct v4l2_subdev_ops ov1063x_subdev_ops = {
+       .video  = &ov1063x_video_ops,
+};
+
+/*
+ * i2c_driver function
+ */
+
+static int ov1063x_of_probe(struct i2c_client *client,
+                       struct device_node *node)
+{
+       struct ov1063x_priv *priv = to_ov1063x(client);
+       struct gpio *gpios = &priv->mux_gpios[0];
+       unsigned int flags;
+       int i, gpio;
+
+       /* Iterate over all the gpios in the device tree
+        * ENOENT is returned when trying to access last + 1 gpio */
+       for (i = 0; i < MAX_NUM_GPIOS; i++) {
+               gpio = of_get_named_gpio_flags(node, "mux-gpios", i, &flags);
+               if (gpio_is_valid(gpio)) {
+                       gpios[i].gpio   = gpio;
+                       gpios[i].flags  = (flags & GPIO_ACTIVE_LOW) ?
+                               GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
+                       gpios[i].label  = client->name;
+               } else if (gpio == -ENOENT) {
+                       break;
+               } else {
+                       return gpio;
+               }
+       }
+       priv->num_gpios = i;
+       return 0;
+}
+
+static int ov1063x_probe(struct i2c_client *client,
+                        const struct i2c_device_id *did)
+{
+       struct device_node *node = client->dev.of_node;
+       struct ov1063x_priv *priv;
+       struct v4l2_subdev *sd;
+       int ret = 0;
+
+       priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, priv);
+
+       ret = ov1063x_of_probe(client, node);
+       if (ret)
+               goto err;
+
+       /* TODO External XVCLK is board specific */
+       priv->xvclk = 24000000;
+       /* Default framerate */
+       priv->fps_numerator = 30;
+       priv->fps_denominator = 1;
+       priv->cfmt = &ov1063x_cfmts[0];
+       priv->width = OV1063X_MAX_WIDTH;
+       priv->height = OV1063X_MAX_HEIGHT;
+
+       sd = &(priv->subdev);
+       v4l2_i2c_subdev_init(sd, client, &ov1063x_subdev_ops);
+       v4l2_ctrl_handler_init(&priv->hdl, 2);
+       v4l2_ctrl_new_std(&priv->hdl, &ov1063x_ctrl_ops,
+                         V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&priv->hdl, &ov1063x_ctrl_ops,
+                         V4L2_CID_HFLIP, 0, 1, 1, 0);
+       priv->subdev.ctrl_handler = &priv->hdl;
+       if (priv->hdl.error) {
+               ret = priv->hdl.error;
+               goto err;
+       }
+
+       ret = ov1063x_init_gpios(client);
+       if (ret) {
+               dev_err(&client->dev, "Failed to request gpios");
+               goto err;
+       }
+
+       ret = ov1063x_video_probe(client);
+       if (ret) {
+               v4l2_ctrl_handler_free(&priv->hdl);
+               goto err;
+       }
+
+       sd->dev = &client->dev;
+       ret = v4l2_async_register_subdev(sd);
+
+       pm_runtime_enable(&client->dev);
+
+err:
+       return ret;
+}
+
+static int ov1063x_remove(struct i2c_client *client)
+{
+       struct ov1063x_priv *priv = i2c_get_clientdata(client);
+
+       v4l2_device_unregister_subdev(&priv->subdev);
+       v4l2_ctrl_handler_free(&priv->hdl);
+
+       return 0;
+}
+
+static const struct i2c_device_id ov1063x_id[] = {
+       { "ov10635", 0 },
+       { "ov10633", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ov1063x_id);
+
+#if defined(CONFIG_OF)
+static const struct of_device_id ov1063x_dt_id[] = {
+       {
+               .compatible = "ovti,ov10635", .data = "ov10635"
+       },
+       {
+               .compatible = "ovti,ov10633", .data = "ov10633"
+       },
+       {
+       }
+};
+
+#else
+#define ov1063x_dt_id NULL
+#endif
+
+static struct i2c_driver ov1063x_i2c_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "ov1063x",
+               .of_match_table = ov1063x_dt_id,
+       },
+       .probe = ov1063x_probe,
+       .remove = ov1063x_remove,
+       .id_table = ov1063x_id,
+};
+
+module_i2c_driver(ov1063x_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV1063X");
+MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/ov1063x_regs.h b/drivers/media/i2c/ov1063x_regs.h
new file mode 100644 (file)
index 0000000..74545f7
--- /dev/null
@@ -0,0 +1,682 @@
+
+struct ov1063x_reg {
+       u16     reg;
+       u8      val;
+};
+
+static const struct ov1063x_reg ov1063x_regs_default[] = {
+       /* Register configuration for full resolution : 1280x720 */
+               {0x103, 0x1},    /** Software Reset */
+               {0x301b, 0xff},  /** System Control Clock Reset #1 */
+               {0x301c, 0xff},  /** System Control Clock Reset #2 */
+               {0x301a, 0xff},  /** System Control Clock Reset #0 */
+               {0x300c, 0x61},  /** Serial Camera Control Bus ID */
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x300c, 0x61},
+               {0x3021, 0x3},  /** System Control Misc */
+               {0x3011, 0x2},
+               {0x6900, 0xc},
+               {0x6901, 0x1},
+               {0x3033, 0x8},  /** System clock/4 */
+               {0x3503, 0x10}, /** AEC Delay enabled */
+               {0x302d, 0x2f}, /** Power Down Control */
+               {0x3025, 0x3},  /** Debug Control enabled */
+               /*
+                * FPS is computed as:
+                * XVCLK           = 9MHz
+                * preDivide   = {/1,/1.5,/2,/3,/4,/5,/6,/7}
+                * decided based on (0x3004[6:4].
+                * numerator   = (0x3003[5:0] * XVCLK)/preDivide)
+                * denominator = (2 * (1+0x3004[2:0]))
+                * FPS = numerator/denominator.
+                */
+               /* {0x3003, 0x1B}, */ /* fps = 30fps. */
+               /* {0x3004, 0x03}, */
+#ifdef CONFIG_VIDEO_TI_LVDS
+               {0x3003, 0x20}, /* fps = 15fps. */
+               {0x3004, 0x3},
+#else
+               {0x3003, 0x28}, /* fps = 15fps. */
+               {0x3004, 0x31},
+#endif
+               {0x3005, 0x20},
+               {0x3006, 0x91},
+               {0x3600, 0x74},
+               {0x3601, 0x2b},
+               {0x3612, 0x0},
+               {0x3611, 0x67},
+               {0x3633, 0xba},
+               {0x3602, 0x2f},
+               {0x3603, 0x0},
+               {0x3630, 0xa8},
+               {0x3631, 0x16},
+               {0x3714, 0x10},
+               {0x371d, 0x1},
+               {0x4300, 0x3A}, /* UYVY mode */
+               {0x3007, 0x1},
+               /*
+                * RAW mode and Pixel CLK selct.
+                * 0x3024[0] = 1 :: System CLK (0x3003,0x3004)
+                * 0x3024[0] = 0 :: secondary CLK (0x3005,0x3006)
+                */
+               {0x3024, 0x1},
+               {0x3020, 0xb},
+               {0x3702, 0xd},
+               {0x3703, 0x20},
+               {0x3704, 0x15},
+               {0x3709, 0x28},
+               {0x370d, 0x0},
+               {0x3712, 0x0},
+               {0x3713, 0x20},
+               {0x3715, 0x4},
+               {0x381d, 0x40},
+               {0x381c, 0x0},
+               {0x3824, 0x10},
+               {0x3815, 0x8c},
+               {0x3804, 0x5},
+               {0x3805, 0x1f},
+               {0x3800, 0x0},
+               {0x3801, 0x0},
+               {0x3806, 0x3},
+               {0x3807, 0x1},
+               {0x3802, 0x0},
+               {0x3803, 0x2e},
+               {0x3808, 0x5},
+               {0x3809, 0x0},
+               {0x380a, 0x2},
+               {0x380b, 0xd0},
+               {0x380c, 0x6},
+               {0x380d, 0xf6}, /* 1280x720 */
+#ifdef CONFIG_VIDEO_TI_LVDS
+               {0x380e, 0x3},
+               {0x380f, 0x80},
+#else
+               {0x380e, 0x2},
+               {0x380f, 0xec}, /* 1280x720 */
+#endif
+               {0x3811, 0x8},
+               {0x381f, 0xc},
+               {0x3621, 0x63},
+               {0x5005, 0x8},
+               {0x56d5, 0x0},
+               {0x56d6, 0x80},
+               {0x56d7, 0x0},
+               {0x56d8, 0x0},
+               {0x56d9, 0x0},
+               {0x56da, 0x80},
+               {0x56db, 0x0},
+               {0x56dc, 0x0},
+               {0x56e8, 0x0},
+               {0x56e9, 0x7f},
+               {0x56ea, 0x0},
+               {0x56eb, 0x7f},
+               {0x5100, 0x0},
+               {0x5101, 0x80},
+               {0x5102, 0x0},
+               {0x5103, 0x80},
+               {0x5104, 0x0},
+               {0x5105, 0x80},
+               {0x5106, 0x0},
+               {0x5107, 0x80},
+               {0x5108, 0x0},
+               {0x5109, 0x0},
+               {0x510a, 0x0},
+               {0x510b, 0x0},
+               {0x510c, 0x0},
+               {0x510d, 0x0},
+               {0x510e, 0x0},
+               {0x510f, 0x0},
+               {0x5110, 0x0},
+               {0x5111, 0x80},
+               {0x5112, 0x0},
+               {0x5113, 0x80},
+               {0x5114, 0x0},
+               {0x5115, 0x80},
+               {0x5116, 0x0},
+               {0x5117, 0x80},
+               {0x5118, 0x0},
+               {0x5119, 0x0},
+               {0x511a, 0x0},
+               {0x511b, 0x0},
+               {0x511c, 0x0},
+               {0x511d, 0x0},
+               {0x511e, 0x0},
+               {0x511f, 0x0},
+               {0x56d0, 0x0},
+               {0x5006, 0x24},
+               {0x5608, 0x0},
+               {0x52d7, 0x6},
+               {0x528d, 0x8},
+               {0x5293, 0x12},
+               {0x52d3, 0x12},
+               {0x5288, 0x6},
+               {0x5289, 0x20},
+               {0x52c8, 0x6},
+               {0x52c9, 0x20},
+               {0x52cd, 0x4},
+               {0x5381, 0x0},
+               {0x5382, 0xff},
+               {0x5589, 0x76},
+               {0x558a, 0x47},
+               {0x558b, 0xef},
+               {0x558c, 0xc9},
+               {0x558d, 0x49},
+               {0x558e, 0x30},
+               {0x558f, 0x67},
+               {0x5590, 0x3f},
+               {0x5591, 0xf0},
+               {0x5592, 0x10},
+               {0x55a2, 0x6d},
+               {0x55a3, 0x55},
+               {0x55a4, 0xc3},
+               {0x55a5, 0xb5},
+               {0x55a6, 0x43},
+               {0x55a7, 0x38},
+               {0x55a8, 0x5f},
+               {0x55a9, 0x4b},
+               {0x55aa, 0xf0},
+               {0x55ab, 0x10},
+               {0x5581, 0x52},
+               {0x5300, 0x1},
+               {0x5301, 0x0},
+               {0x5302, 0x0},
+               {0x5303, 0xe},
+               {0x5304, 0x0},
+               {0x5305, 0xe},
+               {0x5306, 0x0},
+               {0x5307, 0x36},
+               {0x5308, 0x0},
+               {0x5309, 0xd9},
+               {0x530a, 0x0},
+               {0x530b, 0xf},
+               {0x530c, 0x0},
+               {0x530d, 0x2c},
+               {0x530e, 0x0},
+               {0x530f, 0x59},
+               {0x5310, 0x0},
+               {0x5311, 0x7b},
+               {0x5312, 0x0},
+               {0x5313, 0x22},
+               {0x5314, 0x0},
+               {0x5315, 0xd5},
+               {0x5316, 0x0},
+               {0x5317, 0x13},
+               {0x5318, 0x0},
+               {0x5319, 0x18},
+               {0x531a, 0x0},
+               {0x531b, 0x26},
+               {0x531c, 0x0},
+               {0x531d, 0xdc},
+               {0x531e, 0x0},
+               {0x531f, 0x2},
+               {0x5320, 0x0},
+               {0x5321, 0x24},
+               {0x5322, 0x0},
+               {0x5323, 0x56},
+               {0x5324, 0x0},
+               {0x5325, 0x85},
+               {0x5326, 0x0},
+               {0x5327, 0x20},
+               {0x5609, 0x1},
+               {0x560a, 0x40},
+               {0x560b, 0x1},
+               {0x560c, 0x40},
+               {0x560d, 0x0},
+               {0x560e, 0xfa},
+               {0x560f, 0x0},
+               {0x5610, 0xfa},
+               {0x5611, 0x2},
+               {0x5612, 0x80},
+               {0x5613, 0x2},
+               {0x5614, 0x80},
+               {0x5615, 0x1},
+               {0x5616, 0x2c},
+               {0x5617, 0x1},
+               {0x5618, 0x2c},
+               {0x563b, 0x1},
+               {0x563c, 0x1},
+               {0x563d, 0x1},
+               {0x563e, 0x1},
+               {0x563f, 0x3},
+               {0x5640, 0x3},
+               {0x5641, 0x3},
+               {0x5642, 0x5},
+               {0x5643, 0x9},
+               {0x5644, 0x5},
+               {0x5645, 0x5},
+               {0x5646, 0x5},
+               {0x5647, 0x5},
+               {0x5651, 0x0},
+               {0x5652, 0x80},
+               {0x521a, 0x1},
+               {0x521b, 0x3},
+               {0x521c, 0x6},
+               {0x521d, 0xa},
+               {0x521e, 0xe},
+               {0x521f, 0x12},
+               {0x5220, 0x16},
+               {0x5223, 0x2},
+               {0x5225, 0x4},
+               {0x5227, 0x8},
+               {0x5229, 0xc},
+               {0x522b, 0x12},
+               {0x522d, 0x18},
+               {0x522f, 0x1e},
+               {0x5241, 0x4},
+               {0x5242, 0x1},
+               {0x5243, 0x3},
+               {0x5244, 0x6},
+               {0x5245, 0xa},
+               {0x5246, 0xe},
+               {0x5247, 0x12},
+               {0x5248, 0x16},
+               {0x524a, 0x3},
+               {0x524c, 0x4},
+               {0x524e, 0x8},
+               {0x5250, 0xc},
+               {0x5252, 0x12},
+               {0x5254, 0x18},
+               {0x5256, 0x1e},
+#ifdef CONFIG_VIDEO_TI_LVDS
+               {0x4605, 0x8},
+#else
+               {0x4605, 0x00}, /* 8-bit YUV mode. */
+#endif
+               {0x4606, 0x7},
+               {0x4607, 0x71},
+               {0x460a, 0x2},
+               {0x460b, 0x70},
+               {0x460c, 0x0},
+               {0x4620, 0xe},
+               {0x4700, 0x4},
+               {0x4701, 0x01},
+               /* {0x4702, 0x1}, */
+               {0x4702, 0x00},  /* 01 */
+               {0x4703, 0x00},
+               {0x4704, 0x00}, /* 01 */
+               /*
+                * Non-overlapping HSYNC-VSYNC.
+                * Therefore do not set the VSYNC delay registers.
+                */
+               {0x4705, 0x00}, /* Vsync delay high byte */
+               {0x4706, 0x00}, /* Vsync delay middle byte */
+               {0x4707, 0x00}, /* Vsync delay low byte{0x4708, 0x1}, */
+               /* {0x4709, 0x50}, */
+               {0x4004, 0x8},
+               {0x4005, 0x18},
+               {0x4001, 0x4},
+               {0x4050, 0x20},
+               {0x4051, 0x22},
+               {0x4057, 0x9c},
+               {0x405a, 0x0},
+               {0x4202, 0x2},
+               {0x3023, 0x10},
+               {0x100, 0x1},
+               {0x100, 0x1},
+               {0x6f0e, 0x0},
+               {0x6f0f, 0x0},
+               {0x460e, 0x8},
+               {0x460f, 0x1},
+               {0x4610, 0x0},
+               {0x4611, 0x1},
+               {0x4612, 0x0},
+               {0x4613, 0x1},
+#ifdef CONFIG_VIDEO_TI_LVDS
+               {0x4605, 0x8},
+#else
+               {0x4605, 0x00},
+#endif
+               {0x4608, 0x0},
+               {0x4609, 0x8},
+               {0x6804, 0x0},
+               {0x6805, 0x6},
+               {0x6806, 0x0},
+               {0x5120, 0x0},
+               {0x3510, 0x0},
+               {0x3504, 0x0},
+               {0x6800, 0x0},
+               {0x6f0d, 0x0},
+               {0x5000, 0xff},
+               {0x5001, 0xbf},
+               {0x5002, 0xfe},
+               {0x503d, 0x0},
+               /* {0x503e, 0x00}, */
+               {0xc450, 0x1},
+               {0xc452, 0x4},
+               {0xc453, 0x0},
+               {0xc454, 0x0},
+               {0xc455, 0x0},
+               {0xc456, 0x0},
+               {0xc457, 0x0},
+               {0xc458, 0x0},
+               {0xc459, 0x0},
+               {0xc45b, 0x0},
+               {0xc45c, 0x0},
+               {0xc45d, 0x0},
+               {0xc45e, 0x0},
+               {0xc45f, 0x0},
+               {0xc460, 0x0},
+               {0xc461, 0x1},
+               {0xc462, 0x1},
+               {0xc464, 0x88},
+               {0xc465, 0x0},
+               {0xc466, 0x8a},
+               {0xc467, 0x0},
+               {0xc468, 0x86},
+               {0xc469, 0x0},
+               {0xc46a, 0x40},
+               {0xc46b, 0x50},
+               {0xc46c, 0x30},
+               {0xc46d, 0x28},
+               {0xc46e, 0x60},
+               {0xc46f, 0x40},
+               {0xc47c, 0x1},
+               {0xc47d, 0x38},
+               {0xc47e, 0x0},
+               {0xc47f, 0x0},
+               {0xc480, 0x0},
+               {0xc481, 0xff},
+               {0xc482, 0x0},
+               {0xc483, 0x40},
+               {0xc484, 0x0},
+               {0xc485, 0x18},
+               {0xc486, 0x0},
+               {0xc487, 0x18},
+               {0xc488, 0x2e},
+               {0xc489, 0x80},
+               {0xc48a, 0x2e},
+               {0xc48b, 0x80},
+               {0xc48c, 0x0},
+               {0xc48d, 0x4},
+               {0xc48e, 0x0},
+               {0xc48f, 0x4},
+               {0xc490, 0x7},
+               {0xc492, 0x20},
+               {0xc493, 0x8},
+               {0xc498, 0x2},
+               {0xc499, 0x0},
+               {0xc49a, 0x2},
+               {0xc49b, 0x0},
+               {0xc49c, 0x2},
+               {0xc49d, 0x0},
+               {0xc49e, 0x2},
+               {0xc49f, 0x60},
+               {0xc4a0, 0x4},
+               {0xc4a1, 0x0},
+               {0xc4a2, 0x6},
+               {0xc4a3, 0x0},
+               {0xc4a4, 0x0},
+               {0xc4a5, 0x10},
+               {0xc4a6, 0x0},
+               {0xc4a7, 0x40},
+               {0xc4a8, 0x0},
+               {0xc4a9, 0x80},
+               {0xc4aa, 0xd},
+               {0xc4ab, 0x0},
+               {0xc4ac, 0xf},
+               {0xc4ad, 0xc0},
+               {0xc4b4, 0x1},
+               {0xc4b5, 0x1},
+               {0xc4b6, 0x0},
+               {0xc4b7, 0x1},
+               {0xc4b8, 0x0},
+               {0xc4b9, 0x1},
+               {0xc4ba, 0x1},
+               {0xc4bb, 0x0},
+               {0xc4be, 0x2},
+               {0xc4bf, 0x33},
+               {0xc4c8, 0x3},
+               {0xc4c9, 0xd0},
+               {0xc4ca, 0xe},
+               {0xc4cb, 0x0},
+               {0xc4cc, 0xe},
+               {0xc4cd, 0x51},
+               {0xc4ce, 0xe},
+               {0xc4cf, 0x51},
+               {0xc4d0, 0x4},
+               {0xc4d1, 0x80},
+               {0xc4e0, 0x4},
+               {0xc4e1, 0x2},
+               {0xc4e2, 0x1},
+               {0xc4e4, 0x10},
+               {0xc4e5, 0x20},
+               {0xc4e6, 0x30},
+               {0xc4e7, 0x40},
+               {0xc4e8, 0x50},
+               {0xc4e9, 0x60},
+               {0xc4ea, 0x70},
+               {0xc4eb, 0x80},
+               {0xc4ec, 0x90},
+               {0xc4ed, 0xa0},
+               {0xc4ee, 0xb0},
+               {0xc4ef, 0xc0},
+               {0xc4f0, 0xd0},
+               {0xc4f1, 0xe0},
+               {0xc4f2, 0xf0},
+               {0xc4f3, 0x80},
+               {0xc4f4, 0x0},
+               {0xc4f5, 0x20},
+               {0xc4f6, 0x2},
+               {0xc4f7, 0x0},
+               {0xc4f8, 0x4},
+               {0xc4f9, 0xb},
+               {0xc4fa, 0x0},
+               {0xc4fb, 0x1},
+               {0xc4fc, 0x1},
+               {0xc4fd, 0x1},
+               {0xc4fe, 0x4},
+               {0xc4ff, 0x2},
+               {0xc500, 0x68},
+               {0xc501, 0x74},
+               {0xc502, 0x70},
+               {0xc503, 0x80},
+               {0xc504, 0x5},
+               {0xc505, 0x80},
+               {0xc506, 0x3},
+               {0xc507, 0x80},
+               {0xc508, 0x1},
+               {0xc509, 0xc0},
+               {0xc50a, 0x1},
+               {0xc50b, 0xa0},
+               {0xc50c, 0x1},
+               {0xc50d, 0x2c},
+               {0xc50e, 0x1},
+               {0xc50f, 0xa},
+               {0xc510, 0x0},
+               {0xc511, 0x0},
+               {0xc512, 0xe5},
+               {0xc513, 0x14},
+               {0xc514, 0x4},
+               {0xc515, 0x0},
+               {0xc518, 0x3},
+               {0xc519, 0x48},
+               {0xc51a, 0x7},
+               {0xc51b, 0x70},
+               {0xc2e0, 0x0},
+               {0xc2e1, 0x51},
+               {0xc2e2, 0x0},
+               {0xc2e3, 0xd6},
+               {0xc2e4, 0x1},
+               {0xc2e5, 0x5e},
+               {0xc2e9, 0x1},
+               {0xc2ea, 0x7a},
+               {0xc2eb, 0x90},
+               {0xc2ed, 0x1},
+               {0xc2ee, 0x7a},
+               {0xc2ef, 0x64},
+               {0xc308, 0x0},
+               {0xc309, 0x0},
+               {0xc30a, 0x0},
+               {0xc30c, 0x0},
+               {0xc30d, 0x1},
+               {0xc30e, 0x0},
+               {0xc30f, 0x0},
+               {0xc310, 0x1},
+               {0xc311, 0x60},
+               {0xc312, 0xff},
+               {0xc313, 0x8},
+               {0xc314, 0x1},
+               {0xc315, 0x7f},
+               {0xc316, 0xff},
+               {0xc317, 0xb},
+               {0xc318, 0x0},
+               {0xc319, 0xc},
+               {0xc31a, 0x0},
+               {0xc31b, 0xe0},
+               {0xc31c, 0x0},
+               {0xc31d, 0x14},
+               {0xc31e, 0x0},
+               {0xc31f, 0xc5},
+               {0xc320, 0xff},
+               {0xc321, 0x4b},
+               {0xc322, 0xff},
+               {0xc323, 0xf0},
+               {0xc324, 0xff},
+               {0xc325, 0xe8},
+               {0xc326, 0x0},
+               {0xc327, 0x46},
+               {0xc328, 0xff},
+               {0xc329, 0xd2},
+               {0xc32a, 0xff},
+               {0xc32b, 0xe4},
+               {0xc32c, 0xff},
+               {0xc32d, 0xbb},
+               {0xc32e, 0x0},
+               {0xc32f, 0x61},
+               {0xc330, 0xff},
+               {0xc331, 0xf9},
+               {0xc332, 0x0},
+               {0xc333, 0xd9},
+               {0xc334, 0x0},
+               {0xc335, 0x2e},
+               {0xc336, 0x0},
+               {0xc337, 0xb1},
+               {0xc338, 0xff},
+               {0xc339, 0x64},
+               {0xc33a, 0xff},
+               {0xc33b, 0xeb},
+               {0xc33c, 0xff},
+               {0xc33d, 0xe8},
+               {0xc33e, 0x0},
+               {0xc33f, 0x48},
+               {0xc340, 0xff},
+               {0xc341, 0xd0},
+               {0xc342, 0xff},
+               {0xc343, 0xed},
+               {0xc344, 0xff},
+               {0xc345, 0xad},
+               {0xc346, 0x0},
+               {0xc347, 0x66},
+               {0xc348, 0x1},
+               {0xc349, 0x0},
+               {0x6700, 0x4},
+               {0x6701, 0x7b},
+               {0x6702, 0xfd},
+               {0x6703, 0xf9},
+               {0x6704, 0x3d},
+               {0x6705, 0x71},
+               /*
+                * 0x6706[3:0] :: XVCLK
+                * 0x6706[3:0] :: 0 = 6MHz
+                * 0x6706[3:0] :: 1 = 9MHz
+                * 0x6706[3:0] :: 8 = 24MHz
+                * 0x6706[3:0] :: 9 = 27MHz
+                */
+#ifdef CONFIG_VIDEO_TI_LVDS
+               {0x6706, 0x78},
+#else
+               {0x6706, 0x71},
+#endif
+               {0x6708, 0x5},
+               {0x3822, 0x50},
+               {0x6f06, 0x6f},
+               {0x6f07, 0x0},
+               {0x6f0a, 0x6f},
+               {0x6f0b, 0x0},
+               {0x6f00, 0x3},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x3042, 0xf0},
+               {0x301b, 0xf0},
+               {0x301c, 0xf0},
+               {0x301a, 0xf0},
+               {0x301c, 0x70},
+};
+
+static const struct ov1063x_reg ov1063x_regs_change_mode[] = {
+       { 0x301b, 0xff }, { 0x301c, 0xff }, { 0x301a, 0xff }, { 0x5005, 0x08 },
+       { 0x3007, 0x01 }, { 0x381c, 0x00 }, { 0x381f, 0x0C }, { 0x4001, 0x04 },
+       { 0x4004, 0x08 }, { 0x4050, 0x20 }, { 0x4051, 0x22 }, { 0x6e47, 0x0C },
+       { 0x4610, 0x05 }, { 0x4613, 0x10 },
+};
+
+static const struct ov1063x_reg ov1063x_regs_bt656[] = {
+       { 0x4700, 0x02 }, { 0x4302, 0x03 }, { 0x4303, 0xf8 }, { 0x4304, 0x00 },
+       { 0x4305, 0x08 }, { 0x4306, 0x03 }, { 0x4307, 0xf8 }, { 0x4308, 0x00 },
+       { 0x4309, 0x08 },
+};
+
+static const struct ov1063x_reg ov1063x_regs_bt656_10bit[] = {
+       { 0x4700, 0x02 }, { 0x4302, 0x03 }, { 0x4303, 0xfe }, { 0x4304, 0x00 },
+       { 0x4305, 0x02 }, { 0x4306, 0x03 }, { 0x4307, 0xfe }, { 0x4308, 0x00 },
+       { 0x4309, 0x02 },
+};
+
+static const struct ov1063x_reg ov1063x_regs_vert_sub_sample[] = {
+       { 0x381f, 0x06 }, { 0x4001, 0x02 }, { 0x4004, 0x02 }, { 0x4050, 0x10 },
+       { 0x4051, 0x11 }, { 0x6e47, 0x06 }, { 0x4610, 0x03 }, { 0x4613, 0x0a },
+};
+
+static const struct ov1063x_reg ov1063x_regs_enable[] = {
+       { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 },
+       { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 },
+       { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 },
+       { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 },
+       { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 },
+       { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x3042, 0xf9 },
+       { 0x3042, 0xf9 }, { 0x3042, 0xf9 }, { 0x301b, 0xf0 }, { 0x301c, 0xf0 },
+       { 0x301a, 0xf0 },
+};
index f3e78e1fb4d22b4214ef9a0d2ab0fa4d50341154..38efe62da5331c769e33e5c2db46c26679b90f01 100644 (file)
@@ -129,6 +129,21 @@ config VIDEO_TI_VIP
        Driver support for VIP module on certain TI SoC's
        VIP = Video Input Port.
 
+config VIDEO_TI_CAL
+       tristate "TI CAL (Camera Adaptation Layer) driver"
+       depends on VIDEO_DEV && VIDEO_V4L2 && SOC_DRA7XX
+       select MEDIA_CONTROLLER
+       select VIDEO_V4L2_SUBDEV_API
+       select VIDEOBUF2_DMA_CONTIG
+       select FONT_SUPPORT
+       select FONT_8x16
+       select VIDEOBUF2_VMALLOC
+       default n
+       ---help---
+         Support for the TI CAL (Camera Adaptation Layer) block
+         found on DRA72X SoC.
+         In TI Technical Reference Manual this module is refered as
+         Camera Interface Subsystem (CAMSS).
 
 endif # V4L_PLATFORM_DRIVERS
 
index bd6b32174db6bbece21e205066ae23444e58fba1..0c40efa71141d7028bc36f4fa2793446eac0b94d 100644 (file)
@@ -21,6 +21,8 @@ obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
 
 obj-$(CONFIG_VIDEO_TI_VPE)             += ti-vpe/
 
+obj-$(CONFIG_VIDEO_TI_CAL)             += ti-vpe/
+
 obj-$(CONFIG_VIDEO_MX2_EMMAPRP)                += mx2_emmaprp.o
 obj-$(CONFIG_VIDEO_CODA)               += coda.o
 
index f723f1f2f5784e4501e7b39dcb027c507523cb07..ab851278d9d0829d4a005eff54ef64efdc5f5e21 100644 (file)
@@ -30,7 +30,7 @@
 
 /* Offset base used to differentiate between CAPTURE and OUTPUT
 *  while mmaping */
-#define DST_QUEUE_OFF_BASE      (TASK_SIZE / 2)
+#define DST_QUEUE_OFF_BASE     (1 << 30)
 
 #define MFC_BANK1_ALLOC_CTX    0
 #define MFC_BANK2_ALLOC_CTX    1
index 744e43b480bcc217f3da9522cc992061fa7f691a..f698e322a1cd62b64f0573a1e706fb8254ccbd53 100644 (file)
@@ -1183,6 +1183,7 @@ static int sh_veu_probe(struct platform_device *pdev)
        }
 
        *vdev = sh_veu_videodev;
+       vdev->v4l2_dev = &veu->v4l2_dev;
        spin_lock_init(&veu->lock);
        mutex_init(&veu->fop_lock);
        vdev->lock = &veu->fop_lock;
index 3ac9c207889d299abc085cb50ab419554135260a..1dce806eac15f137aa4aa3c325c0687a5e6e2c43 100644 (file)
@@ -12,3 +12,6 @@ ti-vpe-y := vpe.o sc.o csc.o
 ti-vip-y := vip.o
 ti-vpdma-y := vpdma.o
 
+obj-$(CONFIG_VIDEO_TI_CAL) += ti-cal.o
+
+ti-cal-y := cal.o
diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c
new file mode 100644 (file)
index 0000000..27b96a9
--- /dev/null
@@ -0,0 +1,2328 @@
+/*
+ * TI CAL camera interface driver
+ *
+ * Copyright (c) 2015 Texas Instruments Inc.
+ * Benoit Parrot, <bparrot@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioctl.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+
+#include <media/v4l2-of.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-common.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+#include "cal_regs.h"
+
+#define CAL_MODULE_NAME "cal"
+
+#define MAX_WIDTH 1920
+#define MAX_HEIGHT 1200
+
+#define CAL_VERSION "0.1.0"
+
+MODULE_DESCRIPTION("TI CAL driver");
+MODULE_AUTHOR("Benoit Parrot, <bparrot@ti.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(CAL_VERSION);
+
+static unsigned video_nr = -1;
+module_param(video_nr, uint, 0644);
+MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
+
+static unsigned n_devs = 2;
+module_param(n_devs, uint, 0644);
+MODULE_PARM_DESC(n_devs, "number of video devices to create");
+
+static unsigned debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+/* timeperframe: min/max and default */
+static const struct v4l2_fract
+       tpf_default = {.numerator = 1001,       .denominator = 30000};
+
+#define cal_dbg(level, caldev, fmt, arg...)    \
+               v4l2_dbg(level, debug, &caldev->v4l2_dev, fmt, ##arg)
+#define cal_info(caldev, fmt, arg...)  \
+               v4l2_info(&caldev->v4l2_dev, fmt, ##arg)
+#define cal_err(caldev, fmt, arg...)   \
+               v4l2_err(&caldev->v4l2_dev, fmt, ##arg)
+
+#define ctx_dbg(level, ctx, fmt, arg...)       \
+               v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg)
+#define ctx_info(ctx, fmt, arg...)     \
+               v4l2_info(&ctx->v4l2_dev, fmt, ##arg)
+#define ctx_err(ctx, fmt, arg...)      \
+               v4l2_err(&ctx->v4l2_dev, fmt, ##arg)
+
+/* ------------------------------------------------------------------
+       Basic structures
+   ------------------------------------------------------------------*/
+
+struct cal_fmt {
+       const char *name;
+       u32     fourcc;
+       u32     code;
+       u32     colorspace;
+       u8      depth;
+       bool    supported;
+       u32     index;
+};
+
+static const struct cal_fmt formats[] = {
+       {
+               .name           = "YUV 4:2:2 packed, YCbYCr",
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .code           = V4L2_MBUS_FMT_YUYV8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "YUV 4:2:2 packed, CbYCrY",
+               .fourcc         = V4L2_PIX_FMT_UYVY,
+               .code           = V4L2_MBUS_FMT_UYVY8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "YUV 4:2:2 packed, YCrYCb",
+               .fourcc         = V4L2_PIX_FMT_YVYU,
+               .code           = V4L2_MBUS_FMT_YVYU8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "4YUV 4:2:2 packed, CrYCbY",
+               .fourcc         = V4L2_PIX_FMT_VYUY,
+               .code           = V4L2_MBUS_FMT_VYUY8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RGB565 (LE)",
+               .fourcc         = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
+               .code           = V4L2_MBUS_FMT_RGB565_2X8_LE,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RGB565 (BE)",
+               .fourcc         = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
+               .code           = V4L2_MBUS_FMT_RGB565_2X8_BE,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RGB555 (LE)",
+               .fourcc         = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
+               .code           = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RGB555 (BE)",
+               .fourcc         = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
+               .code           = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RGB24 (LE)",
+               .fourcc         = V4L2_PIX_FMT_RGB24, /* rgb */
+               .code           = V4L2_MBUS_FMT_RGB888_2X12_LE,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 24,
+               .supported      = false,
+       }, {
+               .name           = "RGB24 (BE)",
+               .fourcc         = V4L2_PIX_FMT_BGR24, /* bgr */
+               .code           = V4L2_MBUS_FMT_RGB888_2X12_BE,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 24,
+               .supported      = false,
+       }, {
+               .name           = "RGB32",
+               .fourcc         = V4L2_PIX_FMT_RGB32, /* argb */
+               .code           = V4L2_MBUS_FMT_ARGB8888_1X32,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 32,
+               .supported      = false,
+       }, {
+               .name           = "RAW8 BGGR",
+               .fourcc         = V4L2_PIX_FMT_SBGGR8,
+               .code           = V4L2_MBUS_FMT_SBGGR8_1X8,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 8,
+               .supported      = false,
+       }, {
+               .name           = "RAW8 GBRG",
+               .fourcc         = V4L2_PIX_FMT_SGBRG8,
+               .code           = V4L2_MBUS_FMT_SGBRG8_1X8,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 8,
+               .supported      = false,
+       }, {
+               .name           = "RAW8 GRBG",
+               .fourcc         = V4L2_PIX_FMT_SGRBG8,
+               .code           = V4L2_MBUS_FMT_SGRBG8_1X8,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 8,
+               .supported      = false,
+       }, {
+               .name           = "RAW8 RGGB",
+               .fourcc         = V4L2_PIX_FMT_SRGGB8,
+               .code           = V4L2_MBUS_FMT_SRGGB8_1X8,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 8,
+               .supported      = false,
+       }, {
+               .name           = "RAW10 BGGR",
+               .fourcc         = V4L2_PIX_FMT_SBGGR10,
+               .code           = V4L2_MBUS_FMT_SBGGR10_1X10,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RAW10 GBRG",
+               .fourcc         = V4L2_PIX_FMT_SGBRG10,
+               .code           = V4L2_MBUS_FMT_SGBRG10_1X10,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RAW10 GRBG",
+               .fourcc         = V4L2_PIX_FMT_SGRBG10,
+               .code           = V4L2_MBUS_FMT_SGRBG10_1X10,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RAW10 RGGB",
+               .fourcc         = V4L2_PIX_FMT_SRGGB10,
+               .code           = V4L2_MBUS_FMT_SRGGB10_1X10,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RAW12 BGGR",
+               .fourcc         = V4L2_PIX_FMT_SBGGR12,
+               .code           = V4L2_MBUS_FMT_SBGGR12_1X12,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RAW12 GBRG",
+               .fourcc         = V4L2_PIX_FMT_SGBRG12,
+               .code           = V4L2_MBUS_FMT_SGBRG12_1X12,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RAW12 GRBG",
+               .fourcc         = V4L2_PIX_FMT_SGRBG12,
+               .code           = V4L2_MBUS_FMT_SGRBG12_1X12,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       }, {
+               .name           = "RAW12 RGGB",
+               .fourcc         = V4L2_PIX_FMT_SRGGB12,
+               .code           = V4L2_MBUS_FMT_SRGGB12_1X12,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .depth          = 16,
+               .supported      = false,
+       },
+};
+
+static const struct cal_fmt *find_format_by_pix(u32 pixelformat)
+{
+       const struct cal_fmt *fmt;
+       unsigned int k;
+
+       for (k = 0; k < ARRAY_SIZE(formats); k++) {
+               fmt = &formats[k];
+               if (fmt->fourcc == pixelformat)
+                       return fmt;
+       }
+
+       return NULL;
+}
+
+static const struct cal_fmt *find_format_by_code(u32 code)
+{
+       const struct cal_fmt *fmt;
+       unsigned int k;
+
+       for (k = 0; k < ARRAY_SIZE(formats); k++) {
+               fmt = &formats[k];
+               if (fmt->code == code)
+                       return fmt;
+       }
+
+       return NULL;
+}
+
+/* buffer for one video frame */
+struct cal_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct vb2_buffer       vb;
+       struct list_head        list;
+       const struct cal_fmt    *fmt;
+};
+
+struct cal_dmaqueue {
+       struct list_head        active;
+
+       /* Counters to control fps rate */
+       int                     frame;
+       int                     ini_jiffies;
+};
+
+struct cm_data {
+       void __iomem            *base;
+       struct resource         *res;
+
+       unsigned int            camerrx_control;
+
+       struct platform_device *pdev;
+};
+
+struct cc_data {
+       void __iomem            *base;
+       struct resource         *res;
+
+       struct platform_device *pdev;
+};
+
+/*
+ * there is one cal_dev structure in the driver, it is shared by
+ * all instances.
+ */
+struct cal_dev {
+       int                     irq;
+       void __iomem            *base;
+       struct resource         *res;
+       struct platform_device  *pdev;
+       struct v4l2_device      v4l2_dev;
+
+       struct cm_data          *cm;            /* Control Module handle */
+
+       struct cal_ctx          *ctx[2];
+};
+
+/*
+ * There is one cal_ctx structure for each camera core context.
+ */
+struct cal_ctx {
+       struct v4l2_device      v4l2_dev;
+       struct v4l2_ctrl_handler ctrl_handler;
+       struct video_device     vdev;
+       struct v4l2_async_notifier notifier;
+       struct v4l2_subdev      *sensor;
+       struct v4l2_of_endpoint endpoint;
+
+       struct v4l2_async_subdev asd;
+       struct v4l2_async_subdev *asd_list[1];
+
+       struct v4l2_fh          fh;
+       struct cal_dev          *dev;
+       struct cc_data          *cc;
+
+       /* v4l2_ioctl mutex */
+       struct mutex            mutex;
+       /* v4l2 buffers lock */
+       spinlock_t              slock;
+
+       /* Several counters */
+       unsigned long           jiffies;
+
+       struct vb2_alloc_ctx    *alloc_ctx;
+       struct cal_dmaqueue     vidq;
+
+       /* Input Number */
+       int                     input;
+
+       /* video capture */
+       const struct cal_fmt    *fmt;
+       struct v4l2_fract       timeperframe;
+       unsigned int            width, height;
+       unsigned int            field;
+       unsigned int            pixelsize;
+       unsigned int            external_rate;
+       struct vb2_queue        vb_vidq;
+       unsigned int            seq_count;
+       unsigned int            csi2_port;
+       unsigned int            virtual_channel;
+
+       /* Pointer pointing to current v4l2_buffer */
+       struct cal_buffer       *cur_frm;
+       /* Pointer pointing to next v4l2_buffer */
+       struct cal_buffer       *next_frm;
+};
+
+
+static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n)
+{
+       return container_of(n, struct cal_ctx, notifier);
+}
+
+#define NUM_INPUTS 1
+
+/* register field read/write helpers */
+static inline int get_field(u32 value, u32 mask, int shift)
+{
+       return (value & (mask << shift)) >> shift;
+}
+
+static inline void write_field(u32 *valp, u32 field, u32 mask, int shift)
+{
+       u32 val = *valp;
+
+       val &= ~(mask << shift);
+       val |= (field & mask) << shift;
+       *valp = val;
+}
+
+static inline u32 cal_read(struct cal_dev *dev, int offset)
+{
+       return ioread32(dev->base + offset);
+}
+
+static inline void cal_write(struct cal_dev *dev, int offset, u32 value)
+{
+       iowrite32(value, dev->base + offset);
+}
+
+static inline int
+cal_read_field(struct cal_dev *dev, int offset, u32 mask, int shift)
+{
+       return get_field(cal_read(dev, offset), mask, shift);
+}
+
+
+static inline void cal_write_field(struct cal_dev *dev, int offset, u32 field,
+               u32 mask, int shift)
+{
+       u32 val = cal_read(dev, offset);
+
+       write_field(&val, field, mask, shift);
+
+       cal_write(dev, offset, val);
+}
+
+/*
+ * Control Module block access
+ */
+static struct cm_data *cm_create(struct cal_dev *dev)
+{
+       struct platform_device *pdev = dev->pdev;
+       struct cm_data *cm;
+
+       cal_dbg(3, dev, "cm_create\n");
+
+       cm = devm_kzalloc(&pdev->dev, sizeof(*cm), GFP_KERNEL);
+       if (!cm) {
+               cal_err(dev, "couldn't alloc cm_data\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       cm->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                               "camerrx_control");
+       if (!cm->res) {
+               cal_err(dev, "missing platform resources data\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       cal_dbg(1, dev, "ioresource %s at  %x - %x\n",
+               cm->res->name, cm->res->start, cm->res->end);
+
+       cm->base = devm_ioremap_resource(&pdev->dev, cm->res);
+       if (!cm->base) {
+               cal_err(dev, "failed to ioremap\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       return cm;
+}
+
+static inline u32 cm_read(struct cm_data *dev, int offset)
+{
+       return ioread32(dev->base + offset);
+}
+
+static inline void cm_write(struct cm_data *dev, int offset, u32 value)
+{
+       iowrite32(value, dev->base + offset);
+}
+
+static inline void cm_write_field(struct cm_data *dev, int offset, u32 field,
+               u32 mask, int shift)
+{
+       u32 val = cm_read(dev, offset);
+
+       write_field(&val, field, mask, shift);
+
+       cm_write(dev, offset, val);
+}
+
+static void camerarx_phy_enable(struct cal_ctx *ctx)
+{
+       u32 val;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       if (!ctx->dev->cm->base) {
+               ctx_err(ctx, "cm not mapped\n");
+               return;
+       }
+
+       val = cm_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL);
+       if (ctx->csi2_port == 1) {
+               write_field(&val, 1, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK,
+                           CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_SHIFT);
+               write_field(&val, 0, CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK,
+                           CM_CAMERRX_CTRL_CSI0_CAMMODE_SHIFT);
+               /* enable all lanes by default */
+               write_field(&val, 0xf, CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK,
+                           CM_CAMERRX_CTRL_CSI0_LANEENABLE_SHIFT);
+               write_field(&val, 1, CM_CAMERRX_CTRL_CSI0_MODE_MASK,
+                           CM_CAMERRX_CTRL_CSI0_MODE_SHIFT);
+       } else if (ctx->csi2_port == 2) {
+               write_field(&val, 1, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK,
+                           CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_SHIFT);
+               write_field(&val, 0, CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK,
+                           CM_CAMERRX_CTRL_CSI0_CAMMODE_SHIFT);
+               /* enable all lanes by default */
+               write_field(&val, 0x3, CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK,
+                           CM_CAMERRX_CTRL_CSI0_LANEENABLE_SHIFT);
+               write_field(&val, 1, CM_CAMERRX_CTRL_CSI1_MODE_MASK,
+                           CM_CAMERRX_CTRL_CSI0_MODE_SHIFT);
+       }
+       cm_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val);
+}
+
+static void camerarx_phy_disable(struct cal_ctx *ctx)
+{
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       if (!ctx->dev->cm->base) {
+               ctx_err(ctx, "cm not mapped\n");
+               return;
+       }
+
+       if (ctx->csi2_port == 1)
+               cm_write_field(ctx->dev->cm,
+                              CM_CTRL_CORE_CAMERRX_CONTROL,
+                              0x0,
+                              CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK,
+                              CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_SHIFT);
+       else if (ctx->csi2_port == 2)
+               cm_write_field(ctx->dev->cm,
+                              CM_CTRL_CORE_CAMERRX_CONTROL,
+                              0x0,
+                              CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK,
+                              CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_SHIFT);
+}
+
+/*
+ * Camera Instance access block
+ */
+static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core)
+{
+       struct platform_device *pdev = dev->pdev;
+       struct cc_data *cc;
+
+       cal_dbg(3, dev, "cc_create\n");
+
+       cc = devm_kzalloc(&pdev->dev, sizeof(*cc), GFP_KERNEL);
+       if (!cc) {
+               cal_err(dev, "couldn't alloc cc_data\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       cc->res = platform_get_resource_byname(pdev,
+                                              IORESOURCE_MEM,
+                                              (core == 0) ?
+                                               "cal_rx_core0" :
+                                               "cal_rx_core1");
+       if (!cc->res) {
+               cal_err(dev, "missing platform resources data\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       cal_dbg(1, dev, "ioresource %s at  %x - %x\n",
+               cc->res->name, cc->res->start, cc->res->end);
+
+       cc->base = devm_ioremap_resource(&pdev->dev, cc->res);
+       if (!cc->base) {
+               cal_err(dev, "failed to ioremap\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       return cc;
+}
+
+static inline u32 cc_read(struct cc_data *dev, int offset)
+{
+       return ioread32(dev->base + offset);
+}
+
+static inline void cc_write(struct cc_data *dev, int offset, u32 value)
+{
+       iowrite32(value, dev->base + offset);
+}
+
+/*
+ * Get Revision and HW info
+ */
+static void cal_get_hwinfo(struct cal_dev *dev)
+{
+       u32 revision = 0;
+       u32 hwinfo = 0;
+
+       revision = cal_read(dev, CAL_HL_REVISION);
+       cal_dbg(3, dev, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n",
+               revision);
+
+       hwinfo = cal_read(dev, CAL_HL_HWINFO);
+       cal_dbg(3, dev, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n",
+               hwinfo);
+}
+
+/*
+ * Soft-Reset the Main Cal module. Not sure if this is needed.
+ */
+/*
+static void cal_top_reset(struct cal_dev *dev)
+{
+       cal_write_field(dev,
+                       CAL_HL_SYSCONFIG,
+                       CAL_HL_SYSCONFIG_SOFTRESET_RESET,
+                       CAL_HL_SYSCONFIG_SOFTRESET_MASK,
+                       CAL_HL_SYSCONFIG_SOFTRESET_SHIFT);
+
+       while(cal_read_field(dev,
+                            CAL_HL_SYSCONFIG,
+                            CAL_HL_SYSCONFIG_SOFTRESET_MASK,
+                            CAL_HL_SYSCONFIG_SOFTRESET_SHIFT) !=
+             CAL_HL_SYSCONFIG_SOFTRESET_DONE);
+}
+*/
+
+static void cal_quickdump_regs(struct cal_dev *dev)
+{
+       cal_info(dev, "CAL Registers @ 0x%08x:\n", dev->res->start);
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
+                      dev->base, (dev->res->end - dev->res->start + 1), false);
+
+       if (!dev->ctx[0]) {
+               cal_info(dev, "CSI2 Core 0 Registers @ 0x%08x:\n",
+                        dev->ctx[0]->cc->res->start);
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
+                              dev->ctx[0]->cc->base,
+                              (dev->ctx[0]->cc->res->end -
+                               dev->ctx[0]->cc->res->start + 1),
+                              false);
+       }
+
+       if (!dev->ctx[1]) {
+               cal_info(dev, "CSI2 Core 1 Registers @ 0x%08x:\n",
+                        dev->ctx[1]->cc->res->start);
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
+                              dev->ctx[1]->cc->base,
+                              (dev->ctx[1]->cc->res->end -
+                               dev->ctx[1]->cc->res->start + 1),
+                              false);
+       }
+
+       cal_info(dev, "CAMERRX_Control Registers @ 0x%08x:\n",
+                dev->cm->res->start);
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4,
+                      dev->cm->base,
+                      (dev->cm->res->end - dev->cm->res->start + 1), false);
+}
+
+/*
+ * Enable the expected IRQ sources
+ */
+static void enable_irqs(struct cal_ctx *ctx)
+{
+       /* Enable IRQ_WDMA_END 0/1 */
+       cal_write_field(ctx->dev,
+                       CAL_HL_IRQENABLE_SET(2),
+                       CAL_HL_IRQ_ENABLE,
+                       CAL_HL_IRQ_MASK(ctx->csi2_port),
+                       CAL_HL_IRQ_SHIFT(ctx->csi2_port));
+       /* Enable IRQ_WDMA_START 0/1 */
+       cal_write_field(ctx->dev,
+                       CAL_HL_IRQENABLE_SET(3),
+                       CAL_HL_IRQ_ENABLE,
+                       CAL_HL_IRQ_MASK(ctx->csi2_port),
+                       CAL_HL_IRQ_SHIFT(ctx->csi2_port));
+       /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
+       cal_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0xFF000000);
+}
+
+static void disable_irqs(struct cal_ctx *ctx)
+{
+       /* Disable IRQ_WDMA_END 0/1 */
+       cal_write_field(ctx->dev,
+                       CAL_HL_IRQENABLE_CLR(2),
+                       CAL_HL_IRQ_CLEAR,
+                       CAL_HL_IRQ_MASK(ctx->csi2_port),
+                       CAL_HL_IRQ_SHIFT(ctx->csi2_port));
+       /* Disable IRQ_WDMA_START 0/1 */
+       cal_write_field(ctx->dev,
+                       CAL_HL_IRQENABLE_CLR(3),
+                       CAL_HL_IRQ_ENABLE,
+                       CAL_HL_IRQ_MASK(ctx->csi2_port),
+                       CAL_HL_IRQ_SHIFT(ctx->csi2_port));
+       /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
+       cal_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0);
+}
+
+static void csi2_init(struct cal_ctx *ctx)
+{
+       u32 val;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       val = cal_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port));
+       write_field(&val, CAL_GEN_ENABLE,
+                   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK,
+                   CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_SHIFT);
+       write_field(&val, CAL_GEN_ENABLE,
+                   CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK,
+                   CAL_CSI2_TIMING_STOP_STATE_X16_IO1_SHIFT);
+       write_field(&val, CAL_GEN_DISABLE,
+                   CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK,
+                   CAL_CSI2_TIMING_STOP_STATE_X4_IO1_SHIFT);
+       write_field(&val, 407, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK,
+                   CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT);
+       cal_write(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port), val);
+       ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x\n", ctx->csi2_port,
+               cal_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)));
+
+       val = cal_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
+       write_field(&val, CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL,
+                   CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK,
+                   CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_SHIFT);
+       write_field(&val, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON,
+                   CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK,
+                   CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_SHIFT);
+       cal_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
+       while (cal_read_field(ctx->dev,
+                            CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port),
+                            CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK,
+                            CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_SHIFT) !=
+              CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON)
+               ;
+       ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n", ctx->csi2_port,
+               cal_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)));
+
+       val = cal_read(ctx->dev, CAL_CTRL);
+       write_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
+                   CAL_CTRL_BURSTSIZE_MASK, CAL_CTRL_BURSTSIZE_SHIFT);
+       write_field(&val, 0xF,
+                   CAL_CTRL_TAGCNT_MASK, CAL_CTRL_TAGCNT_SHIFT);
+       write_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
+                   CAL_CTRL_POSTED_WRITES_MASK, CAL_CTRL_POSTED_WRITES_SHIFT);
+       write_field(&val, 0xFF,
+                   CAL_CTRL_MFLAGL_MASK, CAL_CTRL_MFLAGL_SHIFT);
+       write_field(&val, 0xFF,
+                   CAL_CTRL_MFLAGH_MASK, CAL_CTRL_MFLAGH_SHIFT);
+       cal_write(ctx->dev, CAL_CTRL, val);
+       ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->dev, CAL_CTRL));
+}
+
+static void csi2_lane_config(struct cal_ctx *ctx)
+{
+       u32 val = cal_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port));
+       u32 lane_shift = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT;
+       u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK;
+       u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK;
+       int lane;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       write_field(&val, ctx->endpoint.bus.mipi_csi2.clock_lane+1,
+                   lane_mask, lane_shift);
+       write_field(&val,
+                   ctx->endpoint.bus.mipi_csi2.lane_polarities[0],
+                   polarity_mask, lane_shift+3);
+       for (lane = 0;
+            lane < ctx->endpoint.bus.mipi_csi2.num_data_lanes;
+            lane++) {
+               /*
+                * Every lane are one nibble apart starting with the
+                * clock followed by the data lanes so shift incements by 4.
+                */
+               lane_shift += 4;
+               write_field(&val,
+                           ctx->endpoint.bus.mipi_csi2.data_lanes[lane]+1,
+                           lane_mask, lane_shift);
+               write_field(&val,
+                           ctx->endpoint.bus.mipi_csi2.lane_polarities[lane+1],
+                           polarity_mask, lane_shift+3);
+       }
+       cal_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val);
+       ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n",
+               ctx->csi2_port, val);
+}
+
+static void csi2_ppi_enable(struct cal_ctx *ctx)
+{
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       cal_write_field(ctx->dev,
+                       CAL_CSI2_PPI_CTRL(ctx->csi2_port),
+                       CAL_GEN_ENABLE,
+                       CAL_CSI2_PPI_CTRL_IF_EN_MASK,
+                       CAL_CSI2_PPI_CTRL_IF_EN_SHIFT);
+}
+
+static void csi2_ppi_disable(struct cal_ctx *ctx)
+{
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       cal_write_field(ctx->dev,
+                       CAL_CSI2_PPI_CTRL(ctx->csi2_port),
+                       CAL_GEN_DISABLE,
+                       CAL_CSI2_PPI_CTRL_IF_EN_MASK,
+                       CAL_CSI2_PPI_CTRL_IF_EN_SHIFT);
+}
+
+static void csi2_ctx_config(struct cal_ctx *ctx)
+{
+       u32 val;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       val = cal_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port));
+       write_field(&val, ctx->csi2_port, CAL_CSI2_CTX_CPORT_MASK,
+                   CAL_CSI2_CTX_CPORT_SHIFT);
+       /* DT type: MIPI CSI-2 Specs
+             1: All DT filter is disabled
+          0x24: RGB888 1 pixel  = 3 bytes
+          0x2B: RAW10  4 pixels = 5 bytes
+          0x2A: RAW8   1 pixel  = 1 byte
+          0x1E: YUV422 2 pixels = 4 bytes
+        */
+       write_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK,
+                   CAL_CSI2_CTX_DT_SHIFT);
+       /* Virtual Channel from the CSI2 sensor usually 0! */
+       write_field(&val, ctx->virtual_channel, CAL_CSI2_CTX_VC_MASK,
+                   CAL_CSI2_CTX_VC_SHIFT);
+       /* NUM_LINES_PER_FRAME => 0 means we don't know */
+       write_field(&val, 0, CAL_CSI2_CTX_LINES_MASK,
+                   CAL_CSI2_CTX_LINES_SHIFT);
+       write_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK,
+                   CAL_CSI2_CTX_ATT_SHIFT);
+       cal_write_field(ctx->dev,
+                       CAL_CSI2_CTX0(ctx->csi2_port),
+                       CAL_CSI2_CTX_PACK_MODE_LINE,
+                       CAL_CSI2_CTX_PACK_MODE_MASK,
+                       CAL_CSI2_CTX_PACK_MODE_SHIFT);
+       write_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
+                   CAL_CSI2_CTX_PACK_MODE_MASK, CAL_CSI2_CTX_PACK_MODE_SHIFT);
+       cal_write(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port), val);
+       ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->csi2_port,
+               cal_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port)));
+}
+
+static void pix_proc_config(struct cal_ctx *ctx)
+{
+       u32 val;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       val = cal_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port));
+       write_field(&val, CAL_PIX_PROC_EXTRACT_B8, CAL_PIX_PROC_EXTRACT_MASK,
+                   CAL_PIX_PROC_EXTRACT_SHIFT);
+       write_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK,
+                   CAL_PIX_PROC_DPCMD_SHIFT);
+       write_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK,
+                   CAL_PIX_PROC_DPCME_SHIFT);
+       write_field(&val, CAL_PIX_PROC_PACK_B8, CAL_PIX_PROC_PACK_MASK,
+                   CAL_PIX_PROC_PACK_SHIFT);
+       write_field(&val, ctx->csi2_port, CAL_PIX_PROC_CPORT_MASK,
+                   CAL_PIX_PROC_CPORT_SHIFT);
+       cal_write_field(ctx->dev,
+                       CAL_PIX_PROC(ctx->csi2_port),
+                       CAL_GEN_ENABLE,
+                       CAL_PIX_PROC_EN_MASK,
+                       CAL_PIX_PROC_EN_SHIFT);
+       write_field(&val, CAL_GEN_ENABLE, CAL_PIX_PROC_EN_MASK,
+                   CAL_PIX_PROC_EN_SHIFT);
+       cal_write(ctx->dev, CAL_PIX_PROC(ctx->csi2_port), val);
+       ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port,
+               cal_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port)));
+}
+
+#define bytes_per_line(pixel, bpp) (ALIGN(pixel*bpp, 16))
+
+static void cal_wr_dma_config(struct cal_ctx *ctx,
+                             unsigned int width)
+{
+       u32 val;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       val = cal_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port));
+       write_field(&val, ctx->csi2_port, CAL_WR_DMA_CTRL_CPORT_MASK,
+                   CAL_WR_DMA_CTRL_CPORT_SHIFT);
+       write_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
+                   CAL_WR_DMA_CTRL_DTAG_MASK, CAL_WR_DMA_CTRL_DTAG_SHIFT);
+       write_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
+                   CAL_WR_DMA_CTRL_MODE_MASK, CAL_WR_DMA_CTRL_MODE_SHIFT);
+       write_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
+                   CAL_WR_DMA_CTRL_PATTERN_MASK,
+                   CAL_WR_DMA_CTRL_PATTERN_SHIFT);
+       write_field(&val, CAL_GEN_ENABLE,
+                   CAL_WR_DMA_CTRL_STALL_RD_MASK,
+                   CAL_WR_DMA_CTRL_STALL_RD_SHIFT);
+       cal_write(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port), val);
+       ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->csi2_port,
+               cal_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port)));
+
+       /*
+        * width/16 not sure but giving it a whirl.
+        * zero does not work right
+        */
+       cal_write_field(ctx->dev,
+                       CAL_WR_DMA_OFST(ctx->csi2_port),
+                       (width/16),
+                       CAL_WR_DMA_OFST_MASK,
+                       CAL_WR_DMA_OFST_SHIFT);
+       ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->csi2_port,
+               cal_read(ctx->dev, CAL_WR_DMA_OFST(ctx->csi2_port)));
+
+       val = cal_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port));
+       /* 64 bit word means no skipping */
+       write_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK,
+                   CAL_WR_DMA_XSIZE_XSKIP_SHIFT);
+       /*
+        * (width*8)/64 this should be size of an entire line
+        * in 64bit word but 0 means all data until the end
+        * is detected automagically
+        */
+       write_field(&val, (width/8), CAL_WR_DMA_XSIZE_MASK,
+                   CAL_WR_DMA_XSIZE_SHIFT);
+       cal_write(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port), val);
+       ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->csi2_port,
+               cal_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port)));
+}
+
+static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr)
+{
+       cal_write(ctx->dev, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr);
+/*     ctx_dbg(3, ctx, "CAL_WR_DMA_ADDR(%d) = 0x%08x\n", ctx->csi2_port,
+               cal_read(ctx->dev,CAL_WR_DMA_ADDR(ctx->csi2_port))); */
+}
+
+/*
+ * TCLK values are OK at their reset values
+ */
+#define TCLK_TERM      0
+#define TCLK_MISS      1
+#define TCLK_SETTLE    14
+#define THS_SETTLE     15
+
+static void csi2_phy_config(struct cal_ctx *ctx)
+{
+       unsigned int reg0, reg1;
+       unsigned int ths_term, ths_settle;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+#ifdef LEGACY_CSI2PHY_FORMULA
+       {
+       int csi2_ddrclk_khz;
+
+       csi2_ddrclk_khz = ctx->external_rate / 1000
+               / (2 * ctx->endpoint.bus.mipi_csi2.num_data_lanes)
+               * ctx->fmt->depth;
+
+       /*
+        * THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1.
+        * THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3.
+        */
+       ths_term = DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1;
+       ths_settle = DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3;
+       }
+#else
+       {
+       unsigned int ddrclkperiod_us;
+
+       /*
+        * THS_TERM: Programmed value = floor(20 ns/DDRClk period) - 2.
+        */
+       ddrclkperiod_us = ctx->external_rate / 2000000;
+       ddrclkperiod_us = 1000000 / ddrclkperiod_us;
+       ctx_dbg(1, ctx, "ddrclkperiod_us: %d\n", ddrclkperiod_us);
+
+       ths_term = 20000 / ddrclkperiod_us;
+       ths_term = (ths_term >= 2) ? ths_term - 2 : ths_term;
+       ctx_dbg(1, ctx, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
+
+       /*
+        * THS_SETTLE: Programmed value = floor(176.3 ns/CtrlClk period) - 1.
+        *      Since CtrlClk is fixed at 96Mhz then we get
+        *      ths_settle = floor(176.3 / 10.416) - 1 = 15
+        * If we ever switch to a dynamic clock then this code might be useful
+        *
+        * unsigned int ctrlclkperiod_us;
+        * ctrlclkperiod_us = 96000000 / 1000000;
+        * ctrlclkperiod_us = 1000000 / ctrlclkperiod_us;
+        * ctx_dbg(1, ctx, "ctrlclkperiod_us: %d\n", ctrlclkperiod_us);
+
+        * ths_settle = 176300  / ctrlclkperiod_us;
+        * ths_settle = (ths_settle > 1) ? ths_settle - 1 : ths_settle;
+        */
+
+       ths_settle = THS_SETTLE;
+       ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
+       }
+#endif
+       reg0 = cc_read(ctx->cc, CAL_CSI2_PHY_REG0);
+       write_field(&reg0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE,
+                   CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK,
+                   CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_SHIFT);
+       write_field(&reg0, ths_term,
+                   CAL_CSI2_PHY_REG0_THS_TERM_MASK,
+                   CAL_CSI2_PHY_REG0_THS_TERM_SHIFT);
+       write_field(&reg0, ths_settle,
+                   CAL_CSI2_PHY_REG0_THS_SETTLE_MASK,
+                   CAL_CSI2_PHY_REG0_THS_SETTLE_SHIFT);
+
+       ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", (ctx->csi2_port-1), reg0);
+       cc_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0);
+
+       reg1 = cc_read(ctx->cc, CAL_CSI2_PHY_REG1);
+       write_field(&reg1, TCLK_TERM,
+                   CAL_CSI2_PHY_REG1_TCLK_TERM_MASK,
+                   CAL_CSI2_PHY_REG1_TCLK_TERM_SHIFT);
+       write_field(&reg1, 0xb8,
+                   CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK,
+                   CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_SHIFT);
+       write_field(&reg1, TCLK_MISS,
+                   CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK,
+                   CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT);
+       write_field(&reg1, TCLK_SETTLE,
+                   CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK,
+                   CAL_CSI2_PHY_REG1_TCLK_SETTLE_SHIFT);
+
+       ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", (ctx->csi2_port-1), reg1);
+       cc_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1);
+}
+
+static int cal_get_external_info(struct cal_ctx *ctx)
+{
+       struct v4l2_ctrl *ctrl;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       ctrl = v4l2_ctrl_find(&ctx->ctrl_handler, V4L2_CID_PIXEL_RATE);
+       if (ctrl == NULL) {
+               ctx_err(ctx, "no pixel rate control in subdev: %s\n",
+                       ctx->sensor->name);
+               return -EPIPE;
+       }
+
+       ctx->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
+       ctx_dbg(3, ctx, "sensor Pixel Rate: %d\n", ctx->external_rate);
+
+       return 0;
+}
+
+static int ls_count;
+static int le_count;
+static int fs_count;
+static int fe_count;
+static int irq_count;
+
+#define isvcirqset(irq, vc, ff) (irq & \
+       (CAL_CSI2_VC_IRQENABLE_ ##ff ##_IRQ_##vc ##_MASK << \
+        CAL_CSI2_VC_IRQENABLE_ ##ff ##_IRQ_##vc ##_SHIFT))
+
+#define isportirqset(irq, port) (irq & \
+       (CAL_HL_IRQ_MASK(port) << CAL_HL_IRQ_SHIFT(port)))
+
+static irqreturn_t cal_irq(int irq_cal, void *data)
+{
+       struct cal_dev *dev = (struct cal_dev *)data;
+       struct cal_ctx *ctx;
+       struct cal_dmaqueue *dma_q;
+       struct cal_buffer *buf;
+       unsigned long addr;
+       u32 irqst2, irqst3, vc_irqst1;
+
+       irq_count++;
+       vc_irqst1 = cal_read(dev, CAL_CSI2_VC_IRQSTATUS(1));
+       if (vc_irqst1) {
+               /* Clear Interrupt status */
+               cal_write(dev, CAL_CSI2_VC_IRQSTATUS(1), vc_irqst1);
+               if (isvcirqset(vc_irqst1, 3, FS)) {
+                       fs_count++;
+                       ls_count = 0;
+                       le_count = 0;
+               }
+               if (isvcirqset(vc_irqst1, 3, LS))
+                       ls_count++;
+               if (isvcirqset(vc_irqst1, 3, LE))
+                       le_count++;
+               if (isvcirqset(vc_irqst1, 3, FE))
+                       fe_count++;
+       }
+
+       /* Check which DMA just finished */
+       irqst2 = cal_read(dev, CAL_HL_IRQSTATUS(2));
+       if (irqst2) {
+               /* Clear Interrupt status */
+               cal_write(dev, CAL_HL_IRQSTATUS(2), irqst2);
+
+               /* Need to check both port */
+               if (isportirqset(irqst2, 1)) {
+                       ctx = dev->ctx[0];
+
+                       if (ctx->cur_frm != ctx->next_frm) {
+                               v4l2_get_timestamp(
+                                       &ctx->cur_frm->vb.v4l2_buf.timestamp);
+
+                               vb2_buffer_done(&ctx->cur_frm->vb,
+                                               VB2_BUF_STATE_DONE);
+                               ctx->cur_frm = ctx->next_frm;
+                       }
+               }
+
+               if (isportirqset(irqst2, 2)) {
+                       ctx = dev->ctx[1];
+
+                       if (ctx->cur_frm != ctx->next_frm) {
+                               v4l2_get_timestamp(
+                                       &ctx->cur_frm->vb.v4l2_buf.timestamp);
+
+                               vb2_buffer_done(&ctx->cur_frm->vb,
+                                               VB2_BUF_STATE_DONE);
+                               ctx->cur_frm = ctx->next_frm;
+                       }
+               }
+       }
+
+       /* Check which DMA just started */
+       irqst3 = cal_read(dev, CAL_HL_IRQSTATUS(3));
+       if (irqst3) {
+               /* Clear Interrupt status */
+               cal_write(dev, CAL_HL_IRQSTATUS(3), irqst3);
+
+               /* Need to check both port */
+               if (isportirqset(irqst3, 1)) {
+                       ctx = dev->ctx[0];
+                       dma_q = &ctx->vidq;
+
+                       spin_lock(&ctx->slock);
+                       if (!list_empty(&dma_q->active) &&
+                           ctx->cur_frm == ctx->next_frm) {
+                               buf = list_entry(dma_q->active.next,
+                                                struct cal_buffer, list);
+                               ctx->next_frm = buf;
+                               list_del(&buf->list);
+
+                               addr = vb2_dma_contig_plane_dma_addr(&buf->vb,
+                                                                    0);
+                               cal_wr_dma_addr(ctx, addr);
+                       }
+                       spin_unlock(&ctx->slock);
+               }
+
+               if (isportirqset(irqst3, 2)) {
+                       ctx = dev->ctx[1];
+                       dma_q = &ctx->vidq;
+
+                       spin_lock(&ctx->slock);
+                       if (!list_empty(&dma_q->active) &&
+                           ctx->cur_frm == ctx->next_frm) {
+                               buf = list_entry(dma_q->active.next,
+                                                struct cal_buffer, list);
+                               ctx->next_frm = buf;
+                               list_del(&buf->list);
+
+                               addr = vb2_dma_contig_plane_dma_addr(&buf->vb,
+                                                                    0);
+                               cal_wr_dma_addr(ctx, addr);
+                       }
+                       spin_unlock(&ctx->slock);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int cal_start_streaming(struct cal_ctx *ctx)
+{
+       struct cal_dmaqueue *dma_q = &ctx->vidq;
+       struct cal_buffer *buf;
+       unsigned long addr = 0;
+       unsigned long flags;
+       int ret;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       spin_lock_irqsave(&ctx->slock, flags);
+       if (list_empty(&dma_q->active)) {
+               spin_unlock_irqrestore(&ctx->slock, flags);
+               ctx_dbg(3, ctx, "buffer queue is empty\n");
+               return -EIO;
+       }
+
+       buf = list_entry(dma_q->active.next, struct cal_buffer, list);
+       ctx->cur_frm = buf;
+       ctx->next_frm = buf;
+       list_del(&buf->list);
+       spin_unlock_irqrestore(&ctx->slock, flags);
+
+       v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+
+       addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb, 0);
+
+       ctx_dbg(3, ctx, "enable_irqs\n");
+
+       ret = cal_get_external_info(ctx);
+       if (ret < 0)
+               return ret;
+
+       enable_irqs(ctx);
+       camerarx_phy_enable(ctx);
+       csi2_init(ctx);
+       csi2_phy_config(ctx);
+       csi2_lane_config(ctx);
+       csi2_ctx_config(ctx);
+       pix_proc_config(ctx);
+       cal_wr_dma_config(ctx, ALIGN((ctx->width * ctx->pixelsize), 16));
+       cal_wr_dma_addr(ctx, addr);
+       csi2_ppi_enable(ctx);
+
+       if (ctx->sensor) {
+               if (v4l2_subdev_call(ctx->sensor, video, s_stream, 1)) {
+                       ctx_err(ctx, "stream on failed in subdev\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (debug >= 4)
+               cal_quickdump_regs(ctx->dev);
+
+       ctx_dbg(3, ctx, "returning from %s\n", __func__);
+       return 0;
+}
+
+static void cal_stop_streaming(struct cal_ctx *ctx)
+{
+       struct cal_dmaqueue *dma_q = &ctx->vidq;
+       unsigned long flags;
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       if (ctx->sensor) {
+               if (v4l2_subdev_call(ctx->sensor, video, s_stream, 0))
+                       ctx_err(ctx, "stream off failed in subdev\n");
+       }
+
+       ctx_dbg(3, ctx, "csi2_ppi_disable\n");
+       csi2_ppi_disable(ctx);
+
+       ctx_dbg(3, ctx, "disable_irqs\n");
+       disable_irqs(ctx);
+
+       /* Release all active buffers */
+       spin_lock_irqsave(&ctx->slock, flags);
+       while (!list_empty(&dma_q->active)) {
+               struct cal_buffer *buf;
+               buf = list_entry(dma_q->active.next, struct cal_buffer, list);
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               ctx_dbg(3, ctx, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
+       }
+       spin_unlock_irqrestore(&ctx->slock, flags);
+
+       if (ctx->cur_frm == ctx->next_frm) {
+               vb2_buffer_done(&ctx->cur_frm->vb, VB2_BUF_STATE_ERROR);
+               ctx_dbg(3, ctx, "[%p/%d] done cur_frm\n", ctx->cur_frm,
+                       ctx->cur_frm->vb.v4l2_buf.index);
+       } else {
+               vb2_buffer_done(&ctx->cur_frm->vb, VB2_BUF_STATE_ERROR);
+               ctx_dbg(3, ctx, "[%p/%d] done cur_frm\n", ctx->cur_frm,
+                       ctx->cur_frm->vb.v4l2_buf.index);
+               vb2_buffer_done(&ctx->next_frm->vb, VB2_BUF_STATE_ERROR);
+               ctx_dbg(3, ctx, "[%p/%d] done next_frm\n", ctx->next_frm,
+                       ctx->next_frm->vb.v4l2_buf.index);
+       }
+       ctx->cur_frm = NULL;
+       ctx->next_frm = NULL;
+
+       ctx_dbg(3, ctx, "returning from %s\n", __func__);
+}
+
+/*
+ * video ioctls
+ */
+static int vidioc_querycap(struct file *file, void *priv,
+                       struct v4l2_capability *cap)
+{
+       struct cal_ctx *ctx = video_drvdata(file);
+
+       strcpy(cap->driver, CAL_MODULE_NAME);
+       strcpy(cap->card, CAL_MODULE_NAME);
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                "platform:%s", ctx->v4l2_dev.name);
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+                           V4L2_CAP_READWRITE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       const struct cal_fmt *fmt = NULL;
+       u32 k;
+
+       if (f->index >= ARRAY_SIZE(formats))
+               return -EINVAL;
+
+       for (k = 0; k < ARRAY_SIZE(formats); k++) {
+               if ((formats[k].index == f->index) &&
+                   (formats[k].supported)) {
+                       fmt = &formats[k];
+                       break;
+               }
+       }
+       if (!fmt)
+               return -EINVAL;
+
+       strlcpy(f->description, fmt->name, sizeof(f->description));
+       f->pixelformat = fmt->fourcc;
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       return 0;
+}
+
+static int __subdev_get_format(struct cal_ctx *ctx,
+                              struct v4l2_mbus_framefmt *fmt)
+{
+       struct v4l2_subdev_format sd_fmt;
+       struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
+       int ret;
+
+       ctx_dbg(2, ctx, "%s\n", __func__);
+
+       if (!ctx->sensor)
+               return -EINVAL;
+
+       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       sd_fmt.pad = 0;
+
+       ret = v4l2_subdev_call(ctx->sensor, pad, get_fmt, NULL, &sd_fmt);
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+               return ret;
+
+       if (ret) {
+               ret = v4l2_subdev_call(ctx->sensor, video, g_mbus_fmt,
+                                      mbus_fmt);
+               if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+                       return ret;
+       }
+
+       *fmt = *mbus_fmt;
+
+       ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__,
+               fmt->width, fmt->height, fmt->code);
+
+       return 0;
+}
+
+static int __subdev_set_format(struct cal_ctx *ctx,
+                              struct v4l2_mbus_framefmt *fmt)
+{
+       struct v4l2_subdev_format sd_fmt;
+       struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format;
+       int ret;
+
+       ctx_dbg(2, ctx, "%s\n", __func__);
+
+       if (!ctx->sensor)
+               return -EINVAL;
+
+       sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       sd_fmt.pad = 0;
+       *mbus_fmt = *fmt;
+
+       ret = v4l2_subdev_call(ctx->sensor, pad, set_fmt, NULL, &sd_fmt);
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+               return ret;
+
+       if (ret) {
+               ret = v4l2_subdev_call(ctx->sensor, video, s_mbus_fmt,
+                                      mbus_fmt);
+               if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+                       return ret;
+       }
+
+       ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__,
+               fmt->width, fmt->height, fmt->code);
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cal_ctx *ctx = video_drvdata(file);
+       const struct cal_fmt *fmt;
+       struct v4l2_mbus_framefmt mbus_fmt;
+       int ret;
+
+       ret = __subdev_get_format(ctx, &mbus_fmt);
+       if (ret)
+               return ret;
+
+       fmt = find_format_by_code(mbus_fmt.code);
+       if (!fmt) {
+               ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n",
+                       mbus_fmt.code);
+               /* code not found, use a working default */
+               fmt = find_format_by_code(V4L2_MBUS_FMT_YUYV8_2X8);
+               mbus_fmt.code = fmt->code;
+               mbus_fmt.colorspace = fmt->colorspace;
+               mbus_fmt.width = 1920;
+               mbus_fmt.height = 1080;
+               mbus_fmt.field = V4L2_FIELD_NONE;
+       }
+
+       if (ctx->fmt != fmt) {
+               /* looks like current format has changed, update local */
+               ctx->fmt = fmt;
+               ctx->width = mbus_fmt.width;
+               ctx->height = mbus_fmt.height;
+               ctx->field = mbus_fmt.field;
+               ctx->pixelsize = ctx->fmt->depth >> 3;
+       }
+
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->fmt.pix.width        = ctx->width;
+       f->fmt.pix.height       = ctx->height;
+       f->fmt.pix.field        = ctx->field;
+       f->fmt.pix.pixelformat  = ctx->fmt->fourcc;
+       f->fmt.pix.colorspace   = ctx->fmt->colorspace;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * ctx->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct cal_ctx *ctx = video_drvdata(file);
+       const struct cal_fmt *fmt;
+       struct v4l2_fmtdesc fmt_desc;
+
+       ctx_dbg(2, ctx, "%s\n", __func__);
+
+       fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+       if (!fmt) {
+               ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n",
+                       f->fmt.pix.pixelformat);
+
+               /* Just get the first one enumerated */
+               fmt_desc.index = 0;
+               if (vidioc_enum_fmt_vid_cap(file, priv, &fmt_desc)) {
+                       ctx_dbg(3, ctx,
+                               "no default fmt found , this should not happen.\n");
+                       fmt = find_format_by_code(V4L2_MBUS_FMT_YUYV8_2X8);
+               } else {
+                       fmt = find_format_by_pix(fmt_desc.pixelformat);
+               }
+               f->fmt.pix.pixelformat = fmt->fourcc;
+       }
+
+       f->fmt.pix.field = ctx->field;
+       v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2,
+                             &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0);
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = fmt->colorspace;
+       f->fmt.pix.priv = 0;
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cal_ctx *ctx = video_drvdata(file);
+       struct vb2_queue *q = &ctx->vb_vidq;
+       const struct cal_fmt *fmt;
+       struct v4l2_mbus_framefmt mbus_fmt;
+       int ret;
+
+       ctx_dbg(2, ctx, "%s\n", __func__);
+
+       if (vb2_is_busy(q)) {
+               ctx_dbg(3, ctx, "%s device busy\n", __func__);
+               return -EBUSY;
+       }
+
+       ret = vidioc_try_fmt_vid_cap(file, priv, f);
+       if (ret < 0)
+               return ret;
+
+       fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+
+       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code);
+
+       ret = __subdev_set_format(ctx, &mbus_fmt);
+       if (ret)
+               return ret;
+
+       /* Just double check nothing has gone wrong */
+       if (mbus_fmt.code != fmt->code) {
+               ctx_dbg(3, ctx,
+                       "%s subdev changed format on us, this should not happen\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       ctx->fmt = fmt;
+       ctx->pixelsize = ctx->fmt->depth >> 3;
+       ctx->field = f->fmt.pix.field;
+       ctx->width = f->fmt.pix.width;
+       ctx->height = f->fmt.pix.height;
+
+       return 0;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *fh,
+                                 struct v4l2_frmsizeenum *fsize)
+{
+       struct cal_ctx *ctx = video_drvdata(file);
+       const struct cal_fmt *fmt;
+       struct v4l2_subdev_frame_size_enum fse;
+       int ret;
+
+       ctx_dbg(2, ctx, "%s\n", __func__);
+
+       /* check for valid format */
+       fmt = find_format_by_pix(fsize->pixel_format);
+       if (fmt == NULL) {
+               ctx_dbg(3, ctx, "Invalid pixel code: %x\n",
+                       fsize->pixel_format);
+               return -EINVAL;
+       }
+
+       fse.index = fsize->index;
+       fse.pad = 0;
+       fse.code = fmt->code;
+
+       ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, NULL, &fse);
+       if (ret)
+               return -EINVAL;
+
+       ctx_dbg(1, ctx, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n",
+               __func__, fse.index, fse.code, fse.min_width, fse.max_width,
+               fse.min_height, fse.max_height);
+
+       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+       fsize->discrete.width = fse.max_width;
+       fsize->discrete.height = fse.max_height;
+
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                            struct v4l2_input *inp)
+{
+       if (inp->index >= NUM_INPUTS)
+               return -EINVAL;
+
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       sprintf(inp->name, "Camera %u", inp->index);
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct cal_ctx *ctx = video_drvdata(file);
+
+       *i = ctx->input;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct cal_ctx *ctx = video_drvdata(file);
+
+       if (i >= NUM_INPUTS)
+               return -EINVAL;
+
+       if (i == ctx->input)
+               return 0;
+
+       ctx->input = i;
+       return 0;
+}
+
+/* timeperframe is arbitrary and continuous */
+static int vidioc_enum_frameintervals(struct file *file, void *priv,
+                                            struct v4l2_frmivalenum *fival)
+{
+       struct cal_ctx *ctx = video_drvdata(file);
+       const struct cal_fmt *fmt;
+       struct v4l2_frmsizeenum fsize;
+       int ret;
+
+       if (fival->index)
+               return -EINVAL;
+
+       fmt = find_format_by_pix(fival->pixel_format);
+       if (!fmt)
+               return -EINVAL;
+
+       /* check for valid width/height */
+       ret = 0;
+       for (fsize.index = 0; ; fsize.index++) {
+               ret = v4l2_subdev_call(ctx->sensor, video,
+                                      enum_framesizes, &fsize);
+               if (ret) {
+                       if (fsize.index == 0)
+                               ctx_dbg(1, ctx, "enum_frameinterval failed on the first enum_framesize\n");
+                       return -EINVAL;
+               }
+
+               if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+                       if ((fival->width == fsize.discrete.width) &&
+                           (fival->height == fsize.discrete.height))
+                               break;
+               } else if ((fsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) ||
+                          (fsize.type == V4L2_FRMSIZE_TYPE_STEPWISE)) {
+                       if ((fival->width >= fsize.stepwise.min_width) &&
+                           (fival->width <= fsize.stepwise.max_width) &&
+                           (fival->height >= fsize.stepwise.min_height) &&
+                           (fival->height <= fsize.stepwise.max_height))
+                               break;
+               } else {
+                       return -EINVAL;
+               }
+       }
+
+       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       fival->discrete.numerator = 1;
+       fival->discrete.denominator = 30;
+
+       return 0;
+}
+
+/*
+ * Videobuf operations
+ */
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                      unsigned int *nbuffers, unsigned int *nplanes,
+                      unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct cal_ctx *ctx = vb2_get_drv_priv(vq);
+       unsigned long size;
+
+       size = ctx->width * ctx->height * ctx->pixelsize;
+       if (fmt) {
+               if (fmt->fmt.pix.sizeimage < size)
+                       return -EINVAL;
+               size = fmt->fmt.pix.sizeimage;
+               /* check against insane over 8K resolution buffers */
+               if (size > 7680 * 4320 * ctx->pixelsize)
+                       return -EINVAL;
+       }
+
+       *nplanes = 1;
+       sizes[0] = size;
+       alloc_ctxs[0] = ctx->alloc_ctx;
+
+       ctx_dbg(3, ctx, "nbuffers=%d, size=%ld\n", *nbuffers, size);
+
+       return 0;
+}
+
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+       struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct cal_buffer *buf = container_of(vb, struct cal_buffer, vb);
+       unsigned long size;
+
+       BUG_ON(NULL == ctx->fmt);
+
+       size = ctx->width * ctx->height * ctx->pixelsize;
+       if (vb2_plane_size(vb, 0) < size) {
+               ctx_err(ctx,
+                       "data will not fit into plane (%lu < %lu)\n",
+                       vb2_plane_size(vb, 0), size);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(&buf->vb, 0, size);
+       return 0;
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+       struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct cal_buffer *buf = container_of(vb, struct cal_buffer, vb);
+       struct cal_dmaqueue *vidq = &ctx->vidq;
+       unsigned long flags = 0;
+
+       /* recheck locking */
+       spin_lock_irqsave(&ctx->slock, flags);
+       list_add_tail(&buf->list, &vidq->active);
+       spin_unlock_irqrestore(&ctx->slock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct cal_ctx *ctx = vb2_get_drv_priv(vq);
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       return cal_start_streaming(ctx);
+}
+
+/* abort streaming and wait for last buffer */
+static int stop_streaming(struct vb2_queue *vq)
+{
+       struct cal_ctx *ctx = vb2_get_drv_priv(vq);
+
+       ctx_dbg(3, ctx, "%s\n", __func__);
+
+       cal_stop_streaming(ctx);
+       return 0;
+}
+
+static void cal_unlock(struct vb2_queue *q)
+{
+       struct cal_ctx *ctx = vb2_get_drv_priv(q);
+       mutex_unlock(&ctx->mutex);
+}
+
+static void cal_lock(struct vb2_queue *q)
+{
+       struct cal_ctx *ctx = vb2_get_drv_priv(q);
+       mutex_lock(&ctx->mutex);
+}
+
+static struct vb2_ops cal_video_qops = {
+       .queue_setup            = queue_setup,
+       .buf_prepare            = buffer_prepare,
+       .buf_queue              = buffer_queue,
+       .start_streaming        = start_streaming,
+       .stop_streaming         = stop_streaming,
+       .wait_prepare           = cal_unlock,
+       .wait_finish            = cal_lock,
+};
+
+static const struct v4l2_file_operations cal_fops = {
+       .owner          = THIS_MODULE,
+       .open           = v4l2_fh_open,
+       .release        = vb2_fop_release,
+       .read           = vb2_fop_read,
+       .poll           = vb2_fop_poll,
+       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+       .mmap           = vb2_fop_mmap,
+};
+
+static const struct v4l2_ioctl_ops cal_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_enum_framesizes   = vidioc_enum_framesizes,
+       .vidioc_reqbufs       = vb2_ioctl_reqbufs,
+       .vidioc_create_bufs   = vb2_ioctl_create_bufs,
+       .vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
+       .vidioc_querybuf      = vb2_ioctl_querybuf,
+       .vidioc_qbuf          = vb2_ioctl_qbuf,
+       .vidioc_dqbuf         = vb2_ioctl_dqbuf,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
+       .vidioc_streamon      = vb2_ioctl_streamon,
+       .vidioc_streamoff     = vb2_ioctl_streamoff,
+       .vidioc_log_status    = v4l2_ctrl_log_status,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static struct video_device cal_videodev = {
+       .name           = CAL_MODULE_NAME,
+       .fops           = &cal_fops,
+       .ioctl_ops      = &cal_ioctl_ops,
+       .minor          = -1,
+       .release        = video_device_release,
+};
+
+static int cal_runtime_get(struct cal_dev *dev)
+{
+       int r;
+
+       cal_dbg(3, dev, "cal_runtime_get\n");
+
+       r = pm_runtime_get_sync(&dev->pdev->dev);
+       WARN_ON(r < 0);
+       return r < 0 ? r : 0;
+}
+
+static void cal_runtime_put(struct cal_dev *dev)
+{
+       int r;
+
+       cal_dbg(3, dev, "cal_runtime_put\n");
+
+       r = pm_runtime_put_sync(&dev->pdev->dev);
+       WARN_ON(r < 0 && r != -ENOSYS);
+}
+
+/* -----------------------------------------------------------------
+       Initialization and module stuff
+   ------------------------------------------------------------------*/
+static int cal_release(struct cal_dev *dev)
+{
+       struct cal_ctx *ctx;
+       int i;
+
+       for (i = 0; i < n_devs; i++) {
+               ctx = dev->ctx[i];
+               if (ctx) {
+                       v4l2_info(&ctx->v4l2_dev, "unregistering %s\n",
+                                 video_device_node_name(&ctx->vdev));
+                       video_unregister_device(&ctx->vdev);
+                       v4l2_device_unregister(&ctx->v4l2_dev);
+                       vb2_dma_contig_cleanup_ctx(ctx->alloc_ctx);
+                       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+                       kfree(ctx->cc);
+                       kfree(ctx);
+               }
+       }
+
+       return 0;
+}
+
+static int cal_complete_ctx(struct cal_ctx *ctx);
+
+static int cal_async_bound(struct v4l2_async_notifier *notifier,
+                       struct v4l2_subdev *subdev,
+                       struct v4l2_async_subdev *asd)
+{
+       struct cal_ctx *ctx = notifier_to_ctx(notifier);
+       struct v4l2_subdev_mbus_code_enum mbus_code;
+       int i, j;
+
+       ctx_dbg(1, ctx, "cal_async_bound\n");
+
+       if (ctx->sensor) {
+               ctx_info(ctx, "Rejecting subdev %s (Already set!!)",
+                        subdev->name);
+               return 0;
+       }
+
+       ctx->sensor = subdev;
+       ctx_info(ctx, "Using sensor %s for capture\n",
+                subdev->name);
+
+       /* setup the supported formats & indexes */
+       for (j = 0, i = 0; ; ++j) {
+               struct cal_fmt *fmt;
+               int ret;
+
+               memset(&mbus_code, 0, sizeof(mbus_code));
+               mbus_code.index = j;
+               ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
+                                      NULL, &mbus_code);
+               if (ret)
+                       break;
+
+               fmt = (struct cal_fmt *)find_format_by_code(mbus_code.code);
+               if (!fmt)
+                       continue;
+
+               fmt->supported = true;
+               fmt->index = i++;
+       }
+
+       cal_complete_ctx(ctx);
+
+       return 0;
+}
+
+static int cal_async_complete(struct v4l2_async_notifier *notifier)
+{
+       struct cal_ctx *ctx = notifier_to_ctx(notifier);
+       ctx_dbg(1, ctx, "cal_async_complete\n");
+       return 0;
+}
+
+static int cal_complete_ctx(struct cal_ctx *ctx)
+{
+       struct video_device *vfd;
+       struct vb2_queue *q;
+       int ret;
+
+       ctx->timeperframe = tpf_default;
+
+       ctx->width = 1920;
+       ctx->height = 1080;
+       ctx->field = V4L2_FIELD_NONE;
+       ctx->fmt = find_format_by_code(V4L2_MBUS_FMT_SGRBG8_1X8);
+       ctx->pixelsize = ctx->fmt->depth >> 3;
+       ctx->external_rate = 192000000;
+
+       /* initialize locks */
+       spin_lock_init(&ctx->slock);
+
+       /* initialize queue */
+       q = &ctx->vb_vidq;
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+       q->drv_priv = ctx;
+       q->buf_struct_size = sizeof(struct cal_buffer);
+       q->ops = &cal_video_qops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+       /* q->min_buffers_needed = 1; */
+
+       ret = vb2_queue_init(q);
+       if (ret)
+               return ret;
+
+       mutex_init(&ctx->mutex);
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&ctx->vidq.active);
+
+       vfd = &ctx->vdev;
+       *vfd = cal_videodev;
+       /* Pass on debug flag if it is high enough */
+       vfd->debug = (debug >= 4) ? 1 : 0;
+       vfd->v4l2_dev = &ctx->v4l2_dev;
+       vfd->queue = q;
+       set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+
+       /*
+        * Provide a mutex to v4l2 core. It will be used to protect
+        * all fops and v4l2 ioctls.
+        */
+       vfd->lock = &ctx->mutex;
+       video_set_drvdata(vfd, ctx);
+
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
+       if (ret < 0)
+               return ret;
+
+       v4l2_info(&ctx->v4l2_dev, "V4L2 device registered as %s\n",
+                 video_device_node_name(vfd));
+
+       ctx->alloc_ctx = vb2_dma_contig_init_ctx(vfd->v4l2_dev->dev);
+       if (IS_ERR(ctx->alloc_ctx)) {
+               ctx_err(ctx, "Failed to alloc vb2 context\n");
+               ret = PTR_ERR(ctx->alloc_ctx);
+               goto vdev_unreg;
+       }
+
+       return 0;
+
+vdev_unreg:
+       video_unregister_device(vfd);
+       return ret;
+}
+
+static struct device_node *
+of_get_next_port(const struct device_node *parent,
+                struct device_node *prev)
+{
+       struct device_node *port = NULL;
+
+       if (!parent)
+               return NULL;
+
+       if (!prev) {
+               struct device_node *ports;
+               /*
+                * It's the first call, we have to find a port subnode
+                * within this node or within an optional 'ports' node.
+                */
+               ports = of_get_child_by_name(parent, "ports");
+               if (ports)
+                       parent = ports;
+
+               port = of_get_child_by_name(parent, "port");
+
+               /* release the 'ports' node */
+               of_node_put(ports);
+       } else {
+               struct device_node *ports;
+
+               ports = of_get_parent(prev);
+               if (!ports)
+                       return NULL;
+
+               do {
+                       port = of_get_next_child(ports, prev);
+                       if (!port) {
+                               of_node_put(ports);
+                               return NULL;
+                       }
+                       prev = port;
+               } while (of_node_cmp(port->name, "port") != 0);
+       }
+
+       return port;
+}
+
+static struct device_node *
+of_get_next_endpoint(const struct device_node *parent,
+                    struct device_node *prev)
+{
+       struct device_node *ep = NULL;
+
+       if (!parent)
+               return NULL;
+
+       do {
+               ep = of_get_next_child(parent, prev);
+               if (!ep)
+                       return NULL;
+               prev = ep;
+       } while (of_node_cmp(ep->name, "endpoint") != 0);
+
+       return ep;
+}
+
+static int of_cal_create_instance(struct cal_ctx *ctx, int inst)
+{
+       struct platform_device *pdev = ctx->dev->pdev;
+       struct device_node *ep_node, *port, *remote_ep,
+                       *sensor_node, *parent;
+       struct v4l2_of_endpoint *endpoint;
+       struct v4l2_async_subdev *asd;
+       u32 regval = 0;
+       int ret, index, found_port = 0, lane;
+
+       parent = pdev->dev.of_node;
+
+       asd = &ctx->asd;
+       endpoint = &ctx->endpoint;
+
+       ep_node = NULL;
+       port = NULL;
+       remote_ep = NULL;
+       sensor_node = NULL;
+       ret = -EINVAL;
+
+       ctx_dbg(3, ctx, "Scanning Port node for csi2 port: %d\n", inst);
+       for (index = 0; index < CAL_NUM_CSI2_PORTS; index++) {
+               port = of_get_next_port(parent, port);
+               if (!port) {
+                       ctx_dbg(1, ctx, "No port node found for csi2 port:%d\n",
+                               index);
+                       goto cleanup_exit;
+               }
+
+               /* Match the slice number with <REG> */
+               of_property_read_u32(port, "reg", &regval);
+               ctx_dbg(3, ctx, "port:%d inst:%d <reg>:%d\n",
+                       index, inst, regval);
+               if ((regval == inst) && (index == inst)) {
+                       found_port = 1;
+                       break;
+               }
+       }
+
+       if (!found_port) {
+               ctx_dbg(1, ctx, "No port node matches csi2 port:%d\n",
+                       inst);
+               goto cleanup_exit;
+       }
+
+       ctx_dbg(3, ctx, "Scanning sub-device for csi2 port: %d\n",
+               inst);
+
+       ep_node = of_get_next_endpoint(port, ep_node);
+       if (!ep_node) {
+               ctx_dbg(3, ctx, "can't get next endpoint\n");
+               goto cleanup_exit;
+       }
+
+       sensor_node = of_graph_get_remote_port_parent(ep_node);
+       if (!sensor_node) {
+               ctx_dbg(3, ctx, "can't get remote parent\n");
+               goto cleanup_exit;
+       }
+       asd->match_type = V4L2_ASYNC_MATCH_OF;
+       asd->match.of.node = sensor_node;
+
+       remote_ep = of_parse_phandle(ep_node, "remote-endpoint", 0);
+       if (!remote_ep) {
+               ctx_dbg(3, ctx, "can't get remote-endpoint\n");
+               goto cleanup_exit;
+       }
+       v4l2_of_parse_endpoint(remote_ep, endpoint);
+
+       if (endpoint->bus_type != V4L2_MBUS_CSI2) {
+               ctx_err(ctx, "Port:%d sub-device %s is not a CSI2 device\n",
+                       inst, sensor_node->name);
+               goto cleanup_exit;
+       }
+
+       /* Store Virtual Channel number */
+       ctx->virtual_channel = endpoint->base.id;
+
+       ctx_dbg(3, ctx, "Port:%d v4l2-endpoint: CSI2\n", inst);
+       ctx_dbg(3, ctx, "Virtual Channel=%d\n", ctx->virtual_channel);
+       ctx_dbg(3, ctx, "flags=0x%08x\n", endpoint->bus.mipi_csi2.flags);
+       ctx_dbg(3, ctx, "clock_lane=%d\n", endpoint->bus.mipi_csi2.clock_lane);
+       ctx_dbg(3, ctx, "num_data_lanes=%d\n",
+               endpoint->bus.mipi_csi2.num_data_lanes);
+       ctx_dbg(3, ctx, "data_lanes= <\n");
+       for (lane = 0; lane < endpoint->bus.mipi_csi2.num_data_lanes; lane++)
+               ctx_dbg(3, ctx, "\t%d\n",
+                       endpoint->bus.mipi_csi2.data_lanes[lane]);
+       ctx_dbg(3, ctx, "\t>\n");
+
+       ctx_dbg(1, ctx, "Port: %d found sub-device %s\n",
+               inst, sensor_node->name);
+
+       ctx_dbg(1, ctx, "Asynchronous subdevice registration\n");
+       ctx->asd_list[0] = asd;
+       ctx->notifier.subdevs = ctx->asd_list;
+       ctx->notifier.num_subdevs = 1;
+       ctx->notifier.bound = cal_async_bound;
+       ctx->notifier.complete = cal_async_complete;
+       ret = v4l2_async_notifier_register(&ctx->v4l2_dev,
+                                          &ctx->notifier);
+       if (ret) {
+               ctx_err(ctx, "Error registering async notifier\n");
+               ret = -EINVAL;
+       }
+
+cleanup_exit:
+       if (!remote_ep)
+               of_node_put(remote_ep);
+       if (!sensor_node)
+               of_node_put(sensor_node);
+       if (!ep_node)
+               of_node_put(ep_node);
+       if (!port)
+               of_node_put(port);
+
+       return ret;
+}
+
+static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst)
+{
+       struct cal_ctx *ctx;
+       struct v4l2_ctrl_handler *hdl;
+       int ret;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return 0;
+       /* save the cal_dev * for future ref */
+       ctx->dev = dev;
+
+       snprintf(ctx->v4l2_dev.name, sizeof(ctx->v4l2_dev.name),
+                "%s-%03d", CAL_MODULE_NAME, inst);
+       ret = v4l2_device_register(&dev->pdev->dev, &ctx->v4l2_dev);
+       if (ret)
+               goto free_ctx;
+
+       hdl = &ctx->ctrl_handler;
+       ret = v4l2_ctrl_handler_init(hdl, 11);
+       if (ret) {
+               ctx_err(ctx, "Failed to init ctrl handler\n");
+               goto free_hdl;
+       }
+       ctx->v4l2_dev.ctrl_handler = hdl;
+
+       /* Make sure Camera Core H/W register area is available */
+       ctx->cc = cc_create(dev, inst);
+       if (IS_ERR(ctx->cc)) {
+               ret = PTR_ERR(ctx->cc);
+               goto unreg_dev;
+       }
+
+       /* Store the instance id */
+       ctx->csi2_port = inst + 1;
+
+       ret = of_cal_create_instance(ctx, inst);
+       if (ret) {
+               ctx_dbg(1, ctx, "Error scanning cal instance: %d\n", inst);
+               ret = -EINVAL;
+               goto free_cc;
+       }
+       return ctx;
+
+free_cc:
+       kfree(ctx->cc);
+free_hdl:
+       v4l2_ctrl_handler_free(hdl);
+unreg_dev:
+       v4l2_device_unregister(&ctx->v4l2_dev);
+free_ctx:
+       kfree(ctx);
+       return 0;
+}
+
+static int cal_probe(struct platform_device *pdev)
+{
+       struct cal_dev *dev;
+       int ret;
+       int irq, func;
+
+       dev_info(&pdev->dev, "Probing %s\n",
+                CAL_MODULE_NAME);
+
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       /* set pseudo v4l2 device name so we can use v4l2_printk */
+       strcpy(dev->v4l2_dev.name, CAL_MODULE_NAME);
+
+       /* save pdev pointer */
+       dev->pdev = pdev;
+
+       dev->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                       "cal_top");
+       cal_dbg(1, dev, "ioresource %s at  %x - %x\n",
+               dev->res->name, dev->res->start, dev->res->end);
+
+       dev->base = devm_ioremap(&pdev->dev, dev->res->start, SZ_32K);
+       if (!dev->base) {
+               ret = -ENOMEM;
+               goto just_exit;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       cal_dbg(1, dev, "got irq# %d\n", irq);
+       ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME,
+                       dev);
+       if (ret)
+               goto just_exit;
+
+       platform_set_drvdata(pdev, dev);
+
+       pm_runtime_enable(&pdev->dev);
+
+       ret = cal_runtime_get(dev);
+       if (ret)
+               goto just_exit;
+
+       /* Just check we can actually access the module */
+       cal_get_hwinfo(dev);
+
+       func = cal_read_field(dev, CAL_HL_REVISION, CAL_HL_REVISION_FUNC_MASK,
+               CAL_HL_REVISION_FUNC_SHIFT);
+       cal_dbg(1, dev, "CAL HL_REVISION function %x\n", func);
+
+       dev->cm = cm_create(dev);
+       if (IS_ERR(dev->cm)) {
+               ret = PTR_ERR(dev->cm);
+               goto runtime_put;
+       }
+       dev->ctx[0] = NULL;
+       dev->ctx[1] = NULL;
+
+       dev->ctx[0] = cal_create_instance(dev, 0);
+       dev->ctx[1] = cal_create_instance(dev, 1);
+       if ((dev->ctx[0] == NULL) && (dev->ctx[1] == NULL)) {
+               ret = -ENODEV;
+               cal_err(dev, "Neither port is configured, no point in staying up\n");
+               goto free_ctx;
+       }
+
+       return 0;
+
+free_ctx:
+       kfree(dev->ctx[0]);
+       kfree(dev->ctx[1]);
+       kfree(dev->cm);
+runtime_put:
+       cal_runtime_put(dev);
+       pm_runtime_disable(&pdev->dev);
+just_exit:
+       return ret;
+}
+
+static int cal_remove(struct platform_device *pdev)
+{
+       struct cal_dev *dev =
+               (struct cal_dev *)platform_get_drvdata(pdev);
+
+       cal_info(dev, "Removing %s\n", CAL_MODULE_NAME);
+
+       cal_release(dev);
+
+       /* disable csi2 phy */
+       if (dev->ctx[0])
+               camerarx_phy_disable(dev->ctx[0]);
+       if (dev->ctx[1])
+               camerarx_phy_disable(dev->ctx[1]);
+       kfree(dev->cm);
+
+       cal_runtime_put(dev);
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id cal_of_match[] = {
+       { .compatible = "ti,cal", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, cal_of_match);
+#else
+#define cal_of_match NULL
+#endif
+
+static struct platform_driver cal_pdrv = {
+       .probe          = cal_probe,
+       .remove         = cal_remove,
+       .driver         = {
+               .name   = CAL_MODULE_NAME,
+               .of_match_table = cal_of_match,
+       },
+};
+
+module_platform_driver(cal_pdrv);
diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h
new file mode 100644 (file)
index 0000000..096f1c1
--- /dev/null
@@ -0,0 +1,779 @@
+/*
+ * TI CAL camera interface driver
+ *
+ * Copyright (c) 2015 Texas Instruments Inc.
+ *
+ * Benoit Parrot, <bparrot@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef __TI_CAL_REGS_H
+#define __TI_CAL_REGS_H
+
+#define CAL_NUM_CSI2_PORTS             2
+
+/* CAL register offsets */
+
+#define CAL_HL_REVISION                        0x0000
+#define CAL_HL_HWINFO                  0x0004
+#define CAL_HL_SYSCONFIG               0x0010
+#define CAL_HL_IRQ_EOI                 0x001c
+#define CAL_HL_IRQSTATUS_RAW(m)                (0x20U + ((m-1) * 0x10U))
+#define CAL_HL_IRQSTATUS(m)            (0x24U + ((m-1) * 0x10U))
+#define CAL_HL_IRQENABLE_SET(m)                (0x28U + ((m-1) * 0x10U))
+#define CAL_HL_IRQENABLE_CLR(m)                (0x2cU + ((m-1) * 0x10U))
+#define CAL_PIX_PROC(m)                        (0xc0U + ((m-1) * 0x4U))
+#define CAL_CTRL                       0x100
+#define CAL_CTRL1                      0x104
+#define CAL_LINE_NUMBER_EVT            0x108
+#define CAL_VPORT_CTRL1                        0x120
+#define CAL_VPORT_CTRL2                        0x124
+#define CAL_BYS_CTRL1                  0x130
+#define CAL_BYS_CTRL2                  0x134
+#define CAL_RD_DMA_CTRL                        0x140
+#define CAL_RD_DMA_PIX_ADDR            0x144
+#define CAL_RD_DMA_PIX_OFST            0x148
+#define CAL_RD_DMA_XSIZE               0x14c
+#define CAL_RD_DMA_YSIZE               0x150
+#define CAL_RD_DMA_INIT_ADDR           0x154
+#define CAL_RD_DMA_INIT_OFST           0x168
+#define CAL_RD_DMA_CTRL2               0x16c
+#define CAL_WR_DMA_CTRL(m)             (0x200U + ((m-1) * 0x10U))
+#define CAL_WR_DMA_ADDR(m)             (0x204U + ((m-1) * 0x10U))
+#define CAL_WR_DMA_OFST(m)             (0x208U + ((m-1) * 0x10U))
+#define CAL_WR_DMA_XSIZE(m)            (0x20cU + ((m-1) * 0x10U))
+#define CAL_CSI2_PPI_CTRL(m)           (0x300U + ((m-1) * 0x80U))
+#define CAL_CSI2_COMPLEXIO_CFG(m)      (0x304U + ((m-1) * 0x80U))
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS(m)        (0x308U + ((m-1) * 0x80U))
+#define CAL_CSI2_SHORT_PACKET(m)       (0x30cU + ((m-1) * 0x80U))
+#define CAL_CSI2_COMPLEXIO_IRQENABLE(m)        (0x310U + ((m-1) * 0x80U))
+#define CAL_CSI2_TIMING(m)             (0x314U + ((m-1) * 0x80U))
+#define CAL_CSI2_VC_IRQENABLE(m)       (0x318U + ((m-1) * 0x80U))
+#define CAL_CSI2_VC_IRQSTATUS(m)       (0x328U + ((m-1) * 0x80U))
+#define CAL_CSI2_CTX0(m)               (0x330U + ((m-1) * 0x80U))
+#define CAL_CSI2_CTX1(m)               (0x334U + ((m-1) * 0x80U))
+#define CAL_CSI2_CTX2(m)               (0x338U + ((m-1) * 0x80U))
+#define CAL_CSI2_CTX3(m)               (0x33cU + ((m-1) * 0x80U))
+#define CAL_CSI2_CTX4(m)               (0x340U + ((m-1) * 0x80U))
+#define CAL_CSI2_CTX5(m)               (0x344U + ((m-1) * 0x80U))
+#define CAL_CSI2_CTX6(m)               (0x348U + ((m-1) * 0x80U))
+#define CAL_CSI2_CTX7(m)               (0x34cU + ((m-1) * 0x80U))
+#define CAL_CSI2_STATUS0(m)            (0x350U + ((m-1) * 0x80U))
+#define CAL_CSI2_STATUS1(m)            (0x354U + ((m-1) * 0x80U))
+#define CAL_CSI2_STATUS2(m)            (0x358U + ((m-1) * 0x80U))
+#define CAL_CSI2_STATUS3(m)            (0x35cU + ((m-1) * 0x80U))
+#define CAL_CSI2_STATUS4(m)            (0x360U + ((m-1) * 0x80U))
+#define CAL_CSI2_STATUS5(m)            (0x364U + ((m-1) * 0x80U))
+#define CAL_CSI2_STATUS6(m)            (0x368U + ((m-1) * 0x80U))
+#define CAL_CSI2_STATUS7(m)            (0x36cU + ((m-1) * 0x80U))
+
+/* CAL CSI2 PHY register offsets */
+#define CAL_CSI2_PHY_REG0              0x000
+#define CAL_CSI2_PHY_REG1              0x004
+#define CAL_CSI2_PHY_REG2              0x008
+
+/* CAL Control Module Core Camerrx Control register offsets */
+#define CM_CTRL_CORE_CAMERRX_CONTROL   0x000
+
+/*********************************************************************
+* Generic value used in various field below
+*********************************************************************/
+
+#define CAL_GEN_DISABLE                        0
+#define CAL_GEN_ENABLE                 1
+#define CAL_GEN_FALSE                  0
+#define CAL_GEN_TRUE                   1
+
+/*********************************************************************
+* Field Definition Macros
+*********************************************************************/
+
+#define CAL_HL_REVISION_MINOR_MASK             0x3f
+#define CAL_HL_REVISION_MINOR_SHIFT            0
+#define CAL_HL_REVISION_CUSTOM_MASK            0x03
+#define CAL_HL_REVISION_CUSTOM_SHIFT           6
+#define CAL_HL_REVISION_MAJOR_MASK             0x07
+#define CAL_HL_REVISION_MAJOR_SHIFT            8
+#define CAL_HL_REVISION_RTL_MASK               0x1f
+#define CAL_HL_REVISION_RTL_SHIFT              11
+#define CAL_HL_REVISION_FUNC_MASK              0xfff
+#define CAL_HL_REVISION_FUNC_SHIFT             16
+#define CAL_HL_REVISION_SCHEME_MASK            0x03
+#define CAL_HL_REVISION_SCHEME_SHIFT           30
+#define CAL_HL_REVISION_SCHEME_H08                     1
+#define CAL_HL_REVISION_SCHEME_LEGACY                  0
+
+#define CAL_HL_HWINFO_WFIFO_MASK               0xf
+#define CAL_HL_HWINFO_WFIFO_SHIFT              0
+#define CAL_HL_HWINFO_RFIFO_MASK               0xf
+#define CAL_HL_HWINFO_RFIFO_SHIFT              4
+#define CAL_HL_HWINFO_PCTX_MASK                        0x1f
+#define CAL_HL_HWINFO_PCTX_SHIFT               8
+#define CAL_HL_HWINFO_WCTX_MASK                        0x3f
+#define CAL_HL_HWINFO_WCTX_SHIFT               13
+#define CAL_HL_HWINFO_VFIFO_MASK               0xf
+#define CAL_HL_HWINFO_VFIFO_SHIFT              19
+#define CAL_HL_HWINFO_NCPORT_MASK              0x1f
+#define CAL_HL_HWINFO_NCPORT_SHIFT             23
+#define CAL_HL_HWINFO_NPPI_CTXS0_MASK          0x3
+#define CAL_HL_HWINFO_NPPI_CTXS0_SHIFT         28
+#define CAL_HL_HWINFO_NPPI_CTXS1_MASK          0x3
+#define CAL_HL_HWINFO_NPPI_CTXS1_SHIFT         30
+#define CAL_HL_HWINFO_NPPI_CONTEXTS_ZERO               0
+#define CAL_HL_HWINFO_NPPI_CONTEXTS_FOUR               1
+#define CAL_HL_HWINFO_NPPI_CONTEXTS_EIGHT              2
+#define CAL_HL_HWINFO_NPPI_CONTEXTS_RESERVED           3
+
+#define CAL_HL_SYSCONFIG_SOFTRESET_MASK                0x01
+#define CAL_HL_SYSCONFIG_SOFTRESET_SHIFT       0
+#define CAL_HL_SYSCONFIG_SOFTRESET_DONE                        0x0
+#define CAL_HL_SYSCONFIG_SOFTRESET_PENDING             0x1
+#define CAL_HL_SYSCONFIG_SOFTRESET_NOACTION            0x0
+#define CAL_HL_SYSCONFIG_SOFTRESET_RESET               0x1
+#define CAL_HL_SYSCONFIG_IDLE_MASK             0x03
+#define CAL_HL_SYSCONFIG_IDLE_SHIFT            2
+#define CAL_HL_SYSCONFIG_IDLEMODE_FORCE                        0
+#define CAL_HL_SYSCONFIG_IDLEMODE_NO                   1
+#define CAL_HL_SYSCONFIG_IDLEMODE_SMART1               2
+#define CAL_HL_SYSCONFIG_IDLEMODE_SMART2               3
+
+#define CAL_HL_IRQ_EOI_LINE_NUMBER_MASK                0x0001
+#define CAL_HL_IRQ_EOI_LINE_NUMBER_SHIFT       0
+#define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0               0
+#define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0                        0
+
+#define CAL_HL_IRQ_SHIFT(m)                    (m-1)
+/*#define CAL_HL_IRQ_MASK(m)                   (0x1 << (m-1)) */
+#define CAL_HL_IRQ_MASK(m)                     0x1
+#define CAL_HL_IRQ_NOACTION                            0x0
+#define CAL_HL_IRQ_ENABLE                              0x1
+#define CAL_HL_IRQ_CLEAR                               0x1
+#define CAL_HL_IRQ_DISABLED                            0x0
+#define CAL_HL_IRQ_ENABLED                             0x1
+#define CAL_HL_IRQ_PENDING                             0x1
+
+#define CAL_PIX_PROC_EN_MASK                   0x1
+#define CAL_PIX_PROC_EN_SHIFT                  0
+#define CAL_PIX_PROC_EXTRACT_MASK              0xf
+#define CAL_PIX_PROC_EXTRACT_SHIFT             1
+#define CAL_PIX_PROC_EXTRACT_B6                                0x0
+#define CAL_PIX_PROC_EXTRACT_B7                                0x1
+#define CAL_PIX_PROC_EXTRACT_B8                                0x2
+#define CAL_PIX_PROC_EXTRACT_B10                       0x3
+#define CAL_PIX_PROC_EXTRACT_B10_MIPI                  0x4
+#define CAL_PIX_PROC_EXTRACT_B12                       0x5
+#define CAL_PIX_PROC_EXTRACT_B12_MIPI                  0x6
+#define CAL_PIX_PROC_EXTRACT_B14                       0x7
+#define CAL_PIX_PROC_EXTRACT_B14_MIPI                  0x8
+#define CAL_PIX_PROC_EXTRACT_B16_BE                    0x9
+#define CAL_PIX_PROC_EXTRACT_B16_LE                    0xa
+#define CAL_PIX_PROC_DPCMD_MASK                        0x1f
+#define CAL_PIX_PROC_DPCMD_SHIFT               5
+#define CAL_PIX_PROC_DPCMD_BYPASS                      0x0
+#define CAL_PIX_PROC_DPCMD_DPCM_10_8_1                 0x2
+#define CAL_PIX_PROC_DPCMD_DPCM_12_8_1                 0x8
+#define CAL_PIX_PROC_DPCMD_DPCM_10_7_1                 0x4
+#define CAL_PIX_PROC_DPCMD_DPCM_10_7_2                 0x5
+#define CAL_PIX_PROC_DPCMD_DPCM_10_6_1                 0x6
+#define CAL_PIX_PROC_DPCMD_DPCM_10_6_2                 0x7
+#define CAL_PIX_PROC_DPCMD_DPCM_12_7_1                 0xa
+#define CAL_PIX_PROC_DPCMD_DPCM_12_6_1                 0xc
+#define CAL_PIX_PROC_DPCMD_DPCM_14_10                  0xe
+#define CAL_PIX_PROC_DPCMD_DPCM_14_8_1                 0x10
+#define CAL_PIX_PROC_DPCMD_DPCM_16_12_1                        0x12
+#define CAL_PIX_PROC_DPCMD_DPCM_16_10_1                        0x14
+#define CAL_PIX_PROC_DPCMD_DPCM_16_8_1                 0x16
+#define CAL_PIX_PROC_DPCME_MASK                        0x1f
+#define CAL_PIX_PROC_DPCME_SHIFT               11
+#define CAL_PIX_PROC_DPCME_BYPASS                      0x0
+#define CAL_PIX_PROC_DPCME_DPCM_10_8_1                 0x2
+#define CAL_PIX_PROC_DPCME_DPCM_12_8_1                 0x8
+#define CAL_PIX_PROC_DPCME_DPCM_14_10                  0xe
+#define CAL_PIX_PROC_DPCME_DPCM_14_8_1                 0x10
+#define CAL_PIX_PROC_DPCME_DPCM_16_12_1                        0x12
+#define CAL_PIX_PROC_DPCME_DPCM_16_10_1                        0x14
+#define CAL_PIX_PROC_DPCME_DPCM_16_8_1                 0x16
+#define CAL_PIX_PROC_PACK_MASK                 0x7
+#define CAL_PIX_PROC_PACK_SHIFT                        16
+#define CAL_PIX_PROC_PACK_B8                           0x0
+#define CAL_PIX_PROC_PACK_B10_MIPI                     0x2
+#define CAL_PIX_PROC_PACK_B12                          0x3
+#define CAL_PIX_PROC_PACK_B12_MIPI                     0x4
+#define CAL_PIX_PROC_PACK_B16                          0x5
+#define CAL_PIX_PROC_PACK_ARGB                         0x6
+#define CAL_PIX_PROC_CPORT_MASK                        0x1f
+#define CAL_PIX_PROC_CPORT_SHIFT               19
+
+#define CAL_CTRL_POSTED_WRITES_MASK            0x1
+#define CAL_CTRL_POSTED_WRITES_SHIFT           0
+#define CAL_CTRL_POSTED_WRITES_NONPOSTED               0
+#define CAL_CTRL_POSTED_WRITES                         1
+#define CAL_CTRL_TAGCNT_MASK                   0xf
+#define CAL_CTRL_TAGCNT_SHIFT                  1
+#define CAL_CTRL_BURSTSIZE_MASK                        0x3
+#define CAL_CTRL_BURSTSIZE_SHIFT               5
+#define CAL_CTRL_BURSTSIZE_BURST16                     0x0
+#define CAL_CTRL_BURSTSIZE_BURST32                     0x1
+#define CAL_CTRL_BURSTSIZE_BURST64                     0x2
+#define CAL_CTRL_BURSTSIZE_BURST128                    0x3
+#define CAL_CTRL_LL_FORCE_STATE_MASK           0x3f
+#define CAL_CTRL_LL_FORCE_STATE_SHIFT          7
+#define CAL_CTRL_MFLAGL_MASK                   0xff
+#define CAL_CTRL_MFLAGL_SHIFT                  13
+#define CAL_CTRL_PWRSCPCLK_MASK                        0x1
+#define CAL_CTRL_PWRSCPCLK_SHIFT               21
+#define CAL_CTRL_PWRSCPCLK_AUTO                                0
+#define CAL_CTRL_PWRSCPCLK_FORCE                       1
+#define CAL_CTRL_RD_DMA_STALL_MASK             0x1
+#define CAL_CTRL_RD_DMA_STALL_SHIFT            22
+#define CAL_CTRL_MFLAGH_MASK                   0xff
+#define CAL_CTRL_MFLAGH_SHIFT                  24
+
+#define CAL_CTRL1_PPI_GROUPING_MASK            0x3
+#define CAL_CTRL1_PPI_GROUPING_SHIFT           0
+#define CAL_CTRL1_PPI_GROUPING_DISABLED                        0
+#define CAL_CTRL1_PPI_GROUPING_RESERVED                        1
+#define CAL_CTRL1_PPI_GROUPING_0                       2
+#define CAL_CTRL1_PPI_GROUPING_1                       3
+#define CAL_CTRL1_INTERLEAVE01_MASK            0x3
+#define CAL_CTRL1_INTERLEAVE01_SHIFT           2
+#define CAL_CTRL1_INTERLEAVE01_DISABLED                        0
+#define CAL_CTRL1_INTERLEAVE01_PIX1                    1
+#define CAL_CTRL1_INTERLEAVE01_PIX4                    2
+#define CAL_CTRL1_INTERLEAVE01_RESERVED                        3
+#define CAL_CTRL1_INTERLEAVE23_MASK            0x3
+#define CAL_CTRL1_INTERLEAVE23_SHIFT           4
+#define CAL_CTRL1_INTERLEAVE23_DISABLED                        0
+#define CAL_CTRL1_INTERLEAVE23_PIX1                    1
+#define CAL_CTRL1_INTERLEAVE23_PIX4                    2
+#define CAL_CTRL1_INTERLEAVE23_RESERVED                        3
+
+#define CAL_LINE_NUMBER_EVT_CPORT_MASK         0x1f
+#define CAL_LINE_NUMBER_EVT_CPORT_SHIFT                0
+#define CAL_LINE_NUMBER_EVT_MASK               0x3fff
+#define CAL_LINE_NUMBER_EVT_SHIFT              16
+
+#define CAL_VPORT_CTRL1_PCLK_SHIFT             0
+#define CAL_VPORT_CTRL1_PCLK_MASK              0x1ffff
+#define CAL_VPORT_CTRL1_XBLK_SHIFT             17
+#define CAL_VPORT_CTRL1_XBLK_MASK              0xff
+#define CAL_VPORT_CTRL1_YBLK_SHIFT             25
+#define CAL_VPORT_CTRL1_YBLK_MASK              0x3f
+#define CAL_VPORT_CTRL1_WIDTH_SHIFT            31
+#define CAL_VPORT_CTRL1_WIDTH_MASK             0x1
+#define CAL_VPORT_CTRL1_WIDTH_ONE                      0
+#define CAL_VPORT_CTRL1_WIDTH_TWO                      1
+
+#define CAL_VPORT_CTRL2_CPORT_SHIFT            0
+#define CAL_VPORT_CTRL2_CPORT_MASK             0x1f
+#define CAL_VPORT_CTRL2_FREERUNNING_SHIFT      15
+#define CAL_VPORT_CTRL2_FREERUNNING_MASK       0x1
+#define CAL_VPORT_CTRL2_FREERUNNING_GATED              0
+#define CAL_VPORT_CTRL2_FREERUNNING_FREE               1
+#define CAL_VPORT_CTRL2_FS_RESETS_SHIFT                16
+#define CAL_VPORT_CTRL2_FS_RESETS_MASK         0x1
+#define CAL_VPORT_CTRL2_FS_RESETS_NO                   0
+#define CAL_VPORT_CTRL2_FS_RESETS_YES                  1
+#define CAL_VPORT_CTRL2_FSM_RESET_SHIFT                17
+#define CAL_VPORT_CTRL2_FSM_RESET_MASK         0x1
+#define CAL_VPORT_CTRL2_FSM_RESET_NOEFFECT             0
+#define CAL_VPORT_CTRL2_FSM_RESET                      1
+#define CAL_VPORT_CTRL2_RDY_THR_SHIFT          18
+#define CAL_VPORT_CTRL2_RDY_THR_MASK           0x3fff
+
+#define CAL_BYS_CTRL1_PCLK_SHIFT               0
+#define CAL_BYS_CTRL1_PCLK_MASK                        0x1ffff
+#define CAL_BYS_CTRL1_XBLK_SHIFT               17
+#define CAL_BYS_CTRL1_XBLK_MASK                        0xff
+#define CAL_BYS_CTRL1_YBLK_SHIFT               25
+#define CAL_BYS_CTRL1_YBLK_MASK                        0x3f
+#define CAL_BYS_CTRL1_BYSINEN_SHIFT            31
+#define CAL_BYS_CTRL1_BYSINEN_MASK             0x1
+
+#define CAL_BYS_CTRL2_CPORTIN_SHIFT            0
+#define CAL_BYS_CTRL2_CPORTIN_MASK             0x1f
+#define CAL_BYS_CTRL2_CPORTOUT_SHIFT           5
+#define CAL_BYS_CTRL2_CPORTOUT_MASK            0x1f
+#define CAL_BYS_CTRL2_DUPLICATEDDATA_SHIFT     10
+#define CAL_BYS_CTRL2_DUPLICATEDDATA_MASK      0x1
+#define CAL_BYS_CTRL2_DUPLICATEDDATA_NO                        0
+#define CAL_BYS_CTRL2_DUPLICATEDDATA_YES               1
+#define CAL_BYS_CTRL2_FREERUNNING_SHIFT                11
+#define CAL_BYS_CTRL2_FREERUNNING_MASK         0x1
+#define CAL_BYS_CTRL2_FREERUNNING_NO                   0
+#define CAL_BYS_CTRL2_FREERUNNING_YES                  1
+
+#define CAL_RD_DMA_CTRL_GO_SHIFT               0
+#define CAL_RD_DMA_CTRL_GO_MASK                        0x1
+#define CAL_RD_DMA_CTRL_GO_DIS                         0
+#define CAL_RD_DMA_CTRL_GO_EN                          1
+#define CAL_RD_DMA_CTRL_GO_IDLE                                0
+#define CAL_RD_DMA_CTRL_GO_BUSY                                1
+#define CAL_RD_DMA_CTRL_INIT_SHIFT             1
+#define CAL_RD_DMA_CTRL_INIT_MASK              0x1
+#define CAL_RD_DMA_CTRL_BW_LIMITER_SHIFT       2
+#define CAL_RD_DMA_CTRL_BW_LIMITER_MASK                0x1ff
+#define CAL_RD_DMA_CTRL_OCP_TAG_CNT_SHIFT      11
+#define CAL_RD_DMA_CTRL_OCP_TAG_CNT_MASK       0xf
+#define CAL_RD_DMA_CTRL_PCLK_SHIFT             15
+#define CAL_RD_DMA_CTRL_PCLK_MASK              0x1ffff
+
+#define CAL_RD_DMA_PIX_ADDR_SHIFT              3
+#define CAL_RD_DMA_PIX_ADDR_MASK               0x1fffffff
+
+#define CAL_RD_DMA_PIX_OFST_SHIFT              4
+#define CAL_RD_DMA_PIX_OFST_MASK               0xfffffff
+
+#define CAL_RD_DMA_XSIZE_SHIFT                 19
+#define CAL_RD_DMA_XSIZE_MASK                  0x1fff
+
+#define CAL_RD_DMA_YSIZE_SHIFT                 16
+#define CAL_RD_DMA_YSIZE_MASK                  0x3fff
+
+#define CAL_RD_DMA_INIT_ADDR_SHIFT             3
+#define CAL_RD_DMA_INIT_ADDR_MASK              0x1fffffff
+
+#define CAL_RD_DMA_INIT_OFST_SHIFT             3
+#define CAL_RD_DMA_INIT_OFST_MASK              0x1fffffff
+
+#define CAL_RD_DMA_CTRL2_CIRC_MODE_SHIFT       0
+#define CAL_RD_DMA_CTRL2_CIRC_MODE_MASK                0x7
+#define CAL_RD_DMA_CTRL2_CIRC_MODE_DIS                 0
+#define CAL_RD_DMA_CTRL2_CIRC_MODE_ONE                 1
+#define CAL_RD_DMA_CTRL2_CIRC_MODE_FOUR                        2
+#define CAL_RD_DMA_CTRL2_CIRC_MODE_SIXTEEN             3
+#define CAL_RD_DMA_CTRL2_CIRC_MODE_SIXTYFOUR           4
+#define CAL_RD_DMA_CTRL2_CIRC_MODE_RESERVED            5
+#define CAL_RD_DMA_CTRL2_ICM_CSTART_SHIFT      3
+#define CAL_RD_DMA_CTRL2_ICM_CSTART_MASK       0x1
+#define CAL_RD_DMA_CTRL2_PATTERN_SHIFT         4
+#define CAL_RD_DMA_CTRL2_PATTERN_MASK          0x3
+#define CAL_RD_DMA_CTRL2_PATTERN_LINEAR                        0
+#define CAL_RD_DMA_CTRL2_PATTERN_YUV420                        1
+#define CAL_RD_DMA_CTRL2_PATTERN_RD2SKIP2              2
+#define CAL_RD_DMA_CTRL2_PATTERN_RD2SKIP4              3
+#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_SHIFT  6
+#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_MASK   0x1
+#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_FREERUNNING    0
+#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_WAITFORBYSOUT  1
+#define CAL_RD_DMA_CTRL2_CIRC_SIZE_SHIFT       16
+#define CAL_RD_DMA_CTRL2_CIRC_SIZE_MASK                0x3fff
+
+#define CAL_WR_DMA_CTRL_MODE_SHIFT             0
+#define CAL_WR_DMA_CTRL_MODE_MASK              0x7
+#define CAL_WR_DMA_CTRL_MODE_DIS                       0
+#define CAL_WR_DMA_CTRL_MODE_SHD                       1
+#define CAL_WR_DMA_CTRL_MODE_CNT                       2
+#define CAL_WR_DMA_CTRL_MODE_CNT_INIT                  3
+#define CAL_WR_DMA_CTRL_MODE_CONST                     4
+#define CAL_WR_DMA_CTRL_MODE_RESERVED                  5
+#define CAL_WR_DMA_CTRL_PATTERN_SHIFT          3
+#define CAL_WR_DMA_CTRL_PATTERN_MASK           0x3
+#define CAL_WR_DMA_CTRL_PATTERN_LINEAR                 0
+#define CAL_WR_DMA_CTRL_PATTERN_WR2SKIP2               2
+#define CAL_WR_DMA_CTRL_PATTERN_WR2SKIP4               3
+#define CAL_WR_DMA_CTRL_PATTERN_RESERVED               1
+#define CAL_WR_DMA_CTRL_ICM_PSTART_SHIFT       5
+#define CAL_WR_DMA_CTRL_ICM_PSTART_MASK                0x1
+#define CAL_WR_DMA_CTRL_DTAG_SHIFT             6
+#define CAL_WR_DMA_CTRL_DTAG_MASK              0x7
+#define CAL_WR_DMA_CTRL_DTAG_ATT_HDR                   0
+#define CAL_WR_DMA_CTRL_DTAG_ATT_DAT                   1
+#define CAL_WR_DMA_CTRL_DTAG                           2
+#define CAL_WR_DMA_CTRL_DTAG_PIX_HDR                   3
+#define CAL_WR_DMA_CTRL_DTAG_PIX_DAT                   4
+#define CAL_WR_DMA_CTRL_DTAG_D5                                5
+#define CAL_WR_DMA_CTRL_DTAG_D6                                6
+#define CAL_WR_DMA_CTRL_DTAG_D7                                7
+#define CAL_WR_DMA_CTRL_CPORT_SHIFT            9
+#define CAL_WR_DMA_CTRL_CPORT_MASK             0x1f
+#define CAL_WR_DMA_CTRL_STALL_RD_SHIFT         14
+#define CAL_WR_DMA_CTRL_STALL_RD_MASK          0x1
+#define CAL_WR_DMA_CTRL_YSIZE_SHIFT            18
+#define CAL_WR_DMA_CTRL_YSIZE_MASK             0x3fff
+
+#define CAL_WR_DMA_ADDR_SHIFT                  4
+#define CAL_WR_DMA_ADDR_MASK                   0xfffffff
+
+#define CAL_WR_DMA_OFST_SHIFT                  4
+#define CAL_WR_DMA_OFST_MASK                   0x7fff
+#define CAL_WR_DMA_OFST_CIRC_MODE_SHIFT                22
+#define CAL_WR_DMA_OFST_CIRC_MODE_MASK         0x3
+#define CAL_WR_DMA_OFST_CIRC_MODE_ONE                  1
+#define CAL_WR_DMA_OFST_CIRC_MODE_FOUR                 2
+#define CAL_WR_DMA_OFST_CIRC_MODE_SIXTYFOUR            3
+#define CAL_WR_DMA_OFST_CIRC_MODE_DISABLED             0
+#define CAL_WR_DMA_OFST_CIRC_SIZE_SHIFT                24
+#define CAL_WR_DMA_OFST_CIRC_SIZE_MASK         0xff
+
+#define CAL_WR_DMA_XSIZE_XSKIP_SHIFT           3
+#define CAL_WR_DMA_XSIZE_XSKIP_MASK            0x1fff
+#define CAL_WR_DMA_XSIZE_SHIFT                 19
+#define CAL_WR_DMA_XSIZE_MASK                  0x1fff
+
+#define CAL_CSI2_PPI_CTRL_IF_EN_SHIFT          0
+#define CAL_CSI2_PPI_CTRL_IF_EN_MASK           0x1
+#define CAL_CSI2_PPI_CTRL_ECC_EN_SHIFT         2
+#define CAL_CSI2_PPI_CTRL_ECC_EN_MASK          0x1
+#define CAL_CSI2_PPI_CTRL_FRAME_SHIFT          3
+#define CAL_CSI2_PPI_CTRL_FRAME_MASK           0x1
+#define CAL_CSI2_PPI_CTRL_FRAME_IMMEDIATE              0
+#define CAL_CSI2_PPI_CTRL_FRAME                                1
+
+#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT    0
+#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK     0x7
+#define CAL_CSI2_COMPLEXIO_CFG_POSITION_5                      5
+#define CAL_CSI2_COMPLEXIO_CFG_POSITION_4                      4
+#define CAL_CSI2_COMPLEXIO_CFG_POSITION_3                      3
+#define CAL_CSI2_COMPLEXIO_CFG_POSITION_2                      2
+#define CAL_CSI2_COMPLEXIO_CFG_POSITION_1                      1
+#define CAL_CSI2_COMPLEXIO_CFG_POSITION_NOT_USED               0
+#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_SHIFT         3
+#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_CFG_POL_PLUSMINUS                   0
+#define CAL_CSI2_COMPLEXIO_CFG_POL_MINUSPLUS                   1
+#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POSITION_SHIFT    4
+#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POSITION_MASK     0x7
+#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POL_SHIFT         7
+#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POL_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POSITION_SHIFT    8
+#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POSITION_MASK     0x7
+#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POL_SHIFT         11
+#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POL_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POSITION_SHIFT    12
+#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POSITION_MASK     0x7
+#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POL_SHIFT         15
+#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POL_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POSITION_SHIFT    16
+#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POSITION_MASK     0x7
+#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POL_SHIFT         19
+#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POL_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_AUTO_SHIFT          24
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_AUTO_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_SHIFT                25
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK         0x3
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_OFF            0
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON             1
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ULP            2
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_SHIFT           27
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK            0x3
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF               0
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON                        1
+#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ULP               2
+#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_SHIFT                29
+#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK         0x1
+#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED       1
+#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING         0
+#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_SHIFT                30
+#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK         0x1
+#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL                      0
+#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL          1
+
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS1_SHIFT           0
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS1_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS2_SHIFT           1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS2_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS3_SHIFT           2
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS3_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS4_SHIFT           3
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS4_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS5_SHIFT           4
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTHS5_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS1_SHIFT       5
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS1_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS2_SHIFT       6
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS2_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS3_SHIFT       7
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS3_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS4_SHIFT       8
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS4_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS5_SHIFT       9
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRSOTSYNCHS5_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC1_SHIFT             10
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC1_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC2_SHIFT             11
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC2_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC3_SHIFT             12
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC3_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC4_SHIFT             13
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC4_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC5_SHIFT             14
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRESC5_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL1_SHIFT         15
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL1_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL2_SHIFT         16
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL2_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL3_SHIFT         17
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL3_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL4_SHIFT         18
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL4_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL5_SHIFT         19
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ERRCONTROL5_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM1_SHIFT          20
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM1_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM2_SHIFT          21
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM2_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM3_SHIFT          22
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM3_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM4_SHIFT          23
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM4_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM5_SHIFT          24
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEULPM5_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEALLULPMENTER_SHIFT   25
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEALLULPMENTER_MASK    0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEALLULPMEXIT_SHIFT    26
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_STATEALLULPMEXIT_MASK     0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_FIFO_OVR_SHIFT            27
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_FIFO_OVR_MASK             0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_SHORT_PACKET_SHIFT                28
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_SHORT_PACKET_MASK         0x1
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ECC_NO_CORRECTION_SHIFT   30
+#define CAL_CSI2_COMPLEXIO_IRQSTATUS_ECC_NO_CORRECTION_MASK    0x1
+
+#define CAL_CSI2_SHORT_PACKET_SHIFT    0
+#define CAL_CSI2_SHORT_PACKET_MASK     0xffffff
+
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS1_SHIFT           0
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS1_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS2_SHIFT           1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS2_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS3_SHIFT           2
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS3_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS4_SHIFT           3
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS4_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS5_SHIFT           4
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTHS5_MASK            0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS1_SHIFT       5
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS1_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS2_SHIFT       6
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS2_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS3_SHIFT       7
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS3_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS4_SHIFT       8
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS4_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS5_SHIFT       9
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRSOTSYNCHS5_MASK                0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC1_SHIFT             10
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC1_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC2_SHIFT             11
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC2_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC3_SHIFT             12
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC3_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC4_SHIFT             13
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC4_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC5_SHIFT             14
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRESC5_MASK              0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL1_SHIFT         15
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL1_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL2_SHIFT         16
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL2_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL3_SHIFT         17
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL3_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL4_SHIFT         18
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL4_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL5_SHIFT         19
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ERRCONTROL5_MASK          0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM1_SHIFT          20
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM1_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM2_SHIFT          21
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM2_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM3_SHIFT          22
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM3_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM4_SHIFT          23
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM4_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM5_SHIFT          24
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEULPM5_MASK           0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEALLULPMENTER_SHIFT   25
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEALLULPMENTER_MASK    0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEALLULPMEXIT_SHIFT    26
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_STATEALLULPMEXIT_MASK     0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_FIFO_OVR_SHIFT            27
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_FIFO_OVR_MASK             0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_SHORT_PACKET_SHIFT                28
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_SHORT_PACKET_MASK         0x1
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ECC_NO_CORRECTION_SHIFT   30
+#define CAL_CSI2_COMPLEXIO_IRQENABLE_ECC_NO_CORRECTION_MASK    0x1
+
+#define CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT   0
+#define CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK    0x1fff
+#define CAL_CSI2_TIMING_STOP_STATE_X4_IO1_SHIFT                13
+#define CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK         0x1
+#define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_SHIFT       14
+#define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK                0x1
+#define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_SHIFT                15
+#define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK         0x1
+
+#define CAL_CSI2_VC_IRQENABLE_FS_IRQ_0_SHIFT                   0
+#define CAL_CSI2_VC_IRQENABLE_FS_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_FE_IRQ_0_SHIFT                   1
+#define CAL_CSI2_VC_IRQENABLE_FE_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_LS_IRQ_0_SHIFT                   2
+#define CAL_CSI2_VC_IRQENABLE_LS_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_LE_IRQ_0_SHIFT                   3
+#define CAL_CSI2_VC_IRQENABLE_LE_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_CS_IRQ_0_SHIFT                   4
+#define CAL_CSI2_VC_IRQENABLE_CS_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_ECC_CORRECTION0_IRQ_0_SHIFT      5
+#define CAL_CSI2_VC_IRQENABLE_ECC_CORRECTION0_IRQ_0_MASK       0x1
+#define CAL_CSI2_VC_IRQENABLE_FS_IRQ_1_SHIFT                   8
+#define CAL_CSI2_VC_IRQENABLE_FS_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_FE_IRQ_1_SHIFT                   9
+#define CAL_CSI2_VC_IRQENABLE_FE_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_LS_IRQ_1_SHIFT                   10
+#define CAL_CSI2_VC_IRQENABLE_LS_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_LE_IRQ_1_SHIFT                   11
+#define CAL_CSI2_VC_IRQENABLE_LE_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_CS_IRQ_1_SHIFT                   12
+#define CAL_CSI2_VC_IRQENABLE_CS_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_ECC_CORRECTION0_IRQ_1_SHIFT      13
+#define CAL_CSI2_VC_IRQENABLE_ECC_CORRECTION0_IRQ_1_MASK       0x1
+#define CAL_CSI2_VC_IRQENABLE_FS_IRQ_2_SHIFT                   16
+#define CAL_CSI2_VC_IRQENABLE_FS_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_FE_IRQ_2_SHIFT                   17
+#define CAL_CSI2_VC_IRQENABLE_FE_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_LS_IRQ_2_SHIFT                   18
+#define CAL_CSI2_VC_IRQENABLE_LS_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_LE_IRQ_2_SHIFT                   19
+#define CAL_CSI2_VC_IRQENABLE_LE_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_CS_IRQ_2_SHIFT                   20
+#define CAL_CSI2_VC_IRQENABLE_CS_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_ECC_CORRECTION0_IRQ_2_SHIFT      21
+#define CAL_CSI2_VC_IRQENABLE_ECC_CORRECTION0_IRQ_2_MASK       0x1
+#define CAL_CSI2_VC_IRQENABLE_FS_IRQ_3_SHIFT                   24
+#define CAL_CSI2_VC_IRQENABLE_FS_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_FE_IRQ_3_SHIFT                   25
+#define CAL_CSI2_VC_IRQENABLE_FE_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_LS_IRQ_3_SHIFT                   26
+#define CAL_CSI2_VC_IRQENABLE_LS_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_LE_IRQ_3_SHIFT                   27
+#define CAL_CSI2_VC_IRQENABLE_LE_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_CS_IRQ_3_SHIFT                   28
+#define CAL_CSI2_VC_IRQENABLE_CS_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQENABLE_ECC_CORRECTION0_IRQ_3_SHIFT      29
+#define CAL_CSI2_VC_IRQENABLE_ECC_CORRECTION0_IRQ_3_MASK       0x1
+
+#define CAL_CSI2_VC_IRQSTATUS_FS_IRQ_0_SHIFT                   0
+#define CAL_CSI2_VC_IRQSTATUS_FS_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_FE_IRQ_0_SHIFT                   1
+#define CAL_CSI2_VC_IRQSTATUS_FE_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_LS_IRQ_0_SHIFT                   2
+#define CAL_CSI2_VC_IRQSTATUS_LS_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_LE_IRQ_0_SHIFT                   3
+#define CAL_CSI2_VC_IRQSTATUS_LE_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_CS_IRQ_0_SHIFT                   4
+#define CAL_CSI2_VC_IRQSTATUS_CS_IRQ_0_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_ECC_CORRECTION0_IRQ_0_SHIFT      5
+#define CAL_CSI2_VC_IRQSTATUS_ECC_CORRECTION0_IRQ_0_MASK       0x1
+#define CAL_CSI2_VC_IRQSTATUS_FS_IRQ_1_SHIFT                   8
+#define CAL_CSI2_VC_IRQSTATUS_FS_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_FE_IRQ_1_SHIFT                   9
+#define CAL_CSI2_VC_IRQSTATUS_FE_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_LS_IRQ_1_SHIFT                   10
+#define CAL_CSI2_VC_IRQSTATUS_LS_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_LE_IRQ_1_SHIFT                   11
+#define CAL_CSI2_VC_IRQSTATUS_LE_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_CS_IRQ_1_SHIFT                   12
+#define CAL_CSI2_VC_IRQSTATUS_CS_IRQ_1_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_ECC_CORRECTION0_IRQ_1_SHIFT      13
+#define CAL_CSI2_VC_IRQSTATUS_ECC_CORRECTION0_IRQ_1_MASK       0x1
+#define CAL_CSI2_VC_IRQSTATUS_FS_IRQ_2_SHIFT                   16
+#define CAL_CSI2_VC_IRQSTATUS_FS_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_FE_IRQ_2_SHIFT                   17
+#define CAL_CSI2_VC_IRQSTATUS_FE_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_LS_IRQ_2_SHIFT                   18
+#define CAL_CSI2_VC_IRQSTATUS_LS_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_LE_IRQ_2_SHIFT                   19
+#define CAL_CSI2_VC_IRQSTATUS_LE_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_CS_IRQ_2_SHIFT                   20
+#define CAL_CSI2_VC_IRQSTATUS_CS_IRQ_2_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_ECC_CORRECTION0_IRQ_2_SHIFT      21
+#define CAL_CSI2_VC_IRQSTATUS_ECC_CORRECTION0_IRQ_2_MASK       0x1
+#define CAL_CSI2_VC_IRQSTATUS_FS_IRQ_3_SHIFT                   24
+#define CAL_CSI2_VC_IRQSTATUS_FS_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_FE_IRQ_3_SHIFT                   25
+#define CAL_CSI2_VC_IRQSTATUS_FE_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_LS_IRQ_3_SHIFT                   26
+#define CAL_CSI2_VC_IRQSTATUS_LS_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_LE_IRQ_3_SHIFT                   27
+#define CAL_CSI2_VC_IRQSTATUS_LE_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_CS_IRQ_3_SHIFT                   28
+#define CAL_CSI2_VC_IRQSTATUS_CS_IRQ_3_MASK                    0x1
+#define CAL_CSI2_VC_IRQSTATUS_ECC_CORRECTION0_IRQ_3_SHIFT      29
+#define CAL_CSI2_VC_IRQSTATUS_ECC_CORRECTION0_IRQ_3_MASK       0x1
+
+#define CAL_CSI2_CTX_DT_SHIFT          0
+#define CAL_CSI2_CTX_DT_MASK           0x3f
+#define CAL_CSI2_CTX_VC_SHIFT          6
+#define CAL_CSI2_CTX_VC_MASK           0x3
+#define CAL_CSI2_CTX_CPORT_SHIFT       8
+#define CAL_CSI2_CTX_CPORT_MASK                0x1f
+#define CAL_CSI2_CTX_ATT_SHIFT         13
+#define CAL_CSI2_CTX_ATT_MASK          0x1
+#define CAL_CSI2_CTX_ATT_PIX                   0
+#define CAL_CSI2_CTX_ATT                       1
+#define CAL_CSI2_CTX_PACK_MODE_SHIFT   14
+#define CAL_CSI2_CTX_PACK_MODE_MASK    0x1
+#define CAL_CSI2_CTX_PACK_MODE_LINE            0
+#define CAL_CSI2_CTX_PACK_MODE_FRAME           1
+#define CAL_CSI2_CTX_LINES_SHIFT       16
+#define CAL_CSI2_CTX_LINES_MASK                0x3fff
+
+#define CAL_CSI2_STATUS_FRAME_SHIF     0
+#define CAL_CSI2_STATUS_FRAME_MASK     0xffff
+
+#define CAL_CSI2_PHY_REG0_THS_SETTLE_SHIFT     0
+#define CAL_CSI2_PHY_REG0_THS_SETTLE_MASK      0xff
+#define CAL_CSI2_PHY_REG0_THS_TERM_SHIFT       8
+#define CAL_CSI2_PHY_REG0_THS_TERM_MASK                0xff
+#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_SHIFT  24
+#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK   0x1
+#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE                1
+#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_ENABLE         0
+
+#define CAL_CSI2_PHY_REG1_TCLK_SETTLE_SHIFT                    0
+#define CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK                     0xff
+#define CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT             8
+#define CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK              0x3
+#define CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_SHIFT           10
+#define CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK            0xFF
+#define CAL_CSI2_PHY_REG1_TCLK_TERM_SHIFT                      18
+#define CAL_CSI2_PHY_REG1_TCLK_TERM_MASK                       0x7f
+#define CAL_CSI2_PHY_REG0_CLOCK_MISS_DETECTOR_STATUS_SHIFT     25
+#define CAL_CSI2_PHY_REG0_CLOCK_MISS_DETECTOR_STATUS_MASK      0x1
+#define CAL_CSI2_PHY_REG0_CLOCK_MISS_DETECTOR_STATUS_ERROR             1
+#define CAL_CSI2_PHY_REG0_CLOCK_MISS_DETECTOR_STATUS_SUCCESS           0
+#define CAL_CSI2_PHY_REG0_RESET_DONE_STATUS_SHIFT              28
+#define CAL_CSI2_PHY_REG0_RESET_DONE_STATUS_MASK               0x3
+
+#define CAL_CSI2_PHY_REG2_CCP2_SYNC_PATTERN_SHIFT              0
+#define CAL_CSI2_PHY_REG2_CCP2_SYNC_PATTERN_MASK               0xffffff
+#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT         24
+#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC3_MASK          0x3
+#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT         26
+#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC2_MASK          0x3
+#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT         28
+#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC1_MASK          0x3
+#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT         30
+#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC0_MASK          0x3
+
+#define CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_SHIFT                   0
+#define CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK                    0x1
+#define CM_CAMERRX_CTRL_CSI1_CAMMODE_SHIFT                     1
+#define CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK                      0x3
+#define CM_CAMERRX_CTRL_CSI1_LANEENABLE_SHIFT                  3
+#define CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK                   0x3
+#define CM_CAMERRX_CTRL_CSI1_MODE_SHIFT                                5
+#define CM_CAMERRX_CTRL_CSI1_MODE_MASK                         0x1
+#define CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_SHIFT                   10
+#define CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK                    0x1
+#define CM_CAMERRX_CTRL_CSI0_CAMMODE_SHIFT                     11
+#define CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK                      0x3
+#define CM_CAMERRX_CTRL_CSI0_LANEENABLE_SHIFT                  13
+#define CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK                   0xf
+#define CM_CAMERRX_CTRL_CSI0_MODE_SHIFT                                17
+#define CM_CAMERRX_CTRL_CSI0_MODE_MASK                         0x1
+
+#endif
index 93f0af546b769b14604e6d5a6fcb9aa68a20f68d..67bd4f95956f4ec819504902b9312e17fdba32b4 100644 (file)
@@ -88,9 +88,6 @@ void sc_set_hs_coeffs(struct sc_data *sc, void *addr, unsigned int src_w,
                }
        }
 
-       if (idx == sc->hs_index)
-               return;
-
        cp = scaler_hs_coeffs[idx];
 
        for (i = 0; i < SC_NUM_PHASES * 2; i++) {
@@ -105,8 +102,6 @@ void sc_set_hs_coeffs(struct sc_data *sc, void *addr, unsigned int src_w,
                coeff_h += SC_NUM_TAPS_MEM_ALIGN - SC_H_NUM_TAPS;
        }
 
-       sc->hs_index = idx;
-
        sc->load_coeff_h = true;
 }
 
@@ -134,9 +129,6 @@ void sc_set_vs_coeffs(struct sc_data *sc, void *addr, unsigned int src_h,
                idx = VS_LT_9_16_SCALE + sixteenths - 8;
        }
 
-       if (idx == sc->vs_index)
-               return;
-
        cp = scaler_vs_coeffs[idx];
 
        for (i = 0; i < SC_NUM_PHASES * 2; i++) {
@@ -150,7 +142,6 @@ void sc_set_vs_coeffs(struct sc_data *sc, void *addr, unsigned int src_h,
                coeff_v += SC_NUM_TAPS_MEM_ALIGN - SC_V_NUM_TAPS;
        }
 
-       sc->vs_index = idx;
        sc->load_coeff_v = true;
 }
 
index 60e411e05c308e27702e20fc87adcb032078f03a..de947db989902b11b59649be099654c107941faa 100644 (file)
@@ -189,9 +189,6 @@ struct sc_data {
        bool                    load_coeff_h;   /* have new h SC coeffs */
        bool                    load_coeff_v;   /* have new v SC coeffs */
 
-       unsigned int            hs_index;       /* h SC coeffs selector */
-       unsigned int            vs_index;       /* v SC coeffs selector */
-
        struct platform_device *pdev;
 };
 
index 2cd0f87da8e29785ad38a87b05b219893024e720..50f4b1bbddc624e96d6d41e6b13bdbf98089d34e 100644 (file)
@@ -127,9 +127,9 @@ static struct vip_srce_info srce_info[5] = {
 
 static struct vip_fmt vip_formats[] = {
        {
-               .name           = "YUV 444 co-planar",
+               .name           = "NV24 YUV 444 co-planar",
                .fourcc         = V4L2_PIX_FMT_NV24,
-               .code           = V4L2_MBUS_FMT_YDYUYDYV8_1X16,
+               .code           = V4L2_MBUS_FMT_UYVY8_2X8,
                .colorspace     = V4L2_COLORSPACE_SMPTE170M,
                .coplanar       = 1,
                .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_Y444],
@@ -137,9 +137,9 @@ static struct vip_fmt vip_formats[] = {
                                  },
        },
        {
-               .name           = "YUV 422 co-planar",
+               .name           = "NV16 YUV 422 co-planar",
                .fourcc         = V4L2_PIX_FMT_NV16,
-               .code           = V4L2_MBUS_FMT_YDYUYDYV8_1X16,
+               .code           = V4L2_MBUS_FMT_UYVY8_2X8,
                .colorspace     = V4L2_COLORSPACE_SMPTE170M,
                .coplanar       = 1,
                .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_Y422],
@@ -147,9 +147,9 @@ static struct vip_fmt vip_formats[] = {
                                  },
        },
        {
-               .name           = "YUV 420 co-planar",
+               .name           = "NV12 YUV 420 co-planar",
                .fourcc         = V4L2_PIX_FMT_NV12,
-               .code           = V4L2_MBUS_FMT_YDYUYDYV8_1X16,
+               .code           = V4L2_MBUS_FMT_UYVY8_2X8,
                .colorspace     = V4L2_COLORSPACE_SMPTE170M,
                .coplanar       = 1,
                .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_Y420],
@@ -162,25 +162,34 @@ static struct vip_fmt vip_formats[] = {
                .code           = V4L2_MBUS_FMT_UYVY8_2X8,
                .colorspace     = V4L2_COLORSPACE_SMPTE170M,
                .coplanar       = 0,
-               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_CY422],
+               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_CBY422],
                                  },
        },
        {
                .name           = "YUYV 422 packed",
                .fourcc         = V4L2_PIX_FMT_YUYV,
-               .code           = V4L2_MBUS_FMT_YUYV8_2X8,
+               .code           = V4L2_MBUS_FMT_UYVY8_2X8,
                .colorspace     = V4L2_COLORSPACE_SMPTE170M,
                .coplanar       = 0,
-               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YC422],
+               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YCB422],
                                  },
        },
        {
                .name           = "VYUY 422 packed",
                .fourcc         = V4L2_PIX_FMT_VYUY,
-               .code           = V4L2_MBUS_FMT_VYUY8_2X8,
+               .code           = V4L2_MBUS_FMT_UYVY8_2X8,
+               .colorspace     = V4L2_COLORSPACE_SMPTE170M,
+               .coplanar       = 0,
+               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_CRY422],
+                                 },
+       },
+       {
+               .name           = "YVYU 422 packed",
+               .fourcc         = V4L2_PIX_FMT_YVYU,
+               .code           = V4L2_MBUS_FMT_UYVY8_2X8,
                .colorspace     = V4L2_COLORSPACE_SMPTE170M,
                .coplanar       = 0,
-               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YC422],
+               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YCR422],
                                  },
        },
        {
@@ -219,39 +228,11 @@ static char *fourcc_to_str(u32 fmt)
 /*
  * Find our format description corresponding to the passed v4l2_format
  */
-#ifdef DISABLED_FOR_NOW
-static struct vip_fmt *find_format_by_pix(u32 pixelformat)
-{
-       struct vip_fmt *fmt;
-       unsigned int k;
-
-       for (k = 0; k < ARRAY_SIZE(vip_formats); k++) {
-               fmt = &vip_formats[k];
-               if (fmt->fourcc == pixelformat)
-                       return fmt;
-       }
 
-       return NULL;
-}
-#endif
-
-static struct vip_fmt *find_format_by_code(u32 code)
-{
-       struct vip_fmt *fmt;
-       unsigned int k;
-
-       for (k = 0; k < ARRAY_SIZE(vip_formats); k++) {
-               fmt = &vip_formats[k];
-               if (fmt->code == code)
-                       return fmt;
-       }
-
-       return NULL;
-}
-
-static struct vip_fmt *find_active_format_by_pix(struct vip_dev *dev,
-                                                u32 pixelformat)
+static struct vip_fmt *find_port_format_by_pix(struct vip_port *port,
+                                              u32 pixelformat)
 {
+       struct vip_dev *dev = port->dev;
        struct vip_fmt *fmt;
        unsigned int k;
 
@@ -264,21 +245,6 @@ static struct vip_fmt *find_active_format_by_pix(struct vip_dev *dev,
        return NULL;
 }
 
-static struct vip_fmt *find_active_format_by_code(struct vip_dev *dev,
-                                                u32 code)
-{
-       struct vip_fmt *fmt;
-       unsigned int k;
-
-       for (k = 0; k < dev->num_active_fmt; k++) {
-               fmt = dev->active_fmt[k];
-               if (fmt->code == code)
-                       return fmt;
-       }
-
-       return NULL;
-}
-
 static LIST_HEAD(vip_shared_list);
 
 static inline struct vip_dev *notifier_to_vip_dev(struct v4l2_async_notifier *n)
@@ -304,6 +270,7 @@ static inline struct vip_dev *notifier_to_vip_dev(struct v4l2_async_notifier *n)
 static int alloc_port(struct vip_dev *, int);
 static void free_port(struct vip_port *);
 static int vip_setup_parser(struct vip_port *port);
+static void stop_dma(struct vip_stream *stream);
 
 static inline u32 read_sreg(struct vip_shared *shared, int offset)
 {
@@ -524,7 +491,7 @@ static void vip_set_pclk_polarity(struct vip_port *port, int polarity)
 {
        u32 val, ret, offset;
 
-       if (polarity == 0 && port->dev->syscon) {
+       if (polarity == 1 && port->dev->syscon) {
 
                /*
                 * When the VIP parser is configured to so that the pixel clock
@@ -1024,9 +991,9 @@ static int add_out_dtd(struct vip_stream *stream, int srce_type)
         * This will make sure that an abort descriptor for this channel
         * would be submitted to VPDMA causing any ongoing  transaction to be
         * aborted and cleanup the VPDMA FSM for this channel */
-       dev->vpdma_channels[channel] = 1;
+       stream->vpdma_channels[channel] = 1;
 
-       vpdma_rawchan_add_out_dtd(&dev->desc_list, c_rect->width, c_rect,
+       vpdma_rawchan_add_out_dtd(&stream->desc_list, c_rect->width, c_rect,
                fmt->vpdma_fmt[plane], dma_addr, max_width, max_height,
                channel, flags);
 
@@ -1056,11 +1023,10 @@ static void add_stream_dtds(struct vip_stream *stream)
                add_out_dtd(stream, VIP_SRCE_CHROMA);
 }
 
-static void enable_irqs(struct vip_dev *dev, int irq_num)
+static void enable_irqs(struct vip_dev *dev, int irq_num, int list_num)
 {
        u32 reg_addr = VIP_INT0_ENABLE0_SET +
                        VIP_INTC_INTX_OFFSET * irq_num;
-       int list_num = dev->slice_id;
 
        write_sreg(dev->shared, reg_addr, 1 << (list_num * 2));
 
@@ -1068,24 +1034,23 @@ static void enable_irqs(struct vip_dev *dev, int irq_num)
                irq_num, list_num, true);
 }
 
-static void disable_irqs(struct vip_dev *dev, int irq_num)
+static void disable_irqs(struct vip_dev *dev, int irq_num, int list_num)
 {
        u32 reg_addr = VIP_INT0_ENABLE0_CLR +
                        VIP_INTC_INTX_OFFSET * irq_num;
-       int list_num = dev->slice_id;
 
-       write_sreg(dev->shared, reg_addr, 0xffffffff);
+       write_sreg(dev->shared, reg_addr, 1 << (list_num * 2));
 
        vpdma_enable_list_complete_irq(dev->shared->vpdma,
                irq_num, list_num, false);
 }
 
-static void clear_irqs(struct vip_dev *dev, int irq_num)
+static void clear_irqs(struct vip_dev *dev, int irq_num, int list_num)
 {
        u32 reg_addr = VIP_INT0_STATUS0_CLR +
                        VIP_INTC_INTX_OFFSET * irq_num;
 
-       write_sreg(dev->shared, reg_addr, 0xffffffff);
+       write_sreg(dev->shared, reg_addr, 1 << (list_num * 2));
 
        vpdma_clear_list_stat(dev->shared->vpdma, irq_num, dev->slice_id);
 }
@@ -1096,11 +1061,11 @@ static void populate_desc_list(struct vip_stream *stream)
        struct vip_dev *dev = port->dev;
        unsigned int list_length;
 
-       dev->desc_next = dev->desc_list.buf.addr;
+       stream->desc_next = stream->desc_list.buf.addr;
        add_stream_dtds(stream);
 
-       list_length = dev->desc_next - dev->desc_list.buf.addr;
-       vpdma_map_desc_buf(dev->shared->vpdma, &dev->desc_list.buf);
+       list_length = stream->desc_next - stream->desc_list.buf.addr;
+       vpdma_map_desc_buf(dev->shared->vpdma, &stream->desc_list.buf);
 }
 
 /*
@@ -1108,13 +1073,15 @@ static void populate_desc_list(struct vip_stream *stream)
  * Should be called after a new vb is queued and on a vpdma list
  * completion interrupt.
  */
-static void start_dma(struct vip_dev *dev, struct vip_buffer *buf)
+static void start_dma(struct vip_stream *stream, struct vip_buffer *buf)
 {
+       struct vip_dev *dev = stream->port->dev;
        struct vpdma_data *vpdma = dev->shared->vpdma;
+       int list_num = stream->list_num;
        dma_addr_t dma_addr;
        int drop_data;
 
-       if (vpdma_list_busy(vpdma, dev->slice_id)) {
+       if (vpdma_list_busy(vpdma, list_num)) {
                vip_err(dev, "vpdma list busy, cannot post");
                return;                         /* nothing to do */
        }
@@ -1130,9 +1097,17 @@ static void start_dma(struct vip_dev *dev, struct vip_buffer *buf)
                vip_dbg(4, dev, "start_dma: dropped\n");
        }
 
-       vpdma_update_dma_addr(dev->shared->vpdma, &dev->desc_list,
-                             dma_addr, dev->write_desc, drop_data);
-       vpdma_submit_descs(dev->shared->vpdma, &dev->desc_list, dev->slice_id);
+       vpdma_update_dma_addr(dev->shared->vpdma, &stream->desc_list,
+                             dma_addr, stream->write_desc, drop_data, 0);
+
+       if (stream->port->fmt->coplanar) {
+               dma_addr += stream->width * stream->height;
+               vpdma_update_dma_addr(dev->shared->vpdma, &stream->desc_list,
+                             dma_addr, stream->write_desc + 1, drop_data, 1);
+       }
+
+       vpdma_submit_descs(dev->shared->vpdma,
+                       &stream->desc_list, stream->list_num);
 }
 
 static void vip_schedule_next_buffer(struct vip_stream *stream)
@@ -1153,13 +1128,13 @@ static void vip_schedule_next_buffer(struct vip_stream *stream)
                                 struct vip_buffer, list);
 
                buf->drop = true;
-               list_move_tail(&buf->list, &dev->vip_bufs);
+               list_move_tail(&buf->list, &stream->post_bufs);
                buf = NULL;
        } else if (vb2_is_streaming(&stream->vb_vidq)) {
                buf = list_entry(stream->vidq.next,
                                struct vip_buffer, list);
                buf->drop = false;
-               list_move_tail(&buf->list, &dev->vip_bufs);
+               list_move_tail(&buf->list, &stream->post_bufs);
                vip_dbg(4, dev, "added next buffer\n");
        } else {
                vip_err(dev, "IRQ occurred when not streaming\n");
@@ -1171,12 +1146,12 @@ static void vip_schedule_next_buffer(struct vip_stream *stream)
                buf = list_entry(stream->dropq.next,
                                 struct vip_buffer, list);
                buf->drop = true;
-               list_move_tail(&buf->list, &dev->vip_bufs);
+               list_move_tail(&buf->list, &stream->post_bufs);
                buf = NULL;
        }
 
        spin_unlock_irqrestore(&dev->slock, flags);
-       start_dma(dev, buf);
+       start_dma(stream, buf);
 }
 
 static void vip_process_buffer_complete(struct vip_stream *stream)
@@ -1186,15 +1161,16 @@ static void vip_process_buffer_complete(struct vip_stream *stream)
        struct vb2_buffer *vb = NULL;
        unsigned long flags, fld;
 
-       buf = list_first_entry(&dev->vip_bufs, struct vip_buffer, list);
+       buf = list_first_entry(&stream->post_bufs, struct vip_buffer, list);
 
        if (stream->port->flags & FLAG_INTERLACED) {
-               vpdma_unmap_desc_buf(dev->shared->vpdma, &dev->desc_list.buf);
+               vpdma_unmap_desc_buf(dev->shared->vpdma,
+                                       &stream->desc_list.buf);
 
-               fld = dtd_get_field(dev->write_desc);
+               fld = dtd_get_field(stream->write_desc);
                stream->field = fld ? V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP;
 
-               vpdma_map_desc_buf(dev->shared->vpdma, &dev->desc_list.buf);
+               vpdma_map_desc_buf(dev->shared->vpdma, &stream->desc_list.buf);
        }
 
        if (buf) {
@@ -1226,8 +1202,9 @@ static void vip_process_buffer_complete(struct vip_stream *stream)
 static irqreturn_t vip_irq(int irq_vip, void *data)
 {
        struct vip_dev *dev = (struct vip_dev *)data;
+       struct vpdma_data *vpdma = dev->shared->vpdma;
        struct vip_stream *stream;
-       int list_num = dev->slice_id;
+       int list_num;
        int irq_num = dev->slice_id;
        u32 irqst, reg_addr;
 
@@ -1241,51 +1218,42 @@ static irqreturn_t vip_irq(int irq_vip, void *data)
        vip_dbg(8, dev, "IRQ %d VIP_INT%d_STATUS0 0x%x\n",
                irq_vip, irq_num, irqst);
        if (irqst) {
-               vpdma_clear_list_stat(dev->shared->vpdma, irq_num, list_num);
-
                reg_addr = VIP_INT0_STATUS0_CLR +
                        VIP_INTC_INTX_OFFSET * irq_num;
                write_sreg(dev->shared, reg_addr, irqst);
-       }
 
-       stream = dev->ports[0]->cap_streams[0];
-       if (dev->num_skip_irq)
-               dev->num_skip_irq--;
-       else
-               vip_process_buffer_complete(stream);
+               for (list_num = 0; list_num < 8;  list_num++) {
+                       /* Check for LIST_COMPLETE IRQ */
+                       if (!(irqst & (1 << list_num * 2)))
+                               continue;
 
-       vip_schedule_next_buffer(stream);
+                       vip_dbg(8, dev, "IRQ %d: handling LIST%d_COMPLETE\n",
+                               irq_num, list_num);
 
-       return IRQ_HANDLED;
-}
+                       stream = vpdma_hwlist_get_priv(vpdma, list_num);
+                       if (!stream || stream->list_num != list_num) {
+                               vip_err(dev, "IRQ occured for unused list");
+                               continue;
+                       }
 
-/*
- * video ioctls
- */
-static struct v4l2_mbus_framefmt *
-vip_video_pix_to_mbus(const struct v4l2_pix_format *pix,
-                     struct v4l2_mbus_framefmt *mbus)
-{
-       unsigned int i;
+                       vpdma_clear_list_stat(vpdma, irq_num, list_num);
 
-       memset(mbus, 0, sizeof(*mbus));
-       mbus->width = pix->width;
-       mbus->height = pix->height;
+                       if (dev->num_skip_irq)
+                               dev->num_skip_irq--;
+                       else
+                               vip_process_buffer_complete(stream);
 
-       mbus->code = V4L2_MBUS_FMT_YUYV8_2X8;
-       for (i = 0; i < ARRAY_SIZE(vip_formats) - 1; ++i) {
-               if (vip_formats[i].fourcc == pix->pixelformat) {
-                       mbus->code = vip_formats[i].code;
-                       break;
+                       vip_schedule_next_buffer(stream);
+                       irqst &= ~((1 << list_num * 2));
                }
        }
 
-       mbus->colorspace = pix->colorspace;
-       mbus->field = pix->field;
-
-       return mbus;
+       return IRQ_HANDLED;
 }
 
+/*
+ * video ioctls
+ */
 static int vip_querycap(struct file *file, void *priv,
                        struct v4l2_capability *cap)
 {
@@ -1293,7 +1261,8 @@ static int vip_querycap(struct file *file, void *priv,
        strncpy(cap->card, VIP_MODULE_NAME, sizeof(cap->card) - 1);
        snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
                VIP_MODULE_NAME);
-       cap->device_caps  = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
+       cap->device_caps  = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
+                           V4L2_CAP_READWRITE;
        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
        return 0;
 }
@@ -1307,6 +1276,7 @@ static int vip_enuminput(struct file *file, void *priv,
                return -EINVAL;
 
        inp->type = V4L2_INPUT_TYPE_CAMERA;
+       inp->std = stream->vfd->tvnorms;
        sprintf(inp->name, "camera %u", stream->vfd->num);
 
        return 0;
@@ -1330,7 +1300,9 @@ static int vip_querystd(struct file *file, void *fh, v4l2_std_id *std)
        struct vip_stream *stream = file2stream(file);
        struct vip_dev *dev = stream->port->dev;
 
+       *std = stream->vfd->tvnorms;
        v4l2_subdev_call(dev->sensor, video, querystd, std);
+       vip_dbg(1, dev, "querystd: 0x%lx\n", (unsigned long)*std);
        return 0;
 }
 
@@ -1339,8 +1311,10 @@ static int vip_g_std(struct file *file, void *fh, v4l2_std_id *std)
        struct vip_stream *stream = file2stream(file);
        struct vip_dev *dev = stream->port->dev;
 
-       *std = 0;
+       *std = stream->vfd->tvnorms;
        v4l2_subdev_call(dev->sensor, video, g_std_output, std);
+       vip_dbg(1, dev, "g_std: 0x%lx\n", (unsigned long)*std);
+
        return 0;
 }
 
@@ -1349,6 +1323,14 @@ static int vip_s_std(struct file *file, void *fh, v4l2_std_id std)
        struct vip_stream *stream = file2stream(file);
        struct vip_dev *dev = stream->port->dev;
 
+       vip_dbg(1, dev, "s_std: 0x%lx\n", (unsigned long)std);
+
+       if (!(std & stream->vfd->tvnorms)) {
+               vip_dbg(1, dev, "s_std after check: 0x%lx\n",
+                       (unsigned long)std);
+               return -EINVAL;
+       }
+
        v4l2_subdev_call(dev->sensor, video, s_std_output, std);
        return 0;
 }
@@ -1358,9 +1340,10 @@ static int vip_enum_fmt_vid_cap(struct file *file, void *priv,
 {
        struct vip_stream *stream = file2stream(file);
        struct vip_dev *dev = stream->port->dev;
-       struct vip_fmt *fmt;
+       struct vip_fmt *fmt = NULL;
 
        vip_dbg(3, dev, "enum_fmt index:%d\n", f->index);
+
        if (f->index >= dev->num_active_fmt)
                return -EINVAL;
 
@@ -1385,18 +1368,14 @@ static int vip_enum_framesizes(struct file *file, void *priv,
 {
        struct vip_stream *stream = file2stream(file);
        struct vip_dev *dev = stream->port->dev;
+       struct vip_port *port = stream->port;
        struct vip_fmt *fmt;
-       int ret;
 
-       fmt = find_active_format_by_pix(dev, f->pixel_format);
+       fmt = find_port_format_by_pix(port, f->pixel_format);
        if (!fmt)
                return -EINVAL;
 
-       ret = v4l2_subdev_call(dev->sensor, video, enum_framesizes, f);
-       if (ret)
-               vip_dbg(1, dev, "enum_framesizes failed in subdev\n");
-
-       return ret;
+       return v4l2_subdev_call(dev->sensor, video, enum_framesizes, f);
 }
 
 static int vip_enum_frameintervals(struct file *file, void *priv,
@@ -1404,6 +1383,7 @@ static int vip_enum_frameintervals(struct file *file, void *priv,
 {
        struct vip_stream *stream = file2stream(file);
        struct vip_dev *dev = stream->port->dev;
+       struct vip_port *port = stream->port;
        struct v4l2_frmsizeenum fsize;
        struct vip_fmt *fmt;
        int ret;
@@ -1411,7 +1391,7 @@ static int vip_enum_frameintervals(struct file *file, void *priv,
        if (f->index)
                return -EINVAL;
 
-       fmt = find_active_format_by_pix(dev, f->pixel_format);
+       fmt = find_port_format_by_pix(port, f->pixel_format);
        if (!fmt)
                return -EINVAL;
 
@@ -1421,8 +1401,6 @@ static int vip_enum_frameintervals(struct file *file, void *priv,
                ret = v4l2_subdev_call(dev->sensor, video,
                                        enum_framesizes, &fsize);
                if (ret) {
-                       if (fsize.index == 0)
-                               vip_dbg(1, dev, "enum_frameinterval failed on the first enum_framesize\n");
                        return -EINVAL;
                }
 
@@ -1437,8 +1415,9 @@ static int vip_enum_frameintervals(struct file *file, void *priv,
                            (f->height >= fsize.stepwise.min_height) &&
                            (f->height <= fsize.stepwise.max_height))
                                break;
-               } else
+               } else {
                        return -EINVAL;
+               }
        }
 
        f->type = V4L2_FRMIVAL_TYPE_DISCRETE;
@@ -1448,6 +1427,19 @@ static int vip_enum_frameintervals(struct file *file, void *priv,
        return 0;
 }
 
+static int vip_g_parm(struct file *file, void *priv,
+                     struct v4l2_streamparm *parm)
+{
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       parm->parm.capture.capability   = V4L2_CAP_TIMEPERFRAME;
+       parm->parm.capture.timeperframe.numerator = 1;
+       parm->parm.capture.timeperframe.denominator = 30;
+       parm->parm.capture.readbuffers  = 4;
+       return 0;
+}
+
 static int vip_s_parm(struct file *file, void *priv,
                        struct v4l2_streamparm *parm)
 {
@@ -1456,35 +1448,30 @@ static int vip_s_parm(struct file *file, void *priv,
 
        parm->parm.capture.timeperframe.numerator = 1;
        parm->parm.capture.timeperframe.denominator = 30;
+       parm->parm.capture.readbuffers  = 4;
 
        return 0;
 }
 
-static int vip_try_fmt_vid_cap(struct file *file, void *priv,
-                              struct v4l2_format *f)
+static int vip_calc_format_size(struct vip_port *port,
+                               struct vip_fmt *fmt,
+                               struct v4l2_format *f)
 {
-       struct vip_stream *stream = file2stream(file);
-       struct vip_dev *dev = stream->port->dev;
-       struct vip_fmt *fmt = find_active_format_by_pix(dev,
-                                                       f->fmt.pix.pixelformat);
-       enum v4l2_field field;
+       struct vip_dev *dev = port->dev;
+       enum v4l2_field *field;
 
        if (!fmt) {
-               vip_err(dev,
-                       "Fourcc format (0x%08x) invalid.\n",
-                       f->fmt.pix.pixelformat);
+               vip_dbg(2, dev,
+                       "no vip_fmt format provided!\n");
                return -EINVAL;
        }
 
-       field = f->fmt.pix.field;
-
-       if (field == V4L2_FIELD_ANY)
-               field = V4L2_FIELD_NONE;
-       else if (V4L2_FIELD_NONE != field && V4L2_FIELD_ALTERNATE != field)
+       field = &f->fmt.pix.field;
+       if (*field == V4L2_FIELD_ANY)
+               *field = V4L2_FIELD_NONE;
+       else if (V4L2_FIELD_NONE != *field && V4L2_FIELD_ALTERNATE != *field)
                return -EINVAL;
 
-       f->fmt.pix.field = field;
-
        v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, W_ALIGN,
                              &f->fmt.pix.height, MIN_H, MAX_H, H_ALIGN,
                              S_ALIGN);
@@ -1499,7 +1486,7 @@ static int vip_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.colorspace = fmt->colorspace;
        f->fmt.pix.priv = 0;
 
-       vip_dbg(3, dev, "try_fmt fourcc:%s size: %dx%d bpl:%d img_size:%d\n",
+       vip_dbg(3, dev, "calc_format_size: fourcc:%s size: %dx%d bpl:%d img_size:%d\n",
                fourcc_to_str(f->fmt.pix.pixelformat),
                f->fmt.pix.width, f->fmt.pix.height,
                f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
@@ -1507,16 +1494,75 @@ static int vip_try_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
+static int vip_try_fmt_vid_cap(struct file *file, void *priv,
+                              struct v4l2_format *f)
+{
+       struct vip_stream *stream = file2stream(file);
+       struct vip_port *port = stream->port;
+       struct vip_dev *dev = port->dev;
+       struct v4l2_frmsizeenum fsize;
+       struct vip_fmt *fmt;
+       int ret, found;
+
+       vip_dbg(3, dev, "try_fmt fourcc:%s size: %dx%d\n",
+               fourcc_to_str(f->fmt.pix.pixelformat),
+               f->fmt.pix.width, f->fmt.pix.height);
+
+       fmt = find_port_format_by_pix(port, f->fmt.pix.pixelformat);
+       if (!fmt) {
+               vip_dbg(2, dev,
+                       "Fourcc format (0x%08x) not found.\n",
+                       f->fmt.pix.pixelformat);
+
+               /* Just get the first one enumerated */
+               fmt = dev->active_fmt[0];
+               f->fmt.pix.pixelformat = fmt->fourcc;
+       }
+
+       /* check for/find a valid width/height */
+       ret = 0;
+       found = false;
+       for (fsize.index = 0; ; fsize.index++) {
+               ret = v4l2_subdev_call(dev->sensor, video,
+                                       enum_framesizes, &fsize);
+               if (ret)
+                       break;
+
+               if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+                       if ((f->fmt.pix.width == fsize.discrete.width) &&
+                           (f->fmt.pix.height == fsize.discrete.height)) {
+                               found = true;
+                               break;
+                       }
+               } else if ((fsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) ||
+                          (fsize.type == V4L2_FRMSIZE_TYPE_STEPWISE)) {
+                       if ((f->fmt.pix.width >= fsize.stepwise.min_width) &&
+                           (f->fmt.pix.width <= fsize.stepwise.max_width) &&
+                           (f->fmt.pix.height >= fsize.stepwise.min_height) &&
+                           (f->fmt.pix.height <= fsize.stepwise.max_height)) {
+                               found = true;
+                               break;
+                       }
+               }
+       }
+
+       if (!found) {
+               /* use existing values as default */
+               f->fmt.pix.width = port->mbus_framefmt.width;
+               f->fmt.pix.height =  port->mbus_framefmt.height;
+       }
+
+       /* That we have a fmt calculate imagesize and bytesperline */
+       return vip_calc_format_size(port, fmt, f);
+}
+
 static int vip_g_fmt_vid_cap(struct file *file, void *priv,
                             struct v4l2_format *f)
 {
        struct vip_stream *stream = file2stream(file);
        struct vip_port *port = stream->port;
        struct vip_dev *dev = stream->port->dev;
-       struct v4l2_mbus_framefmt mbus_fmt;
-       struct vip_fmt *fmt;
-       struct v4l2_format try_f;
-       int ret;
+       struct vip_fmt *fmt = port->fmt;
 
        /* Use last known values or defaults */
        f->fmt.pix.width        = stream->width;
@@ -1527,99 +1573,19 @@ static int vip_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = stream->bytesperline;
        f->fmt.pix.sizeimage    = stream->sizeimage;
 
-       /* Check with the subdevice */
-       ret = v4l2_subdev_call(dev->sensor, video, g_mbus_fmt, &mbus_fmt);
-       if (ret)
-               vip_dbg(1, dev, "g_mbus_fmt failed in subdev\n");
-
-       fmt = find_active_format_by_code(dev, mbus_fmt.code);
-       if (!fmt) {
-               vip_err(dev,
-                       "mbus_code (0x%08x) invalid.\n",
-                       mbus_fmt.code);
-               return -EINVAL;
-       }
-
-       vip_dbg(3, dev, "g_fmt subdev mbus_code: %04X fourcc:%s size: %dx%d\n",
-               fmt->code,
-               fourcc_to_str(fmt->fourcc),
-               mbus_fmt.width, mbus_fmt.height);
-
-       /*
-        * Run a try_fmt call to properly calculate
-        * the sizeimage and bytesperline values
-        * in case the defaults were not accurate.
-        */
-       try_f = *f;
-       try_f.fmt.pix.pixelformat = fmt->fourcc;
-       try_f.fmt.pix.width = mbus_fmt.width;
-       try_f.fmt.pix.height = mbus_fmt.height;
-       try_f.fmt.pix.field = mbus_fmt.field;
-       try_f.fmt.pix.colorspace = mbus_fmt.colorspace;
-
-       ret = vip_try_fmt_vid_cap(file, priv, &try_f);
-       if (ret)
-               return ret;
-
-       if (port->fmt != fmt) {
-               vip_dbg(1, dev, "g_fmt fmt mismatch port->fmt:%p fmt:%p\n",
-                       port->fmt, fmt);
-               vip_dbg(1, dev, "g_fmt port->fmt->fourcc:%s\n",
-                       fourcc_to_str(port->fmt->fourcc));
-               vip_dbg(1, dev, "fmt->fourcc:%s\n",
-                       fourcc_to_str(fmt->fourcc));
-               vip_dbg(1, dev, "g_fmt port->fmt->name:%s fmt->name:%s\n",
-                       port->fmt->name, fmt->name);
-               port->fmt = fmt;
-       }
-       /*
-        * Since everything looks correct update
-        * the local copy as well to make sure we are consistent
-        */
-       *f = try_f;
-       stream->width = f->fmt.pix.width;
-       stream->height = f->fmt.pix.height;
-       stream->sup_field = f->fmt.pix.field;
-       if (stream->sup_field == V4L2_FIELD_ALTERNATE)
-               port->flags |= FLAG_INTERLACED;
-       else
-               port->flags &= ~FLAG_INTERLACED;
-       stream->bytesperline = f->fmt.pix.bytesperline;
-       stream->sizeimage = f->fmt.pix.sizeimage;
-       port->c_rect.left       = 0;
-       port->c_rect.top        = 0;
-       port->c_rect.width      = stream->width;
-       port->c_rect.height     = stream->height;
-
-       vip_dbg(3, dev, "g_fmt fourcc:%s size: %dx%d bpl:%d img_size:%d\n",
+       vip_dbg(3, dev,
+               "g_fmt fourcc:%s code: %04x size: %dx%d bpl:%d img_size:%d\n",
                fourcc_to_str(f->fmt.pix.pixelformat),
+               fmt->code,
                f->fmt.pix.width, f->fmt.pix.height,
                f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
+       vip_dbg(3, dev, "g_fmt vpdma data type: 0x%02X\n",
+               port->fmt->vpdma_fmt[0]->data_type);
 
        return 0;
 }
 
-/*
- * Set the registers that are modified when the video format changes.
- */
-static void set_fmt_params(struct vip_stream *stream)
-{
-       struct vip_dev *dev = stream->port->dev;
-
-       stream->sequence = 0;
-       stream->field = V4L2_FIELD_TOP;
-
-       if (stream->port->fmt->colorspace == V4L2_COLORSPACE_SRGB) {
-               vip_set_slice_path(dev, VIP_RGB_OUT_LO_DATA_SELECT);
-               /* Set alpha component in background color */
-               vpdma_set_bg_color(dev->shared->vpdma,
-                       (struct vpdma_data_format *)
-                        stream->port->fmt->vpdma_fmt[0],
-                       0xff);
-       }
-}
-
-int vip_s_fmt_vid_cap(struct file *file, void *priv,
+static int vip_s_fmt_vid_cap(struct file *file, void *priv,
                             struct v4l2_format *f)
 {
        struct vip_stream *stream = file2stream(file);
@@ -1646,14 +1612,10 @@ int vip_s_fmt_vid_cap(struct file *file, void *priv,
                return -EBUSY;
        }
 
-       port->fmt               = find_active_format_by_pix(dev,
-                                       f->fmt.pix.pixelformat);
+       port->fmt = find_port_format_by_pix(port,
+                                           f->fmt.pix.pixelformat);
        stream->width           = f->fmt.pix.width;
        stream->height          = f->fmt.pix.height;
-       if (port->fmt->colorspace != f->fmt.pix.colorspace)
-               vip_dbg(1, dev, "s_fmt colorspace mismatch port->fmt %d f->fmt %d\n",
-                       port->fmt->colorspace, f->fmt.pix.colorspace);
-
        stream->bytesperline    = f->fmt.pix.bytesperline;
        stream->sizeimage       = f->fmt.pix.sizeimage;
        stream->sup_field       = f->fmt.pix.field;
@@ -1668,17 +1630,16 @@ int vip_s_fmt_vid_cap(struct file *file, void *priv,
        else
                port->flags &= ~FLAG_INTERLACED;
 
-       vip_dbg(1, dev,
-               "Setting format for type %d, wxh: %dx%d, fourcc:%s\n",
-               f->type, stream->width, stream->height,
-               fourcc_to_str(port->fmt->fourcc));
-
        vip_dbg(3, dev, "s_fmt fourcc:%s size: %dx%d bpl:%d img_size:%d\n",
                fourcc_to_str(f->fmt.pix.pixelformat),
                f->fmt.pix.width, f->fmt.pix.height,
                f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
 
-       mf = vip_video_pix_to_mbus(&f->fmt.pix, &sfmt.format);
+       mf = &sfmt.format;
+       v4l2_fill_mbus_format(mf, &f->fmt.pix, port->fmt->code);
+
+       /* Save it */
+       port->mbus_framefmt = *mf;
 
        vip_dbg(3, dev, "s_fmt pix_to_mbus mbus_code: %04X size: %dx%d\n",
                mf->code,
@@ -1700,10 +1661,41 @@ int vip_s_fmt_vid_cap(struct file *file, void *priv,
        vip_dbg(3, dev, "s_fmt subdev s_fmt mbus_code: %04X size: %dx%d\n",
                mf->code,
                mf->width, mf->height);
+       vip_dbg(3, dev, "s_fmt vpdma data type: 0x%02X\n",
+               port->fmt->vpdma_fmt[0]->data_type);
 
        return 0;
 }
-EXPORT_SYMBOL(vip_s_fmt_vid_cap);
+
+/*
+ * Set the registers that are modified when the video format changes.
+ */
+static void set_fmt_params(struct vip_stream *stream)
+{
+       struct vip_dev *dev = stream->port->dev;
+       int data_path_reg;
+
+       stream->sequence = 0;
+       stream->field = V4L2_FIELD_TOP;
+
+       if (stream->port->fmt->colorspace == V4L2_COLORSPACE_SRGB) {
+               vip_set_slice_path(dev, VIP_RGB_OUT_LO_DATA_SELECT);
+               /* Set alpha component in background color */
+               vpdma_set_bg_color(dev->shared->vpdma,
+                                  (struct vpdma_data_format *)
+                                  stream->port->fmt->vpdma_fmt[0],
+                                  0xff);
+       }
+
+       data_path_reg = VIP_VIP1_DATA_PATH_SELECT + 4 * dev->slice_id;
+       if (stream->port->fmt->coplanar) {
+               stream->port->flags &= ~FLAG_MULT_PORT;
+               write_vreg(dev, data_path_reg, 0x600);
+       } else {
+               stream->port->flags |= FLAG_MULT_PORT;
+               write_vreg(dev, data_path_reg, 0x8000);
+       }
+}
 
 static int vip_g_selection(struct file *file, void *fh,
                           struct v4l2_selection *s)
@@ -1807,7 +1799,7 @@ static const struct v4l2_ioctl_ops vip_ioctl_ops = {
        .vidioc_enum_frameintervals     = vip_enum_frameintervals,
        .vidioc_enum_framesizes         = vip_enum_framesizes,
        .vidioc_s_parm                  = vip_s_parm,
-
+       .vidioc_g_parm                  = vip_g_parm,
        .vidioc_g_selection     = vip_g_selection,
        .vidioc_s_selection     = vip_s_selection,
        .vidioc_reqbufs         = vb2_ioctl_reqbufs,
@@ -1916,26 +1908,28 @@ static int vip_start_streaming(struct vb2_queue *vq, unsigned int count)
        dev->num_skip_irq = VIP_VPDMA_FIFO_SIZE;
 
        spin_lock_irqsave(&dev->slock, flags);
-       if (vpdma_list_busy(dev->shared->vpdma, dev->slice_id)) {
+       if (vpdma_list_busy(dev->shared->vpdma, stream->list_num)) {
                spin_unlock_irqrestore(&dev->slock, flags);
-               vpdma_unmap_desc_buf(dev->shared->vpdma, &dev->desc_list.buf);
-               vpdma_reset_desc_list(&dev->desc_list);
+               vpdma_unmap_desc_buf(dev->shared->vpdma,
+                               &stream->desc_list.buf);
+               vpdma_reset_desc_list(&stream->desc_list);
                return -EBUSY;
        }
 
-       list_move_tail(&buf->list, &dev->vip_bufs);
+       list_move_tail(&buf->list, &stream->post_bufs);
        spin_unlock_irqrestore(&dev->slock, flags);
 
        vip_dbg(2, dev, "start_streaming: start_dma buf 0x%x\n",
                (unsigned int)buf);
-       start_dma(dev, buf);
+       start_dma(stream, buf);
 
        /* We enable the irq after posting the vpdma descriptor
         * to prevent sprurious interrupt coming in before the
         * vb2 layer is completely ready to handle them
         * otherwise the vb2_streaming test would fail early on
          */
-       enable_irqs(dev, dev->slice_id);
+       enable_irqs(dev, dev->slice_id, stream->list_num);
+
        return 0;
 }
 
@@ -1956,12 +1950,14 @@ static int vip_stop_streaming(struct vb2_queue *vq)
                        vip_dbg(1, dev, "stream on failed in subdev\n");
        }
 
-       disable_irqs(dev, dev->slice_id);
-       clear_irqs(dev, dev->slice_id);
+       disable_irqs(dev, dev->slice_id, stream->list_num);
+       clear_irqs(dev, dev->slice_id, stream->list_num);
+       stop_dma(stream);
 
        /* release all active buffers */
-       while (!list_empty(&dev->vip_bufs)) {
-               buf = list_entry(dev->vip_bufs.next, struct vip_buffer, list);
+       while (!list_empty(&stream->post_bufs)) {
+               buf = list_entry(stream->post_bufs.next,
+                                       struct vip_buffer, list);
                list_del(&buf->list);
                if (buf->drop == 1)
                        list_add_tail(&buf->list, &stream->dropq);
@@ -1977,8 +1973,8 @@ static int vip_stop_streaming(struct vb2_queue *vq)
        if (!vb2_is_streaming(vq))
                return 0;
 
-       vpdma_unmap_desc_buf(dev->shared->vpdma, &dev->desc_list.buf);
-       vpdma_reset_desc_list(&dev->desc_list);
+       vpdma_unmap_desc_buf(dev->shared->vpdma, &stream->desc_list.buf);
+       vpdma_reset_desc_list(&stream->desc_list);
 
        return 0;
 }
@@ -2014,33 +2010,123 @@ static struct vb2_ops vip_video_qops = {
  */
 
 static int vip_init_dev(struct vip_dev *dev)
+{
+       if (dev->num_ports != 0)
+               goto done;
+
+       vip_set_clock_enable(dev, 1);
+done:
+       dev->num_ports++;
+
+       return 0;
+}
+
+static int vip_init_port(struct vip_port *port)
 {
        int ret;
+       struct vip_dev *dev = port->dev;
+       struct vip_fmt *fmt;
+       struct v4l2_mbus_framefmt *mbus_fmt = &port->mbus_framefmt;
 
-       if (dev->num_ports != 0)
+       if (port->num_streams != 0)
                goto done;
 
-       ret = vpdma_create_desc_list(&dev->desc_list, VIP_DESC_LIST_SIZE,
+       ret = vip_init_dev(port->dev);
+       if (ret)
+               goto done;
+
+       /* Get subdevice current frame format */
+       ret = v4l2_subdev_call(dev->sensor, video, g_mbus_fmt, mbus_fmt);
+       if (ret)
+               vip_dbg(1, dev, "init_port g_mbus_fmt failed in subdev\n");
+
+       /* try to find one that matches */
+       fmt = find_port_format_by_pix(port, mbus_fmt->code);
+       if (!fmt) {
+               vip_dbg(1, dev, "subdev default mbus_fmt %04x is not matched.\n",
+                       mbus_fmt->code);
+               /* if all else fails just pick the first one */
+               fmt = dev->active_fmt[0];
+
+               mbus_fmt->code = fmt->code;
+               ret = v4l2_subdev_call(dev->sensor, video,
+                                      s_mbus_fmt, mbus_fmt);
+               if (ret)
+                       vip_dbg(1, dev, "init_port s_mbus_fmt failed in subdev\n");
+       }
+
+       /* Assign current format */
+       port->fmt = fmt;
+
+       vip_dbg(3, dev, "vip_init_port: g_mbus_fmt subdev mbus_code: %04X fourcc:%s size: %dx%d\n",
+               fmt->code,
+               fourcc_to_str(fmt->fourcc),
+               mbus_fmt->width, mbus_fmt->height);
+
+       if (mbus_fmt->field == V4L2_FIELD_ALTERNATE)
+               port->flags |= FLAG_INTERLACED;
+       else
+               port->flags &= ~FLAG_INTERLACED;
+
+       port->c_rect.left       = 0;
+       port->c_rect.top        = 0;
+       port->c_rect.width      = mbus_fmt->width;
+       port->c_rect.height     = mbus_fmt->height;
+
+done:
+       port->num_streams++;
+       return 0;
+}
+
+static int vip_init_stream(struct vip_stream *stream)
+{
+       struct vip_port *port = stream->port;
+       struct vip_dev *dev = port->dev;
+       struct vip_fmt *fmt;
+       struct v4l2_mbus_framefmt *mbus_fmt;
+       struct v4l2_format f;
+       int ret;
+
+       ret = vip_init_port(port);
+       if (ret != 0)
+               return ret;
+
+       fmt = port->fmt;
+       mbus_fmt = &port->mbus_framefmt;
+
+       /* Properly calculate the sizeimage and bytesperline values. */
+       v4l2_fill_pix_format(&f.fmt.pix, mbus_fmt);
+       f.fmt.pix.pixelformat = fmt->fourcc;
+       ret = vip_calc_format_size(port, fmt, &f);
+       if (ret)
+               return ret;
+
+       stream->width = f.fmt.pix.width;
+       stream->height = f.fmt.pix.height;
+       stream->sup_field = f.fmt.pix.field;
+       stream->bytesperline = f.fmt.pix.bytesperline;
+       stream->sizeimage = f.fmt.pix.sizeimage;
+
+       vip_dbg(3, dev, "init_stream fourcc:%s size: %dx%d bpl:%d img_size:%d\n",
+               fourcc_to_str(f.fmt.pix.pixelformat),
+               f.fmt.pix.width, f.fmt.pix.height,
+               f.fmt.pix.bytesperline, f.fmt.pix.sizeimage);
+       vip_dbg(3, dev, "init_stream vpdma data type: 0x%02X\n",
+               port->fmt->vpdma_fmt[0]->data_type);
+
+       ret = vpdma_create_desc_list(&stream->desc_list, VIP_DESC_LIST_SIZE,
                        VPDMA_LIST_TYPE_NORMAL);
 
        if (ret != 0)
                return ret;
 
-       dev->write_desc = (struct vpdma_dtd *)dev->desc_list.buf.addr
+       stream->write_desc = (struct vpdma_dtd *)stream->desc_list.buf.addr
                                + 15;
-       vip_set_clock_enable(dev, 1);
-done:
-       dev->num_ports++;
-
        return 0;
 }
 
 static void vip_release_dev(struct vip_dev *dev)
 {
-       vpdma_unmap_desc_buf(dev->shared->vpdma, &dev->desc_list.buf);
-       vpdma_free_desc_buf(&dev->desc_list.buf);
-       vpdma_free_desc_list(&dev->desc_list);
-
        /*
         * On last close, disable clocks to conserve power
         */
@@ -2054,9 +2140,10 @@ static int vip_setup_parser(struct vip_port *port)
        struct vip_dev *dev = port->dev;
        struct v4l2_of_endpoint *endpoint = dev->endpoint;
        int iface = DUAL_8B_INTERFACE;
-       int sync_type;
+       int sync_type, pclk_type;
        unsigned int flags;
 
+       flags = endpoint->bus.parallel.flags;
        vip_reset_port(port);
        vip_set_port_enable(port, 1);
 
@@ -2077,7 +2164,8 @@ static int vip_setup_parser(struct vip_port *port)
                        break;
                        case 1:
                        default:
-                               sync_type = EMBEDDED_SYNC_SINGLE_YUV422;
+                               sync_type =
+                               EMBEDDED_SYNC_LINE_MULTIPLEXED_YUV422;
                        }
                }
 
@@ -2099,7 +2187,6 @@ static int vip_setup_parser(struct vip_port *port)
                else
                        sync_type = DISCRETE_SYNC_SINGLE_YUV422;
 
-               flags = endpoint->bus.parallel.flags;
                if (flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH |
                        V4L2_MBUS_HSYNC_ACTIVE_LOW))
                        vip_set_vsync_polarity(port,
@@ -2110,11 +2197,6 @@ static int vip_setup_parser(struct vip_port *port)
                        vip_set_hsync_polarity(port,
                                flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH ? 1 : 0);
 
-               if (flags & (V4L2_MBUS_PCLK_SAMPLE_RISING |
-                       V4L2_MBUS_PCLK_SAMPLE_FALLING))
-                       vip_set_pclk_polarity(port,
-                               flags & V4L2_MBUS_PCLK_SAMPLE_RISING ? 1 : 0);
-
                vip_xtra_set_repack_sel(port, 0);
                vip_set_actvid_hsync_n(port, 0);
                vip_set_actvid_polarity(port, 1);
@@ -2125,57 +2207,44 @@ static int vip_setup_parser(struct vip_port *port)
                return -EINVAL;
        }
 
+       pclk_type = flags & V4L2_MBUS_PCLK_SAMPLE_RISING ? 0 : 1;
+       vip_set_pclk_polarity(port, pclk_type);
        vip_set_data_interface(port, iface);
        vip_sync_type(port, sync_type);
        return 0;
 }
 
-static int vip_init_port(struct vip_port *port)
+static void vip_release_stream(struct vip_stream *stream)
 {
-       int ret;
-
-       if (port->num_streams != 0)
-               goto done;
-
-       ret = vip_init_dev(port->dev);
-       if (ret)
-               goto done;
-
-       port->fmt = port->dev->active_fmt[0];
-       port->src_colorspace = port->fmt->colorspace;
-       port->c_rect.left = 0;
-       port->c_rect.top = 0;
+       struct vip_dev *dev = stream->port->dev;
 
-done:
-       port->num_streams++;
-       return 0;
+       vpdma_unmap_desc_buf(dev->shared->vpdma, &stream->desc_list.buf);
+       vpdma_free_desc_buf(&stream->desc_list.buf);
+       vpdma_free_desc_list(&stream->desc_list);
 }
 
-static void vip_release_port(struct vip_port *port)
+static void stop_dma(struct vip_stream *stream)
 {
-       struct vip_dev *dev = port->dev;
+       struct vip_dev *dev = stream->port->dev;
        int ch, size = 0;
 
        /* Create a list of channels to be cleared */
        for (ch = 0; ch < VPDMA_MAX_CHANNELS; ch++) {
-               if (dev->vpdma_channels[ch] == 1) {
-                       dev->vpdma_channels[size++] = ch;
+               if (stream->vpdma_channels[ch] == 1) {
+                       stream->vpdma_channels[size++] = ch;
                        vip_dbg(2, dev, "Clear channel no: %d\n", ch);
                }
        }
 
        /* Clear all the used channels for the list */
-       vpdma_list_cleanup(dev->shared->vpdma, dev->slice_id,
-               dev->vpdma_channels, size);
+       vpdma_list_cleanup(dev->shared->vpdma, stream->list_num,
+               stream->vpdma_channels, size);
 
        for (ch = 0; ch < VPDMA_MAX_CHANNELS; ch++)
-               dev->vpdma_channels[ch] = 0;
-
-       if (--port->num_streams == 0)
-               vip_release_dev(port->dev);
+               stream->vpdma_channels[ch] = 0;
 }
 
-int vip_open(struct file *file)
+static int vip_open(struct file *file)
 {
        struct vip_stream *stream = video_drvdata(file);
        struct vip_port *port = stream->port;
@@ -2199,22 +2268,10 @@ int vip_open(struct file *file)
         * Then initialize hw module.
         */
        if (v4l2_fh_is_singular_file(file)) {
-               if (vip_init_port(port)) {
-                       goto free_fh;
+               if (vip_init_stream(stream)) {
                        ret = -ENODEV;
+                       goto free_fh;
                }
-               stream->width = 1280;
-               stream->height = 720;
-               stream->sizeimage = stream->width * stream->height *
-                       (port->fmt->vpdma_fmt[0]->depth +
-                       (port->fmt->coplanar ?
-                               port->fmt->vpdma_fmt[1]->depth : 0)) >> 3;
-               stream->bytesperline = round_up((stream->width *
-                                       port->fmt->vpdma_fmt[0]->depth) >> 3,
-                                       1 << L_ALIGN);
-               stream->sup_field = V4L2_FIELD_NONE;
-               port->c_rect.width = stream->width;
-               port->c_rect.height = stream->height;
                vip_dbg(1, dev, "Created stream instance %p\n", stream);
        }
 
@@ -2230,9 +2287,8 @@ free_fh:
        }
        return ret;
 }
-EXPORT_SYMBOL(vip_open);
 
-int vip_release(struct file *file)
+static int vip_release(struct file *file)
 {
        struct vip_stream *stream = video_drvdata(file);
        struct vip_port *port = stream->port;
@@ -2249,7 +2305,10 @@ int vip_release(struct file *file)
                mutex_lock(&dev->mutex);
 
                vip_stop_streaming(q);
-               vip_release_port(stream->port);
+               vip_release_stream(stream);
+
+               if (--port->num_streams == 0)
+                       vip_release_dev(port->dev);
 
                mutex_unlock(&dev->mutex);
                vip_dbg(1, dev, "Releasing stream instance %p\n", stream);
@@ -2257,12 +2316,12 @@ int vip_release(struct file *file)
 
        return vb2_fop_release(file);
 }
-EXPORT_SYMBOL(vip_release);
 
 static const struct v4l2_file_operations vip_fops = {
        .owner          = THIS_MODULE,
        .open           = vip_open,
        .release        = vip_release,
+       .read           = vb2_fop_read,
        .poll           = vb2_fop_poll,
        .unlocked_ioctl = video_ioctl2,
        .mmap           = vb2_fop_mmap,
@@ -2274,6 +2333,7 @@ static struct video_device vip_videodev = {
        .ioctl_ops      = &vip_ioctl_ops,
        .minor          = -1,
        .release        = video_device_release,
+       .tvnorms        = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
 };
 
 static int alloc_stream(struct vip_port *port, int stream_id, int vfl_type)
@@ -2293,6 +2353,15 @@ static int alloc_stream(struct vip_port *port, int stream_id, int vfl_type)
        stream->stream_id = stream_id;
        stream->vfl_type = vfl_type;
 
+       stream->list_num = vpdma_hwlist_alloc(dev->shared->vpdma, stream);
+       if (stream->list_num < 0) {
+               vip_err(dev, "Could not get VPDMA hwlist");
+               ret = -ENODEV;
+               goto do_free_stream;
+       }
+
+       INIT_LIST_HEAD(&stream->post_bufs);
+
        if (vfl_type == VFL_TYPE_GRABBER)
                port->cap_streams[stream_id] = stream;
        else
@@ -2303,7 +2372,7 @@ static int alloc_stream(struct vip_port *port, int stream_id, int vfl_type)
         */
        q = &stream->vb_vidq;
        q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       q->io_modes = VB2_MMAP | VB2_DMABUF;
+       q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
        q->drv_priv = stream;
        q->buf_struct_size = sizeof(struct vip_buffer);
        q->ops = &vip_video_qops;
@@ -2380,9 +2449,53 @@ static void free_stream(struct vip_stream *stream)
 
        video_unregister_device(stream->vfd);
        video_device_release(stream->vfd);
+       vpdma_hwlist_release(dev->shared->vpdma, stream->list_num);
        kfree(stream);
 }
 
+static int get_subdev_active_format(struct vip_port *port,
+                                   struct v4l2_subdev *subdev)
+{
+       struct vip_dev *dev = port->dev;
+       struct vip_fmt *fmt;
+       enum v4l2_mbus_pixelcode code;
+       int ret = 0;
+       unsigned int k, i, j;
+
+       /* Enumerate sub device formats and enable all matching local formats */
+       dev->num_active_fmt = 0;
+       for (k = 0, i = 0;
+            (ret != -EINVAL);
+            k++) {
+               ret = v4l2_subdev_call(subdev, video, enum_mbus_fmt, k, &code);
+               if (ret == 0) {
+                       vip_dbg(2, dev,
+                               "subdev %s: code: %04x idx: %d\n",
+                               subdev->name, code, k);
+
+                       for (j = 0; j < ARRAY_SIZE(vip_formats); j++) {
+                               fmt = &vip_formats[j];
+                               if (code == fmt->code) {
+                                       dev->active_fmt[i] = fmt;
+                                       dev->num_active_fmt = i++;
+                                       vip_dbg(2, dev,
+                                               "matched fourcc: %s: code: %04x idx: %d\n",
+                                               fourcc_to_str(fmt->fourcc),
+                                               fmt->code,
+                                               dev->num_active_fmt);
+                               }
+                       }
+               }
+       }
+
+       if (i == 0) {
+               vip_err(dev, "No suitable format reported by subdev %s\n",
+                       subdev->name);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 static int alloc_port(struct vip_dev *dev, int id)
 {
        struct vip_port *port;
@@ -2396,10 +2509,18 @@ static int alloc_port(struct vip_dev *dev, int id)
        port->dev = dev;
        port->port_id = id;
        port->num_streams = 0;
+       port->flags |= FLAG_MULT_PORT;
 
        ret = alloc_stream(port, 0, VFL_TYPE_GRABBER);
 
-       return 0;
+       if (dev->endpoint->bus_type == V4L2_MBUS_BT656) {
+               /* Allocate streams for 4 channels */
+               ret = alloc_stream(port, 2, VFL_TYPE_GRABBER);
+               ret = alloc_stream(port, 4, VFL_TYPE_GRABBER);
+               ret = alloc_stream(port, 6, VFL_TYPE_GRABBER);
+       }
+
+       return get_subdev_active_format(port, dev->sensor);
 }
 
 static void free_port(struct vip_port *port)
@@ -2461,38 +2582,6 @@ static int vip_runtime_get(struct platform_device *pdev)
        return r < 0 ? r : 0;
 }
 
-static int get_subdev_active_format(struct vip_dev *dev,
-                                   struct v4l2_subdev *subdev)
-{
-       struct vip_fmt *fmt;
-       enum v4l2_mbus_pixelcode code;
-       int ret = 0;
-       unsigned int k;
-
-       /* first find how many formats to allocate the correct size */
-       dev->num_active_fmt = 0;
-       for (k = 0;
-            (ret != -EINVAL) && (dev->num_active_fmt < VIP_MAX_ACTIVE_FMT);
-            k++) {
-               ret = v4l2_subdev_call(subdev, video, enum_mbus_fmt, k, &code);
-               if (ret == 0) {
-                       fmt = find_format_by_code(code);
-                       if (fmt) {
-                               dev->active_fmt[dev->num_active_fmt] = fmt;
-                               dev->num_active_fmt++;
-                       }
-               }
-       }
-
-       if (dev->num_active_fmt == 0) {
-
-               vip_err(dev, "No suitable format reported by subdev %s\n",
-                       subdev->name);
-               return -EINVAL;
-       }
-
-       return 0;
-}
 
 static int vip_async_bound(struct v4l2_async_notifier *notifier,
                        struct v4l2_subdev *subdev,
@@ -2500,33 +2589,33 @@ static int vip_async_bound(struct v4l2_async_notifier *notifier,
 {
        struct vip_dev *dev = notifier_to_vip_dev(notifier);
        unsigned int idx = asd - &dev->config->asd[0];
+       int ret;
 
        vip_dbg(1, dev, "vip_async_bound\n");
        if (idx > dev->config->asd_sizes)
                return -EINVAL;
 
-       if (get_subdev_active_format(dev, subdev))
-               return 0;
-
        if (dev->sensor) {
                if (asd < dev->sensor->asd) {
                        /* Notified of a subdev earlier in the array */
+                       dev->sensor = subdev;
+                       dev->endpoint = &dev->config->endpoints[idx];
                        vip_info(dev, "Switching to subdev %s (High priority)",
                                 subdev->name);
-               } else {
+
+               } else
                        vip_info(dev, "Rejecting subdev %s (Low priority)",
                                 subdev->name);
-                       return 0;
-               }
-       } else
-               alloc_port(dev, 0);
+               return 0;
+       }
 
        dev->sensor = subdev;
        dev->endpoint = &dev->config->endpoints[idx];
-       vip_info(dev, "Using sensor %s for capture\n",
-                subdev->name);
+       ret = alloc_port(dev, 0);
+       if (!ret)
+               vip_info(dev, "Using sensor %s for capture\n", subdev->name);
 
-       return 0;
+       return ret;
 }
 
 static int vip_async_complete(struct v4l2_async_notifier *notifier)
@@ -2792,12 +2881,6 @@ static int vip_probe(struct platform_device *pdev)
        vip_shared_set_clock_enable(shared, 1);
        vip_top_vpdma_reset(shared);
 
-       shared->vpdma = vpdma_create(pdev, vip_vpdma_fw_cb);
-       if (!shared->vpdma) {
-               dev_err(&pdev->dev, "Creating VPDMA failed");
-               goto do_iounmap;
-       }
-
        list_add_tail(&shared->list, &vip_shared_list);
        platform_set_drvdata(pdev, shared);
        atomic_set(&shared->devs_allocated, 0);
@@ -2810,6 +2893,10 @@ static int vip_probe(struct platform_device *pdev)
                if (!dev)
                        return -ENOMEM;
 
+               dev->instance_id = (int)of_dev_id->data;
+               snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
+                       "%s%d-s%d", VIP_MODULE_NAME, dev->instance_id, slice);
+
                dev->irq = platform_get_irq(pdev, slice);
                if (!dev->irq) {
                        dev_err(&pdev->dev, "Could not get IRQ");
@@ -2817,7 +2904,7 @@ static int vip_probe(struct platform_device *pdev)
                }
 
                if (devm_request_irq(&pdev->dev, dev->irq, vip_irq,
-                                    0, VIP_MODULE_NAME, dev) < 0) {
+                                    0, dev->v4l2_dev.name, dev) < 0) {
                        ret = -ENOMEM;
                        goto dev_unreg;
                }
@@ -2825,12 +2912,6 @@ static int vip_probe(struct platform_device *pdev)
                spin_lock_init(&dev->slock);
                spin_lock_init(&dev->lock);
 
-               INIT_LIST_HEAD(&dev->vip_bufs);
-
-               dev->instance_id = (int)of_dev_id->data;
-
-               snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
-                       "%s%d-%d", VIP_MODULE_NAME, dev->instance_id, slice);
                ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
                if (ret)
                        goto err_runtime_get;
@@ -2862,6 +2943,13 @@ static int vip_probe(struct platform_device *pdev)
                vip_set_slice_path(dev, VIP_MULTI_CHANNEL_DATA_SELECT);
        }
 
+       shared->vpdma = &shared->vpdma_data;
+       ret = vpdma_create(pdev, shared->vpdma, vip_vpdma_fw_cb);
+       if (ret) {
+               dev_err(&pdev->dev, "Creating VPDMA failed");
+               goto dev_unreg;
+       }
+
        return 0;
 
 dev_unreg:
@@ -2917,6 +3005,7 @@ static const struct of_device_id vip_of_match[] = {
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, vip_of_match);
 #else
 #define vip_of_match NULL
 #endif
index 6abb864b06fd23f759d1d9487d7b6d38261ddb5d..e3c142df72404e6caa3c50c9d51d94ef83410114 100644 (file)
 #define VIP_VBI_STREAMS_PER_PORT       16
 
 #define VIP_MAX_SUBDEV                 5
+/*
+ * This value needs to be at least as large as the number of entry in
+ * vip_formats[].
+ * When vip_formats[] is modified make sure to adjust this value also.
+ */
 #define VIP_MAX_ACTIVE_FMT             10
 
 /* buffer for one video frame */
@@ -90,6 +95,7 @@ struct vip_shared {
        struct resource         *res;
        void __iomem            *base;
        atomic_t                devs_allocated; /* count of devs being shared */
+       struct vpdma_data       vpdma_data;
        struct vpdma_data       *vpdma;
        struct vip_dev          *devs[VIP_NUM_SLICES];
 };
@@ -131,12 +137,6 @@ struct vip_dev {
        int                     num_skip_irq;
        void __iomem            *base;
 
-       struct vpdma_desc_list  desc_list;      /* DMA descriptor list */
-       struct vpdma_dtd        *write_desc;
-       void                    *desc_next;     /* next unused desc_list addr */
-       /* Maintain a list of used channels - Needed for VPDMA cleanup */
-       int                     vpdma_channels[VPDMA_MAX_CHANNELS];
-       struct list_head        vip_bufs;       /* vip_bufs to be DMAed */
        struct vb2_alloc_ctx    *alloc_ctx;
        struct vip_port         *ports[VIP_NUM_PORTS];
 
@@ -156,7 +156,9 @@ struct vip_port {
        unsigned int            src_width;
        unsigned int            src_height;
        struct v4l2_rect        c_rect;         /* crop rectangle */
-       struct vip_fmt          *fmt;           /* format info */
+       struct v4l2_mbus_framefmt mbus_framefmt;
+
+       struct vip_fmt          *fmt;           /* current format info */
        int                     num_streams;    /* count of open streams */
        struct vip_stream       *cap_streams[VIP_CAP_STREAMS_PER_PORT];
        struct vip_stream       *vbi_streams[VIP_VBI_STREAMS_PER_PORT];
@@ -170,6 +172,7 @@ struct vip_stream {
        struct video_device     *vfd;
        struct vip_port         *port;
        int                     stream_id;
+       int                     list_num;
        int                     vfl_type;
        enum v4l2_field         field;          /* current field */
        unsigned int            sequence;       /* current frame/field seq */
@@ -180,16 +183,16 @@ struct vip_stream {
        unsigned int            sizeimage;      /* image size in memory */
        struct list_head        vidq;           /* incoming vip_bufs queue */
        struct list_head        dropq;          /* drop vip_bufs queue */
+       struct list_head        post_bufs;      /* vip_bufs to be DMAed */
+       /* Maintain a list of used channels - Needed for VPDMA cleanup */
+       int                     vpdma_channels[VPDMA_MAX_CHANNELS];
+       struct vpdma_desc_list  desc_list;      /* DMA descriptor list */
+       struct vpdma_dtd        *write_desc;
+       void                    *desc_next;     /* next unused desc_list addr */
        struct vb2_queue        vb_vidq;
        struct video_device     vdev;
-       int                     open;
 };
 
-extern int vip_open(struct file *file);
-extern int vip_release(struct file *file);
-extern int vip_s_fmt_vid_cap(struct file *file, void *priv,
-                            struct v4l2_format *f);
-
 /*
  * VIP Enumerations
  */
index 94947a65b752ef8d1c8b60ef76c23eb1104d2ad8..155ecf5e03e7ba46f1d50d0d526eccd458d2283e 100644 (file)
@@ -59,9 +59,9 @@ const struct vpdma_data_format vpdma_yuv_fmts[] = {
                .data_type      = DATA_TYPE_C420,
                .depth          = 4,
        },
-       [VPDMA_DATA_FMT_YC422] = {
+       [VPDMA_DATA_FMT_YCR422] = {
                .type           = VPDMA_DATA_FMT_TYPE_YUV,
-               .data_type      = DATA_TYPE_YC422,
+               .data_type      = DATA_TYPE_YCR422,
                .depth          = 16,
        },
        [VPDMA_DATA_FMT_YC444] = {
@@ -69,9 +69,19 @@ const struct vpdma_data_format vpdma_yuv_fmts[] = {
                .data_type      = DATA_TYPE_YC444,
                .depth          = 24,
        },
-       [VPDMA_DATA_FMT_CY422] = {
+       [VPDMA_DATA_FMT_CRY422] = {
                .type           = VPDMA_DATA_FMT_TYPE_YUV,
-               .data_type      = DATA_TYPE_CY422,
+               .data_type      = DATA_TYPE_CRY422,
+               .depth          = 16,
+       },
+       [VPDMA_DATA_FMT_CBY422] = {
+               .type           = VPDMA_DATA_FMT_TYPE_YUV,
+               .data_type      = DATA_TYPE_CBY422,
+               .depth          = 16,
+       },
+       [VPDMA_DATA_FMT_YCB422] = {
+               .type           = VPDMA_DATA_FMT_TYPE_YUV,
+               .data_type      = DATA_TYPE_YCB422,
                .depth          = 16,
        },
 };
@@ -516,12 +526,13 @@ static void dump_dtd(struct vpdma_dtd *dtd);
 
 void vpdma_update_dma_addr(struct vpdma_data *vpdma,
        struct vpdma_desc_list *list, dma_addr_t dma_addr,
-       void *write_dtd, int drop)
+       void *write_dtd, int drop, int idx)
 {
        struct vpdma_dtd *dtd = list->buf.addr;
        dma_addr_t write_desc_addr;
        int offset;
 
+       dtd += idx;
        vpdma_unmap_desc_buf(vpdma, &list->buf);
 
        dtd->start_addr = dma_addr;
@@ -903,6 +914,50 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width,
 }
 EXPORT_SYMBOL(vpdma_add_in_dtd);
 
+int vpdma_hwlist_alloc(struct vpdma_data *vpdma, void *priv)
+{
+       int i, list_num = -1;
+       unsigned long flags;
+
+       spin_lock_irqsave(&vpdma->lock, flags);
+       for (i = 0; i < VPDMA_MAX_NUM_LIST &&
+           vpdma->hwlist_used[i] == true; i++)
+               ;
+
+       if (i < VPDMA_MAX_NUM_LIST) {
+               list_num = i;
+               vpdma->hwlist_used[i] = true;
+               vpdma->hwlist_priv[i] = priv;
+       }
+       spin_unlock_irqrestore(&vpdma->lock, flags);
+
+       return list_num;
+}
+EXPORT_SYMBOL(vpdma_hwlist_alloc);
+
+void *vpdma_hwlist_get_priv(struct vpdma_data *vpdma, int list_num)
+{
+       if (!vpdma || list_num >= VPDMA_MAX_NUM_LIST)
+               return NULL;
+
+       return vpdma->hwlist_priv[list_num];
+}
+EXPORT_SYMBOL(vpdma_hwlist_get_priv);
+
+void *vpdma_hwlist_release(struct vpdma_data *vpdma, int list_num)
+{
+       void *priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&vpdma->lock, flags);
+       vpdma->hwlist_used[list_num] = false;
+       priv = vpdma->hwlist_priv;
+       spin_unlock_irqrestore(&vpdma->lock, flags);
+
+       return priv;
+}
+EXPORT_SYMBOL(vpdma_hwlist_release);
+
 /* set or clear the mask for list complete interrupt */
 void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int irq_num,
                int list_num, bool enable)
@@ -1074,21 +1129,14 @@ static int vpdma_load_firmware(struct vpdma_data *vpdma)
        return 0;
 }
 
-struct vpdma_data *vpdma_create(struct platform_device *pdev,
+int vpdma_create(struct platform_device *pdev, struct vpdma_data *vpdma,
                void (*cb)(struct platform_device *pdev))
 {
        struct resource *res;
-       struct vpdma_data *vpdma;
        int r;
 
        dev_dbg(&pdev->dev, "vpdma_create\n");
 
-       vpdma = devm_kzalloc(&pdev->dev, sizeof(*vpdma), GFP_KERNEL);
-       if (!vpdma) {
-               dev_err(&pdev->dev, "couldn't alloc vpdma_dev\n");
-               return ERR_PTR(-ENOMEM);
-       }
-
        vpdma->pdev = pdev;
        vpdma->cb = cb;
        spin_lock_init(&vpdma->lock);
@@ -1096,22 +1144,22 @@ struct vpdma_data *vpdma_create(struct platform_device *pdev,
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpdma");
        if (res == NULL) {
                dev_err(&pdev->dev, "missing platform resources data\n");
-               return ERR_PTR(-ENODEV);
+               return -ENODEV;
        }
 
        vpdma->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (!vpdma->base) {
                dev_err(&pdev->dev, "failed to ioremap\n");
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
        }
 
        r = vpdma_load_firmware(vpdma);
        if (r) {
                pr_err("failed to load firmware %s\n", VPDMA_FIRMWARE);
-               return ERR_PTR(r);
+               return r;
        }
 
-       return vpdma;
+       return 0;
 }
 EXPORT_SYMBOL(vpdma_create);
 
index c448c8a71b390742907919546cfb0a375d3b1425..0df156b7c1cf9c287dc2644422676e6d7161b0a7 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef __TI_VPDMA_H_
 #define __TI_VPDMA_H_
 
+#define VPDMA_MAX_NUM_LIST             8
 /*
  * A vpdma_buf tracks the size, DMA address and mapping status of each
  * driver DMA area.
@@ -36,6 +37,8 @@ struct vpdma_data {
        struct platform_device  *pdev;
 
        spinlock_t              lock;
+       bool                    hwlist_used[VPDMA_MAX_NUM_LIST];
+       void                    *hwlist_priv[VPDMA_MAX_NUM_LIST];
        /* callback to VPE driver when the firmware is loaded */
        void (*cb)(struct platform_device *pdev);
 };
@@ -71,9 +74,11 @@ enum vpdma_yuv_formats {
        VPDMA_DATA_FMT_C444,
        VPDMA_DATA_FMT_C422,
        VPDMA_DATA_FMT_C420,
-       VPDMA_DATA_FMT_YC422,
+       VPDMA_DATA_FMT_YCR422,
        VPDMA_DATA_FMT_YC444,
-       VPDMA_DATA_FMT_CY422,
+       VPDMA_DATA_FMT_CRY422,
+       VPDMA_DATA_FMT_CBY422,
+       VPDMA_DATA_FMT_YCB422,
 };
 
 enum vpdma_rgb_formats {
@@ -214,7 +219,13 @@ int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list,
 bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num);
 void vpdma_update_dma_addr(struct vpdma_data *vpdma,
        struct vpdma_desc_list *list, dma_addr_t dma_addr,
-       void *write_dtd, int drop);
+       void *write_dtd, int drop, int idx);
+
+/* VPDMA hardware list funcs */
+int vpdma_hwlist_alloc(struct vpdma_data *vpdma, void *priv);
+void *vpdma_hwlist_get_priv(struct vpdma_data *vpdma, int list_num);
+void *vpdma_hwlist_release(struct vpdma_data *vpdma, int list_num);
+
 /* helpers for creating vpdma descriptors */
 void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client,
                struct vpdma_buf *blk, u32 dest_offset);
@@ -262,7 +273,7 @@ void vpdma_set_bg_color(struct vpdma_data *vpdma,
 void vpdma_dump_regs(struct vpdma_data *vpdma);
 
 /* initialize vpdma, passed with VPE's platform device pointer */
-struct vpdma_data *vpdma_create(struct platform_device *pdev,
+int vpdma_create(struct platform_device *pdev, struct vpdma_data *vpdma,
                void (*cb)(struct platform_device *pdev));
 
 #endif
index 269051a68618f1957fc2939623e5fdc68d2dd520..ad25e566d166a756c2cc0660ccc6947afb3a1483 100644 (file)
 #define VPDMA_LIST_TYPE_SHFT           16
 #define VPDMA_LIST_SIZE_MASK           0xffff
 
-/* VPDMA data type values for data formats */
+/*
+ * The YUV data type definition below are taken from
+ * both the TRM and i839 Errata information.
+ * Use the correct data type considering byte
+ * reordering of components.
+ *
+ * Also since the single use of "C" in the 422 case
+ * to mean "Cr" (i.e. V component). It was decided
+ * to explictly label them CR to remove any confusion.
+ * Bear in mind that the type label refer to the memory
+ * packed order (LSB - MSB).
+ */
 #define DATA_TYPE_Y444                         0x0
 #define DATA_TYPE_Y422                         0x1
 #define DATA_TYPE_Y420                         0x2
 #define DATA_TYPE_C444                         0x4
 #define DATA_TYPE_C422                         0x5
 #define DATA_TYPE_C420                         0x6
-#define DATA_TYPE_YC422                                0x7
 #define DATA_TYPE_YC444                                0x8
-#define DATA_TYPE_CY422                                0x27
-
-#define DATA_TYPE_RGB16_565                    0x0
-#define DATA_TYPE_ARGB_1555                    0x1
-#define DATA_TYPE_ARGB_4444                    0x2
-#define DATA_TYPE_RGBA_5551                    0x3
-#define DATA_TYPE_RGBA_4444                    0x4
-#define DATA_TYPE_ARGB24_6666                  0x5
-#define DATA_TYPE_RGB24_888                    0x6
-#define DATA_TYPE_ARGB32_8888                  0x7
-#define DATA_TYPE_RGBA24_6666                  0x8
-#define DATA_TYPE_RGBA32_8888                  0x9
-#define DATA_TYPE_BGR16_565                    0x10
-#define DATA_TYPE_ABGR_1555                    0x11
-#define DATA_TYPE_ABGR_4444                    0x12
-#define DATA_TYPE_BGRA_5551                    0x13
-#define DATA_TYPE_BGRA_4444                    0x14
-#define DATA_TYPE_ABGR24_6666                  0x15
-#define DATA_TYPE_BGR24_888                    0x16
-#define DATA_TYPE_ABGR32_8888                  0x17
-#define DATA_TYPE_BGRA24_6666                  0x18
-#define DATA_TYPE_BGRA32_8888                  0x19
+#define DATA_TYPE_YCB422                       0x7
+#define DATA_TYPE_YCR422                       0x17
+#define DATA_TYPE_CBY422                       0x27
+#define DATA_TYPE_CRY422                       0x37
+
+/*
+ * The RGB data type definition below are defined
+ * to follow Errata i839.
+ * The initial values were taken from both the TRM and
+ * the i839 Errata information.
+ * But some of the ARGB definition appeared to be wrong
+ * as they would yield RGBA instead.
+ * They have been corrected based on experimentation.
+ */
+#define DATA_TYPE_RGB16_565                    0x10
+#define DATA_TYPE_ARGB_1555                    0x13
+#define DATA_TYPE_ARGB_4444                    0x14
+#define DATA_TYPE_RGBA_5551                    0x11
+#define DATA_TYPE_RGBA_4444                    0x12
+#define DATA_TYPE_ARGB24_6666                  0x18
+#define DATA_TYPE_RGB24_888                    0x16
+#define DATA_TYPE_ARGB32_8888                  0x17
+#define DATA_TYPE_RGBA24_6666                  0x15
+#define DATA_TYPE_RGBA32_8888                  0x19
+#define DATA_TYPE_BGR16_565                    0x0
+#define DATA_TYPE_ABGR_1555                    0x3
+#define DATA_TYPE_ABGR_4444                    0x4
+#define DATA_TYPE_BGRA_5551                    0x1
+#define DATA_TYPE_BGRA_4444                    0x2
+#define DATA_TYPE_ABGR24_6666                  0x8
+#define DATA_TYPE_BGR24_888                    0x6
+#define DATA_TYPE_ABGR32_8888                  0x7
+#define DATA_TYPE_BGRA24_6666                  0x5
+#define DATA_TYPE_BGRA32_8888                  0x9
 
 #define DATA_TYPE_MV                           0x3
 
 #define VIP1_CHAN_NUM_MULT_ANC_A_SRC0  70
 #define        VPE_CHAN_NUM_LUMA_OUT           102
 #define        VPE_CHAN_NUM_CHROMA_OUT         103
-#define VIP1_CHAN_NUM_PORT_B_LUMA      104
-#define VIP1_CHAN_NUM_PORT_B_CHROMA    105
+#define VIP1_CHAN_NUM_PORT_B_LUMA      102
+#define VIP1_CHAN_NUM_PORT_B_CHROMA    103
 #define        VPE_CHAN_NUM_RGB_OUT            106
 #define VIP1_CHAN_NUM_PORT_A_RGB       106
 #define VIP1_CHAN_NUM_PORT_B_RGB       107
index e96b556806bfb6cd1fbe609ef6ac781a0ab49a8c..dc82552d57e327ec5bb01c420f920b34398fe8b7 100644 (file)
@@ -234,7 +234,7 @@ struct vpe_fmt {
 
 static struct vpe_fmt vpe_formats[] = {
        {
-               .name           = "YUV 422 co-planar",
+               .name           = "NV16 YUV 422 co-planar",
                .fourcc         = V4L2_PIX_FMT_NV16,
                .types          = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
                .coplanar       = 1,
@@ -243,7 +243,7 @@ static struct vpe_fmt vpe_formats[] = {
                                  },
        },
        {
-               .name           = "YUV 420 co-planar",
+               .name           = "NV12 YUV 420 co-planar",
                .fourcc         = V4L2_PIX_FMT_NV12,
                .types          = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
                .coplanar       = 1,
@@ -256,7 +256,7 @@ static struct vpe_fmt vpe_formats[] = {
                .fourcc         = V4L2_PIX_FMT_YUYV,
                .types          = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
                .coplanar       = 0,
-               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YC422],
+               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YCB422],
                                  },
        },
        {
@@ -264,7 +264,7 @@ static struct vpe_fmt vpe_formats[] = {
                .fourcc         = V4L2_PIX_FMT_UYVY,
                .types          = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
                .coplanar       = 0,
-               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_CY422],
+               .vpdma_fmt      = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_CBY422],
                                  },
        },
        {
@@ -381,6 +381,7 @@ struct vpe_dev {
        struct resource         *res;
 
        struct vb2_alloc_ctx    *alloc_ctx;
+       struct vpdma_data       vpdma_data;
        struct vpdma_data       *vpdma;         /* vpdma data handle */
        struct sc_data          *sc;            /* scaler data handle */
        struct csc_data         *csc;           /* csc data handle */
@@ -2261,6 +2262,9 @@ static int vpe_release(struct file *file)
 
        vpe_dbg(dev, "releasing instance %p\n", ctx);
 
+       vpe_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+       vpe_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+
        mutex_lock(&dev->dev_mutex);
        free_vbs(ctx);
        free_mv_buffers(ctx);
@@ -2478,11 +2482,10 @@ static int vpe_probe(struct platform_device *pdev)
                goto runtime_put;
        }
 
-       dev->vpdma = vpdma_create(pdev, vpe_fw_cb);
-       if (IS_ERR(dev->vpdma)) {
-               ret = PTR_ERR(dev->vpdma);
+       dev->vpdma = &dev->vpdma_data;
+       ret = vpdma_create(pdev, dev->vpdma, vpe_fw_cb);
+       if (ret)
                goto runtime_put;
-       }
 
        return 0;
 
@@ -2525,6 +2528,7 @@ static const struct of_device_id vpe_of_match[] = {
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, vpe_of_match);
 #else
 #define vpe_of_match NULL
 #endif
index 37bc00f418f1db47272238d90830ed2a7ac1f872..7596537becf770656db11ce1612080089d38ccc8 100644 (file)
@@ -244,6 +244,11 @@ static int stk1160_stop_streaming(struct stk1160 *dev)
        if (mutex_lock_interruptible(&dev->v4l_lock))
                return -ERESTARTSYS;
 
+       /*
+        * Once URBs are cancelled, the URB complete handler
+        * won't be running. This is required to safely release the
+        * current buffer (dev->isoc_ctl.buf).
+        */
        stk1160_cancel_isoc(dev);
 
        /*
@@ -624,8 +629,16 @@ void stk1160_clear_queue(struct stk1160 *dev)
                stk1160_info("buffer [%p/%d] aborted\n",
                                buf, buf->vb.v4l2_buf.index);
        }
-       /* It's important to clear current buffer */
-       dev->isoc_ctl.buf = NULL;
+
+       /* It's important to release the current buffer */
+       if (dev->isoc_ctl.buf) {
+               buf = dev->isoc_ctl.buf;
+               dev->isoc_ctl.buf = NULL;
+
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               stk1160_info("buffer [%p/%d] aborted\n",
+                               buf, buf->vb.v4l2_buf.index);
+       }
        spin_unlock_irqrestore(&dev->buf_lock, flags);
 }
 
index 9e20cb91b505fdfd8ac9c2a0597de0d576c1b545..d22c3bdb8921951e4daefe340a95a99551f227a0 100644 (file)
 
 #include <media/v4l2-of.h>
 
-static void v4l2_of_parse_csi_bus(const struct device_node *node,
-                                 struct v4l2_of_endpoint *endpoint)
+static int v4l2_of_parse_csi_bus(const struct device_node *node,
+                                struct v4l2_of_endpoint *endpoint)
 {
        struct v4l2_of_bus_mipi_csi2 *bus = &endpoint->bus.mipi_csi2;
-       u32 data_lanes[ARRAY_SIZE(bus->data_lanes)];
        struct property *prop;
        bool have_clk_lane = false;
        unsigned int flags = 0;
@@ -32,16 +31,34 @@ static void v4l2_of_parse_csi_bus(const struct device_node *node,
        prop = of_find_property(node, "data-lanes", NULL);
        if (prop) {
                const __be32 *lane = NULL;
-               int i;
+               unsigned int i;
 
-               for (i = 0; i < ARRAY_SIZE(data_lanes); i++) {
-                       lane = of_prop_next_u32(prop, lane, &data_lanes[i]);
+               for (i = 0; i < ARRAY_SIZE(bus->data_lanes); i++) {
+                       lane = of_prop_next_u32(prop, lane, &v);
                        if (!lane)
                                break;
+                       bus->data_lanes[i] = v;
                }
                bus->num_data_lanes = i;
-               while (i--)
-                       bus->data_lanes[i] = data_lanes[i];
+       }
+
+       prop = of_find_property(node, "lane-polarities", NULL);
+       if (prop) {
+               const __be32 *polarity = NULL;
+               unsigned int i;
+
+               for (i = 0; i < ARRAY_SIZE(bus->lane_polarities); i++) {
+                       polarity = of_prop_next_u32(prop, polarity, &v);
+                       if (!polarity)
+                               break;
+                       bus->lane_polarities[i] = v;
+               }
+
+               if (i < 1 + bus->num_data_lanes /* clock + data */) {
+                       pr_warn("%s: too few lane-polarities entries (need %u, got %u)\n",
+                               node->full_name, 1 + bus->num_data_lanes, i);
+                       return -EINVAL;
+               }
        }
 
        if (!of_property_read_u32(node, "clock-lanes", &v)) {
@@ -56,6 +73,8 @@ static void v4l2_of_parse_csi_bus(const struct device_node *node,
 
        bus->flags = flags;
        endpoint->bus_type = V4L2_MBUS_CSI2;
+
+       return 0;
 }
 
 static void v4l2_of_parse_parallel_bus(const struct device_node *node,
@@ -130,11 +149,15 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node,
 int v4l2_of_parse_endpoint(const struct device_node *node,
                           struct v4l2_of_endpoint *endpoint)
 {
+       int rval;
+
        of_graph_parse_endpoint(node, &endpoint->base);
        endpoint->bus_type = 0;
        memset(&endpoint->bus, 0, sizeof(endpoint->bus));
 
-       v4l2_of_parse_csi_bus(node, endpoint);
+       rval = v4l2_of_parse_csi_bus(node, endpoint);
+       if (rval)
+               return rval;
        /*
         * Parse the parallel video bus properties only if none
         * of the MIPI CSI-2 specific properties were found.
index fc145d202c46907cf1ed40572068fcf3d21441c1..922a750640e8684f9ddda9ca7a20bec44832b5b3 100644 (file)
@@ -758,7 +758,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
 
                if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
                        if (msb->data_dir == READ) {
-                               for (cnt = 0; cnt < msb->current_seg; cnt++)
+                               for (cnt = 0; cnt < msb->current_seg; cnt++) {
                                        t_len += msb->req_sg[cnt].length
                                                 / msb->page_size;
 
@@ -766,6 +766,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
                                                t_len += msb->current_page - 1;
 
                                        t_len *= msb->page_size;
+                               }
                        }
                } else
                        t_len = blk_rq_bytes(msb->block_req);
index 38917a82233521768d3a1623046f68025de24295..2df3cbc968d173626b9db64695a0b64e71eadd5f 100644 (file)
@@ -629,7 +629,7 @@ static int __init kempld_init(void)
        if (force_device_id[0]) {
                for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++)
                        if (strstr(id->ident, force_device_id))
-                               if (id->callback && id->callback(id))
+                               if (id->callback && !id->callback(id))
                                        break;
                if (id->matches[0].slot == DMI_NONE)
                        return -ENODEV;
index 0d256cb002eb00480113435390fc19d5d92cb6cf..d290c746ea12a51d660862bb81eb7e58bac47568 100644 (file)
@@ -206,6 +206,7 @@ static int tps65218_probe(struct i2c_client *client,
        struct tps65218 *tps;
        const struct of_device_id *match;
        int ret;
+       unsigned int chipid;
 
        match = of_match_device(of_tps65218_match_table, &client->dev);
        if (!match) {
@@ -237,6 +238,15 @@ static int tps65218_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
+
+       ret = tps65218_reg_read(tps, TPS65218_REG_CHIPID, &chipid);
+       if (ret) {
+               dev_err(tps->dev, "Failed to read chipid: %d\n", ret);
+               return ret;
+       }
+
+       tps->rev = chipid & TPS65218_CHIPID_REV_MASK;
+
        ret = of_platform_populate(client->dev.of_node, NULL, NULL,
                                   &client->dev);
        if (ret < 0)
index cdd31c2a2a2bf095e827758e3d71567d80557a5f..b2965382d0ececa9cf92e6ca654d23cb90c28c1b 100644 (file)
@@ -275,6 +275,8 @@ void mei_stop(struct mei_device *dev)
 
        dev->dev_state = MEI_DEV_POWER_DOWN;
        mei_reset(dev);
+       /* move device to disabled state unconditionally */
+       dev->dev_state = MEI_DEV_DISABLED;
 
        mutex_unlock(&dev->device_lock);
 
index 3aed525e55b48bee7303715c55dea5f162f23752..7c19c5389d7ed674b0b2956ceca1aca815413cbf 100644 (file)
@@ -343,12 +343,26 @@ void st_int_recv(void *disc_data,
                        /* Unknow packet? */
                default:
                        type = *ptr;
-                       if (st_gdata->list[type] == NULL) {
-                               pr_err("chip/interface misbehavior dropping"
-                                       " frame starting with 0x%02x", type);
-                               goto done;
 
+                       /* Default case means non-HCILL packets,
+                        * possibilities are packets for:
+                        * (a) valid protocol -  Supported Protocols within
+                        *     the ST_MAX_CHANNELS.
+                        * (b) registered protocol - Checked by
+                        *     "st_gdata->list[type] == NULL)" are supported
+                        *     protocols only.
+                        *  Rules out any invalid protocol and
+                        *  unregistered protocols with channel ID < 16.
+                        */
+
+                       if ((type >= ST_MAX_CHANNELS) ||
+                                       (st_gdata->list[type] == NULL)) {
+                               pr_err("chip/interface misbehavior: "
+                                               "dropping frame starting "
+                                               "with 0x%02x\n", type);
+                               goto done;
                        }
+
                        st_gdata->rx_skb = alloc_skb(
                                        st_gdata->list[type]->max_frame_size,
                                        GFP_ATOMIC);
@@ -895,5 +909,3 @@ void st_core_exit(struct st_data_s *st_gdata)
                kfree(st_gdata);
        }
 }
-
-
index f6c8944abd971d4acc5839b0a6f3ea77f8dbfe28..1a3ba434abfe4eaba22b70f68c5b54501542d62f 100644 (file)
@@ -219,6 +219,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
 {
        unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0;
        const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 };
+       long timeout;
 
        pr_debug("%s", __func__);
 
@@ -228,10 +229,11 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
                return -EIO;
        }
 
-       if (!wait_for_completion_interruptible_timeout(
-               &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
-               pr_err(" waiting for ver info- timed out ");
-               return -ETIMEDOUT;
+       timeout = wait_for_completion_interruptible_timeout(
+               &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME));
+       if (timeout <= 0) {
+               pr_err(" waiting for ver info- timed out or received signal");
+               return timeout ? -ERESTARTSYS : -ETIMEDOUT;
        }
        reinit_completion(&kim_gdata->kim_rcvd);
        /* the positions 12 & 13 in the response buffer provide with the
@@ -394,13 +396,14 @@ static long download_firmware(struct kim_data_s *kim_gdata)
                        break;
                case ACTION_WAIT_EVENT:  /* wait */
                        pr_debug("W");
-                       if (!wait_for_completion_interruptible_timeout(
+                       err = wait_for_completion_interruptible_timeout(
                                        &kim_gdata->kim_rcvd,
-                                       msecs_to_jiffies(CMD_RESP_TIME))) {
-                               pr_err("response timeout during fw download ");
+                                       msecs_to_jiffies(CMD_RESP_TIME));
+                       if (err <= 0) {
+                               pr_err("response timeout/signaled during fw download ");
                                /* timed out */
                                release_firmware(kim_gdata->fw_entry);
-                               return -ETIMEDOUT;
+                               return err ? -ERESTARTSYS : -ETIMEDOUT;
                        }
                        reinit_completion(&kim_gdata->kim_rcvd);
                        break;
index df72c478c5a2b9fc482b980dac455b77a83e4f34..b1e21fc869c319c401f0f570761fe11565f88d53 100644 (file)
@@ -951,6 +951,18 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
        md->reset_done &= ~type;
 }
 
+int mmc_access_rpmb(struct mmc_queue *mq)
+{
+       struct mmc_blk_data *md = mq->data;
+       /*
+        * If this is a RPMB partition access, return ture
+        */
+       if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
+               return true;
+
+       return false;
+}
+
 static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
 {
        struct mmc_blk_data *md = mq->data;
index 3e049c13429cfbe730179724053796cc65ba62de..6ceede0a0bf798c6947d89a7a4993c3490465550 100644 (file)
@@ -38,7 +38,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
                return BLKPREP_KILL;
        }
 
-       if (mq && mmc_card_removed(mq->card))
+       if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
                return BLKPREP_KILL;
 
        req->cmd_flags |= REQ_DONTPREP;
index 5752d50049a34c2a9ee8f6585105990f1e018d05..99e6521e61696202c036dfb00fe6bdcd96c0f613 100644 (file)
@@ -73,4 +73,6 @@ extern void mmc_queue_bounce_post(struct mmc_queue_req *);
 extern int mmc_packed_init(struct mmc_queue *, struct mmc_card *);
 extern void mmc_packed_clean(struct mmc_queue *);
 
+extern int mmc_access_rpmb(struct mmc_queue *);
+
 #endif
index 7da9e4cc9993f3b85017f1a94426cc1732b72b23..3a67baa7420bec4d75ea7441ef2cead976e4214d 100644 (file)
@@ -2685,6 +2685,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
+       case PM_RESTORE_PREPARE:
                spin_lock_irqsave(&host->lock, flags);
                host->rescan_disable = 1;
                spin_unlock_irqrestore(&host->lock, flags);
index 54730f4aac87f0143ca08a5ca740634376fc4871..9c208fdf43abf4e431f1e5ea524b7227d791f81f 100644 (file)
@@ -1401,7 +1401,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
        host            = mmc_priv(mmc);
        host->mmc       = mmc;
        host->addr      = reg;
-       host->timeout   = msecs_to_jiffies(1000);
+       host->timeout   = msecs_to_jiffies(10000);
        host->ccs_enable = !pd || !pd->ccs_unsupported;
        host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present;
 
index 51e15fd531086c7e743eb00e5f1d250862f91bf3..d058b00ba2186fad620e968ee2ae081fa5e3147d 100644 (file)
@@ -481,6 +481,42 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
        nand_writel(info, NDCR, ndcr | int_mask);
 }
 
+static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
+{
+       if (info->ecc_bch) {
+               int timeout;
+
+               /*
+                * According to the datasheet, when reading from NDDB
+                * with BCH enabled, after each 32 bytes reads, we
+                * have to make sure that the NDSR.RDDREQ bit is set.
+                *
+                * Drain the FIFO 8 32 bits reads at a time, and skip
+                * the polling on the last read.
+                */
+               while (len > 8) {
+                       __raw_readsl(info->mmio_base + NDDB, data, 8);
+
+                       for (timeout = 0;
+                            !(nand_readl(info, NDSR) & NDSR_RDDREQ);
+                            timeout++) {
+                               if (timeout >= 5) {
+                                       dev_err(&info->pdev->dev,
+                                               "Timeout on RDDREQ while draining the FIFO\n");
+                                       return;
+                               }
+
+                               mdelay(1);
+                       }
+
+                       data += 32;
+                       len -= 8;
+               }
+       }
+
+       __raw_readsl(info->mmio_base + NDDB, data, len);
+}
+
 static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
        unsigned int do_bytes = min(info->data_size, info->chunk_size);
@@ -497,14 +533,14 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
                                      DIV_ROUND_UP(info->oob_size, 4));
                break;
        case STATE_PIO_READING:
-               __raw_readsl(info->mmio_base + NDDB,
-                            info->data_buff + info->data_buff_pos,
-                            DIV_ROUND_UP(do_bytes, 4));
+               drain_fifo(info,
+                          info->data_buff + info->data_buff_pos,
+                          DIV_ROUND_UP(do_bytes, 4));
 
                if (info->oob_size > 0)
-                       __raw_readsl(info->mmio_base + NDDB,
-                                    info->oob_buff + info->oob_buff_pos,
-                                    DIV_ROUND_UP(info->oob_size, 4));
+                       drain_fifo(info,
+                                  info->oob_buff + info->oob_buff_pos,
+                                  DIV_ROUND_UP(info->oob_size, 4));
                break;
        default:
                dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
index 6f27d9a1be3b7ff3294e0549bc7fef308a9a1b85..21841fe25ad381fbcca4e56df31046f749a715d3 100644 (file)
@@ -408,7 +408,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
                second_is_newer = !second_is_newer;
        } else {
                dbg_bld("PEB %d CRC is OK", pnum);
-               bitflips = !!err;
+               bitflips |= !!err;
        }
        mutex_unlock(&ubi->buf_mutex);
 
index 8ca49f2043e4b8a7fe41109129de5760995b59d4..4cbbd55311336f544b49be4ce4b08d5d525b4afb 100644 (file)
@@ -451,7 +451,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
                /* Validate the request */
                err = -EINVAL;
                if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
-                   req.bytes < 0 || req.lnum >= vol->usable_leb_size)
+                   req.bytes < 0 || req.bytes > vol->usable_leb_size)
                        break;
 
                err = get_exclusive(desc);
index 0e11671dadc48c129c3f9cd669c8cf7c9ec5bf70..930cf2c77abb14a386610a56de9c7eabed6b9598 100644 (file)
@@ -1362,7 +1362,8 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
                                 * during re-size.
                                 */
                                ubi_move_aeb_to_list(av, aeb, &ai->erase);
-                       vol->eba_tbl[aeb->lnum] = aeb->pnum;
+                       else
+                               vol->eba_tbl[aeb->lnum] = aeb->pnum;
                }
        }
 
index f913d701a5b3d96222ca9eeb71007c6ee982e209..c4b1af07a121963b06dd7cd71826b14d639e14ee 100644 (file)
@@ -74,6 +74,8 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
        for (i = 0; i < vol->used_ebs; i++) {
                int size;
 
+               cond_resched();
+
                if (i == vol->used_ebs - 1)
                        size = vol->last_eb_bytes;
                else
index 68b924ec222e0f7fef1e868b6e0381582df4aee3..c6b0b078ab99364c01c8e41af28ea784f74ead8c 100644 (file)
@@ -995,7 +995,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                                int cancel)
 {
        int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
-       int vol_id = -1, uninitialized_var(lnum);
+       int vol_id = -1, lnum = -1;
 #ifdef CONFIG_MTD_UBI_FASTMAP
        int anchor = wrk->anchor;
 #endif
index dcde56057fe14f7bb64a8221db03b2d72a22d842..3177498f3eab7976f3b48a49b96def2312145337 100644 (file)
@@ -2479,7 +2479,7 @@ out:
        return NETDEV_TX_OK;
 err_free:
        /* no suitable interface, frame not sent */
-       kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        goto out;
 }
 
index e8f133e926aae720d09d76117bd0c84dcc90d775..c67bbc9c36dcb6af873b1ff304b58bd2fd2ec7ed 100644 (file)
@@ -1479,7 +1479,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
        }
 
        /* no suitable interface, frame not sent */
-       kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 out:
        return NETDEV_TX_OK;
 }
index 15379824d77d2123b50779981f35a43997eb2a11..32b0e7055b1e875a98cc8578741e8fb4c06cc2dc 100644 (file)
@@ -3568,7 +3568,7 @@ static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int sl
                }
        }
        /* no slave that can tx has been found */
-       kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 }
 
 /**
@@ -3650,7 +3650,7 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
        if (slave)
                bond_dev_queue_xmit(bond, skb, slave->dev);
        else
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
 
        return NETDEV_TX_OK;
 }
@@ -3698,7 +3698,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
        if (slave && IS_UP(slave->dev) && slave->link == BOND_LINK_UP)
                bond_dev_queue_xmit(bond, skb, slave->dev);
        else
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
 
        return NETDEV_TX_OK;
 }
@@ -3785,7 +3785,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev
                pr_err("%s: Error: Unknown bonding mode %d\n",
                       dev->name, bond->params.mode);
                WARN_ON_ONCE(1);
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 }
@@ -3806,7 +3806,7 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (bond_has_slaves(bond))
                ret = __bond_start_xmit(skb, dev);
        else
-               kfree_skb(skb);
+               dev_kfree_skb_any(skb);
        rcu_read_unlock();
 
        return ret;
index 1468c4658804eac90dd6bdc9bd0449879caa9424..84ad2b44377c28d2dcecd9c316df957d47e9cade 100644 (file)
@@ -502,6 +502,14 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
        skb->pkt_type = PACKET_BROADCAST;
        skb->ip_summed = CHECKSUM_UNNECESSARY;
 
+       skb_reset_mac_header(skb);
+       skb_reset_network_header(skb);
+       skb_reset_transport_header(skb);
+
+       skb_reset_mac_header(skb);
+       skb_reset_network_header(skb);
+       skb_reset_transport_header(skb);
+
        can_skb_reserve(skb);
        can_skb_prv(skb)->ifindex = dev->ifindex;
 
index 61376abdab395cd941f9a118c46e9912e17f4452..dbd8d21a8f1078fa66b9c1c4b9431e19c2a68675 100644 (file)
@@ -1095,12 +1095,19 @@ static int flexcan_probe(struct platform_device *pdev)
        const struct flexcan_devtype_data *devtype_data;
        struct net_device *dev;
        struct flexcan_priv *priv;
+       struct regulator *reg_xceiver;
        struct resource *mem;
        struct clk *clk_ipg = NULL, *clk_per = NULL;
        void __iomem *base;
        int err, irq;
        u32 clock_freq = 0;
 
+       reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
+       if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+       else if (IS_ERR(reg_xceiver))
+               reg_xceiver = NULL;
+
        if (pdev->dev.of_node)
                of_property_read_u32(pdev->dev.of_node,
                                                "clock-frequency", &clock_freq);
@@ -1162,9 +1169,7 @@ static int flexcan_probe(struct platform_device *pdev)
        priv->pdata = dev_get_platdata(&pdev->dev);
        priv->devtype_data = devtype_data;
 
-       priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
-       if (IS_ERR(priv->reg_xceiver))
-               priv->reg_xceiver = NULL;
+       priv->reg_xceiver = reg_xceiver;
 
        netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
 
index 9339cccfe05a35977493a0fbaf766b91f49f8acb..ad0e71c7a6076238a19f1d6a7b73a574525bcdfb 100644 (file)
@@ -1516,7 +1516,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 {
        struct pcnet32_private *lp;
        int i, media;
-       int fdx, mii, fset, dxsuflo;
+       int fdx, mii, fset, dxsuflo, sram;
        int chip_version;
        char *chipname;
        struct net_device *dev;
@@ -1553,7 +1553,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
        }
 
        /* initialize variables */
-       fdx = mii = fset = dxsuflo = 0;
+       fdx = mii = fset = dxsuflo = sram = 0;
        chip_version = (chip_version >> 12) & 0xffff;
 
        switch (chip_version) {
@@ -1586,6 +1586,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                chipname = "PCnet/FAST III 79C973";     /* PCI */
                fdx = 1;
                mii = 1;
+               sram = 1;
                break;
        case 0x2626:
                chipname = "PCnet/Home 79C978"; /* PCI */
@@ -1609,6 +1610,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                chipname = "PCnet/FAST III 79C975";     /* PCI */
                fdx = 1;
                mii = 1;
+               sram = 1;
                break;
        case 0x2628:
                chipname = "PCnet/PRO 79C976";
@@ -1637,6 +1639,31 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                dxsuflo = 1;
        }
 
+       /*
+        * The Am79C973/Am79C975 controllers come with 12K of SRAM
+        * which we can use for the Tx/Rx buffers but most importantly,
+        * the use of SRAM allow us to use the BCR18:NOUFLO bit to avoid
+        * Tx fifo underflows.
+        */
+       if (sram) {
+               /*
+                * The SRAM is being configured in two steps. First we
+                * set the SRAM size in the BCR25:SRAM_SIZE bits. According
+                * to the datasheet, each bit corresponds to a 512-byte
+                * page so we can have at most 24 pages. The SRAM_SIZE
+                * holds the value of the upper 8 bits of the 16-bit SRAM size.
+                * The low 8-bits start at 0x00 and end at 0xff. So the
+                * address range is from 0x0000 up to 0x17ff. Therefore,
+                * the SRAM_SIZE is set to 0x17. The next step is to set
+                * the BCR26:SRAM_BND midway through so the Tx and Rx
+                * buffers can share the SRAM equally.
+                */
+               a->write_bcr(ioaddr, 25, 0x17);
+               a->write_bcr(ioaddr, 26, 0xc);
+               /* And finally enable the NOUFLO bit */
+               a->write_bcr(ioaddr, 18, a->read_bcr(ioaddr, 18) | (1 << 11));
+       }
+
        dev = alloc_etherdev(sizeof(*lp));
        if (!dev) {
                ret = -ENOMEM;
index 6c9e1c9bdeb8cbe06ae1788bd7ecb628e2ea4564..0c8a1686660302a9d40bf08ab2d8a3b3d554eb12 100644 (file)
@@ -2886,7 +2886,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                sw_cons = BNX2_NEXT_TX_BD(sw_cons);
 
                tx_bytes += skb->len;
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                tx_pkt++;
                if (tx_pkt == budget)
                        break;
@@ -6640,7 +6640,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        mapping = dma_map_single(&bp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
        if (dma_mapping_error(&bp->pdev->dev, mapping)) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
@@ -6733,7 +6733,7 @@ dma_error:
                               PCI_DMA_TODEVICE);
        }
 
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        return NETDEV_TX_OK;
 }
 
index 7d4382286457e6f0bf1b9ba87a981dd758fc874b..242874041ba4912854bb46d1e671ecc2f8b2b272 100644 (file)
@@ -12395,6 +12395,9 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
        pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
                               PCICFG_VENDOR_ID_OFFSET);
 
+       /* Set PCIe reset type to fundamental for EEH recovery */
+       pdev->needs_freset = 1;
+
        /* AER (Advanced Error reporting) configuration */
        rc = pci_enable_pcie_error_reporting(pdev);
        if (!rc)
index 82061139b2159a2d1fbb1e4ed3144d8d28967921..bc65dc85a6220b885a248eb7345e8ae81dcf30f8 100644 (file)
@@ -6593,7 +6593,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
                pkts_compl++;
                bytes_compl += skb->len;
 
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
 
                if (unlikely(tx_bug)) {
                        tg3_tx_recover(tp);
@@ -6925,7 +6925,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                if (len > (tp->dev->mtu + ETH_HLEN) &&
                    skb->protocol != htons(ETH_P_8021Q) &&
                    skb->protocol != htons(ETH_P_8021AD)) {
-                       dev_kfree_skb(skb);
+                       dev_kfree_skb_any(skb);
                        goto drop_it_no_recycle;
                }
 
@@ -7808,7 +7808,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
                                          PCI_DMA_TODEVICE);
                /* Make sure the mapping succeeded */
                if (pci_dma_mapping_error(tp->pdev, new_addr)) {
-                       dev_kfree_skb(new_skb);
+                       dev_kfree_skb_any(new_skb);
                        ret = -1;
                } else {
                        u32 save_entry = *entry;
@@ -7823,13 +7823,13 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
                                            new_skb->len, base_flags,
                                            mss, vlan)) {
                                tg3_tx_skb_unmap(tnapi, save_entry, -1);
-                               dev_kfree_skb(new_skb);
+                               dev_kfree_skb_any(new_skb);
                                ret = -1;
                        }
                }
        }
 
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        *pskb = new_skb;
        return ret;
 }
@@ -7872,7 +7872,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
        } while (segs);
 
 tg3_tso_bug_end:
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 
        return NETDEV_TX_OK;
 }
@@ -8110,7 +8110,7 @@ dma_error:
        tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i);
        tnapi->tx_buffers[tnapi->tx_prod].skb = NULL;
 drop:
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 drop_nofree:
        tp->tx_dropped++;
        return NETDEV_TX_OK;
index 80bfa0391913a8c8893290a371e6cdc0f26b47f6..075e7e7abea97eeeb97af191c107a2595c3e2ac8 100644 (file)
@@ -1883,7 +1883,7 @@ static u16 be_tx_compl_process(struct be_adapter *adapter,
                queue_tail_inc(txq);
        } while (cur_index != last_index);
 
-       kfree_skb(sent_skb);
+       dev_kfree_skb_any(sent_skb);
        return num_wrbs;
 }
 
index ad5a5aadc7e15901a3722ac673f36a25a3a99884..70eb4d27b4fa5d630a6b7fe93ab5ae3d7a5c6ca6 100644 (file)
@@ -2152,13 +2152,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
                skb_new = skb_realloc_headroom(skb, fcb_len);
                if (!skb_new) {
                        dev->stats.tx_errors++;
-                       kfree_skb(skb);
+                       dev_kfree_skb_any(skb);
                        return NETDEV_TX_OK;
                }
 
                if (skb->sk)
                        skb_set_owner_w(skb_new, skb->sk);
-               consume_skb(skb);
+               dev_consume_skb_any(skb);
                skb = skb_new;
        }
 
index 46e6544ed1b7f5c1ba9367dd1dfe444d725cd0e3..b655fe4f4c2e7e0d19beb8d4479ab698853515bb 100644 (file)
@@ -144,6 +144,11 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
                                     struct e1000_rx_ring *rx_ring,
                                     int *work_done, int work_to_do);
+static void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter,
+                                        struct e1000_rx_ring *rx_ring,
+                                        int cleaned_count)
+{
+}
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
                                   struct e1000_rx_ring *rx_ring,
                                   int cleaned_count);
@@ -3531,8 +3536,11 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
                msleep(1);
        /* e1000_down has a dependency on max_frame_size */
        hw->max_frame_size = max_frame;
-       if (netif_running(netdev))
+       if (netif_running(netdev)) {
+               /* prevent buffers from being reallocated */
+               adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers;
                e1000_down(adapter);
+       }
 
        /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
         * means we reserve 2 more, this pushes us to allocate from the next
index 57e390cbe6d0d21630f6bf6904a0c8a663601931..f42c201f727fc7fdb46062808cd0435927081256 100644 (file)
@@ -1521,12 +1521,12 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        int tso;
 
        if (test_bit(__IXGB_DOWN, &adapter->flags)) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
        if (skb->len <= 0) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
@@ -1543,7 +1543,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        tso = ixgb_tso(adapter, skb);
        if (tso < 0) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
index 2f83f3489fdb3bac96b3f6556a5f926a0a176c57..8be0f3e1e8e9d12d238966b9df89b3c85bd39562 100644 (file)
@@ -2497,13 +2497,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        netif_carrier_off(dev);
        mlx4_en_set_default_moderation(priv);
 
-       err = register_netdev(dev);
-       if (err) {
-               en_err(priv, "Netdev registration failed for port %d\n", port);
-               goto out;
-       }
-       priv->registered = 1;
-
        en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
        en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
 
@@ -2543,6 +2536,14 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
                queue_delayed_work(mdev->workqueue, &priv->service_task,
                                   SERVICE_TASK_DELAY);
 
+       err = register_netdev(dev);
+       if (err) {
+               en_err(priv, "Netdev registration failed for port %d\n", port);
+               goto out;
+       }
+
+       priv->registered = 1;
+
        return 0;
 
 out:
index 13457032d15ff09489cff354b3322f06011e1c2b..019a04a3138401147b03c10c5b66cd517bc6c318 100644 (file)
@@ -325,7 +325,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
                        }
                }
        }
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        return tx_info->nr_txbb;
 }
 
index 737c1a881f781917061d8b39ad43762f62ee7a6e..a3c1daa7ad5cbfbff82699cf9a1a95bcec2022da 100644 (file)
@@ -899,7 +899,7 @@ out_unlock:
 
        return NETDEV_TX_OK;
 out_dma_error:
-       kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        cp->dev->stats.tx_dropped++;
        goto out_unlock;
 }
index da5972eefdd2bfc5d702fd553cf68b91c5485fb5..8cb2f357026e7bca87586eac3552471d0307c841 100644 (file)
@@ -1717,9 +1717,9 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
                if (len < ETH_ZLEN)
                        memset(tp->tx_buf[entry], 0, ETH_ZLEN);
                skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
        } else {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                dev->stats.tx_dropped++;
                return NETDEV_TX_OK;
        }
index 3ff7bc3e7a23ba419c9957917a9471a939db54f2..90c14d16f2614a76a857f504514ce2a4491faeff 100644 (file)
@@ -5834,7 +5834,7 @@ static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
                                             tp->TxDescArray + entry);
                        if (skb) {
                                tp->dev->stats.tx_dropped++;
-                               dev_kfree_skb(skb);
+                               dev_kfree_skb_any(skb);
                                tx_skb->skb = NULL;
                        }
                }
@@ -6059,7 +6059,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 err_dma_1:
        rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
 err_dma_0:
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 err_update_stats:
        dev->stats.tx_dropped++;
        return NETDEV_TX_OK;
@@ -6142,7 +6142,7 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
                        tp->tx_stats.packets++;
                        tp->tx_stats.bytes += tx_skb->skb->len;
                        u64_stats_update_end(&tp->tx_stats.syncp);
-                       dev_kfree_skb(tx_skb->skb);
+                       dev_kfree_skb_any(tx_skb->skb);
                        tx_skb->skb = NULL;
                }
                dirty_tx++;
index 07c942b6ae011bc1d96d2e7a5e97ed2d3ffe4c24..e8c21f911b6f640243c01f6147fe9d41687b1f5e 100644 (file)
@@ -637,12 +637,15 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
        } /* else everything is zero */
 }
 
+/* Neighbour code has some assumptions on HH_DATA_MOD alignment */
+#define MACVTAP_RESERVE HH_DATA_OFF(ETH_HLEN)
+
 /* Get packet from user space buffer */
 static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
                                const struct iovec *iv, unsigned long total_len,
                                size_t count, int noblock)
 {
-       int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN);
+       int good_linear = SKB_MAX_HEAD(MACVTAP_RESERVE);
        struct sk_buff *skb;
        struct macvlan_dev *vlan;
        unsigned long len = total_len;
@@ -701,7 +704,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
                        linear = vnet_hdr.hdr_len;
        }
 
-       skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
+       skb = macvtap_alloc_skb(&q->sk, MACVTAP_RESERVE, copylen,
                                linear, noblock, &err);
        if (!skb)
                goto err;
index 76d96b9ebcdb94d2e57c3f52d5b49a41e7397ab4..1d568788c3e32164a1b286e2f96d69338c4b4141 100644 (file)
@@ -193,6 +193,25 @@ static inline unsigned int phy_find_valid(unsigned int idx, u32 features)
        return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
 }
 
+/**
+ * phy_check_valid - check if there is a valid PHY setting which matches
+ *                  speed, duplex, and feature mask
+ * @speed: speed to match
+ * @duplex: duplex to match
+ * @features: A mask of the valid settings
+ *
+ * Description: Returns true if there is a valid setting, false otherwise.
+ */
+static inline bool phy_check_valid(int speed, int duplex, u32 features)
+{
+       unsigned int idx;
+
+       idx = phy_find_valid(phy_find_setting(speed, duplex), features);
+
+       return settings[idx].speed == speed && settings[idx].duplex == duplex &&
+               (settings[idx].setting & features);
+}
+
 /**
  * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex
  * @phydev: the target phy_device struct
@@ -955,7 +974,6 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
                int eee_lp, eee_cap, eee_adv;
                u32 lp, cap, adv;
                int status;
-               unsigned int idx;
 
                /* Read phy status to properly get the right settings */
                status = phy_read_status(phydev);
@@ -987,8 +1005,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
 
                adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
                lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
-               idx = phy_find_setting(phydev->speed, phydev->duplex);
-               if (!(lp & adv & settings[idx].setting))
+               if (!phy_check_valid(phydev->speed, phydev->duplex, lp & adv))
                        return -EPROTONOSUPPORT;
 
                if (clk_stop_enable) {
index 32efe8371ff8deb43d62804ecd0887163af5035f..c28e2dafb3f024c73127c42b562e8c15f295fc6d 100644 (file)
@@ -42,9 +42,7 @@
 
 static struct team_port *team_port_get_rcu(const struct net_device *dev)
 {
-       struct team_port *port = rcu_dereference(dev->rx_handler_data);
-
-       return team_port_exists(dev) ? port : NULL;
+       return rcu_dereference(dev->rx_handler_data);
 }
 
 static struct team_port *team_port_get_rtnl(const struct net_device *dev)
@@ -1725,11 +1723,11 @@ static int team_set_mac_address(struct net_device *dev, void *p)
        if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-       rcu_read_lock();
-       list_for_each_entry_rcu(port, &team->port_list, list)
+       mutex_lock(&team->lock);
+       list_for_each_entry(port, &team->port_list, list)
                if (team->ops.port_change_dev_addr)
                        team->ops.port_change_dev_addr(team, port);
-       rcu_read_unlock();
+       mutex_unlock(&team->lock);
        return 0;
 }
 
index 3eed708a6182e761fb79d197eadfbcbc028e5afc..fe48f4c513730fa485aaf31dcf8be8ed119736f8 100644 (file)
@@ -300,9 +300,18 @@ static const struct driver_info    cx82310_info = {
        .tx_fixup       = cx82310_tx_fixup,
 };
 
+#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+                      USB_DEVICE_ID_MATCH_DEV_INFO, \
+       .idVendor = (vend), \
+       .idProduct = (prod), \
+       .bDeviceClass = (cl), \
+       .bDeviceSubClass = (sc), \
+       .bDeviceProtocol = (pr)
+
 static const struct usb_device_id products[] = {
        {
-               USB_DEVICE_AND_INTERFACE_INFO(0x0572, 0xcb01, 0xff, 0, 0),
+               USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0),
                .driver_info = (unsigned long) &cx82310_info
        },
        { },
index 3d18bb0eee8528ece6509ec3848c3044ff5804ce..1bfe0fcaccf5ba31bf125f898ec6c624f506206e 100644 (file)
@@ -134,6 +134,11 @@ static const struct usb_device_id  products [] = {
 }, {
        USB_DEVICE(0x050d, 0x258a),     /* Belkin F5U258/F5U279 (PL-25A1) */
        .driver_info =  (unsigned long) &prolific_info,
+}, {
+       USB_DEVICE(0x3923, 0x7825),     /* National Instruments USB
+                                        * Host-to-Host Cable
+                                        */
+       .driver_info =  (unsigned long) &prolific_info,
 },
 
        { },            // END
index a3399c4f13a9a85c070bebf1ecbcd7cc6eed24e6..b9b651ea985156d0cd5dcbb814d75b927bf7d238 100644 (file)
@@ -478,7 +478,7 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
        regval = ioread32(reg);
        iowrite32(regval | val, reg);
        regval = ioread32(reg);
-       usleep_range(100, 150);
+       udelay(100);    /* NB: should be atomic */
 
        /* Bring BB/MAC out of reset */
        iowrite32(regval & ~val, reg);
index 61f6b21fb0aeeaa4e6ef20dfca3baddf6ad638cd..dc6bd8cd9b837d85155d494a0afd2b32b7775240 100644 (file)
@@ -197,9 +197,9 @@ struct hif_scatter_req {
        /* bounce buffer for upper layers to copy to/from */
        u8 *virt_dma_buf;
 
-       struct hif_scatter_item scat_list[1];
-
        u32 scat_q_depth;
+
+       struct hif_scatter_item scat_list[0];
 };
 
 struct ath6kl_irq_proc_registers {
index 7126bdd4236c2b1e78dd3a9d2c600dbadbb53f0e..6bf15a33171487f7e133526e6c993e53fddd85fb 100644 (file)
@@ -348,7 +348,7 @@ static int ath6kl_sdio_alloc_prep_scat_req(struct ath6kl_sdio *ar_sdio,
        int i, scat_req_sz, scat_list_sz, size;
        u8 *virt_buf;
 
-       scat_list_sz = (n_scat_entry - 1) * sizeof(struct hif_scatter_item);
+       scat_list_sz = n_scat_entry * sizeof(struct hif_scatter_item);
        scat_req_sz = sizeof(*s_req) + scat_list_sz;
 
        if (!virt_scat)
index 3441f70d0ff911594dfd4066e782f0ca042e02d6..6e8cdb8a0cc52cd10600ec87a139f2c0e72b8bc3 100644 (file)
@@ -708,7 +708,6 @@ struct iwl_priv {
        unsigned long reload_jiffies;
        int reload_count;
        bool ucode_loaded;
-       bool init_ucode_run;            /* Don't run init uCode again */
 
        u8 plcp_delta_threshold;
 
index cf03ef5619d9fea602151cf573162848ffd12366..8b2dedc301592d743990b12668b2d6d91314898f 100644 (file)
@@ -418,9 +418,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv)
        if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len)
                return 0;
 
-       if (priv->init_ucode_run)
-               return 0;
-
        iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
                                   calib_complete, ARRAY_SIZE(calib_complete),
                                   iwlagn_wait_calib, priv);
@@ -440,8 +437,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv)
         */
        ret = iwl_wait_notification(&priv->notif_wait, &calib_wait,
                                        UCODE_CALIB_TIMEOUT);
-       if (!ret)
-               priv->init_ucode_run = true;
 
        goto out;
 
index 6f8d0574596657d6a602b136b346536a3e81fa58..bf67b1ce674fb971841832863432b437c4da82c4 100644 (file)
@@ -594,7 +594,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 
        ret = iwl_mvm_mac_ctxt_add(mvm, vif);
        if (ret)
-               goto out_remove_mac;
+               goto out_release;
 
        iwl_mvm_power_disable(mvm, vif);
 
index f583167691595f14f82f707da0359958a335668d..66c92a16da2939d869fd3758ffc933612d06e31d 100644 (file)
@@ -314,6 +314,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
        {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
        {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
+       {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
        {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
        {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
        {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
@@ -370,6 +371,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
        {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
        {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+       {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */
        {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
        {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/
        {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/
index 7f1669cdea090ed6895b8eaabf0ab7f74054d9c4..779dc2b2ca7591077e18494a4eaa3c82ed8f846d 100644 (file)
@@ -136,7 +136,7 @@ WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, protection_filter, "%u");
 WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u");
 WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u");
 
-WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(rx_rate, rx_frames_per_rates, 50);
 
 WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate,
                                  AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE);
index f7381dd69009a150e1901a876494d225e0267f5e..1bce4325e86bba78bc808fb95eea3738bb9a6663 100644 (file)
@@ -26,8 +26,8 @@
 
 #include "wlcore.h"
 
-int wl1271_format_buffer(char __user *userbuf, size_t count,
-                        loff_t *ppos, char *fmt, ...);
+__printf(4, 5) int wl1271_format_buffer(char __user *userbuf, size_t count,
+                                       loff_t *ppos, char *fmt, ...);
 
 int wl1271_debugfs_init(struct wl1271 *wl);
 void wl1271_debugfs_exit(struct wl1271 *wl);
index 48f20ff1add93716b4099dde15d9d7737c35521b..bbff99dcbaeabcd6939aa2c179411d31f1c07946 100644 (file)
@@ -290,7 +290,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
        struct device_node *p;
        const __be32 *intspec, *tmp, *addr;
        u32 intsize, intlen;
-       int i, res = -EINVAL;
+       int i, res;
 
        pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
 
@@ -323,15 +323,19 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
 
        /* Get size of interrupt specifier */
        tmp = of_get_property(p, "#interrupt-cells", NULL);
-       if (tmp == NULL)
+       if (tmp == NULL) {
+               res = -EINVAL;
                goto out;
+       }
        intsize = be32_to_cpu(*tmp);
 
        pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
 
        /* Check index */
-       if ((index + 1) * intsize > intlen)
+       if ((index + 1) * intsize > intlen) {
+               res = -EINVAL;
                goto out;
+       }
 
        /* Copy intspec into irq structure */
        intspec += index * intsize;
index 34ff7026440cac0e929df3db06cba8f93b2a5c00..5d3b45640181a3dd82bb44a39ee486da8e184ac3 100644 (file)
@@ -127,16 +127,8 @@ static const char *aer_agent_string[] = {
 static void __print_tlp_header(struct pci_dev *dev,
                               struct aer_header_log_regs *t)
 {
-       unsigned char *tlp = (unsigned char *)&t;
-
-       dev_err(&dev->dev, "  TLP Header:"
-               " %02x%02x%02x%02x %02x%02x%02x%02x"
-               " %02x%02x%02x%02x %02x%02x%02x%02x\n",
-               *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
-               *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
-               *(tlp + 11), *(tlp + 10), *(tlp + 9),
-               *(tlp + 8), *(tlp + 15), *(tlp + 14),
-               *(tlp + 13), *(tlp + 12));
+       dev_err(&dev->dev, "  TLP Header: %08x %08x %08x %08x\n",
+               t->dw0, t->dw1, t->dw2, t->dw3);
 }
 
 static void __aer_print_error(struct pci_dev *dev,
index 0805d3c5c3c6c832e8846cb38fd8fb025c6740f3..2b66e9c7bce3f6870da0776f8fdb82c65e8e3c87 100644 (file)
@@ -51,7 +51,9 @@ static void devm_phy_consume(struct device *dev, void *res)
 
 static int devm_phy_match(struct device *dev, void *res, void *match_data)
 {
-       return res == match_data;
+       struct phy **phy = res;
+
+       return *phy == match_data;
 }
 
 static struct phy *phy_lookup(struct device *device, const char *port)
index f99f7df1cf659450105f2c4fffd397cf4b9a2aa3..124aa21a806b94d76f0d01c6333c462b604c862b 100644 (file)
@@ -1122,7 +1122,7 @@ void devm_pinctrl_put(struct pinctrl *p)
 EXPORT_SYMBOL_GPL(devm_pinctrl_put);
 
 int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
-                        bool dup, bool locked)
+                        bool dup)
 {
        int i, ret;
        struct pinctrl_maps *maps_node;
@@ -1190,11 +1190,9 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
                maps_node->maps = maps;
        }
 
-       if (!locked)
-               mutex_lock(&pinctrl_maps_mutex);
+       mutex_lock(&pinctrl_maps_mutex);
        list_add_tail(&maps_node->node, &pinctrl_maps);
-       if (!locked)
-               mutex_unlock(&pinctrl_maps_mutex);
+       mutex_unlock(&pinctrl_maps_mutex);
 
        return 0;
 }
@@ -1209,7 +1207,7 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
 int pinctrl_register_mappings(struct pinctrl_map const *maps,
                              unsigned num_maps)
 {
-       return pinctrl_register_map(maps, num_maps, true, false);
+       return pinctrl_register_map(maps, num_maps, true);
 }
 
 void pinctrl_unregister_map(struct pinctrl_map const *map)
index c675ba61d479845b66a3fa8e632583cf8550c0c9..3b3d8ae8d97a312fe94394179a563939f309e829 100644 (file)
@@ -182,7 +182,7 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
 }
 
 int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
-                        bool dup, bool locked);
+                        bool dup);
 void pinctrl_unregister_map(struct pinctrl_map const *map);
 
 extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev);
index 340fb4e6c600393f0504e6d6cd5f7adc9cbad29e..fd91c4c31f6b638f33a69e2052b60c7ad6f26f31 100644 (file)
@@ -92,7 +92,7 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
        dt_map->num_maps = num_maps;
        list_add_tail(&dt_map->node, &p->dt_maps);
 
-       return pinctrl_register_map(map, num_maps, false, true);
+       return pinctrl_register_map(map, num_maps, false);
 }
 
 struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
index 7297df2ebf503771d080a3467869819d72921b08..54407a8209b514fbf8f62b939f80ab9ee386422b 100644 (file)
@@ -1027,9 +1027,9 @@ static int compal_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
-                                                     DRIVER_NAME, data,
-                                                     compal_hwmon_groups);
+       hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
+                                                          DRIVER_NAME, data,
+                                                          compal_hwmon_groups);
        if (IS_ERR(hwmon_dev)) {
                err = PTR_ERR(hwmon_dev);
                goto remove;
@@ -1037,7 +1037,9 @@ static int compal_probe(struct platform_device *pdev)
 
        /* Power supply */
        initialize_power_supply_data(data);
-       power_supply_register(&compal_device->dev, &data->psy);
+       err = power_supply_register(&compal_device->dev, &data->psy);
+       if (err < 0)
+               goto remove;
 
        platform_set_drvdata(pdev, data);
 
index ed49b50b220b3ed6541c5b6f82079e1d0373e8f7..72da2a6c22db953b1c9c95a84fc27a9007580891 100644 (file)
@@ -417,8 +417,10 @@ static int lp8788_psy_register(struct platform_device *pdev,
        pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop);
        pchg->battery.get_property = lp8788_battery_get_property;
 
-       if (power_supply_register(&pdev->dev, &pchg->battery))
+       if (power_supply_register(&pdev->dev, &pchg->battery)) {
+               power_supply_unregister(&pchg->charger);
                return -EPERM;
+       }
 
        return 0;
 }
index 7ef445a6cfa6d824f297c39ad0b93555126fd82e..cf907609ec49eea0ddff12a23e44afe05b02434c 100644 (file)
@@ -192,6 +192,7 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
 {
        struct twl4030_madc_battery *twl4030_madc_bat;
        struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data;
+       int ret = 0;
 
        twl4030_madc_bat = kzalloc(sizeof(*twl4030_madc_bat), GFP_KERNEL);
        if (!twl4030_madc_bat)
@@ -216,9 +217,11 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
 
        twl4030_madc_bat->pdata = pdata;
        platform_set_drvdata(pdev, twl4030_madc_bat);
-       power_supply_register(&pdev->dev, &twl4030_madc_bat->psy);
+       ret = power_supply_register(&pdev->dev, &twl4030_madc_bat->psy);
+       if (ret < 0)
+               kfree(twl4030_madc_bat);
 
-       return 0;
+       return ret;
 }
 
 static int twl4030_madc_battery_remove(struct platform_device *pdev)
index ea6c270eea72f1fcd814cf28c3179337b83952b4..6a9cdd907f789f767c67f889889d14ee74cc87fd 100644 (file)
@@ -1773,10 +1773,12 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
        trace_regulator_enable(rdev_get_name(rdev));
 
        if (rdev->ena_pin) {
-               ret = regulator_ena_gpio_ctrl(rdev, true);
-               if (ret < 0)
-                       return ret;
-               rdev->ena_gpio_state = 1;
+               if (!rdev->ena_gpio_state) {
+                       ret = regulator_ena_gpio_ctrl(rdev, true);
+                       if (ret < 0)
+                               return ret;
+                       rdev->ena_gpio_state = 1;
+               }
        } else if (rdev->desc->ops->enable) {
                ret = rdev->desc->ops->enable(rdev);
                if (ret < 0)
@@ -1906,10 +1908,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
        trace_regulator_disable(rdev_get_name(rdev));
 
        if (rdev->ena_pin) {
-               ret = regulator_ena_gpio_ctrl(rdev, false);
-               if (ret < 0)
-                       return ret;
-               rdev->ena_gpio_state = 0;
+               if (rdev->ena_gpio_state) {
+                       ret = regulator_ena_gpio_ctrl(rdev, false);
+                       if (ret < 0)
+                               return ret;
+                       rdev->ena_gpio_state = 0;
+               }
 
        } else if (rdev->desc->ops->disable) {
                ret = rdev->desc->ops->disable(rdev);
@@ -3463,12 +3467,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
                                 config->ena_gpio, ret);
                        goto wash;
                }
-
-               if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
-                       rdev->ena_gpio_state = 1;
-
-               if (config->ena_gpio_invert)
-                       rdev->ena_gpio_state = !rdev->ena_gpio_state;
        }
 
        /* set regulator constraints */
@@ -3640,9 +3638,11 @@ int regulator_suspend_finish(void)
        list_for_each_entry(rdev, &regulator_list, list) {
                mutex_lock(&rdev->mutex);
                if (rdev->use_count > 0  || rdev->constraints->always_on) {
-                       error = _regulator_do_enable(rdev);
-                       if (error)
-                               ret = error;
+                       if (!_regulator_is_enabled(rdev)) {
+                               error = _regulator_do_enable(rdev);
+                               if (error)
+                                       ret = error;
+                       }
                } else {
                        if (!have_full_constraints())
                                goto unlock;
index 9553b616ab8396952e791346e7fe718150e5acbc..599e21d6c1975e0293870fea9099b3a79247008e 100644 (file)
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
 
+#include "internal.h"
+
+const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
+       [PM_SUSPEND_MEM]        = "regulator-state-mem",
+       [PM_SUSPEND_MAX]        = "regulator-state-disk",
+};
+
 static void of_get_regulation_constraints(struct device_node *np,
                                        struct regulator_init_data **init_data)
 {
@@ -23,7 +30,9 @@ static void of_get_regulation_constraints(struct device_node *np,
        const __be32 *min_uA, *max_uA, *ramp_delay;
        struct property *prop;
        struct regulation_constraints *constraints = &(*init_data)->constraints;
-       int ret;
+       struct regulator_state *suspend_state;
+       struct device_node *suspend_np;
+       int ret, i;
        u32 pval;
 
        constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -67,11 +76,6 @@ static void of_get_regulation_constraints(struct device_node *np,
        if (of_property_read_bool(np, "regulator-allow-bypass"))
                constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
 
-       if (of_property_read_bool(np, "regulator-suspend-enable")) {
-               constraints->state_mem.enabled = 1;
-               constraints->initial_state = PM_SUSPEND_MEM;
-       }
-
        prop = of_find_property(np, "regulator-ramp-delay", NULL);
        if (prop && prop->value) {
                ramp_delay = prop->value;
@@ -84,6 +88,39 @@ static void of_get_regulation_constraints(struct device_node *np,
        ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
        if (!ret)
                constraints->enable_time = pval;
+
+       for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
+               switch (i) {
+               case PM_SUSPEND_MEM:
+                       suspend_state = &constraints->state_mem;
+                       break;
+               case PM_SUSPEND_MAX:
+                       suspend_state = &constraints->state_disk;
+                       break;
+               case PM_SUSPEND_ON:
+               case PM_SUSPEND_FREEZE:
+               case PM_SUSPEND_STANDBY:
+               default:
+                       continue;
+               };
+
+               suspend_np = of_get_child_by_name(np, regulator_states[i]);
+               if (!suspend_np || !suspend_state)
+                       continue;
+
+               if (of_property_read_bool(suspend_np,
+                                         "regulator-on-in-suspend"))
+                       suspend_state->enabled = true;
+               else if (of_property_read_bool(suspend_np,
+                                              "regulator-off-in-suspend"))
+                       suspend_state->disabled = true;
+
+               if (i == PM_SUSPEND_MEM)
+                       constraints->initial_state = PM_SUSPEND_MEM;
+
+               suspend_state = NULL;
+               suspend_np = NULL;
+       }
 }
 
 /**
index a7ce34d1b5f2e8514ad33fcb2170c35ab7e5ecca..8793b83c4da21df87901accb76935022e7b0c5e5 100644 (file)
@@ -916,6 +916,9 @@ static int palmas_ldo_registration(struct palmas_pmic *pmic,
                            (id == PALMAS_REG_LDO6))
                                desc->enable_time = 2000;
                } else {
+                       if (!ddata->has_regen3 && id == PALMAS_REG_REGEN3)
+                               continue;
+
                        desc->n_voltages = 1;
                        if (reg_init && reg_init->roof_floor)
                                desc->ops = &palmas_ops_ext_control_extreg;
@@ -1398,6 +1401,7 @@ static struct palmas_pmic_driver_data palmas_ddata = {
        .ldo_begin = PALMAS_REG_LDO1,
        .ldo_end = PALMAS_REG_LDOUSB,
        .max_reg = PALMAS_NUM_REGS,
+       .has_regen3 = true,
        .palmas_regs_info = palmas_generic_regs_info,
        .palmas_matches = palmas_matches,
        .sleep_req_info = palma_sleep_req_info,
@@ -1411,6 +1415,7 @@ static struct palmas_pmic_driver_data tps65917_ddata = {
        .ldo_begin = TPS65917_REG_LDO1,
        .ldo_end = TPS65917_REG_LDO5,
        .max_reg = TPS65917_NUM_REGS,
+       .has_regen3 = true,
        .palmas_regs_info = tps65917_regs_info,
        .palmas_matches = tps65917_matches,
        .sleep_req_info = tps65917_sleep_req_info,
@@ -1573,6 +1578,12 @@ static int palmas_regulators_probe(struct platform_device *pdev)
        if (!pmic)
                return -ENOMEM;
 
+       if (of_device_is_compatible(node, "ti,tps659038-pmic")) {
+               palmas_generic_regs_info[PALMAS_REG_REGEN2].ctrl_addr =
+                                                       TPS659038_REGEN2_CTRL;
+               palmas_ddata.has_regen3 = false;
+       }
+
        pmic->dev = &pdev->dev;
        pmic->palmas = palmas;
        palmas->pmic = pmic;
index 57c516726f560c98dcef784a300029348a57d59f..865c11e31ed53af6644e5c26e0060aa086b19e2a 100644 (file)
@@ -175,8 +175,20 @@ static int tps65218_pmic_set_suspend_disable(struct regulator_dev *dev)
        if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
                return -EINVAL;
 
-       if (!tps->info[rid]->strobe)
-               return -EINVAL;
+       /*
+        * Certain revisions of TPS65218 will need to have DCDC3 regulator
+        * enabled always, otherwise an immediate system reboot will occur
+        * during poweroff.
+        */
+       if (rid == TPS65218_DCDC_3 && tps->rev == TPS65218_REV_2_1)
+               return 0;
+
+       if (!tps->info[rid]->strobe) {
+               if (rid == TPS65218_DCDC_3)
+                       tps->info[rid]->strobe = 3;
+               else
+                       return -EINVAL;
+       }
 
        return tps65218_set_bits(tps, dev->desc->bypass_reg,
                                 dev->desc->bypass_mask,
index 1a332f108285c8c2c659ac17f41ae46fa74e7f30..d4a0e0d9f475bbf3ebfed94b1eb063efb54ef66e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * OMAP Remote Processor driver
  *
- * Copyright (C) 2011-2014 Texas Instruments, Inc.
+ * Copyright (C) 2011-2015 Texas Instruments, Inc.
  * Copyright (C) 2011 Google, Inc.
  *
  * Ohad Ben-Cohen <ohad@wizery.com>
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/remoteproc.h>
 #include <linux/mailbox_client.h>
 #include <linux/omap-mailbox.h>
+#include <linux/omap-iommu.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/platform_data/remoteproc-omap.h>
 
 #include "omap_remoteproc.h"
 #include "remoteproc_internal.h"
 
+/* default auto-suspend delay (ms) */
+#define DEFAULT_AUTOSUSPEND_DELAY 10000
+
 /**
  * struct omap_rproc_timers_info - timers for the omap rproc
  * @odt: timer pointer
@@ -54,7 +60,12 @@ struct omap_rproc_timers_info {
  * @num_timers: number of rproc timer(s)
  * @num_wd_timers: number of rproc watchdog timers
  * @timers: timer(s) info used by rproc
+ * @autosuspend_delay: auto-suspend delay value to be used for runtime pm
+ * @need_resume: if true a resume is needed in the system resume callback
  * @rproc: rproc handle
+ * @pm_comp: completion primitive to sync for suspend response
+ * @standby_addr: kernel address of the register having module standby status
+ * @suspend_acked: state machine flag to store the suspend request ack
  */
 struct omap_rproc {
        struct mbox_chan *mbox;
@@ -62,17 +73,24 @@ struct omap_rproc {
        int num_timers;
        int num_wd_timers;
        struct omap_rproc_timers_info *timers;
+       int autosuspend_delay;
+       bool need_resume;
        struct rproc *rproc;
+       struct completion pm_comp;
+       void __iomem *standby_addr;
+       bool suspend_acked;
 };
 
 /**
  * struct omap_rproc_fw_data - firmware data for the omap remote processor
  * @device_name: device name of the remote processor
  * @fw_name: firmware name to use
+ * @autosuspend_delay: custom auto-suspend delay value in milliseconds
  */
 struct omap_rproc_fw_data {
        const char *device_name;
        const char *fw_name;
+       int autosuspend_delay;
 };
 
 /**
@@ -291,6 +309,11 @@ static void omap_rproc_mbox_callback(struct mbox_client *client, void *data)
        case RP_MBOX_ECHO_REPLY:
                dev_info(dev, "received echo reply from %s\n", name);
                break;
+       case RP_MBOX_SUSPEND_ACK:
+       case RP_MBOX_SUSPEND_CANCEL:
+               oproc->suspend_acked = msg == RP_MBOX_SUSPEND_ACK;
+               complete(&oproc->pm_comp);
+               break;
        default:
                if (msg >= RP_MBOX_END_MSG) {
                        dev_err(dev, "dropping unknown message %x", msg);
@@ -309,10 +332,22 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid)
        struct device *dev = rproc->dev.parent;
        int ret;
 
+       /* wake up the rproc before kicking it */
+       ret = pm_runtime_get_sync(dev);
+       if (WARN_ON(ret < 0)) {
+               dev_err(dev, "pm_runtime_get_sync() failed during kick, ret = %d\n",
+                       ret);
+               pm_runtime_put_noidle(dev);
+               return;
+       }
+
        /* send the index of the triggered virtqueue in the mailbox payload */
        ret = mbox_send_message(oproc->mbox, (void *)vqid);
        if (ret < 0)
-               dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret);
+               dev_err(dev, "mbox_send_message failed: %d\n", ret);
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
 }
 
 /*
@@ -373,6 +408,19 @@ static int omap_rproc_start(struct rproc *rproc)
                goto reset_timers;
        }
 
+       /*
+        * remote processor is up, so update the runtime pm status and
+        * enable the auto-suspend. The device usage count is incremented
+        * manually for balancing it for auto-suspend
+        */
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+       pm_runtime_get_noresume(dev);
+       pm_runtime_set_autosuspend_delay(dev, oproc->autosuspend_delay);
+       pm_runtime_use_autosuspend(dev);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
        return 0;
 
 reset_timers:
@@ -391,17 +439,49 @@ static int omap_rproc_stop(struct rproc *rproc)
        struct omap_rproc *oproc = rproc->priv;
        int ret;
 
+       /*
+        * cancel any possible scheduled runtime suspend by incrementing
+        * the device usage count, and resuming the device. The remoteproc
+        * also needs to be woken up if suspended, to avoid the remoteproc
+        * OS to continue to remember any context that it has saved, and
+        * avoid potential issues in misindentifying a subsequent device
+        * reboot as a power restore boot
+        */
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0) {
+               pm_runtime_put_noidle(dev);
+               return ret;
+       }
+
        ret = pdata->device_shutdown(pdev);
        if (ret)
-               return ret;
+               goto out;
 
        ret = omap_rproc_disable_timers(pdev, true);
        if (ret)
-               return ret;
+               goto enable_device;
 
        mbox_free_channel(oproc->mbox);
 
+       /*
+        * update the runtime pm states and status now that the remoteproc
+        * has stopped
+        */
+       pm_runtime_dont_use_autosuspend(dev);
+       pm_runtime_put_noidle(dev);
+       pm_runtime_disable(dev);
+       pm_runtime_set_suspended(dev);
+
        return 0;
+
+enable_device:
+       pdata->device_enable(pdev);
+out:
+       /* schedule the next auto-suspend */
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+       return ret;
+
 }
 
 static struct rproc_ops omap_rproc_ops = {
@@ -410,6 +490,283 @@ static struct rproc_ops omap_rproc_ops = {
        .kick           = omap_rproc_kick,
 };
 
+#ifdef CONFIG_PM
+static bool _is_rproc_in_standby(struct omap_rproc *oproc)
+{
+       static int standby_mask = (1 << 18);
+
+       return readl(oproc->standby_addr) & standby_mask;
+}
+
+/* 1 sec is long enough time to let the remoteproc side suspend the device */
+#define DEF_SUSPEND_TIMEOUT 1000
+static int _suspend(struct rproc *rproc, bool auto_suspend)
+{
+       struct device *dev = rproc->dev.parent;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_rproc_pdata *pdata = dev_get_platdata(dev);
+       struct omap_rproc *oproc = rproc->priv;
+       unsigned long to = msecs_to_jiffies(DEF_SUSPEND_TIMEOUT);
+       unsigned long ta = jiffies + to;
+       u32 suspend_msg = auto_suspend ?
+                               RP_MBOX_SUSPEND_AUTO : RP_MBOX_SUSPEND_SYSTEM;
+       int ret;
+
+       reinit_completion(&oproc->pm_comp);
+       oproc->suspend_acked = false;
+       ret = mbox_send_message(oproc->mbox, (void *)suspend_msg);
+       if (ret < 0) {
+               dev_err(dev, "PM mbox_send_message failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = wait_for_completion_timeout(&oproc->pm_comp, to);
+       if (!oproc->suspend_acked)
+               return -EBUSY;
+
+       /*
+        * The remoteproc side is returning the ACK message before saving the
+        * context, because the context saving is performed within a SYS/BIOS
+        * function, and it cannot have any inter-dependencies against the IPC
+        * layer. Also, as the SYS/BIOS needs to preserve properly the processor
+        * register set, sending this ACK or signalling the completion of the
+        * context save through a shared memory variable can never be the
+        * absolute last thing to be executed on the remoteproc side, and the
+        * MPU cannot use the ACK message as a sync point to put the remoteproc
+        * into reset. The only way to ensure that the remote processor has
+        * completed saving the context is to check that the  module has reached
+        * STANDBY state (after saving the context, the SYS/BIOS executes the
+        * appropriate target-specific WFI instruction causing the module to
+        * enter STANDBY).
+        */
+       while (!_is_rproc_in_standby(oproc)) {
+               if (time_after(jiffies, ta))
+                       return -ETIME;
+               schedule();
+       }
+
+       ret = pdata->device_shutdown(pdev);
+       if (ret)
+               return ret;
+
+       ret = omap_rproc_disable_timers(pdev, false);
+       if (ret) {
+               dev_err(dev, "disabling timers during suspend failed %d\n",
+                       ret);
+               goto enable_device;
+       }
+
+       ret = omap_iommu_domain_suspend(rproc->domain, auto_suspend);
+       if (ret) {
+               dev_err(dev, "iommu domain suspend failed %d\n", ret);
+               goto enable_timers;
+       }
+
+       return 0;
+
+enable_timers:
+       /* ignore errors on re-enabling code */
+       omap_rproc_enable_timers(pdev, false);
+enable_device:
+       pdata->device_enable(pdev);
+       return ret;
+}
+
+static int _omap_rproc_suspend(struct rproc *rproc, bool auto_suspend)
+{
+       struct omap_rproc *oproc = rproc->priv;
+
+       /*
+        * do not even attempt suspend if the remote processor is not
+        * idled for auto-suspend
+        */
+       if (auto_suspend && !_is_rproc_in_standby(oproc))
+               return -EBUSY;
+
+       return _suspend(rproc, auto_suspend);
+}
+
+static int _omap_rproc_resume(struct rproc *rproc, bool auto_suspend)
+{
+       struct device *dev = rproc->dev.parent;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_rproc_pdata *pdata = dev_get_platdata(dev);
+       int ret;
+
+       ret = omap_iommu_domain_resume(rproc->domain, auto_suspend);
+       if (ret) {
+               dev_err(dev, "omap_iommu resume failed %d\n", ret);
+               goto out;
+       }
+
+       /* boot address could be lost after suspend, so restore it */
+       if (pdata->set_bootaddr)
+               pdata->set_bootaddr(rproc->bootaddr);
+
+       ret = omap_rproc_enable_timers(pdev, false);
+       if (ret) {
+               dev_err(dev, "enabling timers during resume failed %d\n",
+                       ret);
+               goto suspend_iommu;
+       }
+
+       ret = pdata->device_enable(pdev);
+       if (ret)
+               goto disable_timers;
+
+       return 0;
+
+disable_timers:
+       omap_rproc_disable_timers(pdev, false);
+suspend_iommu:
+       omap_iommu_domain_suspend(rproc->domain, auto_suspend);
+out:
+       return ret;
+}
+
+static int omap_rproc_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rproc *rproc = platform_get_drvdata(pdev);
+       struct omap_rproc *oproc = rproc->priv;
+       int ret = 0;
+
+       mutex_lock(&rproc->lock);
+       if (rproc->state == RPROC_OFFLINE)
+               goto out;
+
+       if (rproc->state == RPROC_SUSPENDED)
+               goto out;
+
+       if (rproc->state != RPROC_RUNNING) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       ret = _omap_rproc_suspend(rproc, false);
+       if (ret) {
+               dev_err(dev, "suspend failed %d\n", ret);
+               goto out;
+       }
+
+       /*
+        * remoteproc is running at the time of system suspend, so remember
+        * it so as to wake it up during system resume
+        */
+       oproc->need_resume = 1;
+       rproc->state = RPROC_SUSPENDED;
+
+       /*
+        * update the runtime pm status to be suspended, without decrementing
+        * the device usage count
+        */
+       pm_runtime_disable(dev);
+       pm_runtime_set_suspended(dev);
+       pm_runtime_enable(dev);
+out:
+       mutex_unlock(&rproc->lock);
+       return ret;
+}
+
+static int omap_rproc_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rproc *rproc = platform_get_drvdata(pdev);
+       struct omap_rproc *oproc = rproc->priv;
+       int ret = 0;
+
+       mutex_lock(&rproc->lock);
+       if (rproc->state == RPROC_OFFLINE)
+               goto out;
+
+       if (rproc->state != RPROC_SUSPENDED) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /*
+        * remoteproc was auto-suspended at the time of system suspend,
+        * so no need to wake-up the processor (leave it in suspended
+        * state, will be woken up during a subsequent runtime_resume)
+        */
+       if (!oproc->need_resume)
+               goto out;
+
+       ret = _omap_rproc_resume(rproc, false);
+       if (ret) {
+               dev_err(dev, "resume failed %d\n", ret);
+               goto out;
+       }
+       oproc->need_resume = false;
+
+       rproc->state = RPROC_RUNNING;
+
+       /*
+        * update the runtime pm status to be active, without incrementing
+        * the device usage count
+        */
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+       pm_runtime_mark_last_busy(dev);
+out:
+       mutex_unlock(&rproc->lock);
+       return ret;
+}
+
+static int omap_rproc_runtime_suspend(struct device *dev)
+{
+       struct rproc *rproc = dev_get_drvdata(dev);
+       int ret;
+
+       if (WARN_ON(rproc->state != RPROC_RUNNING)) {
+               dev_err(dev, "rproc cannot be runtime suspended when not running!\n");
+               return -EBUSY;
+       }
+
+       ret = _omap_rproc_suspend(rproc, true);
+       if (ret)
+               goto abort;
+
+       rproc->state = RPROC_SUSPENDED;
+       return 0;
+
+abort:
+       pm_runtime_mark_last_busy(dev);
+       return ret;
+}
+
+static int omap_rproc_runtime_resume(struct device *dev)
+{
+       struct rproc *rproc = dev_get_drvdata(dev);
+       int ret;
+
+       if (WARN_ON(rproc->state != RPROC_SUSPENDED)) {
+               dev_err(dev, "rproc cannot be runtime resumed if not suspended!\n");
+               return -EBUSY;
+       }
+
+       ret = _omap_rproc_resume(rproc, true);
+       if (ret) {
+               dev_err(dev, "runtime resume failed %d\n", ret);
+               return ret;
+       }
+
+       rproc->state = RPROC_RUNNING;
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+static const struct omap_rproc_fw_data omap4_dsp_fw_data = {
+       .device_name    = "dsp",
+       .fw_name        = "tesla-dsp.xe64T",
+};
+
+static const struct omap_rproc_fw_data omap4_ipu_fw_data = {
+       .device_name    = "ipu",
+       .fw_name        = "ducati-m3-core0.xem3",
+};
+
 static const struct omap_rproc_fw_data dra7_rproc_fw_data[] = {
        {
                .device_name    = "40800000.dsp",
@@ -435,19 +792,19 @@ static const struct omap_rproc_fw_data dra7_rproc_fw_data[] = {
 static const struct of_device_id omap_rproc_of_match[] = {
        {
                .compatible     = "ti,omap4-rproc-dsp",
-               .data           = "tesla-dsp.xe64T",
+               .data           = &omap4_dsp_fw_data,
        },
        {
                .compatible     = "ti,omap4-rproc-ipu",
-               .data           = "ducati-m3-core0.xem3",
+               .data           = &omap4_ipu_fw_data,
        },
        {
                .compatible     = "ti,omap5-rproc-dsp",
-               .data           = "tesla-dsp.xe64T",
+               .data           = &omap4_dsp_fw_data,
        },
        {
                .compatible     = "ti,omap5-rproc-ipu",
-               .data           = "ducati-m3-core0.xem3",
+               .data           = &omap4_ipu_fw_data,
        },
        {
                .compatible     = "ti,dra7-rproc-dsp",
@@ -463,6 +820,36 @@ static const struct of_device_id omap_rproc_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, omap_rproc_of_match);
 
+static int omap_rproc_get_autosuspend_delay(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       const struct omap_rproc_fw_data *data;
+       const struct of_device_id *match;
+       int delay = -EINVAL;
+
+       match = of_match_device(omap_rproc_of_match, &pdev->dev);
+       if (!match)
+               return -ENODEV;
+
+       data = match->data;
+
+       if (!of_device_is_compatible(np, "ti,dra7-rproc-dsp") &&
+           !of_device_is_compatible(np, "ti,dra7-rproc-ipu")) {
+               delay = data->autosuspend_delay;
+               goto out;
+       }
+
+       for (; data && data->device_name; data++) {
+               if (!strcmp(dev_name(&pdev->dev), data->device_name)) {
+                       delay = data->autosuspend_delay;
+                       break;
+               }
+       }
+
+out:
+       return (delay > 0) ? delay : DEFAULT_AUTOSUSPEND_DELAY;
+}
+
 static const char *omap_rproc_get_firmware(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -473,11 +860,12 @@ static const char *omap_rproc_get_firmware(struct platform_device *pdev)
        if (!match)
                return ERR_PTR(-ENODEV);
 
+       data = match->data;
+
        if (!of_device_is_compatible(np, "ti,dra7-rproc-dsp") &&
            !of_device_is_compatible(np, "ti,dra7-rproc-ipu"))
-               return match->data;
+               return data->fw_name;
 
-       data = match->data;
        for (; data && data->device_name; data++) {
                if (!strcmp(dev_name(&pdev->dev), data->device_name))
                        return data->fw_name;
@@ -494,6 +882,7 @@ static int omap_rproc_probe(struct platform_device *pdev)
        struct omap_rproc *oproc;
        struct rproc *rproc;
        const char *firmware;
+       u32 standby_addr = 0;
        int num_timers;
        int ret;
 
@@ -502,6 +891,16 @@ static int omap_rproc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       /*
+        * self-manage the ordering dependencies between omap_device_enable/idle
+        * and omap_device_assert/deassert_hardreset API during runtime suspend
+        * and resume, rather than relying on the order in omap_device layer.
+        */
+       if (pdev->dev.pm_domain) {
+               dev_dbg(&pdev->dev, "device pm_domain is being reset for this remoteproc device\n");
+               pdev->dev.pm_domain = NULL;
+       }
+
        if (!pdata || !pdata->device_enable || !pdata->device_shutdown) {
                dev_err(&pdev->dev, "platform data is either missing or incomplete\n");
                return -ENODEV;
@@ -583,6 +982,20 @@ static int omap_rproc_probe(struct platform_device *pdev)
                        oproc->num_timers, oproc->num_wd_timers);
        }
 
+       init_completion(&oproc->pm_comp);
+       oproc->autosuspend_delay = omap_rproc_get_autosuspend_delay(pdev);
+       if (oproc->autosuspend_delay < 0)
+               goto free_rproc;
+
+       ret = of_property_read_u32(np, "ti,rproc-standby-info", &standby_addr);
+       if (ret || !standby_addr)
+               goto free_rproc;
+
+       oproc->standby_addr = devm_ioremap(&pdev->dev, standby_addr,
+                                          sizeof(u32));
+       if (!oproc->standby_addr)
+               goto free_rproc;
+
        platform_set_drvdata(pdev, rproc);
 
        ret = rproc_add(rproc);
@@ -609,12 +1022,19 @@ static int omap_rproc_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct dev_pm_ops omap_rproc_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(omap_rproc_suspend, omap_rproc_resume)
+       SET_RUNTIME_PM_OPS(omap_rproc_runtime_suspend,
+                          omap_rproc_runtime_resume, NULL)
+};
+
 static struct platform_driver omap_rproc_driver = {
        .probe = omap_rproc_probe,
        .remove = omap_rproc_remove,
        .driver = {
                .name = "omap-rproc",
                .owner = THIS_MODULE,
+               .pm = &omap_rproc_pm_ops,
                .of_match_table = of_match_ptr(omap_rproc_of_match),
        },
 };
index 72f656c93caa63e2378f8ef5d3b6dd93ff9008cb..9ca3281ee7bb08f266f13ce300fda39b9e4be361 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Remote processor messaging
  *
- * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011-2015 Texas Instruments, Inc.
  * Copyright (C) 2011 Google, Inc.
  * All rights reserved.
  *
  * @RP_MBOX_ABORT_REQUEST: a "please crash" request, used for testing the
  * recovery mechanism (to some extent).
  *
+ * @RP_MBOX_SUSPEND_AUTO: auto suspend request for the remote processor
+ *
+ * @RP_MBOX_SUSPEND_SYSTEM: system suspend request for the remote processor
+ *
+ * @RP_MBOX_SUSPEND_ACK: successful response from remote processor for a
+ * suspend request
+ *
+ * @RP_MBOX_SUSPEND_CANCEL: a cancel suspend response from a remote processor
+ * on a suspend request
+ *
  * Introduce new message definitions if any here.
  *
  * @RP_MBOX_END_MSG: Indicates end of known/defined messages from remote core
@@ -70,7 +80,11 @@ enum omap_rp_mbox_messages {
        RP_MBOX_ECHO_REQUEST    = 0xFFFFFF03,
        RP_MBOX_ECHO_REPLY      = 0xFFFFFF04,
        RP_MBOX_ABORT_REQUEST   = 0xFFFFFF05,
-       RP_MBOX_END_MSG         = 0xFFFFFF06,
+       RP_MBOX_SUSPEND_AUTO    = 0xFFFFFF10,
+       RP_MBOX_SUSPEND_SYSTEM  = 0xFFFFFF11,
+       RP_MBOX_SUSPEND_ACK     = 0xFFFFFF12,
+       RP_MBOX_SUSPEND_CANCEL  = 0xFFFFFF13,
+       RP_MBOX_END_MSG         = 0xFFFFFF14,
 };
 
 #endif /* _OMAP_RPMSG_H */
index b6fdb51895e994fc59736e216f067d121ede1950..3e374a06562cf58ec7e0404c3c1ebd3ecdff56fa 100644 (file)
@@ -589,7 +589,7 @@ static void pru_rproc_mbox_callback(struct mbox_client *client, void *data)
 
        /* msg contains the index of the triggered vring */
        if (rproc_vq_interrupt(pru->rproc, msg) == IRQ_NONE)
-               dev_err(dev, "no message was found in vqid %d\n", msg);
+               dev_dbg(dev, "no message was found in vqid %d\n", msg);
 }
 
 /* kick a virtqueue */
@@ -603,7 +603,7 @@ static void pru_rproc_kick(struct rproc *rproc, int vq_id)
 
        /* send the index of the triggered virtqueue in the mailbox payload */
        ret = mbox_send_message(pru->mbox, (void *)vq_id);
-       if (ret)
+       if (ret < 0)
                dev_err(dev, "mbox_send_message failed: %d\n", ret);
 }
 
@@ -1371,7 +1371,7 @@ static int __init pruss_init(void)
                platform_driver_unregister(&pruss_driver);
        }
 
-       return 0;
+       return ret;
 }
 module_init(pruss_init);
 
index b36c6d34173f31c85ff193bb1581d211a650410b..5655bc85b631b38e49be2eb950b6b97d0082efc1 100644 (file)
@@ -770,8 +770,10 @@ static ssize_t rppc_read(struct file *filp, char __user *buf, size_t len,
        function = rppc_find_fxn(rpc, packet->msg_id);
        if (function && function->num_translations > 0) {
                ret = rppc_xlate_buffers(rpc, function, RPPC_RPA_TO_UVA);
-               if (ret < 0)
+               if (ret < 0) {
+                       dev_err(rpc->dev, "failed to translate back pointers from remote core!\n");
                        goto failure;
+               }
        }
        returned.fxn_id = RPPC_FXN_MASK(packet->fxn_id);
        returned.status = packet->result;
index 39b822135a8f5dc9aedd6f53a505291de1806786..3f4152804867384f2ab286c497a7c327d5625428 100644 (file)
@@ -481,7 +481,7 @@ int rppc_xlate_buffers(struct rppc_instance *rpc, struct rppc_function *func,
        int i, limit, inc = 1;
        virt_addr_t kva, uva, buva;
        phys_addr_t rda;
-       int ret = 0;
+       int ret = 0, final_ret = 0;
        int xlate_fd;
 
        limit = func->num_translations;
@@ -638,6 +638,12 @@ unwind:
                        dev_err(dev, "error during UVA to RDA translations!! current translation = %d\n",
                                i);
                }
+               /*
+                * store away the return value to return back to caller
+                * in case of an error, record only the first error
+                */
+               if (!final_ret)
+                       final_ret = ret;
        }
 
        /*
@@ -650,5 +656,5 @@ unwind:
                mutex_unlock(&rpc->lock);
        }
 
-       return ret;
+       return final_ret;
 }
index fbcbe52c5cc2f7b361abd19622d4ffa3f7e0b212..f59b66318f3776f49fb4d5d24e85b9a34685d158 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/io.h>
+#include <linux/regulator/machine.h>
 
 /* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock
  * with century-range alarm matching, driven by the 32kHz clock.
 #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN        BIT(1)
 
 /* OMAP_RTC_PMIC_REG bit fields: */
+#define OMAP_RTC_PMIC_EXT_WAKEUP_EN    (1<<0)
+#define OMAP_RTC_PMIC_EXT_WAKEUP_POL   (1<<4)
+#define OMAP_RTC_PMIC_EXT_WAKEUP_STS   (1<<12)
 #define OMAP_RTC_PMIC_POWER_EN_EN       (1<<16)
 
 /* OMAP_RTC_KICKER values */
@@ -152,6 +156,11 @@ static void __iomem        *rtc_base;
 
 #define rtc_writel(val, addr)  writel(val, rtc_base + (addr))
 
+struct omap_rtc_plat_data {
+       void __iomem *base;
+       bool is_power_controller;
+       struct rtc_device *rtc;
+};
 
 /* we rely on the rtc framework to handle locking (rtc->ops_lock),
  * so the only other requirement is that register accesses which
@@ -444,11 +453,15 @@ static void rtc_power_off(void)
 {
        u32 val;
 
+       regulator_suspend_prepare(PM_SUSPEND_MAX);
+
        omap_rtc_power_off_program();
 
-       /* Set PMIC power enable */
+       /* Set PMIC power enable and EXT_WAKEUP in case PB power on is used */
        val = readl(rtc_base + OMAP_RTC_PMIC_REG);
-       writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base + OMAP_RTC_PMIC_REG);
+       val |= OMAP_RTC_PMIC_POWER_EN_EN | OMAP_RTC_PMIC_EXT_WAKEUP_POL |
+              OMAP_RTC_PMIC_EXT_WAKEUP_EN;
+       writel(val, rtc_base + OMAP_RTC_PMIC_REG);
 
        /* Wait 1 second for power-off, if we are still alive, bail out */
        for (val = 0; val < 1000; val++)
@@ -507,15 +520,22 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
        struct resource         *res;
        struct rtc_device       *rtc;
        u8                      reg, new_ctrl;
-       bool                    pm_off = false;
        const struct platform_device_id *id_entry;
        const struct of_device_id *of_id;
+       struct omap_rtc_plat_data *pdata;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, pdata);
 
        of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
        if (of_id) {
                pdev->id_entry = of_id->data;
-               pm_off = of_property_read_bool(pdev->dev.of_node,
-                                       "ti,system-power-controller");
+               pdata->is_power_controller =
+                       of_property_read_bool(pdev->dev.of_node,
+                                             "ti,system-power-controller");
        }
 
        id_entry = platform_get_device_id(pdev);
@@ -557,10 +577,11 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
                        pdev->name, PTR_ERR(rtc));
                goto fail0;
        }
-       platform_set_drvdata(pdev, rtc);
+
+       pdata->rtc = rtc;
 
        /* RTC power off */
-       if (pm_off && !pm_power_off)
+       if (pdata->is_power_controller && !pm_power_off)
                pm_power_off = rtc_power_off;
 
        /* clear pending irqs, and set 1/second periodic,
@@ -579,7 +600,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 
        /* clear old status */
        reg = rtc_read(OMAP_RTC_STATUS_REG);
-       if (!pm_off) {
+       if (!pdata->is_power_controller) {
                /* For RTCs with power off capability, this bit is redefined */
                if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
                        pr_info("%s: RTC power up reset detected\n",
@@ -707,7 +728,12 @@ static SIMPLE_DEV_PM_OPS(omap_rtc_pm_ops, omap_rtc_suspend, omap_rtc_resume);
 
 static void omap_rtc_shutdown(struct platform_device *pdev)
 {
-       rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+       struct omap_rtc_plat_data *pdata;
+
+       pdata = platform_get_drvdata(pdev);
+
+       if (!pdata->is_power_controller)
+               rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
 }
 
 MODULE_ALIAS("platform:omap_rtc");
index 0a7325361d2958dceeae99da5959e518f8490985..5f57e3d35e26d4aad0e3620759e7ee253bccce92 100644 (file)
@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
 static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
 static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
 
 /* Functions */
 
@@ -1352,11 +1351,11 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
                                }
 
                                /* Now complete the io */
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                                tw_dev->state[request_id] = TW_S_COMPLETED;
                                twa_free_request_id(tw_dev, request_id);
                                tw_dev->posted_request_count--;
-                               tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                               twa_unmap_scsi_data(tw_dev, request_id);
                        }
 
                        /* Check for valid status after each drain */
@@ -1414,26 +1413,6 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm
        }
 } /* End twa_load_sgl() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twa_map_scsi_sg_data() */
-
 /* This function will poll for a response interrupt of a request */
 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
 {
@@ -1612,9 +1591,11 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
                        if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twa_unmap_scsi_data(tw_dev, i);
+                               struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                               cmd->result = (DID_RESET << 16);
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1793,21 +1774,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        switch (retval) {
        case SCSI_MLQUEUE_HOST_BUSY:
+               scsi_dma_unmap(SCpnt);
                twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                break;
        case 1:
-               tw_dev->state[request_id] = TW_S_COMPLETED;
-               twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                SCpnt->result = (DID_ERROR << 16);
+               scsi_dma_unmap(SCpnt);
                done(SCpnt);
+               tw_dev->state[request_id] = TW_S_COMPLETED;
+               twa_free_request_id(tw_dev, request_id);
                retval = 0;
        }
 out:
@@ -1875,8 +1853,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                                command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
                                command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
                        } else {
-                               sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
-                               if (sg_count == 0)
+                               sg_count = scsi_dma_map(srb);
+                               if (sg_count < 0)
                                        goto out;
 
                                scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1991,15 +1969,6 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code)
        return(table[index].text);
 } /* End twa_string_lookup() */
 
-/* This function will perform a pci-dma unmap */
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twa_unmap_scsi_data() */
-
 /* This function gets called when a disk is coming on-line */
 static int twa_slave_configure(struct scsi_device *sdev)
 {
index 040f7214e5b7a5c3782743a4a66a456aea79df81..0fdc83cfa0e1a28a42757ae52f434523238075b3 100644 (file)
@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[] = {
 #define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SINGLE  1
-#define TW_PHASE_SGLIST  2
-
 /* Misc defines */
 #define TW_9550SX_DRAIN_COMPLETED            0xFFFF
 #define TW_SECTOR_SIZE                        512
index 4de346017e9ff91b43aed80d48231ac60f23a4e3..61702ac00d42f3632eec2e9a310d03d59667c5e2 100644 (file)
@@ -303,26 +303,6 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
        return 0;
 } /* End twl_post_command_packet() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twl_map_scsi_sg_data() */
-
 /* This function hands scsi cdb's to the firmware */
 static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
 {
@@ -370,8 +350,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
        if (!sglistarg) {
                /* Map sglist from scsi layer to cmd packet */
                if (scsi_sg_count(srb)) {
-                       sg_count = twl_map_scsi_sg_data(tw_dev, request_id);
-                       if (sg_count == 0)
+                       sg_count = scsi_dma_map(srb);
+                       if (sg_count <= 0)
                                goto out;
 
                        scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1116,15 +1096,6 @@ out:
        return retval;
 } /* End twl_initialize_device_extension() */
 
-/* This function will perform a pci-dma unmap */
-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twl_unmap_scsi_data() */
-
 /* This function will handle attention interrupts */
 static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
 {
@@ -1265,11 +1236,11 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance)
                        }
 
                        /* Now complete the io */
+                       scsi_dma_unmap(cmd);
+                       cmd->scsi_done(cmd);
                        tw_dev->state[request_id] = TW_S_COMPLETED;
                        twl_free_request_id(tw_dev, request_id);
                        tw_dev->posted_request_count--;
-                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                       twl_unmap_scsi_data(tw_dev, request_id);
                }
 
                /* Check for another response interrupt */
@@ -1414,10 +1385,12 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res
                if ((tw_dev->state[i] != TW_S_FINISHED) &&
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
-                       if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twl_unmap_scsi_data(tw_dev, i);
+                       struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                       if (cmd) {
+                               cmd->result = (DID_RESET << 16);
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1521,9 +1494,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        if (retval) {
                tw_dev->state[request_id] = TW_S_COMPLETED;
index d474892701d4540658a36b48edb7b903a8b9ba76..fec6449c7595132f706439277cd396b4dc66c0a8 100644 (file)
@@ -103,10 +103,6 @@ static char *twl_aen_severity_table[] =
 #define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SGLIST  2
-
 /* Misc defines */
 #define TW_SECTOR_SIZE                        512
 #define TW_MAX_UNITS                         32
index 752624e6bc0022807c6265539cad6d8b42d1611f..b327742b95ef82e31ecd09a5193f48772b235970 100644 (file)
@@ -1284,32 +1284,6 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
        return 0;
 } /* End tw_initialize_device_extension() */
 
-static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       int use_sg;
-
-       dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
-
-       use_sg = scsi_dma_map(cmd);
-       if (use_sg < 0) {
-               printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End tw_map_scsi_sg_data() */
-
-static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End tw_unmap_scsi_data() */
-
 /* This function will reset a device extension */
 static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
 {
@@ -1332,8 +1306,8 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
                        srb = tw_dev->srb[i];
                        if (srb != NULL) {
                                srb->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
+                               scsi_dma_unmap(srb);
+                               srb->scsi_done(srb);
                        }
                }
        }
@@ -1780,8 +1754,8 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
        command_packet->byte8.io.lba = lba;
        command_packet->byte6.block_count = num_sectors;
 
-       use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
-       if (!use_sg)
+       use_sg = scsi_dma_map(srb);
+       if (use_sg <= 0)
                return 1;
 
        scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
@@ -1968,9 +1942,6 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        switch (*command) {
                case READ_10:
                case READ_6:
@@ -2198,12 +2169,11 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance)
 
                                /* Now complete the io */
                                if ((error != TW_ISR_DONT_COMPLETE)) {
+                                       scsi_dma_unmap(tw_dev->srb[request_id]);
+                                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
                                        tw_dev->state[request_id] = TW_S_COMPLETED;
                                        tw_state_request_finish(tw_dev, request_id);
                                        tw_dev->posted_request_count--;
-                                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                                       
-                                       tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
                                }
                        }
                                
index 49dcf03c631a52f971170d6ee029083a69edab34..1d31858766ce4b7e0fda8b569fed1850208c72c3 100644 (file)
@@ -195,11 +195,6 @@ static unsigned char tw_sense_table[][4] =
 #define TW_AEN_SMART_FAIL        0x000F
 #define TW_AEN_SBUF_FAIL         0x0024
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SINGLE 1
-#define TW_PHASE_SGLIST 2
-
 /* Misc defines */
 #define TW_ALIGNMENT_6000                    64 /* 64 bytes */
 #define TW_ALIGNMENT_7000                     4  /* 4 bytes */
index 5642a9b250c2fe11201510460563ec576c70461c..19ddd43a00cfe26cb35d8b5e37f742cd931b8dd2 100644 (file)
@@ -581,7 +581,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)
                        "beiscsi_hba_alloc - iscsi_host_alloc failed\n");
                return NULL;
        }
-       shost->dma_boundary = pcidev->dma_mask;
        shost->max_id = BE2_MAX_SESSIONS;
        shost->max_channel = 0;
        shost->max_cmd_len = BEISCSI_MAX_CMD_LEN;
@@ -5685,9 +5684,9 @@ free_port:
 hba_free:
        if (phba->msix_enabled)
                pci_disable_msix(phba->pcidev);
-       iscsi_host_remove(phba->shost);
        pci_dev_put(phba->pcidev);
        iscsi_host_free(phba->shost);
+       pci_set_drvdata(pcidev, NULL);
 disable_pci:
        pci_disable_device(pcidev);
        return ret;
index 65180e15de6ebfb6797cff83cab776a0e5e8e314..50c75e1fbf8a0e17e6b6bc4f8a5f1e7e725b7b7b 100644 (file)
@@ -7006,7 +7006,7 @@ bfa_flash_sem_get(void __iomem *bar)
        while (!bfa_raw_sem_get(bar)) {
                if (--n <= 0)
                        return BFA_STATUS_BADFLASH;
-               udelay(10000);
+               mdelay(10);
        }
        return BFA_STATUS_OK;
 }
index 62b58d38ce2e63beda6d1ba4d9876c9af2e51008..60de66252fa2b9ea168648c5097da7f8ae7f49ae 100644 (file)
@@ -500,6 +500,7 @@ static void sas_revalidate_domain(struct work_struct *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;
+       struct domain_device *ddev = port->port_dev;
 
        /* prevent revalidation from finding sata links in recovery */
        mutex_lock(&ha->disco_mutex);
@@ -514,8 +515,9 @@ static void sas_revalidate_domain(struct work_struct *work)
        SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id,
                    task_pid_nr(current));
 
-       if (port->port_dev)
-               res = sas_ex_revalidate_domain(port->port_dev);
+       if (ddev && (ddev->dev_type == SAS_FANOUT_EXPANDER_DEVICE ||
+                    ddev->dev_type == SAS_EDGE_EXPANDER_DEVICE))
+               res = sas_ex_revalidate_domain(ddev);
 
        SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n",
                    port->id, task_pid_nr(current), res);
index 6c1f223a8e1d335fa7c86a374e470e666e848906..4c0b8b4e1d407489afbff23876fecb40283c9e50 100644 (file)
@@ -441,14 +441,11 @@ static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag)
 static int mvs_task_prep_ata(struct mvs_info *mvi,
                             struct mvs_task_exec_info *tei)
 {
-       struct sas_ha_struct *sha = mvi->sas;
        struct sas_task *task = tei->task;
        struct domain_device *dev = task->dev;
        struct mvs_device *mvi_dev = dev->lldd_dev;
        struct mvs_cmd_hdr *hdr = tei->hdr;
        struct asd_sas_port *sas_port = dev->port;
-       struct sas_phy *sphy = dev->phy;
-       struct asd_sas_phy *sas_phy = sha->sas_phy[sphy->number];
        struct mvs_slot_info *slot;
        void *buf_prd;
        u32 tag = tei->tag, hdr_tag;
@@ -468,7 +465,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
        slot->tx = mvi->tx_prod;
        del_q = TXQ_MODE_I | tag |
                (TXQ_CMD_STP << TXQ_CMD_SHIFT) |
-               (MVS_PHY_ID << TXQ_PHY_SHIFT) |
+               ((sas_port->phy_mask & TXQ_PHY_MASK) << TXQ_PHY_SHIFT) |
                (mvi_dev->taskfileset << TXQ_SRS_SHIFT);
        mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q);
 
index 9d81f7693f99e5349d3394384ae5d87342014f1c..1817f3f2b02d50565fe2794ff96bcd358b3fd7a7 100644 (file)
@@ -1515,7 +1515,7 @@ static int tcm_qla2xxx_check_initiator_node_acl(
        /*
         * Finally register the new FC Nexus with TCM
         */
-       __transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess);
+       transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess);
 
        return 0;
 }
index 64e487a8bf59144a4877d7a773fbc23852cb5231..719bd8257520e4a3aa864b108cfdbe375cf1db7d 100644 (file)
@@ -1258,9 +1258,11 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
                                    "rejecting I/O to dead device\n");
                        ret = BLKPREP_KILL;
                        break;
-               case SDEV_QUIESCE:
                case SDEV_BLOCK:
                case SDEV_CREATED_BLOCK:
+                       ret = BLKPREP_DEFER;
+                       break;
+               case SDEV_QUIESCE:
                        /*
                         * If the devices is blocked we defer normal commands.
                         */
index df5e961484e108312f6f01765882dd4319d584f7..eb81c98386b9d59a0bde9f828ee141b0c884bd2d 100644 (file)
@@ -522,7 +522,7 @@ static ssize_t
 sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
 {
        sg_io_hdr_t *hp = &srp->header;
-       int err = 0;
+       int err = 0, err2;
        int len;
 
        if (count < SZ_SG_IO_HDR) {
@@ -551,8 +551,8 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
                goto err_out;
        }
 err_out:
-       err = sg_finish_rem_req(srp);
-       return (0 == err) ? count : err;
+       err2 = sg_finish_rem_req(srp);
+       return err ? : err2 ? : count;
 }
 
 static ssize_t
index 86b05151fdab3906353a3c55f54abdbe283b8c2d..97892f258043f4ba04998b1f4d6b72e36ffca239 100644 (file)
@@ -739,21 +739,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
                        if (bounce_sgl[j].length == PAGE_SIZE) {
                                /* full..move to next entry */
                                sg_kunmap_atomic(bounce_addr);
+                               bounce_addr = 0;
                                j++;
+                       }
 
-                               /* if we need to use another bounce buffer */
-                               if (srclen || i != orig_sgl_count - 1)
-                                       bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+                       /* if we need to use another bounce buffer */
+                       if (srclen && bounce_addr == 0)
+                               bounce_addr = sg_kmap_atomic(bounce_sgl, j);
 
-                       } else if (srclen == 0 && i == orig_sgl_count - 1) {
-                               /* unmap the last bounce that is < PAGE_SIZE */
-                               sg_kunmap_atomic(bounce_addr);
-                       }
                }
 
                sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
        }
 
+       if (bounce_addr)
+               sg_kunmap_atomic(bounce_addr);
+
        local_irq_restore(flags);
 
        return total_copied;
index 5d7b07f083266e64ab0d91436c10ae89a9ec112c..5f8c6d2f4df7307832383bf9fe402ce6ca2b4097 100644 (file)
@@ -781,17 +781,17 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
                        (unsigned long long)xfer->rx_dma);
        }
 
-       /* REVISIT: We're waiting for ENDRX before we start the next
+       /* REVISIT: We're waiting for RXBUFF before we start the next
         * transfer because we need to handle some difficult timing
-        * issues otherwise. If we wait for ENDTX in one transfer and
-        * then starts waiting for ENDRX in the next, it's difficult
-        * to tell the difference between the ENDRX interrupt we're
-        * actually waiting for and the ENDRX interrupt of the
+        * issues otherwise. If we wait for TXBUFE in one transfer and
+        * then starts waiting for RXBUFF in the next, it's difficult
+        * to tell the difference between the RXBUFF interrupt we're
+        * actually waiting for and the RXBUFF interrupt of the
         * previous transfer.
         *
         * It should be doable, though. Just not now...
         */
-       spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
+       spi_writel(as, IER, SPI_BIT(RXBUFF) | SPI_BIT(OVRES));
        spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
 }
 
index 971855e859c75c977816481fd90152b8f0af5443..fe091a87fd6d1f8a4dfcfad1e99f674ed232a8e5 100644 (file)
@@ -503,12 +503,12 @@ static void giveback(struct pl022 *pl022)
        pl022->cur_msg = NULL;
        pl022->cur_transfer = NULL;
        pl022->cur_chip = NULL;
-       spi_finalize_current_message(pl022->master);
 
        /* disable the SPI/SSP operation */
        writew((readw(SSP_CR1(pl022->virtbase)) &
                (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
 
+       spi_finalize_current_message(pl022->master);
 }
 
 /**
index fbf3b22efe5a245845866046f58ba33567bd9ade..d6563ec700d4f2c15001867edb28557162a56f53 100644 (file)
@@ -846,13 +846,14 @@ void spi_finalize_current_message(struct spi_master *master)
                                "failed to unprepare message: %d\n", ret);
                }
        }
+
+       trace_spi_message_done(mesg);
+
        master->cur_msg_prepared = false;
 
        mesg->state = NULL;
        if (mesg->complete)
                mesg->complete(mesg->context);
-
-       trace_spi_message_done(mesg);
 }
 EXPORT_SYMBOL_GPL(spi_finalize_current_message);
 
index d7c6e36021e884727f9bd0a7fc858d83824d441a..2fe5b61d886a71b792f4a74a12e3b7c0ab3e2a3b 100644 (file)
@@ -243,7 +243,10 @@ static int spidev_message(struct spidev_data *spidev,
                k_tmp->len = u_tmp->len;
 
                total += k_tmp->len;
-               if (total > bufsiz) {
+               /* Check total length of transfers.  Also check each
+                * transfer length to avoid arithmetic overflow.
+                */
+               if (total > bufsiz || k_tmp->len > bufsiz) {
                        status = -EMSGSIZE;
                        goto done;
                }
index 1e9da405d8332364c8984a0a7fa9008b965d442a..528781049ad5546beda8c03c16066299804b1663 100644 (file)
@@ -262,7 +262,7 @@ static int compat_cmd(struct file *file, unsigned long arg)
 {
        struct comedi_cmd __user *cmd;
        struct comedi32_cmd_struct __user *cmd32;
-       int rc;
+       int rc, err;
 
        cmd32 = compat_ptr(arg);
        cmd = compat_alloc_user_space(sizeof(*cmd));
@@ -271,7 +271,15 @@ static int compat_cmd(struct file *file, unsigned long arg)
        if (rc)
                return rc;
 
-       return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
+       rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
+       if (rc == -EAGAIN) {
+               /* Special case: copy cmd back to user. */
+               err = put_compat_cmd(cmd32, cmd);
+               if (err)
+                       rc = err;
+       }
+
+       return rc;
 }
 
 /* Handle 32-bit COMEDI_CMDTEST ioctl. */
index 4fff1738e3f8c2e45dbd0dfb534344663cd89f48..3d1cb5b0a956ee7b6f371635b116f4abecf5ee52 100644 (file)
@@ -441,6 +441,29 @@ static const struct comedi_lrange ai_ranges_64xx = {
        }
 };
 
+static const uint8_t ai_range_code_64xx[8] = {
+       0x0, 0x1, 0x2, 0x3,     /* bipolar 10, 5, 2,5, 1.25 */
+       0x8, 0x9, 0xa, 0xb      /* unipolar 10, 5, 2.5, 1.25 */
+};
+
+/* analog input ranges for 64-Mx boards */
+static const struct comedi_lrange ai_ranges_64_mx = {
+       7, {
+               BIP_RANGE(5),
+               BIP_RANGE(2.5),
+               BIP_RANGE(1.25),
+               BIP_RANGE(0.625),
+               UNI_RANGE(5),
+               UNI_RANGE(2.5),
+               UNI_RANGE(1.25)
+       }
+};
+
+static const uint8_t ai_range_code_64_mx[7] = {
+       0x0, 0x1, 0x2, 0x3,     /* bipolar 5, 2.5, 1.25, 0.625 */
+       0x9, 0xa, 0xb           /* unipolar 5, 2.5, 1.25 */
+};
+
 /* analog input ranges for 60xx boards */
 static const struct comedi_lrange ai_ranges_60xx = {
        4, {
@@ -451,6 +474,10 @@ static const struct comedi_lrange ai_ranges_60xx = {
        }
 };
 
+static const uint8_t ai_range_code_60xx[4] = {
+       0x0, 0x1, 0x4, 0x7      /* bipolar 10, 5, 0.5, 0.05 */
+};
+
 /* analog input ranges for 6030, etc boards */
 static const struct comedi_lrange ai_ranges_6030 = {
        14, {
@@ -471,6 +498,11 @@ static const struct comedi_lrange ai_ranges_6030 = {
        }
 };
 
+static const uint8_t ai_range_code_6030[14] = {
+       0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */
+       0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf  /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */
+};
+
 /* analog input ranges for 6052, etc boards */
 static const struct comedi_lrange ai_ranges_6052 = {
        15, {
@@ -492,6 +524,11 @@ static const struct comedi_lrange ai_ranges_6052 = {
        }
 };
 
+static const uint8_t ai_range_code_6052[15] = {
+       0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */
+       0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf       /* unipolar 10 ... 0.1 */
+};
+
 /* analog input ranges for 4020 board */
 static const struct comedi_lrange ai_ranges_4020 = {
        2, {
@@ -595,6 +632,7 @@ struct pcidas64_board {
        int ai_bits;            /*  analog input resolution */
        int ai_speed;           /*  fastest conversion period in ns */
        const struct comedi_lrange *ai_range_table;
+       const uint8_t *ai_range_code;
        int ao_nchan;           /*  number of analog out channels */
        int ao_bits;            /*  analog output resolution */
        int ao_scan_speed;      /*  analog output scan speed */
@@ -653,6 +691,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
                .ai_range_table = &ai_ranges_64xx,
+               .ai_range_code  = ai_range_code_64xx,
                .ao_range_table = &ao_ranges_64xx,
                .ao_range_code  = ao_range_code_64xx,
                .ai_fifo        = &ai_fifo_64xx,
@@ -668,6 +707,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
                .ai_range_table = &ai_ranges_64xx,
+               .ai_range_code  = ai_range_code_64xx,
                .ao_range_table = &ao_ranges_64xx,
                .ao_range_code  = ao_range_code_64xx,
                .ai_fifo        = &ai_fifo_64xx,
@@ -682,7 +722,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_bits        = 16,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ao_range_table = &ao_ranges_64xx,
                .ao_range_code  = ao_range_code_64xx,
                .ai_fifo        = &ai_fifo_64xx,
@@ -697,7 +738,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_bits        = 16,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ao_range_table = &ao_ranges_64xx,
                .ao_range_code  = ao_range_code_64xx,
                .ai_fifo        = &ai_fifo_64xx,
@@ -712,7 +754,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_bits        = 16,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ao_range_table = &ao_ranges_64xx,
                .ao_range_code  = ao_range_code_64xx,
                .ai_fifo        = &ai_fifo_64xx,
@@ -727,6 +770,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_bits        = 16,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_60xx,
+               .ai_range_code  = ai_range_code_60xx,
                .ao_range_table = &range_bipolar10,
                .ao_range_code  = ao_range_code_60xx,
                .ai_fifo        = &ai_fifo_60xx,
@@ -742,6 +786,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 100000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_60xx,
+               .ai_range_code  = ai_range_code_60xx,
                .ao_range_table = &range_bipolar10,
                .ao_range_code  = ao_range_code_60xx,
                .ai_fifo        = &ai_fifo_60xx,
@@ -756,6 +801,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 100000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_60xx,
+               .ai_range_code  = ai_range_code_60xx,
                .ao_range_table = &range_bipolar10,
                .ao_range_code  = ao_range_code_60xx,
                .ai_fifo        = &ai_fifo_60xx,
@@ -771,6 +817,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 100000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_60xx,
+               .ai_range_code  = ai_range_code_60xx,
                .ao_range_table = &range_bipolar10,
                .ao_range_code  = ao_range_code_60xx,
                .ai_fifo        = &ai_fifo_60xx,
@@ -786,6 +833,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_6030,
+               .ai_range_code  = ai_range_code_6030,
                .ao_range_table = &ao_ranges_6030,
                .ao_range_code  = ao_range_code_6030,
                .ai_fifo        = &ai_fifo_60xx,
@@ -801,6 +849,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_6030,
+               .ai_range_code  = ai_range_code_6030,
                .ao_range_table = &ao_ranges_6030,
                .ao_range_code  = ao_range_code_6030,
                .ai_fifo        = &ai_fifo_60xx,
@@ -814,6 +863,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_nchan       = 0,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_6030,
+               .ai_range_code  = ai_range_code_6030,
                .ai_fifo        = &ai_fifo_60xx,
                .has_8255       = 0,
        },
@@ -825,6 +875,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_nchan       = 0,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_6030,
+               .ai_range_code  = ai_range_code_6030,
                .ai_fifo        = &ai_fifo_60xx,
                .has_8255       = 0,
        },
@@ -837,6 +888,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 0,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_60xx,
+               .ai_range_code  = ai_range_code_60xx,
                .ai_fifo        = &ai_fifo_60xx,
                .has_8255       = 0,
        },
@@ -850,6 +902,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 100000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_60xx,
+               .ai_range_code  = ai_range_code_60xx,
                .ao_range_table = &range_bipolar10,
                .ao_range_code  = ao_range_code_60xx,
                .ai_fifo        = &ai_fifo_60xx,
@@ -865,6 +918,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 100000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_60xx,
+               .ai_range_code  = ai_range_code_60xx,
                .ao_range_table = &range_bipolar10,
                .ao_range_code  = ao_range_code_60xx,
                .ai_fifo        = &ai_fifo_60xx,
@@ -880,6 +934,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 1000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_6052,
+               .ai_range_code  = ai_range_code_6052,
                .ao_range_table = &ao_ranges_6030,
                .ao_range_code  = ao_range_code_6030,
                .ai_fifo        = &ai_fifo_60xx,
@@ -895,6 +950,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 3333,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_6052,
+               .ai_range_code  = ai_range_code_6052,
                .ao_range_table = &ao_ranges_6030,
                .ao_range_code  = ao_range_code_6030,
                .ai_fifo        = &ai_fifo_60xx,
@@ -910,6 +966,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 1000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_6052,
+               .ai_range_code  = ai_range_code_6052,
                .ao_range_table = &ao_ranges_6030,
                .ao_range_code  = ao_range_code_6030,
                .ai_fifo        = &ai_fifo_60xx,
@@ -925,6 +982,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 1000,
                .layout         = LAYOUT_60XX,
                .ai_range_table = &ai_ranges_6052,
+               .ai_range_code  = ai_range_code_6052,
                .ao_range_table = &ao_ranges_6030,
                .ao_range_code  = ao_range_code_6030,
                .ai_fifo        = &ai_fifo_60xx,
@@ -959,6 +1017,7 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
                .ai_range_table = &ai_ranges_64xx,
+               .ai_range_code  = ai_range_code_64xx,
                .ai_fifo        = ai_fifo_64xx,
                .has_8255       = 1,
        },
@@ -970,7 +1029,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_nchan       = 0,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ai_fifo        = ai_fifo_64xx,
                .has_8255       = 1,
        },
@@ -982,7 +1042,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_nchan       = 0,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ai_fifo        = ai_fifo_64xx,
                .has_8255       = 1,
        },
@@ -994,7 +1055,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_nchan       = 0,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ai_fifo        = ai_fifo_64xx,
                .has_8255       = 1,
        },
@@ -1006,7 +1068,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_nchan       = 2,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ai_fifo        = ai_fifo_64xx,
                .has_8255       = 1,
        },
@@ -1018,7 +1081,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_nchan       = 2,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ai_fifo        = ai_fifo_64xx,
                .has_8255       = 1,
        },
@@ -1030,7 +1094,8 @@ static const struct pcidas64_board pcidas64_boards[] = {
                .ao_nchan       = 2,
                .ao_scan_speed  = 10000,
                .layout         = LAYOUT_64XX,
-               .ai_range_table = &ai_ranges_64xx,
+               .ai_range_table = &ai_ranges_64_mx,
+               .ai_range_code  = ai_range_code_64_mx,
                .ai_fifo        = ai_fifo_64xx,
                .has_8255       = 1,
        },
@@ -1127,45 +1192,8 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
                                       unsigned int range_index)
 {
        const struct pcidas64_board *thisboard = comedi_board(dev);
-       const struct comedi_krange *range =
-               &thisboard->ai_range_table->range[range_index];
-       unsigned int bits = 0;
 
-       switch (range->max) {
-       case 10000000:
-               bits = 0x000;
-               break;
-       case 5000000:
-               bits = 0x100;
-               break;
-       case 2000000:
-       case 2500000:
-               bits = 0x200;
-               break;
-       case 1000000:
-       case 1250000:
-               bits = 0x300;
-               break;
-       case 500000:
-               bits = 0x400;
-               break;
-       case 200000:
-       case 250000:
-               bits = 0x500;
-               break;
-       case 100000:
-               bits = 0x600;
-               break;
-       case 50000:
-               bits = 0x700;
-               break;
-       default:
-               comedi_error(dev, "bug! in ai_range_bits_6xxx");
-               break;
-       }
-       if (range->min == 0)
-               bits += 0x900;
-       return bits;
+       return thisboard->ai_range_code[range_index] << 8;
 }
 
 static unsigned int hw_revision(const struct comedi_device *dev,
index 9ec1df9cff956b830e7a7ab64cde1858319de75e..27e1a6e62d069894345c6f0d085084b3ec34b31b 100644 (file)
@@ -214,11 +214,17 @@ struct mxs_lradc {
        unsigned long           is_divided;
 
        /*
-        * Touchscreen LRADC channels receives a private slot in the CTRL4
-        * register, the slot #7. Therefore only 7 slots instead of 8 in the
-        * CTRL4 register can be mapped to LRADC channels when using the
-        * touchscreen.
-        *
+        * When the touchscreen is enabled, we give it two private virtual
+        * channels: #6 and #7. This means that only 6 virtual channels (instead
+        * of 8) will be available for buffered capture.
+        */
+#define TOUCHSCREEN_VCHANNEL1          7
+#define TOUCHSCREEN_VCHANNEL2          6
+#define BUFFER_VCHANS_LIMITED          0x3f
+#define BUFFER_VCHANS_ALL              0xff
+       u8                      buffer_vchans;
+
+       /*
         * Furthermore, certain LRADC channels are shared between touchscreen
         * and/or touch-buttons and generic LRADC block. Therefore when using
         * either of these, these channels are not available for the regular
@@ -342,6 +348,9 @@ struct mxs_lradc {
 #define        LRADC_CTRL4                             0x140
 #define        LRADC_CTRL4_LRADCSELECT_MASK(n)         (0xf << ((n) * 4))
 #define        LRADC_CTRL4_LRADCSELECT_OFFSET(n)       ((n) * 4)
+#define        LRADC_CTRL4_LRADCSELECT(n, x) \
+                               (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \
+                               LRADC_CTRL4_LRADCSELECT_MASK(n))
 
 #define LRADC_RESOLUTION                       12
 #define LRADC_SINGLE_SAMPLE_MASK               ((1 << LRADC_RESOLUTION) - 1)
@@ -423,6 +432,14 @@ static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc)
                                        LRADC_STATUS_TOUCH_DETECT_RAW);
 }
 
+static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch,
+                                 unsigned ch)
+{
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch),
+                               LRADC_CTRL4);
+       mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4);
+}
+
 static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
 {
        /*
@@ -450,12 +467,8 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
                LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
                        LRADC_DELAY(3));
 
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
-                       LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
-                       LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1);
 
-       /* wake us again, when the complete conversion is done */
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
        /*
         * after changing the touchscreen plates setting
         * the signals need some initial time to settle. Start the
@@ -508,12 +521,8 @@ static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1,
                LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
                                        LRADC_DELAY(3));
 
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
-                       LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
-                       LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1);
 
-       /* wake us again, when the conversions are done */
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
        /*
         * after changing the touchscreen plates setting
         * the signals need some initial time to settle. Start the
@@ -578,36 +587,6 @@ static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc,
 #define TS_CH_XM 4
 #define TS_CH_YM 5
 
-static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
-{
-       u32 reg;
-       int val;
-
-       reg = readl(lradc->base + LRADC_CTRL1);
-
-       /* only channels 3 to 5 are of interest here */
-       if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP);
-       } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM);
-       } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM);
-       } else {
-               return -EIO;
-       }
-
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
-
-       return val;
-}
-
 /*
  * YP(open)--+-------------+
  *           |             |--+
@@ -651,7 +630,8 @@ static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_X;
-       mxs_lradc_setup_ts_channel(lradc, TS_CH_YP);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP);
+       mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1);
 }
 
 /*
@@ -672,7 +652,8 @@ static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_Y;
-       mxs_lradc_setup_ts_channel(lradc, TS_CH_XM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM);
+       mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1);
 }
 
 /*
@@ -693,7 +674,10 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_PRESSURE;
-       mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP);
+       mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2,
+                                               TOUCHSCREEN_VCHANNEL1);
 }
 
 static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
@@ -706,6 +690,19 @@ static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
 
+static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc)
+{
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
+                               LRADC_CTRL1);
+       mxs_lradc_reg_set(lradc,
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
+       /*
+        * start with the Y-pos, because it uses nearly the same plate
+        * settings like the touch detection
+        */
+       mxs_lradc_prepare_y_pos(lradc);
+}
+
 static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
 {
        input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos);
@@ -723,10 +720,12 @@ static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc)
         * start a dummy conversion to burn time to settle the signals
         * note: we are not interested in the conversion's value
         */
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5));
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1);
-       mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) |
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(TOUCHSCREEN_VCHANNEL1));
+       mxs_lradc_reg_clear(lradc,
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
+       mxs_lradc_reg_wrt(lradc,
+               LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) |
                LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */
                        LRADC_DELAY(2));
 }
@@ -758,59 +757,45 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
 
        /* if it is released, wait for the next touch via IRQ */
        lradc->cur_plate = LRADC_TOUCH;
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ |
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
 
 /* touchscreen's state machine */
 static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
 {
-       int val;
-
        switch (lradc->cur_plate) {
        case LRADC_TOUCH:
-               /*
-                * start with the Y-pos, because it uses nearly the same plate
-                * settings like the touch detection
-                */
-               if (mxs_lradc_check_touch_event(lradc)) {
-                       mxs_lradc_reg_clear(lradc,
-                                       LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-                                       LRADC_CTRL1);
-                       mxs_lradc_prepare_y_pos(lradc);
-               }
+               if (mxs_lradc_check_touch_event(lradc))
+                       mxs_lradc_start_touch_event(lradc);
                mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ,
                                        LRADC_CTRL1);
                return;
 
        case LRADC_SAMPLE_Y:
-               val = mxs_lradc_read_ts_channel(lradc);
-               if (val < 0) {
-                       mxs_lradc_enable_touch_detection(lradc); /* re-start */
-                       return;
-               }
-               lradc->ts_y_pos = val;
+               lradc->ts_y_pos = mxs_lradc_read_raw_channel(lradc,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_prepare_x_pos(lradc);
                return;
 
        case LRADC_SAMPLE_X:
-               val = mxs_lradc_read_ts_channel(lradc);
-               if (val < 0) {
-                       mxs_lradc_enable_touch_detection(lradc); /* re-start */
-                       return;
-               }
-               lradc->ts_x_pos = val;
+               lradc->ts_x_pos = mxs_lradc_read_raw_channel(lradc,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_prepare_pressure(lradc);
                return;
 
        case LRADC_SAMPLE_PRESSURE:
-               lradc->ts_pressure =
-                       mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+               lradc->ts_pressure = mxs_lradc_read_ts_pressure(lradc,
+                                                       TOUCHSCREEN_VCHANNEL2,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_complete_touch_event(lradc);
                return;
 
        case LRADC_SAMPLE_VALID:
-               val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
                mxs_lradc_finish_touch_event(lradc, 1);
                break;
        }
@@ -842,9 +827,9 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val)
         * used if doing raw sampling.
         */
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0),
                        LRADC_CTRL1);
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+       mxs_lradc_reg_clear(lradc, 0x1, LRADC_CTRL0);
 
        /* Enable / disable the divider per requirement */
        if (test_bit(chan, &lradc->is_divided))
@@ -1091,9 +1076,8 @@ static void mxs_lradc_disable_ts(struct mxs_lradc *lradc)
 {
        /* stop all interrupts from firing */
        mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
-               LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) |
-               LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5),
-               LRADC_CTRL1);
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
 
        /* Power-down touchscreen touch-detect circuitry. */
        mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
@@ -1159,25 +1143,30 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
        struct iio_dev *iio = data;
        struct mxs_lradc *lradc = iio_priv(iio);
        unsigned long reg = readl(lradc->base + LRADC_CTRL1);
+       uint32_t clr_irq = mxs_lradc_irq_mask(lradc);
        const uint32_t ts_irq_mask =
                LRADC_CTRL1_TOUCH_DETECT_IRQ |
-               LRADC_CTRL1_LRADC_IRQ(2) |
-               LRADC_CTRL1_LRADC_IRQ(3) |
-               LRADC_CTRL1_LRADC_IRQ(4) |
-               LRADC_CTRL1_LRADC_IRQ(5);
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2);
 
        if (!(reg & mxs_lradc_irq_mask(lradc)))
                return IRQ_NONE;
 
-       if (lradc->use_touchscreen && (reg & ts_irq_mask))
+       if (lradc->use_touchscreen && (reg & ts_irq_mask)) {
                mxs_lradc_handle_touch(lradc);
+               /* Make sure we don't clear the next conversion's interrupt. */
+               clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+                               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2));
+       }
 
-       if (iio_buffer_enabled(iio))
-               iio_trigger_poll(iio->trig, iio_get_time_ns());
-       else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
+       if (iio_buffer_enabled(iio)) {
+               if (reg & lradc->buffer_vchans)
+                       iio_trigger_poll(iio->trig, iio_get_time_ns());
+       } else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) {
                complete(&lradc->completion);
+       }
 
-       mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1);
 
        return IRQ_HANDLED;
 }
@@ -1288,9 +1277,10 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
        }
 
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-                                                       LRADC_CTRL1);
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+               mxs_lradc_reg_clear(lradc,
+                       lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
+                       LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0);
 
        for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
                ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
@@ -1323,10 +1313,11 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
        mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
                                        LRADC_DELAY_KICK, LRADC_DELAY(0));
 
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+       mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0);
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-                                       LRADC_CTRL1);
+               mxs_lradc_reg_clear(lradc,
+                       lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
+                       LRADC_CTRL1);
 
        kfree(lradc->buffer);
        mutex_unlock(&lradc->lock);
@@ -1352,7 +1343,7 @@ static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio,
        if (lradc->use_touchbutton)
                rsvd_chans++;
        if (lradc->use_touchscreen)
-               rsvd_chans++;
+               rsvd_chans += 2;
 
        /* Test for attempts to map channels with special mode of operation. */
        if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS))
@@ -1412,6 +1403,13 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
                .channel = 8,
                .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
        },
+       /* Hidden channel to keep indexes */
+       {
+               .type = IIO_TEMP,
+               .indexed = 1,
+               .scan_index = -1,
+               .channel = 9,
+       },
        MXS_ADC_CHAN(10, IIO_VOLTAGE),  /* VDDIO */
        MXS_ADC_CHAN(11, IIO_VOLTAGE),  /* VTH */
        MXS_ADC_CHAN(12, IIO_VOLTAGE),  /* VDDA */
@@ -1563,6 +1561,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 
        touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
 
+       if (touch_ret == 0)
+               lradc->buffer_vchans = BUFFER_VCHANS_LIMITED;
+       else
+               lradc->buffer_vchans = BUFFER_VCHANS_ALL;
+
        /* Grab all IRQ sources */
        for (i = 0; i < of_cfg->irq_count; i++) {
                lradc->irq[i] = platform_get_irq(pdev, i);
index cbd663ed030cfe1edb054516d1d0b2b7bf258fa0..19405ed56cabe7687f9507c3d23d2f4054244510 100644 (file)
@@ -278,7 +278,7 @@ void ll_invalidate_aliases(struct inode *inode)
               inode->i_ino, inode->i_generation, inode);
 
        ll_lock_dcache(inode);
-       ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
+       ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) {
                CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p "
                       "inode %p flags %d\n", dentry->d_name.len,
                       dentry->d_name.name, dentry, dentry->d_parent,
index 6cfdb9e4b74bf716a7bd3bcae91fc1f52eb7c018..5ae562ea95f7f1424cf520e5642c2debe866639e 100644 (file)
@@ -678,7 +678,7 @@ void lustre_dump_dentry(struct dentry *dentry, int recur)
                return;
 
        list_for_each(tmp, &dentry->d_subdirs) {
-               struct dentry *d = list_entry(tmp, struct dentry, d_u.d_child);
+               struct dentry *d = list_entry(tmp, struct dentry, d_child);
                lustre_dump_dentry(d, recur - 1);
        }
 }
index fc8d264f6c9a9a99d50b38a47a0e55514d5555d8..8e9a9e95b5cc4cdc61fd5a35f38b5f781353be8f 100644 (file)
@@ -175,14 +175,14 @@ static void ll_invalidate_negative_children(struct inode *dir)
        struct ll_d_hlist_node *p;
 
        ll_lock_dcache(dir);
-       ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_alias) {
+       ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (!list_empty(&dentry->d_subdirs)) {
                        struct dentry *child;
 
                        list_for_each_entry_safe(child, tmp_subdir,
                                                 &dentry->d_subdirs,
-                                                d_u.d_child) {
+                                                d_child) {
                                if (child->d_inode == NULL)
                                        d_lustre_invalidate(child, 1);
                        }
@@ -364,7 +364,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry)
        discon_alias = invalid_alias = NULL;
 
        ll_lock_dcache(inode);
-       ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
+       ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_u.d_alias) {
                LASSERT(alias != dentry);
 
                spin_lock(&alias->d_lock);
@@ -953,7 +953,7 @@ static void ll_get_child_fid(struct inode * dir, struct qstr *name,
 {
        struct dentry *parent, *child;
 
-       parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_alias);
+       parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_u.d_alias);
        child = d_lookup(parent, name);
        if (child) {
                if (child->d_inode)
index 93cbfbb7e7f7ba418fd5081a0edd92ed219e7342..6096771e24005b7372e36e801f02efbdeb1d826c 100644 (file)
@@ -642,7 +642,7 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio)
                return 0;
        }
 
-       if (cfio->fault.ft_flags & VM_FAULT_SIGBUS) {
+       if (cfio->fault.ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
                CDEBUG(D_PAGE, "got addr %p - SIGBUS\n", vmf->virtual_address);
                return -EFAULT;
        }
index ec4b1fd1402199563cf294d000f08e41a8ab03a8..790e12e0f5248e4fbbeb3661b6db3c970d2c32bc 100644 (file)
@@ -275,11 +275,11 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
  * LCD types
  */
 #define LCD_TYPE_NONE          0
-#define LCD_TYPE_OLD           1
-#define LCD_TYPE_KS0074                2
-#define LCD_TYPE_HANTRONIX     3
-#define LCD_TYPE_NEXCOM                4
-#define LCD_TYPE_CUSTOM                5
+#define LCD_TYPE_CUSTOM                1
+#define LCD_TYPE_OLD           2
+#define LCD_TYPE_KS0074                3
+#define LCD_TYPE_HANTRONIX     4
+#define LCD_TYPE_NEXCOM                5
 
 /*
  * keypad types
@@ -457,8 +457,7 @@ MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
 static int lcd_type = -1;
 module_param(lcd_type, int, 0000);
 MODULE_PARM_DESC(lcd_type,
-                "LCD type: 0=none, 1=old //, 2=serial ks0074, "
-                "3=hantronix //, 4=nexcom //, 5=compiled-in");
+               "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom");
 
 static int lcd_proto = -1;
 module_param(lcd_proto, int, 0000);
index edb1b2768b17353bc93aed5a82f929b91fb78499..dbd9d44919acccc178bdd3701b13e3b6e4f691a4 100644 (file)
@@ -936,6 +936,7 @@ bool RFbSetPower(
                break;
        case RATE_6M:
        case RATE_9M:
+       case RATE_12M:
        case RATE_18M:
                byPwr = pDevice->abyOFDMPwrTbl[uCH];
                if (pDevice->byRFType == RF_UW2452) {
index 1e8f64bff03c665046c8b51b72bb1cf5809e3aa3..2dc48d4ff4336c72876248045c9cac927eb7cd8f 100644 (file)
@@ -752,6 +752,7 @@ int RFbSetPower(struct vnt_private *priv, u32 rate, u32 channel)
                break;
        case RATE_6M:
        case RATE_9M:
+       case RATE_12M:
        case RATE_18M:
        case RATE_24M:
        case RATE_36M:
index 104f29e6b290ed884c0d58a869e468ad58607c77..b61c555a5a8fbf9b436d418410c5391cc54495e8 100644 (file)
@@ -1165,7 +1165,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * traditional iSCSI block I/O.
         */
        if (iscsit_allocate_iovecs(cmd) < 0) {
-               return iscsit_add_reject_cmd(cmd,
+               return iscsit_reject_cmd(cmd,
                                ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
        }
        immed_data = cmd->immediate_data;
@@ -4196,11 +4196,17 @@ int iscsit_close_connection(
        pr_debug("Closing iSCSI connection CID %hu on SID:"
                " %u\n", conn->cid, sess->sid);
        /*
-        * Always up conn_logout_comp just in case the RX Thread is sleeping
-        * and the logout response never got sent because the connection
-        * failed.
+        * Always up conn_logout_comp for the traditional TCP case just in case
+        * the RX Thread in iscsi_target_rx_opcode() is sleeping and the logout
+        * response never got sent because the connection failed.
+        *
+        * However for iser-target, isert_wait4logout() is using conn_logout_comp
+        * to signal logout response TX interrupt completion.  Go ahead and skip
+        * this for iser since isert_rx_opcode() does not wait on logout failure,
+        * and to avoid iscsi_conn pointer dereference in iser-target code.
         */
-       complete(&conn->conn_logout_comp);
+       if (conn->conn_transport->transport_type == ISCSI_TCP)
+               complete(&conn->conn_logout_comp);
 
        iscsi_release_thread_set(conn);
 
index 26ae6886ac59d0890bf778144ce79934978b7cac..093b8cb85de72c91cfbd1dd9e11718c11128edf6 100644 (file)
@@ -1591,8 +1591,6 @@ int target_configure_device(struct se_device *dev)
        ret = dev->transport->configure_device(dev);
        if (ret)
                goto out;
-       dev->dev_flags |= DF_CONFIGURED;
-
        /*
         * XXX: there is not much point to have two different values here..
         */
@@ -1654,6 +1652,8 @@ int target_configure_device(struct se_device *dev)
        list_add_tail(&dev->g_dev_node, &g_device_list);
        mutex_unlock(&g_device_mutex);
 
+       dev->dev_flags |= DF_CONFIGURED;
+
        return 0;
 
 out_free_alua:
index 41eff7d64cb8878bd4a7a42acbf1a13c9f141b70..b199f1e21d0e67fbf7df63118843ea2c8e0dc396 100644 (file)
@@ -263,40 +263,32 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot,
        struct se_device *se_dev = cmd->se_dev;
        struct fd_dev *dev = FD_DEV(se_dev);
        struct file *prot_fd = dev->fd_prot_file;
-       struct scatterlist *sg;
        loff_t pos = (cmd->t_task_lba * se_dev->prot_length);
        unsigned char *buf;
-       u32 prot_size, len, size;
-       int rc, ret = 1, i;
+       u32 prot_size;
+       int rc, ret = 1;
 
        prot_size = (cmd->data_length / se_dev->dev_attrib.block_size) *
                     se_dev->prot_length;
 
        if (!is_write) {
-               fd_prot->prot_buf = vzalloc(prot_size);
+               fd_prot->prot_buf = kzalloc(prot_size, GFP_KERNEL);
                if (!fd_prot->prot_buf) {
                        pr_err("Unable to allocate fd_prot->prot_buf\n");
                        return -ENOMEM;
                }
                buf = fd_prot->prot_buf;
 
-               fd_prot->prot_sg_nents = cmd->t_prot_nents;
-               fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist) *
-                                          fd_prot->prot_sg_nents, GFP_KERNEL);
+               fd_prot->prot_sg_nents = 1;
+               fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist),
+                                          GFP_KERNEL);
                if (!fd_prot->prot_sg) {
                        pr_err("Unable to allocate fd_prot->prot_sg\n");
-                       vfree(fd_prot->prot_buf);
+                       kfree(fd_prot->prot_buf);
                        return -ENOMEM;
                }
-               size = prot_size;
-
-               for_each_sg(fd_prot->prot_sg, sg, fd_prot->prot_sg_nents, i) {
-
-                       len = min_t(u32, PAGE_SIZE, size);
-                       sg_set_buf(sg, buf, len);
-                       size -= len;
-                       buf += len;
-               }
+               sg_init_table(fd_prot->prot_sg, fd_prot->prot_sg_nents);
+               sg_set_buf(fd_prot->prot_sg, buf, prot_size);
        }
 
        if (is_write) {
@@ -317,7 +309,7 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot,
 
        if (is_write || ret < 0) {
                kfree(fd_prot->prot_sg);
-               vfree(fd_prot->prot_buf);
+               kfree(fd_prot->prot_buf);
        }
 
        return ret;
@@ -652,11 +644,11 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                                                 0, fd_prot.prot_sg, 0);
                        if (rc) {
                                kfree(fd_prot.prot_sg);
-                               vfree(fd_prot.prot_buf);
+                               kfree(fd_prot.prot_buf);
                                return rc;
                        }
                        kfree(fd_prot.prot_sg);
-                       vfree(fd_prot.prot_buf);
+                       kfree(fd_prot.prot_buf);
                }
        } else {
                memset(&fd_prot, 0, sizeof(struct fd_prot));
@@ -672,7 +664,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                                                  0, fd_prot.prot_sg, 0);
                        if (rc) {
                                kfree(fd_prot.prot_sg);
-                               vfree(fd_prot.prot_buf);
+                               kfree(fd_prot.prot_buf);
                                return rc;
                        }
                }
@@ -703,7 +695,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 
        if (ret < 0) {
                kfree(fd_prot.prot_sg);
-               vfree(fd_prot.prot_buf);
+               kfree(fd_prot.prot_buf);
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
 
index 1205dbd4f83d96dcf7a0b5692f2a46bddd6b053e..70cb37516d407bc611bce32f6cd42c3efa8997be 100644 (file)
@@ -76,7 +76,7 @@ enum preempt_type {
 };
 
 static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *,
-                       struct t10_pr_registration *, int);
+                                             struct t10_pr_registration *, int, int);
 
 static sense_reason_t
 target_scsi2_reservation_check(struct se_cmd *cmd)
@@ -528,6 +528,18 @@ static int core_scsi3_pr_seq_non_holder(
 
                        return 0;
                }
+       } else if (we && registered_nexus) {
+               /*
+                * Reads are allowed for Write Exclusive locks
+                * from all registrants.
+                */
+               if (cmd->data_direction == DMA_FROM_DEVICE) {
+                       pr_debug("Allowing READ CDB: 0x%02x for %s"
+                               " reservation\n", cdb[0],
+                               core_scsi3_pr_dump_type(pr_reg_type));
+
+                       return 0;
+               }
        }
        pr_debug("%s Conflict for %sregistered nexus %s CDB: 0x%2x"
                " for %s reservation\n", transport_dump_cmd_direction(cmd),
@@ -1186,7 +1198,7 @@ static int core_scsi3_check_implicit_release(
                 *    service action with the SERVICE ACTION RESERVATION KEY
                 *    field set to zero (see 5.7.11.3).
                 */
-               __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0);
+               __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0, 1);
                ret = 1;
                /*
                 * For 'All Registrants' reservation types, all existing
@@ -1228,7 +1240,8 @@ static void __core_scsi3_free_registration(
 
        pr_reg->pr_reg_deve->def_pr_registered = 0;
        pr_reg->pr_reg_deve->pr_res_key = 0;
-       list_del(&pr_reg->pr_reg_list);
+       if (!list_empty(&pr_reg->pr_reg_list))
+               list_del(&pr_reg->pr_reg_list);
        /*
         * Caller accessing *pr_reg using core_scsi3_locate_pr_reg(),
         * so call core_scsi3_put_pr_reg() to decrement our reference.
@@ -1280,6 +1293,7 @@ void core_scsi3_free_pr_reg_from_nacl(
 {
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
        struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder;
+       bool free_reg = false;
        /*
         * If the passed se_node_acl matches the reservation holder,
         * release the reservation.
@@ -1287,13 +1301,18 @@ void core_scsi3_free_pr_reg_from_nacl(
        spin_lock(&dev->dev_reservation_lock);
        pr_res_holder = dev->dev_pr_res_holder;
        if ((pr_res_holder != NULL) &&
-           (pr_res_holder->pr_reg_nacl == nacl))
-               __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0);
+           (pr_res_holder->pr_reg_nacl == nacl)) {
+               __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0, 1);
+               free_reg = true;
+       }
        spin_unlock(&dev->dev_reservation_lock);
        /*
         * Release any registration associated with the struct se_node_acl.
         */
        spin_lock(&pr_tmpl->registration_lock);
+       if (pr_res_holder && free_reg)
+               __core_scsi3_free_registration(dev, pr_res_holder, NULL, 0);
+
        list_for_each_entry_safe(pr_reg, pr_reg_tmp,
                        &pr_tmpl->registration_list, pr_reg_list) {
 
@@ -1316,7 +1335,7 @@ void core_scsi3_free_all_registrations(
        if (pr_res_holder != NULL) {
                struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
                __core_scsi3_complete_pro_release(dev, pr_res_nacl,
-                               pr_res_holder, 0);
+                                                 pr_res_holder, 0, 0);
        }
        spin_unlock(&dev->dev_reservation_lock);
 
@@ -1877,8 +1896,8 @@ static int core_scsi3_update_aptpl_buf(
                }
 
                if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
-                       pr_err("Unable to update renaming"
-                               " APTPL metadata\n");
+                       pr_err("Unable to update renaming APTPL metadata,"
+                              " reallocating larger buffer\n");
                        ret = -EMSGSIZE;
                        goto out;
                }
@@ -1895,8 +1914,8 @@ static int core_scsi3_update_aptpl_buf(
                        lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);
 
                if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
-                       pr_err("Unable to update renaming"
-                               " APTPL metadata\n");
+                       pr_err("Unable to update renaming APTPL metadata,"
+                              " reallocating larger buffer\n");
                        ret = -EMSGSIZE;
                        goto out;
                }
@@ -1959,7 +1978,7 @@ static int __core_scsi3_write_aptpl_to_file(
 static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl)
 {
        unsigned char *buf;
-       int rc;
+       int rc, len = PR_APTPL_BUF_LEN;
 
        if (!aptpl) {
                char *null_buf = "No Registrations or Reservations\n";
@@ -1973,25 +1992,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b
 
                return 0;
        }
-
-       buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
+retry:
+       buf = vzalloc(len);
        if (!buf)
                return TCM_OUT_OF_RESOURCES;
 
-       rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN);
+       rc = core_scsi3_update_aptpl_buf(dev, buf, len);
        if (rc < 0) {
-               kfree(buf);
-               return TCM_OUT_OF_RESOURCES;
+               vfree(buf);
+               len *= 2;
+               goto retry;
        }
 
        rc = __core_scsi3_write_aptpl_to_file(dev, buf);
        if (rc != 0) {
                pr_err("SPC-3 PR: Could not update APTPL\n");
-               kfree(buf);
+               vfree(buf);
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
        dev->t10_pr.pr_aptpl_active = 1;
-       kfree(buf);
+       vfree(buf);
        pr_debug("SPC-3 PR: Set APTPL Bit Activated\n");
        return 0;
 }
@@ -2125,13 +2145,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                /*
                 * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus.
                 */
-               pr_holder = core_scsi3_check_implicit_release(
-                               cmd->se_dev, pr_reg);
+               type = pr_reg->pr_res_type;
+               pr_holder = core_scsi3_check_implicit_release(cmd->se_dev,
+                                                             pr_reg);
                if (pr_holder < 0) {
                        ret = TCM_RESERVATION_CONFLICT;
                        goto out;
                }
-               type = pr_reg->pr_res_type;
 
                spin_lock(&pr_tmpl->registration_lock);
                /*
@@ -2289,6 +2309,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
        spin_lock(&dev->dev_reservation_lock);
        pr_res_holder = dev->dev_pr_res_holder;
        if (pr_res_holder) {
+               int pr_res_type = pr_res_holder->pr_res_type;
                /*
                 * From spc4r17 Section 5.7.9: Reserving:
                 *
@@ -2299,7 +2320,9 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
                 * the logical unit, then the command shall be completed with
                 * RESERVATION CONFLICT status.
                 */
-               if (pr_res_holder != pr_reg) {
+               if ((pr_res_holder != pr_reg) &&
+                   (pr_res_type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG) &&
+                   (pr_res_type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) {
                        struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
                        pr_err("SPC-3 PR: Attempted RESERVE from"
                                " [%s]: %s while reservation already held by"
@@ -2405,23 +2428,59 @@ static void __core_scsi3_complete_pro_release(
        struct se_device *dev,
        struct se_node_acl *se_nacl,
        struct t10_pr_registration *pr_reg,
-       int explicit)
+       int explicit,
+       int unreg)
 {
        struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
        char i_buf[PR_REG_ISID_ID_LEN];
+       int pr_res_type = 0, pr_res_scope = 0;
 
        memset(i_buf, 0, PR_REG_ISID_ID_LEN);
        core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
        /*
         * Go ahead and release the current PR reservation holder.
+        * If an All Registrants reservation is currently active and
+        * a unregister operation is requested, replace the current
+        * dev_pr_res_holder with another active registration.
         */
-       dev->dev_pr_res_holder = NULL;
+       if (dev->dev_pr_res_holder) {
+               pr_res_type = dev->dev_pr_res_holder->pr_res_type;
+               pr_res_scope = dev->dev_pr_res_holder->pr_res_scope;
+               dev->dev_pr_res_holder->pr_res_type = 0;
+               dev->dev_pr_res_holder->pr_res_scope = 0;
+               dev->dev_pr_res_holder->pr_res_holder = 0;
+               dev->dev_pr_res_holder = NULL;
+       }
+       if (!unreg)
+               goto out;
 
-       pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared"
-               " reservation holder TYPE: %s ALL_TG_PT: %d\n",
-               tfo->get_fabric_name(), (explicit) ? "explicit" : "implicit",
-               core_scsi3_pr_dump_type(pr_reg->pr_res_type),
-               (pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
+       spin_lock(&dev->t10_pr.registration_lock);
+       list_del_init(&pr_reg->pr_reg_list);
+       /*
+        * If the I_T nexus is a reservation holder, the persistent reservation
+        * is of an all registrants type, and the I_T nexus is the last remaining
+        * registered I_T nexus, then the device server shall also release the
+        * persistent reservation.
+        */
+       if (!list_empty(&dev->t10_pr.registration_list) &&
+           ((pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
+            (pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))) {
+               dev->dev_pr_res_holder =
+                       list_entry(dev->t10_pr.registration_list.next,
+                                  struct t10_pr_registration, pr_reg_list);
+               dev->dev_pr_res_holder->pr_res_type = pr_res_type;
+               dev->dev_pr_res_holder->pr_res_scope = pr_res_scope;
+               dev->dev_pr_res_holder->pr_res_holder = 1;
+       }
+       spin_unlock(&dev->t10_pr.registration_lock);
+out:
+       if (!dev->dev_pr_res_holder) {
+               pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared"
+                       " reservation holder TYPE: %s ALL_TG_PT: %d\n",
+                       tfo->get_fabric_name(), (explicit) ? "explicit" :
+                       "implicit", core_scsi3_pr_dump_type(pr_res_type),
+                       (pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
+       }
        pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n",
                tfo->get_fabric_name(), se_nacl->initiatorname,
                i_buf);
@@ -2552,7 +2611,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
         *    server shall not establish a unit attention condition.
         */
        __core_scsi3_complete_pro_release(dev, se_sess->se_node_acl,
-                       pr_reg, 1);
+                                         pr_reg, 1, 0);
 
        spin_unlock(&dev->dev_reservation_lock);
 
@@ -2640,7 +2699,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
        if (pr_res_holder) {
                struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
                __core_scsi3_complete_pro_release(dev, pr_res_nacl,
-                       pr_res_holder, 0);
+                                                 pr_res_holder, 0, 0);
        }
        spin_unlock(&dev->dev_reservation_lock);
        /*
@@ -2699,7 +2758,7 @@ static void __core_scsi3_complete_pro_preempt(
         */
        if (dev->dev_pr_res_holder)
                __core_scsi3_complete_pro_release(dev, nacl,
-                               dev->dev_pr_res_holder, 0);
+                                                 dev->dev_pr_res_holder, 0, 0);
 
        dev->dev_pr_res_holder = pr_reg;
        pr_reg->pr_res_holder = 1;
@@ -2943,8 +3002,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
         */
        if (pr_reg_n != pr_res_holder)
                __core_scsi3_complete_pro_release(dev,
-                               pr_res_holder->pr_reg_nacl,
-                               dev->dev_pr_res_holder, 0);
+                                                 pr_res_holder->pr_reg_nacl,
+                                                 dev->dev_pr_res_holder, 0, 0);
        /*
         * b) Remove the registrations for all I_T nexuses identified
         *    by the SERVICE ACTION RESERVATION KEY field, except the
@@ -3414,7 +3473,7 @@ after_iport_check:
         *    holder (i.e., the I_T nexus on which the
         */
        __core_scsi3_complete_pro_release(dev, pr_res_nacl,
-                       dev->dev_pr_res_holder, 0);
+                                         dev->dev_pr_res_holder, 0, 0);
        /*
         * g) Move the persistent reservation to the specified I_T nexus using
         *    the same scope and type as the persistent reservation released in
@@ -3854,7 +3913,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
        unsigned char *buf;
        u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len;
        u32 off = 8; /* off into first Full Status descriptor */
-       int format_code = 0;
+       int format_code = 0, pr_res_type = 0, pr_res_scope = 0;
+       bool all_reg = false;
 
        if (cmd->data_length < 8) {
                pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
@@ -3871,6 +3931,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
        buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
        buf[3] = (dev->t10_pr.pr_generation & 0xff);
 
+       spin_lock(&dev->dev_reservation_lock);
+       if (dev->dev_pr_res_holder) {
+               struct t10_pr_registration *pr_holder = dev->dev_pr_res_holder;
+
+               if (pr_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG ||
+                   pr_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) {
+                       all_reg = true;
+                       pr_res_type = pr_holder->pr_res_type;
+                       pr_res_scope = pr_holder->pr_res_scope;
+               }
+       }
+       spin_unlock(&dev->dev_reservation_lock);
+
        spin_lock(&pr_tmpl->registration_lock);
        list_for_each_entry_safe(pr_reg, pr_reg_tmp,
                        &pr_tmpl->registration_list, pr_reg_list) {
@@ -3920,14 +3993,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
                 * reservation holder for PR_HOLDER bit.
                 *
                 * Also, if this registration is the reservation
-                * holder, fill in SCOPE and TYPE in the next byte.
+                * holder or there is an All Registrants reservation
+                * active, fill in SCOPE and TYPE in the next byte.
                 */
                if (pr_reg->pr_res_holder) {
                        buf[off++] |= 0x01;
                        buf[off++] = (pr_reg->pr_res_scope & 0xf0) |
                                     (pr_reg->pr_res_type & 0x0f);
-               } else
+               } else if (all_reg) {
+                       buf[off++] |= 0x01;
+                       buf[off++] = (pr_res_scope & 0xf0) |
+                                    (pr_res_type & 0x0f);
+               } else {
                        off += 2;
+               }
 
                off += 4; /* Skip over reserved area */
                /*
index 0f199f6a07385e6ea03d4c12da24863cd7e4f7cd..29f28808fc0324ac76d6c621a4708961070c5587 100644 (file)
@@ -1111,7 +1111,7 @@ static u32 pscsi_get_device_type(struct se_device *dev)
        struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
        struct scsi_device *sd = pdv->pdv_sd;
 
-       return sd->type;
+       return (sd) ? sd->type : TYPE_NO_LUN;
 }
 
 static sector_t pscsi_get_blocks(struct se_device *dev)
index 5216acd68b4bfe949b530410942a68ac4bbf7f57..f89b24a09b19b969e7f9b521fc5e52efdb821928 100644 (file)
@@ -266,6 +266,8 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
 static sense_reason_t
 sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
 {
+       struct se_device *dev = cmd->se_dev;
+       sector_t end_lba = dev->transport->get_blocks(dev) + 1;
        unsigned int sectors = sbc_get_write_same_sectors(cmd);
 
        if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
@@ -279,6 +281,16 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
                        sectors, cmd->se_dev->dev_attrib.max_write_same_len);
                return TCM_INVALID_CDB_FIELD;
        }
+       /*
+        * Sanity check for LBA wrap and request past end of device.
+        */
+       if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
+           ((cmd->t_task_lba + sectors) > end_lba)) {
+               pr_err("WRITE_SAME exceeds last lba %llu (lba %llu, sectors %u)\n",
+                      (unsigned long long)end_lba, cmd->t_task_lba, sectors);
+               return TCM_ADDRESS_OUT_OF_RANGE;
+       }
+
        /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
        if (flags[0] & 0x10) {
                pr_warn("WRITE SAME with ANCHOR not supported\n");
@@ -302,7 +314,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
        return 0;
 }
 
-static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd)
+static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success)
 {
        unsigned char *buf, *addr;
        struct scatterlist *sg;
@@ -366,7 +378,7 @@ sbc_execute_rw(struct se_cmd *cmd)
                               cmd->data_direction);
 }
 
-static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
+static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
 {
        struct se_device *dev = cmd->se_dev;
 
@@ -389,7 +401,7 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
        return TCM_NO_SENSE;
 }
 
-static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
+static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success)
 {
        struct se_device *dev = cmd->se_dev;
        struct scatterlist *write_sg = NULL, *sg;
@@ -404,10 +416,15 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
 
        /*
         * Handle early failure in transport_generic_request_failure(),
-        * which will not have taken ->caw_mutex yet..
+        * which will not have taken ->caw_sem yet..
         */
-       if (!cmd->t_data_sg || !cmd->t_bidi_data_sg)
+       if (!success && (!cmd->t_data_sg || !cmd->t_bidi_data_sg))
                return TCM_NO_SENSE;
+       /*
+        * Handle special case for zero-length COMPARE_AND_WRITE
+        */
+       if (!cmd->data_length)
+               goto out;
        /*
         * Immediately exit + release dev->caw_sem if command has already
         * been failed with a non-zero SCSI status.
@@ -911,7 +928,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
                unsigned long long end_lba;
 
                end_lba = dev->transport->get_blocks(dev) + 1;
-               if (cmd->t_task_lba + sectors > end_lba) {
+               if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
+                   ((cmd->t_task_lba + sectors) > end_lba)) {
                        pr_err("cmd exceeds last lba %llu "
                                "(lba %llu, sectors %u)\n",
                                end_lba, cmd->t_task_lba, sectors);
index e6463ef33cd24ceaf5ba12c3271176c9cfba788c..6fc38903046c7ef42fa6cefc0bdbb24a1ac564d5 100644 (file)
@@ -1600,11 +1600,11 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        transport_complete_task_attr(cmd);
        /*
         * Handle special case for COMPARE_AND_WRITE failure, where the
-        * callback is expected to drop the per device ->caw_mutex.
+        * callback is expected to drop the per device ->caw_sem.
         */
        if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
             cmd->transport_complete_callback)
-               cmd->transport_complete_callback(cmd);
+               cmd->transport_complete_callback(cmd, false);
 
        switch (sense_reason) {
        case TCM_NON_EXISTENT_LUN:
@@ -1941,8 +1941,12 @@ static void target_complete_ok_work(struct work_struct *work)
        if (cmd->transport_complete_callback) {
                sense_reason_t rc;
 
-               rc = cmd->transport_complete_callback(cmd);
+               rc = cmd->transport_complete_callback(cmd, true);
                if (!rc && !(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE_POST)) {
+                       if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
+                           !cmd->data_length)
+                               goto queue_rsp;
+
                        return;
                } else if (rc) {
                        ret = transport_send_check_condition_and_sense(cmd,
@@ -1956,6 +1960,7 @@ static void target_complete_ok_work(struct work_struct *work)
                }
        }
 
+queue_rsp:
        switch (cmd->data_direction) {
        case DMA_FROM_DEVICE:
                spin_lock(&cmd->se_lun->lun_sep_lock);
@@ -2044,6 +2049,16 @@ static inline void transport_reset_sgl_orig(struct se_cmd *cmd)
 static inline void transport_free_pages(struct se_cmd *cmd)
 {
        if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) {
+               /*
+                * Release special case READ buffer payload required for
+                * SG_TO_MEM_NOALLOC to function with COMPARE_AND_WRITE
+                */
+               if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) {
+                       transport_free_sgl(cmd->t_bidi_data_sg,
+                                          cmd->t_bidi_data_nents);
+                       cmd->t_bidi_data_sg = NULL;
+                       cmd->t_bidi_data_nents = 0;
+               }
                transport_reset_sgl_orig(cmd);
                return;
        }
@@ -2192,6 +2207,7 @@ sense_reason_t
 transport_generic_new_cmd(struct se_cmd *cmd)
 {
        int ret = 0;
+       bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
 
        /*
         * Determine is the TCM fabric module has already allocated physical
@@ -2200,7 +2216,6 @@ transport_generic_new_cmd(struct se_cmd *cmd)
         */
        if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) &&
            cmd->data_length) {
-               bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
 
                if ((cmd->se_cmd_flags & SCF_BIDI) ||
                    (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)) {
@@ -2223,6 +2238,20 @@ transport_generic_new_cmd(struct se_cmd *cmd)
                                       cmd->data_length, zero_flag);
                if (ret < 0)
                        return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       } else if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
+                   cmd->data_length) {
+               /*
+                * Special case for COMPARE_AND_WRITE with fabrics
+                * using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC.
+                */
+               u32 caw_length = cmd->t_task_nolb *
+                                cmd->se_dev->dev_attrib.block_size;
+
+               ret = target_alloc_sgl(&cmd->t_bidi_data_sg,
+                                      &cmd->t_bidi_data_nents,
+                                      caw_length, zero_flag);
+               if (ret < 0)
+                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
        /*
         * If this command is not a write we can execute it right here,
@@ -2327,6 +2356,10 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
        list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
 out:
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+
+       if (ret && ack_kref)
+               target_put_sess_cmd(se_sess, se_cmd);
+
        return ret;
 }
 EXPORT_SYMBOL(target_get_sess_cmd);
index e415af32115a80bd7927627e826731b2c8b461c3..c67d3795db4a3f7b57d19743bfa5f3015e035973 100644 (file)
@@ -346,7 +346,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd)
                ep = fc_seq_exch(seq);
                if (ep) {
                        lport = ep->lp;
-                       if (lport && (ep->xid <= lport->lro_xid))
+                       if (lport && (ep->xid <= lport->lro_xid)) {
                                /*
                                 * "ddp_done" trigger invalidation of HW
                                 * specific DDP context
@@ -361,6 +361,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd)
                                 * identified using ep->xid)
                                 */
                                cmd->was_ddp_setup = 0;
+                       }
                }
        }
 }
index a4929272074f3f8a161ff7978289af475560b9eb..58b5c6694cd4361472b34fa941890e5121d3dba9 100644 (file)
@@ -420,7 +420,8 @@ const struct ti_bandgap_data dra752_data = {
                        TI_BANDGAP_FEATURE_FREEZE_BIT |
                        TI_BANDGAP_FEATURE_TALERT |
                        TI_BANDGAP_FEATURE_COUNTER_DELAY |
-                       TI_BANDGAP_FEATURE_HISTORY_BUFFER,
+                       TI_BANDGAP_FEATURE_HISTORY_BUFFER |
+                       TI_BANDGAP_FEATURE_ERRATA_814,
        .fclock_name = "l3instr_ts_gclk_div",
        .div_ck_name = "l3instr_ts_gclk_div",
        .conv_table = dra752_adc_to_temp,
index eff0c80fd4af50110cde6b4dc5cba3500787e91e..79ff70c446ba195ef893125b377567ff4ac2e58b 100644 (file)
@@ -319,7 +319,8 @@ const struct ti_bandgap_data omap5430_data = {
                        TI_BANDGAP_FEATURE_FREEZE_BIT |
                        TI_BANDGAP_FEATURE_TALERT |
                        TI_BANDGAP_FEATURE_COUNTER_DELAY |
-                       TI_BANDGAP_FEATURE_HISTORY_BUFFER,
+                       TI_BANDGAP_FEATURE_HISTORY_BUFFER |
+                       TI_BANDGAP_FEATURE_ERRATA_813,
        .fclock_name = "l3instr_ts_gclk_div",
        .div_ck_name = "l3instr_ts_gclk_div",
        .conv_table = omap5430_adc_to_temp,
index 74c0e3474d6e935a7d16bf29e6304e59b9a01a1f..c2c585a3ea490f4a97e9e91324846e595fa5b151 100644 (file)
@@ -118,6 +118,37 @@ exit:
        return ret;
 }
 
+/**
+ * ti_errata814_bandgap_read_temp() - helper function to read dra7 sensor temperature
+ * @bgp: pointer to ti_bandgap structure
+ * @reg: desired register (offset) to be read
+ *
+ * Function to read dra7 bandgap sensor temperature. This is done separately
+ * so as to workaround the errata "Bandgap Temperature read Dtemp can be
+ * corrupted" - Errata ID: i814".
+ * Read accesses to registers listed below can be corrupted due to incorrect
+ * resynchronization between clock domains.
+ * Read access to registers below can be corrupted :
+ * CTRL_CORE_DTEMP_MPU/GPU/CORE/DSPEVE/IVA_n (n = 0 to 4)
+ * CTRL_CORE_TEMP_SENSOR_MPU/GPU/CORE/DSPEVE/IVA_n
+ *
+ * Return: the register value.
+ */
+static u32 ti_errata814_bandgap_read_temp(struct ti_bandgap *bgp,  u32 reg)
+{
+       u32 val1, val2;
+
+       val1 = ti_bandgap_readl(bgp, reg);
+       val2 = ti_bandgap_readl(bgp, reg);
+
+       /* If both times we read the same value then that is right */
+       if (val1 == val2)
+               return val1;
+
+       /* if val1 and val2 are different read it third time */
+       return ti_bandgap_readl(bgp, reg);
+}
+
 /**
  * ti_bandgap_read_temp() - helper function to read sensor temperature
  * @bgp: pointer to ti_bandgap structure
@@ -148,7 +179,11 @@ static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id)
        }
 
        /* read temperature */
-       temp = ti_bandgap_readl(bgp, reg);
+       if (TI_BANDGAP_HAS(bgp, ERRATA_814))
+               temp = ti_errata814_bandgap_read_temp(bgp, reg);
+       else
+               temp = ti_bandgap_readl(bgp, reg);
+
        temp &= tsr->bgap_dtemp_mask;
 
        if (TI_BANDGAP_HAS(bgp, FREEZE_BIT))
@@ -410,7 +445,7 @@ static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id,
 {
        struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data;
        struct temp_sensor_registers *tsr;
-       u32 thresh_val, reg_val, t_hot, t_cold;
+       u32 thresh_val, reg_val, t_hot, t_cold, ctrl;
        int err = 0;
 
        tsr = bgp->conf->sensors[id].registers;
@@ -442,8 +477,47 @@ static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id,
                  ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask);
        reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) |
                   (t_cold << __ffs(tsr->threshold_tcold_mask));
+
+       /**
+        * Errata i813:
+        * Spurious Thermal Alert: Talert can happen randomly while the device
+        * remains under the temperature limit defined for this event to trig.
+        * This spurious event is caused by a incorrect re-synchronization
+        * between clock domains. The comparison between configured threshold
+        * and current temperature value can happen while the value is
+        * transitioning (metastable), thus causing inappropriate event
+        * generation. No spurious event occurs as long as the threshold value
+        * stays unchanged. Spurious event can be generated while a thermal
+        * alert threshold is modified in
+        * CONTROL_BANDGAP_THRESHOLD_MPU/GPU/CORE/DSPEVE/IVA_n.
+        */
+
+       if (TI_BANDGAP_HAS(bgp, ERRATA_813)) {
+               /* Mask t_hot and t_cold events at the IP Level */
+               ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
+
+               if (hot)
+                       ctrl &= ~tsr->mask_hot_mask;
+               else
+                       ctrl &= ~tsr->mask_cold_mask;
+
+               ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
+       }
+
+       /* Write the threshold value */
        ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold);
 
+       if (TI_BANDGAP_HAS(bgp, ERRATA_813)) {
+               /* Unmask t_hot and t_cold events at the IP Level */
+               ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
+               if (hot)
+                       ctrl |= tsr->mask_hot_mask;
+               else
+                       ctrl |= tsr->mask_cold_mask;
+
+               ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
+       }
+
        if (err) {
                dev_err(bgp->dev, "failed to reprogram thot threshold\n");
                err = -EIO;
index b3adf72f252d310779e5014b9ee272bf2a499946..0c52f7afba00b5335adbeba60cd31f547d2256a3 100644 (file)
@@ -318,6 +318,10 @@ struct ti_temp_sensor {
  * TI_BANDGAP_FEATURE_HISTORY_BUFFER - used when the bandgap device features
  *     a history buffer of temperatures.
  *
+ * TI_BANDGAP_FEATURE_ERRATA_814 - used to workaorund when the bandgap device
+ *     has Errata 814
+ * TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device
+ *     has Errata 813
  * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a
  *      specific feature (above) or not. Return non-zero, if yes.
  */
@@ -331,6 +335,8 @@ struct ti_temp_sensor {
 #define TI_BANDGAP_FEATURE_FREEZE_BIT          BIT(7)
 #define TI_BANDGAP_FEATURE_COUNTER_DELAY       BIT(8)
 #define TI_BANDGAP_FEATURE_HISTORY_BUFFER      BIT(9)
+#define TI_BANDGAP_FEATURE_ERRATA_814          BIT(10)
+#define TI_BANDGAP_FEATURE_ERRATA_813          BIT(11)
 #define TI_BANDGAP_HAS(b, f)                   \
                        ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f)
 
index 2dc2831840ca1852efb1cec280ced8b2e0afb0ae..8eb65f26fcae48e9f09155a6def71ae3937bfdee 100644 (file)
@@ -299,11 +299,27 @@ static int xen_initial_domain_console_init(void)
        return 0;
 }
 
+static void xen_console_update_evtchn(struct xencons_info *info)
+{
+       if (xen_hvm_domain()) {
+               uint64_t v;
+               int err;
+
+               err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
+               if (!err && v)
+                       info->evtchn = v;
+       } else
+               info->evtchn = xen_start_info->console.domU.evtchn;
+}
+
 void xen_console_resume(void)
 {
        struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE);
-       if (info != NULL && info->irq)
+       if (info != NULL && info->irq) {
+               if (!xen_initial_domain())
+                       xen_console_update_evtchn(info);
                rebind_evtchn_irq(info->evtchn, info->irq);
+       }
 }
 
 static void xencons_disconnect_backend(struct xencons_info *info)
index 850e232d086e315c8bf56c432687cb967fcdb1d1..8ab46ad40f2862cf1ac67758d58e424d1c0a1d4c 100644 (file)
@@ -247,8 +247,6 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
 
 static void n_tty_check_throttle(struct tty_struct *tty)
 {
-       if (tty->driver->type == TTY_DRIVER_TYPE_PTY)
-               return;
        /*
         * Check the remaining room for the input canonicalization
         * mode.  We don't want to throttle the driver if we're in
@@ -1512,23 +1510,6 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag)
                n_tty_receive_char_flagged(tty, c, flag);
 }
 
-/**
- *     n_tty_receive_buf       -       data receive
- *     @tty: terminal device
- *     @cp: buffer
- *     @fp: flag buffer
- *     @count: characters
- *
- *     Called by the terminal driver when a block of characters has
- *     been received. This function must be called from soft contexts
- *     not from interrupt context. The driver is responsible for making
- *     calls one at a time and in order (or using flush_to_ldisc)
- *
- *     n_tty_receive_buf()/producer path:
- *             claims non-exclusive termios_rwsem
- *             publishes read_head and canon_head
- */
-
 static void
 n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp,
                           char *fp, int count)
@@ -1684,24 +1665,85 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
        }
 }
 
+/**
+ *     n_tty_receive_buf_common        -       process input
+ *     @tty: device to receive input
+ *     @cp: input chars
+ *     @fp: flags for each char (if NULL, all chars are TTY_NORMAL)
+ *     @count: number of input chars in @cp
+ *
+ *     Called by the terminal driver when a block of characters has
+ *     been received. This function must be called from soft contexts
+ *     not from interrupt context. The driver is responsible for making
+ *     calls one at a time and in order (or using flush_to_ldisc)
+ *
+ *     Returns the # of input chars from @cp which were processed.
+ *
+ *     In canonical mode, the maximum line length is 4096 chars (including
+ *     the line termination char); lines longer than 4096 chars are
+ *     truncated. After 4095 chars, input data is still processed but
+ *     not stored. Overflow processing ensures the tty can always
+ *     receive more input until at least one line can be read.
+ *
+ *     In non-canonical mode, the read buffer will only accept 4095 chars;
+ *     this provides the necessary space for a newline char if the input
+ *     mode is switched to canonical.
+ *
+ *     Note it is possible for the read buffer to _contain_ 4096 chars
+ *     in non-canonical mode: the read buffer could already contain the
+ *     maximum canon line of 4096 chars when the mode is switched to
+ *     non-canonical.
+ *
+ *     n_tty_receive_buf()/producer path:
+ *             claims non-exclusive termios_rwsem
+ *             publishes commit_head or canon_head
+ */
 static int
 n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
                         char *fp, int count, int flow)
 {
        struct n_tty_data *ldata = tty->disc_data;
-       int room, n, rcvd = 0;
+       int room, n, rcvd = 0, overflow;
 
        down_read(&tty->termios_rwsem);
 
        while (1) {
-               room = receive_room(tty);
+               /*
+                * When PARMRK is set, each input char may take up to 3 chars
+                * in the read buf; reduce the buffer space avail by 3x
+                *
+                * If we are doing input canonicalization, and there are no
+                * pending newlines, let characters through without limit, so
+                * that erase characters will be handled.  Other excess
+                * characters will be beeped.
+                *
+                * paired with store in *_copy_from_read_buf() -- guarantees
+                * the consumer has loaded the data in read_buf up to the new
+                * read_tail (so this producer will not overwrite unread data)
+                */
+               size_t tail = ldata->read_tail;
+
+               room = N_TTY_BUF_SIZE - (ldata->read_head - tail);
+               if (I_PARMRK(tty))
+                       room = (room + 2) / 3;
+               room--;
+               if (room <= 0) {
+                       overflow = ldata->icanon && ldata->canon_head == tail;
+                       if (overflow && room < 0)
+                               ldata->read_head--;
+                       room = overflow;
+                       ldata->no_room = flow && !room;
+               } else
+                       overflow = 0;
+
                n = min(count, room);
-               if (!n) {
-                       if (flow && !room)
-                               ldata->no_room = 1;
+               if (!n)
                        break;
-               }
-               __receive_buf(tty, cp, fp, n);
+
+               /* ignore parity errors if handling overflow */
+               if (!overflow || !fp || *fp != TTY_PARITY)
+                       __receive_buf(tty, cp, fp, n);
+
                cp += n;
                if (fp)
                        fp += n;
@@ -1710,7 +1752,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
        }
 
        tty->receive_room = room;
-       n_tty_check_throttle(tty);
+
+       /* Unthrottle if handling overflow on pty */
+       if (tty->driver->type == TTY_DRIVER_TYPE_PTY) {
+               if (overflow) {
+                       tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
+                       tty_unthrottle_safe(tty);
+                       __tty_set_flow_change(tty, 0);
+               }
+       } else
+               n_tty_check_throttle(tty);
+
        up_read(&tty->termios_rwsem);
 
        return rcvd;
index 866888e99fe4741effb76e6c3b3968f8acd76371..96e319464364024e5178d66d544ac1da29e2779b 100644 (file)
@@ -66,7 +66,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
               "Please send the output of lspci -vv, this\n"
               "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
               "manufacturer and name of serial board or\n"
-              "modem board to rmk+serial@arm.linux.org.uk.\n",
+              "modem board to <linux-serial@vger.kernel.org>.\n",
               pci_name(dev), str, dev->vendor, dev->device,
               dev->subsystem_vendor, dev->subsystem_device);
 }
index 0d3e6cb36748dd64e5112816c00e59decdf908c7..9d162ef79af64ea8a380153fc0c070eb03794481 100644 (file)
@@ -757,6 +757,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
        config.direction = DMA_MEM_TO_DEV;
        config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
        config.dst_addr = port->mapbase + ATMEL_US_THR;
+       config.dst_maxburst = 1;
 
        ret = dmaengine_device_control(atmel_port->chan_tx,
                                        DMA_SLAVE_CONFIG,
@@ -921,6 +922,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
        config.direction = DMA_DEV_TO_MEM;
        config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
        config.src_addr = port->mapbase + ATMEL_US_RHR;
+       config.src_maxburst = 1;
 
        ret = dmaengine_device_control(atmel_port->chan_rx,
                                        DMA_SLAVE_CONFIG,
index 175f123f4f09fb243106992e40301cd19b2386e5..501c465feb59eb26ebde1dd9bda4d28de5d8a3a5 100644 (file)
@@ -362,6 +362,9 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
        writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
                        sport->port.membase + UARTPFIFO);
 
+       /* explicitly clear RDRF */
+       readb(sport->port.membase + UARTSR1);
+
        /* flush Tx and Rx FIFO */
        writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
                        sport->port.membase + UARTCFIFO);
index 99246606a256b71cbef9272b1402afc4bdcf1009..9dd8a71fff9e84ea3a8c7091470b4d84e4caffe1 100644 (file)
@@ -261,7 +261,6 @@ static struct of_device_id of_platform_serial_table[] = {
        { .compatible = "ibm,qpace-nwp-serial",
                .data = (void *)PORT_NWPSERIAL, },
 #endif
-       { .type = "serial",         .data = (void *)PORT_UNKNOWN, },
        { /* end of list */ },
 };
 
index 25d07412e08e21640864f144b491726e5f58a68e..39988fa91294a547a4ced872877e98b9ed736cba 100644 (file)
@@ -996,8 +996,8 @@ EXPORT_SYMBOL(start_tty);
 /* We limit tty time update visibility to every 8 seconds or so. */
 static void tty_update_time(struct timespec *time)
 {
-       unsigned long sec = get_seconds() & ~7;
-       if ((long)(sec - time->tv_sec) > 0)
+       unsigned long sec = get_seconds();
+       if (abs(sec - time->tv_sec) & ~7)
                time->tv_sec = sec;
 }
 
index 6fd60fece6b4b01684695b7df4af376e695ff873..22da05d27009b1b116c84aa27af833c2b213bc25 100644 (file)
@@ -217,11 +217,17 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 #endif
        if (!timeout)
                timeout = MAX_SCHEDULE_TIMEOUT;
+
        if (wait_event_interruptible_timeout(tty->write_wait,
-                       !tty_chars_in_buffer(tty), timeout) >= 0) {
-               if (tty->ops->wait_until_sent)
-                       tty->ops->wait_until_sent(tty, timeout);
+                       !tty_chars_in_buffer(tty), timeout) < 0) {
+               return;
        }
+
+       if (timeout == MAX_SCHEDULE_TIMEOUT)
+               timeout = 0;
+
+       if (tty->ops->wait_until_sent)
+               tty->ops->wait_until_sent(tty, timeout);
 }
 EXPORT_SYMBOL(tty_wait_until_sent);
 
index a051a7a2b1bd534a93fd459da7c553e0a5af4dfa..a81f9dd7ee97db06a86c18b813defea0b207099c 100644 (file)
@@ -245,7 +245,7 @@ static void wdm_int_callback(struct urb *urb)
        case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
                dev_dbg(&desc->intf->dev,
                        "NOTIFY_RESPONSE_AVAILABLE received: index %d len %d",
-                       dr->wIndex, dr->wLength);
+                       le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength));
                break;
 
        case USB_CDC_NOTIFY_NETWORK_CONNECTION:
@@ -262,7 +262,9 @@ static void wdm_int_callback(struct urb *urb)
                clear_bit(WDM_POLL_RUNNING, &desc->flags);
                dev_err(&desc->intf->dev,
                        "unknown notification %d received: index %d len %d\n",
-                       dr->bNotificationType, dr->wIndex, dr->wLength);
+                       dr->bNotificationType,
+                       le16_to_cpu(dr->wIndex),
+                       le16_to_cpu(dr->wLength));
                goto exit;
        }
 
@@ -408,7 +410,7 @@ static ssize_t wdm_write
                             USB_RECIP_INTERFACE);
        req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
        req->wValue = 0;
-       req->wIndex = desc->inum;
+       req->wIndex = desc->inum; /* already converted */
        req->wLength = cpu_to_le16(count);
        set_bit(WDM_IN_USE, &desc->flags);
        desc->outbuf = buf;
@@ -422,7 +424,7 @@ static ssize_t wdm_write
                rv = usb_translate_errors(rv);
        } else {
                dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
-                       req->wIndex);
+                       le16_to_cpu(req->wIndex));
        }
 out:
        usb_autopm_put_interface(desc->intf);
@@ -820,7 +822,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
        desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
        desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
        desc->irq->wValue = 0;
-       desc->irq->wIndex = desc->inum;
+       desc->irq->wIndex = desc->inum; /* already converted */
        desc->irq->wLength = cpu_to_le16(desc->wMaxCommand);
 
        usb_fill_control_urb(
index 9ca77166d37e8357cb35ee1f2cc71083841f2d9e..45b7b96f9ed39a047cbbd2ab6bd312f728627e39 100644 (file)
@@ -501,6 +501,7 @@ static void async_completed(struct urb *urb)
        as->status = urb->status;
        signr = as->signr;
        if (signr) {
+               memset(&sinfo, 0, sizeof(sinfo));
                sinfo.si_signo = as->signr;
                sinfo.si_errno = as->status;
                sinfo.si_code = SI_ASYNCIO;
@@ -2227,6 +2228,7 @@ static void usbdev_remove(struct usb_device *udev)
                wake_up_all(&ps->wait);
                list_del_init(&ps->list);
                if (ps->discsignr) {
+                       memset(&sinfo, 0, sizeof(sinfo));
                        sinfo.si_signo = ps->discsignr;
                        sinfo.si_errno = EPIPE;
                        sinfo.si_code = SI_ASYNCIO;
index 8d621bd88a39e04c37ec1c27feddd60123dab494..47d8dafe9d9f789781285a0f83072724c8b5dcb2 100644 (file)
@@ -3300,10 +3300,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
                dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
                                port1, status);
        } else {
-               /* drive resume for at least 20 msec */
+               /* drive resume for USB_RESUME_TIMEOUT msec */
                dev_dbg(&udev->dev, "usb %sresume\n",
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""));
-               msleep(25);
+               msleep(USB_RESUME_TIMEOUT);
 
                /* Virtual root hubs can trigger on GET_PORT_STATUS to
                 * stop resume signaling.  Then finish the resume
index 4d918ed8d343394bcc92cea19e4e025a9f7c7c5c..0f9980088c083628c44cc3f13a8e4248f1a0dcce 100644 (file)
@@ -1501,7 +1501,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                        dev_dbg(hsotg->dev,
                                "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
                        writel(0, hsotg->regs + PCGCTL);
-                       usleep_range(20000, 40000);
+                       msleep(USB_RESUME_TIMEOUT);
 
                        hprt0 = dwc2_read_hprt0(hsotg);
                        hprt0 |= HPRT0_RES;
index 042c66b71df8a2c831370667e819585a04774621..b89b543cdd087e5532042407f4fe7a4ae9bdd77a 100644 (file)
@@ -560,7 +560,7 @@ static int bos_desc(struct usb_composite_dev *cdev)
        usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
        usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
        usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
-       usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
+       usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT);
 
        /*
         * The Superspeed USB Capability descriptor shall be implemented by all
index 69b76efd11e9bea3f11d9d2effe293c04045f01c..44e698cd524628fb02bebcf7dd71f145676ab675 100644 (file)
@@ -975,6 +975,15 @@ unknown:
                break;
        }
        /* host either stalls (value < 0) or reports success */
+       if (value >= 0) {
+               req->length = value;
+               req->zero = value < wLength;
+               value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+               if (value < 0) {
+                       ERROR(dev, "%s:%d Error!\n", __func__, __LINE__);
+                       req->status = 0;
+               }
+       }
        return value;
 }
 
index 488a30836c36cbee57f2e16f7813db7075891699..3df32fa8c8ae242b5a97fff439daeb4904037577 100644 (file)
@@ -787,12 +787,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                                        ehci->reset_done[i] == 0))
                                continue;
 
-                       /* start 20 msec resume signaling from this port,
-                        * and make khubd collect PORT_STAT_C_SUSPEND to
-                        * stop that signaling.  Use 5 ms extra for safety,
-                        * like usb_port_resume() does.
+                       /* start USB_RESUME_TIMEOUT msec resume signaling from
+                        * this port, and make hub_wq collect
+                        * PORT_STAT_C_SUSPEND to stop that signaling.
                         */
-                       ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
+                       ehci->reset_done[i] = jiffies +
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        set_bit(i, &ehci->resuming_ports);
                        ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
                        usb_hcd_start_port_resume(&hcd->self, i);
index 28a5b488eb3020efc42e42485622039fdab91f1d..80ce6fbecc3c386012eef3a11e75183cdac7b686 100644 (file)
@@ -482,10 +482,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
                ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
        }
 
-       /* msleep for 20ms only if code is trying to resume port */
+       /*
+        * msleep for USB_RESUME_TIMEOUT ms only if code is trying to resume
+        * port
+        */
        if (resume_needed) {
                spin_unlock_irq(&ehci->lock);
-               msleep(20);
+               msleep(USB_RESUME_TIMEOUT);
                spin_lock_irq(&ehci->lock);
                if (ehci->shutdown)
                        goto shutdown;
@@ -953,7 +956,7 @@ static int ehci_hub_control (
                        temp &= ~PORT_WAKE_BITS;
                        ehci_writel(ehci, temp | PORT_RESUME, status_reg);
                        ehci->reset_done[wIndex] = jiffies
-                                       + msecs_to_jiffies(20);
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        set_bit(wIndex, &ehci->resuming_ports);
                        usb_hcd_start_port_resume(&hcd->self, wIndex);
                        break;
index 98a89d16cc3e8f8e117b325620e36517e45ab523..8aa4ba0a0c695b8b188f47105dc0c109f2437b09 100644 (file)
@@ -1595,7 +1595,7 @@ static int fotg210_hub_control(
                        /* resume signaling for 20 msec */
                        fotg210_writel(fotg210, temp | PORT_RESUME, status_reg);
                        fotg210->reset_done[wIndex] = jiffies
-                                       + msecs_to_jiffies(20);
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
                        clear_bit(wIndex, &fotg210->port_c_suspend);
index ba9499060f639c3bff934d4868ca71cfd6948bb4..3e3926aa584e00e50aca8c1b63387d6629c55662 100644 (file)
@@ -1550,10 +1550,9 @@ static int fusbh200_hub_control (
                        if ((temp & PORT_PE) == 0)
                                goto error;
 
-                       /* resume signaling for 20 msec */
                        fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
                        fusbh200->reset_done[wIndex] = jiffies
-                                       + msecs_to_jiffies(20);
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
                        clear_bit(wIndex, &fusbh200->port_c_suspend);
index 240e792c81a7b5e7a3c60406b7faf16bd01f743a..b62298fe0be80a2e3e68c5c9a0a9e2b50f9a78b7 100644 (file)
@@ -1487,7 +1487,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
        spin_unlock_irq(&isp116x->lock);
 
        hcd->state = HC_STATE_RESUMING;
-       msleep(20);
+       msleep(USB_RESUME_TIMEOUT);
 
        /* Go operational */
        spin_lock_irq(&isp116x->lock);
index e07248b6ab67accbb0a731809d93713a5f6ae5fe..1b1e6e0d927017a3408c36d99d4beafb722edf84 100644 (file)
@@ -2500,11 +2500,12 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
                                        || oxu->reset_done[i] != 0)
                                continue;
 
-                       /* start 20 msec resume signaling from this port,
-                        * and make khubd collect PORT_STAT_C_SUSPEND to
+                       /* start USB_RESUME_TIMEOUT resume signaling from this
+                        * port, and make hub_wq collect PORT_STAT_C_SUSPEND to
                         * stop that signaling.
                         */
-                       oxu->reset_done[i] = jiffies + msecs_to_jiffies(20);
+                       oxu->reset_done[i] = jiffies +
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        oxu_dbg(oxu, "port %d remote wakeup\n", i + 1);
                        mod_timer(&hcd->rh_timer, oxu->reset_done[i]);
                }
index 110b4b9ebeaa1f047056b29faf6f76d9a0808ff9..f130bb2f7bbea000272ef50c1cf62fea32eee04c 100644 (file)
@@ -2300,7 +2300,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
                rh->port &= ~USB_PORT_STAT_SUSPEND;
                rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
                r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
-               msleep(50);
+               msleep(USB_RESUME_TIMEOUT);
                r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
        }
 
index a517151867af33a0d62f57ed9674c1a0e6777654..0f53cc8c8ecf03eb1408fc2f9dfe2db21483f4af 100644 (file)
@@ -1259,7 +1259,7 @@ sl811h_hub_control(
                        sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
 
                        mod_timer(&sl811->timer, jiffies
-                                       + msecs_to_jiffies(20));
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT));
                        break;
                case USB_PORT_FEAT_POWER:
                        port_power(sl811, 0);
index 93e17b12fb3304b0191f36b3eb2f2b6eef334132..98c66d88ebde2c58c0cbecfa79861d82d6474ad0 100644 (file)
@@ -165,7 +165,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
                                /* Port received a wakeup request */
                                set_bit(port, &uhci->resuming_ports);
                                uhci->ports_timeout = jiffies +
-                                               msecs_to_jiffies(25);
+                                       msecs_to_jiffies(USB_RESUME_TIMEOUT);
                                usb_hcd_start_port_resume(
                                                &uhci_to_hcd(uhci)->self, port);
 
@@ -337,7 +337,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        uhci_finish_suspend(uhci, port, port_addr);
 
                        /* USB v2.0 7.1.7.5 */
-                       uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
+                       uhci->ports_timeout = jiffies +
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        break;
                case USB_PORT_FEAT_POWER:
                        /* UHCI has no power switching */
index 69aece31143a12d965af1014b0c133f773ffafcf..d0d7eb7ff82488423ecbfd30b6ad3dd3ea93b140 100644 (file)
@@ -381,6 +381,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
                status = PORT_PLC;
                port_change_bit = "link state";
                break;
+       case USB_PORT_FEAT_C_PORT_CONFIG_ERROR:
+               status = PORT_CEC;
+               port_change_bit = "config error";
+               break;
        default:
                /* Should never happen */
                return;
@@ -582,6 +586,8 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        status |= USB_PORT_STAT_C_LINK_STATE << 16;
                if ((raw_port_status & PORT_WRC))
                        status |= USB_PORT_STAT_C_BH_RESET << 16;
+               if ((raw_port_status & PORT_CEC))
+                       status |= USB_PORT_STAT_C_CONFIG_ERROR << 16;
        }
 
        if (hcd->speed != HCD_USB3) {
@@ -999,6 +1005,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                case USB_PORT_FEAT_C_OVER_CURRENT:
                case USB_PORT_FEAT_C_ENABLE:
                case USB_PORT_FEAT_C_PORT_LINK_STATE:
+               case USB_PORT_FEAT_C_PORT_CONFIG_ERROR:
                        xhci_clear_port_change_bit(xhci, wValue, wIndex,
                                        port_array[wIndex], temp);
                        break;
@@ -1063,7 +1070,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
         */
        status = bus_state->resuming_ports;
 
-       mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC;
+       mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC;
 
        spin_lock_irqsave(&xhci->lock, flags);
        /* For each port, did anything change?  If so, set that bit in buf. */
index 272b3de4680f134e86b1318d063eec333932c4ea..67b952971c1b6d469036c268d0c19581beaec258 100644 (file)
@@ -117,6 +117,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
                xhci->quirks |= XHCI_LPM_SUPPORT;
                xhci->quirks |= XHCI_INTEL_HOST;
+               xhci->quirks |= XHCI_AVOID_BEI;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                        pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) {
@@ -132,7 +133,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 * PPT chipsets.
                 */
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
-               xhci->quirks |= XHCI_AVOID_BEI;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
            (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
index 0958458799843406e548293e494af9df7c6b54d9..4867cae860ed261ebf8b47708f7f6abdaec56728 100644 (file)
@@ -1615,7 +1615,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                } else {
                        xhci_dbg(xhci, "resume HS port %d\n", port_id);
                        bus_state->resume_done[faked_port_index] = jiffies +
-                               msecs_to_jiffies(20);
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        set_bit(faked_port_index, &bus_state->resuming_ports);
                        mod_timer(&hcd->rh_timer,
                                  bus_state->resume_done[faked_port_index]);
@@ -1985,7 +1985,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
        if (event_trb != ep_ring->dequeue) {
                /* The event was for the status stage */
                if (event_trb == td->last_trb) {
-                       if (td->urb->actual_length != 0) {
+                       if (td->urb_length_set) {
                                /* Don't overwrite a previously set error code
                                 */
                                if ((*status == -EINPROGRESS || *status == 0) &&
@@ -1999,7 +1999,13 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
                                        td->urb->transfer_buffer_length;
                        }
                } else {
-               /* Maybe the event was for the data stage? */
+                       /*
+                        * Maybe the event was for the data stage? If so, update
+                        * already the actual_length of the URB and flag it as
+                        * set, so that it is not overwritten in the event for
+                        * the last TRB.
+                        */
+                       td->urb_length_set = true;
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
                                EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
index 0b6407e583c568cb9661f362143940579729fb74..870f4cccd986527cc93f6a9926f8c02420326b79 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * xHCI host controller driver
  *
@@ -88,9 +89,10 @@ struct xhci_cap_regs {
 #define HCS_IST(p)             (((p) >> 0) & 0xf)
 /* bits 4:7, max number of Event Ring segments */
 #define HCS_ERST_MAX(p)                (((p) >> 4) & 0xf)
+/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */
 /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
-/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */
-#define HCS_MAX_SCRATCHPAD(p)   (((p) >> 27) & 0x1f)
+/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */
+#define HCS_MAX_SCRATCHPAD(p)   ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f))
 
 /* HCSPARAMS3 - hcs_params3 - bitmasks */
 /* bits 0:7, Max U1 to U0 latency for the roothub ports */
@@ -1288,6 +1290,8 @@ struct xhci_td {
        struct xhci_segment     *start_seg;
        union xhci_trb          *first_trb;
        union xhci_trb          *last_trb;
+       /* actual_length of the URB has already been set */
+       bool                    urb_length_set;
 };
 
 /* xHCI command default timeout value */
index 5114d2f6beb49667e3b31d2e2ee5de62d3ed2cd1..4e5065036af3469a5dc471b607d5da08874d756f 100644 (file)
@@ -99,6 +99,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
+#include <linux/usb.h>
 
 #include "musb_core.h"
 
@@ -478,7 +479,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                                                (USB_PORT_STAT_C_SUSPEND << 16)
                                                | MUSB_PORT_STAT_RESUME;
                                musb->rh_timer = jiffies
-                                                + msecs_to_jiffies(20);
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
                                musb->need_finish_resume = 1;
 
                                musb->xceiv->otg->state = OTG_STATE_A_HOST;
@@ -2323,7 +2324,7 @@ static int musb_resume(struct device *dev)
        if (musb->need_finish_resume) {
                musb->need_finish_resume = 0;
                schedule_delayed_work(&musb->finish_resume_work,
-                                     msecs_to_jiffies(20));
+                                     msecs_to_jiffies(USB_RESUME_TIMEOUT));
        }
 
        /*
@@ -2366,7 +2367,7 @@ static int musb_runtime_resume(struct device *dev)
        if (musb->need_finish_resume) {
                musb->need_finish_resume = 0;
                schedule_delayed_work(&musb->finish_resume_work,
-                               msecs_to_jiffies(20));
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT));
        }
 
        return 0;
index a133bd8c5dc7f310fbcdc90d1f6adce0e28b068a..f5e17fe058e13c6f1cd9543f2868daa6a56fd484 100644 (file)
@@ -136,7 +136,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
                /* later, GetPortStatus will stop RESUME signaling */
                musb->port1_status |= MUSB_PORT_STAT_RESUME;
                schedule_delayed_work(&musb->finish_resume_work,
-                                     msecs_to_jiffies(20));
+                                     msecs_to_jiffies(USB_RESUME_TIMEOUT));
        }
 }
 
index fd0d7f122ace3a8e42115f17a1bcf0ef2d1af065..1abe16acc8284d338c2eed95d5c1f46df7ac2847 100644 (file)
@@ -78,7 +78,9 @@ static void devm_usb_phy_release(struct device *dev, void *res)
 
 static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
 {
-       return res == match_data;
+       struct usb_phy **phy = res;
+
+       return *phy == match_data;
 }
 
 /**
index 9374bd2aba20759f4bb4b03d2a9d51058aead9fd..6f91eb9ae81a44ebd3b8eb530594e3d3481e0d65 100644 (file)
@@ -51,6 +51,7 @@ static int usb_serial_device_probe(struct device *dev)
 {
        struct usb_serial_driver *driver;
        struct usb_serial_port *port;
+       struct device *tty_dev;
        int retval = 0;
        int minor;
 
@@ -75,12 +76,20 @@ static int usb_serial_device_probe(struct device *dev)
        retval = device_create_file(dev, &dev_attr_port_number);
        if (retval) {
                if (driver->port_remove)
-                       retval = driver->port_remove(port);
+                       driver->port_remove(port);
                goto exit_with_autopm;
        }
 
        minor = port->minor;
-       tty_register_device(usb_serial_tty_driver, minor, dev);
+       tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev);
+       if (IS_ERR(tty_dev)) {
+               retval = PTR_ERR(tty_dev);
+               device_remove_file(dev, &dev_attr_port_number);
+               if (driver->port_remove)
+                       driver->port_remove(port);
+               goto exit_with_autopm;
+       }
+
        dev_info(&port->serial->dev->dev,
                 "%s converter now attached to ttyUSB%d\n",
                 driver->description, minor);
index a2d040971afeff2c0bc4a6c990f7a29ca1dfcc10..8d114b9733edfa81311535030aa4f3d727de3dd9 100644 (file)
@@ -147,6 +147,8 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */
        { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */
        { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */
+       { USB_DEVICE(0x16C0, 0x09B0) }, /* Lunatico Seletek */
+       { USB_DEVICE(0x16C0, 0x09B1) }, /* Lunatico Seletek */
        { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
        { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
        { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
index debcdef4cbf0e37a97f8f17d863153726ccaf0bb..2d858f81ab33f8d3133dcd391994ca1556b2f408 100644 (file)
@@ -617,6 +617,7 @@ static const struct usb_device_id id_table_combined[] = {
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
        /*
         * ELV devices:
         */
@@ -812,6 +813,8 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
+       { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
@@ -991,6 +994,23 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
        /* GE Healthcare devices */
        { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
+       /* Active Research (Actisense) devices */
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) },
        { }                                     /* Terminating entry */
 };
 
@@ -1882,8 +1902,12 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
 {
        struct usb_device *udev = serial->dev;
 
-       if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
-           (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))
+       if (udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems"))
+               return ftdi_jtag_probe(serial);
+
+       if (udev->product &&
+               (!strcmp(udev->product, "BeagleBone/XDS100V2") ||
+                !strcmp(udev->product, "SNAP Connect E10")))
                return ftdi_jtag_probe(serial);
 
        return 0;
index e52409c9be999f817cbdb627f4be8ec6f127cbe6..4e4f46f3c89c025670d42860756f39b2bb62ae24 100644 (file)
@@ -38,6 +38,9 @@
 
 #define FTDI_LUMEL_PD12_PID    0x6002
 
+/* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */
+#define CYBER_CORTEX_AV_PID    0x8698
+
 /*
  * Marvell OpenRD Base, Client
  * http://www.open-rd.org
  */
 #define FTDI_NT_ORIONLXM_PID   0x7c90  /* OrionLXm Substation Automation Platform */
 
+/*
+ * Synapse Wireless product ids (FTDI_VID)
+ * http://www.synapse-wireless.com
+ */
+#define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */
+
 
 /********************************/
 /** third-party VID/PID combos **/
  */
 #define GE_HEALTHCARE_VID              0x1901
 #define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015
+
+/*
+ * Active Research (Actisense) devices
+ */
+#define ACTISENSE_NDC_PID              0xD9A8 /* NDC USB Serial Adapter */
+#define ACTISENSE_USG_PID              0xD9A9 /* USG USB Serial Adapter */
+#define ACTISENSE_NGT_PID              0xD9AA /* NGT NMEA2000 Interface */
+#define ACTISENSE_NGW_PID              0xD9AB /* NGW NMEA2000 Gateway */
+#define ACTISENSE_D9AC_PID             0xD9AC /* Actisense Reserved */
+#define ACTISENSE_D9AD_PID             0xD9AD /* Actisense Reserved */
+#define ACTISENSE_D9AE_PID             0xD9AE /* Actisense Reserved */
+#define ACTISENSE_D9AF_PID             0xD9AF /* Actisense Reserved */
+#define CHETCO_SEAGAUGE_PID            0xA548 /* SeaGauge USB Adapter */
+#define CHETCO_SEASWITCH_PID           0xA549 /* SeaSwitch USB Adapter */
+#define CHETCO_SEASMART_NMEA2000_PID   0xA54A /* SeaSmart NMEA2000 Gateway */
+#define CHETCO_SEASMART_ETHERNET_PID   0xA54B /* SeaSmart Ethernet Gateway */
+#define CHETCO_SEASMART_WIFI_PID       0xA5AC /* SeaSmart Wifi Gateway */
+#define CHETCO_SEASMART_DISPLAY_PID    0xA5AD /* SeaSmart NMEA2000 Display */
+#define CHETCO_SEASMART_LITE_PID       0xA5AE /* SeaSmart Lite USB Adapter */
+#define CHETCO_SEASMART_ANALOG_PID     0xA5AF /* SeaSmart Analog Adapter */
index b63ce023f96f1ab7284e218ca68219da5f952440..d6a197917ebd6e4528c64d3b215707b0e6bb9785 100644 (file)
@@ -258,7 +258,8 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
         * character or at least one jiffy.
         */
        period = max_t(unsigned long, (10 * HZ / bps), 1);
-       period = min_t(unsigned long, period, timeout);
+       if (timeout)
+               period = min_t(unsigned long, period, timeout);
 
        dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n",
                                        __func__, jiffies_to_msecs(timeout),
@@ -268,7 +269,7 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
                schedule_timeout_interruptible(period);
                if (signal_pending(current))
                        break;
-               if (time_after(jiffies, expire))
+               if (timeout && time_after(jiffies, expire))
                        break;
        }
 }
index ab1d690274ae52b3230f04acbd8194a49f68b7ba..460a40669967855cfeea7c6cc911064822c6882a 100644 (file)
@@ -1284,7 +1284,8 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
        }
 
        /* Initial port termios */
-       mxuport_set_termios(tty, port, NULL);
+       if (tty)
+               mxuport_set_termios(tty, port, NULL);
 
        /*
         * TODO: use RQ_VENDOR_GET_MSR, once we know what it
index 5d055341f0578692f69d79f145615874a35c43d1..d8206f7573a9a4b3fa6aeab06f06c20ba6768b24 100644 (file)
@@ -14,6 +14,7 @@ config DISPLAY_ENCODER_TPD12S015
 
 config DISPLAY_DRA7EVM_ENCODER_TPD12S015
         tristate "DRA7 EVM TPD12S015 HDMI ESD protection and level shifter"
+       depends on SND_DAVINCI_SOC_MCASP
        help
          A custom TPD12S015 driver for the DRA7 EVM board, it contains some
          hacks required for HDMI to work properly on J6 EVM.
index ec42daa626e449c970120577113fda4c09098bdf..6e4a7234a86a6eae064472da4d3422765cb89796 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/of_gpio.h>
+#include <linux/suspend.h>
+#include <linux/of_platform.h>
 
 #include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#define CLK_BASE                       0x4a009000
-#define MCASP2_BASE                    0x48464000
-#define        CTRL_BASE                       0x4a003400
-#define        PINMUX_BASE                     0x4a003600
-
-#define CM_L4PER2_MCASP2_CLKCTRL       0x860
-#define        CM_L4PER2_CLKSTCTRL             0x8fc
-#define MCASP_PFUNC                    0x10
-#define MCASP_PDIR                     0x14
-#define MCASP_PDOUT                    0x18
-#define PAD_I2C2_SDA                   0x408
-#define PAD_I2C2_SCL                   0x40c
 
 #define SEL_I2C2       0
 #define SEL_HDMI       1
 
+int dra7_mcasp_hdmi_gpio_get(struct platform_device *pdev);
+int dra7_mcasp_hdmi_gpio_put(struct platform_device *pdev);
+int dra7_mcasp_hdmi_gpio_set(struct platform_device *pdev, bool high);
+
 /* HPD gpio debounce time in microseconds */
 #define HPD_DEBOUNCE_TIME      1000
 
@@ -49,94 +42,83 @@ struct panel_drv_data {
        int hpd_gpio;
 
        struct omap_video_timings timings;
-};
-
-static void __iomem *mcasp2_base;
-static void __iomem *ctrl_base;
 
-static int sel_hdmi_i2c2_init(struct device *dev)
-{
-       void __iomem *clk_base;
-       void __iomem *pmux_base;
+       struct pinctrl *pins;
+       struct pinctrl_state *pin_state_i2c;
+       struct pinctrl_state *pin_state_ddc;
 
-       mcasp2_base = devm_ioremap(dev, MCASP2_BASE, 0x20);
-       if (!mcasp2_base) {
-               dev_err(dev, "couldn't ioremap MCASP2 regs\n");
-               return -ENOMEM;
-       }
+       struct i2c_adapter *ddc_i2c_adapter;
+};
 
-       ctrl_base = devm_ioremap(dev, CTRL_BASE, SZ_1K);
-       if (!ctrl_base) {
-               dev_err(dev, "couldn't ioremap Control Module regs\n");
-               return -ENOMEM;
-       }
+static struct platform_device *mcasp;
 
-       clk_base = devm_ioremap(dev, CLK_BASE, SZ_4K);
-       if (!clk_base) {
-               dev_err(dev, "couldn't ioremap clock domain regs\n");
-               return -ENOMEM;
-       }
+static int hdmi_i2c2_hack_init(struct device *dev)
+{
+       struct device_node *node;
 
-       pmux_base = devm_ioremap(dev, PINMUX_BASE, SZ_1K);
-       if (!pmux_base) {
-               dev_err(dev, "couldn't ioremap PMUX regs\n");
-               return -ENOMEM;
-       }
+       node = of_parse_phandle(dev->of_node, "mcasp-gpio", 0);
 
-       iowrite32(0x40000, pmux_base + 0xfc);
+       if (!node)
+               return -ENODEV;
 
-       /* set CM_L4PER2_CLKSTCTRL to sw supervised wkup */
-       iowrite32(0x2, clk_base + CM_L4PER2_CLKSTCTRL);
+       mcasp = of_find_device_by_node(node);
 
-       iowrite32(0x2, clk_base + CM_L4PER2_MCASP2_CLKCTRL);
+       return 0;
+}
 
-       dev_dbg(dev, "CM_L4PER2_CLKSTCTRL %08x\n",
-               ioread32(clk_base + CM_L4PER2_CLKSTCTRL));
+static int hdmi_i2c2_hack_resume_mcasp(void)
+{
+       return dra7_mcasp_hdmi_gpio_get(mcasp);
+}
 
-       /* let it propogate */
+static void hdmi_i2c2_hack_suspend_mcasp(void)
+{
+       dra7_mcasp_hdmi_gpio_put(mcasp);
+}
 
-       udelay(5);
+static int hdmi_i2c2_hack_pm_notif(struct notifier_block *b, unsigned long v, void *d)
+{
+       switch (v) {
+       case PM_SUSPEND_PREPARE:
+               hdmi_i2c2_hack_suspend_mcasp();
+               return 0;
 
-       /*
-        * make mcasp2_aclkr a gpio and set direction to high
-        */
-       iowrite32(1 << 29, mcasp2_base + MCASP_PFUNC);
-       iowrite32(1 << 29, mcasp2_base + MCASP_PDIR);
+       case PM_POST_SUSPEND:
+               hdmi_i2c2_hack_resume_mcasp();
+               return 0;
 
-       return 0;
+       default:
+               return 0;
+       }
 }
 
+static struct notifier_block hdmi_i2c2_hack_pm_notif_block = {
+       .notifier_call = hdmi_i2c2_hack_pm_notif,
+};
+
 /*
  * use SEL_I2C2 to configure pcf8575@26 to set/unset LS_OE and CT_HPD, and use
- * SEL_HDMI to read edid via the HDMI ddc lines and recieve HPD events
+ * SEL_HDMI to read edid via the HDMI ddc lines
  */
-static void config_demux(struct device *dev, int sel)
+static void hdmi_i2c2_hack_demux(struct device *dev, int sel)
 {
-       u32 val;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 
        /*
-        * switch to I2C2 or HDMI DDC internal pinmux and drive MCASP2_ACLKR
+        * switch to I2C2 or HDMI DDC internal pinmux and drive MCASP8_AXR2
         * to low or high to select I2C2 or HDMI path respectively
         */
        if (sel == SEL_I2C2) {
-               val = ioread32(mcasp2_base + MCASP_PDOUT);
-               iowrite32(val & ~(1 << 29), mcasp2_base + MCASP_PDOUT);
-
-               iowrite32(0x60000, ctrl_base + PAD_I2C2_SDA);
-               iowrite32(0x60000, ctrl_base + PAD_I2C2_SCL);
+               pinctrl_select_state(ddata->pins, ddata->pin_state_i2c);
+               dra7_mcasp_hdmi_gpio_set(mcasp, false);
        } else {
-               val = ioread32(mcasp2_base + MCASP_PDOUT);
-               iowrite32(val | (1 << 29), mcasp2_base + MCASP_PDOUT);
-
-               iowrite32(0x60001, ctrl_base + PAD_I2C2_SDA);
-               iowrite32(0x60001, ctrl_base + PAD_I2C2_SCL);
+               pinctrl_select_state(ddata->pins, ddata->pin_state_ddc);
+               dra7_mcasp_hdmi_gpio_set(mcasp, true);
        }
 
        /* let it propogate */
        udelay(5);
-
-       dev_dbg(dev, "select %d, PDOUT %08x\n", sel,
-               ioread32(mcasp2_base + MCASP_PDOUT));
 }
 
 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
@@ -267,11 +249,15 @@ static int tpd_read_edid(struct omap_dss_device *dssdev,
        if (gpio_is_valid(ddata->ls_oe_gpio))
                gpio_set_value_cansleep(ddata->ls_oe_gpio, 1);
 
-       config_demux(dssdev->dev, SEL_HDMI);
+       i2c_lock_adapter(ddata->ddc_i2c_adapter);
+
+       hdmi_i2c2_hack_demux(dssdev->dev, SEL_HDMI);
 
        r = in->ops.hdmi->read_edid(in, edid, len);
 
-       config_demux(dssdev->dev, SEL_I2C2);
+       hdmi_i2c2_hack_demux(dssdev->dev, SEL_I2C2);
+
+       i2c_unlock_adapter(ddata->ddc_i2c_adapter);
 
        if (gpio_is_valid(ddata->ls_oe_gpio))
                gpio_set_value_cansleep(ddata->ls_oe_gpio, 0);
@@ -322,32 +308,6 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
        .set_hdmi_mode          = tpd_set_hdmi_mode,
 };
 
-static int tpd_probe_pdata(struct platform_device *pdev)
-{
-       struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-       struct encoder_tpd12s015_platform_data *pdata;
-       struct omap_dss_device *dssdev, *in;
-
-       pdata = dev_get_platdata(&pdev->dev);
-
-       ddata->ct_cp_hpd_gpio = pdata->ct_cp_hpd_gpio;
-       ddata->ls_oe_gpio = pdata->ls_oe_gpio;
-       ddata->hpd_gpio = pdata->hpd_gpio;
-
-       in = omap_dss_find_output(pdata->source);
-       if (in == NULL) {
-               dev_err(&pdev->dev, "Failed to find video source\n");
-               return -ENODEV;
-       }
-
-       ddata->in = in;
-
-       dssdev = &ddata->dssdev;
-       dssdev->name = pdata->name;
-
-       return 0;
-}
-
 static int tpd_probe_of(struct platform_device *pdev)
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
@@ -391,6 +351,41 @@ static int tpd_probe_of(struct platform_device *pdev)
        return 0;
 }
 
+static int tpd_init_pins(struct platform_device *pdev)
+{
+       struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+       struct device_node *node;
+
+       ddata->pins = devm_pinctrl_get(&pdev->dev);
+       if (IS_ERR(ddata->pins))
+               return PTR_ERR(ddata->pins);
+
+       ddata->pin_state_i2c = pinctrl_lookup_state(ddata->pins, "i2c");
+       if (IS_ERR(ddata->pin_state_i2c))
+               return PTR_ERR(ddata->pin_state_i2c);
+
+       ddata->pin_state_ddc = pinctrl_lookup_state(ddata->pins, "ddc");
+       if (IS_ERR(ddata->pin_state_ddc))
+               return PTR_ERR(ddata->pin_state_ddc);
+
+       node = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
+       if (!node)
+               return -ENODEV;
+
+       ddata->ddc_i2c_adapter = of_find_i2c_adapter_by_node(node);
+       if (!ddata->ddc_i2c_adapter)
+               return -ENODEV;
+
+       return 0;
+}
+
+static void tpd_uninit_pins(struct platform_device *pdev)
+{
+       struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+
+       i2c_put_adapter(ddata->ddc_i2c_adapter);
+}
+
 static int tpd_probe(struct platform_device *pdev)
 {
        struct omap_dss_device *in, *dssdev;
@@ -403,11 +398,7 @@ static int tpd_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ddata);
 
-       if (dev_get_platdata(&pdev->dev)) {
-               r = tpd_probe_pdata(pdev);
-               if (r)
-                       return r;
-       } else if (pdev->dev.of_node) {
+       if (pdev->dev.of_node) {
                r = tpd_probe_of(pdev);
                if (r)
                        return r;
@@ -415,15 +406,25 @@ static int tpd_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       r = tpd_init_pins(pdev);
+       if (r)
+               goto err_pins;
+
        /*
         * initialize the SEL_HDMI_I2C2 line going to the demux. Configure the
         * demux to select the I2C2 bus
         */
-       r = sel_hdmi_i2c2_init(&pdev->dev);
+       r = hdmi_i2c2_hack_init(&pdev->dev);
        if (r)
-               return r;
+               goto err_hack;
+
+       r = hdmi_i2c2_hack_resume_mcasp();
+       if (r)
+               goto err_hack;
+
+       hdmi_i2c2_hack_demux(&pdev->dev, SEL_I2C2);
 
-       config_demux(&pdev->dev, SEL_I2C2);
+       register_pm_notifier(&hdmi_i2c2_hack_pm_notif_block);
 
        r = devm_gpio_request_one(&pdev->dev, ddata->ct_cp_hpd_gpio,
                        GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd");
@@ -475,6 +476,10 @@ static int tpd_probe(struct platform_device *pdev)
 err_reg:
 err_debounce:
 err_gpio:
+       hdmi_i2c2_hack_suspend_mcasp();
+err_hack:
+       tpd_uninit_pins(pdev);
+err_pins:
        omap_dss_put_device(ddata->in);
        return r;
 }
@@ -485,6 +490,12 @@ static int __exit tpd_remove(struct platform_device *pdev)
        struct omap_dss_device *dssdev = &ddata->dssdev;
        struct omap_dss_device *in = ddata->in;
 
+       tpd_uninit_pins(pdev);
+
+       unregister_pm_notifier(&hdmi_i2c2_hack_pm_notif_block);
+
+       hdmi_i2c2_hack_suspend_mcasp();
+
        omapdss_unregister_output(&ddata->dssdev);
 
        WARN_ON(omapdss_device_is_enabled(dssdev));
index 415c32453614297277475bbae43a16c2675452c2..c69dc72c3053b337a2fd17d4a55c4a5c1ebd4521 100644 (file)
@@ -41,8 +41,7 @@ struct sii9022_audio {
        u32 i2s_fifo_routing[4];
 };
 
-static int sii9022_dai_digital_mute(struct snd_soc_dai *dai,
-                                   int mute)
+static int sii9022_mute(struct snd_soc_dai *dai, int mute)
 {
        struct panel_drv_data *dd = dev_get_drvdata(dai->dev);
        u8 channel_layout = dd->audio->channels > 2 ?
@@ -191,9 +190,8 @@ static int sii9022_audio_start(struct snd_soc_dai *dai,
        ret = sii9022_select_mclk_div(&i2s_config_reg, params_rate(params),
                                      dd->audio->mclk);
        if (ret)
-               dev_info(dai->dev, "No matching mclk divider %u/%u != %d\n",
-                        dd->audio->mclk, params_rate(params),
-                        ret);
+               dev_warn(dai->dev, "Inaccurate reference clock (%u/%d != %u)\n",
+                        dd->audio->mclk, ret, params_rate(params));
 
        switch (params_rate(params)) {
        case 32000:
@@ -237,7 +235,7 @@ static int sii9022_audio_start(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       ret = sii9022_dai_digital_mute(dai, true);
+       ret = sii9022_mute(dai, true);
        if (ret < 0)
                return ret;
 
@@ -292,11 +290,21 @@ static int sii9022_dai_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *dai)
 {
+       struct panel_drv_data *dd = dev_get_drvdata(dai->dev);
+       int r;
+
        dev_dbg(dai->dev, "%s: format %d rate %d channels %d\n", __func__,
                params_format(params),
                params_rate(params),
                params_channels(params));
-       return sii9022_audio_start(dai, params);
+
+       mutex_lock(&dd->lock);
+
+       r = sii9022_audio_start(dai, params);
+
+       mutex_unlock(&dd->lock);
+
+       return r;
 }
 
 static int sii9022_dai_set_sysclk(struct snd_soc_dai *dai,
@@ -317,11 +325,28 @@ static int sii9022_dai_set_fmt(struct snd_soc_dai *dai,
        return 0;
 }
 
+static int sii9022_dai_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct panel_drv_data *dd = dev_get_drvdata(dai->dev);
+       int r;
+
+       mutex_lock(&dd->lock);
+       r = sii9022_mute(dai, mute);
+       mutex_unlock(&dd->lock);
+
+       return r;
+}
+
 static void sii9022_dai_shutdown(struct snd_pcm_substream *s,
                                 struct snd_soc_dai *dai)
 {
+       struct panel_drv_data *dd = dev_get_drvdata(dai->dev);
+
        dev_dbg(dai->dev, "%s called\n", __func__);
+
+       mutex_lock(&dd->lock);
        sii9022_audio_stop(dai);
+       mutex_unlock(&dd->lock);
 }
 
 static struct snd_soc_dai_ops sii9022_dai_ops = {
index 4aee140adda3aad05fc7e3b022a32a11f7eec187..0b48af124179d62f3b40f992a90b48faf6bdd190 100644 (file)
@@ -457,7 +457,7 @@ static void sii9022_handle_hpd(struct panel_drv_data *ddata)
        }
 }
 
-static irqreturn_t dispc_irq_handler(int irq, void *arg)
+static irqreturn_t sii9022_irq_handler(int irq, void *arg)
 {
        struct panel_drv_data *ddata = arg;
 
@@ -517,7 +517,7 @@ static int sii9022_connect(struct omap_dss_device *dssdev,
                schedule_delayed_work(&ddata->work, msecs_to_jiffies(250));
        } else {
                r = devm_request_threaded_irq(dev, ddata->irq,
-                       NULL, dispc_irq_handler,
+                       NULL, sii9022_irq_handler,
                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                        "sii9022 int", ddata);
                if (r) {
@@ -671,27 +671,16 @@ static int sii9022_check_timings(struct omap_dss_device *dssdev,
        return in->ops.dpi->check_timings(in, timings);
 }
 
-static int sii9022_read_edid(struct omap_dss_device *dssdev,
+static int _sii9022_read_edid(struct panel_drv_data *ddata,
                u8 *edid, int len)
 {
-       struct panel_drv_data *ddata = to_panel_data(dssdev);
        struct i2c_client *client = ddata->i2c_client;
        unsigned ctrl_reg;
        int r, l, bytes_read;
 
-       mutex_lock(&ddata->lock);
-
-       if (ddata->use_polling)
-               sii9022_handle_hpd(ddata);
-
-       if (ddata->htplg_state == false) {
-               r = -ENODEV;
-               goto err_hpd;
-       }
-
        r = sii9022_request_ddc_access(ddata, &ctrl_reg);
        if (r)
-               goto err_ddc_request;
+               return r;
 
        l = min(len, EDID_LENGTH);
 
@@ -717,16 +706,54 @@ static int sii9022_read_edid(struct omap_dss_device *dssdev,
        if (r)
                goto err_ddc_read;
 
+       return bytes_read;
+
+err_ddc_read:
+       sii9022_release_ddc_access(ddata, ctrl_reg);
+
+       return r;
+}
+
+static int sii9022_read_edid(struct omap_dss_device *dssdev,
+               u8 *edid, int len)
+{
+       struct panel_drv_data *ddata = to_panel_data(dssdev);
+       int r;
+
+       mutex_lock(&ddata->lock);
+
+       if (ddata->use_polling)
+               sii9022_handle_hpd(ddata);
+
+       if (ddata->htplg_state == false) {
+               r = -ENODEV;
+               goto err_hpd;
+       }
+
+       /*
+        * Sometimes we get -EREMOTEIO. The reason is unclear, but doing an i2c
+        * read to SiI9022 after requesting the DDC access seems to cause
+        * -EREMOTEIO both from the first i2c read and from the subsequent EDID
+        * read. We don't do that, but it could mean that SiI9022 has some
+        * issues around the DDC access.
+        *
+        * Retrying the EDID read solves the problem.
+        */
+
+       r = _sii9022_read_edid(ddata, edid, len);
+       if (r == -EREMOTEIO)
+               r = _sii9022_read_edid(ddata, edid, len);
+       if (r < 0)
+               goto err_ddc_read;
+
        print_hex_dump_debug("EDID: ", DUMP_PREFIX_NONE, 16, 1, edid,
-               bytes_read, false);
+               r, false);
 
        mutex_unlock(&ddata->lock);
 
-       return bytes_read;
+       return r;
 
 err_ddc_read:
-       sii9022_release_ddc_access(ddata, ctrl_reg);
-err_ddc_request:
 err_hpd:
        mutex_unlock(&ddata->lock);
 
index 83779c2b292ad466311a235402a4c7564f9f0a14..bc638bfd61d6d238943e18d4f2d954dc53d5a05b 100644 (file)
@@ -616,6 +616,13 @@ static void dispc_mgr_disable_digit_out(void)
 
 void dispc_mgr_enable_sync(enum omap_channel channel)
 {
+       struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel);
+
+       if (mgr->output->output_type == OMAP_DISPLAY_TYPE_HDMI) {
+               dispc_mgr_enable(channel, true);
+               return;
+       }
+
        if (dss_mgr_is_lcd(channel))
                dispc_mgr_enable_lcd_out(channel);
        else if (channel == OMAP_DSS_CHANNEL_DIGIT)
@@ -626,6 +633,13 @@ void dispc_mgr_enable_sync(enum omap_channel channel)
 
 void dispc_mgr_disable_sync(enum omap_channel channel)
 {
+       struct omap_overlay_manager *mgr = omap_dss_get_overlay_manager(channel);
+
+       if (mgr->output->output_type == OMAP_DISPLAY_TYPE_HDMI) {
+               dispc_mgr_enable(channel, false);
+               return;
+       }
+
        if (dss_mgr_is_lcd(channel))
                dispc_mgr_disable_lcd_out(channel);
        else if (channel == OMAP_DSS_CHANNEL_DIGIT)
index d05d1551b1bdf141e46aa9aa019dfb24a6cc2a4d..6697b5e3e3ee3042d4e4829cfa70b4765bdceeca 100644 (file)
@@ -102,6 +102,9 @@ struct dispc_features {
 
        /* polarities must be programmed to CTRL_CORE_SMA_SW_1 also */
        bool has_ctrl_core_sma_sw_1:1;
+
+       /* PIXEL_INC is not added to the last pixel of a line */
+       bool last_pixel_inc_missing:1;
 };
 
 #define DISPC_MAX_NR_FIFOS 5
@@ -1747,6 +1750,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation,
                        row_repeat = false;
        }
 
+       /*
+        * OMAP4/5 Errata i631:
+        * NV12 in 1D mode must use ROTATION=1. Otherwise DSS will fetch extra
+        * rows beyond the framebuffer, which may cause OCP error.
+        */
+       if (color_mode == OMAP_DSS_COLOR_NV12 &&
+                       rotation_type != OMAP_DSS_ROT_TILER)
+               vidrot = 1;
+
        REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
        if (dss_has_feature(FEAT_ROWREPEATENABLE))
                REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane),
@@ -2160,7 +2172,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk,
        if (height > out_height) {
                unsigned int ppl = mgr_timings->x_res;
 
-               tmp = pclk * height * out_width;
+               tmp = (u64)pclk * height * out_width;
                do_div(tmp, 2 * out_height * ppl);
                core_clk = tmp;
 
@@ -2168,14 +2180,14 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk,
                        if (ppl == out_width)
                                return 0;
 
-                       tmp = pclk * (height - 2 * out_height) * out_width;
+                       tmp = (u64)pclk * (height - 2 * out_height) * out_width;
                        do_div(tmp, 2 * out_height * (ppl - out_width));
                        core_clk = max_t(u32, core_clk, tmp);
                }
        }
 
        if (width > out_width) {
-               tmp = pclk * width;
+               tmp = (u64)pclk * width;
                do_div(tmp, out_width);
                core_clk = max_t(u32, core_clk, tmp);
 
@@ -2273,6 +2285,11 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
                }
        } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
 
+       if (error) {
+               DSSERR("failed to find scaling settings\n");
+               return -EINVAL;
+       }
+
        if (in_width > maxsinglelinewidth) {
                DSSERR("Cannot scale max input width exceeded");
                return -EINVAL;
@@ -2289,7 +2306,6 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
 {
        int error;
        u16 in_width, in_height;
-       int min_factor = min(*decim_x, *decim_y);
        const int maxsinglelinewidth =
                        dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
 
@@ -2323,20 +2339,32 @@ again:
                error = (error || in_width > maxsinglelinewidth * 2 ||
                        (in_width > maxsinglelinewidth && *five_taps) ||
                        !*core_clk || *core_clk > dispc_core_clk_rate());
-               if (error) {
-                       if (*decim_x == *decim_y) {
-                               *decim_x = min_factor;
-                               ++*decim_y;
+
+               if (!error) {
+                       /* verify that we're inside the limits of scaler */
+                       if (in_width / 4 > out_width)
+                                       error = 1;
+
+                       if (*five_taps) {
+                               if (in_height / 4 > out_height)
+                                       error = 1;
                        } else {
-                               swap(*decim_x, *decim_y);
-                               if (*decim_x < *decim_y)
-                                       ++*decim_x;
+                               if (in_height / 2 > out_height)
+                                       error = 1;
                        }
                }
+
+               if (error)
+                       ++*decim_y;
        } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
 
-       if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
-                               height, out_width, out_height, *five_taps)) {
+       if (error) {
+               DSSERR("failed to find scaling settings\n");
+               return -EINVAL;
+       }
+
+       if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width,
+                               in_height, out_width, out_height, *five_taps)) {
                        DSSERR("horizontal timing too tight\n");
                        return -EINVAL;
        }
@@ -2396,6 +2424,9 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
        return 0;
 }
 
+#define DIV_FRAC(dividend, divisor) \
+       ((dividend) * 100 / (divisor) - ((dividend) / (divisor) * 100))
+
 static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
                enum omap_overlay_caps caps,
                const struct omap_video_timings *mgr_timings,
@@ -2455,8 +2486,19 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
        if (ret)
                return ret;
 
-       DSSDBG("required core clk rate = %lu Hz\n", core_clk);
-       DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
+       DSSDBG("%dx%d -> %dx%d (%d.%02d x %d.%02d), decim %dx%d %dx%d (%d.%02d x %d.%02d), taps %d, req clk %lu, cur clk %lu\n",
+               width, height,
+               out_width, out_height,
+               out_width / width, DIV_FRAC(out_width, width),
+               out_height / height, DIV_FRAC(out_height, height),
+
+               decim_x, decim_y,
+               width / decim_x, height / decim_y,
+               out_width / (width / decim_x), DIV_FRAC(out_width, width / decim_x),
+               out_height / (height / decim_y), DIV_FRAC(out_height, height / decim_y),
+
+               *five_taps ? 5 : 3,
+               core_clk, dispc_core_clk_rate());
 
        if (!core_clk || core_clk > dispc_core_clk_rate()) {
                DSSERR("failed to set up scaling, "
@@ -2674,6 +2716,9 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
                dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
        }
 
+       if (dispc.feat->last_pixel_inc_missing)
+               row_inc += pix_inc - 1;
+
        dispc_ovl_set_row_inc(plane, row_inc);
        dispc_ovl_set_pix_inc(plane, pix_inc);
 
@@ -3759,6 +3804,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
        .no_framedone_tv        =       true,
        .set_max_preload        =       false,
        .alt_clk_dsi_pll        =       false,
+       .last_pixel_inc_missing =       true,
 };
 
 static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
@@ -3780,6 +3826,7 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
        .no_framedone_tv        =       true,
        .set_max_preload        =       false,
        .alt_clk_dsi_pll        =       true,
+       .last_pixel_inc_missing =       true,
 };
 
 static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
@@ -3801,6 +3848,7 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
        .no_framedone_tv        =       true,
        .set_max_preload        =       false,
        .alt_clk_dsi_pll        =       true,
+       .last_pixel_inc_missing =       true,
 };
 
 static const struct dispc_features omap44xx_dispc_feats __initconst = {
index ca4fbeca296e30ced6e45bd7e1bdbd40d646d03a..f3e43eff0ee55963691291095dcb1f562c6d1f0c 100644 (file)
@@ -252,43 +252,25 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
        /* tv size */
        dss_mgr_set_timings(mgr, p);
 
-       r = hdmi_wp_video_start(&hdmi.wp);
-       if (r)
-               goto err_vid_enable;
-
-       /*
-        * XXX Seems that on we easily get a flood of sync-lost errors when
-        * enabling the output. This seems to be related to the time between
-        * HDMI VSYNC and enabling the DISPC output.
-        *
-        * Testing shows that the sync-lost errors do not happen if we enable
-        * the DISPC output very soon after HDMI VBLANK. So wait here for
-        * VBLANK to reduce the chances of sync-losts.
-        */
-       hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC);
-
-       while (true) {
-               u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW);
-               if (v & HDMI_IRQ_VIDEO_VSYNC)
-                       break;
-               usleep_range(500, 1000);
-       }
-
        r = dss_mgr_enable(mgr);
        if (r)
                goto err_mgr_enable;
 
+       r = hdmi_wp_video_start(&hdmi.wp);
+       if (r)
+               goto err_vid_enable;
+
        hdmi_wp_set_irqenable(wp,
                HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
 
        return 0;
 
-err_mgr_enable:
-       hdmi_wp_video_stop(&hdmi.wp);
 err_vid_enable:
-err_phy_cfg:
+       dss_mgr_disable(mgr);
+err_mgr_enable:
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 err_phy_pwr:
+err_phy_cfg:
        hdmi_pll_disable(&hdmi.wp);
 err_pll_enable:
        hdmi_power_off_core(dssdev);
@@ -298,41 +280,13 @@ err_pll_enable:
 static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 {
        struct omap_overlay_manager *mgr = hdmi.output.manager;
-       const struct omap_video_timings *t;
-       unsigned vblank;
 
        hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
 
-       /*
-        * XXX Seems that on we easily get a flood of sync-lost errors when
-        * disabling the output, and sometimes the DISPC seems to get stuck and
-        * we never get FRAMEDONE. This seems to happen if we disable DISPC
-        * output during HDMI VBLANK.
-        *
-        * To reduce the possibility for sync-lost errors, calculate the time
-        * for the vertical blanking, wait for VBLANK, then wait until VBLANK
-        * ends.
-        */
-       t = &hdmi.cfg.timings;
-       vblank = t->hfp + t->hsw + t->hbp + t->x_res;
-       vblank *= t->vsw + t->vbp;
-       vblank = (vblank * 1000) / (t->pixelclock / 1000);
-
-       hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC);
-
-       while (true) {
-               u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW);
-               if (v & HDMI_IRQ_VIDEO_VSYNC)
-                       break;
-               usleep_range(500, 1000);
-       }
-
-       usleep_range(vblank, vblank + 1000);
+       hdmi_wp_video_stop(&hdmi.wp);
 
        dss_mgr_disable(mgr);
 
-       hdmi_wp_video_stop(&hdmi.wp);
-
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 
        hdmi_pll_disable(&hdmi.wp);
@@ -657,7 +611,6 @@ static int audio_enable(struct device *dev, bool enable)
        if (!enable)
                hd->audio_abort_cb = NULL;
 
-out:
        mutex_unlock(&hd->lock);
 
        return ret;
index 7eafea5b8e190c15f03a51e12ca28ad830acc647..fa72e735dad2f995c127a265cd6b82a43bf9c73c 100644 (file)
@@ -654,6 +654,13 @@ static void hdmi_core_audio_infoframe_cfg(struct hdmi_core_data *core,
        hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3);
        sum += info_aud->db3;
 
+       /*
+        * The OMAP HDMI IP requires to use the 8-channel channel code when
+        * transmitting more than two channels.
+        */
+       if (info_aud->db4_ca != 0x00)
+               info_aud->db4_ca = 0x13;
+
        hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca);
        sum += info_aud->db4_ca;
 
@@ -795,7 +802,9 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
 
        /*
         * the HDMI IP needs to enable four stereo channels when transmitting
-        * more than 2 audio channels
+        * more than 2 audio channels.  Similarly, the channel count in the
+        * Audio InfoFrame has to match the sample_present bits (some channels
+        * are padded with zeroes)
         */
        if (channel_count == 2) {
                audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
@@ -807,6 +816,7 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
                                HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
                                HDMI_AUDIO_I2S_SD3_EN;
                acore.layout = HDMI_AUDIO_LAYOUT_8CH;
+               audio->cea->db1_ct_cc = 7;
        }
 
        acore.en_spdif = false;
index e50c11f4b475c2b807d10eb57092b5d178b884dc..14c0d611a19d143093cc0e170e4f19f0309ab080 100644 (file)
@@ -273,40 +273,22 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
        /* tv size */
        dss_mgr_set_timings(mgr, p);
 
-       r = hdmi_wp_video_start(&hdmi.wp);
-       if (r)
-               goto err_vid_enable;
-
-       /*
-        * XXX Seems that on we easily get a flood of sync-lost errors when
-        * enabling the output. This seems to be related to the time between
-        * HDMI VSYNC and enabling the DISPC output.
-        *
-        * Testing shows that the sync-lost errors do not happen if we enable
-        * the DISPC output very soon after HDMI VBLANK. So wait here for
-        * VBLANK to reduce the chances of sync-losts.
-        */
-       hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC);
-
-       while (true) {
-               u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW);
-               if (v & HDMI_IRQ_VIDEO_VSYNC)
-                       break;
-               usleep_range(500, 1000);
-       }
-
        r = dss_mgr_enable(mgr);
        if (r)
                goto err_mgr_enable;
 
+       r = hdmi_wp_video_start(&hdmi.wp);
+       if (r)
+               goto err_vid_enable;
+
        hdmi_wp_set_irqenable(&hdmi.wp,
                        HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
 
        return 0;
 
-err_mgr_enable:
-       hdmi_wp_video_stop(&hdmi.wp);
 err_vid_enable:
+       dss_mgr_disable(mgr);
+err_mgr_enable:
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 err_phy_pwr:
 err_phy_cfg:
@@ -319,41 +301,13 @@ err_pll_enable:
 static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 {
        struct omap_overlay_manager *mgr = hdmi.output.manager;
-       const struct omap_video_timings *t;
-       unsigned vblank;
 
        hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
 
-       /*
-        * XXX Seems that on we easily get a flood of sync-lost errors when
-        * disabling the output, and sometimes the DISPC seems to get stuck and
-        * we never get FRAMEDONE. This seems to happen if we disable DISPC
-        * output during HDMI VBLANK.
-        *
-        * To reduce the possibility for sync-lost errors, calculate the time
-        * for the vertical blanking, wait for VBLANK, then wait until VBLANK
-        * ends.
-        */
-       t = &hdmi.cfg.timings;
-       vblank = t->hfp + t->hsw + t->hbp + t->x_res;
-       vblank *= t->vsw + t->vbp;
-       vblank = (vblank * 1000) / (t->pixelclock / 1000);
-
-       hdmi_write_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_VSYNC);
-
-       while (true) {
-               u32 v = hdmi_read_reg(hdmi.wp.base, HDMI_WP_IRQSTATUS_RAW);
-               if (v & HDMI_IRQ_VIDEO_VSYNC)
-                       break;
-               usleep_range(500, 1000);
-       }
-
-       usleep_range(vblank, vblank + 1000);
+       hdmi_wp_video_stop(&hdmi.wp);
 
        dss_mgr_disable(mgr);
 
-       hdmi_wp_video_stop(&hdmi.wp);
-
        hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
 
        hdmi_pll_disable(&hdmi.wp);
index f3b19309c04f98a0dc8466102e4f88befdaa89eb..e5f6321cc39d40f19744b8090d4881dd3deb527e 100644 (file)
@@ -790,7 +790,9 @@ static void hdmi5_core_audio_infoframe_cfg(struct hdmi_core_data *core,
 
        hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF1, info_aud->db2_sf_ss);
        hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF2, info_aud->db4_ca);
-       hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF3, info_aud->db5_dminh_lsv);
+       hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF3,
+         (info_aud->db5_dminh_lsv & CEA861_AUDIO_INFOFRAME_DB5_DM_INH) >> 3 |
+         (info_aud->db5_dminh_lsv & CEA861_AUDIO_INFOFRAME_DB5_LSV));
 }
 
 int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
@@ -870,6 +872,7 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
        audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
        audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
        audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
+       audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
 
        /* only LPCM atm */
        audio_format.type = HDMI_AUDIO_TYPE_LPCM;
index 5154120dfae5f9acbaeb8609ec96c65d0f2ea68f..cc8a49950e4b4d0dfe4fa619cb4d9eba27950c5b 100644 (file)
@@ -110,7 +110,23 @@ int hdmi_wp_video_start(struct hdmi_wp_data *wp)
 
 void hdmi_wp_video_stop(struct hdmi_wp_data *wp)
 {
+       int i;
+
+       hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, HDMI_IRQ_VIDEO_FRAME_DONE);
+
        REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31);
+
+       for (i = 0; i < 50; ++i) {
+               u32 v;
+
+               msleep(20);
+
+               v = hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS_RAW);
+               if (v & HDMI_IRQ_VIDEO_FRAME_DONE)
+                       return;
+       }
+
+       DSSERR("no HDMI FRAMEDONE when disabling output\n");
 }
 
 void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
index d7ff9175730747488aac13569ed6125c3ae1a6ca..843e5d8538bd60ee376c780825bdfd2bf558c5c6 100644 (file)
@@ -352,6 +352,15 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static void evtchn_2l_resume(void)
+{
+       int i;
+
+       for_each_online_cpu(i)
+               memset(per_cpu(cpu_evtchn_mask, i), 0, sizeof(xen_ulong_t) *
+                               EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD);
+}
+
 static const struct evtchn_ops evtchn_ops_2l = {
        .max_channels      = evtchn_2l_max_channels,
        .nr_channels       = evtchn_2l_max_channels,
@@ -363,6 +372,7 @@ static const struct evtchn_ops evtchn_ops_2l = {
        .mask              = evtchn_2l_mask,
        .unmask            = evtchn_2l_unmask,
        .handle_events     = evtchn_2l_handle_events,
+       .resume            = evtchn_2l_resume,
 };
 
 void __init xen_evtchn_2l_init(void)
index f4a9e3311297b7b562f9235dae03e92b9266a9cc..a5cc476256f19dfbdacf86a76324c28314016d5b 100644 (file)
@@ -547,20 +547,26 @@ static unsigned int __startup_pirq(unsigned int irq)
        pirq_query_unmask(irq);
 
        rc = set_evtchn_to_irq(evtchn, irq);
-       if (rc != 0) {
-               pr_err("irq%d: Failed to set port to irq mapping (%d)\n",
-                      irq, rc);
-               xen_evtchn_close(evtchn);
-               return 0;
-       }
-       bind_evtchn_to_cpu(evtchn, 0);
+       if (rc)
+               goto err;
+
        info->evtchn = evtchn;
+       bind_evtchn_to_cpu(evtchn, 0);
+
+       rc = xen_evtchn_port_setup(info);
+       if (rc)
+               goto err;
 
 out:
        unmask_evtchn(evtchn);
        eoi_pirq(irq_get_irq_data(irq));
 
        return 0;
+
+err:
+       pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc);
+       xen_evtchn_close(evtchn);
+       return 0;
 }
 
 static unsigned int startup_pirq(struct irq_data *data)
@@ -1288,8 +1294,9 @@ void rebind_evtchn_irq(int evtchn, int irq)
 
        mutex_unlock(&irq_mapping_update_lock);
 
-       /* new event channels are always bound to cpu 0 */
-       irq_set_affinity(irq, cpumask_of(0));
+        bind_evtchn_to_cpu(evtchn, info->cpu);
+       /* This will be deferred until interrupt is processed */
+       irq_set_affinity(irq, cpumask_of(info->cpu));
 
        /* Unmask the event channel. */
        enable_irq(irq);
index 46ae0f9f02adcca044734c58f56a93ca12801f85..75fe3d466515a08cf8ec8da7eebafd8c5b903895 100644 (file)
@@ -16,7 +16,7 @@
 #include "conf_space.h"
 #include "conf_space_quirks.h"
 
-static bool permissive;
+bool permissive;
 module_param(permissive, bool, 0644);
 
 /* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
index e56c934ad137be00ce34e5099726e31472e86a93..2e1d73d1d5d09393ebf7e2ab21a026b709e5bb5f 100644 (file)
@@ -64,6 +64,8 @@ struct config_field_entry {
        void *data;
 };
 
+extern bool permissive;
+
 #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
 
 /* Add fields to a device - the add_fields macro expects to get a pointer to
index c5ee82587e8cc3b5feb5e594763da576765fd268..2d7369391472fd572dd3f5b837be3a2625ab4a93 100644 (file)
 #include "pciback.h"
 #include "conf_space.h"
 
+struct pci_cmd_info {
+       u16 val;
+};
+
 struct pci_bar_info {
        u32 val;
        u32 len_val;
@@ -20,22 +24,36 @@ struct pci_bar_info {
 #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
 #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
 
-static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
+/* Bits guests are allowed to control in permissive mode. */
+#define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \
+                          PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \
+                          PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK)
+
+static void *command_init(struct pci_dev *dev, int offset)
 {
-       int i;
-       int ret;
-
-       ret = xen_pcibk_read_config_word(dev, offset, value, data);
-       if (!pci_is_enabled(dev))
-               return ret;
-
-       for (i = 0; i < PCI_ROM_RESOURCE; i++) {
-               if (dev->resource[i].flags & IORESOURCE_IO)
-                       *value |= PCI_COMMAND_IO;
-               if (dev->resource[i].flags & IORESOURCE_MEM)
-                       *value |= PCI_COMMAND_MEMORY;
+       struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+       int err;
+
+       if (!cmd)
+               return ERR_PTR(-ENOMEM);
+
+       err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val);
+       if (err) {
+               kfree(cmd);
+               return ERR_PTR(err);
        }
 
+       return cmd;
+}
+
+static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
+{
+       int ret = pci_read_config_word(dev, offset, value);
+       const struct pci_cmd_info *cmd = data;
+
+       *value &= PCI_COMMAND_GUEST;
+       *value |= cmd->val & ~PCI_COMMAND_GUEST;
+
        return ret;
 }
 
@@ -43,6 +61,8 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
 {
        struct xen_pcibk_dev_data *dev_data;
        int err;
+       u16 val;
+       struct pci_cmd_info *cmd = data;
 
        dev_data = pci_get_drvdata(dev);
        if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
@@ -83,6 +103,19 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
                }
        }
 
+       cmd->val = value;
+
+       if (!permissive && (!dev_data || !dev_data->permissive))
+               return 0;
+
+       /* Only allow the guest to control certain bits. */
+       err = pci_read_config_word(dev, offset, &val);
+       if (err || val == value)
+               return err;
+
+       value &= PCI_COMMAND_GUEST;
+       value |= val & ~PCI_COMMAND_GUEST;
+
        return pci_write_config_word(dev, offset, value);
 }
 
@@ -282,6 +315,8 @@ static const struct config_field header_common[] = {
        {
         .offset    = PCI_COMMAND,
         .size      = 2,
+        .init      = command_init,
+        .release   = bar_release,
         .u.w.read  = command_read,
         .u.w.write = command_write,
        },
index d9a43674cb9479eb673140121e60ee0355acf409..9cca0ea4e47909a11a91eebf48653c957d68f5b1 100644 (file)
@@ -126,7 +126,7 @@ affs_fix_dcache(struct inode *inode, u32 entry_ino)
 {
        struct dentry *dentry;
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                if (entry_ino == (u32)(long)dentry->d_fsdata) {
                        dentry->d_fsdata = (void *)inode->i_ino;
                        break;
index 2f7e8c2e3e769c04f50b233c7f7f113b523e7e40..3241659491b1b80e78d133b04444c79b507dc0fe 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -719,6 +719,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 err_cleanup:
        aio_nr_sub(ctx->max_reqs);
 err_ctx:
+       atomic_set(&ctx->dead, 1);
+       if (ctx->mmap_size)
+               vm_munmap(ctx->mmap_base, ctx->mmap_size);
        aio_free_ring(ctx);
 err:
        mutex_unlock(&ctx->ring_lock);
index 3182c0e68b4204cb2aec089b5d960b7053534757..e3399dc2453b0c51537dba1d9ef91b0ffc082659 100644 (file)
@@ -95,7 +95,7 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param)
  */
 static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in)
 {
-       struct autofs_dev_ioctl tmp;
+       struct autofs_dev_ioctl tmp, *res;
 
        if (copy_from_user(&tmp, in, sizeof(tmp)))
                return ERR_PTR(-EFAULT);
@@ -103,7 +103,11 @@ static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *i
        if (tmp.size < sizeof(tmp))
                return ERR_PTR(-EINVAL);
 
-       return memdup_user(in, tmp.size);
+       res = memdup_user(in, tmp.size);
+       if (!IS_ERR(res))
+               res->size = tmp.size;
+
+       return res;
 }
 
 static inline void free_dev_ioctl(struct autofs_dev_ioctl *param)
index 394e90b02c5e60783b828a2d39d7698806505930..edb46e67d5cab4898df2f12b5a0a67b7c50e08d7 100644 (file)
@@ -91,7 +91,7 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev,
        spin_lock(&root->d_lock);
 
        if (prev)
-               next = prev->d_u.d_child.next;
+               next = prev->d_child.next;
        else {
                prev = dget_dlock(root);
                next = prev->d_subdirs.next;
@@ -105,13 +105,13 @@ cont:
                return NULL;
        }
 
-       q = list_entry(next, struct dentry, d_u.d_child);
+       q = list_entry(next, struct dentry, d_child);
 
        spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
        /* Already gone or negative dentry (under construction) - try next */
        if (!d_count(q) || !simple_positive(q)) {
                spin_unlock(&q->d_lock);
-               next = q->d_u.d_child.next;
+               next = q->d_child.next;
                goto cont;
        }
        dget_dlock(q);
@@ -161,13 +161,13 @@ again:
                                goto relock;
                        }
                        spin_unlock(&p->d_lock);
-                       next = p->d_u.d_child.next;
+                       next = p->d_child.next;
                        p = parent;
                        if (next != &parent->d_subdirs)
                                break;
                }
        }
-       ret = list_entry(next, struct dentry, d_u.d_child);
+       ret = list_entry(next, struct dentry, d_child);
 
        spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
        /* Negative dentry - try next */
@@ -461,7 +461,7 @@ found:
        spin_lock(&sbi->lookup_lock);
        spin_lock(&expired->d_parent->d_lock);
        spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
-       list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
+       list_move(&expired->d_parent->d_subdirs, &expired->d_child);
        spin_unlock(&expired->d_lock);
        spin_unlock(&expired->d_parent->d_lock);
        spin_unlock(&sbi->lookup_lock);
index cc87c1abac9710169cd56ad44a78cf7185da2834..9e016e6fb582d3df3cbe993988090cdb75fd9dbd 100644 (file)
@@ -655,7 +655,7 @@ static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
        /* only consider parents below dentrys in the root */
        if (IS_ROOT(parent->d_parent))
                return;
-       d_child = &dentry->d_u.d_child;
+       d_child = &dentry->d_child;
        /* Set parent managed if it's becoming empty */
        if (d_child->next == &parent->d_subdirs &&
            d_child->prev == &parent->d_subdirs)
index f4d7b2fc9ffbc19a336d8abe2095e7cf990da52c..78f46089a0778fbc3b7b549962c5896c2a72c795 100644 (file)
@@ -751,6 +751,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
            i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
                int elf_prot = 0, elf_flags;
                unsigned long k, vaddr;
+               unsigned long total_size = 0;
 
                if (elf_ppnt->p_type != PT_LOAD)
                        continue;
@@ -815,10 +816,16 @@ static int load_elf_binary(struct linux_binprm *bprm)
 #else
                        load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 #endif
+                       total_size = total_mapping_size(elf_phdata,
+                                                       loc->elf_ex.e_phnum);
+                       if (!total_size) {
+                               error = -EINVAL;
+                               goto out_free_dentry;
+                       }
                }
 
                error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-                               elf_prot, elf_flags, 0);
+                               elf_prot, elf_flags, total_size);
                if (BAD_ADDR(error)) {
                        send_sig(SIGKILL, current, 0);
                        retval = IS_ERR((void *)error) ?
index d2f1c011d73ab3025e3056585b0ce7568be1747a..794d7c6ea9ee4c4105acc0a2c2dfbd63d9bf19d9 100644 (file)
@@ -6645,12 +6645,11 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
                return -ENOSPC;
        }
 
-       if (btrfs_test_opt(root, DISCARD))
-               ret = btrfs_discard_extent(root, start, len, NULL);
-
        if (pin)
                pin_down_extent(root, cache, start, len, 1);
        else {
+               if (btrfs_test_opt(root, DISCARD))
+                       ret = btrfs_discard_extent(root, start, len, NULL);
                btrfs_add_free_space(cache, start, len);
                btrfs_update_reserved_bytes(cache, len, RESERVE_FREE);
        }
index 279b06ef5522f70e07bbb401cfb0babc2dced37d..0a841ddd6843cbe4dfbd6f1981940bfa93953e93 100644 (file)
@@ -1774,22 +1774,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
        mutex_unlock(&inode->i_mutex);
 
        /*
-        * we want to make sure fsync finds this change
-        * but we haven't joined a transaction running right now.
-        *
-        * Later on, someone is sure to update the inode and get the
-        * real transid recorded.
-        *
-        * We set last_trans now to the fs_info generation + 1,
-        * this will either be one more than the running transaction
-        * or the generation used for the next transaction if there isn't
-        * one running right now.
-        *
         * We also have to set last_sub_trans to the current log transid,
         * otherwise subsequent syncs to a file that's been synced in this
         * transaction will appear to have already occured.
         */
-       BTRFS_I(inode)->last_trans = root->fs_info->generation + 1;
        BTRFS_I(inode)->last_sub_trans = root->log_transid;
        if (num_written > 0) {
                err = generic_write_sync(file, pos, num_written);
@@ -1892,25 +1880,37 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        atomic_inc(&root->log_batch);
 
        /*
-        * check the transaction that last modified this inode
-        * and see if its already been committed
-        */
-       if (!BTRFS_I(inode)->last_trans) {
-               mutex_unlock(&inode->i_mutex);
-               goto out;
-       }
-
-       /*
-        * if the last transaction that changed this file was before
-        * the current transaction, we can bail out now without any
-        * syncing
+        * If the last transaction that changed this file was before the current
+        * transaction and we have the full sync flag set in our inode, we can
+        * bail out now without any syncing.
+        *
+        * Note that we can't bail out if the full sync flag isn't set. This is
+        * because when the full sync flag is set we start all ordered extents
+        * and wait for them to fully complete - when they complete they update
+        * the inode's last_trans field through:
+        *
+        *     btrfs_finish_ordered_io() ->
+        *         btrfs_update_inode_fallback() ->
+        *             btrfs_update_inode() ->
+        *                 btrfs_set_inode_last_trans()
+        *
+        * So we are sure that last_trans is up to date and can do this check to
+        * bail out safely. For the fast path, when the full sync flag is not
+        * set in our inode, we can not do it because we start only our ordered
+        * extents and don't wait for them to complete (that is when
+        * btrfs_finish_ordered_io runs), so here at this point their last_trans
+        * value might be less than or equals to fs_info->last_trans_committed,
+        * and setting a speculative last_trans for an inode when a buffered
+        * write is made (such as fs_info->generation + 1 for example) would not
+        * be reliable since after setting the value and before fsync is called
+        * any number of transactions can start and commit (transaction kthread
+        * commits the current transaction periodically), and a transaction
+        * commit does not start nor waits for ordered extents to complete.
         */
        smp_mb();
        if (btrfs_inode_in_log(inode, root->fs_info->generation) ||
-           BTRFS_I(inode)->last_trans <=
-           root->fs_info->last_trans_committed) {
-               BTRFS_I(inode)->last_trans = 0;
-
+           (full_sync && BTRFS_I(inode)->last_trans <=
+            root->fs_info->last_trans_committed)) {
                /*
                 * We'v had everything committed since the last time we were
                 * modified so clear this flag in case it was set for whatever
index d68a7250f00b913c9f3ff81fe4190884af70ab58..653cdd85e0f2bca75ed05ead5e79a196d7934c88 100644 (file)
@@ -6870,7 +6870,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
            ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) &&
             em->block_start != EXTENT_MAP_HOLE)) {
                int type;
-               int ret;
                u64 block_start, orig_start, orig_block_len, ram_bytes;
 
                if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
index 0b72006aecbece81402764a23808ec4e8e33f35e..3e16042338e497de38ee1ba2530ebdf6d0c59c63 100644 (file)
@@ -2708,6 +2708,9 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 len,
        if (src == dst)
                return -EINVAL;
 
+       if (len == 0)
+               return 0;
+
        btrfs_double_lock(src, loff, dst, dst_loff, len);
 
        ret = extent_same_check_offsets(src, loff, len);
@@ -3226,6 +3229,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
        if (off + len == src->i_size)
                len = ALIGN(src->i_size, bs) - off;
 
+       if (len == 0) {
+               ret = 0;
+               goto out_unlock;
+       }
+
        /* verify the end result is block aligned */
        if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) ||
            !IS_ALIGNED(destoff, bs))
index aeb57b98c53f33050a5a4bd1a9311885c3349685..ec8b6542c8bd3b4535b616db698d52a1f3a245d3 100644 (file)
@@ -979,7 +979,7 @@ again:
                base = btrfs_item_ptr_offset(leaf, path->slots[0]);
 
                while (cur_offset < item_size) {
-                       extref = (struct btrfs_inode_extref *)base + cur_offset;
+                       extref = (struct btrfs_inode_extref *)(base + cur_offset);
 
                        victim_name_len = btrfs_inode_extref_name_len(leaf, extref);
 
@@ -1235,21 +1235,13 @@ out:
 }
 
 static int insert_orphan_item(struct btrfs_trans_handle *trans,
-                             struct btrfs_root *root, u64 offset)
+                             struct btrfs_root *root, u64 ino)
 {
        int ret;
-       struct btrfs_path *path;
-
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
 
-       ret = btrfs_find_item(root, path, BTRFS_ORPHAN_OBJECTID,
-                       offset, BTRFS_ORPHAN_ITEM_KEY, NULL);
-       if (ret > 0)
-               ret = btrfs_insert_orphan_item(trans, root, offset);
-
-       btrfs_free_path(path);
+       ret = btrfs_insert_orphan_item(trans, root, ino);
+       if (ret == -EEXIST)
+               ret = 0;
 
        return ret;
 }
index ad8328d797ea9910c21f0ecd5db6051d347a4571..488e987c337495276c74868bc25b796293bea8be 100644 (file)
@@ -324,22 +324,42 @@ const struct xattr_handler *btrfs_xattr_handlers[] = {
 /*
  * Check if the attribute is in a supported namespace.
  *
- * This applied after the check for the synthetic attributes in the system
+ * This is applied after the check for the synthetic attributes in the system
  * namespace.
  */
-static bool btrfs_is_valid_xattr(const char *name)
+static int btrfs_is_valid_xattr(const char *name)
 {
-       return !strncmp(name, XATTR_SECURITY_PREFIX,
-                       XATTR_SECURITY_PREFIX_LEN) ||
-              !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
-              !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
-              !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) ||
-               !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN);
+       int len = strlen(name);
+       int prefixlen = 0;
+
+       if (!strncmp(name, XATTR_SECURITY_PREFIX,
+                       XATTR_SECURITY_PREFIX_LEN))
+               prefixlen = XATTR_SECURITY_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               prefixlen = XATTR_SYSTEM_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+               prefixlen = XATTR_TRUSTED_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+               prefixlen = XATTR_USER_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
+               prefixlen = XATTR_BTRFS_PREFIX_LEN;
+       else
+               return -EOPNOTSUPP;
+
+       /*
+        * The name cannot consist of just prefix
+        */
+       if (len <= prefixlen)
+               return -EINVAL;
+
+       return 0;
 }
 
 ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
                       void *buffer, size_t size)
 {
+       int ret;
+
        /*
         * If this is a request for a synthetic attribute in the system.*
         * namespace use the generic infrastructure to resolve a handler
@@ -348,8 +368,9 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_getxattr(dentry, name, buffer, size);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
        return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
 }
 
@@ -357,6 +378,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                   size_t size, int flags)
 {
        struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+       int ret;
 
        /*
         * The permission on security.* and system.* is not checked
@@ -373,8 +395,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_setxattr(dentry, name, value, size, flags);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
 
        if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
                return btrfs_set_prop(dentry->d_inode, name,
@@ -390,6 +413,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 int btrfs_removexattr(struct dentry *dentry, const char *name)
 {
        struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+       int ret;
 
        /*
         * The permission on security.* and system.* is not checked
@@ -406,8 +430,9 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_removexattr(dentry, name);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
 
        if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
                return btrfs_set_prop(dentry->d_inode, name,
index 5e0982aa7000a978c0d3640a7eddefe55a02ba3a..18e14cf8f2235161af5cef237402839026e6dd09 100644 (file)
@@ -111,7 +111,7 @@ static int fpos_cmp(loff_t l, loff_t r)
 /*
  * When possible, we try to satisfy a readdir by peeking at the
  * dcache.  We make this work by carefully ordering dentries on
- * d_u.d_child when we initially get results back from the MDS, and
+ * d_child when we initially get results back from the MDS, and
  * falling back to a "normal" sync readdir if any dentries in the dir
  * are dropped.
  *
@@ -146,11 +146,11 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx)
                p = parent->d_subdirs.prev;
                dout(" initial p %p/%p\n", p->prev, p->next);
        } else {
-               p = last->d_u.d_child.prev;
+               p = last->d_child.prev;
        }
 
 more:
-       dentry = list_entry(p, struct dentry, d_u.d_child);
+       dentry = list_entry(p, struct dentry, d_child);
        di = ceph_dentry(dentry);
        while (1) {
                dout(" p %p/%p %s d_subdirs %p/%p\n", p->prev, p->next,
@@ -172,7 +172,7 @@ more:
                     !dentry->d_inode ? " null" : "");
                spin_unlock(&dentry->d_lock);
                p = p->prev;
-               dentry = list_entry(p, struct dentry, d_u.d_child);
+               dentry = list_entry(p, struct dentry, d_child);
                di = ceph_dentry(dentry);
        }
 
index 6471f9c83428d3558ca0924145b661ace28d1f50..ee24490ee9252241dc6d796037bb63daa062e1b1 100644 (file)
@@ -1289,7 +1289,7 @@ retry_lookup:
                        /* reorder parent's d_subdirs */
                        spin_lock(&parent->d_lock);
                        spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
-                       list_move(&dn->d_u.d_child, &parent->d_subdirs);
+                       list_move(&dn->d_child, &parent->d_subdirs);
                        spin_unlock(&dn->d_lock);
                        spin_unlock(&parent->d_lock);
                }
index 0218a9b23b38526847bd4fd26f8cd6812d487632..40ddb6e9391223fd8211c314bd4b74d7af3233db 100644 (file)
@@ -1821,6 +1821,7 @@ refind_writable:
                        cifsFileInfo_put(inv_file);
                        spin_lock(&cifs_file_list_lock);
                        ++refind;
+                       inv_file = NULL;
                        goto refind_writable;
                }
        }
index f2ddcf7ac9c3ad0b5cfa261c5a8f3889336ef23a..7ee427e16f3b207e7fdbed87a024ef5313162bae 100644 (file)
@@ -883,7 +883,7 @@ inode_has_hashed_dentries(struct inode *inode)
        struct dentry *dentry;
 
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
                        spin_unlock(&inode->i_lock);
                        return true;
index 34a17d425be611c2675b6709d3537de7d8f1ed25..30f3eb5bc022869f0192379abf3fb83bd9f3b4bb 100644 (file)
@@ -630,7 +630,8 @@ smb2_clone_range(const unsigned int xid,
 
                        /* No need to change MaxChunks since already set to 1 */
                        chunk_sizes_updated = true;
-               }
+               } else
+                       goto cchunk_out;
        }
 
 cchunk_out:
index 1da168c61d35c2194422fa24c5bca3235a1c19ca..9bc1147a6c5d4d5666f948500d1ec0ccbc4413b4 100644 (file)
@@ -92,7 +92,7 @@ static void coda_flag_children(struct dentry *parent, int flag)
        struct dentry *de;
 
        spin_lock(&parent->d_lock);
-       list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) {
+       list_for_each_entry(de, &parent->d_subdirs, d_child) {
                /* don't know what to do with negative dentries */
                if (de->d_inode ) 
                        coda_flag_inode(de->d_inode, flag);
index 8d1c8697ebdadcee31cab70b0d0334405e91c32d..105ece700237988cf1d9ba9f034818d963a3961f 100644 (file)
@@ -44,7 +44,7 @@
 /*
  * Usage:
  * dcache->d_inode->i_lock protects:
- *   - i_dentry, d_alias, d_inode of aliases
+ *   - i_dentry, d_u.d_alias, d_inode of aliases
  * dcache_hash_bucket lock protects:
  *   - the dcache hash table
  * s_anon bl list spinlock protects:
@@ -59,7 +59,7 @@
  *   - d_unhashed()
  *   - d_parent and d_subdirs
  *   - childrens' d_child and d_parent
- *   - d_alias, d_inode
+ *   - d_u.d_alias, d_inode
  *
  * Ordering:
  * dentry->d_inode->i_lock
@@ -239,7 +239,6 @@ static void __d_free(struct rcu_head *head)
 {
        struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
 
-       WARN_ON(!hlist_unhashed(&dentry->d_alias));
        if (dname_external(dentry))
                kfree(dentry->d_name.name);
        kmem_cache_free(dentry_cache, dentry); 
@@ -250,6 +249,7 @@ static void __d_free(struct rcu_head *head)
  */
 static void d_free(struct dentry *dentry)
 {
+       WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias));
        BUG_ON((int)dentry->d_lockref.count > 0);
        this_cpu_dec(nr_dentry);
        if (dentry->d_op && dentry->d_op->d_release)
@@ -288,7 +288,7 @@ static void dentry_iput(struct dentry * dentry)
        struct inode *inode = dentry->d_inode;
        if (inode) {
                dentry->d_inode = NULL;
-               hlist_del_init(&dentry->d_alias);
+               hlist_del_init(&dentry->d_u.d_alias);
                spin_unlock(&dentry->d_lock);
                spin_unlock(&inode->i_lock);
                if (!inode->i_nlink)
@@ -313,7 +313,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
        struct inode *inode = dentry->d_inode;
        __d_clear_type(dentry);
        dentry->d_inode = NULL;
-       hlist_del_init(&dentry->d_alias);
+       hlist_del_init(&dentry->d_u.d_alias);
        dentry_rcuwalk_barrier(dentry);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&inode->i_lock);
@@ -435,7 +435,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
        __releases(parent->d_lock)
        __releases(dentry->d_inode->i_lock)
 {
-       list_del(&dentry->d_u.d_child);
+       __list_del_entry(&dentry->d_child);
        /*
         * Inform d_walk() that we are no longer attached to the
         * dentry tree
@@ -737,7 +737,7 @@ static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
 
 again:
        discon_alias = NULL;
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&alias->d_lock);
                if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
                        if (IS_ROOT(alias) &&
@@ -790,7 +790,7 @@ void d_prune_aliases(struct inode *inode)
        struct dentry *dentry;
 restart:
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (!dentry->d_lockref.count) {
                        /*
@@ -1091,7 +1091,7 @@ repeat:
 resume:
        while (next != &this_parent->d_subdirs) {
                struct list_head *tmp = next;
-               struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
+               struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
                next = tmp->next;
 
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
@@ -1123,33 +1123,31 @@ resume:
        /*
         * All done at this level ... ascend and resume the search.
         */
+       rcu_read_lock();
+ascend:
        if (this_parent != parent) {
                struct dentry *child = this_parent;
                this_parent = child->d_parent;
 
-               rcu_read_lock();
                spin_unlock(&child->d_lock);
                spin_lock(&this_parent->d_lock);
 
-               /*
-                * might go back up the wrong parent if we have had a rename
-                * or deletion
-                */
-               if (this_parent != child->d_parent ||
-                        (child->d_flags & DCACHE_DENTRY_KILLED) ||
-                        need_seqretry(&rename_lock, seq)) {
-                       spin_unlock(&this_parent->d_lock);
-                       rcu_read_unlock();
+               /* might go back up the wrong parent if we have had a rename. */
+               if (need_seqretry(&rename_lock, seq))
                        goto rename_retry;
+               next = child->d_child.next;
+               while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+                       if (next == &this_parent->d_subdirs)
+                               goto ascend;
+                       child = list_entry(next, struct dentry, d_child);
+                       next = next->next;
                }
                rcu_read_unlock();
-               next = child->d_u.d_child.next;
                goto resume;
        }
-       if (need_seqretry(&rename_lock, seq)) {
-               spin_unlock(&this_parent->d_lock);
+       if (need_seqretry(&rename_lock, seq))
                goto rename_retry;
-       }
+       rcu_read_unlock();
        if (finish)
                finish(data);
 
@@ -1159,6 +1157,9 @@ out_unlock:
        return;
 
 rename_retry:
+       spin_unlock(&this_parent->d_lock);
+       rcu_read_unlock();
+       BUG_ON(seq & 1);
        if (!retry)
                return;
        seq = 1;
@@ -1524,8 +1525,8 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
        INIT_HLIST_BL_NODE(&dentry->d_hash);
        INIT_LIST_HEAD(&dentry->d_lru);
        INIT_LIST_HEAD(&dentry->d_subdirs);
-       INIT_HLIST_NODE(&dentry->d_alias);
-       INIT_LIST_HEAD(&dentry->d_u.d_child);
+       INIT_HLIST_NODE(&dentry->d_u.d_alias);
+       INIT_LIST_HEAD(&dentry->d_child);
        d_set_d_op(dentry, dentry->d_sb->s_d_op);
 
        this_cpu_inc(nr_dentry);
@@ -1555,7 +1556,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
         */
        __dget_dlock(parent);
        dentry->d_parent = parent;
-       list_add(&dentry->d_u.d_child, &parent->d_subdirs);
+       list_add(&dentry->d_child, &parent->d_subdirs);
        spin_unlock(&parent->d_lock);
 
        return dentry;
@@ -1648,7 +1649,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        spin_lock(&dentry->d_lock);
        __d_set_type(dentry, add_flags);
        if (inode)
-               hlist_add_head(&dentry->d_alias, &inode->i_dentry);
+               hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
        dentry->d_inode = inode;
        dentry_rcuwalk_barrier(dentry);
        spin_unlock(&dentry->d_lock);
@@ -1672,7 +1673,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
  
 void d_instantiate(struct dentry *entry, struct inode * inode)
 {
-       BUG_ON(!hlist_unhashed(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
        if (inode)
                spin_lock(&inode->i_lock);
        __d_instantiate(entry, inode);
@@ -1711,7 +1712,7 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
                return NULL;
        }
 
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                /*
                 * Don't need alias->d_lock here, because aliases with
                 * d_parent == entry->d_parent are not subject to name or
@@ -1737,7 +1738,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
 {
        struct dentry *result;
 
-       BUG_ON(!hlist_unhashed(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
 
        if (inode)
                spin_lock(&inode->i_lock);
@@ -1768,7 +1769,7 @@ EXPORT_SYMBOL(d_instantiate_unique);
  */
 int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode)
 {
-       BUG_ON(!hlist_unhashed(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
 
        spin_lock(&inode->i_lock);
        if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) {
@@ -1807,7 +1808,7 @@ static struct dentry * __d_find_any_alias(struct inode *inode)
 
        if (hlist_empty(&inode->i_dentry))
                return NULL;
-       alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        __dget(alias);
        return alias;
 }
@@ -1884,7 +1885,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
        spin_lock(&tmp->d_lock);
        tmp->d_inode = inode;
        tmp->d_flags |= add_flags;
-       hlist_add_head(&tmp->d_alias, &inode->i_dentry);
+       hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry);
        hlist_bl_lock(&tmp->d_sb->s_anon);
        hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
        hlist_bl_unlock(&tmp->d_sb->s_anon);
@@ -2327,7 +2328,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
        struct dentry *child;
 
        spin_lock(&dparent->d_lock);
-       list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) {
+       list_for_each_entry(child, &dparent->d_subdirs, d_child) {
                if (dentry == child) {
                        spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
                        __dget_dlock(dentry);
@@ -2574,8 +2575,8 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
        /* Unhash the target: dput() will then get rid of it */
        __d_drop(target);
 
-       list_del(&dentry->d_u.d_child);
-       list_del(&target->d_u.d_child);
+       list_del(&dentry->d_child);
+       list_del(&target->d_child);
 
        /* Switch the names.. */
        switch_names(dentry, target);
@@ -2585,15 +2586,15 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
        if (IS_ROOT(dentry)) {
                dentry->d_parent = target->d_parent;
                target->d_parent = target;
-               INIT_LIST_HEAD(&target->d_u.d_child);
+               INIT_LIST_HEAD(&target->d_child);
        } else {
                swap(dentry->d_parent, target->d_parent);
 
                /* And add them back to the (new) parent lists */
-               list_add(&target->d_u.d_child, &target->d_parent->d_subdirs);
+               list_add(&target->d_child, &target->d_parent->d_subdirs);
        }
 
-       list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
+       list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
 
        write_seqcount_end(&target->d_seq);
        write_seqcount_end(&dentry->d_seq);
@@ -2700,9 +2701,9 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
        swap(dentry->d_name.hash, anon->d_name.hash);
 
        dentry->d_parent = dentry;
-       list_del_init(&dentry->d_u.d_child);
+       list_del_init(&dentry->d_child);
        anon->d_parent = dparent;
-       list_move(&anon->d_u.d_child, &dparent->d_subdirs);
+       list_move(&anon->d_child, &dparent->d_subdirs);
 
        write_seqcount_end(&dentry->d_seq);
        write_seqcount_end(&anon->d_seq);
@@ -3334,7 +3335,7 @@ void d_tmpfile(struct dentry *dentry, struct inode *inode)
 {
        inode_dec_link_count(inode);
        BUG_ON(dentry->d_name.name != dentry->d_iname ||
-               !hlist_unhashed(&dentry->d_alias) ||
+               !hlist_unhashed(&dentry->d_u.d_alias) ||
                !d_unlinked(dentry));
        spin_lock(&dentry->d_parent->d_lock);
        spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
index 15761957cc3f2c6937b2cc6453fdeeb4b383b8c2..4a9f0e0c6644f45a6350a08f00cfc042ac0960c4 100644 (file)
@@ -245,10 +245,19 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root)
        return 0;
 }
 
+static void debugfs_evict_inode(struct inode *inode)
+{
+       truncate_inode_pages(&inode->i_data, 0);
+       clear_inode(inode);
+       if (S_ISLNK(inode->i_mode))
+               kfree(inode->i_private);
+}
+
 static const struct super_operations debugfs_super_operations = {
        .statfs         = simple_statfs,
        .remount_fs     = debugfs_remount,
        .show_options   = debugfs_show_options,
+       .evict_inode    = debugfs_evict_inode,
 };
 
 static int debug_fill_super(struct super_block *sb, void *data, int silent)
@@ -465,23 +474,14 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
        int ret = 0;
 
        if (debugfs_positive(dentry)) {
-               if (dentry->d_inode) {
-                       dget(dentry);
-                       switch (dentry->d_inode->i_mode & S_IFMT) {
-                       case S_IFDIR:
-                               ret = simple_rmdir(parent->d_inode, dentry);
-                               break;
-                       case S_IFLNK:
-                               kfree(dentry->d_inode->i_private);
-                               /* fall through */
-                       default:
-                               simple_unlink(parent->d_inode, dentry);
-                               break;
-                       }
-                       if (!ret)
-                               d_delete(dentry);
-                       dput(dentry);
-               }
+               dget(dentry);
+               if (S_ISDIR(dentry->d_inode->i_mode))
+                       ret = simple_rmdir(parent->d_inode, dentry);
+               else
+                       simple_unlink(parent->d_inode, dentry);
+               if (!ret)
+                       d_delete(dentry);
+               dput(dentry);
        }
        return ret;
 }
@@ -552,7 +552,7 @@ void debugfs_remove_recursive(struct dentry *dentry)
         * use the d_u.d_child as the rcu head and corrupt this list.
         */
        spin_lock(&parent->d_lock);
-       list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) {
+       list_for_each_entry(child, &parent->d_subdirs, d_child) {
                if (!debugfs_positive(child))
                        continue;
 
index ea4449d0536a7c79e36605d2512eba3b7d15541e..05f1942d7edba5e4086562c7beea27389b4d99ca 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1268,6 +1268,53 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
        spin_unlock(&p->fs->lock);
 }
 
+static void bprm_fill_uid(struct linux_binprm *bprm)
+{
+       struct inode *inode;
+       unsigned int mode;
+       kuid_t uid;
+       kgid_t gid;
+
+       /* clear any previous set[ug]id data from a previous binary */
+       bprm->cred->euid = current_euid();
+       bprm->cred->egid = current_egid();
+
+       if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
+               return;
+
+       if (current->no_new_privs)
+               return;
+
+       inode = file_inode(bprm->file);
+       mode = ACCESS_ONCE(inode->i_mode);
+       if (!(mode & (S_ISUID|S_ISGID)))
+               return;
+
+       /* Be careful if suid/sgid is set */
+       mutex_lock(&inode->i_mutex);
+
+       /* reload atomically mode/uid/gid now that lock held */
+       mode = inode->i_mode;
+       uid = inode->i_uid;
+       gid = inode->i_gid;
+       mutex_unlock(&inode->i_mutex);
+
+       /* We ignore suid/sgid if there are no mappings for them in the ns */
+       if (!kuid_has_mapping(bprm->cred->user_ns, uid) ||
+                !kgid_has_mapping(bprm->cred->user_ns, gid))
+               return;
+
+       if (mode & S_ISUID) {
+               bprm->per_clear |= PER_CLEAR_ON_SETID;
+               bprm->cred->euid = uid;
+       }
+
+       if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+               bprm->per_clear |= PER_CLEAR_ON_SETID;
+               bprm->cred->egid = gid;
+       }
+}
+
 /*
  * Fill the binprm structure from the inode.
  * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
@@ -1276,36 +1323,9 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
  */
 int prepare_binprm(struct linux_binprm *bprm)
 {
-       struct inode *inode = file_inode(bprm->file);
-       umode_t mode = inode->i_mode;
        int retval;
 
-
-       /* clear any previous set[ug]id data from a previous binary */
-       bprm->cred->euid = current_euid();
-       bprm->cred->egid = current_egid();
-
-       if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
-           !current->no_new_privs &&
-           kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) &&
-           kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) {
-               /* Set-uid? */
-               if (mode & S_ISUID) {
-                       bprm->per_clear |= PER_CLEAR_ON_SETID;
-                       bprm->cred->euid = inode->i_uid;
-               }
-
-               /* Set-gid? */
-               /*
-                * If setgid is set but no group execute bit then this
-                * is a candidate for mandatory locking, not a setgid
-                * executable.
-                */
-               if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
-                       bprm->per_clear |= PER_CLEAR_ON_SETID;
-                       bprm->cred->egid = inode->i_gid;
-               }
-       }
+       bprm_fill_uid(bprm);
 
        /* fill in binprm security blob */
        retval = security_bprm_set_creds(bprm);
index 48a359dd286e79b08062db77ffdc593be92a2cb6..831d4f057e158ccf70828ac5e982b07f7fb353da 100644 (file)
@@ -50,7 +50,7 @@ find_acceptable_alias(struct dentry *result,
 
        inode = result->d_inode;
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                dget(dentry);
                spin_unlock(&inode->i_lock);
                if (toput)
index 171b9fa0f27af0d7271a7014f42d911995e20d99..4e8b79def9c7a7659f86f4a7c4b38b6421b8caa6 100644 (file)
@@ -656,6 +656,14 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 
        BUG_ON(end < lblk);
 
+       if ((status & EXTENT_STATUS_DELAYED) &&
+           (status & EXTENT_STATUS_WRITTEN)) {
+               ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as "
+                               " delayed and written which can potentially "
+                               " cause data loss.\n", lblk, len);
+               WARN_ON(1);
+       }
+
        newes.es_lblk = lblk;
        newes.es_len = len;
        ext4_es_store_pblock(&newes, pblk);
index 3a7e0341447fb58fdfd7279f48af7a27caf95591..da03340fdb17ee5f8587f0187528159e14deaac7 100644 (file)
@@ -569,6 +569,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
+                   !(status & EXTENT_STATUS_WRITTEN) &&
                    ext4_find_delalloc_range(inode, map->m_lblk,
                                             map->m_lblk + map->m_len - 1))
                        status |= EXTENT_STATUS_DELAYED;
@@ -678,6 +679,7 @@ found:
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
+                   !(status & EXTENT_STATUS_WRITTEN) &&
                    ext4_find_delalloc_range(inode, map->m_lblk,
                                             map->m_lblk + map->m_len - 1))
                        status |= EXTENT_STATUS_DELAYED;
index 2dcbfb6245d8c4b689e55f288fbb63b0fadce35d..bc7e37bc0c5b21647d490acb7850b1f135a48164 100644 (file)
@@ -1869,7 +1869,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                          struct inode *inode)
 {
        struct inode *dir = dentry->d_parent->d_inode;
-       struct buffer_head *bh;
+       struct buffer_head *bh = NULL;
        struct ext4_dir_entry_2 *de;
        struct ext4_dir_entry_tail *t;
        struct super_block *sb;
@@ -1893,14 +1893,14 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                        return retval;
                if (retval == 1) {
                        retval = 0;
-                       return retval;
+                       goto out;
                }
        }
 
        if (is_dx(dir)) {
                retval = ext4_dx_add_entry(handle, dentry, inode);
                if (!retval || (retval != ERR_BAD_DX_DIR))
-                       return retval;
+                       goto out;
                ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
                dx_fallback++;
                ext4_mark_inode_dirty(handle, dir);
@@ -1912,14 +1912,15 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                        return PTR_ERR(bh);
 
                retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
-               if (retval != -ENOSPC) {
-                       brelse(bh);
-                       return retval;
-               }
+               if (retval != -ENOSPC)
+                       goto out;
 
                if (blocks == 1 && !dx_fallback &&
-                   EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
-                       return make_indexed_dir(handle, dentry, inode, bh);
+                   EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+                       retval = make_indexed_dir(handle, dentry, inode, bh);
+                       bh = NULL; /* make_indexed_dir releases bh */
+                       goto out;
+               }
                brelse(bh);
        }
        bh = ext4_append(handle, dir, &block);
@@ -1935,6 +1936,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        }
 
        retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
+out:
        brelse(bh);
        if (retval == 0)
                ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY);
index 6eb13c621a14f24aa3eede3ab1d24a654f85f908..499155ca3e84243a7e575bfb4b6094ee0dc8bbce 100644 (file)
@@ -819,8 +819,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
 
        newpage = buf->page;
 
-       if (WARN_ON(!PageUptodate(newpage)))
-               return -EIO;
+       if (!PageUptodate(newpage))
+               SetPageUptodate(newpage);
 
        ClearPageMappedToDisk(newpage);
 
@@ -1726,6 +1726,9 @@ copy_finish:
 static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
                       unsigned int size, struct fuse_copy_state *cs)
 {
+       /* Don't try to move pages (yet) */
+       cs->move_pages = 0;
+
        switch (code) {
        case FUSE_NOTIFY_POLL:
                return fuse_notify_poll(fc, size, cs);
index 6e560d56094b2ccaf7091ec784a6a039af214f43..754fdf8c6356388f16bbdc285240394b350bd90e 100644 (file)
@@ -131,13 +131,16 @@ skip:
        hfs_bnode_write(node, entry, data_off + key_len, entry_len);
        hfs_bnode_dump(node);
 
-       if (new_node) {
-               /* update parent key if we inserted a key
-                * at the start of the first node
-                */
-               if (!rec && new_node != node)
-                       hfs_brec_update_parent(fd);
+       /*
+        * update parent key if we inserted a key
+        * at the start of the node and it is not the new node
+        */
+       if (!rec && new_node != node) {
+               hfs_bnode_read_key(node, fd->search_key, data_off + size);
+               hfs_brec_update_parent(fd);
+       }
 
+       if (new_node) {
                hfs_bnode_put(fd->bnode);
                if (!new_node->parent) {
                        hfs_btree_inc_height(tree);
@@ -168,9 +171,6 @@ skip:
                goto again;
        }
 
-       if (!rec)
-               hfs_brec_update_parent(fd);
-
        return 0;
 }
 
@@ -370,6 +370,8 @@ again:
        if (IS_ERR(parent))
                return PTR_ERR(parent);
        __hfs_brec_find(parent, fd, hfs_find_rec_by_key);
+       if (fd->record < 0)
+               return -ENOENT;
        hfs_bnode_dump(parent);
        rec = fd->record;
 
index a1844244246f8e8e8da60da61e2aaabd2750e58e..868c0b70a30e8eb11b84f4581e54a93a27e98d8b 100644 (file)
@@ -113,18 +113,18 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
 
                        spin_lock(&dentry->d_lock);
                        /* d_lock not required for cursor */
-                       list_del(&cursor->d_u.d_child);
+                       list_del(&cursor->d_child);
                        p = dentry->d_subdirs.next;
                        while (n && p != &dentry->d_subdirs) {
                                struct dentry *next;
-                               next = list_entry(p, struct dentry, d_u.d_child);
+                               next = list_entry(p, struct dentry, d_child);
                                spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
                                if (simple_positive(next))
                                        n--;
                                spin_unlock(&next->d_lock);
                                p = p->next;
                        }
-                       list_add_tail(&cursor->d_u.d_child, p);
+                       list_add_tail(&cursor->d_child, p);
                        spin_unlock(&dentry->d_lock);
                }
        }
@@ -149,7 +149,7 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
 {
        struct dentry *dentry = file->f_path.dentry;
        struct dentry *cursor = file->private_data;
-       struct list_head *p, *q = &cursor->d_u.d_child;
+       struct list_head *p, *q = &cursor->d_child;
 
        if (!dir_emit_dots(file, ctx))
                return 0;
@@ -158,7 +158,7 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
                list_move(q, &dentry->d_subdirs);
 
        for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
-               struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
+               struct dentry *next = list_entry(p, struct dentry, d_child);
                spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
                if (!simple_positive(next)) {
                        spin_unlock(&next->d_lock);
@@ -286,7 +286,7 @@ int simple_empty(struct dentry *dentry)
        int ret = 0;
 
        spin_lock(&dentry->d_lock);
-       list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+       list_for_each_entry(child, &dentry->d_subdirs, d_child) {
                spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
                if (simple_positive(child)) {
                        spin_unlock(&child->d_lock);
index 0dd72c8e65fd45a8423f4135bbafc1ef717516f6..ccb8000f3459995e6cb750d98d1ed3bcacbffcf1 100644 (file)
@@ -1545,7 +1545,8 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
 
        if (should_follow_link(path->dentry, follow)) {
                if (nd->flags & LOOKUP_RCU) {
-                       if (unlikely(unlazy_walk(nd, path->dentry))) {
+                       if (unlikely(nd->path.mnt != path->mnt ||
+                                    unlazy_walk(nd, path->dentry))) {
                                err = -ECHILD;
                                goto out_err;
                        }
@@ -2992,7 +2993,8 @@ finish_lookup:
 
        if (should_follow_link(path->dentry, !symlink_ok)) {
                if (nd->flags & LOOKUP_RCU) {
-                       if (unlikely(unlazy_walk(nd, path->dentry))) {
+                       if (unlikely(nd->path.mnt != path->mnt ||
+                                    unlazy_walk(nd, path->dentry))) {
                                error = -ECHILD;
                                goto out;
                        }
index 039f3802d70efed3d5e2b5efea811dde3d41e69d..2faa7eacb62b6318b5c77ce8a59cdbd21b5d38c7 100644 (file)
@@ -3025,6 +3025,12 @@ bool fs_fully_visible(struct file_system_type *type)
                if (mnt->mnt.mnt_sb->s_type != type)
                        continue;
 
+               /* This mount is not fully visible if it's root directory
+                * is not the root directory of the filesystem.
+                */
+               if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root)
+                       continue;
+
                /* This mount is not fully visible if there are any child mounts
                 * that cover anything except for empty directories.
                 */
index c320ac52353e458723f46613893bcc0423ccc463..dc9747d6a4d09dc0b6aec989700566068213738a 100644 (file)
@@ -406,7 +406,7 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dent = list_entry(next, struct dentry, d_u.d_child);
+               dent = list_entry(next, struct dentry, d_child);
                if ((unsigned long)dent->d_fsdata == fpos) {
                        if (dent->d_inode)
                                dget(dent);
index 32c06587351a138f34b09955802ad397c5b6a5f3..6d5e7c56c79d44ef177d9a1741b86ac457d4ff82 100644 (file)
@@ -194,7 +194,7 @@ ncp_renew_dentries(struct dentry *parent)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dentry = list_entry(next, struct dentry, d_u.d_child);
+               dentry = list_entry(next, struct dentry, d_child);
 
                if (dentry->d_fsdata == NULL)
                        ncp_age_dentry(server, dentry);
@@ -216,7 +216,7 @@ ncp_invalidate_dircache_entries(struct dentry *parent)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dentry = list_entry(next, struct dentry, d_u.d_child);
+               dentry = list_entry(next, struct dentry, d_child);
                dentry->d_fsdata = NULL;
                ncp_age_dentry(server, dentry);
                next = next->next;
index 3ed1be9aade33c82031443a5f8612e248dc78fc2..2ea3537b8bdee61421f1a3f3606760ffd7fed199 100644 (file)
@@ -161,8 +161,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
                                  &delegation->flags);
                        NFS_I(inode)->delegation_state = delegation->type;
                        spin_unlock(&delegation->lock);
-                       put_rpccred(oldcred);
                        rcu_read_unlock();
+                       put_rpccred(oldcred);
                        trace_nfs4_reclaim_delegation(inode, res->delegation_type);
                } else {
                        /* We appear to have raced with a delegation return. */
index 66984a9aafaad9ad74d81415d5737cbafad81618..5b8ab0e444f97056741e6f0160909108105e1dea 100644 (file)
@@ -58,7 +58,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
                 */
                spin_lock(&sb->s_root->d_inode->i_lock);
                spin_lock(&sb->s_root->d_lock);
-               hlist_del_init(&sb->s_root->d_alias);
+               hlist_del_init(&sb->s_root->d_u.d_alias);
                spin_unlock(&sb->s_root->d_lock);
                spin_unlock(&sb->s_root->d_inode->i_lock);
        }
index b2e3ff34762070a4b37085c051223809b59e4a6c..090d8ce25bd1036e53c26ce46e9340ee7d0a6180 100644 (file)
@@ -31,6 +31,8 @@
 #include "alloc.h"
 #include "dat.h"
 
+static void __nilfs_btree_init(struct nilfs_bmap *bmap);
+
 static struct nilfs_btree_path *nilfs_btree_alloc_path(void)
 {
        struct nilfs_btree_path *path;
@@ -368,6 +370,34 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
        return ret;
 }
 
+/**
+ * nilfs_btree_root_broken - verify consistency of btree root node
+ * @node: btree root node to be examined
+ * @ino: inode number
+ *
+ * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
+ */
+static int nilfs_btree_root_broken(const struct nilfs_btree_node *node,
+                                  unsigned long ino)
+{
+       int level, flags, nchildren;
+       int ret = 0;
+
+       level = nilfs_btree_node_get_level(node);
+       flags = nilfs_btree_node_get_flags(node);
+       nchildren = nilfs_btree_node_get_nchildren(node);
+
+       if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
+                    level >= NILFS_BTREE_LEVEL_MAX ||
+                    nchildren < 0 ||
+                    nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) {
+               pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n",
+                       ino, level, flags, nchildren);
+               ret = 1;
+       }
+       return ret;
+}
+
 int nilfs_btree_broken_node_block(struct buffer_head *bh)
 {
        int ret;
@@ -1713,7 +1743,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree,
 
        /* convert and insert */
        dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
-       nilfs_btree_init(btree);
+       __nilfs_btree_init(btree);
        if (nreq != NULL) {
                nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
                nilfs_bmap_commit_alloc_ptr(btree, nreq, dat);
@@ -2294,12 +2324,23 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
        .bop_gather_data        =       NULL,
 };
 
-int nilfs_btree_init(struct nilfs_bmap *bmap)
+static void __nilfs_btree_init(struct nilfs_bmap *bmap)
 {
        bmap->b_ops = &nilfs_btree_ops;
        bmap->b_nchildren_per_block =
                NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap));
-       return 0;
+}
+
+int nilfs_btree_init(struct nilfs_bmap *bmap)
+{
+       int ret = 0;
+
+       __nilfs_btree_init(bmap);
+
+       if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap),
+                                   bmap->b_inode->i_ino))
+               ret = -EIO;
+       return ret;
 }
 
 void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
index 5bee81674d5362f3184d058974aa1f0ecd70bacf..14538a8651027e8f2e8b839cc6cb9c272bb0e5cb 100644 (file)
@@ -1906,6 +1906,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
                                             struct the_nilfs *nilfs)
 {
        struct nilfs_inode_info *ii, *n;
+       int during_mount = !(sci->sc_super->s_flags & MS_ACTIVE);
        int defer_iput = false;
 
        spin_lock(&nilfs->ns_inode_lock);
@@ -1918,10 +1919,10 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
                brelse(ii->i_bh);
                ii->i_bh = NULL;
                list_del_init(&ii->i_dirty);
-               if (!ii->vfs_inode.i_nlink) {
+               if (!ii->vfs_inode.i_nlink || during_mount) {
                        /*
-                        * Defer calling iput() to avoid a deadlock
-                        * over I_SYNC flag for inodes with i_nlink == 0
+                        * Defer calling iput() to avoid deadlocks if
+                        * i_nlink == 0 or mount is not yet finished.
                         */
                        list_add_tail(&ii->i_dirty, &sci->sc_iput_queue);
                        defer_iput = true;
index 9d3e9c50066aaf5856350cf3bc85576a79bab900..700129940c6eb86418543b42a578dfce0f4942d2 100644 (file)
@@ -63,14 +63,14 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
        spin_lock(&inode->i_lock);
        /* run all of the dentries associated with this inode.  Since this is a
         * directory, there damn well better only be one item on this list */
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                struct dentry *child;
 
                /* run all of the children of the original inode and fix their
                 * d_flags to indicate parental interest (their parent is the
                 * original inode) */
                spin_lock(&alias->d_lock);
-               list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) {
+               list_for_each_entry(child, &alias->d_subdirs, d_child) {
                        if (!child->d_inode)
                                continue;
 
index 0d3a97d2d5f659caeb60f20f448ce25371036ff2..116748502baec3a337c9db93fc4d8ff8ff60a43b 100644 (file)
@@ -173,7 +173,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
        struct dentry *dentry;
 
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
                        trace_ocfs2_find_local_alias(dentry->d_name.len,
index 1be3398c96f676f574d8478616b58ab21013d587..1dd0bcc75536268779de762360c389b80c6b4d46 100644 (file)
@@ -726,6 +726,19 @@ lookup:
        if (tmpres) {
                spin_unlock(&dlm->spinlock);
                spin_lock(&tmpres->spinlock);
+
+               /*
+                * Right after dlm spinlock was released, dlm_thread could have
+                * purged the lockres. Check if lockres got unhashed. If so
+                * start over.
+                */
+               if (hlist_unhashed(&tmpres->hash_node)) {
+                       spin_unlock(&tmpres->spinlock);
+                       dlm_lockres_put(tmpres);
+                       tmpres = NULL;
+                       goto lookup;
+               }
+
                /* Wait on the thread that is mastering the resource */
                if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
                        __dlm_wait_on_lockres(tmpres);
index 51632c40e896fd0b7c4e4c87b2afc5dc4f418aca..7fe30f655aa58060da58573fa15fa4f3f8b08e18 100644 (file)
@@ -2391,10 +2391,14 @@ out_dio:
        /* buffered aio wouldn't have proper lock coverage today */
        BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
 
+       if (unlikely(written <= 0))
+               goto no_sync;
+
        if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) ||
            ((file->f_flags & O_DIRECT) && !direct_io)) {
-               ret = filemap_fdatawrite_range(file->f_mapping, *ppos,
-                                              *ppos + count - 1);
+               ret = filemap_fdatawrite_range(file->f_mapping,
+                                              iocb->ki_pos - written,
+                                              iocb->ki_pos - 1);
                if (ret < 0)
                        written = ret;
 
@@ -2407,10 +2411,12 @@ out_dio:
                }
 
                if (!ret)
-                       ret = filemap_fdatawait_range(file->f_mapping, *ppos,
-                                                     *ppos + count - 1);
+                       ret = filemap_fdatawait_range(file->f_mapping,
+                                                     iocb->ki_pos - written,
+                                                     iocb->ki_pos - 1);
        }
 
+no_sync:
        /*
         * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
         * function pointer which is called when o_direct io completes so that
index 2ed7325f713ec325a0059c59b9768ef16b7dbdc9..17679f2b2f1ca4c24171cc87523ac36bb4711e73 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -539,6 +539,7 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
        uid = make_kuid(current_user_ns(), user);
        gid = make_kgid(current_user_ns(), group);
 
+retry_deleg:
        newattrs.ia_valid =  ATTR_CTIME;
        if (user != (uid_t) -1) {
                if (!uid_valid(uid))
@@ -555,7 +556,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
        if (!S_ISDIR(inode->i_mode))
                newattrs.ia_valid |=
                        ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
-retry_deleg:
        mutex_lock(&inode->i_mutex);
        error = security_path_chown(path, uid, gid);
        if (!error)
index b7f268eb5f45251ae1977c643540e081c6612546..2e2d9d5d78d967a432100b9a20804e0f9d7293a1 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mount.h>
 #include <linux/init.h>
 #include <linux/idr.h>
-#include <linux/namei.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
@@ -162,17 +161,6 @@ void proc_free_inum(unsigned int inum)
        spin_unlock_irqrestore(&proc_inum_lock, flags);
 }
 
-static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-       nd_set_link(nd, __PDE_DATA(dentry->d_inode));
-       return NULL;
-}
-
-static const struct inode_operations proc_link_inode_operations = {
-       .readlink       = generic_readlink,
-       .follow_link    = proc_follow_link,
-};
-
 /*
  * Don't create negative dentries here, return -ENOENT by hand
  * instead.
index 124fc43c709088a46b26c90a16e251a2fd7c4f66..2f2815f3176e3382305f1b4120ba2af94c04a888 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/mount.h>
 #include <linux/magic.h>
+#include <linux/namei.h>
 
 #include <asm/uaccess.h>
 
@@ -401,6 +402,26 @@ static const struct file_operations proc_reg_file_ops_no_compat = {
 };
 #endif
 
+static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+       struct proc_dir_entry *pde = PDE(dentry->d_inode);
+       if (unlikely(!use_pde(pde)))
+               return ERR_PTR(-EINVAL);
+       nd_set_link(nd, pde->data);
+       return pde;
+}
+
+static void proc_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+{
+       unuse_pde(p);
+}
+
+const struct inode_operations proc_link_inode_operations = {
+       .readlink       = generic_readlink,
+       .follow_link    = proc_follow_link,
+       .put_link       = proc_put_link,
+};
+
 struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
 {
        struct inode *inode = new_inode_pseudo(sb);
index 651d09a11dde360a3ebabc26cc206aefb3b0515c..8b8ca1db6316583f08c57d5dd547296bc2dc2341 100644 (file)
@@ -202,6 +202,7 @@ struct pde_opener {
        int closing;
        struct completion *c;
 };
+extern const struct inode_operations proc_link_inode_operations;
 
 extern const struct inode_operations proc_pid_link_inode_operations;
 
index c4b2646b6d7c66f7b1c37d6fbaf033cc5ccaa561..eaa7374305a31c6793a15ae3a81c48f5d081753e 100644 (file)
@@ -993,9 +993,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
        struct vm_area_struct *vma;
        struct pagemapread *pm = walk->private;
        spinlock_t *ptl;
-       pte_t *pte;
+       pte_t *pte, *orig_pte;
        int err = 0;
-       pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
 
        /* find the first VMA at or above 'addr' */
        vma = find_vma(walk->mm, addr);
@@ -1009,6 +1008,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 
                for (; addr != end; addr += PAGE_SIZE) {
                        unsigned long offset;
+                       pagemap_entry_t pme;
 
                        offset = (addr & ~PAGEMAP_WALK_MASK) >>
                                        PAGE_SHIFT;
@@ -1023,32 +1023,55 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 
        if (pmd_trans_unstable(pmd))
                return 0;
-       for (; addr != end; addr += PAGE_SIZE) {
-               int flags2;
-
-               /* check to see if we've left 'vma' behind
-                * and need a new, higher one */
-               if (vma && (addr >= vma->vm_end)) {
-                       vma = find_vma(walk->mm, addr);
-                       if (vma && (vma->vm_flags & VM_SOFTDIRTY))
-                               flags2 = __PM_SOFT_DIRTY;
-                       else
-                               flags2 = 0;
-                       pme = make_pme(PM_NOT_PRESENT(pm->v2) | PM_STATUS2(pm->v2, flags2));
+
+       while (1) {
+               /* End of address space hole, which we mark as non-present. */
+               unsigned long hole_end;
+
+               if (vma)
+                       hole_end = min(end, vma->vm_start);
+               else
+                       hole_end = end;
+
+               for (; addr < hole_end; addr += PAGE_SIZE) {
+                       pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
+
+                       err = add_to_pagemap(addr, &pme, pm);
+                       if (err)
+                               return err;
                }
 
-               /* check that 'vma' actually covers this address,
-                * and that it isn't a huge page vma */
-               if (vma && (vma->vm_start <= addr) &&
-                   !is_vm_hugetlb_page(vma)) {
-                       pte = pte_offset_map(pmd, addr);
+               if (!vma || vma->vm_start >= end)
+                       break;
+               /*
+                * We can't possibly be in a hugetlb VMA. In general,
+                * for a mm_walk with a pmd_entry and a hugetlb_entry,
+                * the pmd_entry can only be called on addresses in a
+                * hugetlb if the walk starts in a non-hugetlb VMA and
+                * spans a hugepage VMA. Since pagemap_read walks are
+                * PMD-sized and PMD-aligned, this will never be true.
+                */
+               BUG_ON(is_vm_hugetlb_page(vma));
+
+               /* Addresses in the VMA. */
+               orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
+               for (; addr < min(end, vma->vm_end); pte++, addr += PAGE_SIZE) {
+                       pagemap_entry_t pme;
+
                        pte_to_pagemap_entry(&pme, pm, vma, addr, *pte);
-                       /* unmap before userspace copy */
-                       pte_unmap(pte);
+                       err = add_to_pagemap(addr, &pme, pm);
+                       if (err)
+                               break;
                }
-               err = add_to_pagemap(addr, &pme, pm);
+               pte_unmap_unlock(orig_pte, ptl);
+
                if (err)
                        return err;
+
+               if (addr == end)
+                       break;
+
+               vma = find_vma(walk->mm, addr);
        }
 
        cond_resched();
@@ -1227,6 +1250,9 @@ out:
 
 static int pagemap_open(struct inode *inode, struct file *file)
 {
+       /* do not disclose physical addresses: attack vector */
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
        pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about "
                        "to stop being page-shift some time soon. See the "
                        "linux/Documentation/vm/pagemap.txt for details.\n");
index fea6773f87fc7f5fe8e3141579ebd63b4b8efcc8..5d51f27549cc1a1c442b20bbe47f4cd25f243a55 100644 (file)
@@ -175,7 +175,7 @@ acpi_status __init acpi_load_tables(void);
  */
 acpi_status __init acpi_reallocate_root_table(void);
 
-acpi_status __init acpi_find_root_pointer(acpi_size *rsdp_address);
+acpi_status __init acpi_find_root_pointer(acpi_physical_address * rsdp_address);
 
 acpi_status acpi_unload_table_id(acpi_owner_id id);
 
index 68a3ada689c900b90b26af4ec61377cd8405472f..8fc12f80b6161f2e53e045cee3302b99249361ab 100644 (file)
@@ -198,9 +198,29 @@ typedef int INT32;
 typedef s32 acpi_native_int;
 
 typedef u32 acpi_size;
+
+#ifdef ACPI_32BIT_PHYSICAL_ADDRESS
+
+/*
+ * OSPMs can define this to shrink the size of the structures for 32-bit
+ * none PAE environment. ASL compiler may always define this to generate
+ * 32-bit OSPM compliant tables.
+ */
 typedef u32 acpi_io_address;
 typedef u32 acpi_physical_address;
 
+#else                          /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
+/*
+ * It is reported that, after some calculations, the physical addresses can
+ * wrap over the 32-bit boundary on 32-bit PAE environment.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=87971
+ */
+typedef u64 acpi_io_address;
+typedef u64 acpi_physical_address;
+
+#endif                         /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
 #define ACPI_MAX_PTR                    ACPI_UINT32_MAX
 #define ACPI_SIZE_MAX                   ACPI_UINT32_MAX
 
index b402eb67af83fd5496669eec6e8ed6fe2d168f58..579912c7156c78ac2a286c3cbeed380f545b6633 100644 (file)
@@ -76,6 +76,7 @@
 #define ACPI_LARGE_NAMESPACE_NODE
 #define ACPI_DATA_TABLE_DISASSEMBLY
 #define ACPI_SINGLE_THREADED
+#define ACPI_32BIT_PHYSICAL_ADDRESS
 #endif
 
 /* acpi_exec configuration. Multithreaded with full AML debugger */
index f1a24b5c3b906ef91804bca4f6f56b4158d93aca..b58fd667f87bc7c7b093c3cac1d293d78d89ec4d 100644 (file)
@@ -3,6 +3,8 @@
 
 /* References to section boundaries */
 
+#include <linux/compiler.h>
+
 /*
  * Usage guidelines:
  * _text, _data: architecture specific, don't use them in arch-independent code
@@ -37,6 +39,8 @@ extern char __start_rodata[], __end_rodata[];
 /* Start and end of .ctors section - used for constructor calls. */
 extern char __ctors_start[], __ctors_end[];
 
+extern __visible const void __nosave_begin, __nosave_end;
+
 /* function descriptor handling (if any).  Override
  * in asm/sections.h */
 #ifndef dereference_function_descriptor
index 4db14a267aa54cc358e97acb26b2402fe764ae7e..c934c80990b7179061c7ab1a2e256237672f4ec2 100644 (file)
@@ -19,9 +19,9 @@
 #define PULL_DISABLE           (1 << 16)
 #define PULL_UP                        (1 << 17)
 #define INPUT_EN               (1 << 18)
+#define DS0_FORCE_OFF_MODE     (1 << 24)
 #define SLEWCTRL_FAST          0
 #define SLEWCTRL_SLOW          (1 << 19)
-#define DS0_FORCE_OFF_MODE     (1 << 24)
 #define DS0_PULL_UP_DOWN_EN    (1 << 27)
 #define WAKEUP_ENABLE          (1 << 29)
 
index bbc3a6c88fce3410b954b6c91c407297e2f03e7f..33fd7ff53a77537c110261d7bf79ec099dc93b19 100644 (file)
@@ -180,7 +180,9 @@ enum rq_flag_bits {
        __REQ_ELVPRIV,          /* elevator private data attached */
        __REQ_FAILED,           /* set if the request failed */
        __REQ_QUIET,            /* don't worry about errors */
-       __REQ_PREEMPT,          /* set for "ide_preempt" requests */
+       __REQ_PREEMPT,          /* set for "ide_preempt" requests and also
+                                  for requests for which the SCSI "quiesce"
+                                  state must be ignored. */
        __REQ_ALLOCED,          /* request came from our alloc pool */
        __REQ_COPY_USER,        /* contains copies of user pages */
        __REQ_FLUSH_SEQ,        /* request for flush sequence */
index 300c7b91b75c7ea5e2c9f7c15a46f717fd9d2f8f..a418f80bb42b39b7ca3597e99cda0f1abc7552d8 100644 (file)
@@ -24,6 +24,7 @@
  * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
  * @clk_bypass: struct clk pointer to the clock's bypass clock input
  * @clk_ref: struct clk pointer to the clock's reference clock input
+ * @sink_clkdm: the main clockdomain fed by this DPLL, for errata i810 on DRA7
  * @control_reg: register containing the DPLL mode bitfield
  * @enable_mask: mask of the DPLL mode bitfield in @control_reg
  * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
@@ -71,6 +72,7 @@ struct dpll_data {
        u32                     div1_mask;
        struct clk              *clk_bypass;
        struct clk              *clk_ref;
+       struct clockdomain      *sink_clkdm;
        void __iomem            *control_reg;
        u32                     enable_mask;
        unsigned long           last_rounded_rate;
@@ -269,6 +271,7 @@ unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
 long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
                           unsigned long *parent_rate);
 void omap2_init_clk_clkdm(struct clk_hw *clk);
+void omap2_init_dpll_clkdm(struct dpll_data *dd, struct device_node *np);
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
                                    unsigned long parent_rate);
 int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
index 50fcbb0ac4e7033922508aa1fc805936087cd5f2..d1338170b6b9059e60102bf3eb8119c16936440f 100644 (file)
@@ -69,7 +69,6 @@ struct cpuidle_device {
        unsigned int            cpu;
 
        int                     last_residency;
-       int                     state_count;
        struct cpuidle_state_usage      states_usage[CPUIDLE_STATE_MAX];
        struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
        struct cpuidle_driver_kobj *kobj_driver;
index 2b00d92a6e6fcec18b0ccf532b25839813d0868e..9a00fb543a5300f367c53a78c5959671cae62471 100644 (file)
@@ -702,6 +702,12 @@ static inline struct ablkcipher_request *ablkcipher_request_cast(
        return container_of(req, struct ablkcipher_request, base);
 }
 
+static inline struct aead_request *aead_request_cast(
+                                       struct crypto_async_request *req)
+{
+       return container_of(req, struct aead_request, base);
+}
+
 static inline struct ablkcipher_request *ablkcipher_request_alloc(
        struct crypto_ablkcipher *tfm, gfp_t gfp)
 {
index 3b50cac7ccb39a51a9819514fb2dfa3204d6da34..0f0eb1c1e676c27a0d69415e2d0d4f1c088cf3cb 100644 (file)
@@ -124,15 +124,15 @@ struct dentry {
        void *d_fsdata;                 /* fs-specific data */
 
        struct list_head d_lru;         /* LRU list */
+       struct list_head d_child;       /* child of parent list */
+       struct list_head d_subdirs;     /* our children */
        /*
-        * d_child and d_rcu can share memory
+        * d_alias and d_rcu can share memory
         */
        union {
-               struct list_head d_child;       /* child of parent list */
+               struct hlist_node d_alias;      /* inode alias list */
                struct rcu_head d_rcu;
        } d_u;
-       struct list_head d_subdirs;     /* our children */
-       struct hlist_node d_alias;      /* inode alias list */
 };
 
 /*
index 337fded71aa937bde1c8f4ee416e6be4a60ef20a..4d39c71da38cc03bc63d263c2501ceecaa3d752e 100644 (file)
@@ -119,6 +119,7 @@ struct palmas_pmic_driver_data {
        int ldo_begin;
        int ldo_end;
        int max_reg;
+       bool has_regen3;
        struct palmas_regs_info *palmas_regs_info;
        struct of_regulator_match *palmas_matches;
        struct palmas_sleep_requestor_info *sleep_req_info;
@@ -3007,6 +3008,9 @@ enum usb_irq_events {
 #define PALMAS_GPADC_TRIM15                                    0x0E
 #define PALMAS_GPADC_TRIM16                                    0x0F
 
+/* TPS659038 regen2_ctrl offset iss different from palmas */
+#define TPS659038_REGEN2_CTRL                                  0x12
+
 /* TPS65917 Interrupt registers */
 
 /* Registers for function INTERRUPT */
index 2012b5e468ffe0b2fe60cc3ee0ebddd225d4274b..b12077429c056375f84ef371212b8acd2cee200c 100644 (file)
 #define TPS65218_CHIPID_CHIP_MASK      0xF8
 #define TPS65218_CHIPID_REV_MASK       0x07
 
+#define TPS65218_REV_1_0               0x0
+#define TPS65218_REV_1_1               0x1
+#define TPS65218_REV_2_0               0x2
+#define TPS65218_REV_2_1               0x3
+
 #define TPS65218_INT1_VPRG             BIT(5)
 #define TPS65218_INT1_AC               BIT(4)
 #define TPS65218_INT1_PB               BIT(3)
@@ -262,6 +267,7 @@ struct tps_info {
 struct tps65218 {
        struct device *dev;
        unsigned int id;
+       u8 rev;
 
        struct mutex tps_lock;          /* lock guarding the data structure */
        /* IRQ Data */
index 46b8ab56b9dbddb3ed52df387f9ada2bbf6a40c1..a7b311dfa7422605ff6ee4df15e9d41170f90b5b 100644 (file)
@@ -1009,6 +1009,7 @@ static inline int page_mapped(struct page *page)
 #define VM_FAULT_WRITE 0x0008  /* Special case for get_user_pages */
 #define VM_FAULT_HWPOISON 0x0010       /* Hit poisoned small page */
 #define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */
+#define VM_FAULT_SIGSEGV 0x0040
 
 #define VM_FAULT_NOPAGE        0x0100  /* ->fault installed the pte, not return page */
 #define VM_FAULT_LOCKED        0x0200  /* ->fault locked the returned page */
@@ -1017,8 +1018,9 @@ static inline int page_mapped(struct page *page)
 
 #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
 
-#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
-                        VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE)
+#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
+                        VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
+                        VM_FAULT_FALLBACK)
 
 /* Encode hstate index for a hwpoisoned large page */
 #define VM_FAULT_SET_HINDEX(x) ((x) << 12)
index 911718fa92ede21741c5da0afc644dbc0c012a03..bf46cc81345156704c70b587f52c67df97223d24 100644 (file)
@@ -1880,6 +1880,12 @@ void netdev_freemem(struct net_device *dev);
 void synchronize_net(void);
 int init_dummy_netdev(struct net_device *dev);
 
+DECLARE_PER_CPU(int, xmit_recursion);
+static inline int dev_recursion_level(void)
+{
+       return this_cpu_read(xmit_recursion);
+}
+
 struct net_device *dev_get_by_index(struct net *net, int ifindex);
 struct net_device *__dev_get_by_index(struct net *net, int ifindex);
 struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex);
index 98755767c7b067098443397aef09ecb145f0cd3e..1108acaacfc62abb35590d3e9c2c92820c49e326 100644 (file)
@@ -458,7 +458,7 @@ struct nilfs_btree_node {
 /* level */
 #define NILFS_BTREE_LEVEL_DATA          0
 #define NILFS_BTREE_LEVEL_NODE_MIN      (NILFS_BTREE_LEVEL_DATA + 1)
-#define NILFS_BTREE_LEVEL_MAX           14
+#define NILFS_BTREE_LEVEL_MAX           14     /* Max level (exclusive) */
 
 /**
  * struct nilfs_palloc_group_desc - block group descriptor
index cac78de09c07e0a8bdaeee4015b86577ba79e164..7a3a9c88f1639a215594c67b6a1a49f250f0a54c 100644 (file)
@@ -49,4 +49,7 @@ extern void *omap_da_to_va(struct device *dev, u32 da);
 extern void omap_iommu_save_ctx(struct device *dev);
 extern void omap_iommu_restore_ctx(struct device *dev);
 
+int omap_iommu_domain_suspend(struct iommu_domain *domain, bool auto_suspend);
+int omap_iommu_domain_resume(struct iommu_domain *domain, bool auto_suspend);
+
 #endif
index 5b429c43a29778ae9b9fb8b545599c2464a736c7..f5b08ec6c1b4b2092583a56d115b3d9a3f358c40 100644 (file)
@@ -51,4 +51,8 @@ struct iommu_platform_data {
 
        int (*assert_reset)(struct platform_device *pdev, const char *name);
        int (*deassert_reset)(struct platform_device *pdev, const char *name);
+       int (*device_enable)(struct platform_device *pdev);
+       int (*device_idle)(struct platform_device *pdev);
+       int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request,
+                                   u8 *pwrst);
 };
index 218b058060f14dc515495d40e9c988f180ec0a68..91fe6a38b3076684ed4bb44b62f023727c3725f3 100644 (file)
@@ -1695,7 +1695,7 @@ static inline pid_t task_tgid_vnr(struct task_struct *tsk)
 }
 
 
-static int pid_alive(const struct task_struct *p);
+static inline int pid_alive(const struct task_struct *p);
 static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns)
 {
        pid_t pid = 0;
index ad8f85908a565f0a2be0e1362fcfa16aa560ab2f..ab3133797ff7180231826043dfcc505b3a07cc1e 100644 (file)
@@ -661,6 +661,7 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
 
 struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags,
                            int node);
+struct sk_buff *__build_skb(void *data, unsigned int frag_size);
 struct sk_buff *build_skb(void *data, unsigned int frag_size);
 static inline struct sk_buff *alloc_skb(unsigned int size,
                                        gfp_t priority)
index 4302af20816767d49ed03698f88ed33634fcd240..d8834a79e545c229e5ea4686d6f9407b0092e9e7 100644 (file)
@@ -206,6 +206,32 @@ void usb_put_intf(struct usb_interface *intf);
 #define USB_MAXINTERFACES      32
 #define USB_MAXIADS            (USB_MAXINTERFACES/2)
 
+/*
+ * USB Resume Timer: Every Host controller driver should drive the resume
+ * signalling on the bus for the amount of time defined by this macro.
+ *
+ * That way we will have a 'stable' behavior among all HCDs supported by Linux.
+ *
+ * Note that the USB Specification states we should drive resume for *at least*
+ * 20 ms, but it doesn't give an upper bound. This creates two possible
+ * situations which we want to avoid:
+ *
+ * (a) sometimes an msleep(20) might expire slightly before 20 ms, which causes
+ * us to fail USB Electrical Tests, thus failing Certification
+ *
+ * (b) Some (many) devices actually need more than 20 ms of resume signalling,
+ * and while we can argue that's against the USB Specification, we don't have
+ * control over which devices a certification laboratory will be using for
+ * certification. If CertLab uses a device which was tested against Windows and
+ * that happens to have relaxed resume signalling rules, we might fall into
+ * situations where we fail interoperability and electrical tests.
+ *
+ * In order to avoid both conditions, we're using a 40 ms resume timeout, which
+ * should cope with both LPJ calibration errors and devices not following every
+ * detail of the USB Specification.
+ */
+#define USB_RESUME_TIMEOUT     40 /* ms */
+
 /**
  * struct usb_interface_cache - long-term representation of a device interface
  * @num_altsetting: number of altsettings defined.
index 6c62cfa25f1a03d8505ac2604404702048368f1c..bc9d2c2ddf873342d54c44a36cbcacbfe53e05c0 100644 (file)
@@ -71,7 +71,8 @@ enum {
        /* data contains off-queue information when !WORK_STRUCT_PWQ */
        WORK_OFFQ_FLAG_BASE     = WORK_STRUCT_COLOR_SHIFT,
 
-       WORK_OFFQ_CANCELING     = (1 << WORK_OFFQ_FLAG_BASE),
+       __WORK_OFFQ_CANCELING   = WORK_OFFQ_FLAG_BASE,
+       WORK_OFFQ_CANCELING     = (1 << __WORK_OFFQ_CANCELING),
 
        /*
         * When a work item is off queue, its high bits point to the last
index 87943786acbc1c88af83313f73e2cd57995cb1df..2b2d0fabe35cef8d953d30a367bdadd27772a23a 100644 (file)
@@ -29,12 +29,15 @@ struct device_node;
  * @data_lanes: an array of physical data lane indexes
  * @clock_lane: physical lane index of the clock lane
  * @num_data_lanes: number of data lanes
+ * @lane_polarities: polarity of the lanes. The order is the same of
+ *                the physical lanes.
  */
 struct v4l2_of_bus_mipi_csi2 {
        unsigned int flags;
        unsigned char data_lanes[4];
        unsigned char clock_lane;
        unsigned short num_data_lanes;
+       bool lane_polarities[5];
 };
 
 /**
index 3446cdd29608d4d2c99ba47e5fc322505ae2238f..5128fa7a83021dfc7343676d5282e441a0f95882 100644 (file)
@@ -407,22 +407,6 @@ static __inline__ void inet_reset_saddr(struct sock *sk)
 
 #endif
 
-static inline int sk_mc_loop(struct sock *sk)
-{
-       if (!sk)
-               return 1;
-       switch (sk->sk_family) {
-       case AF_INET:
-               return inet_sk(sk)->mc_loop;
-#if IS_ENABLED(CONFIG_IPV6)
-       case AF_INET6:
-               return inet6_sk(sk)->mc_loop;
-#endif
-       }
-       WARN_ON(1);
-       return 1;
-}
-
 bool ip_call_ra_chain(struct sk_buff *skb);
 
 /*
index 2e74c6cfa612c528075f3b691e950d3b3d42c58a..ee2d53ae62fe06add5636b921a3393d09ff85dcd 100644 (file)
@@ -168,7 +168,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 
 static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
 {
-       struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
+       struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ?
+                               inet6_sk(skb->sk) : NULL;
 
        return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ?
               skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
index f66b2b19a6e44579a6f98cf7149e6c2fab296554..0c79a740e97dc8eb86dbef4acedf074c941a57b3 100644 (file)
@@ -1815,6 +1815,8 @@ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
 
 struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
 
+bool sk_mc_loop(struct sock *sk);
+
 static inline bool sk_can_gso(const struct sock *sk)
 {
        return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type);
index dfb42ca6d0436539ada89bcd063c26e5c4e85d86..8898cdeb42a4a85a3025c8238ad5dfc775265f74 100644 (file)
@@ -41,7 +41,8 @@
 
 #define EMUPAGESIZE     4096
 #define MAXREQVOICES    8
-#define MAXPAGES        8192
+#define MAXPAGES0       4096   /* 32 bit mode */
+#define MAXPAGES1       8192   /* 31 bit mode */
 #define RESERVED        0
 #define NUM_MIDI        16
 #define NUM_G           64              /* use all channels */
@@ -50,8 +51,7 @@
 
 /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */
 #define EMU10K1_DMA_MASK       0x7fffffffUL    /* 31bit */
-#define AUDIGY_DMA_MASK                0x7fffffffUL    /* 31bit FIXME - 32 should work? */
-                                               /* See ALSA bug #1276 - rlrevell */
+#define AUDIGY_DMA_MASK                0xffffffffUL    /* 32bit mode */
 
 #define TMEMSIZE        256*1024
 #define TMEMSIZEREG     4
 
 #define MAPB                   0x0d            /* Cache map B                                          */
 
-#define MAP_PTE_MASK           0xffffe000      /* The 19 MSBs of the PTE indexed by the PTI            */
-#define MAP_PTI_MASK           0x00001fff      /* The 13 bit index to one of the 8192 PTE dwords       */
+#define MAP_PTE_MASK0          0xfffff000      /* The 20 MSBs of the PTE indexed by the PTI            */
+#define MAP_PTI_MASK0          0x00000fff      /* The 12 bit index to one of the 4096 PTE dwords       */
+
+#define MAP_PTE_MASK1          0xffffe000      /* The 19 MSBs of the PTE indexed by the PTI            */
+#define MAP_PTI_MASK1          0x00001fff      /* The 13 bit index to one of the 8192 PTE dwords       */
 
 /* 0x0e, 0x0f: Not used */
 
@@ -1706,6 +1709,7 @@ struct snd_emu10k1 {
        unsigned short model;                   /* subsystem id */
        unsigned int card_type;                 /* EMU10K1_CARD_* */
        unsigned int ecard_ctrl;                /* ecard control bits */
+       unsigned int address_mode;              /* address mode */
        unsigned long dma_mask;                 /* PCI DMA mask */
        unsigned int delay_pcm_irq;             /* in samples */
        int max_cache_pages;                    /* max memory size / PAGE_SIZE */
index 6e89ef6c11c1a42c853a8f87021bbf1244a14ffc..13412ab158ee6232fb800d8aebe3c6ac13b74ba2 100644 (file)
@@ -302,7 +302,7 @@ struct device;
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
        .tlv.p = (tlv_array), \
        .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
-       .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
+       .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
 #define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
        SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
 #define SOC_DAPM_ENUM(xname, xenum) \
index 1772fadcff62aaa8ab1e3ab2b4a7aef15de87fa7..e4b9e011d2a195a8e79d228066417d92bd5f7098 100644 (file)
@@ -407,7 +407,7 @@ struct t10_reservation {
        /* Activate Persistence across Target Power Loss enabled
         * for SCSI device */
        int pr_aptpl_active;
-#define PR_APTPL_BUF_LEN                       8192
+#define PR_APTPL_BUF_LEN                       262144
        u32 pr_generation;
        spinlock_t registration_lock;
        spinlock_t aptpl_reg_lock;
@@ -513,7 +513,7 @@ struct se_cmd {
        sense_reason_t          (*execute_cmd)(struct se_cmd *);
        sense_reason_t          (*execute_rw)(struct se_cmd *, struct scatterlist *,
                                              u32, enum dma_data_direction);
-       sense_reason_t (*transport_complete_callback)(struct se_cmd *);
+       sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool);
 
        unsigned char           *t_task_cdb;
        unsigned char           __t_task_cdb[TCM_MAX_COMMAND_SIZE];
index aece1346ceb741bf11dd0d70215a4f91e9eeba3c..4ad10baecd4dcddbb47e503ccc41b1c309aaba3c 100644 (file)
@@ -268,11 +268,11 @@ TRACE_EVENT(mm_page_alloc_extfrag,
 
        TP_PROTO(struct page *page,
                int alloc_order, int fallback_order,
-               int alloc_migratetype, int fallback_migratetype, int new_migratetype),
+               int alloc_migratetype, int fallback_migratetype),
 
        TP_ARGS(page,
                alloc_order, fallback_order,
-               alloc_migratetype, fallback_migratetype, new_migratetype),
+               alloc_migratetype, fallback_migratetype),
 
        TP_STRUCT__entry(
                __field(        struct page *,  page                    )
@@ -289,7 +289,8 @@ TRACE_EVENT(mm_page_alloc_extfrag,
                __entry->fallback_order         = fallback_order;
                __entry->alloc_migratetype      = alloc_migratetype;
                __entry->fallback_migratetype   = fallback_migratetype;
-               __entry->change_ownership       = (new_migratetype == alloc_migratetype);
+               __entry->change_ownership       = (alloc_migratetype ==
+                                       get_pageblock_migratetype(page));
        ),
 
        TP_printk("page=%p pfn=%lu alloc_order=%d fallback_order=%d pageblock_order=%d alloc_migratetype=%d fallback_migratetype=%d fragmenting=%d change_ownership=%d",
index 550e2050d778c5b398cc4c27ce53d33b763b1c1e..18711f326260c148a472e0a90f3992139ecde293 100644 (file)
@@ -971,7 +971,7 @@ static void cgroup_d_remove_dir(struct dentry *dentry)
        parent = dentry->d_parent;
        spin_lock(&parent->d_lock);
        spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-       list_del_init(&dentry->d_u.d_child);
+       list_del_init(&dentry->d_child);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&parent->d_lock);
        remove_dir(dentry);
index 2fb2877e6961f094e979d9f365829b694b75385c..7b4530b0b16b0937ef10bf06fbf12c30570d0def 100644 (file)
@@ -503,9 +503,6 @@ static void update_domain_attr_tree(struct sched_domain_attr *dattr,
 
        rcu_read_lock();
        cpuset_for_each_descendant_pre(cp, pos_css, root_cs) {
-               if (cp == root_cs)
-                       continue;
-
                /* skip the whole subtree if @cp doesn't have any CPU */
                if (cpumask_empty(cp->cpus_allowed)) {
                        pos_css = css_rightmost_descendant(pos_css);
index 69cffb46db170e9a4a54e2fb3c2e0a58d400db62..60146febb9b3ff7ea0a87980fde06c1dbf0bb554 100644 (file)
@@ -4232,6 +4232,13 @@ static void perf_pending_event(struct irq_work *entry)
 {
        struct perf_event *event = container_of(entry,
                        struct perf_event, pending);
+       int rctx;
+
+       rctx = perf_swevent_get_recursion_context();
+       /*
+        * If we 'fail' here, that's OK, it means recursion is already disabled
+        * and we won't recurse 'further'.
+        */
 
        if (event->pending_disable) {
                event->pending_disable = 0;
@@ -4242,6 +4249,9 @@ static void perf_pending_event(struct irq_work *entry)
                event->pending_wakeup = 0;
                perf_event_wakeup(event);
        }
+
+       if (rctx >= 0)
+               perf_swevent_put_recursion_context(rctx);
 }
 
 /*
index cbd69d842341175e4c6db7c68a4b6e3689f5c928..2ca4a8b5fe57960c584d74e7dabf76b22bc71613 100644 (file)
@@ -3,7 +3,7 @@
 
 struct console_cmdline
 {
-       char    name[8];                        /* Name of the driver       */
+       char    name[16];                       /* Name of the driver       */
        int     index;                          /* Minor dev. to use        */
        char    *options;                       /* Options for the driver   */
 #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
index 8c086e6049b9bbe2eb085511834d1c50702a6836..a755ad70fe8f411d0b145013743a0b5851141629 100644 (file)
@@ -2280,6 +2280,7 @@ void register_console(struct console *newcon)
        for (i = 0, c = console_cmdline;
             i < MAX_CMDLINECONSOLES && c->name[0];
             i++, c++) {
+               BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
                if (strcmp(c->name, newcon->name) != 0)
                        continue;
                if (newcon->index >= 0 &&
index 1f4bcb3cc21cee5bcfd1b4e13a77eeff2af23a2b..be9760f8284a41dcab57a6510a980effe41d2233 100644 (file)
@@ -720,6 +720,8 @@ static int ptrace_peek_siginfo(struct task_struct *child,
 static int ptrace_resume(struct task_struct *child, long request,
                         unsigned long data)
 {
+       bool need_siglock;
+
        if (!valid_signal(data))
                return -EIO;
 
@@ -747,8 +749,26 @@ static int ptrace_resume(struct task_struct *child, long request,
                user_disable_single_step(child);
        }
 
+       /*
+        * Change ->exit_code and ->state under siglock to avoid the race
+        * with wait_task_stopped() in between; a non-zero ->exit_code will
+        * wrongly look like another report from tracee.
+        *
+        * Note that we need siglock even if ->exit_code == data and/or this
+        * status was not reported yet, the new status must not be cleared by
+        * wait_task_stopped() after resume.
+        *
+        * If data == 0 we do not care if wait_task_stopped() reports the old
+        * status and clears the code too; this can't race with the tracee, it
+        * takes siglock after resume.
+        */
+       need_siglock = data && !thread_group_empty(current);
+       if (need_siglock)
+               spin_lock_irq(&child->sighand->siglock);
        child->exit_code = data;
        wake_up_state(child, __TASK_TRACED);
+       if (need_siglock)
+               spin_unlock_irq(&child->sighand->siglock);
 
        return 0;
 }
index 9a3f3c4e1f5a944ff9dfd078f75c67b1060e9c6a..5e973efc036e600e8b95483cf7a576c19cb74b68 100644 (file)
@@ -2980,6 +2980,8 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
        } else {
                if (dl_prio(oldprio))
                        p->dl.dl_boosted = 0;
+               if (rt_prio(oldprio))
+                       p->rt.timeout = 0;
                p->sched_class = &fair_sched_class;
        }
 
index 490fcbb1dc5b41727408d28e17ae145754c2c051..93be750348c86f5bda390f66615d42c2298a9950 100644 (file)
@@ -657,9 +657,13 @@ static void run_ksoftirqd(unsigned int cpu)
                 * in the task stack here.
                 */
                __do_softirq();
-               rcu_note_context_switch(cpu);
                local_irq_enable();
                cond_resched();
+
+               preempt_disable();
+               rcu_note_context_switch(cpu);
+               preempt_enable();
+
                return;
        }
        local_irq_enable();
index 774a0807fe811b103d4b80d33b284ef48ecd7fc4..da41de9dc319aefbf3969e959030fb3a1f55e41c 100644 (file)
@@ -2651,7 +2651,7 @@ static DEFINE_PER_CPU(unsigned int, current_context);
 
 static __always_inline int trace_recursive_lock(void)
 {
-       unsigned int val = this_cpu_read(current_context);
+       unsigned int val = __this_cpu_read(current_context);
        int bit;
 
        if (in_interrupt()) {
@@ -2668,18 +2668,17 @@ static __always_inline int trace_recursive_lock(void)
                return 1;
 
        val |= (1 << bit);
-       this_cpu_write(current_context, val);
+       __this_cpu_write(current_context, val);
 
        return 0;
 }
 
 static __always_inline void trace_recursive_unlock(void)
 {
-       unsigned int val = this_cpu_read(current_context);
+       unsigned int val = __this_cpu_read(current_context);
 
-       val--;
-       val &= this_cpu_read(current_context);
-       this_cpu_write(current_context, val);
+       val &= val & (val - 1);
+       __this_cpu_write(current_context, val);
 }
 
 #else
index 813b021379f58fe9e880e5f7d65c0580e63d1014..a2d62b3b90c77c56d657e1270de97cacfc5159f7 100644 (file)
@@ -6158,7 +6158,7 @@ static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t m
        int ret;
 
        /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
 
@@ -6185,7 +6185,7 @@ static int instance_rmdir(struct inode *inode, struct dentry *dentry)
        int ret;
 
        /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
 
index e4c4efc4ba0d7d8bc85b17900de4e6a03d7178ab..c6646a58d23e3d663c1a9a2b358f901070be88f0 100644 (file)
@@ -428,7 +428,7 @@ static void remove_event_file_dir(struct ftrace_event_file *file)
 
        if (dir) {
                spin_lock(&dir->d_lock);        /* probably unneeded */
-               list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
+               list_for_each_entry(child, &dir->d_subdirs, d_child) {
                        if (child->d_inode)     /* probably unneeded */
                                child->d_inode->i_private = NULL;
                }
index f6f31d823e8e77d8f84a32186e2e02483da7562c..423c9e37a9e75f78462d3fe32761239c9e7edd5a 100644 (file)
@@ -2893,19 +2893,57 @@ bool flush_work(struct work_struct *work)
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
+struct cwt_wait {
+       wait_queue_t            wait;
+       struct work_struct      *work;
+};
+
+static int cwt_wakefn(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+       struct cwt_wait *cwait = container_of(wait, struct cwt_wait, wait);
+
+       if (cwait->work != key)
+               return 0;
+       return autoremove_wake_function(wait, mode, sync, key);
+}
+
 static bool __cancel_work_timer(struct work_struct *work, bool is_dwork)
 {
+       static DECLARE_WAIT_QUEUE_HEAD(cancel_waitq);
        unsigned long flags;
        int ret;
 
        do {
                ret = try_to_grab_pending(work, is_dwork, &flags);
                /*
-                * If someone else is canceling, wait for the same event it
-                * would be waiting for before retrying.
+                * If someone else is already canceling, wait for it to
+                * finish.  flush_work() doesn't work for PREEMPT_NONE
+                * because we may get scheduled between @work's completion
+                * and the other canceling task resuming and clearing
+                * CANCELING - flush_work() will return false immediately
+                * as @work is no longer busy, try_to_grab_pending() will
+                * return -ENOENT as @work is still being canceled and the
+                * other canceling task won't be able to clear CANCELING as
+                * we're hogging the CPU.
+                *
+                * Let's wait for completion using a waitqueue.  As this
+                * may lead to the thundering herd problem, use a custom
+                * wake function which matches @work along with exclusive
+                * wait and wakeup.
                 */
-               if (unlikely(ret == -ENOENT))
-                       flush_work(work);
+               if (unlikely(ret == -ENOENT)) {
+                       struct cwt_wait cwait;
+
+                       init_wait(&cwait.wait);
+                       cwait.wait.func = cwt_wakefn;
+                       cwait.work = work;
+
+                       prepare_to_wait_exclusive(&cancel_waitq, &cwait.wait,
+                                                 TASK_UNINTERRUPTIBLE);
+                       if (work_is_canceling(work))
+                               schedule();
+                       finish_wait(&cancel_waitq, &cwait.wait);
+               }
        } while (unlikely(ret < 0));
 
        /* tell other tasks trying to grab @work to back off */
@@ -2914,6 +2952,16 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork)
 
        flush_work(work);
        clear_work_data(work);
+
+       /*
+        * Paired with prepare_to_wait() above so that either
+        * waitqueue_active() is visible here or !work_is_canceling() is
+        * visible there.
+        */
+       smp_mb();
+       if (waitqueue_active(&cancel_waitq))
+               __wake_up(&cancel_waitq, TASK_NORMAL, 1, work);
+
        return ret;
 }
 
index 7a85967060a518a43c5da9125a03d701ab892304..f0f5c5c3de12e1a23b5aeebc7ec05da6e78d3c14 100644 (file)
@@ -139,6 +139,9 @@ static int lz4_uncompress(const char *source, char *dest, int osize)
                        /* Error: request to write beyond destination buffer */
                        if (cpy > oend)
                                goto _output_error;
+                       if ((ref + COPYLENGTH) > oend ||
+                                       (op + COPYLENGTH) > oend)
+                               goto _output_error;
                        LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
                        while (op < cpy)
                                *op++ = *ref++;
index 43d0781daf4703d94be9fd988bd6054f49cdeca4..cb9ea218155780cc6ba2dab7676f72f6c4ff17a0 100644 (file)
@@ -598,7 +598,7 @@ EXPORT_SYMBOL(memset);
 void memzero_explicit(void *s, size_t count)
 {
        memset(s, 0, count);
-       OPTIMIZER_HIDE_VAR(s);
+       barrier();
 }
 EXPORT_SYMBOL(memzero_explicit);
 
index 4229fc22a477bfbe382079954ed59d8b825db4da..a522208bb8ea2f92280a38af701891f0903c34bb 100644 (file)
@@ -937,7 +937,7 @@ static int compact_finished(struct zone *zone,
                        return COMPACT_PARTIAL;
 
                /* Job done if allocation would set block type */
-               if (cc->order >= pageblock_order && area->nr_free)
+               if (order >= pageblock_order && area->nr_free)
                        return COMPACT_PARTIAL;
        }
 
index 472259b0061837be6637854b7e8c25f728de64cc..c3e8660cb616015620741cfee3f6c45c7bb9ac27 100644 (file)
@@ -2488,9 +2488,10 @@ again:
                        goto unlock;
 
                /*
-                * HWPoisoned hugepage is already unmapped and dropped reference
+                * Migrating hugepage or HWPoisoned hugepage is already
+                * unmapped and its refcount is dropped, so just clear pte here.
                 */
-               if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) {
+               if (unlikely(!pte_present(pte))) {
                        huge_pte_clear(mm, address, ptep);
                        goto unlock;
                }
@@ -3163,7 +3164,26 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                        spin_unlock(ptl);
                        continue;
                }
-               if (!huge_pte_none(huge_ptep_get(ptep))) {
+               pte = huge_ptep_get(ptep);
+               if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) {
+                       spin_unlock(ptl);
+                       continue;
+               }
+               if (unlikely(is_hugetlb_entry_migration(pte))) {
+                       swp_entry_t entry = pte_to_swp_entry(pte);
+
+                       if (is_write_migration_entry(entry)) {
+                               pte_t newpte;
+
+                               make_migration_entry_read(&entry);
+                               newpte = swp_entry_to_pte(entry);
+                               set_huge_pte_at(mm, address, ptep, newpte);
+                               pages++;
+                       }
+                       spin_unlock(ptl);
+                       continue;
+               }
+               if (!huge_pte_none(pte)) {
                        pte = huge_ptep_get_and_clear(mm, address, ptep);
                        pte = pte_mkhuge(huge_pte_modify(pte, newprot));
                        pte = arch_make_huge_pte(pte, vma, NULL, 0);
index 68710e80994afed815c58b59a1a3cf421df8101f..5e706e391a02b2760093b905331cb253879dd4f6 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -376,7 +376,7 @@ static int break_ksm(struct vm_area_struct *vma, unsigned long addr)
                else
                        ret = VM_FAULT_WRITE;
                put_page(page);
-       } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM)));
+       } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM)));
        /*
         * We must loop because handle_mm_fault() may back out if there's
         * any difficulty e.g. if pte accessed bit gets updated concurrently.
index a98c7fce470aa7cc5f887eef4057189bb1222703..9502057c3c5452be1a4cf2ecbb9871bb89878848 100644 (file)
@@ -1149,10 +1149,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
         * The check (unnecessarily) ignores LRU pages being isolated and
         * walked by the page reclaim code, however that's not a big loss.
         */
-       if (!PageHuge(p) && !PageTransTail(p)) {
-               if (!PageLRU(p))
-                       shake_page(p, 0);
-               if (!PageLRU(p)) {
+       if (!PageHuge(p)) {
+               if (!PageLRU(hpage))
+                       shake_page(hpage, 0);
+               if (!PageLRU(hpage)) {
                        /*
                         * shake_page could have turned it free.
                         */
@@ -1644,8 +1644,6 @@ static int __soft_offline_page(struct page *page, int flags)
                         * source page should be freed back to buddy before
                         * setting PG_hwpoison.
                         */
-                       if (!is_free_buddy_page(page))
-                               lru_add_drain_all();
                        if (!is_free_buddy_page(page))
                                drain_all_pages();
                        SetPageHWPoison(page);
@@ -1725,12 +1723,12 @@ int soft_offline_page(struct page *page, int flags)
        } else if (ret == 0) { /* for free pages */
                if (PageHuge(page)) {
                        set_page_hwpoison_huge_page(hpage);
-                       dequeue_hwpoisoned_huge_page(hpage);
-                       atomic_long_add(1 << compound_order(hpage),
+                       if (!dequeue_hwpoisoned_huge_page(hpage))
+                               atomic_long_add(1 << compound_order(hpage),
                                        &num_poisoned_pages);
                } else {
-                       SetPageHWPoison(page);
-                       atomic_long_inc(&num_poisoned_pages);
+                       if (!TestSetPageHWPoison(page))
+                               atomic_long_inc(&num_poisoned_pages);
                }
        }
        unset_migratetype_isolate(page, MIGRATE_MOVABLE);
index 7f30beaba74f458db761ec0d935f0f44b3ffd1f3..749e1c68d49010b94158eac4690aa3e211a8964d 100644 (file)
@@ -1836,7 +1836,8 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                                else
                                                        return -EFAULT;
                                        }
-                                       if (ret & VM_FAULT_SIGBUS)
+                                       if (ret & (VM_FAULT_SIGBUS |
+                                                  VM_FAULT_SIGSEGV))
                                                return i ? i : -EFAULT;
                                        BUG();
                                }
@@ -1946,7 +1947,7 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
                        return -ENOMEM;
                if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
                        return -EHWPOISON;
-               if (ret & VM_FAULT_SIGBUS)
+               if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
                        return -EFAULT;
                BUG();
        }
@@ -3235,7 +3236,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
 
        /* Check if we need to add a guard page to the stack */
        if (check_stack_guard_page(vma, address) < 0)
-               return VM_FAULT_SIGBUS;
+               return VM_FAULT_SIGSEGV;
 
        /* Use the zero-page for reads */
        if (!(flags & FAULT_FLAG_WRITE)) {
@@ -4024,7 +4025,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
        if (follow_phys(vma, addr, write, &prot, &phys_addr))
                return -EINVAL;
 
-       maddr = ioremap_prot(phys_addr, PAGE_SIZE, prot);
+       maddr = ioremap_prot(phys_addr, PAGE_ALIGN(len + offset), prot);
        if (write)
                memcpy_toio(maddr + offset, buf, len);
        else
index f6f23833de44702332d81188f0fd7e5fcd926d46..c8e450132813bb5736357cf2c5df39e010e9857e 100644 (file)
@@ -1016,6 +1016,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
                        return NULL;
 
                arch_refresh_nodedata(nid, pgdat);
+       } else {
+               /* Reset the nr_zones and classzone_idx to 0 before reuse */
+               pgdat->nr_zones = 0;
+               pgdat->classzone_idx = 0;
        }
 
        /* we can use NODE_DATA(nid) from here */
@@ -1863,15 +1867,6 @@ void try_offline_node(int nid)
                if (is_vmalloc_addr(zone->wait_table))
                        vfree(zone->wait_table);
        }
-
-       /*
-        * Since there is no way to guarentee the address of pgdat/zone is not
-        * on stack of any kernel threads or used by other kernel objects
-        * without reference counting or other symchronizing method, do not
-        * reset node_data and free pgdat here. Just reset it to 0 and reuse
-        * the memory when the node is online again.
-        */
-       memset(pgdat, 0, sizeof(*pgdat));
 }
 EXPORT_SYMBOL(try_offline_node);
 
index 085bcd890ad2dd1e0d252eb860a91f578c868297..d4c97ba6843bc8f5a017bcf7cce4a71d84722cea 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -129,7 +129,7 @@ EXPORT_SYMBOL_GPL(vm_memory_committed);
  */
 int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
 {
-       unsigned long free, allowed, reserve;
+       long free, allowed, reserve;
 
        vm_acct_memory(pages);
 
@@ -193,7 +193,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
         */
        if (mm) {
                reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
-               allowed -= min(mm->total_vm / 32, reserve);
+               allowed -= min_t(long, mm->total_vm / 32, reserve);
        }
 
        if (percpu_counter_read_positive(&vm_committed_as) < allowed)
index 3ee4f74fbfbe3d7887a9cc8db22b55bb8daf36a1..76b3f90ada7b56ea395d1460d9caaa7c1148f301 100644 (file)
@@ -1905,7 +1905,7 @@ EXPORT_SYMBOL(unmap_mapping_range);
  */
 int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
 {
-       unsigned long free, allowed, reserve;
+       long free, allowed, reserve;
 
        vm_acct_memory(pages);
 
@@ -1969,7 +1969,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
         */
        if (mm) {
                reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
-               allowed -= min(mm->total_vm / 32, reserve);
+               allowed -= min_t(long, mm->total_vm / 32, reserve);
        }
 
        if (percpu_counter_read_positive(&vm_committed_as) < allowed)
index 9f45f87a585959c3cd6b56a4a6d70065302f3b39..656a5490f6931fbb954547d3d86349fff684d388 100644 (file)
@@ -601,7 +601,7 @@ static long long pos_ratio_polynom(unsigned long setpoint,
        long x;
 
        x = div64_s64(((s64)setpoint - (s64)dirty) << RATELIMIT_CALC_SHIFT,
-                   limit - setpoint + 1);
+                     (limit - setpoint) | 1);
        pos_ratio = x;
        pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT;
        pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT;
@@ -828,7 +828,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi,
         * scale global setpoint to bdi's:
         *      bdi_setpoint = setpoint * bdi_thresh / thresh
         */
-       x = div_u64((u64)bdi_thresh << 16, thresh + 1);
+       x = div_u64((u64)bdi_thresh << 16, thresh | 1);
        bdi_setpoint = setpoint * (u64)x >> 16;
        /*
         * Use span=(8*write_bw) in single bdi case as indicated by
@@ -843,7 +843,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi,
 
        if (bdi_dirty < x_intercept - span / 4) {
                pos_ratio = div64_u64(pos_ratio * (x_intercept - bdi_dirty),
-                                   x_intercept - bdi_setpoint + 1);
+                                     (x_intercept - bdi_setpoint) | 1);
        } else
                pos_ratio /= 4;
 
@@ -878,8 +878,11 @@ static void bdi_update_write_bandwidth(struct backing_dev_info *bdi,
         *                   bw * elapsed + write_bandwidth * (period - elapsed)
         * write_bandwidth = ---------------------------------------------------
         *                                          period
+        *
+        * @written may have decreased due to account_page_redirty().
+        * Avoid underflowing @bw calculation.
         */
-       bw = written - bdi->written_stamp;
+       bw = written - min(written, bdi->written_stamp);
        bw *= HZ;
        if (unlikely(elapsed > period)) {
                do_div(bw, elapsed);
@@ -943,7 +946,7 @@ static void global_update_bandwidth(unsigned long thresh,
                                    unsigned long now)
 {
        static DEFINE_SPINLOCK(dirty_lock);
-       static unsigned long update_time;
+       static unsigned long update_time = INITIAL_JIFFIES;
 
        /*
         * check locklessly first to optimize away locking for the most time
index ea419137f845c59118fb27cad170955437dd00a6..0479732f6b02bf1d194fa0886a594a2f3310cd21 100644 (file)
@@ -1081,8 +1081,8 @@ static void change_pageblock_range(struct page *pageblock_page,
  * nor move CMA pages to different free lists. We don't want unmovable pages
  * to be allocated from MIGRATE_CMA areas.
  *
- * Returns the new migratetype of the pageblock (or the same old migratetype
- * if it was unchanged).
+ * Returns the allocation migratetype if free pages were stolen, or the
+ * fallback migratetype if it was decided not to steal.
  */
 static int try_to_steal_freepages(struct zone *zone, struct page *page,
                                  int start_type, int fallback_type)
@@ -1113,12 +1113,10 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page,
 
                /* Claim the whole block if over half of it is free */
                if (pages >= (1 << (pageblock_order-1)) ||
-                               page_group_by_mobility_disabled) {
-
+                               page_group_by_mobility_disabled)
                        set_pageblock_migratetype(page, start_type);
-                       return start_type;
-               }
 
+               return start_type;
        }
 
        return fallback_type;
@@ -1170,7 +1168,7 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
                        set_freepage_migratetype(page, new_type);
 
                        trace_mm_page_alloc_extfrag(page, order, current_order,
-                               start_migratetype, migratetype, new_type);
+                               start_migratetype, migratetype);
 
                        return page;
                }
index d6be3edb7a43493a18766c6824b0a1c9ac430d05..526bf56f4d3193605e374b4d8a983440f5fb0153 100644 (file)
@@ -283,7 +283,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
        int copylen;
 
        ret = -EOPNOTSUPP;
-       if (m->msg_flags&MSG_OOB)
+       if (flags & MSG_OOB)
                goto read_error;
 
        skb = skb_recv_datagram(sk, flags, 0 , &ret);
index a27f8aad9e991f95cc5366bce3e975bff4f16bdd..5e9a2272b7a7895fb2350e5b9f84a07d58f3baad 100644 (file)
@@ -262,6 +262,9 @@ int can_send(struct sk_buff *skb, int loop)
                goto inval_skb;
        }
 
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+       skb_reset_mac_header(skb);
        skb_reset_network_header(skb);
        skb_reset_transport_header(skb);
 
index cbc1a2a265876277848f0a697040cea3db75b7d7..d12529050b291e9951cc03881d46b723f98363d0 100644 (file)
@@ -71,6 +71,13 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
            __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
            __get_user(kmsg->msg_flags, &umsg->msg_flags))
                return -EFAULT;
+
+       if (!tmp1)
+               kmsg->msg_namelen = 0;
+
+       if (kmsg->msg_namelen < 0)
+               return -EINVAL;
+
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
                kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        kmsg->msg_name = compat_ptr(tmp1);
@@ -738,24 +745,18 @@ static unsigned char nas[21] = {
 
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
 {
-       if (flags & MSG_CMSG_COMPAT)
-               return -EINVAL;
        return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
 asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
                                    unsigned int vlen, unsigned int flags)
 {
-       if (flags & MSG_CMSG_COMPAT)
-               return -EINVAL;
        return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
                              flags | MSG_CMSG_COMPAT);
 }
 
 asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
 {
-       if (flags & MSG_CMSG_COMPAT)
-               return -EINVAL;
        return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
@@ -778,9 +779,6 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
        int datagrams;
        struct timespec ktspec;
 
-       if (flags & MSG_CMSG_COMPAT)
-               return -EINVAL;
-
        if (timeout == NULL)
                return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
                                      flags | MSG_CMSG_COMPAT, NULL);
index 4ed77d7245c0e6d0725bc1c60abd58f074ebd44d..73abbd77d72c7fe4eb14931d91c9fbf062beece9 100644 (file)
@@ -940,7 +940,7 @@ bool dev_valid_name(const char *name)
                return false;
 
        while (*name) {
-               if (*name == '/' || isspace(*name))
+               if (*name == '/' || *name == ':' || isspace(*name))
                        return false;
                name++;
        }
@@ -2775,7 +2775,9 @@ static void skb_update_prio(struct sk_buff *skb)
 #define skb_update_prio(skb)
 #endif
 
-static DEFINE_PER_CPU(int, xmit_recursion);
+DEFINE_PER_CPU(int, xmit_recursion);
+EXPORT_SYMBOL(xmit_recursion);
+
 #define RECURSION_LIMIT 10
 
 /**
index 9d3d9e78397b0f90f379addab25c7fd78294b3bc..372ac662adf988f3e0708666fa733d22dc8b7448 100644 (file)
@@ -32,6 +32,9 @@ gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size)
        return 0;
 
 nla_put_failure:
+       kfree(d->xstats);
+       d->xstats = NULL;
+       d->xstats_len = 0;
        spin_unlock_bh(d->lock);
        return -1;
 }
@@ -217,7 +220,9 @@ int
 gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)
 {
        if (d->compat_xstats) {
-               d->xstats = st;
+               d->xstats = kmemdup(st, len, GFP_ATOMIC);
+               if (!d->xstats)
+                       goto err_out;
                d->xstats_len = len;
        }
 
@@ -225,6 +230,11 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)
                return gnet_stats_copy(d, TCA_STATS_APP, st, len);
 
        return 0;
+
+err_out:
+       d->xstats_len = 0;
+       spin_unlock_bh(d->lock);
+       return -1;
 }
 EXPORT_SYMBOL(gnet_stats_copy_app);
 
@@ -257,6 +267,9 @@ gnet_stats_finish_copy(struct gnet_dump *d)
                        return -1;
        }
 
+       kfree(d->xstats);
+       d->xstats = NULL;
+       d->xstats_len = 0;
        spin_unlock_bh(d->lock);
        return 0;
 }
index fdac61cac1bd11b15a69f78584029731e9310e4e..ca68d32b49ba320d80b79707f8bfa4ca3d2b5bd0 100644 (file)
@@ -2812,25 +2812,25 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
 
+       pktgen_finalize_skb(pkt_dev, skb, datalen);
+
        if (!(pkt_dev->flags & F_UDPCSUM)) {
                skb->ip_summed = CHECKSUM_NONE;
        } else if (odev->features & NETIF_F_V4_CSUM) {
                skb->ip_summed = CHECKSUM_PARTIAL;
                skb->csum = 0;
-               udp4_hwcsum(skb, udph->source, udph->dest);
+               udp4_hwcsum(skb, iph->saddr, iph->daddr);
        } else {
-               __wsum csum = udp_csum(skb);
+               __wsum csum = skb_checksum(skb, skb_transport_offset(skb), datalen + 8, 0);
 
                /* add protocol-dependent pseudo-header */
-               udph->check = csum_tcpudp_magic(udph->source, udph->dest,
+               udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
                                                datalen + 8, IPPROTO_UDP, csum);
 
                if (udph->check == 0)
                        udph->check = CSUM_MANGLED_0;
        }
 
-       pktgen_finalize_skb(pkt_dev, skb, datalen);
-
 #ifdef CONFIG_XFRM
        if (!process_ipsec(pkt_dev, skb, protocol))
                return NULL;
@@ -2946,6 +2946,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
 
+       pktgen_finalize_skb(pkt_dev, skb, datalen);
+
        if (!(pkt_dev->flags & F_UDPCSUM)) {
                skb->ip_summed = CHECKSUM_NONE;
        } else if (odev->features & NETIF_F_V6_CSUM) {
@@ -2954,7 +2956,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
                skb->csum_offset = offsetof(struct udphdr, check);
                udph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, 0);
        } else {
-               __wsum csum = udp_csum(skb);
+               __wsum csum = skb_checksum(skb, skb_transport_offset(skb), udplen, 0);
 
                /* add protocol-dependent pseudo-header */
                udph->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, csum);
@@ -2963,8 +2965,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
                        udph->check = CSUM_MANGLED_0;
        }
 
-       pktgen_finalize_skb(pkt_dev, skb, datalen);
-
        return skb;
 }
 
index a6613ff972c1886274561aa1016002a0f052a005..8aadd6a072a424841517bc7bbf434ae0199f4f78 100644 (file)
@@ -1264,14 +1264,10 @@ static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = {
 };
 
 static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
-       [IFLA_VF_MAC]           = { .type = NLA_BINARY,
-                                   .len = sizeof(struct ifla_vf_mac) },
-       [IFLA_VF_VLAN]          = { .type = NLA_BINARY,
-                                   .len = sizeof(struct ifla_vf_vlan) },
-       [IFLA_VF_TX_RATE]       = { .type = NLA_BINARY,
-                                   .len = sizeof(struct ifla_vf_tx_rate) },
-       [IFLA_VF_SPOOFCHK]      = { .type = NLA_BINARY,
-                                   .len = sizeof(struct ifla_vf_spoofchk) },
+       [IFLA_VF_MAC]           = { .len = sizeof(struct ifla_vf_mac) },
+       [IFLA_VF_VLAN]          = { .len = sizeof(struct ifla_vf_vlan) },
+       [IFLA_VF_TX_RATE]       = { .len = sizeof(struct ifla_vf_tx_rate) },
+       [IFLA_VF_SPOOFCHK]      = { .len = sizeof(struct ifla_vf_spoofchk) },
 };
 
 static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = {
@@ -2034,8 +2030,16 @@ replay:
                        }
                }
                err = rtnl_configure_link(dev, ifm);
-               if (err < 0)
-                       unregister_netdevice(dev);
+               if (err < 0) {
+                       if (ops->newlink) {
+                               LIST_HEAD(list_kill);
+
+                               ops->dellink(dev, &list_kill);
+                               unregister_netdevice_many(&list_kill);
+                       } else {
+                               unregister_netdevice(dev);
+                       }
+               }
 out:
                put_net(dest_net);
                return err;
index e2b1bba6988269fb32e7e6b26903031de3242236..69ec61abfb37aee9ab8f6ba2f752189ccc7ff094 100644 (file)
@@ -278,13 +278,14 @@ nodata:
 EXPORT_SYMBOL(__alloc_skb);
 
 /**
- * build_skb - build a network buffer
+ * __build_skb - build a network buffer
  * @data: data buffer provided by caller
- * @frag_size: size of fragment, or 0 if head was kmalloced
+ * @frag_size: size of data, or 0 if head was kmalloced
  *
  * Allocate a new &sk_buff. Caller provides space holding head and
  * skb_shared_info. @data must have been allocated by kmalloc() only if
- * @frag_size is 0, otherwise data should come from the page allocator.
+ * @frag_size is 0, otherwise data should come from the page allocator
+ *  or vmalloc()
  * The return is the new skb buffer.
  * On a failure the return is %NULL, and @data is not freed.
  * Notes :
@@ -295,7 +296,7 @@ EXPORT_SYMBOL(__alloc_skb);
  *  before giving packet to stack.
  *  RX rings only contains data buffers, not full skbs.
  */
-struct sk_buff *build_skb(void *data, unsigned int frag_size)
+struct sk_buff *__build_skb(void *data, unsigned int frag_size)
 {
        struct skb_shared_info *shinfo;
        struct sk_buff *skb;
@@ -309,7 +310,6 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
 
        memset(skb, 0, offsetof(struct sk_buff, tail));
        skb->truesize = SKB_TRUESIZE(size);
-       skb->head_frag = frag_size != 0;
        atomic_set(&skb->users, 1);
        skb->head = data;
        skb->data = data;
@@ -326,6 +326,23 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
 
        return skb;
 }
+
+/* build_skb() is wrapper over __build_skb(), that specifically
+ * takes care of skb->head and skb->pfmemalloc
+ * This means that if @frag_size is not zero, then @data must be backed
+ * by a page fragment, not kmalloc() or vmalloc()
+ */
+struct sk_buff *build_skb(void *data, unsigned int frag_size)
+{
+       struct sk_buff *skb = __build_skb(data, frag_size);
+
+       if (skb && frag_size) {
+               skb->head_frag = 1;
+               if (virt_to_head_page(data)->pfmemalloc)
+                       skb->pfmemalloc = 1;
+       }
+       return skb;
+}
 EXPORT_SYMBOL(build_skb);
 
 struct netdev_alloc_cache {
@@ -352,7 +369,8 @@ refill:
                        gfp_t gfp = gfp_mask;
 
                        if (order)
-                               gfp |= __GFP_COMP | __GFP_NOWARN;
+                               gfp |= __GFP_COMP | __GFP_NOWARN |
+                                      __GFP_NOMEMALLOC;
                        nc->frag.page = alloc_pages(gfp, order);
                        if (likely(nc->frag.page))
                                break;
index c8069561bdb7befa31476685a3c0db5ee9e9bfa1..650dd58ebd050d795c158df00503f247925a2637 100644 (file)
@@ -659,6 +659,25 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
                sock_reset_flag(sk, bit);
 }
 
+bool sk_mc_loop(struct sock *sk)
+{
+       if (dev_recursion_level())
+               return false;
+       if (!sk)
+               return true;
+       switch (sk->sk_family) {
+       case AF_INET:
+               return inet_sk(sk)->mc_loop;
+#if IS_ENABLED(CONFIG_IPV6)
+       case AF_INET6:
+               return inet6_sk(sk)->mc_loop;
+#endif
+       }
+       WARN_ON(1);
+       return true;
+}
+EXPORT_SYMBOL(sk_mc_loop);
+
 /*
  *     This is meant for all protocols to use and covers goings on
  *     at the socket level. Everything here is generic.
index cf9cd13509a7d531f9e4a455d2909f5dfb731923..e731c96eac4b44428f5efa38a094234deeceeeb7 100644 (file)
@@ -25,6 +25,8 @@
 static int zero = 0;
 static int one = 1;
 static int ushort_max = USHRT_MAX;
+static int min_sndbuf = SOCK_MIN_SNDBUF;
+static int min_rcvbuf = SOCK_MIN_RCVBUF;
 
 #ifdef CONFIG_RPS
 static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
@@ -223,7 +225,7 @@ static struct ctl_table net_core_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .extra1         = &min_sndbuf,
        },
        {
                .procname       = "rmem_max",
@@ -231,7 +233,7 @@ static struct ctl_table net_core_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .extra1         = &min_rcvbuf,
        },
        {
                .procname       = "wmem_default",
@@ -239,7 +241,7 @@ static struct ctl_table net_core_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .extra1         = &min_sndbuf,
        },
        {
                .procname       = "rmem_default",
@@ -247,7 +249,7 @@ static struct ctl_table net_core_table[] = {
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .extra1         = &min_rcvbuf,
        },
        {
                .procname       = "dev_weight",
index e34dccbc4d70bd26f7cec88c031dcea31124314a..4eeba4e497a02b2945fd61fba8ee10bf5731a861 100644 (file)
@@ -71,6 +71,20 @@ static inline void inet_diag_unlock_handler(
        mutex_unlock(&inet_diag_table_mutex);
 }
 
+static size_t inet_sk_attr_size(void)
+{
+       return    nla_total_size(sizeof(struct tcp_info))
+               + nla_total_size(1) /* INET_DIAG_SHUTDOWN */
+               + nla_total_size(1) /* INET_DIAG_TOS */
+               + nla_total_size(1) /* INET_DIAG_TCLASS */
+               + nla_total_size(sizeof(struct inet_diag_meminfo))
+               + nla_total_size(sizeof(struct inet_diag_msg))
+               + nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
+               + nla_total_size(TCP_CA_NAME_MAX)
+               + nla_total_size(sizeof(struct tcpvegas_info))
+               + 64;
+}
+
 int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                              struct sk_buff *skb, struct inet_diag_req_v2 *req,
                              struct user_namespace *user_ns,                   
@@ -324,9 +338,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
        if (err)
                goto out;
 
-       rep = nlmsg_new(sizeof(struct inet_diag_msg) +
-                       sizeof(struct inet_diag_meminfo) +
-                       sizeof(struct tcp_info) + 64, GFP_KERNEL);
+       rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL);
        if (!rep) {
                err = -ENOMEM;
                goto out;
index ecb34b5ea42ff6db2944ed649e6e26db2824164f..57075c4508f719a183ebe47beef7ed2b9c1ce1df 100644 (file)
@@ -127,6 +127,9 @@ int ip_forward(struct sk_buff *skb)
        struct rtable *rt;      /* Route we use */
        struct ip_options *opt  = &(IPCB(skb)->opt);
 
+       if (unlikely(skb->sk))
+               goto drop;
+
        if (skb_warn_if_lro(skb))
                goto drop;
 
index c10a3ce5cbff0fc0bd0f23ac72188fd9e39fa83f..9ff497d17545df8054f49e463b030ecf56bf40bc 100644 (file)
@@ -679,27 +679,30 @@ EXPORT_SYMBOL(ip_defrag);
 struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
 {
        struct iphdr iph;
+       int netoff;
        u32 len;
 
        if (skb->protocol != htons(ETH_P_IP))
                return skb;
 
-       if (!skb_copy_bits(skb, 0, &iph, sizeof(iph)))
+       netoff = skb_network_offset(skb);
+
+       if (skb_copy_bits(skb, netoff, &iph, sizeof(iph)) < 0)
                return skb;
 
        if (iph.ihl < 5 || iph.version != 4)
                return skb;
 
        len = ntohs(iph.tot_len);
-       if (skb->len < len || len < (iph.ihl * 4))
+       if (skb->len < netoff + len || len < (iph.ihl * 4))
                return skb;
 
        if (ip_is_fragment(&iph)) {
                skb = skb_share_check(skb, GFP_ATOMIC);
                if (skb) {
-                       if (!pskb_may_pull(skb, iph.ihl*4))
+                       if (!pskb_may_pull(skb, netoff + iph.ihl * 4))
                                return skb;
-                       if (pskb_trim_rcsum(skb, len))
+                       if (pskb_trim_rcsum(skb, netoff + len))
                                return skb;
                        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
                        if (ip_defrag(skb, user))
index dd637fc4b5539a7eba06862d75e742558b281c99..05686c47a289cedf5a51e5ba0589c352f1cc6f8d 100644 (file)
@@ -843,7 +843,8 @@ static int __ip_append_data(struct sock *sk,
        cork->length += length;
        if (((length > mtu) || (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
-           (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) {
+           (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len &&
+           (sk->sk_type == SOCK_DGRAM)) {
                err = ip_ufo_append_data(sk, queue, getfrag, from, length,
                                         hh_len, fragheaderlen, transhdrlen,
                                         maxfraglen, flags);
index 04ce671430cb9d57a4b34eda9872a6458475cfb0..1e2e9bf62f1aedb2742f502ac1db6e0bd3ce93f2 100644 (file)
@@ -158,6 +158,7 @@ void ping_unhash(struct sock *sk)
        if (sk_hashed(sk)) {
                write_lock_bh(&ping_table.lock);
                hlist_nulls_del(&sk->sk_nulls_node);
+               sk_nulls_node_init(&sk->sk_nulls_node);
                sock_put(sk);
                isk->inet_num = 0;
                isk->inet_sport = 0;
@@ -259,6 +260,10 @@ int ping_init_sock(struct sock *sk)
        kgid_t low, high;
        int ret = 0;
 
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6)
+               inet6_sk(sk)->ipv6only = 1;
+#endif
        inet_get_ping_group_range_net(net, &low, &high);
        if (gid_lte(low, group) && gid_lte(group, high))
                return 0;
@@ -305,6 +310,11 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
                if (addr_len < sizeof(*addr))
                        return -EINVAL;
 
+               if (addr->sin_family != AF_INET &&
+                   !(addr->sin_family == AF_UNSPEC &&
+                     addr->sin_addr.s_addr == htonl(INADDR_ANY)))
+                       return -EAFNOSUPPORT;
+
                pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n",
                         sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port));
 
@@ -330,7 +340,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk,
                        return -EINVAL;
 
                if (addr->sin6_family != AF_INET6)
-                       return -EINVAL;
+                       return -EAFNOSUPPORT;
 
                pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n",
                         sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port));
@@ -716,7 +726,7 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
                if (msg->msg_namelen < sizeof(*usin))
                        return -EINVAL;
                if (usin->sin_family != AF_INET)
-                       return -EINVAL;
+                       return -EAFNOSUPPORT;
                daddr = usin->sin_addr.s_addr;
                /* no remote port */
        } else {
index 22917918fa80c5ea4668e7b4f522c4153db78aac..9fbd69efa999eaefa9e9cc5ee13763bd88ac0b2e 100644 (file)
@@ -3064,10 +3064,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                        if (seq_rtt < 0) {
                                seq_rtt = ca_seq_rtt;
                        }
-                       if (!(sacked & TCPCB_SACKED_ACKED))
+                       if (!(sacked & TCPCB_SACKED_ACKED)) {
                                reord = min(pkts_acked, reord);
-                       if (!after(scb->end_seq, tp->high_seq))
-                               flag |= FLAG_ORIG_SACK_ACKED;
+                               if (!after(scb->end_seq, tp->high_seq))
+                                       flag |= FLAG_ORIG_SACK_ACKED;
+                       }
                }
 
                if (sacked & TCPCB_SACKED_ACKED)
index b7effad5a58c0da34d6190aa6566eb5e3d577dd9..e2f8bd0d35ed6b21755df9904c71dc02f09faed5 100644 (file)
@@ -1875,7 +1875,7 @@ void tcp_v4_early_demux(struct sk_buff *skb)
                skb->sk = sk;
                skb->destructor = sock_edemux;
                if (sk->sk_state != TCP_TIME_WAIT) {
-                       struct dst_entry *dst = sk->sk_rx_dst;
+                       struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst);
 
                        if (dst)
                                dst = dst_check(dst, 0);
index 7efa26bb872cf3f22973bfff1d38ee23f24d6fc4..a68cd7100349274de28efe45dad94a1400ce6822 100644 (file)
@@ -2595,43 +2595,65 @@ begin_fwd:
        }
 }
 
-/* Send a fin.  The caller locks the socket for us.  This cannot be
- * allowed to fail queueing a FIN frame under any circumstances.
+/* We allow to exceed memory limits for FIN packets to expedite
+ * connection tear down and (memory) recovery.
+ * Otherwise tcp_send_fin() could be tempted to either delay FIN
+ * or even be forced to close flow without any FIN.
+ */
+static void sk_forced_wmem_schedule(struct sock *sk, int size)
+{
+       int amt, status;
+
+       if (size <= sk->sk_forward_alloc)
+               return;
+       amt = sk_mem_pages(size);
+       sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
+       sk_memory_allocated_add(sk, amt, &status);
+}
+
+/* Send a FIN. The caller locks the socket for us.
+ * We should try to send a FIN packet really hard, but eventually give up.
  */
 void tcp_send_fin(struct sock *sk)
 {
+       struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk);
        struct tcp_sock *tp = tcp_sk(sk);
-       struct sk_buff *skb = tcp_write_queue_tail(sk);
-       int mss_now;
 
-       /* Optimization, tack on the FIN if we have a queue of
-        * unsent frames.  But be careful about outgoing SACKS
-        * and IP options.
+       /* Optimization, tack on the FIN if we have one skb in write queue and
+        * this skb was not yet sent, or we are under memory pressure.
+        * Note: in the latter case, FIN packet will be sent after a timeout,
+        * as TCP stack thinks it has already been transmitted.
         */
-       mss_now = tcp_current_mss(sk);
-
-       if (tcp_send_head(sk) != NULL) {
-               TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN;
-               TCP_SKB_CB(skb)->end_seq++;
+       if (tskb && (tcp_send_head(sk) || sk_under_memory_pressure(sk))) {
+coalesce:
+               TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN;
+               TCP_SKB_CB(tskb)->end_seq++;
                tp->write_seq++;
+               if (!tcp_send_head(sk)) {
+                       /* This means tskb was already sent.
+                        * Pretend we included the FIN on previous transmit.
+                        * We need to set tp->snd_nxt to the value it would have
+                        * if FIN had been sent. This is because retransmit path
+                        * does not change tp->snd_nxt.
+                        */
+                       tp->snd_nxt++;
+                       return;
+               }
        } else {
-               /* Socket is locked, keep trying until memory is available. */
-               for (;;) {
-                       skb = alloc_skb_fclone(MAX_TCP_HEADER,
-                                              sk->sk_allocation);
-                       if (skb)
-                               break;
-                       yield();
+               skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation);
+               if (unlikely(!skb)) {
+                       if (tskb)
+                               goto coalesce;
+                       return;
                }
-
-               /* Reserve space for headers and prepare control bits. */
                skb_reserve(skb, MAX_TCP_HEADER);
+               sk_forced_wmem_schedule(sk, skb->truesize);
                /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
                tcp_init_nondata_skb(skb, tp->write_seq,
                                     TCPHDR_ACK | TCPHDR_FIN);
                tcp_queue_skb(sk, skb);
        }
-       __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF);
+       __tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF);
 }
 
 /* We get here when a process closes a file descriptor (either due to
@@ -2800,6 +2822,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        }
 #endif
 
+       /* Do not fool tcpdump (if any), clean our debris */
+       skb->tstamp.tv64 = 0;
        return skb;
 }
 EXPORT_SYMBOL(tcp_make_synack);
@@ -2899,9 +2923,9 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_fastopen_request *fo = tp->fastopen_req;
-       int syn_loss = 0, space, i, err = 0, iovlen = fo->data->msg_iovlen;
-       struct sk_buff *syn_data = NULL, *data;
+       int syn_loss = 0, space, err = 0;
        unsigned long last_syn_loss = 0;
+       struct sk_buff *syn_data;
 
        tp->rx_opt.mss_clamp = tp->advmss;  /* If MSS is not cached */
        tcp_fastopen_cache_get(sk, &tp->rx_opt.mss_clamp, &fo->cookie,
@@ -2932,42 +2956,39 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
        /* limit to order-0 allocations */
        space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER));
 
-       syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space,
-                                  sk->sk_allocation);
-       if (syn_data == NULL)
+       syn_data = sk_stream_alloc_skb(sk, space, sk->sk_allocation);
+       if (!syn_data)
+               goto fallback;
+       syn_data->ip_summed = CHECKSUM_PARTIAL;
+       memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
+       skb_shinfo(syn_data)->gso_segs = 1;
+       if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space),
+                                        fo->data->msg_iov, 0, space))) {
+               kfree_skb(syn_data);
                goto fallback;
+       }
 
-       for (i = 0; i < iovlen && syn_data->len < space; ++i) {
-               struct iovec *iov = &fo->data->msg_iov[i];
-               unsigned char __user *from = iov->iov_base;
-               int len = iov->iov_len;
+       /* No more data pending in inet_wait_for_connect() */
+       if (space == fo->size)
+               fo->data = NULL;
+       fo->copied = space;
 
-               if (syn_data->len + len > space)
-                       len = space - syn_data->len;
-               else if (i + 1 == iovlen)
-                       /* No more data pending in inet_wait_for_connect() */
-                       fo->data = NULL;
+       tcp_connect_queue_skb(sk, syn_data);
 
-               if (skb_add_data(syn_data, from, len))
-                       goto fallback;
-       }
+       err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation);
 
-       /* Queue a data-only packet after the regular SYN for retransmission */
-       data = pskb_copy(syn_data, sk->sk_allocation);
-       if (data == NULL)
-               goto fallback;
-       TCP_SKB_CB(data)->seq++;
-       TCP_SKB_CB(data)->tcp_flags &= ~TCPHDR_SYN;
-       TCP_SKB_CB(data)->tcp_flags = (TCPHDR_ACK|TCPHDR_PSH);
-       tcp_connect_queue_skb(sk, data);
-       fo->copied = data->len;
-
-       if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) {
+       /* Now full SYN+DATA was cloned and sent (or not),
+        * remove the SYN from the original skb (syn_data)
+        * we keep in write queue in case of a retransmit, as we
+        * also have the SYN packet (with no data) in the same queue.
+        */
+       TCP_SKB_CB(syn_data)->seq++;
+       TCP_SKB_CB(syn_data)->tcp_flags = TCPHDR_ACK | TCPHDR_PSH;
+       if (!err) {
                tp->syn_data = (fo->copied > 0);
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
                goto done;
        }
-       syn_data = NULL;
 
 fallback:
        /* Send a regular SYN with Fast Open cookie request option */
@@ -2976,7 +2997,6 @@ fallback:
        err = tcp_transmit_skb(sk, syn, 1, sk->sk_allocation);
        if (err)
                tp->syn_fastopen = 0;
-       kfree_skb(syn_data);
 done:
        fo->cookie.len = -1;  /* Exclude Fast Open option for SYN retries */
        return err;
@@ -2996,13 +3016,10 @@ int tcp_connect(struct sock *sk)
                return 0;
        }
 
-       buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation);
-       if (unlikely(buff == NULL))
+       buff = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
+       if (unlikely(!buff))
                return -ENOBUFS;
 
-       /* Reserve space for headers. */
-       skb_reserve(buff, MAX_TCP_HEADER);
-
        tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
        tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp;
        tcp_connect_queue_skb(sk, buff);
index b4d5e1d97c1b2576fc02a15b7a05a773197bb8e0..27ca79682efbf681a0ab6073f50f8fa73214028e 100644 (file)
@@ -104,6 +104,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
                                goto again;
                        flp6->saddr = saddr;
                }
+               err = rt->dst.error;
                goto out;
        }
 again:
index 12f7ef0f243a463179e1cc4add04ffc21e9b3506..066d0b03f2b87c5c5e7d61ffc5f64d07ec915241 100644 (file)
@@ -555,7 +555,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
        struct sk_buff *frag;
        struct rt6_info *rt = (struct rt6_info*)skb_dst(skb);
-       struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
+       struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ?
+                               inet6_sk(skb->sk) : NULL;
        struct ipv6hdr *tmp_hdr;
        struct frag_hdr *fh;
        unsigned int mtu, hlen, left, len;
@@ -1294,7 +1295,8 @@ emsgsize:
        if (((length > mtu) ||
             (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
-           (rt->dst.dev->features & NETIF_F_UFO)) {
+           (rt->dst.dev->features & NETIF_F_UFO) &&
+           (sk->sk_type == SOCK_DGRAM)) {
                err = ip6_ufo_append_data(sk, getfrag, from, length,
                                          hh_len, fragheaderlen,
                                          transhdrlen, mtu, flags, rt);
index 09a22f4f36c9e069c6dfb3074909691ef2c82399..bcd65186b4974ece988edf77ed31990ecef1f272 100644 (file)
@@ -1193,7 +1193,14 @@ static void ndisc_router_discovery(struct sk_buff *skb)
        if (rt)
                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;
+               /* Only set hop_limit on the interface if it is higher than
+                * the current hop_limit.
+                */
+               if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) {
+                       in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
+               } else {
+                       ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n");
+               }
                if (rt)
                        dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
                                       ra_msg->icmph.icmp6_hop_limit);
index bda74291c3e0d09c94ff5961cf393cb7695ee518..461199533fe4e59dceb7de031918da3dfeae604e 100644 (file)
@@ -103,9 +103,10 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        if (msg->msg_name) {
                DECLARE_SOCKADDR(struct sockaddr_in6 *, u, msg->msg_name);
-               if (msg->msg_namelen < sizeof(struct sockaddr_in6) ||
-                   u->sin6_family != AF_INET6) {
+               if (msg->msg_namelen < sizeof(*u))
                        return -EINVAL;
+               if (u->sin6_family != AF_INET6) {
+                       return -EAFNOSUPPORT;
                }
                if (sk->sk_bound_dev_if &&
                    sk->sk_bound_dev_if != u->sin6_scope_id) {
index 6f1b8503a4314be2db4a058c8deb7cf1d11f3459..3809ca234c69658461935f8d858b5b84fc1c257b 100644 (file)
@@ -141,7 +141,7 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
        u32 *p = NULL;
 
        if (!(rt->dst.flags & DST_HOST))
-               return NULL;
+               return dst_cow_metrics_generic(dst, old);
 
        peer = rt6_get_peer_create(rt);
        if (peer) {
index a4f890dd223aa247594d918b5297b68b3f254130..9d4332dba8ea079afad5ed68c3cefdc48f632fe0 100644 (file)
@@ -1633,7 +1633,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
                skb->sk = sk;
                skb->destructor = sock_edemux;
                if (sk->sk_state != TCP_TIME_WAIT) {
-                       struct dst_entry *dst = sk->sk_rx_dst;
+                       struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst);
 
                        if (dst)
                                dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
index 2ba8b9705bb75201715844105206ecfc3b480df7..fdcb9688b5d336054fbf82a6cde74d279b6b2575 100644 (file)
@@ -818,7 +818,9 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
        orig_jiffies = jiffies;
 
        /* Set poll time to 200 ms */
-       poll_time = IRDA_MIN(timeout, msecs_to_jiffies(200));
+       poll_time = msecs_to_jiffies(200);
+       if (timeout)
+               poll_time = min_t(unsigned long, timeout, poll_time);
 
        spin_lock_irqsave(&self->spinlock, flags);
        while (self->tx_skb && self->tx_skb->len) {
index 612a5ddaf93b1ab1b5a524c5efef8d6b1f769038..799bafc2af39ea191e3753c88c3f921e44a77162 100644 (file)
@@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = {
        {
                .procname       = "ack",
                .data           = &sysctl_llc2_ack_timeout,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(sysctl_llc2_ack_timeout),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
        {
                .procname       = "busy",
                .data           = &sysctl_llc2_busy_timeout,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(sysctl_llc2_busy_timeout),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
        {
                .procname       = "p",
                .data           = &sysctl_llc2_p_timeout,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(sysctl_llc2_p_timeout),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
        {
                .procname       = "rej",
                .data           = &sysctl_llc2_rej_timeout,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(sysctl_llc2_rej_timeout),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
index bf7a1bbb975f60111e061773056091fe5f394e47..e278c64572de95af1c1945e3d744527848d101a7 100644 (file)
@@ -57,13 +57,24 @@ struct ieee80211_local;
 #define IEEE80211_UNSET_POWER_LEVEL    INT_MIN
 
 /*
- * Some APs experience problems when working with U-APSD. Decrease the
- * probability of that happening by using legacy mode for all ACs but VO.
- * The AP that caused us trouble was a Cisco 4410N. It ignores our
- * setting, and always treats non-VO ACs as legacy.
+ * Some APs experience problems when working with U-APSD. Decreasing the
+ * probability of that happening by using legacy mode for all ACs but VO isn't
+ * enough.
+ *
+ * Cisco 4410N originally forced us to enable VO by default only because it
+ * treated non-VO ACs as legacy.
+ *
+ * However some APs (notably Netgear R7000) silently reclassify packets to
+ * different ACs. Since u-APSD ACs require trigger frames for frame retrieval
+ * clients would never see some frames (e.g. ARP responses) or would fetch them
+ * accidentally after a long time.
+ *
+ * It makes little sense to enable u-APSD queues by default because it needs
+ * userspace applications to be aware of it to actually take advantage of the
+ * possible additional powersavings. Implicitly depending on driver autotrigger
+ * frame support doesn't make much sense.
  */
-#define IEEE80211_DEFAULT_UAPSD_QUEUES \
-       IEEE80211_WMM_IE_STA_QOSINFO_AC_VO
+#define IEEE80211_DEFAULT_UAPSD_QUEUES 0
 
 #define IEEE80211_DEFAULT_MAX_SP_LEN           \
        IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
index 815ca56b39e727bfe6e42246676b8452a575ca62..9abb445ea2617b8ac9d2637a24dc2e2c01a0408c 100644 (file)
@@ -2107,6 +2107,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        hdr = (struct ieee80211_hdr *) skb->data;
        mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
 
+       if (ieee80211_drop_unencrypted(rx, hdr->frame_control))
+               return RX_DROP_MONITOR;
+
        /* frame is in RMC, don't forward */
        if (ieee80211_is_data(hdr->frame_control) &&
            is_multicast_ether_addr(hdr->addr1) &&
index e5a7ac2f36879ff9026d82dd7f8b4fe870a5788f..dca076f6252c7bf980a8bfa0fa89d7471811c70b 100644 (file)
@@ -562,6 +562,7 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
                if (tx->sdata->control_port_no_encrypt)
                        info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
                info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
+               info->flags |= IEEE80211_TX_CTL_USE_MINRATE;
        }
 
        return TX_CONTINUE;
index 27d3f40de3cd7a731c9da9749d6fbe392131752b..847d2a2c5d05d4dedbf993b4d43d67cb4187ca83 100644 (file)
@@ -658,16 +658,24 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
        return err;
 }
 
-static int ip_vs_route_me_harder(int af, struct sk_buff *skb)
+static int ip_vs_route_me_harder(int af, struct sk_buff *skb,
+                                unsigned int hooknum)
 {
+       if (!sysctl_snat_reroute(skb))
+               return 0;
+       /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */
+       if (NF_INET_LOCAL_IN == hooknum)
+               return 0;
 #ifdef CONFIG_IP_VS_IPV6
        if (af == AF_INET6) {
-               if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0)
+               struct dst_entry *dst = skb_dst(skb);
+
+               if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) &&
+                   ip6_route_me_harder(skb) != 0)
                        return 1;
        } else
 #endif
-               if ((sysctl_snat_reroute(skb) ||
-                    skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
+               if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
                    ip_route_me_harder(skb, RTN_LOCAL) != 0)
                        return 1;
 
@@ -790,7 +798,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
                                union nf_inet_addr *snet,
                                __u8 protocol, struct ip_vs_conn *cp,
                                struct ip_vs_protocol *pp,
-                               unsigned int offset, unsigned int ihl)
+                               unsigned int offset, unsigned int ihl,
+                               unsigned int hooknum)
 {
        unsigned int verdict = NF_DROP;
 
@@ -820,7 +829,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
 #endif
                ip_vs_nat_icmp(skb, pp, cp, 1);
 
-       if (ip_vs_route_me_harder(af, skb))
+       if (ip_vs_route_me_harder(af, skb, hooknum))
                goto out;
 
        /* do the statistics and put it back */
@@ -915,7 +924,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
 
        snet.ip = iph->saddr;
        return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp,
-                                   pp, ciph.len, ihl);
+                                   pp, ciph.len, ihl, hooknum);
 }
 
 #ifdef CONFIG_IP_VS_IPV6
@@ -980,7 +989,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
        snet.in6 = ciph.saddr.in6;
        writable = ciph.len;
        return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp,
-                                   pp, writable, sizeof(struct ipv6hdr));
+                                   pp, writable, sizeof(struct ipv6hdr),
+                                   hooknum);
 }
 #endif
 
@@ -1039,7 +1049,8 @@ static inline bool is_new_conn(const struct sk_buff *skb,
  */
 static unsigned int
 handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
-               struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
+               struct ip_vs_conn *cp, struct ip_vs_iphdr *iph,
+               unsigned int hooknum)
 {
        struct ip_vs_protocol *pp = pd->pp;
 
@@ -1077,7 +1088,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
         * if it came from this machine itself.  So re-compute
         * the routing information.
         */
-       if (ip_vs_route_me_harder(af, skb))
+       if (ip_vs_route_me_harder(af, skb, hooknum))
                goto drop;
 
        IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT");
@@ -1180,7 +1191,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
        cp = pp->conn_out_get(af, skb, &iph, 0);
 
        if (likely(cp))
-               return handle_response(af, skb, pd, cp, &iph);
+               return handle_response(af, skb, pd, cp, &iph, hooknum);
        if (sysctl_nat_icmp_send(net) &&
            (pp->protocol == IPPROTO_TCP ||
             pp->protocol == IPPROTO_UDP ||
index db801263ee9fa81a832f4656071198cdc16110e7..a8027e73b6a2f753c487f6a726ed9314d35479aa 100644 (file)
@@ -891,6 +891,8 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
                        IP_VS_DBG(2, "BACKUP, add new conn. failed\n");
                        return;
                }
+               if (!(flags & IP_VS_CONN_F_TEMPLATE))
+                       kfree(param->pe_data);
        }
 
        if (opt)
@@ -1164,6 +1166,7 @@ static inline int ip_vs_proc_sync_conn(struct net *net, __u8 *p, __u8 *msg_end)
                                (opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL)
                                );
 #endif
+       ip_vs_pe_put(param.pe);
        return 0;
        /* Error exit */
 out:
index d25f293776482f5e88c831c290058f2ca2e6af2b..957c1db6665254645f43d0c04456015a1d4df65c 100644 (file)
 
 static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
 
+static bool nf_generic_should_process(u8 proto)
+{
+       switch (proto) {
+#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE
+       case IPPROTO_SCTP:
+               return false;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE
+       case IPPROTO_DCCP:
+               return false;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE
+       case IPPROTO_GRE:
+               return false;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE
+       case IPPROTO_UDPLITE:
+               return false;
+#endif
+       default:
+               return true;
+       }
+}
+
 static inline struct nf_generic_net *generic_pernet(struct net *net)
 {
        return &net->ct.nf_ct_proto.generic;
@@ -67,7 +91,7 @@ static int generic_packet(struct nf_conn *ct,
 static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
                        unsigned int dataoff, unsigned int *timeouts)
 {
-       return true;
+       return nf_generic_should_process(nf_ct_protonum(ct));
 }
 
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
index ad979612238a4afd5f6fb75afbb20e31e25b87d1..7350723aeb15772e31c6ff1b9eec4f49a3a03503 100644 (file)
@@ -611,8 +611,12 @@ nft_match_select_ops(const struct nft_ctx *ctx,
                struct xt_match *match = nft_match->ops.data;
 
                if (strcmp(match->name, mt_name) == 0 &&
-                   match->revision == rev && match->family == family)
+                   match->revision == rev && match->family == family) {
+                       if (!try_module_get(match->me))
+                               return ERR_PTR(-ENOENT);
+
                        return &nft_match->ops;
+               }
        }
 
        match = xt_request_find_match(family, mt_name, rev);
@@ -682,8 +686,12 @@ nft_target_select_ops(const struct nft_ctx *ctx,
                struct xt_target *target = nft_target->ops.data;
 
                if (strcmp(target->name, tg_name) == 0 &&
-                   target->revision == rev && target->family == family)
+                   target->revision == rev && target->family == family) {
+                       if (!try_module_get(target->me))
+                               return ERR_PTR(-ENOENT);
+
                        return &nft_target->ops;
+               }
        }
 
        target = xt_request_find_target(family, tg_name, rev);
index 1ba67931eb1b168fabfa78790f5ed53713188f9d..13332dbf291d6e530b77c3c8a7d155a07788ebc3 100644 (file)
@@ -243,12 +243,13 @@ static int
 extract_icmp6_fields(const struct sk_buff *skb,
                     unsigned int outside_hdrlen,
                     int *protocol,
-                    struct in6_addr **raddr,
-                    struct in6_addr **laddr,
+                    const struct in6_addr **raddr,
+                    const struct in6_addr **laddr,
                     __be16 *rport,
-                    __be16 *lport)
+                    __be16 *lport,
+                    struct ipv6hdr *ipv6_var)
 {
-       struct ipv6hdr *inside_iph, _inside_iph;
+       const struct ipv6hdr *inside_iph;
        struct icmp6hdr *icmph, _icmph;
        __be16 *ports, _ports[2];
        u8 inside_nexthdr;
@@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb,
        if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK)
                return 1;
 
-       inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph);
+       inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph),
+                                       sizeof(*ipv6_var), ipv6_var);
        if (inside_iph == NULL)
                return 1;
        inside_nexthdr = inside_iph->nexthdr;
 
-       inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph),
+       inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) +
+                                             sizeof(*ipv6_var),
                                         &inside_nexthdr, &inside_fragoff);
        if (inside_hdrlen < 0)
                return 1; /* hjm: Packet has no/incomplete transport layer headers. */
@@ -315,10 +318,10 @@ xt_socket_get_sock_v6(struct net *net, const u8 protocol,
 static bool
 socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
 {
-       struct ipv6hdr *iph = ipv6_hdr(skb);
+       struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb);
        struct udphdr _hdr, *hp = NULL;
        struct sock *sk = skb->sk;
-       struct in6_addr *daddr = NULL, *saddr = NULL;
+       const struct in6_addr *daddr = NULL, *saddr = NULL;
        __be16 uninitialized_var(dport), uninitialized_var(sport);
        int thoff = 0, uninitialized_var(tproto);
        const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
@@ -342,7 +345,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
 
        } else if (tproto == IPPROTO_ICMPV6) {
                if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
-                                        &sport, &dport))
+                                        &sport, &dport, &ipv6_var))
                        return false;
        } else {
                return false;
index 1d52506bda14145795b52940e41fa5d5fe3bdd9b..a0b0ea949192ef8aefa5ec76bcbbd51736628f76 100644 (file)
@@ -1624,13 +1624,11 @@ static struct sk_buff *netlink_alloc_large_skb(unsigned int size,
        if (data == NULL)
                return NULL;
 
-       skb = build_skb(data, size);
+       skb = __build_skb(data, size);
        if (skb == NULL)
                vfree(data);
-       else {
-               skb->head_frag = 0;
+       else
                skb->destructor = netlink_skb_destructor;
-       }
 
        return skb;
 }
index a817705ce2d0e9246388c2c65d77b4c486a8feba..dba8d0864f18046ee87a168d49cc159518fa2916 100644 (file)
@@ -88,7 +88,9 @@ static unsigned int rds_iw_unmap_fastreg_list(struct rds_iw_mr_pool *pool,
                        int *unpinned);
 static void rds_iw_destroy_fastreg(struct rds_iw_mr_pool *pool, struct rds_iw_mr *ibmr);
 
-static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwdev, struct rdma_cm_id **cm_id)
+static int rds_iw_get_device(struct sockaddr_in *src, struct sockaddr_in *dst,
+                            struct rds_iw_device **rds_iwdev,
+                            struct rdma_cm_id **cm_id)
 {
        struct rds_iw_device *iwdev;
        struct rds_iw_cm_id *i_cm_id;
@@ -112,15 +114,15 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd
                                src_addr->sin_port,
                                dst_addr->sin_addr.s_addr,
                                dst_addr->sin_port,
-                               rs->rs_bound_addr,
-                               rs->rs_bound_port,
-                               rs->rs_conn_addr,
-                               rs->rs_conn_port);
+                               src->sin_addr.s_addr,
+                               src->sin_port,
+                               dst->sin_addr.s_addr,
+                               dst->sin_port);
 #ifdef WORKING_TUPLE_DETECTION
-                       if (src_addr->sin_addr.s_addr == rs->rs_bound_addr &&
-                           src_addr->sin_port == rs->rs_bound_port &&
-                           dst_addr->sin_addr.s_addr == rs->rs_conn_addr &&
-                           dst_addr->sin_port == rs->rs_conn_port) {
+                       if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr &&
+                           src_addr->sin_port == src->sin_port &&
+                           dst_addr->sin_addr.s_addr == dst->sin_addr.s_addr &&
+                           dst_addr->sin_port == dst->sin_port) {
 #else
                        /* FIXME - needs to compare the local and remote
                         * ipaddr/port tuple, but the ipaddr is the only
@@ -128,7 +130,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd
                         * zero'ed.  It doesn't appear to be properly populated
                         * during connection setup...
                         */
-                       if (src_addr->sin_addr.s_addr == rs->rs_bound_addr) {
+                       if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr) {
 #endif
                                spin_unlock_irq(&iwdev->spinlock);
                                *rds_iwdev = iwdev;
@@ -180,19 +182,13 @@ int rds_iw_update_cm_id(struct rds_iw_device *rds_iwdev, struct rdma_cm_id *cm_i
 {
        struct sockaddr_in *src_addr, *dst_addr;
        struct rds_iw_device *rds_iwdev_old;
-       struct rds_sock rs;
        struct rdma_cm_id *pcm_id;
        int rc;
 
        src_addr = (struct sockaddr_in *)&cm_id->route.addr.src_addr;
        dst_addr = (struct sockaddr_in *)&cm_id->route.addr.dst_addr;
 
-       rs.rs_bound_addr = src_addr->sin_addr.s_addr;
-       rs.rs_bound_port = src_addr->sin_port;
-       rs.rs_conn_addr = dst_addr->sin_addr.s_addr;
-       rs.rs_conn_port = dst_addr->sin_port;
-
-       rc = rds_iw_get_device(&rs, &rds_iwdev_old, &pcm_id);
+       rc = rds_iw_get_device(src_addr, dst_addr, &rds_iwdev_old, &pcm_id);
        if (rc)
                rds_iw_remove_cm_id(rds_iwdev, cm_id);
 
@@ -598,9 +594,17 @@ void *rds_iw_get_mr(struct scatterlist *sg, unsigned long nents,
        struct rds_iw_device *rds_iwdev;
        struct rds_iw_mr *ibmr = NULL;
        struct rdma_cm_id *cm_id;
+       struct sockaddr_in src = {
+               .sin_addr.s_addr = rs->rs_bound_addr,
+               .sin_port = rs->rs_bound_port,
+       };
+       struct sockaddr_in dst = {
+               .sin_addr.s_addr = rs->rs_conn_addr,
+               .sin_port = rs->rs_conn_port,
+       };
        int ret;
 
-       ret = rds_iw_get_device(rs, &rds_iwdev, &cm_id);
+       ret = rds_iw_get_device(&src, &dst, &rds_iwdev, &cm_id);
        if (ret || !cm_id) {
                ret = -ENODEV;
                goto out;
index b5cb2aa08f33aa62ac5bff73684fc228f74dce7e..35773ad6d23de4cf8d390ec3f1e3b1689ce19405 100644 (file)
@@ -71,14 +71,14 @@ static struct ctl_table rds_sysctl_rds_table[] = {
        {
                .procname       = "max_unacked_packets",
                .data           = &rds_sysctl_max_unacked_packets,
-               .maxlen         = sizeof(unsigned long),
+               .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
        {
                .procname       = "max_unacked_bytes",
                .data           = &rds_sysctl_max_unacked_bytes,
-               .maxlen         = sizeof(unsigned long),
+               .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
index 6ec133bf10e0cd0c675d794a7104133bf1f4ffd0..3f13b189af1124fd63eedfd84a0273541ec4baa9 100644 (file)
@@ -248,6 +248,14 @@ static int rpmsg_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                return -EOPNOTSUPP;
        }
 
+       /* return failure on errored-out Rx sockets */
+       lock_sock(sk);
+       if (sk->sk_state == RPMSG_ERROR) {
+               release_sock(sk);
+               return -ENOLINK;
+       }
+       release_sock(sk);
+
        msg->msg_namelen = 0;
 
        skb = skb_recv_datagram(sk, flags, noblock, &ret);
@@ -297,6 +305,8 @@ static unsigned int rpmsg_sock_poll(struct file *file, struct socket *sock,
        /* exceptional events? */
        if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
                mask |= POLLERR;
+       if (sk->sk_state == RPMSG_ERROR)
+               mask |= POLLERR;
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= POLLRDHUP;
        if (sk->sk_shutdown == SHUTDOWN_MASK)
@@ -714,6 +724,7 @@ static void rpmsg_proto_remove(struct rpmsg_channel *rpdev)
                        sk->sk_state = RPMSG_ERROR;
                        rpsk = container_of(sk, struct rpmsg_socket, sk);
                        rpsk->rpdev = NULL;
+                       sk->sk_error_report(sk);
                        release_sock(sk);
                }
        }
index 34b5490dde655ccdbac5dcbbc7b0df1b88ab42ca..4949f753686c20edb2e7d477bc4b850b1a651b7c 100644 (file)
@@ -87,7 +87,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
                if (!skb) {
                        /* nothing remains on the queue */
                        if (copied &&
-                           (msg->msg_flags & MSG_PEEK || timeo == 0))
+                           (flags & MSG_PEEK || timeo == 0))
                                goto out;
 
                        /* wait for a message to turn up */
index 3a633debb6df00f4bf13f51bacbdad0829ad321b..a2abc449ce8feb2b5a0277c79233c3f4f85e7e5d 100644 (file)
@@ -227,6 +227,7 @@ static int tcf_em_validate(struct tcf_proto *tp,
                                 * to replay the request.
                                 */
                                module_put(em->ops->owner);
+                               em->ops = NULL;
                                err = -EAGAIN;
                        }
 #endif
index ae333c1845bb42f28198cdfb957cd03e7412c14c..0adc66caae2f460e54c980373e36e612b268d53a 100644 (file)
@@ -920,7 +920,7 @@ static unsigned int cache_poll(struct file *filp, poll_table *wait,
        poll_wait(filp, &queue_wait, wait);
 
        /* alway allow write */
-       mask = POLL_OUT | POLLWRNORM;
+       mask = POLLOUT | POLLWRNORM;
 
        if (!rp)
                return mask;
index 3919e35ddccc09ff1407ec6fcf41bca2997e3c54..976d1b5ed034b0ce65003748407cf409b5f8c71d 100644 (file)
@@ -4190,6 +4190,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
        if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
                return -EINVAL;
 
+       /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
+        * as userspace might just pass through the capabilities from the IEs
+        * directly, rather than enforcing this restriction and returning an
+        * error in this case.
+        */
+       if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) {
+               params.ht_capa = NULL;
+               params.vht_capa = NULL;
+       }
+
        /* When you run into this, adjust the code below for the new flag */
        BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);
 
index 59b13440813d59da2f4fd7869e960da29739c3b9..f950302af90543496beac3d360579eae2f2429b8 100644 (file)
 #define MSG            "hello world!"
 #define MSG_LIMIT      100
 
+struct instance_data {
+       int rx_count;
+};
+
 static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
                                                void *priv, u32 src)
 {
        int ret;
-       static int rx_count;
+       struct instance_data *idata = dev_get_drvdata(&rpdev->dev);
 
-       dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n", ++rx_count, src);
+       dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n",
+                ++idata->rx_count, src);
 
        print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1,
                       data, len,  true);
 
        /* samples should not live forever */
-       if (rx_count >= MSG_LIMIT) {
+       if (idata->rx_count >= MSG_LIMIT) {
                dev_info(&rpdev->dev, "goodbye!\n");
                return;
        }
@@ -50,10 +55,18 @@ static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
 static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
 {
        int ret;
+       struct instance_data *idata;
 
        dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
                                        rpdev->src, rpdev->dst);
 
+       idata = devm_kzalloc(&rpdev->dev, sizeof(*idata), GFP_KERNEL);
+       if (!idata) {
+               dev_err(&rpdev->dev, "channel data memory allocation failed\n");
+               return -ENOMEM;
+       }
+       dev_set_drvdata(&rpdev->dev, idata);
+
        /* send a message to our remote processor */
        ret = rpmsg_send(rpdev, MSG, strlen(MSG));
        if (ret) {
index ee96a2519eff6f39d2f093ae88774c612d71906e..eda12b7dc286b65ffc416cc814ad83d46331e233 100644 (file)
@@ -53,7 +53,7 @@ struct check {
        void *data;
        bool warn, error;
        enum checkstatus status;
-       int inprogress;
+       bool inprogress;
        int num_prereqs;
        struct check **prereq;
 };
@@ -113,6 +113,7 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
                vfprintf(stderr, fmt, ap);
                fprintf(stderr, "\n");
        }
+       va_end(ap);
 }
 
 #define FAIL(c, ...) \
@@ -141,9 +142,9 @@ static void check_nodes_props(struct check *c, struct node *dt, struct node *nod
                check_nodes_props(c, dt, child);
 }
 
-static int run_check(struct check *c, struct node *dt)
+static bool run_check(struct check *c, struct node *dt)
 {
-       int error = 0;
+       bool error = false;
        int i;
 
        assert(!c->inprogress);
@@ -151,11 +152,11 @@ static int run_check(struct check *c, struct node *dt)
        if (c->status != UNCHECKED)
                goto out;
 
-       c->inprogress = 1;
+       c->inprogress = true;
 
        for (i = 0; i < c->num_prereqs; i++) {
                struct check *prq = c->prereq[i];
-               error |= run_check(prq, dt);
+               error = error || run_check(prq, dt);
                if (prq->status != PASSED) {
                        c->status = PREREQ;
                        check_msg(c, "Failed prerequisite '%s'",
@@ -177,9 +178,9 @@ static int run_check(struct check *c, struct node *dt)
        TRACE(c, "\tCompleted, status %d", c->status);
 
 out:
-       c->inprogress = 0;
+       c->inprogress = false;
        if ((c->status != PASSED) && (c->error))
-               error = 1;
+               error = true;
        return error;
 }
 
@@ -624,11 +625,11 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
        if (!reg && !ranges)
                return;
 
-       if ((node->parent->addr_cells == -1))
+       if (node->parent->addr_cells == -1)
                FAIL(c, "Relying on default #address-cells value for %s",
                     node->fullpath);
 
-       if ((node->parent->size_cells == -1))
+       if (node->parent->size_cells == -1)
                FAIL(c, "Relying on default #size-cells value for %s",
                     node->fullpath);
 }
@@ -706,15 +707,14 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
        c->error = c->error && !error;
 }
 
-void parse_checks_option(bool warn, bool error, const char *optarg)
+void parse_checks_option(bool warn, bool error, const char *arg)
 {
        int i;
-       const char *name = optarg;
+       const char *name = arg;
        bool enable = true;
 
-       if ((strncmp(optarg, "no-", 3) == 0)
-           || (strncmp(optarg, "no_", 3) == 0)) {
-               name = optarg + 3;
+       if ((strncmp(arg, "no-", 3) == 0) || (strncmp(arg, "no_", 3) == 0)) {
+               name = arg + 3;
                enable = false;
        }
 
@@ -733,7 +733,7 @@ void parse_checks_option(bool warn, bool error, const char *optarg)
        die("Unrecognized check name \"%s\"\n", name);
 }
 
-void process_checks(int force, struct boot_info *bi)
+void process_checks(bool force, struct boot_info *bi)
 {
        struct node *dt = bi->dt;
        int i;
index 4a40c5b92474fede88049a2de4876ad641e9e063..8cae23746882e4747ea5d13e300484452fc48eee 100644 (file)
@@ -74,7 +74,7 @@ struct data data_copy_escape_string(const char *s, int len)
        struct data d;
        char *q;
 
-       d = data_grow_for(empty_data, strlen(s)+1);
+       d = data_grow_for(empty_data, len + 1);
 
        q = d.val;
        while (i < len) {
@@ -250,20 +250,20 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref)
        return data_append_markers(d, m);
 }
 
-int data_is_one_string(struct data d)
+bool data_is_one_string(struct data d)
 {
        int i;
        int len = d.len;
 
        if (len == 0)
-               return 0;
+               return false;
 
        for (i = 0; i < len-1; i++)
                if (d.val[i] == '\0')
-                       return 0;
+                       return false;
 
        if (d.val[len-1] != '\0')
-               return 0;
+               return false;
 
-       return 1;
+       return true;
 }
index 3b41bfca636cea743e575cf3c7dfcb95967e915e..0ee1caf03dd057bee8c212002568941f0658edd7 100644 (file)
@@ -20,7 +20,6 @@
 
 %option noyywrap nounput noinput never-interactive
 
-%x INCLUDE
 %x BYTESTRING
 %x PROPNODENAME
 %s V1
@@ -40,6 +39,7 @@ LINECOMMENT   "//".*\n
 #include "dtc-parser.tab.h"
 
 YYLTYPE yylloc;
+extern bool treesource_error;
 
 /* CAUTION: this will stop working if we ever use yyless() or yyunput() */
 #define        YY_USER_ACTION \
@@ -61,7 +61,8 @@ static int dts_version = 1;
                                BEGIN(V1); \
 
 static void push_input_file(const char *filename);
-static int pop_input_file(void);
+static bool pop_input_file(void);
+static void lexical_error(const char *fmt, ...);
 %}
 
 %%
@@ -75,11 +76,11 @@ static int pop_input_file(void);
                        char *line, *tmp, *fn;
                        /* skip text before line # */
                        line = yytext;
-                       while (!isdigit(*line))
+                       while (!isdigit((unsigned char)*line))
                                line++;
                        /* skip digits in line # */
                        tmp = line;
-                       while (!isspace(*tmp))
+                       while (!isspace((unsigned char)*tmp))
                                tmp++;
                        /* "NULL"-terminate line # */
                        *tmp = '\0';
@@ -146,15 +147,42 @@ static int pop_input_file(void);
                }
 
 <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
-                       yylval.literal = xstrdup(yytext);
-                       DPRINT("Literal: '%s'\n", yylval.literal);
+                       char *e;
+                       DPRINT("Integer Literal: '%s'\n", yytext);
+
+                       errno = 0;
+                       yylval.integer = strtoull(yytext, &e, 0);
+
+                       assert(!(*e) || !e[strspn(e, "UL")]);
+
+                       if (errno == ERANGE)
+                               lexical_error("Integer literal '%s' out of range",
+                                             yytext);
+                       else
+                               /* ERANGE is the only strtoull error triggerable
+                                *  by strings matching the pattern */
+                               assert(errno == 0);
                        return DT_LITERAL;
                }
 
 <*>{CHAR_LITERAL}      {
-                       yytext[yyleng-1] = '\0';
-                       yylval.literal = xstrdup(yytext+1);
-                       DPRINT("Character literal: %s\n", yylval.literal);
+                       struct data d;
+                       DPRINT("Character literal: %s\n", yytext);
+
+                       d = data_copy_escape_string(yytext+1, yyleng-2);
+                       if (d.len == 1) {
+                               lexical_error("Empty character literal");
+                               yylval.integer = 0;
+                               return DT_CHAR_LITERAL;
+                       }
+
+                       yylval.integer = (unsigned char)d.val[0];
+
+                       if (d.len > 2)
+                               lexical_error("Character literal has %d"
+                                             " characters instead of 1",
+                                             d.len - 1);
+
                        return DT_CHAR_LITERAL;
                }
 
@@ -164,7 +192,7 @@ static int pop_input_file(void);
                        return DT_REF;
                }
 
-<*>"&{/"{PATHCHAR}+\}  {       /* new-style path reference */
+<*>"&{/"{PATHCHAR}*\}  {       /* new-style path reference */
                        yytext[yyleng-1] = '\0';
                        DPRINT("Ref: %s\n", yytext+2);
                        yylval.labelref = xstrdup(yytext+2);
@@ -238,13 +266,24 @@ static void push_input_file(const char *filename)
 }
 
 
-static int pop_input_file(void)
+static bool pop_input_file(void)
 {
        if (srcfile_pop() == 0)
-               return 0;
+               return false;
 
        yypop_buffer_state();
        yyin = current_srcfile->f;
 
-       return 1;
+       return true;
+}
+
+static void lexical_error(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       srcpos_verror(&yylloc, "Lexical error", fmt, ap);
+       va_end(ap);
+
+       treesource_error = true;
 }
index 2d30f41778b7270b074798b4439952dca28d9c53..a34a2c8b26e223d68066e95e04717ffff0d60498 100644 (file)
@@ -381,25 +381,25 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[161] =
+static yyconst flex_int16_t yy_accept[159] =
     {   0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       31,   29,   18,   18,   29,   29,   29,   29,   29,   29,
-       29,   29,   29,   29,   29,   29,   29,   29,   15,   16,
-       16,   29,   16,   10,   10,   18,   26,    0,    3,    0,
-       27,   12,    0,    0,   11,    0,    0,    0,    0,    0,
-        0,    0,   21,   23,   25,   24,   22,    0,    9,   28,
-        0,    0,    0,   14,   14,   16,   16,   16,   10,   10,
-       10,    0,   12,    0,   11,    0,    0,    0,   20,    0,
-        0,    0,    0,    0,    0,    0,    0,   16,   10,   10,
-       10,    0,   19,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,   16,   13,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,   16,    6,    0,    0,    0,    0,    0,
-        0,    2,    0,    0,    0,    0,    0,    0,    0,    0,
-        4,   17,    0,    0,    2,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    1,    0,    0,
-        0,    0,    5,    8,    0,    0,    0,    0,    7,    0
+        0,    0,    0,    0,    0,    0,    0,    0,   31,   29,
+       18,   18,   29,   29,   29,   29,   29,   29,   29,   29,
+       29,   29,   29,   29,   29,   29,   15,   16,   16,   29,
+       16,   10,   10,   18,   26,    0,    3,    0,   27,   12,
+        0,    0,   11,    0,    0,    0,    0,    0,    0,    0,
+       21,   23,   25,   24,   22,    0,    9,   28,    0,    0,
+        0,   14,   14,   16,   16,   16,   10,   10,   10,    0,
+       12,    0,   11,    0,    0,    0,   20,    0,    0,    0,
+        0,    0,    0,    0,    0,   16,   10,   10,   10,    0,
+       13,   19,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,   16,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   16,    6,    0,    0,    0,    0,    0,    0,    2,
+        0,    0,    0,    0,    0,    0,    0,    0,    4,   17,
+        0,    0,    2,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    1,    0,    0,    0,    0,
+        5,    8,    0,    0,    0,    0,    7,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -440,157 +440,157 @@ static yyconst flex_int32_t yy_meta[47] =
         2,    2,    4,    5,    5,    5,    6,    1,    1,    1,
         7,    8,    8,    8,    8,    1,    1,    7,    7,    7,
         7,    8,    8,    8,    8,    8,    8,    8,    8,    8,
-        8,    8,    8,    3,    1,    1
+        8,    8,    8,    3,    1,    4
     } ;
 
-static yyconst flex_int16_t yy_base[175] =
+static yyconst flex_int16_t yy_base[173] =
     {   0,
-        0,  385,  378,   40,   41,  383,   72,  382,   34,   44,
-      388,  393,   61,  117,  368,  116,  115,  115,  115,   48,
-      367,  107,  368,  339,  127,  120,    0,  147,  393,    0,
-      127,    0,  133,  156,  168,  153,  393,  125,  393,  380,
-      393,    0,  369,  127,  393,  160,  371,  377,  347,   21,
-      343,  346,  393,  393,  393,  393,  393,  359,  393,  393,
-      183,  343,  339,  393,  356,    0,  183,  340,  187,  348,
-      347,    0,    0,    0,  178,  359,  195,  365,  354,  326,
-      332,  325,  334,  328,  204,  326,  331,  324,  393,  335,
-      150,  311,  343,  342,  315,  322,  340,  179,  313,  207,
-
-      319,  316,  317,  393,  337,  333,  305,  302,  311,  301,
-      310,  190,  338,  337,  393,  307,  322,  301,  305,  277,
-      208,  311,  307,  278,  271,  270,  248,  246,  213,  130,
-      393,  393,  263,  235,  207,  221,  218,  229,  213,  213,
-      206,  234,  218,  210,  208,  193,  219,  393,  223,  204,
-      176,  157,  393,  393,  120,  106,   97,  119,  393,  393,
-      245,  251,  259,  263,  267,  273,  280,  284,  292,  300,
-      304,  310,  318,  326
+        0,  383,   34,  382,   65,  381,   37,  105,  387,  391,
+       54,  111,  367,  110,  109,  109,  112,   41,  366,  104,
+      367,  338,  124,  117,    0,  144,  391,    0,  121,    0,
+      135,  155,  140,  179,  391,  160,  391,  379,  391,    0,
+      368,  141,  391,  167,  370,  376,  346,  103,  342,  345,
+      391,  391,  391,  391,  391,  358,  391,  391,  175,  342,
+      338,  391,  355,    0,  185,  339,  184,  347,  346,    0,
+        0,  322,  175,  357,  175,  363,  352,  324,  330,  323,
+      332,  326,  201,  324,  329,  322,  391,  333,  181,  309,
+      391,  341,  340,  313,  320,  338,  178,  311,  146,  317,
+
+      314,  315,  335,  331,  303,  300,  309,  299,  308,  188,
+      336,  335,  391,  305,  320,  281,  283,  271,  203,  288,
+      281,  271,  266,  264,  245,  242,  208,  104,  391,  391,
+      244,  218,  204,  219,  206,  224,  201,  212,  204,  229,
+      215,  208,  207,  200,  219,  391,  233,  221,  200,  181,
+      391,  391,  149,  122,   86,   41,  391,  391,  245,  251,
+      259,  263,  267,  273,  280,  284,  292,  300,  304,  310,
+      318,  326
     } ;
 
-static yyconst flex_int16_t yy_def[175] =
+static yyconst flex_int16_t yy_def[173] =
     {   0,
-      160,    1,    1,    1,    1,    5,  160,    7,    1,    1,
-      160,  160,  160,  160,  160,  161,  162,  163,  160,  160,
-      160,  160,  164,  160,  160,  160,  165,  164,  160,  166,
-      167,  166,  166,  160,  160,  160,  160,  161,  160,  161,
-      160,  168,  160,  163,  160,  163,  169,  170,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  164,  160,  160,
-      160,  160,  160,  160,  164,  166,  167,  166,  160,  160,
-      160,  171,  168,  172,  163,  169,  169,  170,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  166,  160,  160,
-      171,  172,  160,  160,  160,  160,  160,  160,  160,  160,
-
-      160,  160,  166,  160,  160,  160,  160,  160,  160,  160,
-      160,  173,  160,  166,  160,  160,  160,  160,  160,  160,
-      173,  160,  173,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  174,  160,  160,  160,  174,  160,  174,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,    0,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160
+      158,    1,    1,    3,  158,    5,    1,    1,  158,  158,
+      158,  158,  158,  159,  160,  161,  158,  158,  158,  158,
+      162,  158,  158,  158,  163,  162,  158,  164,  165,  164,
+      164,  158,  158,  158,  158,  159,  158,  159,  158,  166,
+      158,  161,  158,  161,  167,  168,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  162,  158,  158,  158,  158,
+      158,  158,  162,  164,  165,  164,  158,  158,  158,  169,
+      166,  170,  161,  167,  167,  168,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  164,  158,  158,  169,  170,
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+
+      158,  164,  158,  158,  158,  158,  158,  158,  158,  171,
+      158,  164,  158,  158,  158,  158,  158,  158,  171,  158,
+      171,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      172,  158,  158,  158,  172,  158,  172,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158,    0,  158,  158,
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      158,  158
     } ;
 
-static yyconst flex_int16_t yy_nxt[440] =
+static yyconst flex_int16_t yy_nxt[438] =
     {   0,
-       12,   13,   14,   13,   15,   16,   12,   17,   18,   12,
-       12,   12,   19,   12,   12,   12,   12,   20,   21,   22,
-       23,   23,   23,   23,   23,   12,   12,   23,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   23,   12,   24,   12,   25,   34,   35,   35,
-       25,   81,   26,   26,   27,   27,   27,   34,   35,   35,
-       82,   28,   36,   36,   36,   53,   54,   29,   28,   28,
-       28,   28,   12,   13,   14,   13,   15,   16,   30,   17,
-       18,   30,   30,   30,   26,   30,   30,   30,   12,   20,
-       21,   22,   31,   31,   31,   31,   31,   32,   12,   31,
-
-       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   31,   31,   12,   24,   12,   36,   36,
-       36,   39,   41,   45,   47,   56,   57,   48,   61,   47,
-       39,  159,   48,   66,   61,   45,   66,   66,   66,  158,
-       46,   40,   49,   59,   50,  157,   51,   49,   52,   50,
-       40,   63,   46,   52,   36,   36,   36,  156,   43,   62,
-       65,   65,   65,   59,  136,   68,  137,   65,   75,   69,
-       69,   69,   70,   71,   65,   65,   65,   65,   70,   71,
-       72,   69,   69,   69,   61,   46,   45,  155,  154,   66,
-       70,   71,   66,   66,   66,  122,   85,   85,   85,   59,
-
-       69,   69,   69,   46,   77,  100,  109,   93,  100,   70,
-       71,  110,  112,  122,  129,  123,  153,   85,   85,   85,
-      135,  135,  135,  148,  148,  160,  135,  135,  135,  152,
-      142,  142,  142,  123,  143,  142,  142,  142,  151,  143,
-      150,  146,  145,  149,  149,   38,   38,   38,   38,   38,
-       38,   38,   38,   42,  144,  141,  140,   42,   42,   44,
-       44,   44,   44,   44,   44,   44,   44,   58,   58,   58,
-       58,   64,  139,   64,   66,  138,  134,   66,  133,   66,
-       66,   67,  132,  131,   67,   67,   67,   67,   73,  130,
-       73,   73,   76,   76,   76,   76,   76,   76,   76,   76,
-
-       78,   78,   78,   78,   78,   78,   78,   78,   91,  160,
-       91,   92,  129,   92,   92,  128,   92,   92,  121,  121,
-      121,  121,  121,  121,  121,  121,  147,  147,  147,  147,
-      147,  147,  147,  147,  127,  126,  125,  124,   61,   61,
-      120,  119,  118,  117,  116,  115,   47,  114,  110,  113,
-      111,  108,  107,  106,   48,  105,  104,   89,  103,  102,
-      101,   99,   98,   97,   96,   95,   94,   79,   77,   90,
-       89,   88,   59,   87,   86,   59,   84,   83,   80,   79,
-       77,   74,  160,   60,   59,   55,   37,  160,   33,   25,
-       26,   25,   11,  160,  160,  160,  160,  160,  160,  160,
-
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160
+       10,   11,   12,   11,   13,   14,   10,   15,   16,   10,
+       10,   10,   17,   10,   10,   10,   10,   18,   19,   20,
+       21,   21,   21,   21,   21,   10,   10,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   10,   22,   10,   24,   25,   25,   25,
+       32,   33,   33,  157,   26,   34,   34,   34,   51,   52,
+       27,   26,   26,   26,   26,   10,   11,   12,   11,   13,
+       14,   28,   15,   16,   28,   28,   28,   24,   28,   28,
+       28,   10,   18,   19,   20,   29,   29,   29,   29,   29,
+       30,   10,   29,   29,   29,   29,   29,   29,   29,   29,
+
+       29,   29,   29,   29,   29,   29,   29,   29,   10,   22,
+       10,   23,   34,   34,   34,   37,   39,   43,   32,   33,
+       33,   45,   54,   55,   46,   59,   45,   64,  156,   46,
+       64,   64,   64,   79,   44,   38,   59,   57,  134,   47,
+      135,   48,   80,   49,   47,   50,   48,   99,   61,   43,
+       50,  110,   41,   67,   67,   67,   60,   63,   63,   63,
+       57,  155,   68,   69,   63,   37,   44,   66,   67,   67,
+       67,   63,   63,   63,   63,   73,   59,   68,   69,   70,
+       34,   34,   34,   43,   75,   38,  154,   92,   83,   83,
+       83,   64,   44,  120,   64,   64,   64,   67,   67,   67,
+
+       44,   57,   99,   68,   69,  107,   68,   69,  120,  127,
+      108,  153,  152,  121,   83,   83,   83,  133,  133,  133,
+      146,  133,  133,  133,  146,  140,  140,  140,  121,  141,
+      140,  140,  140,  151,  141,  158,  150,  149,  148,  144,
+      147,  143,  142,  139,  147,   36,   36,   36,   36,   36,
+       36,   36,   36,   40,  138,  137,  136,   40,   40,   42,
+       42,   42,   42,   42,   42,   42,   42,   56,   56,   56,
+       56,   62,  132,   62,   64,  131,  130,   64,  129,   64,
+       64,   65,  128,  158,   65,   65,   65,   65,   71,  127,
+       71,   71,   74,   74,   74,   74,   74,   74,   74,   74,
+
+       76,   76,   76,   76,   76,   76,   76,   76,   89,  126,
+       89,   90,  125,   90,   90,  124,   90,   90,  119,  119,
+      119,  119,  119,  119,  119,  119,  145,  145,  145,  145,
+      145,  145,  145,  145,  123,  122,   59,   59,  118,  117,
+      116,  115,  114,  113,   45,  112,  108,  111,  109,  106,
+      105,  104,   46,  103,   91,   87,  102,  101,  100,   98,
+       97,   96,   95,   94,   93,   77,   75,   91,   88,   87,
+       86,   57,   85,   84,   57,   82,   81,   78,   77,   75,
+       72,  158,   58,   57,   53,   35,  158,   31,   23,   23,
+        9,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158
     } ;
 
-static yyconst flex_int16_t yy_chk[440] =
+static yyconst flex_int16_t yy_chk[438] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    4,    9,    9,    9,
-       10,   50,    4,    5,    5,    5,    5,   10,   10,   10,
-       50,    5,   13,   13,   13,   20,   20,    5,    5,    5,
-        5,    5,    7,    7,    7,    7,    7,    7,    7,    7,
-        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-
-        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-        7,    7,    7,    7,    7,    7,    7,    7,   14,   14,
-       14,   16,   17,   18,   19,   22,   22,   19,   25,   26,
-       38,  158,   26,   31,   33,   44,   31,   31,   31,  157,
-       18,   16,   19,   31,   19,  156,   19,   26,   19,   26,
-       38,   26,   44,   26,   36,   36,   36,  155,   17,   25,
-       28,   28,   28,   28,  130,   33,  130,   28,   46,   34,
-       34,   34,   91,   91,   28,   28,   28,   28,   34,   34,
-       34,   35,   35,   35,   61,   46,   75,  152,  151,   67,
-       35,   35,   67,   67,   67,  112,   61,   61,   61,   67,
-
-       69,   69,   69,   75,   77,   85,   98,   77,  100,   69,
-       69,   98,  100,  121,  129,  112,  150,   85,   85,   85,
-      135,  135,  135,  143,  147,  149,  129,  129,  129,  146,
-      138,  138,  138,  121,  138,  142,  142,  142,  145,  142,
-      144,  141,  140,  143,  147,  161,  161,  161,  161,  161,
-      161,  161,  161,  162,  139,  137,  136,  162,  162,  163,
-      163,  163,  163,  163,  163,  163,  163,  164,  164,  164,
-      164,  165,  134,  165,  166,  133,  128,  166,  127,  166,
-      166,  167,  126,  125,  167,  167,  167,  167,  168,  124,
-      168,  168,  169,  169,  169,  169,  169,  169,  169,  169,
-
-      170,  170,  170,  170,  170,  170,  170,  170,  171,  123,
-      171,  172,  122,  172,  172,  120,  172,  172,  173,  173,
-      173,  173,  173,  173,  173,  173,  174,  174,  174,  174,
-      174,  174,  174,  174,  119,  118,  117,  116,  114,  113,
-      111,  110,  109,  108,  107,  106,  105,  103,  102,  101,
-       99,   97,   96,   95,   94,   93,   92,   90,   88,   87,
-       86,   84,   83,   82,   81,   80,   79,   78,   76,   71,
-       70,   68,   65,   63,   62,   58,   52,   51,   49,   48,
-       47,   43,   40,   24,   23,   21,   15,   11,    8,    6,
-        3,    2,  160,  160,  160,  160,  160,  160,  160,  160,
-
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160
+        1,    1,    1,    1,    1,    1,    3,    3,    3,    3,
+        7,    7,    7,  156,    3,   11,   11,   11,   18,   18,
+        3,    3,    3,    3,    3,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    8,   12,   12,   12,   14,   15,   16,    8,    8,
+        8,   17,   20,   20,   17,   23,   24,   29,  155,   24,
+       29,   29,   29,   48,   16,   14,   31,   29,  128,   17,
+      128,   17,   48,   17,   24,   17,   24,   99,   24,   42,
+       24,   99,   15,   33,   33,   33,   23,   26,   26,   26,
+       26,  154,   33,   33,   26,   36,   42,   31,   32,   32,
+       32,   26,   26,   26,   26,   44,   59,   32,   32,   32,
+       34,   34,   34,   73,   75,   36,  153,   75,   59,   59,
+       59,   65,   44,  110,   65,   65,   65,   67,   67,   67,
+
+       73,   65,   83,   89,   89,   97,   67,   67,  119,  127,
+       97,  150,  149,  110,   83,   83,   83,  133,  133,  133,
+      141,  127,  127,  127,  145,  136,  136,  136,  119,  136,
+      140,  140,  140,  148,  140,  147,  144,  143,  142,  139,
+      141,  138,  137,  135,  145,  159,  159,  159,  159,  159,
+      159,  159,  159,  160,  134,  132,  131,  160,  160,  161,
+      161,  161,  161,  161,  161,  161,  161,  162,  162,  162,
+      162,  163,  126,  163,  164,  125,  124,  164,  123,  164,
+      164,  165,  122,  121,  165,  165,  165,  165,  166,  120,
+      166,  166,  167,  167,  167,  167,  167,  167,  167,  167,
+
+      168,  168,  168,  168,  168,  168,  168,  168,  169,  118,
+      169,  170,  117,  170,  170,  116,  170,  170,  171,  171,
+      171,  171,  171,  171,  171,  171,  172,  172,  172,  172,
+      172,  172,  172,  172,  115,  114,  112,  111,  109,  108,
+      107,  106,  105,  104,  103,  102,  101,  100,   98,   96,
+       95,   94,   93,   92,   90,   88,   86,   85,   84,   82,
+       81,   80,   79,   78,   77,   76,   74,   72,   69,   68,
+       66,   63,   61,   60,   56,   50,   49,   47,   46,   45,
+       41,   38,   22,   21,   19,   13,    9,    6,    4,    2,
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
+      158,  158,  158,  158,  158,  158,  158
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -631,13 +631,13 @@ char *yytext;
 
 
 
-
-#line 38 "dtc-lexer.l"
+#line 37 "dtc-lexer.l"
 #include "dtc.h"
 #include "srcpos.h"
 #include "dtc-parser.tab.h"
 
 YYLTYPE yylloc;
+extern bool treesource_error;
 
 /* CAUTION: this will stop working if we ever use yyless() or yyunput() */
 #define        YY_USER_ACTION \
@@ -659,14 +659,14 @@ static int dts_version = 1;
                                BEGIN(V1); \
 
 static void push_input_file(const char *filename);
-static int pop_input_file(void);
-#line 664 "dtc-lexer.lex.c"
+static bool pop_input_file(void);
+static void lexical_error(const char *fmt, ...);
+#line 665 "dtc-lexer.lex.c"
 
 #define INITIAL 0
-#define INCLUDE 1
-#define BYTESTRING 2
-#define PROPNODENAME 3
-#define V1 4
+#define BYTESTRING 1
+#define PROPNODENAME 2
+#define V1 3
 
 #ifndef YY_NO_UNISTD_H
 /* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -852,7 +852,7 @@ YY_DECL
        register char *yy_cp, *yy_bp;
        register int yy_act;
     
-#line 67 "dtc-lexer.l"
+#line 68 "dtc-lexer.l"
 
 #line 858 "dtc-lexer.lex.c"
 
@@ -908,13 +908,13 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 161 )
+                               if ( yy_current_state >= 159 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
                        ++yy_cp;
                        }
-               while ( yy_current_state != 160 );
+               while ( yy_current_state != 158 );
                yy_cp = (yy_last_accepting_cpos);
                yy_current_state = (yy_last_accepting_state);
 
@@ -937,7 +937,7 @@ do_action:  /* This label is used only to access EOF actions. */
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
-#line 68 "dtc-lexer.l"
+#line 69 "dtc-lexer.l"
 {
                        char *name = strchr(yytext, '\"') + 1;
                        yytext[yyleng-1] = '\0';
@@ -947,16 +947,16 @@ YY_RULE_SETUP
 case 2:
 /* rule 2 can match eol */
 YY_RULE_SETUP
-#line 74 "dtc-lexer.l"
+#line 75 "dtc-lexer.l"
 {
                        char *line, *tmp, *fn;
                        /* skip text before line # */
                        line = yytext;
-                       while (!isdigit(*line))
+                       while (!isdigit((unsigned char)*line))
                                line++;
                        /* skip digits in line # */
                        tmp = line;
-                       while (!isspace(*tmp))
+                       while (!isspace((unsigned char)*tmp))
                                tmp++;
                        /* "NULL"-terminate line # */
                        *tmp = '\0';
@@ -970,11 +970,10 @@ YY_RULE_SETUP
                }
        YY_BREAK
 case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(INCLUDE):
 case YY_STATE_EOF(BYTESTRING):
 case YY_STATE_EOF(PROPNODENAME):
 case YY_STATE_EOF(V1):
-#line 95 "dtc-lexer.l"
+#line 96 "dtc-lexer.l"
 {
                        if (!pop_input_file()) {
                                yyterminate();
@@ -984,7 +983,7 @@ case YY_STATE_EOF(V1):
 case 3:
 /* rule 3 can match eol */
 YY_RULE_SETUP
-#line 101 "dtc-lexer.l"
+#line 102 "dtc-lexer.l"
 {
                        DPRINT("String: %s\n", yytext);
                        yylval.data = data_copy_escape_string(yytext+1,
@@ -994,7 +993,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 108 "dtc-lexer.l"
+#line 109 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /dts-v1/\n");
                        dts_version = 1;
@@ -1004,7 +1003,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 115 "dtc-lexer.l"
+#line 116 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /memreserve/\n");
                        BEGIN_DEFAULT();
@@ -1013,7 +1012,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 121 "dtc-lexer.l"
+#line 122 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /bits/\n");
                        BEGIN_DEFAULT();
@@ -1022,7 +1021,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 127 "dtc-lexer.l"
+#line 128 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /delete-property/\n");
                        DPRINT("<PROPNODENAME>\n");
@@ -1032,7 +1031,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 134 "dtc-lexer.l"
+#line 135 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /delete-node/\n");
                        DPRINT("<PROPNODENAME>\n");
@@ -1042,7 +1041,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 141 "dtc-lexer.l"
+#line 142 "dtc-lexer.l"
 {
                        DPRINT("Label: %s\n", yytext);
                        yylval.labelref = xstrdup(yytext);
@@ -1052,27 +1051,54 @@ YY_RULE_SETUP
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 148 "dtc-lexer.l"
+#line 149 "dtc-lexer.l"
 {
-                       yylval.literal = xstrdup(yytext);
-                       DPRINT("Literal: '%s'\n", yylval.literal);
+                       char *e;
+                       DPRINT("Integer Literal: '%s'\n", yytext);
+
+                       errno = 0;
+                       yylval.integer = strtoull(yytext, &e, 0);
+
+                       assert(!(*e) || !e[strspn(e, "UL")]);
+
+                       if (errno == ERANGE)
+                               lexical_error("Integer literal '%s' out of range",
+                                             yytext);
+                       else
+                               /* ERANGE is the only strtoull error triggerable
+                                *  by strings matching the pattern */
+                               assert(errno == 0);
                        return DT_LITERAL;
                }
        YY_BREAK
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-#line 154 "dtc-lexer.l"
+#line 168 "dtc-lexer.l"
 {
-                       yytext[yyleng-1] = '\0';
-                       yylval.literal = xstrdup(yytext+1);
-                       DPRINT("Character literal: %s\n", yylval.literal);
+                       struct data d;
+                       DPRINT("Character literal: %s\n", yytext);
+
+                       d = data_copy_escape_string(yytext+1, yyleng-2);
+                       if (d.len == 1) {
+                               lexical_error("Empty character literal");
+                               yylval.integer = 0;
+                               return DT_CHAR_LITERAL;
+                       }
+
+                       yylval.integer = (unsigned char)d.val[0];
+
+                       if (d.len > 2)
+                               lexical_error("Character literal has %d"
+                                             " characters instead of 1",
+                                             d.len - 1);
+
                        return DT_CHAR_LITERAL;
                }
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 161 "dtc-lexer.l"
+#line 189 "dtc-lexer.l"
 {      /* label reference */
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = xstrdup(yytext+1);
@@ -1081,7 +1107,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 167 "dtc-lexer.l"
+#line 195 "dtc-lexer.l"
 {      /* new-style path reference */
                        yytext[yyleng-1] = '\0';
                        DPRINT("Ref: %s\n", yytext+2);
@@ -1091,7 +1117,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 174 "dtc-lexer.l"
+#line 202 "dtc-lexer.l"
 {
                        yylval.byte = strtol(yytext, NULL, 16);
                        DPRINT("Byte: %02x\n", (int)yylval.byte);
@@ -1100,7 +1126,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 180 "dtc-lexer.l"
+#line 208 "dtc-lexer.l"
 {
                        DPRINT("/BYTESTRING\n");
                        BEGIN_DEFAULT();
@@ -1109,7 +1135,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 186 "dtc-lexer.l"
+#line 214 "dtc-lexer.l"
 {
                        DPRINT("PropNodeName: %s\n", yytext);
                        yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@@ -1120,7 +1146,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 194 "dtc-lexer.l"
+#line 222 "dtc-lexer.l"
 {
                        DPRINT("Binary Include\n");
                        return DT_INCBIN;
@@ -1129,64 +1155,64 @@ YY_RULE_SETUP
 case 18:
 /* rule 18 can match eol */
 YY_RULE_SETUP
-#line 199 "dtc-lexer.l"
+#line 227 "dtc-lexer.l"
 /* eat whitespace */
        YY_BREAK
 case 19:
 /* rule 19 can match eol */
 YY_RULE_SETUP
-#line 200 "dtc-lexer.l"
+#line 228 "dtc-lexer.l"
 /* eat C-style comments */
        YY_BREAK
 case 20:
 /* rule 20 can match eol */
 YY_RULE_SETUP
-#line 201 "dtc-lexer.l"
+#line 229 "dtc-lexer.l"
 /* eat C++-style comments */
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 203 "dtc-lexer.l"
+#line 231 "dtc-lexer.l"
 { return DT_LSHIFT; };
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 204 "dtc-lexer.l"
+#line 232 "dtc-lexer.l"
 { return DT_RSHIFT; };
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 205 "dtc-lexer.l"
+#line 233 "dtc-lexer.l"
 { return DT_LE; };
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 206 "dtc-lexer.l"
+#line 234 "dtc-lexer.l"
 { return DT_GE; };
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 207 "dtc-lexer.l"
+#line 235 "dtc-lexer.l"
 { return DT_EQ; };
        YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 208 "dtc-lexer.l"
+#line 236 "dtc-lexer.l"
 { return DT_NE; };
        YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 209 "dtc-lexer.l"
+#line 237 "dtc-lexer.l"
 { return DT_AND; };
        YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 210 "dtc-lexer.l"
+#line 238 "dtc-lexer.l"
 { return DT_OR; };
        YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 212 "dtc-lexer.l"
+#line 240 "dtc-lexer.l"
 {
                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
                                (unsigned)yytext[0]);
@@ -1204,10 +1230,10 @@ YY_RULE_SETUP
        YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 227 "dtc-lexer.l"
+#line 255 "dtc-lexer.l"
 ECHO;
        YY_BREAK
-#line 1211 "dtc-lexer.lex.c"
+#line 1237 "dtc-lexer.lex.c"
 
        case YY_END_OF_BUFFER:
                {
@@ -1499,7 +1525,7 @@ static int yy_get_next_buffer (void)
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 161 )
+                       if ( yy_current_state >= 159 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1527,11 +1553,11 @@ static int yy_get_next_buffer (void)
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 161 )
+               if ( yy_current_state >= 159 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 160);
+       yy_is_jam = (yy_current_state == 158);
 
        return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2166,7 +2192,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 227 "dtc-lexer.l"
+#line 255 "dtc-lexer.l"
 
 
 
@@ -2182,14 +2208,25 @@ static void push_input_file(const char *filename)
 }
 
 
-static int pop_input_file(void)
+static bool pop_input_file(void)
 {
        if (srcfile_pop() == 0)
-               return 0;
+               return false;
 
        yypop_buffer_state();
        yyin = current_srcfile->f;
 
-       return 1;
+       return true;
+}
+
+static void lexical_error(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       srcpos_verror(&yylloc, "Lexical error", fmt, ap);
+       va_end(ap);
+
+       treesource_error = true;
 }
 
index ee1d8c3042fbb841447f369676e4b45b34fd6ab8..7d24359ee411a3e41a69102fa2a421f2e5118553 100644 (file)
 #define YYPULL 1
 
 /* Using locations.  */
-#define YYLSP_NEEDED 0
+#define YYLSP_NEEDED 1
 
 
 
 /* Copy the first part of user declarations.  */
 
 /* Line 268 of yacc.c  */
-#line 21 "dtc-parser.y"
+#line 20 "dtc-parser.y"
 
 #include <stdio.h>
 
 #include "dtc.h"
 #include "srcpos.h"
 
-YYLTYPE yylloc;
-
 extern int yylex(void);
-extern void print_error(char const *fmt, ...);
 extern void yyerror(char const *s);
+#define ERROR(loc, ...) \
+       do { \
+               srcpos_error((loc), "Error", __VA_ARGS__); \
+               treesource_error = true; \
+       } while (0)
 
 extern struct boot_info *the_boot_info;
-extern int treesource_error;
-
-static unsigned long long eval_literal(const char *s, int base, int bits);
-static unsigned char eval_char_literal(const char *s);
+extern bool treesource_error;
 
 
 /* Line 268 of yacc.c  */
-#line 91 "dtc-parser.tab.c"
+#line 90 "dtc-parser.tab.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -130,12 +129,11 @@ static unsigned char eval_char_literal(const char *s);
      DT_PROPNODENAME = 271,
      DT_LITERAL = 272,
      DT_CHAR_LITERAL = 273,
-     DT_BASE = 274,
-     DT_BYTE = 275,
-     DT_STRING = 276,
-     DT_LABEL = 277,
-     DT_REF = 278,
-     DT_INCBIN = 279
+     DT_BYTE = 274,
+     DT_STRING = 275,
+     DT_LABEL = 276,
+     DT_REF = 277,
+     DT_INCBIN = 278
    };
 #endif
 
@@ -146,12 +144,10 @@ typedef union YYSTYPE
 {
 
 /* Line 293 of yacc.c  */
-#line 40 "dtc-parser.y"
+#line 38 "dtc-parser.y"
 
        char *propnodename;
-       char *literal;
        char *labelref;
-       unsigned int cbase;
        uint8_t byte;
        struct data data;
 
@@ -170,19 +166,32 @@ typedef union YYSTYPE
 
 
 /* Line 293 of yacc.c  */
-#line 174 "dtc-parser.tab.c"
+#line 170 "dtc-parser.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
 
 /* Copy the second part of user declarations.  */
 
 
 /* Line 343 of yacc.c  */
-#line 186 "dtc-parser.tab.c"
+#line 195 "dtc-parser.tab.c"
 
 #ifdef short
 # undef short
@@ -340,13 +349,15 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 
 #if (! defined yyoverflow \
      && (! defined __cplusplus \
-        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+        || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+            && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
   yytype_int16 yyss_alloc;
   YYSTYPE yyvs_alloc;
+  YYLTYPE yyls_alloc;
 };
 
 /* The size of the maximum gap between one aligned stack and the next.  */
@@ -355,8 +366,8 @@ union yyalloc
 /* The size of an array large to enough to hold all stacks, each with
    N elements.  */
 # define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+      + 2 * YYSTACK_GAP_MAXIMUM)
 
 # define YYCOPY_NEEDED 1
 
@@ -401,20 +412,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  4
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   133
+#define YYLAST   136
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  48
+#define YYNTOKENS  47
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  28
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  79
+#define YYNRULES  80
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  141
+#define YYNSTATES  144
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   279
+#define YYMAXUTOK   278
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -425,16 +436,16 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    47,     2,     2,     2,    45,    41,     2,
-      33,    35,    44,    42,    34,    43,     2,    26,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    38,    25,
-      36,    29,    30,    37,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    46,     2,     2,     2,    44,    40,     2,
+      32,    34,    43,    41,    33,    42,     2,    25,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    37,    24,
+      35,    28,    29,    36,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    31,     2,    32,    40,     2,     2,     2,     2,     2,
+       2,    30,     2,    31,    39,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    27,    39,    28,    46,     2,     2,     2,
+       2,     2,     2,    26,    38,    27,    45,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -449,7 +460,7 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24
+      15,    16,    17,    18,    19,    20,    21,    22,    23
 };
 
 #if YYDEBUG
@@ -458,58 +469,60 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint16 yyprhs[] =
 {
        0,     0,     3,     8,     9,    12,    17,    20,    23,    27,
-      31,    36,    42,    43,    46,    51,    54,    58,    61,    64,
-      68,    73,    76,    86,    92,    95,    96,    99,   102,   106,
-     108,   111,   114,   117,   119,   121,   125,   127,   129,   135,
-     137,   141,   143,   147,   149,   153,   155,   159,   161,   165,
-     167,   171,   175,   177,   181,   185,   189,   193,   197,   201,
-     203,   207,   211,   213,   217,   221,   225,   227,   229,   232,
-     235,   238,   239,   242,   245,   246,   249,   252,   255,   259
+      32,    36,    41,    47,    48,    51,    56,    59,    63,    66,
+      69,    73,    78,    81,    91,    97,   100,   101,   104,   107,
+     111,   113,   116,   119,   122,   124,   126,   130,   132,   134,
+     140,   142,   146,   148,   152,   154,   158,   160,   164,   166,
+     170,   172,   176,   180,   182,   186,   190,   194,   198,   202,
+     206,   208,   212,   216,   218,   222,   226,   230,   232,   234,
+     237,   240,   243,   244,   247,   250,   251,   254,   257,   260,
+     264
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      49,     0,    -1,     3,    25,    50,    52,    -1,    -1,    51,
-      50,    -1,     4,    59,    59,    25,    -1,    22,    51,    -1,
-      26,    53,    -1,    52,    26,    53,    -1,    52,    23,    53,
-      -1,    52,    15,    23,    25,    -1,    27,    54,    74,    28,
-      25,    -1,    -1,    54,    55,    -1,    16,    29,    56,    25,
-      -1,    16,    25,    -1,    14,    16,    25,    -1,    22,    55,
-      -1,    57,    21,    -1,    57,    58,    30,    -1,    57,    31,
-      73,    32,    -1,    57,    23,    -1,    57,    24,    33,    21,
-      34,    59,    34,    59,    35,    -1,    57,    24,    33,    21,
-      35,    -1,    56,    22,    -1,    -1,    56,    34,    -1,    57,
-      22,    -1,    13,    17,    36,    -1,    36,    -1,    58,    59,
-      -1,    58,    23,    -1,    58,    22,    -1,    17,    -1,    18,
-      -1,    33,    60,    35,    -1,    61,    -1,    62,    -1,    62,
-      37,    60,    38,    61,    -1,    63,    -1,    62,    12,    63,
-      -1,    64,    -1,    63,    11,    64,    -1,    65,    -1,    64,
-      39,    65,    -1,    66,    -1,    65,    40,    66,    -1,    67,
-      -1,    66,    41,    67,    -1,    68,    -1,    67,     9,    68,
-      -1,    67,    10,    68,    -1,    69,    -1,    68,    36,    69,
-      -1,    68,    30,    69,    -1,    68,     7,    69,    -1,    68,
-       8,    69,    -1,    69,     5,    70,    -1,    69,     6,    70,
-      -1,    70,    -1,    70,    42,    71,    -1,    70,    43,    71,
-      -1,    71,    -1,    71,    44,    72,    -1,    71,    26,    72,
-      -1,    71,    45,    72,    -1,    72,    -1,    59,    -1,    43,
-      72,    -1,    46,    72,    -1,    47,    72,    -1,    -1,    73,
-      20,    -1,    73,    22,    -1,    -1,    75,    74,    -1,    75,
-      55,    -1,    16,    53,    -1,    15,    16,    25,    -1,    22,
-      75,    -1
+      48,     0,    -1,     3,    24,    49,    51,    -1,    -1,    50,
+      49,    -1,     4,    58,    58,    24,    -1,    21,    50,    -1,
+      25,    52,    -1,    51,    25,    52,    -1,    51,    21,    22,
+      52,    -1,    51,    22,    52,    -1,    51,    15,    22,    24,
+      -1,    26,    53,    73,    27,    24,    -1,    -1,    53,    54,
+      -1,    16,    28,    55,    24,    -1,    16,    24,    -1,    14,
+      16,    24,    -1,    21,    54,    -1,    56,    20,    -1,    56,
+      57,    29,    -1,    56,    30,    72,    31,    -1,    56,    22,
+      -1,    56,    23,    32,    20,    33,    58,    33,    58,    34,
+      -1,    56,    23,    32,    20,    34,    -1,    55,    21,    -1,
+      -1,    55,    33,    -1,    56,    21,    -1,    13,    17,    35,
+      -1,    35,    -1,    57,    58,    -1,    57,    22,    -1,    57,
+      21,    -1,    17,    -1,    18,    -1,    32,    59,    34,    -1,
+      60,    -1,    61,    -1,    61,    36,    59,    37,    60,    -1,
+      62,    -1,    61,    12,    62,    -1,    63,    -1,    62,    11,
+      63,    -1,    64,    -1,    63,    38,    64,    -1,    65,    -1,
+      64,    39,    65,    -1,    66,    -1,    65,    40,    66,    -1,
+      67,    -1,    66,     9,    67,    -1,    66,    10,    67,    -1,
+      68,    -1,    67,    35,    68,    -1,    67,    29,    68,    -1,
+      67,     7,    68,    -1,    67,     8,    68,    -1,    68,     5,
+      69,    -1,    68,     6,    69,    -1,    69,    -1,    69,    41,
+      70,    -1,    69,    42,    70,    -1,    70,    -1,    70,    43,
+      71,    -1,    70,    25,    71,    -1,    70,    44,    71,    -1,
+      71,    -1,    58,    -1,    42,    71,    -1,    45,    71,    -1,
+      46,    71,    -1,    -1,    72,    19,    -1,    72,    21,    -1,
+      -1,    74,    73,    -1,    74,    54,    -1,    16,    52,    -1,
+      15,    16,    24,    -1,    21,    74,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   109,   109,   118,   121,   128,   132,   140,   144,   148,
-     158,   172,   180,   183,   190,   194,   198,   202,   210,   214,
-     218,   222,   226,   243,   253,   261,   264,   268,   275,   290,
-     295,   315,   329,   336,   340,   344,   351,   355,   356,   360,
-     361,   365,   366,   370,   371,   375,   376,   380,   381,   385,
-     386,   387,   391,   392,   393,   394,   395,   399,   400,   401,
-     405,   406,   407,   411,   412,   413,   414,   418,   419,   420,
-     421,   426,   429,   433,   441,   444,   448,   456,   460,   464
+       0,   104,   104,   113,   116,   123,   127,   135,   139,   144,
+     155,   165,   180,   188,   191,   198,   202,   206,   210,   218,
+     222,   226,   230,   234,   250,   260,   268,   271,   275,   282,
+     298,   303,   322,   336,   343,   344,   345,   352,   356,   357,
+     361,   362,   366,   367,   371,   372,   376,   377,   381,   382,
+     386,   387,   388,   392,   393,   394,   395,   396,   400,   401,
+     402,   406,   407,   408,   412,   413,   414,   415,   419,   420,
+     421,   422,   427,   430,   434,   442,   445,   449,   457,   461,
+     465
 };
 #endif
 
@@ -521,10 +534,10 @@ static const char *const yytname[] =
   "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
   "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
   "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
-  "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", "DT_LABEL",
-  "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
-  "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
-  "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
+  "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF",
+  "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", "']'",
+  "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", "'+'",
+  "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
   "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
   "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
   "integer_expr", "integer_trinary", "integer_or", "integer_and",
@@ -541,36 +554,38 @@ static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,    59,    47,   123,   125,    61,
-      62,    91,    93,    40,    44,    41,    60,    63,    58,   124,
-      94,    38,    43,    45,    42,    37,   126,    33
+     275,   276,   277,   278,    59,    47,   123,   125,    61,    62,
+      91,    93,    40,    44,    41,    60,    63,    58,   124,    94,
+      38,    43,    45,    42,    37,   126,    33
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    48,    49,    50,    50,    51,    51,    52,    52,    52,
-      52,    53,    54,    54,    55,    55,    55,    55,    56,    56,
-      56,    56,    56,    56,    56,    57,    57,    57,    58,    58,
-      58,    58,    58,    59,    59,    59,    60,    61,    61,    62,
-      62,    63,    63,    64,    64,    65,    65,    66,    66,    67,
-      67,    67,    68,    68,    68,    68,    68,    69,    69,    69,
-      70,    70,    70,    71,    71,    71,    71,    72,    72,    72,
-      72,    73,    73,    73,    74,    74,    74,    75,    75,    75
+       0,    47,    48,    49,    49,    50,    50,    51,    51,    51,
+      51,    51,    52,    53,    53,    54,    54,    54,    54,    55,
+      55,    55,    55,    55,    55,    55,    56,    56,    56,    57,
+      57,    57,    57,    57,    58,    58,    58,    59,    60,    60,
+      61,    61,    62,    62,    63,    63,    64,    64,    65,    65,
+      66,    66,    66,    67,    67,    67,    67,    67,    68,    68,
+      68,    69,    69,    69,    70,    70,    70,    70,    71,    71,
+      71,    71,    72,    72,    72,    73,    73,    73,    74,    74,
+      74
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     4,     0,     2,     4,     2,     2,     3,     3,
-       4,     5,     0,     2,     4,     2,     3,     2,     2,     3,
-       4,     2,     9,     5,     2,     0,     2,     2,     3,     1,
-       2,     2,     2,     1,     1,     3,     1,     1,     5,     1,
-       3,     1,     3,     1,     3,     1,     3,     1,     3,     1,
-       3,     3,     1,     3,     3,     3,     3,     3,     3,     1,
-       3,     3,     1,     3,     3,     3,     1,     1,     2,     2,
-       2,     0,     2,     2,     0,     2,     2,     2,     3,     2
+       0,     2,     4,     0,     2,     4,     2,     2,     3,     4,
+       3,     4,     5,     0,     2,     4,     2,     3,     2,     2,
+       3,     4,     2,     9,     5,     2,     0,     2,     2,     3,
+       1,     2,     2,     2,     1,     1,     3,     1,     1,     5,
+       1,     3,     1,     3,     1,     3,     1,     3,     1,     3,
+       1,     3,     3,     1,     3,     3,     3,     3,     3,     3,
+       1,     3,     3,     1,     3,     3,     3,     1,     1,     2,
+       2,     2,     0,     2,     2,     0,     2,     2,     2,     3,
+       2
 };
 
 /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@@ -578,59 +593,59 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     0,     0,     3,     1,     0,     0,     0,     3,    33,
-      34,     0,     0,     6,     0,     2,     4,     0,     0,     0,
-      67,     0,    36,    37,    39,    41,    43,    45,    47,    49,
-      52,    59,    62,    66,     0,    12,     7,     0,     0,     0,
-      68,    69,    70,    35,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     3,     1,     0,     0,     0,     3,    34,
+      35,     0,     0,     6,     0,     2,     4,     0,     0,     0,
+      68,     0,    37,    38,    40,    42,    44,    46,    48,    50,
+      53,    60,    63,    67,     0,    13,     7,     0,     0,     0,
+       0,    69,    70,    71,    36,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     5,    74,     0,     9,     8,    40,     0,
-      42,    44,    46,    48,    50,    51,    55,    56,    54,    53,
-      57,    58,    60,    61,    64,    63,    65,     0,     0,     0,
-       0,    13,     0,    74,    10,     0,     0,     0,    15,    25,
-      77,    17,    79,     0,    76,    75,    38,    16,    78,     0,
-       0,    11,    24,    14,    26,     0,    18,    27,    21,     0,
-      71,    29,     0,     0,     0,     0,    32,    31,    19,    30,
-      28,     0,    72,    73,    20,     0,    23,     0,     0,     0,
-      22
+       0,     0,     0,     0,     5,    75,     0,     0,    10,     8,
+      41,     0,    43,    45,    47,    49,    51,    52,    56,    57,
+      55,    54,    58,    59,    61,    62,    65,    64,    66,     0,
+       0,     0,     0,    14,     0,    75,    11,     9,     0,     0,
+       0,    16,    26,    78,    18,    80,     0,    77,    76,    39,
+      17,    79,     0,     0,    12,    25,    15,    27,     0,    19,
+      28,    22,     0,    72,    30,     0,     0,     0,     0,    33,
+      32,    20,    31,    29,     0,    73,    74,    21,     0,    24,
+       0,     0,     0,    23
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
+static const yytype_int16 yydefgoto[] =
 {
-      -1,     2,     7,     8,    15,    36,    64,    91,   109,   110,
-     122,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    33,   125,    92,    93
+      -1,     2,     7,     8,    15,    36,    65,    93,   112,   113,
+     125,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,   128,    94,    95
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -78
+#define YYPACT_NINF -81
 static const yytype_int8 yypact[] =
 {
-      22,    11,    51,    10,   -78,    23,    10,     2,    10,   -78,
-     -78,    -9,    23,   -78,    30,    38,   -78,    -9,    -9,    -9,
-     -78,    35,   -78,    -6,    52,    29,    48,    49,    33,     3,
-      71,    36,     0,   -78,    64,   -78,   -78,    68,    30,    30,
-     -78,   -78,   -78,   -78,    -9,    -9,    -9,    -9,    -9,    -9,
+      16,   -11,    21,    10,   -81,    25,    10,    19,    10,   -81,
+     -81,    -9,    25,   -81,     2,    51,   -81,    -9,    -9,    -9,
+     -81,     1,   -81,    -6,    50,    14,    28,    29,    36,     3,
+      58,    44,    -3,   -81,    47,   -81,   -81,    65,    68,     2,
+       2,   -81,   -81,   -81,   -81,    -9,    -9,    -9,    -9,    -9,
       -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,
-      -9,    -9,    -9,   -78,    44,    67,   -78,   -78,    52,    55,
-      29,    48,    49,    33,     3,     3,    71,    71,    71,    71,
-      36,    36,     0,     0,   -78,   -78,   -78,    78,    79,    42,
-      44,   -78,    69,    44,   -78,    -9,    73,    74,   -78,   -78,
-     -78,   -78,   -78,    75,   -78,   -78,   -78,   -78,   -78,    -7,
-      -1,   -78,   -78,   -78,   -78,    84,   -78,   -78,   -78,    63,
-     -78,   -78,    32,    66,    82,    -3,   -78,   -78,   -78,   -78,
-     -78,    46,   -78,   -78,   -78,    23,   -78,    70,    23,    72,
-     -78
+      -9,    -9,    -9,    -9,   -81,    63,    69,     2,   -81,   -81,
+      50,    57,    14,    28,    29,    36,     3,     3,    58,    58,
+      58,    58,    44,    44,    -3,    -3,   -81,   -81,   -81,    79,
+      80,    -8,    63,   -81,    72,    63,   -81,   -81,    -9,    76,
+      77,   -81,   -81,   -81,   -81,   -81,    78,   -81,   -81,   -81,
+     -81,   -81,    35,     4,   -81,   -81,   -81,   -81,    86,   -81,
+     -81,   -81,    73,   -81,   -81,    33,    71,    84,    39,   -81,
+     -81,   -81,   -81,   -81,    41,   -81,   -81,   -81,    25,   -81,
+      74,    25,    75,   -81
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -78,   -78,    97,   100,   -78,   -37,   -78,   -77,   -78,   -78,
-     -78,    -5,    65,    13,   -78,    76,    77,    62,    80,    83,
-      34,    20,    26,    28,   -14,   -78,    18,    24
+     -81,   -81,   100,   104,   -81,   -38,   -81,   -80,   -81,   -81,
+     -81,    -5,    66,    13,   -81,    70,    67,    81,    64,    82,
+      37,    27,    34,    38,   -14,   -81,    22,    24
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -639,65 +654,65 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      12,    66,    67,    40,    41,    42,    44,    34,     9,    10,
-      52,    53,   115,   101,     5,   112,   104,   132,   113,   133,
-     116,   117,   118,   119,    11,     1,    60,   114,    14,   134,
-     120,    45,     6,    54,    17,   121,     3,    18,    19,    55,
-       9,    10,    50,    51,    61,    62,    84,    85,    86,     9,
-      10,     4,   100,    37,   126,   127,    11,    35,    87,    88,
-      89,    38,   128,    46,    39,    11,    90,    98,    47,    35,
-      43,    99,    76,    77,    78,    79,    56,    57,    58,    59,
-     135,   136,    80,    81,    74,    75,    82,    83,    48,    63,
-      49,    65,    94,    95,    96,    97,   124,   103,   107,   108,
-     111,   123,   130,   131,   138,    16,    13,   140,   106,    71,
-      69,   105,     0,     0,   102,     0,     0,   129,     0,     0,
-      68,     0,     0,    70,     0,     0,     0,     0,    72,     0,
-     137,     0,    73,   139
+      12,    68,    69,    41,    42,    43,    45,    34,     9,    10,
+      53,    54,   104,     3,     5,   107,   101,   118,    35,     1,
+     102,     4,    61,    11,   119,   120,   121,   122,    35,    97,
+      46,     6,    55,    17,   123,    44,    18,    19,    56,   124,
+      62,    63,     9,    10,    14,    51,    52,    86,    87,    88,
+       9,    10,    48,   103,   129,   130,   115,    11,   135,   116,
+     136,    47,   131,    57,    58,    11,    37,    49,   117,    50,
+     137,    64,    38,    39,   138,   139,    40,    89,    90,    91,
+      78,    79,    80,    81,    92,    59,    60,    66,    76,    77,
+      67,    82,    83,    96,    98,    99,   100,    84,    85,   106,
+     110,   111,   114,   126,   134,   127,   133,   141,    16,   143,
+      13,   109,    71,    74,    72,    70,   105,   108,     0,     0,
+     132,     0,     0,     0,     0,     0,     0,     0,     0,    73,
+       0,     0,    75,   140,     0,     0,   142
 };
 
 #define yypact_value_is_default(yystate) \
-  ((yystate) == (-78))
+  ((yystate) == (-81))
 
 #define yytable_value_is_error(yytable_value) \
   YYID (0)
 
 static const yytype_int16 yycheck[] =
 {
-       5,    38,    39,    17,    18,    19,    12,    12,    17,    18,
-       7,     8,    13,    90,     4,    22,    93,    20,    25,    22,
-      21,    22,    23,    24,    33,     3,    26,    34,    26,    32,
-      31,    37,    22,    30,    43,    36,    25,    46,    47,    36,
-      17,    18,     9,    10,    44,    45,    60,    61,    62,    17,
-      18,     0,    89,    15,    22,    23,    33,    27,    14,    15,
-      16,    23,    30,    11,    26,    33,    22,    25,    39,    27,
-      35,    29,    52,    53,    54,    55,     5,     6,    42,    43,
-      34,    35,    56,    57,    50,    51,    58,    59,    40,    25,
-      41,    23,    25,    38,    16,    16,    33,    28,    25,    25,
-      25,    17,    36,    21,    34,     8,     6,    35,    95,    47,
-      45,    93,    -1,    -1,    90,    -1,    -1,   122,    -1,    -1,
-      44,    -1,    -1,    46,    -1,    -1,    -1,    -1,    48,    -1,
-     135,    -1,    49,   138
+       5,    39,    40,    17,    18,    19,    12,    12,    17,    18,
+       7,     8,    92,    24,     4,    95,    24,    13,    26,     3,
+      28,     0,    25,    32,    20,    21,    22,    23,    26,    67,
+      36,    21,    29,    42,    30,    34,    45,    46,    35,    35,
+      43,    44,    17,    18,    25,     9,    10,    61,    62,    63,
+      17,    18,    38,    91,    21,    22,    21,    32,    19,    24,
+      21,    11,    29,     5,     6,    32,    15,    39,    33,    40,
+      31,    24,    21,    22,    33,    34,    25,    14,    15,    16,
+      53,    54,    55,    56,    21,    41,    42,    22,    51,    52,
+      22,    57,    58,    24,    37,    16,    16,    59,    60,    27,
+      24,    24,    24,    17,    20,    32,    35,    33,     8,    34,
+       6,    98,    46,    49,    47,    45,    92,    95,    -1,    -1,
+     125,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    48,
+      -1,    -1,    50,   138,    -1,    -1,   141
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    49,    25,     0,     4,    22,    50,    51,    17,
-      18,    33,    59,    51,    26,    52,    50,    43,    46,    47,
-      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
-      69,    70,    71,    72,    59,    27,    53,    15,    23,    26,
-      72,    72,    72,    35,    12,    37,    11,    39,    40,    41,
-       9,    10,     7,     8,    30,    36,     5,     6,    42,    43,
-      26,    44,    45,    25,    54,    23,    53,    53,    63,    60,
-      64,    65,    66,    67,    68,    68,    69,    69,    69,    69,
-      70,    70,    71,    71,    72,    72,    72,    14,    15,    16,
-      22,    55,    74,    75,    25,    38,    16,    16,    25,    29,
-      53,    55,    75,    28,    55,    74,    61,    25,    25,    56,
-      57,    25,    22,    25,    34,    13,    21,    22,    23,    24,
-      31,    36,    58,    17,    33,    73,    22,    23,    30,    59,
-      36,    21,    20,    22,    32,    34,    35,    59,    34,    59,
-      35
+       0,     3,    48,    24,     0,     4,    21,    49,    50,    17,
+      18,    32,    58,    50,    25,    51,    49,    42,    45,    46,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    58,    26,    52,    15,    21,    22,
+      25,    71,    71,    71,    34,    12,    36,    11,    38,    39,
+      40,     9,    10,     7,     8,    29,    35,     5,     6,    41,
+      42,    25,    43,    44,    24,    53,    22,    22,    52,    52,
+      62,    59,    63,    64,    65,    66,    67,    67,    68,    68,
+      68,    68,    69,    69,    70,    70,    71,    71,    71,    14,
+      15,    16,    21,    54,    73,    74,    24,    52,    37,    16,
+      16,    24,    28,    52,    54,    74,    27,    54,    73,    60,
+      24,    24,    55,    56,    24,    21,    24,    33,    13,    20,
+      21,    22,    23,    30,    35,    57,    17,    32,    72,    21,
+      22,    29,    58,    35,    20,    19,    21,    31,    33,    34,
+      58,    33,    58,    34
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -774,10 +789,19 @@ while (YYID (0))
 #endif
 
 
-/* This macro is provided for backward compatibility. */
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)                 \
+     fprintf (File, "%d.%d-%d.%d",                     \
+             (Loc).first_line, (Loc).first_column,     \
+             (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
 #endif
 
 
@@ -809,7 +833,7 @@ do {                                                                          \
     {                                                                    \
       YYFPRINTF (stderr, "%s ", Title);                                          \
       yy_symbol_print (stderr,                                           \
-                 Type, Value); \
+                 Type, Value, Location); \
       YYFPRINTF (stderr, "\n");                                                  \
     }                                                                    \
 } while (YYID (0))
@@ -823,17 +847,19 @@ do {                                                                        \
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
 #else
 static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
     FILE *yyoutput;
     int yytype;
     YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
 #endif
 {
   if (!yyvaluep)
     return;
+  YYUSE (yylocationp);
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
@@ -855,13 +881,14 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
 #else
 static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
     FILE *yyoutput;
     int yytype;
     YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
 #endif
 {
   if (yytype < YYNTOKENS)
@@ -869,7 +896,9 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
   else
     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YY_LOCATION_PRINT (yyoutput, *yylocationp);
+  YYFPRINTF (yyoutput, ": ");
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp);
   YYFPRINTF (yyoutput, ")");
 }
 
@@ -912,11 +941,12 @@ do {                                                              \
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
 #else
 static void
-yy_reduce_print (yyvsp, yyrule)
+yy_reduce_print (yyvsp, yylsp, yyrule)
     YYSTYPE *yyvsp;
+    YYLTYPE *yylsp;
     int yyrule;
 #endif
 {
@@ -931,7 +961,7 @@ yy_reduce_print (yyvsp, yyrule)
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
                       &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      );
+                      , &(yylsp[(yyi + 1) - (yynrhs)])                );
       YYFPRINTF (stderr, "\n");
     }
 }
@@ -939,7 +969,7 @@ yy_reduce_print (yyvsp, yyrule)
 # define YY_REDUCE_PRINT(Rule)         \
 do {                                   \
   if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule); \
+    yy_reduce_print (yyvsp, yylsp, Rule); \
 } while (YYID (0))
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
@@ -1216,16 +1246,18 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)
 #else
 static void
-yydestruct (yymsg, yytype, yyvaluep)
+yydestruct (yymsg, yytype, yyvaluep, yylocationp)
     const char *yymsg;
     int yytype;
     YYSTYPE *yyvaluep;
+    YYLTYPE *yylocationp;
 #endif
 {
   YYUSE (yyvaluep);
+  YYUSE (yylocationp);
 
   if (!yymsg)
     yymsg = "Deleting";
@@ -1262,6 +1294,9 @@ int yychar;
 /* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
 
+/* Location data for the lookahead symbol.  */
+YYLTYPE yylloc;
+
 /* Number of syntax errors so far.  */
 int yynerrs;
 
@@ -1299,6 +1334,7 @@ yyparse ()
     /* The stacks and their tools:
        `yyss': related to states.
        `yyvs': related to semantic values.
+       `yyls': related to locations.
 
        Refer to the stacks thru separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
@@ -1313,6 +1349,14 @@ yyparse ()
     YYSTYPE *yyvs;
     YYSTYPE *yyvsp;
 
+    /* The location stack.  */
+    YYLTYPE yylsa[YYINITDEPTH];
+    YYLTYPE *yyls;
+    YYLTYPE *yylsp;
+
+    /* The locations where the error started and ended.  */
+    YYLTYPE yyerror_range[3];
+
     YYSIZE_T yystacksize;
 
   int yyn;
@@ -1322,6 +1366,7 @@ yyparse ()
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
+  YYLTYPE yyloc;
 
 #if YYERROR_VERBOSE
   /* Buffer for error messages, and its allocated size.  */
@@ -1330,7 +1375,7 @@ yyparse ()
   YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
 #endif
 
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
 
   /* The number of symbols on the RHS of the reduced rule.
      Keep to zero when no symbol should be popped.  */
@@ -1339,6 +1384,7 @@ yyparse ()
   yytoken = 0;
   yyss = yyssa;
   yyvs = yyvsa;
+  yyls = yylsa;
   yystacksize = YYINITDEPTH;
 
   YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1354,6 +1400,13 @@ yyparse ()
      The wasted elements are never initialized.  */
   yyssp = yyss;
   yyvsp = yyvs;
+  yylsp = yyls;
+
+#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+  /* Initialize the default location before parsing starts.  */
+  yylloc.first_line   = yylloc.last_line   = 1;
+  yylloc.first_column = yylloc.last_column = 1;
+#endif
 
   goto yysetstate;
 
@@ -1380,6 +1433,7 @@ yyparse ()
           memory.  */
        YYSTYPE *yyvs1 = yyvs;
        yytype_int16 *yyss1 = yyss;
+       YYLTYPE *yyls1 = yyls;
 
        /* Each stack pointer address is followed by the size of the
           data in use in that stack, in bytes.  This used to be a
@@ -1388,8 +1442,10 @@ yyparse ()
        yyoverflow (YY_("memory exhausted"),
                    &yyss1, yysize * sizeof (*yyssp),
                    &yyvs1, yysize * sizeof (*yyvsp),
+                   &yyls1, yysize * sizeof (*yylsp),
                    &yystacksize);
 
+       yyls = yyls1;
        yyss = yyss1;
        yyvs = yyvs1;
       }
@@ -1412,6 +1468,7 @@ yyparse ()
          goto yyexhaustedlab;
        YYSTACK_RELOCATE (yyss_alloc, yyss);
        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+       YYSTACK_RELOCATE (yyls_alloc, yyls);
 #  undef YYSTACK_RELOCATE
        if (yyss1 != yyssa)
          YYSTACK_FREE (yyss1);
@@ -1421,6 +1478,7 @@ yyparse ()
 
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
+      yylsp = yyls + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                  (unsigned long int) yystacksize));
@@ -1496,7 +1554,7 @@ yybackup:
 
   yystate = yyn;
   *++yyvsp = yylval;
-
+  *++yylsp = yylloc;
   goto yynewstate;
 
 
@@ -1527,14 +1585,15 @@ yyreduce:
      GCC warning that YYVAL may be used uninitialized.  */
   yyval = yyvsp[1-yylen];
 
-
+  /* Default location.  */
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
   YY_REDUCE_PRINT (yyn);
   switch (yyn)
     {
         case 2:
 
 /* Line 1806 of yacc.c  */
-#line 110 "dtc-parser.y"
+#line 105 "dtc-parser.y"
     {
                        the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node),
                                                        guess_boot_cpuid((yyvsp[(4) - (4)].node)));
@@ -1544,7 +1603,7 @@ yyreduce:
   case 3:
 
 /* Line 1806 of yacc.c  */
-#line 118 "dtc-parser.y"
+#line 113 "dtc-parser.y"
     {
                        (yyval.re) = NULL;
                }
@@ -1553,7 +1612,7 @@ yyreduce:
   case 4:
 
 /* Line 1806 of yacc.c  */
-#line 122 "dtc-parser.y"
+#line 117 "dtc-parser.y"
     {
                        (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
                }
@@ -1562,7 +1621,7 @@ yyreduce:
   case 5:
 
 /* Line 1806 of yacc.c  */
-#line 129 "dtc-parser.y"
+#line 124 "dtc-parser.y"
     {
                        (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
                }
@@ -1571,7 +1630,7 @@ yyreduce:
   case 6:
 
 /* Line 1806 of yacc.c  */
-#line 133 "dtc-parser.y"
+#line 128 "dtc-parser.y"
     {
                        add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref));
                        (yyval.re) = (yyvsp[(2) - (2)].re);
@@ -1581,7 +1640,7 @@ yyreduce:
   case 7:
 
 /* Line 1806 of yacc.c  */
-#line 141 "dtc-parser.y"
+#line 136 "dtc-parser.y"
     {
                        (yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
                }
@@ -1590,7 +1649,7 @@ yyreduce:
   case 8:
 
 /* Line 1806 of yacc.c  */
-#line 145 "dtc-parser.y"
+#line 140 "dtc-parser.y"
     {
                        (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
                }
@@ -1599,148 +1658,164 @@ yyreduce:
   case 9:
 
 /* Line 1806 of yacc.c  */
-#line 149 "dtc-parser.y"
+#line 145 "dtc-parser.y"
+    {
+                       struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref));
+
+                       add_label(&target->labels, (yyvsp[(2) - (4)].labelref));
+                       if (target)
+                               merge_nodes(target, (yyvsp[(4) - (4)].node));
+                       else
+                               ERROR(&(yylsp[(3) - (4)]), "Label or path %s not found", (yyvsp[(3) - (4)].labelref));
+                       (yyval.node) = (yyvsp[(1) - (4)].node);
+               }
+    break;
+
+  case 10:
+
+/* Line 1806 of yacc.c  */
+#line 156 "dtc-parser.y"
     {
                        struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
 
                        if (target)
                                merge_nodes(target, (yyvsp[(3) - (3)].node));
                        else
-                               print_error("label or path, '%s', not found", (yyvsp[(2) - (3)].labelref));
+                               ERROR(&(yylsp[(2) - (3)]), "Label or path %s not found", (yyvsp[(2) - (3)].labelref));
                        (yyval.node) = (yyvsp[(1) - (3)].node);
                }
     break;
 
-  case 10:
+  case 11:
 
 /* Line 1806 of yacc.c  */
-#line 159 "dtc-parser.y"
+#line 166 "dtc-parser.y"
     {
                        struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref));
 
-                       if (!target)
-                               print_error("label or path, '%s', not found", (yyvsp[(3) - (4)].labelref));
-                       else
+                       if (target)
                                delete_node(target);
+                       else
+                               ERROR(&(yylsp[(3) - (4)]), "Label or path %s not found", (yyvsp[(3) - (4)].labelref));
+
 
                        (yyval.node) = (yyvsp[(1) - (4)].node);
                }
     break;
 
-  case 11:
+  case 12:
 
 /* Line 1806 of yacc.c  */
-#line 173 "dtc-parser.y"
+#line 181 "dtc-parser.y"
     {
                        (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
                }
     break;
 
-  case 12:
+  case 13:
 
 /* Line 1806 of yacc.c  */
-#line 180 "dtc-parser.y"
+#line 188 "dtc-parser.y"
     {
                        (yyval.proplist) = NULL;
                }
     break;
 
-  case 13:
+  case 14:
 
 /* Line 1806 of yacc.c  */
-#line 184 "dtc-parser.y"
+#line 192 "dtc-parser.y"
     {
                        (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
                }
     break;
 
-  case 14:
+  case 15:
 
 /* Line 1806 of yacc.c  */
-#line 191 "dtc-parser.y"
+#line 199 "dtc-parser.y"
     {
                        (yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data));
                }
     break;
 
-  case 15:
+  case 16:
 
 /* Line 1806 of yacc.c  */
-#line 195 "dtc-parser.y"
+#line 203 "dtc-parser.y"
     {
                        (yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data);
                }
     break;
 
-  case 16:
+  case 17:
 
 /* Line 1806 of yacc.c  */
-#line 199 "dtc-parser.y"
+#line 207 "dtc-parser.y"
     {
                        (yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename));
                }
     break;
 
-  case 17:
+  case 18:
 
 /* Line 1806 of yacc.c  */
-#line 203 "dtc-parser.y"
+#line 211 "dtc-parser.y"
     {
                        add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
                        (yyval.prop) = (yyvsp[(2) - (2)].prop);
                }
     break;
 
-  case 18:
+  case 19:
 
 /* Line 1806 of yacc.c  */
-#line 211 "dtc-parser.y"
+#line 219 "dtc-parser.y"
     {
                        (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
                }
     break;
 
-  case 19:
+  case 20:
 
 /* Line 1806 of yacc.c  */
-#line 215 "dtc-parser.y"
+#line 223 "dtc-parser.y"
     {
                        (yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data);
                }
     break;
 
-  case 20:
+  case 21:
 
 /* Line 1806 of yacc.c  */
-#line 219 "dtc-parser.y"
+#line 227 "dtc-parser.y"
     {
                        (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
                }
     break;
 
-  case 21:
+  case 22:
 
 /* Line 1806 of yacc.c  */
-#line 223 "dtc-parser.y"
+#line 231 "dtc-parser.y"
     {
                        (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
                }
     break;
 
-  case 22:
+  case 23:
 
 /* Line 1806 of yacc.c  */
-#line 227 "dtc-parser.y"
+#line 235 "dtc-parser.y"
     {
                        FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL);
                        struct data d;
 
                        if ((yyvsp[(6) - (9)].integer) != 0)
                                if (fseek(f, (yyvsp[(6) - (9)].integer), SEEK_SET) != 0)
-                                       print_error("Couldn't seek to offset %llu in \"%s\": %s",
-                                                    (unsigned long long)(yyvsp[(6) - (9)].integer),
-                                                    (yyvsp[(4) - (9)].data).val,
-                                                    strerror(errno));
+                                       die("Couldn't seek to offset %llu in \"%s\": %s",
+                                           (unsigned long long)(yyvsp[(6) - (9)].integer), (yyvsp[(4) - (9)].data).val,
+                                           strerror(errno));
 
                        d = data_copy_file(f, (yyvsp[(8) - (9)].integer));
 
@@ -1749,10 +1824,10 @@ yyreduce:
                }
     break;
 
-  case 23:
+  case 24:
 
 /* Line 1806 of yacc.c  */
-#line 244 "dtc-parser.y"
+#line 251 "dtc-parser.y"
     {
                        FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);
                        struct data d = empty_data;
@@ -1764,76 +1839,77 @@ yyreduce:
                }
     break;
 
-  case 24:
+  case 25:
 
 /* Line 1806 of yacc.c  */
-#line 254 "dtc-parser.y"
+#line 261 "dtc-parser.y"
     {
                        (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                }
     break;
 
-  case 25:
+  case 26:
 
 /* Line 1806 of yacc.c  */
-#line 261 "dtc-parser.y"
+#line 268 "dtc-parser.y"
     {
                        (yyval.data) = empty_data;
                }
     break;
 
-  case 26:
+  case 27:
 
 /* Line 1806 of yacc.c  */
-#line 265 "dtc-parser.y"
+#line 272 "dtc-parser.y"
     {
                        (yyval.data) = (yyvsp[(1) - (2)].data);
                }
     break;
 
-  case 27:
+  case 28:
 
 /* Line 1806 of yacc.c  */
-#line 269 "dtc-parser.y"
+#line 276 "dtc-parser.y"
     {
                        (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                }
     break;
 
-  case 28:
+  case 29:
 
 /* Line 1806 of yacc.c  */
-#line 276 "dtc-parser.y"
+#line 283 "dtc-parser.y"
     {
-                       (yyval.array).data = empty_data;
-                       (yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7);
-
-                       if (((yyval.array).bits !=  8) &&
-                           ((yyval.array).bits != 16) &&
-                           ((yyval.array).bits != 32) &&
-                           ((yyval.array).bits != 64))
-                       {
-                               print_error("Only 8, 16, 32 and 64-bit elements"
-                                           " are currently supported");
-                               (yyval.array).bits = 32;
+                       unsigned long long bits;
+
+                       bits = (yyvsp[(2) - (3)].integer);
+
+                       if ((bits !=  8) && (bits != 16) &&
+                           (bits != 32) && (bits != 64)) {
+                               ERROR(&(yylsp[(2) - (3)]), "Array elements must be"
+                                     " 8, 16, 32 or 64-bits");
+                               bits = 32;
                        }
+
+                       (yyval.array).data = empty_data;
+                       (yyval.array).bits = bits;
                }
     break;
 
-  case 29:
+  case 30:
 
 /* Line 1806 of yacc.c  */
-#line 291 "dtc-parser.y"
+#line 299 "dtc-parser.y"
     {
                        (yyval.array).data = empty_data;
                        (yyval.array).bits = 32;
                }
     break;
 
-  case 30:
+  case 31:
 
 /* Line 1806 of yacc.c  */
-#line 296 "dtc-parser.y"
+#line 304 "dtc-parser.y"
     {
                        if ((yyvsp[(1) - (2)].array).bits < 64) {
                                uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1;
@@ -1846,19 +1922,18 @@ yyreduce:
                                 * mask), all bits are one.
                                 */
                                if (((yyvsp[(2) - (2)].integer) > mask) && (((yyvsp[(2) - (2)].integer) | mask) != -1ULL))
-                                       print_error(
-                                               "integer value out of range "
-                                               "%016lx (%d bits)", (yyvsp[(1) - (2)].array).bits);
+                                       ERROR(&(yylsp[(2) - (2)]), "Value out of range for"
+                                             " %d-bit array element", (yyvsp[(1) - (2)].array).bits);
                        }
 
                        (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, (yyvsp[(2) - (2)].integer), (yyvsp[(1) - (2)].array).bits);
                }
     break;
 
-  case 31:
+  case 32:
 
 /* Line 1806 of yacc.c  */
-#line 316 "dtc-parser.y"
+#line 323 "dtc-parser.y"
     {
                        uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits);
 
@@ -1867,280 +1942,262 @@ yyreduce:
                                                          REF_PHANDLE,
                                                          (yyvsp[(2) - (2)].labelref));
                        else
-                               print_error("References are only allowed in "
+                               ERROR(&(yylsp[(2) - (2)]), "References are only allowed in "
                                            "arrays with 32-bit elements.");
 
                        (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, val, (yyvsp[(1) - (2)].array).bits);
                }
     break;
 
-  case 32:
-
-/* Line 1806 of yacc.c  */
-#line 330 "dtc-parser.y"
-    {
-                       (yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref));
-               }
-    break;
-
   case 33:
 
 /* Line 1806 of yacc.c  */
 #line 337 "dtc-parser.y"
     {
-                       (yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
-               }
-    break;
-
-  case 34:
-
-/* Line 1806 of yacc.c  */
-#line 341 "dtc-parser.y"
-    {
-                       (yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal));
+                       (yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref));
                }
     break;
 
-  case 35:
+  case 36:
 
 /* Line 1806 of yacc.c  */
-#line 345 "dtc-parser.y"
+#line 346 "dtc-parser.y"
     {
                        (yyval.integer) = (yyvsp[(2) - (3)].integer);
                }
     break;
 
-  case 38:
+  case 39:
 
 /* Line 1806 of yacc.c  */
-#line 356 "dtc-parser.y"
+#line 357 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); }
     break;
 
-  case 40:
+  case 41:
 
 /* Line 1806 of yacc.c  */
-#line 361 "dtc-parser.y"
+#line 362 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 42:
+  case 43:
 
 /* Line 1806 of yacc.c  */
-#line 366 "dtc-parser.y"
+#line 367 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 44:
+  case 45:
 
 /* Line 1806 of yacc.c  */
-#line 371 "dtc-parser.y"
+#line 372 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 46:
+  case 47:
 
 /* Line 1806 of yacc.c  */
-#line 376 "dtc-parser.y"
+#line 377 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 48:
+  case 49:
 
 /* Line 1806 of yacc.c  */
-#line 381 "dtc-parser.y"
+#line 382 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 50:
-
-/* Line 1806 of yacc.c  */
-#line 386 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); }
-    break;
-
   case 51:
 
 /* Line 1806 of yacc.c  */
 #line 387 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); }
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 53:
+  case 52:
 
 /* Line 1806 of yacc.c  */
-#line 392 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); }
+#line 388 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); }
     break;
 
   case 54:
 
 /* Line 1806 of yacc.c  */
 #line 393 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); }
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); }
     break;
 
   case 55:
 
 /* Line 1806 of yacc.c  */
 #line 394 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); }
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); }
     break;
 
   case 56:
 
 /* Line 1806 of yacc.c  */
 #line 395 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); }
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); }
     break;
 
   case 57:
 
 /* Line 1806 of yacc.c  */
-#line 399 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); }
+#line 396 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); }
     break;
 
   case 58:
 
 /* Line 1806 of yacc.c  */
 #line 400 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); }
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 60:
+  case 59:
 
 /* Line 1806 of yacc.c  */
-#line 405 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); }
+#line 401 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); }
     break;
 
   case 61:
 
 /* Line 1806 of yacc.c  */
 #line 406 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); }
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 63:
+  case 62:
 
 /* Line 1806 of yacc.c  */
-#line 411 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); }
+#line 407 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); }
     break;
 
   case 64:
 
 /* Line 1806 of yacc.c  */
 #line 412 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); }
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); }
     break;
 
   case 65:
 
 /* Line 1806 of yacc.c  */
 #line 413 "dtc-parser.y"
-    { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); }
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); }
     break;
 
-  case 68:
+  case 66:
 
 /* Line 1806 of yacc.c  */
-#line 419 "dtc-parser.y"
-    { (yyval.integer) = -(yyvsp[(2) - (2)].integer); }
+#line 414 "dtc-parser.y"
+    { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); }
     break;
 
   case 69:
 
 /* Line 1806 of yacc.c  */
 #line 420 "dtc-parser.y"
-    { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); }
+    { (yyval.integer) = -(yyvsp[(2) - (2)].integer); }
     break;
 
   case 70:
 
 /* Line 1806 of yacc.c  */
 #line 421 "dtc-parser.y"
-    { (yyval.integer) = !(yyvsp[(2) - (2)].integer); }
+    { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); }
     break;
 
   case 71:
 
 /* Line 1806 of yacc.c  */
-#line 426 "dtc-parser.y"
+#line 422 "dtc-parser.y"
+    { (yyval.integer) = !(yyvsp[(2) - (2)].integer); }
+    break;
+
+  case 72:
+
+/* Line 1806 of yacc.c  */
+#line 427 "dtc-parser.y"
     {
                        (yyval.data) = empty_data;
                }
     break;
 
-  case 72:
+  case 73:
 
 /* Line 1806 of yacc.c  */
-#line 430 "dtc-parser.y"
+#line 431 "dtc-parser.y"
     {
                        (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
                }
     break;
 
-  case 73:
+  case 74:
 
 /* Line 1806 of yacc.c  */
-#line 434 "dtc-parser.y"
+#line 435 "dtc-parser.y"
     {
                        (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                }
     break;
 
-  case 74:
+  case 75:
 
 /* Line 1806 of yacc.c  */
-#line 441 "dtc-parser.y"
+#line 442 "dtc-parser.y"
     {
                        (yyval.nodelist) = NULL;
                }
     break;
 
-  case 75:
+  case 76:
 
 /* Line 1806 of yacc.c  */
-#line 445 "dtc-parser.y"
+#line 446 "dtc-parser.y"
     {
                        (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
                }
     break;
 
-  case 76:
+  case 77:
 
 /* Line 1806 of yacc.c  */
-#line 449 "dtc-parser.y"
+#line 450 "dtc-parser.y"
     {
-                       print_error("syntax error: properties must precede subnodes");
+                       ERROR(&(yylsp[(2) - (2)]), "Properties must precede subnodes");
                        YYERROR;
                }
     break;
 
-  case 77:
+  case 78:
 
 /* Line 1806 of yacc.c  */
-#line 457 "dtc-parser.y"
+#line 458 "dtc-parser.y"
     {
                        (yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename));
                }
     break;
 
-  case 78:
+  case 79:
 
 /* Line 1806 of yacc.c  */
-#line 461 "dtc-parser.y"
+#line 462 "dtc-parser.y"
     {
                        (yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename));
                }
     break;
 
-  case 79:
+  case 80:
 
 /* Line 1806 of yacc.c  */
-#line 465 "dtc-parser.y"
+#line 466 "dtc-parser.y"
     {
                        add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref));
                        (yyval.node) = (yyvsp[(2) - (2)].node);
@@ -2150,7 +2207,7 @@ yyreduce:
 
 
 /* Line 1806 of yacc.c  */
-#line 2154 "dtc-parser.tab.c"
+#line 2211 "dtc-parser.tab.c"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2171,6 +2228,7 @@ yyreduce:
   YY_STACK_PRINT (yyss, yyssp);
 
   *++yyvsp = yyval;
+  *++yylsp = yyloc;
 
   /* Now `shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
@@ -2235,7 +2293,7 @@ yyerrlab:
 #endif
     }
 
-
+  yyerror_range[1] = yylloc;
 
   if (yyerrstatus == 3)
     {
@@ -2251,7 +2309,7 @@ yyerrlab:
       else
        {
          yydestruct ("Error: discarding",
-                     yytoken, &yylval);
+                     yytoken, &yylval, &yylloc);
          yychar = YYEMPTY;
        }
     }
@@ -2272,6 +2330,7 @@ yyerrorlab:
   if (/*CONSTCOND*/ 0)
      goto yyerrorlab;
 
+  yyerror_range[1] = yylsp[1-yylen];
   /* Do not reclaim the symbols of the rule which action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
@@ -2305,9 +2364,9 @@ yyerrlab1:
       if (yyssp == yyss)
        YYABORT;
 
-
+      yyerror_range[1] = *yylsp;
       yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp);
+                 yystos[yystate], yyvsp, yylsp);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
@@ -2315,6 +2374,11 @@ yyerrlab1:
 
   *++yyvsp = yylval;
 
+  yyerror_range[2] = yylloc;
+  /* Using YYLLOC is tempting, but would change the location of
+     the lookahead.  YYLOC is available though.  */
+  YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
+  *++yylsp = yyloc;
 
   /* Shift the error token.  */
   YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
@@ -2354,7 +2418,7 @@ yyreturn:
          user semantic actions for why this is necessary.  */
       yytoken = YYTRANSLATE (yychar);
       yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval);
+                  yytoken, &yylval, &yylloc);
     }
   /* Do not reclaim the symbols of the rule which action triggered
      this YYABORT or YYACCEPT.  */
@@ -2363,7 +2427,7 @@ yyreturn:
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp);
+                 yystos[*yyssp], yyvsp, yylsp);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -2381,67 +2445,11 @@ yyreturn:
 
 
 /* Line 2067 of yacc.c  */
-#line 471 "dtc-parser.y"
+#line 472 "dtc-parser.y"
 
 
-void print_error(char const *fmt, ...)
+void yyerror(char const *s)
 {
-       va_list va;
-
-       va_start(va, fmt);
-       srcpos_verror(&yylloc, fmt, va);
-       va_end(va);
-
-       treesource_error = 1;
-}
-
-void yyerror(char const *s) {
-       print_error("%s", s);
-}
-
-static unsigned long long eval_literal(const char *s, int base, int bits)
-{
-       unsigned long long val;
-       char *e;
-
-       errno = 0;
-       val = strtoull(s, &e, base);
-       if (*e) {
-               size_t uls = strspn(e, "UL");
-               if (e[uls])
-                       print_error("bad characters in literal");
-       }
-       if ((errno == ERANGE)
-                || ((bits < 64) && (val >= (1ULL << bits))))
-               print_error("literal out of range");
-       else if (errno != 0)
-               print_error("bad literal");
-       return val;
-}
-
-static unsigned char eval_char_literal(const char *s)
-{
-       int i = 1;
-       char c = s[0];
-
-       if (c == '\0')
-       {
-               print_error("empty character literal");
-               return 0;
-       }
-
-       /*
-        * If the first character in the character literal is a \ then process
-        * the remaining characters as an escape encoding. If the first
-        * character is neither an escape or a terminator it should be the only
-        * character in the literal and will be returned.
-        */
-       if (c == '\\')
-               c = get_escape_char(s, &i);
-
-       if (s[i] != '\0')
-               print_error("malformed character literal");
-
-       return c;
+       ERROR(&yylloc, "%s", s);
 }
 
index 25d3b88c61320bb2525341a66ec2fc556a2fc800..4a97ced1b3918bbe269b8b62e0941fa1369708d1 100644 (file)
      DT_PROPNODENAME = 271,
      DT_LITERAL = 272,
      DT_CHAR_LITERAL = 273,
-     DT_BASE = 274,
-     DT_BYTE = 275,
-     DT_STRING = 276,
-     DT_LABEL = 277,
-     DT_REF = 278,
-     DT_INCBIN = 279
+     DT_BYTE = 274,
+     DT_STRING = 275,
+     DT_LABEL = 276,
+     DT_REF = 277,
+     DT_INCBIN = 278
    };
 #endif
 
@@ -69,12 +68,10 @@ typedef union YYSTYPE
 {
 
 /* Line 2068 of yacc.c  */
-#line 40 "dtc-parser.y"
+#line 38 "dtc-parser.y"
 
        char *propnodename;
-       char *literal;
        char *labelref;
-       unsigned int cbase;
        uint8_t byte;
        struct data data;
 
@@ -93,7 +90,7 @@ typedef union YYSTYPE
 
 
 /* Line 2068 of yacc.c  */
-#line 97 "dtc-parser.tab.h"
+#line 94 "dtc-parser.tab.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -102,4 +99,18 @@ typedef union YYSTYPE
 
 extern YYSTYPE yylval;
 
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYLTYPE yylloc;
 
index f412460f94d7478ad3fb9a81951f5c6a5e60c4ad..5a897e36562d67107dba44fa91274253b34152dc 100644 (file)
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  *                                                                   USA
  */
-
 %{
 #include <stdio.h>
 
 #include "dtc.h"
 #include "srcpos.h"
 
-YYLTYPE yylloc;
-
 extern int yylex(void);
-extern void print_error(char const *fmt, ...);
 extern void yyerror(char const *s);
+#define ERROR(loc, ...) \
+       do { \
+               srcpos_error((loc), "Error", __VA_ARGS__); \
+               treesource_error = true; \
+       } while (0)
 
 extern struct boot_info *the_boot_info;
-extern int treesource_error;
-
-static unsigned long long eval_literal(const char *s, int base, int bits);
-static unsigned char eval_char_literal(const char *s);
+extern bool treesource_error;
 %}
 
 %union {
        char *propnodename;
-       char *literal;
        char *labelref;
-       unsigned int cbase;
        uint8_t byte;
        struct data data;
 
@@ -65,9 +61,8 @@ static unsigned char eval_char_literal(const char *s);
 %token DT_DEL_PROP
 %token DT_DEL_NODE
 %token <propnodename> DT_PROPNODENAME
-%token <literal> DT_LITERAL
-%token <literal> DT_CHAR_LITERAL
-%token <cbase> DT_BASE
+%token <integer> DT_LITERAL
+%token <integer> DT_CHAR_LITERAL
 %token <byte> DT_BYTE
 %token <data> DT_STRING
 %token <labelref> DT_LABEL
@@ -145,6 +140,18 @@ devicetree:
                {
                        $$ = merge_nodes($1, $3);
                }
+
+       | devicetree DT_LABEL DT_REF nodedef
+               {
+                       struct node *target = get_node_by_ref($1, $3);
+
+                       add_label(&target->labels, $2);
+                       if (target)
+                               merge_nodes(target, $4);
+                       else
+                               ERROR(&@3, "Label or path %s not found", $3);
+                       $$ = $1;
+               }
        | devicetree DT_REF nodedef
                {
                        struct node *target = get_node_by_ref($1, $2);
@@ -152,17 +159,18 @@ devicetree:
                        if (target)
                                merge_nodes(target, $3);
                        else
-                               print_error("label or path, '%s', not found", $2);
+                               ERROR(&@2, "Label or path %s not found", $2);
                        $$ = $1;
                }
        | devicetree DT_DEL_NODE DT_REF ';'
                {
                        struct node *target = get_node_by_ref($1, $3);
 
-                       if (!target)
-                               print_error("label or path, '%s', not found", $3);
-                       else
+                       if (target)
                                delete_node(target);
+                       else
+                               ERROR(&@3, "Label or path %s not found", $3);
+
 
                        $$ = $1;
                }
@@ -230,10 +238,9 @@ propdata:
 
                        if ($6 != 0)
                                if (fseek(f, $6, SEEK_SET) != 0)
-                                       print_error("Couldn't seek to offset %llu in \"%s\": %s",
-                                                    (unsigned long long)$6,
-                                                    $4.val,
-                                                    strerror(errno));
+                                       die("Couldn't seek to offset %llu in \"%s\": %s",
+                                           (unsigned long long)$6, $4.val,
+                                           strerror(errno));
 
                        d = data_copy_file(f, $8);
 
@@ -274,18 +281,19 @@ propdataprefix:
 arrayprefix:
        DT_BITS DT_LITERAL '<'
                {
-                       $$.data = empty_data;
-                       $$.bits = eval_literal($2, 0, 7);
-
-                       if (($$.bits !=  8) &&
-                           ($$.bits != 16) &&
-                           ($$.bits != 32) &&
-                           ($$.bits != 64))
-                       {
-                               print_error("Only 8, 16, 32 and 64-bit elements"
-                                           " are currently supported");
-                               $$.bits = 32;
+                       unsigned long long bits;
+
+                       bits = $2;
+
+                       if ((bits !=  8) && (bits != 16) &&
+                           (bits != 32) && (bits != 64)) {
+                               ERROR(&@2, "Array elements must be"
+                                     " 8, 16, 32 or 64-bits");
+                               bits = 32;
                        }
+
+                       $$.data = empty_data;
+                       $$.bits = bits;
                }
        | '<'
                {
@@ -305,9 +313,8 @@ arrayprefix:
                                 * mask), all bits are one.
                                 */
                                if (($2 > mask) && (($2 | mask) != -1ULL))
-                                       print_error(
-                                               "integer value out of range "
-                                               "%016lx (%d bits)", $1.bits);
+                                       ERROR(&@2, "Value out of range for"
+                                             " %d-bit array element", $1.bits);
                        }
 
                        $$.data = data_append_integer($1.data, $2, $1.bits);
@@ -321,7 +328,7 @@ arrayprefix:
                                                          REF_PHANDLE,
                                                          $2);
                        else
-                               print_error("References are only allowed in "
+                               ERROR(&@2, "References are only allowed in "
                                            "arrays with 32-bit elements.");
 
                        $$.data = data_append_integer($1.data, val, $1.bits);
@@ -334,13 +341,7 @@ arrayprefix:
 
 integer_prim:
          DT_LITERAL
-               {
-                       $$ = eval_literal($1, 0, 64);
-               }
        | DT_CHAR_LITERAL
-               {
-                       $$ = eval_char_literal($1);
-               }
        | '(' integer_expr ')'
                {
                        $$ = $2;
@@ -447,7 +448,7 @@ subnodes:
                }
        | subnode propdef
                {
-                       print_error("syntax error: properties must precede subnodes");
+                       ERROR(&@2, "Properties must precede subnodes");
                        YYERROR;
                }
        ;
@@ -470,63 +471,7 @@ subnode:
 
 %%
 
-void print_error(char const *fmt, ...)
-{
-       va_list va;
-
-       va_start(va, fmt);
-       srcpos_verror(&yylloc, fmt, va);
-       va_end(va);
-
-       treesource_error = 1;
-}
-
-void yyerror(char const *s) {
-       print_error("%s", s);
-}
-
-static unsigned long long eval_literal(const char *s, int base, int bits)
-{
-       unsigned long long val;
-       char *e;
-
-       errno = 0;
-       val = strtoull(s, &e, base);
-       if (*e) {
-               size_t uls = strspn(e, "UL");
-               if (e[uls])
-                       print_error("bad characters in literal");
-       }
-       if ((errno == ERANGE)
-                || ((bits < 64) && (val >= (1ULL << bits))))
-               print_error("literal out of range");
-       else if (errno != 0)
-               print_error("bad literal");
-       return val;
-}
-
-static unsigned char eval_char_literal(const char *s)
+void yyerror(char const *s)
 {
-       int i = 1;
-       char c = s[0];
-
-       if (c == '\0')
-       {
-               print_error("empty character literal");
-               return 0;
-       }
-
-       /*
-        * If the first character in the character literal is a \ then process
-        * the remaining characters as an escape encoding. If the first
-        * character is neither an escape or a terminator it should be the only
-        * character in the literal and will be returned.
-        */
-       if (c == '\\')
-               c = get_escape_char(s, &i);
-
-       if (s[i] != '\0')
-               print_error("malformed character literal");
-
-       return c;
+       ERROR(&yylloc, "%s", s);
 }
index a375683c1534f2a1a3791ab34d75f8c15450f58b..8c4add69a76578839de910292b165b4504f47cf2 100644 (file)
@@ -21,8 +21,6 @@
 #include "dtc.h"
 #include "srcpos.h"
 
-#include "version_gen.h"
-
 /*
  * Command line options
  */
@@ -49,55 +47,62 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
                fill_fullpaths(child, tree->fullpath);
 }
 
-static void  __attribute__ ((noreturn)) usage(void)
-{
-       fprintf(stderr, "Usage:\n");
-       fprintf(stderr, "\tdtc [options] <input file>\n");
-       fprintf(stderr, "\nOptions:\n");
-       fprintf(stderr, "\t-h\n");
-       fprintf(stderr, "\t\tThis help text\n");
-       fprintf(stderr, "\t-q\n");
-       fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
-       fprintf(stderr, "\t-I <input format>\n");
-       fprintf(stderr, "\t\tInput formats are:\n");
-       fprintf(stderr, "\t\t\tdts - device tree source text\n");
-       fprintf(stderr, "\t\t\tdtb - device tree blob\n");
-       fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
-       fprintf(stderr, "\t-o <output file>\n");
-       fprintf(stderr, "\t-O <output format>\n");
-       fprintf(stderr, "\t\tOutput formats are:\n");
-       fprintf(stderr, "\t\t\tdts - device tree source text\n");
-       fprintf(stderr, "\t\t\tdtb - device tree blob\n");
-       fprintf(stderr, "\t\t\tasm - assembler source\n");
-       fprintf(stderr, "\t-V <output version>\n");
-       fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
-       fprintf(stderr, "\t-d <output dependency file>\n");
-       fprintf(stderr, "\t-R <number>\n");
-       fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
-       fprintf(stderr, "\t-S <bytes>\n");
-       fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
-       fprintf(stderr, "\t-p <bytes>\n");
-       fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
-       fprintf(stderr, "\t-b <number>\n");
-       fprintf(stderr, "\t\tSet the physical boot cpu\n");
-       fprintf(stderr, "\t-f\n");
-       fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
-       fprintf(stderr, "\t-i\n");
-       fprintf(stderr, "\t\tAdd a path to search for include files\n");
-       fprintf(stderr, "\t-s\n");
-       fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n");
-       fprintf(stderr, "\t-v\n");
-       fprintf(stderr, "\t\tPrint DTC version and exit\n");
-       fprintf(stderr, "\t-H <phandle format>\n");
-       fprintf(stderr, "\t\tphandle formats are:\n");
-       fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
-       fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
-       fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
-       fprintf(stderr, "\t-W [no-]<checkname>\n");
-       fprintf(stderr, "\t-E [no-]<checkname>\n");
-       fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
-       exit(3);
-}
+/* Usage related data. */
+#define FDT_VERSION(version)   _FDT_VERSION(version)
+#define _FDT_VERSION(version)  #version
+static const char usage_synopsis[] = "dtc [options] <input file>";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
+static struct option const usage_long_opts[] = {
+       {"quiet",            no_argument, NULL, 'q'},
+       {"in-format",         a_argument, NULL, 'I'},
+       {"out",               a_argument, NULL, 'o'},
+       {"out-format",        a_argument, NULL, 'O'},
+       {"out-version",       a_argument, NULL, 'V'},
+       {"out-dependency",    a_argument, NULL, 'd'},
+       {"reserve",           a_argument, NULL, 'R'},
+       {"space",             a_argument, NULL, 'S'},
+       {"pad",               a_argument, NULL, 'p'},
+       {"boot-cpu",          a_argument, NULL, 'b'},
+       {"force",            no_argument, NULL, 'f'},
+       {"include",           a_argument, NULL, 'i'},
+       {"sort",             no_argument, NULL, 's'},
+       {"phandle",           a_argument, NULL, 'H'},
+       {"warning",           a_argument, NULL, 'W'},
+       {"error",             a_argument, NULL, 'E'},
+       {"help",             no_argument, NULL, 'h'},
+       {"version",          no_argument, NULL, 'v'},
+       {NULL,               no_argument, NULL, 0x0},
+};
+static const char * const usage_opts_help[] = {
+       "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all",
+       "\n\tInput formats are:\n"
+        "\t\tdts - device tree source text\n"
+        "\t\tdtb - device tree blob\n"
+        "\t\tfs  - /proc/device-tree style directory",
+       "\n\tOutput file",
+       "\n\tOutput formats are:\n"
+        "\t\tdts - device tree source text\n"
+        "\t\tdtb - device tree blob\n"
+        "\t\tasm - assembler source",
+       "\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
+       "\n\tOutput dependency file",
+       "\n\tMake space for <number> reserve map entries (for dtb and asm output)",
+       "\n\tMake the blob at least <bytes> long (extra space)",
+       "\n\tAdd padding to the blob of <bytes> long (extra space)",
+       "\n\tSet the physical boot cpu",
+       "\n\tTry to produce output even if the input tree has errors",
+       "\n\tAdd a path to search for include files",
+       "\n\tSort nodes and properties before outputting (useful for comparing trees)",
+       "\n\tValid phandle formats are:\n"
+        "\t\tlegacy - \"linux,phandle\" properties only\n"
+        "\t\tepapr  - \"phandle\" properties only\n"
+        "\t\tboth   - Both \"linux,phandle\" and \"phandle\" properties",
+       "\n\tEnable/disable warnings (prefix with \"no-\")",
+       "\n\tEnable/disable errors (prefix with \"no-\")",
+       "\n\tPrint this help and exit",
+       "\n\tPrint version and exit",
+       NULL,
+};
 
 int main(int argc, char *argv[])
 {
@@ -106,7 +111,7 @@ int main(int argc, char *argv[])
        const char *outform = "dts";
        const char *outname = "-";
        const char *depname = NULL;
-       int force = 0, sort = 0;
+       bool force = false, sort = false;
        const char *arg;
        int opt;
        FILE *outf = NULL;
@@ -118,8 +123,7 @@ int main(int argc, char *argv[])
        minsize    = 0;
        padsize    = 0;
 
-       while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
-                       != EOF) {
+       while ((opt = util_getopt_long()) != EOF) {
                switch (opt) {
                case 'I':
                        inform = optarg;
@@ -146,7 +150,7 @@ int main(int argc, char *argv[])
                        padsize = strtol(optarg, NULL, 0);
                        break;
                case 'f':
-                       force = 1;
+                       force = true;
                        break;
                case 'q':
                        quiet++;
@@ -158,8 +162,7 @@ int main(int argc, char *argv[])
                        srcfile_add_search_path(optarg);
                        break;
                case 'v':
-                       printf("Version: %s\n", DTC_VERSION);
-                       exit(0);
+                       util_version();
                case 'H':
                        if (streq(optarg, "legacy"))
                                phandle_format = PHANDLE_LEGACY;
@@ -173,7 +176,7 @@ int main(int argc, char *argv[])
                        break;
 
                case 's':
-                       sort = 1;
+                       sort = true;
                        break;
 
                case 'W':
@@ -185,13 +188,14 @@ int main(int argc, char *argv[])
                        break;
 
                case 'h':
+                       usage(NULL);
                default:
-                       usage();
+                       usage("unknown option");
                }
        }
 
        if (argc > (optind+1))
-               usage();
+               usage("missing files");
        else if (argc < (optind+1))
                arg = "-";
        else
@@ -201,9 +205,6 @@ int main(int argc, char *argv[])
        if (minsize && padsize)
                die("Can't set both -p and -S\n");
 
-       if (minsize)
-               fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n");
-
        if (depname) {
                depfile = fopen(depname, "w");
                if (!depfile)
@@ -238,7 +239,7 @@ int main(int argc, char *argv[])
        if (streq(outname, "-")) {
                outf = stdout;
        } else {
-               outf = fopen(outname, "w");
+               outf = fopen(outname, "wb");
                if (! outf)
                        die("Couldn't open output file %s: %s\n",
                            outname, strerror(errno));
index 3e42a071070e6bbf985bf4a0c813f1e677327748..56212c8df660396b1d9bf6752e1121990e0789ab 100644 (file)
@@ -38,9 +38,9 @@
 #include "util.h"
 
 #ifdef DEBUG
-#define debug(fmt,args...)     printf(fmt, ##args)
+#define debug(...)     printf(__VA_ARGS__)
 #else
-#define debug(fmt,args...)
+#define debug(...)
 #endif
 
 
@@ -66,7 +66,6 @@ typedef uint32_t cell_t;
 #define strneq(a, b, n)        (strncmp((a), (b), (n)) == 0)
 
 #define ALIGN(x, a)    (((x) + (a) - 1) & ~((a) - 1))
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
 /* Data blobs */
 enum markertype {
@@ -89,7 +88,7 @@ struct data {
 };
 
 
-#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
+#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
 
 #define for_each_marker(m) \
        for (; (m); (m) = (m)->next)
@@ -119,7 +118,7 @@ struct data data_append_align(struct data d, int align);
 
 struct data data_add_marker(struct data d, enum markertype type, char *ref);
 
-int data_is_one_string(struct data d);
+bool data_is_one_string(struct data d);
 
 /* DT constraints */
 
@@ -128,13 +127,13 @@ int data_is_one_string(struct data d);
 
 /* Live trees */
 struct label {
-       int deleted;
+       bool deleted;
        char *label;
        struct label *next;
 };
 
 struct property {
-       int deleted;
+       bool deleted;
        char *name;
        struct data val;
 
@@ -144,7 +143,7 @@ struct property {
 };
 
 struct node {
-       int deleted;
+       bool deleted;
        char *name;
        struct property *proplist;
        struct node *children;
@@ -248,8 +247,8 @@ void sort_tree(struct boot_info *bi);
 
 /* Checks */
 
-void parse_checks_option(bool warn, bool error, const char *optarg);
-void process_checks(int force, struct boot_info *bi);
+void parse_checks_option(bool warn, bool error, const char *arg);
+void process_checks(bool force, struct boot_info *bi);
 
 /* Flattened trees */
 
index 665dad7bb465b474387af9996e1d36e96a579d6b..bd99fa2d33b85e873bd00178d6390d70f4afaa0d 100644 (file)
@@ -261,7 +261,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
 {
        struct property *prop;
        struct node *child;
-       int seen_name_prop = 0;
+       bool seen_name_prop = false;
 
        if (tree->deleted)
                return;
@@ -279,7 +279,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
                int nameoff;
 
                if (streq(prop->name, "name"))
-                       seen_name_prop = 1;
+                       seen_name_prop = true;
 
                nameoff = stringtable_insert(strbuf, prop->name);
 
index f3774530170ab6ac7465ae31cb5777bbe48614d0..6d1beec9581d559539773215a66f6eb0e8b51d77 100644 (file)
@@ -37,26 +37,26 @@ static struct node *read_fstree(const char *dirname)
        tree = build_node(NULL, NULL);
 
        while ((de = readdir(d)) != NULL) {
-               char *tmpnam;
+               char *tmpname;
 
                if (streq(de->d_name, ".")
                    || streq(de->d_name, ".."))
                        continue;
 
-               tmpnam = join_path(dirname, de->d_name);
+               tmpname = join_path(dirname, de->d_name);
 
-               if (lstat(tmpnam, &st) < 0)
-                       die("stat(%s): %s\n", tmpnam, strerror(errno));
+               if (lstat(tmpname, &st) < 0)
+                       die("stat(%s): %s\n", tmpname, strerror(errno));
 
                if (S_ISREG(st.st_mode)) {
                        struct property *prop;
                        FILE *pfile;
 
-                       pfile = fopen(tmpnam, "r");
+                       pfile = fopen(tmpname, "rb");
                        if (! pfile) {
                                fprintf(stderr,
                                        "WARNING: Cannot open %s: %s\n",
-                                       tmpnam, strerror(errno));
+                                       tmpname, strerror(errno));
                        } else {
                                prop = build_property(xstrdup(de->d_name),
                                                      data_copy_file(pfile,
@@ -67,12 +67,12 @@ static struct node *read_fstree(const char *dirname)
                } else if (S_ISDIR(st.st_mode)) {
                        struct node *newchild;
 
-                       newchild = read_fstree(tmpnam);
+                       newchild = read_fstree(tmpname);
                        newchild = name_node(newchild, xstrdup(de->d_name));
                        add_child(tree, newchild);
                }
 
-               free(tmpnam);
+               free(tmpname);
        }
 
        closedir(d);
index b61465fb2f33813ac78959c22fb3ded4452c9efa..e229b84432f99216189e92d6e61bc505aa4d6b9f 100644 (file)
@@ -511,7 +511,9 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
 
 struct node *get_node_by_ref(struct node *tree, const char *ref)
 {
-       if (ref[0] == '/')
+       if (streq(ref, "/"))
+               return tree;
+       else if (ref[0] == '/')
                return get_node_by_path(tree, ref);
        else
                return get_node_by_label(tree, ref);
index 246ab4bc0d9d8c6e8830e18d35941213730e51ef..f534c22a888d71e9b321d4eadd1430749e171ac0 100644 (file)
@@ -34,7 +34,7 @@ struct search_path {
 static struct search_path *search_path_head, **search_path_tail;
 
 
-static char *dirname(const char *path)
+static char *get_dirname(const char *path)
 {
        const char *slash = strrchr(path, '/');
 
@@ -77,7 +77,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp)
        else
                fullname = join_path(dirname, fname);
 
-       *fp = fopen(fullname, "r");
+       *fp = fopen(fullname, "rb");
        if (!*fp) {
                free(fullname);
                fullname = NULL;
@@ -150,7 +150,7 @@ void srcfile_push(const char *fname)
        srcfile = xmalloc(sizeof(*srcfile));
 
        srcfile->f = srcfile_relative_open(fname, &srcfile->name);
-       srcfile->dir = dirname(srcfile->name);
+       srcfile->dir = get_dirname(srcfile->name);
        srcfile->prev = current_srcfile;
 
        srcfile->lineno = 1;
@@ -159,7 +159,7 @@ void srcfile_push(const char *fname)
        current_srcfile = srcfile;
 }
 
-int srcfile_pop(void)
+bool srcfile_pop(void)
 {
        struct srcfile_state *srcfile = current_srcfile;
 
@@ -177,7 +177,7 @@ int srcfile_pop(void)
         * fix this we could either allocate all the files from a
         * table, or use a pool allocator. */
 
-       return current_srcfile ? 1 : 0;
+       return current_srcfile ? true : false;
 }
 
 void srcfile_add_search_path(const char *dirname)
@@ -290,42 +290,27 @@ srcpos_string(struct srcpos *pos)
        return pos_str;
 }
 
-void
-srcpos_verror(struct srcpos *pos, char const *fmt, va_list va)
+void srcpos_verror(struct srcpos *pos, const char *prefix,
+                  const char *fmt, va_list va)
 {
-       const char *srcstr;
-
-       srcstr = srcpos_string(pos);
+       char *srcstr;
 
-       fprintf(stdout, "Error: %s ", srcstr);
-       vfprintf(stdout, fmt, va);
-       fprintf(stdout, "\n");
-}
+       srcstr = srcpos_string(pos);
 
-void
-srcpos_error(struct srcpos *pos, char const *fmt, ...)
-{
-       va_list va;
+       fprintf(stderr, "%s: %s ", prefix, srcstr);
+       vfprintf(stderr, fmt, va);
+       fprintf(stderr, "\n");
 
-       va_start(va, fmt);
-       srcpos_verror(pos, fmt, va);
-       va_end(va);
+       free(srcstr);
 }
 
-
-void
-srcpos_warn(struct srcpos *pos, char const *fmt, ...)
+void srcpos_error(struct srcpos *pos, const char *prefix,
+                 const char *fmt, ...)
 {
-       const char *srcstr;
        va_list va;
-       va_start(va, fmt);
-
-       srcstr = srcpos_string(pos);
-
-       fprintf(stderr, "Warning: %s ", srcstr);
-       vfprintf(stderr, fmt, va);
-       fprintf(stderr, "\n");
 
+       va_start(va, fmt);
+       srcpos_verror(pos, prefix, fmt, va);
        va_end(va);
 }
 
index 93a27123c2e9c17ec27c728243860121447feb7e..f81827bd684a767da1d62f6f31020284821f5045 100644 (file)
@@ -21,6 +21,7 @@
 #define _SRCPOS_H_
 
 #include <stdio.h>
+#include <stdbool.h>
 
 struct srcfile_state {
        FILE *f;
@@ -55,7 +56,7 @@ extern struct srcfile_state *current_srcfile; /* = NULL */
 FILE *srcfile_relative_open(const char *fname, char **fullnamep);
 
 void srcfile_push(const char *fname);
-int srcfile_pop(void);
+bool srcfile_pop(void);
 
 /**
  * Add a new directory to the search path for input files
@@ -106,12 +107,12 @@ extern struct srcpos *srcpos_copy(struct srcpos *pos);
 extern char *srcpos_string(struct srcpos *pos);
 extern void srcpos_dump(struct srcpos *pos);
 
-extern void srcpos_verror(struct srcpos *pos, char const *, va_list va)
-     __attribute__((format(printf, 2, 0)));
-extern void srcpos_error(struct srcpos *pos, char const *, ...)
-     __attribute__((format(printf, 2, 3)));
-extern void srcpos_warn(struct srcpos *pos, char const *, ...)
-     __attribute__((format(printf, 2, 3)));
+extern void srcpos_verror(struct srcpos *pos, const char *prefix,
+                         const char *fmt, va_list va)
+       __attribute__((format(printf, 3, 0)));
+extern void srcpos_error(struct srcpos *pos, const char *prefix,
+                        const char *fmt, ...)
+       __attribute__((format(printf, 3, 4)));
 
 extern void srcpos_set_line(char *f, int l);
 
index 33eeba55fb4dd6482193902e784dbb1a62368f3e..a55d1d128cce7fe03808691fd06428f9f30da2ae 100644 (file)
@@ -26,12 +26,12 @@ extern int yyparse(void);
 extern YYLTYPE yylloc;
 
 struct boot_info *the_boot_info;
-int treesource_error;
+bool treesource_error;
 
 struct boot_info *dt_from_source(const char *fname)
 {
        the_boot_info = NULL;
-       treesource_error = 0;
+       treesource_error = false;
 
        srcfile_push(fname);
        yyin = current_srcfile->f;
@@ -54,9 +54,9 @@ static void write_prefix(FILE *f, int level)
                fputc('\t', f);
 }
 
-static int isstring(char c)
+static bool isstring(char c)
 {
-       return (isprint(c)
+       return (isprint((unsigned char)c)
                || (c == '\0')
                || strchr("\a\b\t\n\v\f\r", c));
 }
@@ -109,7 +109,7 @@ static void write_propval_string(FILE *f, struct data val)
                        break;
                case '\0':
                        fprintf(f, "\", ");
-                       while (m && (m->offset < i)) {
+                       while (m && (m->offset <= (i + 1))) {
                                if (m->type == LABEL) {
                                        assert(m->offset == (i+1));
                                        fprintf(f, "%s: ", m->ref);
@@ -119,7 +119,7 @@ static void write_propval_string(FILE *f, struct data val)
                        fprintf(f, "\"");
                        break;
                default:
-                       if (isprint(c))
+                       if (isprint((unsigned char)c))
                                fprintf(f, "%c", c);
                        else
                                fprintf(f, "\\x%02hhx", c);
@@ -178,7 +178,7 @@ static void write_propval_bytes(FILE *f, struct data val)
                        m = m->next;
                }
 
-               fprintf(f, "%02hhx", *bp++);
+               fprintf(f, "%02hhx", (unsigned char)(*bp++));
                if ((const void *)bp >= propend)
                        break;
                fprintf(f, " ");
diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh
new file mode 100755 (executable)
index 0000000..3171608
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Simple script to update the version of DTC carried by the Linux kernel
+#
+# This script assumes that the dtc and the linux git trees are in the
+# same directory. After building dtc in the dtc directory, it copies the
+# source files and generated source files into the scripts/dtc directory
+# in the kernel and creates a git commit updating them to the new
+# version.
+#
+# Usage: from the top level Linux source tree, run:
+# $ ./scripts/dtc/update-dtc-source.sh
+#
+# The script will change into the dtc tree, build and test dtc, copy the
+# relevant files into the kernel tree and create a git commit. The commit
+# message will need to be modified to reflect the version of DTC being
+# imported
+#
+# TODO:
+# This script is pretty basic, but it is seldom used so a few manual tasks
+# aren't a big deal. If anyone is interested in making it more robust, the
+# the following would be nice:
+# * Actually fail to complete if any testcase fails.
+#   - The dtc "make check" target needs to return a failure
+# * Extract the version number from the dtc repo for the commit message
+# * Build dtc in the kernel tree
+# * run 'make check" on dtc built from the kernel tree
+
+set -ev
+
+DTC_UPSTREAM_PATH=`pwd`/../dtc
+DTC_LINUX_PATH=`pwd`/scripts/dtc
+
+DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c \
+               srcpos.c srcpos.h treesource.c util.c util.h version_gen.h \
+               Makefile.dtc dtc-lexer.l dtc-parser.y"
+DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h"
+
+# Build DTC
+cd $DTC_UPSTREAM_PATH
+make clean
+make check
+
+# Copy the files into the Linux tree
+cd $DTC_LINUX_PATH
+for f in $DTC_SOURCE; do
+       cp ${DTC_UPSTREAM_PATH}/${f} ${f}
+       git add ${f}
+done
+for f in $DTC_GENERATED; do
+       cp ${DTC_UPSTREAM_PATH}/$f ${f}_shipped
+       git add ${f}_shipped
+done
+
+git commit -e -v -m "scripts/dtc: Update to upstream version [CHANGEME]"
index 2422c34e11dfd381b26d11c1fec39d9369b17d62..9d65226df9e404e7a33ecdbb3f715a3a5a13856e 100644 (file)
 
 #include "libfdt.h"
 #include "util.h"
+#include "version_gen.h"
 
 char *xstrdup(const char *s)
 {
        int len = strlen(s) + 1;
-       char *dup = xmalloc(len);
+       char *d = xmalloc(len);
 
-       memcpy(dup, s, len);
+       memcpy(d, s, len);
 
-       return dup;
+       return d;
 }
 
 char *join_path(const char *path, const char *name)
@@ -69,10 +70,10 @@ char *join_path(const char *path, const char *name)
        return str;
 }
 
-int util_is_printable_string(const void *data, int len)
+bool util_is_printable_string(const void *data, int len)
 {
        const char *s = data;
-       const char *ss;
+       const char *ss, *se;
 
        /* zero length is not */
        if (len == 0)
@@ -82,13 +83,19 @@ int util_is_printable_string(const void *data, int len)
        if (s[len - 1] != '\0')
                return 0;
 
-       ss = s;
-       while (*s && isprint(*s))
-               s++;
+       se = s + len;
 
-       /* not zero, or not done yet */
-       if (*s != '\0' || (s + 1 - ss) < len)
-               return 0;
+       while (s < se) {
+               ss = s;
+               while (s < se && *s && isprint((unsigned char)*s))
+                       s++;
+
+               /* not zero, or not done yet */
+               if (*s != '\0' || s == ss)
+                       return 0;
+
+               s++;
+       }
 
        return 1;
 }
@@ -191,7 +198,7 @@ char get_escape_char(const char *s, int *i)
        return val;
 }
 
-int utilfdt_read_err(const char *filename, char **buffp)
+int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
 {
        int fd = 0;     /* assume stdin */
        char *buf = NULL;
@@ -206,16 +213,12 @@ int utilfdt_read_err(const char *filename, char **buffp)
        }
 
        /* Loop until we have read everything */
-       buf = malloc(bufsize);
+       buf = xmalloc(bufsize);
        do {
                /* Expand the buffer to hold the next chunk */
                if (offset == bufsize) {
                        bufsize *= 2;
-                       buf = realloc(buf, bufsize);
-                       if (!buf) {
-                               ret = ENOMEM;
-                               break;
-                       }
+                       buf = xrealloc(buf, bufsize);
                }
 
                ret = read(fd, &buf[offset], bufsize - offset);
@@ -232,13 +235,20 @@ int utilfdt_read_err(const char *filename, char **buffp)
                free(buf);
        else
                *buffp = buf;
+       *len = bufsize;
        return ret;
 }
 
-char *utilfdt_read(const char *filename)
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+       off_t len;
+       return utilfdt_read_err_len(filename, buffp, &len);
+}
+
+char *utilfdt_read_len(const char *filename, off_t *len)
 {
        char *buff;
-       int ret = utilfdt_read_err(filename, &buff);
+       int ret = utilfdt_read_err_len(filename, &buff, len);
 
        if (ret) {
                fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
@@ -249,6 +259,12 @@ char *utilfdt_read(const char *filename)
        return buff;
 }
 
+char *utilfdt_read(const char *filename)
+{
+       off_t len;
+       return utilfdt_read_len(filename, &len);
+}
+
 int utilfdt_write_err(const char *filename, const void *blob)
 {
        int fd = 1;     /* assume stdout */
@@ -329,3 +345,100 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
                return -1;
        return 0;
 }
+
+void utilfdt_print_data(const char *data, int len)
+{
+       int i;
+       const char *p = data;
+       const char *s;
+
+       /* no data, don't print */
+       if (len == 0)
+               return;
+
+       if (util_is_printable_string(data, len)) {
+               printf(" = ");
+
+               s = data;
+               do {
+                       printf("\"%s\"", s);
+                       s += strlen(s) + 1;
+                       if (s < data + len)
+                               printf(", ");
+               } while (s < data + len);
+
+       } else if ((len % 4) == 0) {
+               const uint32_t *cell = (const uint32_t *)data;
+
+               printf(" = <");
+               for (i = 0, len /= 4; i < len; i++)
+                       printf("0x%08x%s", fdt32_to_cpu(cell[i]),
+                              i < (len - 1) ? " " : "");
+               printf(">");
+       } else {
+               printf(" = [");
+               for (i = 0; i < len; i++)
+                       printf("%02x%s", *p++, i < len - 1 ? " " : "");
+               printf("]");
+       }
+}
+
+void util_version(void)
+{
+       printf("Version: %s\n", DTC_VERSION);
+       exit(0);
+}
+
+void util_usage(const char *errmsg, const char *synopsis,
+               const char *short_opts, struct option const long_opts[],
+               const char * const opts_help[])
+{
+       FILE *fp = errmsg ? stderr : stdout;
+       const char a_arg[] = "<arg>";
+       size_t a_arg_len = strlen(a_arg) + 1;
+       size_t i;
+       int optlen;
+
+       fprintf(fp,
+               "Usage: %s\n"
+               "\n"
+               "Options: -[%s]\n", synopsis, short_opts);
+
+       /* prescan the --long opt length to auto-align */
+       optlen = 0;
+       for (i = 0; long_opts[i].name; ++i) {
+               /* +1 is for space between --opt and help text */
+               int l = strlen(long_opts[i].name) + 1;
+               if (long_opts[i].has_arg == a_argument)
+                       l += a_arg_len;
+               if (optlen < l)
+                       optlen = l;
+       }
+
+       for (i = 0; long_opts[i].name; ++i) {
+               /* helps when adding new applets or options */
+               assert(opts_help[i] != NULL);
+
+               /* first output the short flag if it has one */
+               if (long_opts[i].val > '~')
+                       fprintf(fp, "      ");
+               else
+                       fprintf(fp, "  -%c, ", long_opts[i].val);
+
+               /* then the long flag */
+               if (long_opts[i].has_arg == no_argument)
+                       fprintf(fp, "--%-*s", optlen, long_opts[i].name);
+               else
+                       fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
+                               (int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
+
+               /* finally the help text */
+               fprintf(fp, "%s\n", opts_help[i]);
+       }
+
+       if (errmsg) {
+               fprintf(fp, "\nError: %s\n", errmsg);
+               exit(EXIT_FAILURE);
+       } else
+               exit(EXIT_SUCCESS);
+}
index c8eb45d9f04b718d12c8315356960f5d2976779f..f800b6011fb1444ed5a8bd8471c7793b1f40c030 100644 (file)
@@ -2,6 +2,8 @@
 #define _UTIL_H
 
 #include <stdarg.h>
+#include <stdbool.h>
+#include <getopt.h>
 
 /*
  * Copyright 2011 The Chromium Authors, All Rights Reserved.
  *                                                                   USA
  */
 
-static inline void __attribute__((noreturn)) die(char * str, ...)
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static inline void __attribute__((noreturn)) die(const char *str, ...)
 {
        va_list ap;
 
        va_start(ap, str);
        fprintf(stderr, "FATAL ERROR: ");
        vfprintf(stderr, str, ap);
+       va_end(ap);
        exit(1);
 }
 
@@ -57,13 +62,15 @@ extern char *xstrdup(const char *s);
 extern char *join_path(const char *path, const char *name);
 
 /**
- * Check a string of a given length to see if it is all printable and
- * has a valid terminator.
+ * Check a property of a given length to see if it is all printable and
+ * has a valid terminator. The property can contain either a single string,
+ * or multiple strings each of non-zero length.
  *
  * @param data The string to check
  * @param len  The string length including terminator
- * @return 1 if a valid printable string, 0 if not */
-int util_is_printable_string(const void *data, int len);
+ * @return 1 if a valid printable string, 0 if not
+ */
+bool util_is_printable_string(const void *data, int len);
 
 /*
  * Parse an escaped character starting at index i in string s.  The resulting
@@ -82,6 +89,13 @@ char get_escape_char(const char *s, int *i);
  */
 char *utilfdt_read(const char *filename);
 
+/**
+ * Like utilfdt_read(), but also passes back the size of the file read.
+ *
+ * @param len          If non-NULL, the amount of data we managed to read
+ */
+char *utilfdt_read_len(const char *filename, off_t *len);
+
 /**
  * Read a device tree file into a buffer. Does not report errors, but only
  * returns them. The value returned can be passed to strerror() to obtain
@@ -93,6 +107,12 @@ char *utilfdt_read(const char *filename);
  */
 int utilfdt_read_err(const char *filename, char **buffp);
 
+/**
+ * Like utilfdt_read_err(), but also passes back the size of the file read.
+ *
+ * @param len          If non-NULL, the amount of data we managed to read
+ */
+int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len);
 
 /**
  * Write a device tree buffer to a file. This will report any errors on
@@ -148,6 +168,85 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
 #define USAGE_TYPE_MSG \
        "<type>\ts=string, i=int, u=unsigned, x=hex\n" \
        "\tOptional modifier prefix:\n" \
-       "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
+       "\t\thh or b=byte, h=2 byte, l=4 byte (default)";
+
+/**
+ * Print property data in a readable format to stdout
+ *
+ * Properties that look like strings will be printed as strings. Otherwise
+ * the data will be displayed either as cells (if len is a multiple of 4
+ * bytes) or bytes.
+ *
+ * If len is 0 then this function does nothing.
+ *
+ * @param data Pointers to property data
+ * @param len  Length of property data
+ */
+void utilfdt_print_data(const char *data, int len);
+
+/**
+ * Show source version and exit
+ */
+void util_version(void) __attribute__((noreturn));
+
+/**
+ * Show usage and exit
+ *
+ * This helps standardize the output of various utils.  You most likely want
+ * to use the usage() helper below rather than call this.
+ *
+ * @param errmsg       If non-NULL, an error message to display
+ * @param synopsis     The initial example usage text (and possible examples)
+ * @param short_opts   The string of short options
+ * @param long_opts    The structure of long options
+ * @param opts_help    An array of help strings (should align with long_opts)
+ */
+void util_usage(const char *errmsg, const char *synopsis,
+               const char *short_opts, struct option const long_opts[],
+               const char * const opts_help[]) __attribute__((noreturn));
+
+/**
+ * Show usage and exit
+ *
+ * If you name all your usage variables with usage_xxx, then you can call this
+ * help macro rather than expanding all arguments yourself.
+ *
+ * @param errmsg       If non-NULL, an error message to display
+ */
+#define usage(errmsg) \
+       util_usage(errmsg, usage_synopsis, usage_short_opts, \
+                  usage_long_opts, usage_opts_help)
+
+/**
+ * Call getopt_long() with standard options
+ *
+ * Since all util code runs getopt in the same way, provide a helper.
+ */
+#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
+                                      usage_long_opts, NULL)
+
+/* Helper for aligning long_opts array */
+#define a_argument required_argument
+
+/* Helper for usage_short_opts string constant */
+#define USAGE_COMMON_SHORT_OPTS "hV"
+
+/* Helper for usage_long_opts option array */
+#define USAGE_COMMON_LONG_OPTS \
+       {"help",      no_argument, NULL, 'h'}, \
+       {"version",   no_argument, NULL, 'V'}, \
+       {NULL,        no_argument, NULL, 0x0}
+
+/* Helper for usage_opts_help array */
+#define USAGE_COMMON_OPTS_HELP \
+       "Print this help and exit", \
+       "Print version and exit", \
+       NULL
+
+/* Helper for getopt case statements */
+#define case_USAGE_COMMON_FLAGS \
+       case 'h': usage(NULL); \
+       case 'V': util_version(); \
+       case '?': usage("unknown option");
 
 #endif /* _UTIL_H */
index 6158b867df9989cca70d75b5b7b6416073791df4..32fba6d3899e3b6d7c0fb06a72e709d5ab6675e1 100644 (file)
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.2.0-g37c0b6a0"
+#define DTC_VERSION "DTC 1.4.1-ga4b093f7"
index d60c0ee66387d8078055414992ad36d7a2d31fa8..fc68bf6e4889fa861781439226eeaf120db23322 100644 (file)
@@ -152,7 +152,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
                goto out;
 
        /* No partial writes. */
-       length = EINVAL;
+       length = -EINVAL;
        if (*ppos != 0)
                goto out;
 
@@ -1200,7 +1200,7 @@ static void sel_remove_entries(struct dentry *de)
        spin_lock(&de->d_lock);
        node = de->d_subdirs.next;
        while (node != &de->d_subdirs) {
-               struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
+               struct dentry *d = list_entry(node, struct dentry, d_child);
 
                spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
                list_del_init(node);
@@ -1674,12 +1674,12 @@ static void sel_remove_classes(void)
 
        list_for_each(class_node, &class_dir->d_subdirs) {
                struct dentry *class_subdir = list_entry(class_node,
-                                       struct dentry, d_u.d_child);
+                                       struct dentry, d_child);
                struct list_head *class_subdir_node;
 
                list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
                        struct dentry *d = list_entry(class_subdir_node,
-                                               struct dentry, d_u.d_child);
+                                               struct dentry, d_child);
 
                        if (d->d_inode)
                                if (d->d_inode->i_mode & S_IFDIR)
index 98a29b26c5f41d0448177aaab2c0bd561cc70e2b..f2082a35b8905e5f0a234f62a72e9d38eabdae7e 100644 (file)
@@ -1168,6 +1168,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
 
        if (info->count < 1)
                return -EINVAL;
+       if (!*info->id.name)
+               return -EINVAL;
+       if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name))
+               return -EINVAL;
        access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
                (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
                                 SNDRV_CTL_ELEM_ACCESS_INACTIVE|
index 566b0f69d6284be471239086746376175213f0e1..ee240572318813c7e76dee39d7d8022725fb82ea 100644 (file)
@@ -1404,6 +1404,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
                        if (! snd_pcm_playback_empty(substream)) {
                                snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
                                snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
+                       } else {
+                               runtime->status->state = SNDRV_PCM_STATE_SETUP;
                        }
                        break;
                case SNDRV_PCM_STATE_RUNNING:
index 9b9f7d385134253f3e5ceac1e10caa2f21fe06a7..1010ca1c99948b9467e9890ed54d2e233ac4ffb9 100644 (file)
@@ -683,13 +683,8 @@ static int seq_timing_event(unsigned char *event_rec)
                        break;
 
                case TMR_ECHO:
-                       if (seq_mode == SEQ_2)
-                               seq_copy_to_input(event_rec, 8);
-                       else
-                       {
-                               parm = (parm << 8 | SEQ_ECHO);
-                               seq_copy_to_input((unsigned char *) &parm, 4);
-                       }
+                       parm = (parm << 8 | SEQ_ECHO);
+                       seq_copy_to_input((unsigned char *) &parm, 4);
                        break;
 
                default:;
@@ -1330,7 +1325,6 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a
        int mode = translate_mode(file);
        struct synth_info inf;
        struct seq_event_rec event_rec;
-       unsigned long flags;
        int __user *p = arg;
 
        orig_dev = dev = dev >> 4;
@@ -1485,9 +1479,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a
                case SNDCTL_SEQ_OUTOFBAND:
                        if (copy_from_user(&event_rec, arg, sizeof(event_rec)))
                                return -EFAULT;
-                       spin_lock_irqsave(&lock,flags);
                        play_event(event_rec.arr);
-                       spin_unlock_irqrestore(&lock,flags);
                        return 0;
 
                case SNDCTL_MIDI_INFO:
index 9e1bd0c39a8cf27230bd50196a525d1c2c3f525d..6757458e8db6397ead143401666abc997ed0828e 100644 (file)
@@ -181,8 +181,10 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
        }
 #endif
  
-       strcpy(card->driver, emu->card_capabilities->driver);
-       strcpy(card->shortname, emu->card_capabilities->name);
+       strlcpy(card->driver, emu->card_capabilities->driver,
+               sizeof(card->driver));
+       strlcpy(card->shortname, emu->card_capabilities->name,
+               sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                 "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i",
                 card->shortname, emu->revision, emu->serial, emu->port, emu->irq);
index 0a34b5f1c47571b6c30ae5c04f53180b1e76e0ef..f8a6549f00e51a0dc13ecd08603707222b3359c2 100644 (file)
@@ -415,7 +415,7 @@ start_voice(struct snd_emux_voice *vp)
        snd_emu10k1_ptr_write(hw, Z2, ch, 0);
 
        /* invalidate maps */
-       temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK;
+       temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
        snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
 #if 0
@@ -436,7 +436,7 @@ start_voice(struct snd_emux_voice *vp)
                snd_emu10k1_ptr_write(hw, CDF, ch, sample);
 
                /* invalidate maps */
-               temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK;
+               temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
                snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
                snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
                
index bdd888ec9a8422838144fd93e8c8b8cff92ee4fe..a131092572e6f75317008f9793e1c8cfa042dd60 100644 (file)
@@ -282,7 +282,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
        snd_emu10k1_ptr_write(emu, TCB, 0, 0);  /* taken from original driver */
        snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
 
-       silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK;
+       silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        for (ch = 0; ch < NUM_G; ch++) {
                snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page);
                snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
@@ -348,6 +348,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
        }
 
+       if (emu->address_mode == 0) {
+               /* use 16M in 4G */
+               outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG);
+       }
+
        return 0;
 }
 
@@ -1411,7 +1416,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         *
         */
        {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
-        .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]",
+        .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
         .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0108_chip = 1,
@@ -1561,7 +1566,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .adc_1361t = 1,  /* 24 bit capture instead of 16bit */
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
-        .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]",
+        .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]",
         .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
@@ -1865,8 +1870,10 @@ int snd_emu10k1_create(struct snd_card *card,
 
        is_audigy = emu->audigy = c->emu10k2_chip;
 
+       /* set addressing mode */
+       emu->address_mode = is_audigy ? 0 : 1;
        /* set the DMA transfer mask */
-       emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
+       emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK;
        if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
            pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
                snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
@@ -1889,7 +1896,7 @@ int snd_emu10k1_create(struct snd_card *card,
 
        emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-                               32 * 1024, &emu->ptb_pages) < 0) {
+                               (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) {
                err = -ENOMEM;
                goto error;
        }
@@ -1988,8 +1995,8 @@ int snd_emu10k1_create(struct snd_card *card,
 
        /* Clear silent pages and set up pointers */
        memset(emu->silent_page.area, 0, PAGE_SIZE);
-       silent_page = emu->silent_page.addr << 1;
-       for (idx = 0; idx < MAXPAGES; idx++)
+       silent_page = emu->silent_page.addr << emu->address_mode;
+       for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++)
                ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
 
        /* set up voice indices */
index 5ae1d045bdcb5f0bfad786ab3cc527adbeb3bc86..7581019d7c84c7888b7d053085fbff8c688e389c 100644 (file)
@@ -379,7 +379,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
        snd_emu10k1_ptr_write(emu, Z1, voice, 0);
        snd_emu10k1_ptr_write(emu, Z2, voice, 0);
        /* invalidate maps */
-       silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
+       silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
        snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
        /* modulation envelope */
index 2ca9f2e93139e125925c096f3e6163c3e2cd1c87..53745f4c2bf59f136ed664edd4276d8ccf5cfa63 100644 (file)
@@ -241,31 +241,22 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
        struct snd_emu10k1 *emu = entry->private_data;
        u32 value;
        u32 value2;
-       unsigned long flags;
        u32 rate;
 
        if (emu->card_capabilities->emu_model) {
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, 0x38, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                if ((value & 0x1) == 0) {
-                       spin_lock_irqsave(&emu->emu_lock, flags);
                        snd_emu1010_fpga_read(emu, 0x2a, &value);
                        snd_emu1010_fpga_read(emu, 0x2b, &value2);
-                       spin_unlock_irqrestore(&emu->emu_lock, flags);
                        rate = 0x1770000 / (((value << 5) | value2)+1); 
                        snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
                } else {
                        snd_iprintf(buffer, "ADAT Unlocked\n");
                }
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, 0x20, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                if ((value & 0x4) == 0) {
-                       spin_lock_irqsave(&emu->emu_lock, flags);
                        snd_emu1010_fpga_read(emu, 0x28, &value);
                        snd_emu1010_fpga_read(emu, 0x29, &value2);
-                       spin_unlock_irqrestore(&emu->emu_lock, flags);
                        rate = 0x1770000 / (((value << 5) | value2)+1); 
                        snd_iprintf(buffer, "SPDIF Locked : %d\n", rate);
                } else {
@@ -410,14 +401,11 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
 {
        struct snd_emu10k1 *emu = entry->private_data;
        u32 value;
-       unsigned long flags;
        int i;
        snd_iprintf(buffer, "EMU1010 Registers:\n\n");
 
        for(i = 0; i < 0x40; i+=1) {
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, i, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f);
        }
 }
index ae709c1ab3a848e3b954d7e04747d423b30d1e55..d514458efe3dde8b710cf342c39c8a5831635cfe 100644 (file)
  * aligned pages in others
  */
 #define __set_ptb_entry(emu,page,addr) \
-       (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page)))
+       (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page)))
 
 #define UNIT_PAGES             (PAGE_SIZE / EMUPAGESIZE)
-#define MAX_ALIGN_PAGES                (MAXPAGES / UNIT_PAGES)
+#define MAX_ALIGN_PAGES0               (MAXPAGES0 / UNIT_PAGES)
+#define MAX_ALIGN_PAGES1               (MAXPAGES1 / UNIT_PAGES)
 /* get aligned page from offset address */
 #define get_aligned_page(offset)       ((offset) >> PAGE_SHIFT)
 /* get offset address from aligned page */
@@ -124,7 +125,7 @@ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct lis
                }
                page = blk->mapped_page + blk->pages;
        }
-       size = MAX_ALIGN_PAGES - page;
+       size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page;
        if (size >= max_size) {
                *nextp = pos;
                return page;
@@ -181,7 +182,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
                q = get_emu10k1_memblk(p, mapped_link);
                end_page = q->mapped_page;
        } else
-               end_page = MAX_ALIGN_PAGES;
+               end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0);
 
        /* remove links */
        list_del(&blk->mapped_link);
@@ -305,7 +306,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst
        if (snd_BUG_ON(!emu))
                return NULL;
        if (snd_BUG_ON(runtime->dma_bytes <= 0 ||
-                      runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE))
+                      runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE))
                return NULL;
        hdr = emu->memhdr;
        if (snd_BUG_ON(!hdr))
index f6e5c4ed03ed5e2a270e8011cf4f1811fe276cc5..97ebc105cf3c32d494c486e31544a4a67c28f420 100644 (file)
@@ -2082,6 +2082,16 @@ static void put_vol_mute(struct hda_codec *codec, unsigned int amp_caps,
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
 }
 
+/* meta hook to call each driver's vmaster hook */
+static void vmaster_hook(void *private_data, int enabled)
+{
+       struct hda_vmaster_mute_hook *hook = private_data;
+
+       if (hook->mute_mode != HDA_VMUTE_FOLLOW_MASTER)
+               enabled = hook->mute_mode;
+       hook->hook(hook->codec, enabled);
+}
+
 /**
  * snd_hda_codec_amp_read - Read AMP value
  * @codec: HD-audio codec
@@ -2917,9 +2927,9 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec,
 
        if (!hook->hook || !hook->sw_kctl)
                return 0;
-       snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec);
        hook->codec = codec;
        hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+       snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook);
        if (!expose_enum_ctl)
                return 0;
        kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
@@ -2942,14 +2952,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
         */
        if (hook->codec->bus->shutdown)
                return;
-       switch (hook->mute_mode) {
-       case HDA_VMUTE_FOLLOW_MASTER:
-               snd_ctl_sync_vmaster_hook(hook->sw_kctl);
-               break;
-       default:
-               hook->hook(hook->codec, hook->mute_mode);
-               break;
-       }
+       snd_ctl_sync_vmaster_hook(hook->sw_kctl);
 }
 EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook);
 
index d9a09bdd09db656891aa51f910753b686dc79964..9a23bdea97d8404736ac6141601666b67b975a5c 100644 (file)
@@ -653,12 +653,45 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
        return val;
 }
 
+/* is this a stereo widget or a stereo-to-mono mix? */
+static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
+{
+       unsigned int wcaps = get_wcaps(codec, nid);
+       hda_nid_t conn;
+
+       if (wcaps & AC_WCAP_STEREO)
+               return true;
+       if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
+               return false;
+       if (snd_hda_get_num_conns(codec, nid) != 1)
+               return false;
+       if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
+               return false;
+       return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
+}
+
 /* initialize the amp value (only at the first time) */
 static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
 {
        unsigned int caps = query_amp_caps(codec, nid, dir);
        int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
-       snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
+
+       if (is_stereo_amps(codec, nid, dir))
+               snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
+       else
+               snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
+}
+
+/* update the amp, doing in stereo or mono depending on NID */
+static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
+                     unsigned int mask, unsigned int val)
+{
+       if (is_stereo_amps(codec, nid, dir))
+               return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
+                                               mask, val);
+       else
+               return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
+                                               mask, val);
 }
 
 /* calculate amp value mask we can modify;
@@ -698,7 +731,7 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
                return;
 
        val &= mask;
-       snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
+       update_amp(codec, nid, dir, idx, mask, val);
 }
 
 static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
@@ -4337,13 +4370,11 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
        has_amp = nid_has_mute(codec, mix, HDA_INPUT);
        for (i = 0; i < nums; i++) {
                if (has_amp)
-                       snd_hda_codec_amp_stereo(codec, mix,
-                                                HDA_INPUT, i,
-                                                0xff, HDA_AMP_MUTE);
+                       update_amp(codec, mix, HDA_INPUT, i,
+                                  0xff, HDA_AMP_MUTE);
                else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
-                       snd_hda_codec_amp_stereo(codec, conn[i],
-                                                HDA_OUTPUT, 0,
-                                                0xff, HDA_AMP_MUTE);
+                       update_amp(codec, conn[i], HDA_OUTPUT, 0,
+                                  0xff, HDA_AMP_MUTE);
        }
 }
 
index 103e85a13f35574485a2ac190f960056e50c90e6..84e8879cc372efc80a7e24c3810ff85893c2f0c9 100644 (file)
@@ -959,7 +959,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
                }
        }
 
-       if (!bus->no_response_fallback)
+       if (bus->no_response_fallback)
                return -1;
 
        if (!chip->polling_mode && chip->poll_count < 2) {
@@ -3984,7 +3984,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* Panther Point */
        { PCI_DEVICE(0x8086, 0x1e20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
index ce5a6da834199bd2acd7e6ee18fd123b4f078820..05e19f78b4cb8689ff8ac1b0b4f699bdbf5759da 100644 (file)
@@ -134,13 +134,38 @@ static void print_amp_caps(struct snd_info_buffer *buffer,
                    (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
 }
 
+/* is this a stereo widget or a stereo-to-mono mix? */
+static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid,
+                          int dir, unsigned int wcaps, int indices)
+{
+       hda_nid_t conn;
+
+       if (wcaps & AC_WCAP_STEREO)
+               return true;
+       /* check for a stereo-to-mono mix; it must be:
+        * only a single connection, only for input, and only a mixer widget
+        */
+       if (indices != 1 || dir != HDA_INPUT ||
+           get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
+               return false;
+
+       if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0)
+               return false;
+       /* the connection source is a stereo? */
+       wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP);
+       return !!(wcaps & AC_WCAP_STEREO);
+}
+
 static void print_amp_vals(struct snd_info_buffer *buffer,
                           struct hda_codec *codec, hda_nid_t nid,
-                          int dir, int stereo, int indices)
+                          int dir, unsigned int wcaps, int indices)
 {
        unsigned int val;
+       bool stereo;
        int i;
 
+       stereo = is_stereo_amps(codec, nid, dir, wcaps, indices);
+
        dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
        for (i = 0; i < indices; i++) {
                snd_iprintf(buffer, " [");
@@ -757,12 +782,10 @@ static void print_codec_info(struct snd_info_entry *entry,
                            (codec->single_adc_amp &&
                             wid_type == AC_WID_AUD_IN))
                                print_amp_vals(buffer, codec, nid, HDA_INPUT,
-                                              wid_caps & AC_WCAP_STEREO,
-                                              1);
+                                              wid_caps, 1);
                        else
                                print_amp_vals(buffer, codec, nid, HDA_INPUT,
-                                              wid_caps & AC_WCAP_STEREO,
-                                              conn_len);
+                                              wid_caps, conn_len);
                }
                if (wid_caps & AC_WCAP_OUT_AMP) {
                        snd_iprintf(buffer, "  Amp-Out caps: ");
@@ -771,11 +794,10 @@ static void print_codec_info(struct snd_info_entry *entry,
                        if (wid_type == AC_WID_PIN &&
                            codec->pin_amp_workaround)
                                print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
-                                              wid_caps & AC_WCAP_STEREO,
-                                              conn_len);
+                                              wid_caps, conn_len);
                        else
                                print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
-                                              wid_caps & AC_WCAP_STEREO, 1);
+                                              wid_caps, 1);
                }
 
                switch (wid_type) {
index fc492ac24caa917c9d3670a37f83cb1d3e0bca95..51e208022cc81e2885282ec8b43412a2d7b903b3 100644 (file)
@@ -396,6 +396,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81),
        SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
        SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101),
+       SND_PCI_QUIRK(0x106b, 0x5600, "MacBookAir 5,2", CS420X_MBP81),
        SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42),
        SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
        {} /* terminator */
@@ -587,6 +588,7 @@ static int patch_cs420x(struct hda_codec *codec)
                return -ENOMEM;
 
        spec->gen.automute_hook = cs_automute;
+       codec->single_adc_amp = 1;
 
        snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl,
                           cs420x_fixups);
index ffc19464b978a64dcd071cc57a4af27207b78dae..976493c4a695269892130b48865bffffb7d24be1 100644 (file)
@@ -3232,6 +3232,7 @@ enum {
        CXT_PINCFG_LENOVO_TP410,
        CXT_PINCFG_LEMOTE_A1004,
        CXT_PINCFG_LEMOTE_A1205,
+       CXT_PINCFG_COMPAQ_CQ60,
        CXT_FIXUP_STEREO_DMIC,
        CXT_FIXUP_INC_MIC_BOOST,
        CXT_FIXUP_HEADPHONE_MIC_PIN,
@@ -3368,6 +3369,15 @@ static const struct hda_fixup cxt_fixups[] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = cxt_pincfg_lemote,
        },
+       [CXT_PINCFG_COMPAQ_CQ60] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       /* 0x17 was falsely set up as a mic, it should 0x1d */
+                       { 0x17, 0x400001f0 },
+                       { 0x1d, 0x97a70120 },
+                       { }
+               }
+       },
        [CXT_FIXUP_STEREO_DMIC] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cxt_fixup_stereo_dmic,
@@ -3411,6 +3421,7 @@ static const struct hda_fixup cxt_fixups[] = {
 };
 
 static const struct snd_pci_quirk cxt5051_fixups[] = {
+       SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
        {}
 };
index 910f2dbe1b2406bb15e00e3921799c2887dd39dd..ca26373ebe70c6b9cb41cebb27bec7e84c2cafe8 100644 (file)
@@ -271,7 +271,7 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
 {
        /* We currently only handle front, HP */
        static hda_nid_t pins[] = {
-               0x0f, 0x10, 0x14, 0x15, 0
+               0x0f, 0x10, 0x14, 0x15, 0x17, 0
        };
        hda_nid_t *p;
        for (p = pins; *p; p++)
@@ -2885,6 +2885,8 @@ static void alc283_init(struct hda_codec *codec)
 
        if (!hp_pin)
                return;
+
+       msleep(30);
        hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 
        /* Index 0x43 Direct Drive HP AMP LPM Control 1 */
@@ -3951,6 +3953,7 @@ enum {
        ALC269_FIXUP_QUANTA_MUTE,
        ALC269_FIXUP_LIFEBOOK,
        ALC269_FIXUP_LIFEBOOK_EXTMIC,
+       ALC269_FIXUP_LIFEBOOK_HP_PIN,
        ALC269_FIXUP_AMIC,
        ALC269_FIXUP_DMIC,
        ALC269VB_FIXUP_AMIC,
@@ -4085,6 +4088,13 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                },
        },
+       [ALC269_FIXUP_LIFEBOOK_HP_PIN] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x21, 0x0221102f }, /* HP out */
+                       { }
+               },
+       },
        [ALC269_FIXUP_AMIC] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -4538,6 +4548,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
+       SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN),
        SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
index 12f28d7e0fdcac3ab72da550586a8e37436c7e62..231b26471a638c002dc0466937e2800c3ccb2a9d 100644 (file)
@@ -85,6 +85,7 @@ enum {
        STAC_ALIENWARE_M17X,
        STAC_92HD89XX_HP_FRONT_JACK,
        STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK,
+       STAC_92HD73XX_ASUS_MOBO,
        STAC_92HD73XX_MODELS
 };
 
@@ -1935,7 +1936,18 @@ static const struct hda_fixup stac92hd73xx_fixups[] = {
        [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs,
-       }
+       },
+       [STAC_92HD73XX_ASUS_MOBO] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       /* enable 5.1 and SPDIF out */
+                       { 0x0c, 0x01014411 },
+                       { 0x0d, 0x01014410 },
+                       { 0x0e, 0x01014412 },
+                       { 0x22, 0x014b1180 },
+                       { }
+               }
+       },
 };
 
 static const struct hda_model_fixup stac92hd73xx_models[] = {
@@ -1947,6 +1959,7 @@ static const struct hda_model_fixup stac92hd73xx_models[] = {
        { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" },
        { .id = STAC_DELL_EQ, .name = "dell-eq" },
        { .id = STAC_ALIENWARE_M17X, .name = "alienware" },
+       { .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" },
        {}
 };
 
@@ -1999,6 +2012,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
                                "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
                                "unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_ASUSTEK, 0x83f8, "ASUS AT4NM10",
+                     STAC_92HD73XX_ASUS_MOBO),
        {} /* terminator */
 };
 
index 8fe3b8c18ed4b2c25c00b4963ec766b7671829d9..1eafc1a281930532ba5110316d7c4fc69c461b08 100644 (file)
@@ -71,6 +71,7 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
                if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
                        old_vmaster_hook = spec->vmaster_mute.hook;
                        spec->vmaster_mute.hook = update_tpacpi_mute_led;
+                       spec->vmaster_mute_enum = 1;
                        removefunc = false;
                }
                if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
index f78b27a7c461d3e5580dad311fd583f30755a3b4..23454e9a5d3a3ec821fc4c42771903970d77662e 100644 (file)
@@ -319,7 +319,7 @@ static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
-       unsigned int deemph = ucontrol->value.enumerated.item[0];
+       unsigned int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
@@ -335,7 +335,7 @@ static int adav80x_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = adav80x->deemph;
+       ucontrol->value.integer.value[0] = adav80x->deemph;
        return 0;
 };
 
index 94cbe508dd3748723197f7443f5a6ed8524b2b14..d7184726f8a044a65ec12973edcb39decc11a696 100644 (file)
@@ -76,7 +76,7 @@ static int ak4641_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
@@ -92,7 +92,7 @@ static int ak4641_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = ak4641->deemph;
+       ucontrol->value.integer.value[0] = ak4641->deemph;
        return 0;
 };
 
index ce05fd93dc748c3cc8e1405b1d50296f5e9780e3..a0ad41ac55749061e90369d301ff842a087dd659 100644 (file)
@@ -288,7 +288,7 @@ static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = cs4271->deemph;
+       ucontrol->value.integer.value[0] = cs4271->deemph;
        return 0;
 }
 
@@ -298,7 +298,7 @@ static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
 
-       cs4271->deemph = ucontrol->value.enumerated.item[0];
+       cs4271->deemph = ucontrol->value.integer.value[0];
        return cs4271_set_deemph(codec);
 }
 
index 73f9c3630e2c8e33a56b089fa3a0d5f16e418dd3..651e2fe2c31fcfa235158f00c1463b91eca78489 100644 (file)
@@ -118,7 +118,7 @@ static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = priv->deemph;
+       ucontrol->value.integer.value[0] = priv->deemph;
 
        return 0;
 }
@@ -129,7 +129,7 @@ static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec);
 
-       priv->deemph = ucontrol->value.enumerated.item[0];
+       priv->deemph = ucontrol->value.integer.value[0];
 
        return pcm1681_set_deemph(codec);
 }
index 715589ff0eda8e2788d341c6badb2911b82be3d1..e93c36fd3073c49dad68bc270fab0a46dd8fa9b9 100644 (file)
@@ -1198,13 +1198,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
                /* Enable VDDC charge pump */
                ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP;
        } else if (vddio >= 3100 && vdda >= 3100) {
-               /*
-                * if vddio and vddd > 3.1v,
-                * charge pump should be clean before set ana_pwr
-                */
-               snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
-                               SGTL5000_VDDC_CHRGPMP_POWERUP, 0);
-
+               ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP;
                /* VDDC use VDDIO rail */
                lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
                lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO <<
index a895a5e4bdf207eee6387bc00e8452ae2385233d..c6c65001457de10c09f19cbe3dce44d929aab27c 100644 (file)
@@ -275,7 +275,7 @@ static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = priv->deemph;
+       ucontrol->value.integer.value[0] = priv->deemph;
 
        return 0;
 }
@@ -286,7 +286,7 @@ static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
 
-       priv->deemph = ucontrol->value.enumerated.item[0];
+       priv->deemph = ucontrol->value.integer.value[0];
 
        return tas5086_set_deemph(codec);
 }
index 8ae50274ea8f12f275938e2cdab2c836db1f687e..1a9f4574b65b9ed607fc56e911f997d2224b2ad0 100644 (file)
@@ -610,7 +610,7 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
-       ucontrol->value.enumerated.item[0] = wm2000->anc_active;
+       ucontrol->value.integer.value[0] = wm2000->anc_active;
 
        return 0;
 }
@@ -620,7 +620,7 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
-       int anc_active = ucontrol->value.enumerated.item[0];
+       int anc_active = ucontrol->value.integer.value[0];
        int ret;
 
        if (anc_active > 1)
@@ -643,7 +643,7 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
-       ucontrol->value.enumerated.item[0] = wm2000->spk_ena;
+       ucontrol->value.integer.value[0] = wm2000->spk_ena;
 
        return 0;
 }
@@ -653,7 +653,7 @@ static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
-       int val = ucontrol->value.enumerated.item[0];
+       int val = ucontrol->value.integer.value[0];
        int ret;
 
        if (val > 1)
index 029720366ff8f65f7d6b208216f7cba64b6523af..e593722574de1226286709386892760091efda58 100644 (file)
@@ -122,7 +122,7 @@ static int wm8731_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8731->deemph;
+       ucontrol->value.integer.value[0] = wm8731->deemph;
 
        return 0;
 }
@@ -132,7 +132,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
        int ret = 0;
 
        if (deemph > 1)
index eebcb1da3b7b10769f0e265f95c90a6638266f71..ae7d76efe06303986133129ac2ac2d2e56eb01fb 100644 (file)
@@ -442,7 +442,7 @@ static int wm8903_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8903->deemph;
+       ucontrol->value.integer.value[0] = wm8903->deemph;
 
        return 0;
 }
@@ -452,7 +452,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
        int ret = 0;
 
        if (deemph > 1)
index 53bbfac6a83ad14ed43d2aafca2514ea3a319468..66cb9e95b5eb696858ace317be059c5975658dc0 100644 (file)
@@ -523,7 +523,7 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8904->deemph;
+       ucontrol->value.integer.value[0] = wm8904->deemph;
        return 0;
 }
 
@@ -532,7 +532,7 @@ static int wm8904_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
index 82c8ba9757202402cfe53e44b0a7dd587df502b5..1c1fc6119758e993f3c381137978f7295ec40082 100644 (file)
@@ -393,7 +393,7 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8955->deemph;
+       ucontrol->value.integer.value[0] = wm8955->deemph;
        return 0;
 }
 
@@ -402,7 +402,7 @@ static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
index 942ef8427347d3e2e6c85a3d8cb35d203e221fc5..2a0bfb848512f661d38b9ab4805ef97a2e65277b 100644 (file)
@@ -181,7 +181,7 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = wm8960->deemph;
+       ucontrol->value.integer.value[0] = wm8960->deemph;
        return 0;
 }
 
@@ -190,7 +190,7 @@ static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
-       int deemph = ucontrol->value.enumerated.item[0];
+       int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
index b9010c91b4e63439831e094cd6ea2c8831acbab2..19b2bff109076b10b9f8a80ef7023ae039c5794a 100644 (file)
@@ -49,37 +49,6 @@ static int evm_startup(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int dra7xx_evm_startup(struct snd_pcm_substream *substream)
-{
-       snd_pcm_hw_constraint_minmax(substream->runtime,
-                                    SNDRV_PCM_HW_PARAM_RATE, 44100, 44100);
-
-       return evm_startup(substream);
-}
-
-static int dra7xx_evm_hw_params(struct snd_pcm_substream *substream,
-                                    struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_card *soc_card = rtd->card;
-       struct snd_soc_card_drvdata_davinci *drvdata =
-               snd_soc_card_get_drvdata(soc_card);
-       int ret;
-
-       /* Set MCLK as clock source for tlv320aic3106 */
-       ret = snd_soc_dai_set_sysclk(codec_dai, 0, drvdata->sysclk,
-                                    SND_SOC_CLOCK_IN);
-       if (ret < 0)
-               return ret;
-
-       /* Set McASP sysclk from AHCLKX sourced from ATL */
-       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, drvdata->sysclk,
-                                    SND_SOC_CLOCK_IN);
-       return ret;
-}
-
 static void evm_shutdown(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -123,25 +92,13 @@ static int evm_tda998x_startup(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_mask *fmt = constrs_mask(&runtime->hw_constraints,
                                            SNDRV_PCM_HW_PARAM_FORMAT);
+
        snd_mask_none(fmt);
        snd_mask_set(fmt, TDA998X_SAMPLE_FORMAT);
 
        return evm_startup(substream);
 }
 
-static int evm_tda998x_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_card *soc_card = rtd->card;
-       struct snd_soc_card_drvdata_davinci *drvdata =
-               snd_soc_card_get_drvdata(soc_card);
-
-       return snd_soc_dai_set_sysclk(cpu_dai, 0, drvdata->sysclk,
-                                     SND_SOC_CLOCK_IN);
-}
-
 static struct snd_soc_ops evm_ops = {
        .startup = evm_startup,
        .shutdown = evm_shutdown,
@@ -152,13 +109,11 @@ static struct snd_soc_ops evm_ops = {
 static struct snd_soc_ops evm_tda998x_ops = {
        .startup = evm_tda998x_startup,
        .shutdown = evm_shutdown,
-       .hw_params = evm_tda998x_hw_params,
 };
 
 static struct snd_soc_ops dra7xx_ops = {
-       .startup = dra7xx_evm_startup,
+       .startup = evm_startup,
        .shutdown = evm_shutdown,
-       .hw_params = dra7xx_evm_hw_params,
 };
 
 /* davinci-evm machine dapm widgets */
@@ -221,6 +176,30 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
+/* Logic for a dra7xx-evm */
+static int evm_dra7xx_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_card *card = rtd->card;
+       struct snd_soc_card_drvdata_davinci *drvdata =
+               snd_soc_card_get_drvdata(card);
+       int ret;
+
+       /* Set MCLK as clock source for tlv320aic3106 */
+       ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, drvdata->sysclk,
+                                    SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       /* Set McASP sysclk from AHCLKX sourced from ATL */
+       ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, drvdata->sysclk,
+                                    SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       /* davinci-evm specific widgets work with dra7xx too */
+       return evm_aic3x_init(rtd);
+}
+
 static const struct snd_soc_dapm_widget tda998x_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("HDMI Out"),
 };
@@ -230,12 +209,19 @@ static int evm_tda998x_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dapm_context *dapm = &rtd->codec->dapm;
        struct snd_soc_card *soc_card = rtd->card;
+       struct snd_soc_card_drvdata_davinci *drvdata =
+               snd_soc_card_get_drvdata(soc_card);
        int ret;
 
        ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 1);
        if (ret < 0)
                return ret;
 
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, drvdata->sysclk,
+                                    SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
        snd_soc_dapm_new_controls(dapm, tda998x_dapm_widgets,
                                  ARRAY_SIZE(tda998x_dapm_widgets));
 
@@ -463,7 +449,7 @@ static struct snd_soc_dai_link dra7xx_evm_link = {
        .stream_name    = "AIC3X",
        .codec_dai_name = "tlv320aic3x-hifi",
        .ops            = &dra7xx_ops,
-       .init           = evm_aic3x_init,
+       .init           = evm_dra7xx_init,
        .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS |
                   SND_SOC_DAIFMT_IB_NF,
 };
@@ -562,18 +548,8 @@ static int davinci_evm_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int davinci_evm_remove(struct platform_device *pdev)
-{
-       struct snd_soc_card *card = platform_get_drvdata(pdev);
-
-       snd_soc_unregister_card(card);
-
-       return 0;
-}
-
 static struct platform_driver davinci_evm_driver = {
        .probe          = davinci_evm_probe,
-       .remove         = davinci_evm_remove,
        .driver         = {
                .name   = "davinci_evm",
                .owner  = THIS_MODULE,
index eeb51f9d478f2f558ae01c08458a3af1b2aa7c47..c40ed33cf21fb112b37b1b00698f430a2ff27729 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
+#include <linux/math64.h>
 
 #include <sound/asoundef.h>
 #include <sound/core.h>
@@ -59,6 +60,13 @@ struct davinci_mcasp_context {
        u32     rfifoctl;
        u32     wfifoctl;
        u32     *xrsrctl;
+
+       bool    pm_state;
+};
+
+struct davinci_mcasp_ruledata {
+       struct davinci_mcasp *mcasp;
+       int serializers;
 };
 
 struct davinci_mcasp {
@@ -94,6 +102,13 @@ struct davinci_mcasp {
 #ifdef CONFIG_PM_SLEEP
        struct davinci_mcasp_context context;
 #endif
+
+       struct davinci_mcasp_ruledata ruledata[2];
+       struct snd_pcm_hw_constraint_list chconstr[2];
+#if IS_ENABLED(CONFIG_DISPLAY_DRA7EVM_ENCODER_TPD12S015)
+       bool    is_mcasp8;
+       u8      hdmi_sel_gpio;
+#endif
 };
 
 static inline void mcasp_set_bits(struct davinci_mcasp *mcasp, u32 offset,
@@ -461,7 +476,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
        }
 out:
-       pm_runtime_put_sync(mcasp->dev);
+       pm_runtime_put(mcasp->dev);
        return ret;
 }
 
@@ -470,6 +485,7 @@ static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
 {
        struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
 
+       pm_runtime_get_sync(mcasp->dev);
        switch (div_id) {
        case 0:         /* MCLK divider */
                mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
@@ -495,6 +511,7 @@ static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
                return -EINVAL;
        }
 
+       pm_runtime_put(mcasp->dev);
        return 0;
 }
 
@@ -509,6 +526,7 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 {
        struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
 
+       pm_runtime_get_sync(mcasp->dev);
        if (dir == SND_SOC_CLOCK_OUT) {
                mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
                mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
@@ -521,6 +539,7 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 
        mcasp->sysclk_freq = freq;
 
+       pm_runtime_put(mcasp->dev);
        return 0;
 }
 
@@ -809,6 +828,30 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
        return 0;
 }
 
+static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp,
+                                     unsigned int bclk_freq,
+                                     int *error_ppm)
+{
+       int div = mcasp->sysclk_freq / bclk_freq;
+       int rem = mcasp->sysclk_freq % bclk_freq;
+
+       if (rem != 0) {
+               if (div == 0 ||
+                   ((mcasp->sysclk_freq / div) - bclk_freq) >
+                   (bclk_freq - (mcasp->sysclk_freq / (div+1)))) {
+                       div++;
+                       rem = rem - bclk_freq;
+               }
+       }
+       if (error_ppm)
+               *error_ppm =
+                       (div*1000000 + (int)div64_long(1000000LL*rem,
+                                                      (int)bclk_freq))
+                       /div - 1000000;
+
+       return div;
+}
+
 static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                                        struct snd_pcm_hw_params *params,
                                        struct snd_soc_dai *cpu_dai)
@@ -826,16 +869,17 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
         * the machine driver, we need to calculate the ratio.
         */
        if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
-               unsigned int bclk_freq = snd_soc_params_to_bclk(params);
-               unsigned int div = mcasp->sysclk_freq / bclk_freq;
-               if (mcasp->sysclk_freq % bclk_freq != 0) {
-                       if (((mcasp->sysclk_freq / div) - bclk_freq) >
-                           (bclk_freq - (mcasp->sysclk_freq / (div+1))))
-                               div++;
-                       dev_warn(mcasp->dev,
-                                "Inaccurate BCLK: %u Hz / %u != %u Hz\n",
-                                mcasp->sysclk_freq, div, bclk_freq);
-               }
+               int slots = mcasp->tdm_slots;
+               int rate = params_rate(params);
+               int sbits = params_width(params);
+               int ppm, div;
+
+               div = davinci_mcasp_calc_clk_div(mcasp, rate*sbits*slots,
+                                                &ppm);
+               if (ppm)
+                       dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n",
+                                ppm);
+
                __davinci_mcasp_set_clkdiv(cpu_dai, 1, div, 0);
        }
 
@@ -927,10 +971,89 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static const unsigned int davinci_mcasp_dai_rates[] = {
+       8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
+       88200, 96000, 176400, 192000,
+};
+
+#define DAVINCI_MAX_RATE_ERROR_PPM 1000
+
+static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params,
+                                     struct snd_pcm_hw_rule *rule)
+{
+       struct davinci_mcasp_ruledata *rd = rule->private;
+       struct snd_interval *ri =
+               hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+       int sbits = params_width(params);
+       int slots = rd->mcasp->tdm_slots;
+       struct snd_interval range;
+       int i;
+
+       snd_interval_any(&range);
+       range.empty = 1;
+
+       for (i = 0; i < ARRAY_SIZE(davinci_mcasp_dai_rates); i++) {
+               if (snd_interval_test(ri, davinci_mcasp_dai_rates[i])) {
+                       uint bclk_freq = sbits*slots*
+                               davinci_mcasp_dai_rates[i];
+                       int ppm;
+
+                       davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, &ppm);
+                       if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {
+                               if (range.empty) {
+                                       range.min = davinci_mcasp_dai_rates[i];
+                                       range.empty = 0;
+                               }
+                               range.max = davinci_mcasp_dai_rates[i];
+                       }
+               }
+       }
+
+       dev_dbg(rd->mcasp->dev,
+               "Frequencies %d-%d -> %d-%d for %d sbits and %d tdm slots\n",
+               ri->min, ri->max, range.min, range.max, sbits, slots);
+
+       return snd_interval_refine(hw_param_interval(params, rule->var),
+                                  &range);
+}
+
+static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
+                                       struct snd_pcm_hw_rule *rule)
+{
+       struct davinci_mcasp_ruledata *rd = rule->private;
+       struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_mask nfmt;
+       int rate = params_rate(params);
+       int slots = rd->mcasp->tdm_slots;
+       int i, count = 0;
+
+       snd_mask_none(&nfmt);
+
+       for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
+               if (snd_mask_test(fmt, i)) {
+                       uint bclk_freq = snd_pcm_format_width(i)*slots*rate;
+                       int ppm;
+
+                       davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, &ppm);
+                       if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {
+                               snd_mask_set(&nfmt, i);
+                               count++;
+                       }
+               }
+       }
+       dev_dbg(rd->mcasp->dev,
+               "%d possible sample format for %d Hz and %d tdm slots\n",
+               count, rate, slots);
+
+       return snd_mask_refine(fmt, &nfmt);
+}
+
 static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *cpu_dai)
 {
        struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+       struct davinci_mcasp_ruledata *ruledata =
+                                       &mcasp->ruledata[substream->stream];
        u32 max_channels = 0;
        int i, dir;
 
@@ -952,6 +1075,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
                if (mcasp->serial_dir[i] == dir)
                        max_channels++;
        }
+       ruledata->serializers = max_channels;
        max_channels *= mcasp->tdm_slots;
        /*
         * If the already active stream has less channels than the calculated
@@ -966,6 +1090,37 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
        snd_pcm_hw_constraint_minmax(substream->runtime,
                                     SNDRV_PCM_HW_PARAM_CHANNELS,
                                     2, max_channels);
+
+       if (mcasp->chconstr[substream->stream].count)
+               snd_pcm_hw_constraint_list(substream->runtime,
+                                          0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                                          &mcasp->chconstr[substream->stream]);
+
+       /*
+        * If we rely on implicit BCLK divider setting we should
+        * set constraints based on what we can provide.
+        */
+       if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
+               int ret;
+
+               ruledata->mcasp = mcasp;
+
+               ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                         SNDRV_PCM_HW_PARAM_RATE,
+                                         davinci_mcasp_hw_rule_rate,
+                                         ruledata,
+                                         SNDRV_PCM_HW_PARAM_FORMAT, -1);
+               if (ret)
+                       return ret;
+               ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+                                         SNDRV_PCM_HW_PARAM_FORMAT,
+                                         davinci_mcasp_hw_rule_format,
+                                         ruledata,
+                                         SNDRV_PCM_HW_PARAM_RATE, -1);
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
@@ -1020,6 +1175,10 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
        int i;
        u32 reg;
 
+       context->pm_state = pm_runtime_active(mcasp->dev);
+       if (!context->pm_state)
+               pm_runtime_get_sync(mcasp->dev);
+
        context->txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG);
        context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
        context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG);
@@ -1045,6 +1204,7 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
                context->xrsrctl[i] = mcasp_get_reg(mcasp,
                                                DAVINCI_MCASP_XRSRCTL_REG(i));
 
+       pm_runtime_put_sync(mcasp->dev);
        return 0;
 }
 
@@ -1055,6 +1215,7 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai)
        int i;
        u32 reg;
 
+       pm_runtime_get_sync(mcasp->dev);
        mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, context->txfmtctl);
        mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl);
        mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt);
@@ -1080,6 +1241,9 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai)
                mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
                              context->xrsrctl[i]);
 
+       if (!context->pm_state)
+               pm_runtime_put_sync(mcasp->dev);
+
        return 0;
 }
 #else
@@ -1337,6 +1501,154 @@ nodata:
        return  pdata;
 }
 
+/* All serializers must have equal number of channels */
+static int davinci_mcasp_ch_constraint(struct davinci_mcasp *mcasp,
+                                      struct snd_pcm_hw_constraint_list *cl,
+                                      int serializers)
+{
+       unsigned int *list;
+       int i, count = 0;
+
+       if (serializers <= 1)
+               return 0;
+
+       list = devm_kzalloc(mcasp->dev, sizeof(unsigned int) *
+                           (mcasp->tdm_slots + serializers - 2),
+                           GFP_KERNEL);
+       if (!list)
+               return -ENOMEM;
+
+       for (i = 2; i <= mcasp->tdm_slots; i++)
+               list[count++] = i;
+
+       for (i = 2; i <= serializers; i++)
+               list[count++] = i*mcasp->tdm_slots;
+
+       cl->count = count;
+       cl->list = list;
+
+       return 0;
+}
+
+
+static int davinci_mcasp_init_ch_constraints(struct davinci_mcasp *mcasp)
+{
+       int rx_serializers = 0, tx_serializers = 0, ret, i;
+
+       for (i = 0; i < mcasp->num_serializer; i++)
+               if (mcasp->serial_dir[i] == TX_MODE)
+                       tx_serializers++;
+               else if (mcasp->serial_dir[i] == RX_MODE)
+                       rx_serializers++;
+
+       ret = davinci_mcasp_ch_constraint(mcasp, &mcasp->chconstr[
+                                                 SNDRV_PCM_STREAM_PLAYBACK],
+                                         tx_serializers);
+       if (ret)
+               return ret;
+
+       ret = davinci_mcasp_ch_constraint(mcasp, &mcasp->chconstr[
+                                                 SNDRV_PCM_STREAM_CAPTURE],
+                                         rx_serializers);
+
+       return ret;
+}
+
+#if IS_ENABLED(CONFIG_DISPLAY_DRA7EVM_ENCODER_TPD12S015)
+#define DRA7_MCASP_HDMI_SEL_GPIO       (1 << 2)
+int dra7_mcasp_hdmi_gpio_get(struct platform_device *pdev)
+{
+       struct davinci_mcasp *mcasp;
+
+       if (!pdev)
+               return -EPROBE_DEFER;
+
+       mcasp = dev_get_drvdata(&pdev->dev);
+       if (!mcasp)
+               return -EPROBE_DEFER;
+
+       if (!mcasp->is_mcasp8)
+               return 0;
+
+       pm_runtime_get_sync(mcasp->dev);
+
+       /* First set the direction to output */
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG,
+                      DRA7_MCASP_HDMI_SEL_GPIO);
+       /* then set the PDOUT */
+       if (mcasp->hdmi_sel_gpio)
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG,
+                              DRA7_MCASP_HDMI_SEL_GPIO);
+       else
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG,
+                              DRA7_MCASP_HDMI_SEL_GPIO);
+       /* at last, change the function to GPIO mode */
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_PFUNC_REG,
+                      DRA7_MCASP_HDMI_SEL_GPIO);
+
+       return 0;
+}
+EXPORT_SYMBOL(dra7_mcasp_hdmi_gpio_get);
+
+int dra7_mcasp_hdmi_gpio_put(struct platform_device *pdev)
+{
+       struct davinci_mcasp *mcasp;
+
+       if (!pdev)
+               return -EPROBE_DEFER;
+
+       mcasp = dev_get_drvdata(&pdev->dev);
+       if (!mcasp)
+               return -EPROBE_DEFER;
+
+       if (!mcasp->is_mcasp8)
+               return 0;
+
+       /* Set the pin as McASP pin */
+       mcasp_clr_bits(mcasp, DAVINCI_MCASP_PFUNC_REG,
+                      DRA7_MCASP_HDMI_SEL_GPIO);
+
+       pm_runtime_put_sync(mcasp->dev);
+
+       return 0;
+}
+EXPORT_SYMBOL(dra7_mcasp_hdmi_gpio_put);
+
+int dra7_mcasp_hdmi_gpio_set(struct platform_device *pdev, bool high)
+{
+       struct davinci_mcasp *mcasp;
+
+       if (!pdev)
+               return -EPROBE_DEFER;
+
+       mcasp = dev_get_drvdata(&pdev->dev);
+       if (!mcasp)
+               return -EPROBE_DEFER;
+
+       if (!mcasp->is_mcasp8)
+               return 0;
+
+       if (!pm_runtime_active(mcasp->dev)) {
+               dev_warn(mcasp->dev, "mcasp8 is not enabled!\n");
+               return -ENODEV;
+       }
+
+       if (mcasp->hdmi_sel_gpio == high)
+               return 0;
+
+       mcasp->hdmi_sel_gpio = high;
+       if (mcasp->hdmi_sel_gpio)
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDOUT_REG,
+                              DRA7_MCASP_HDMI_SEL_GPIO);
+       else
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDOUT_REG,
+                              DRA7_MCASP_HDMI_SEL_GPIO);
+
+       return 0;
+}
+EXPORT_SYMBOL(dra7_mcasp_hdmi_gpio_set);
+#endif /* CONFIG_DISPLAY_DRA7EVM_ENCODER_TPD12S015 */
+
 static int davinci_mcasp_probe(struct platform_device *pdev)
 {
        struct davinci_pcm_dma_params *dma_params;
@@ -1374,6 +1686,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                }
        }
 
+#if IS_ENABLED(CONFIG_DISPLAY_DRA7EVM_ENCODER_TPD12S015)
+       if (pdata->version == MCASP_VERSION_4 && mem->start == 0x4847c000)
+               mcasp->is_mcasp8 = true;
+#endif
        ioarea = devm_request_mem_region(&pdev->dev, mem->start,
                        resource_size(mem), pdev->name);
        if (!ioarea) {
@@ -1383,12 +1699,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        pm_runtime_enable(&pdev->dev);
 
-       ret = pm_runtime_get_sync(&pdev->dev);
-       if (IS_ERR_VALUE(ret)) {
-               dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
-               return ret;
-       }
-
        mcasp->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
        if (!mcasp->base) {
                dev_err(&pdev->dev, "ioremap failed\n");
@@ -1511,6 +1821,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        else
                dma_data->filter_data = &dma_params->channel;
 
+       ret = davinci_mcasp_init_ch_constraints(mcasp);
+       if (ret)
+               goto err;
+
        dev_set_drvdata(&pdev->dev, mcasp);
 
        mcasp_reparent_fck(pdev);
@@ -1560,14 +1874,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        return 0;
 
 err:
-       pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        return ret;
 }
 
 static int davinci_mcasp_remove(struct platform_device *pdev)
 {
-       pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
        return 0;
index be873c1b0c204f4f902bfc7e2edad8c10d623e15..d32c540555c41b6c3f9b8f5817a5baa09b5ca47b 100644 (file)
@@ -1,10 +1,8 @@
 #
 # Jz4740 Platform Support
 #
-snd-soc-jz4740-objs := jz4740-pcm.o
 snd-soc-jz4740-i2s-objs := jz4740-i2s.o
 
-obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o
 obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
 
 # Jz4740 Machine Support
index e02abd5f6797bfac3b189ea4873afa397702e3d0..4d3d0b398773e94db0f33452ad939b39e3db451e 100644 (file)
@@ -224,16 +224,18 @@ static int hdmi_dai_hw_params(struct snd_pcm_substream *substream,
 
        cea->db3 = 0; /* not used, all zeros */
 
-       /*
-        * The OMAP HDMI IP requires to use the 8-channel channel code when
-        * transmitting more than two channels.
-        */
        if (params_channels(params) == 2)
                cea->db4_ca = 0x0;
+       else if (params_channels(params) == 6)
+               cea->db4_ca = 0xb;
        else
                cea->db4_ca = 0x13;
 
-       cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED;
+       if (cea->db4_ca == 0x00)
+               cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PERMITTED;
+       else
+               cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED;
+
        /* the expression is trivial but makes clear what we are doing */
        cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV);
 
index 8d809f8509c8e8867a0ddfb28e46d423dd71c19e..25ef4919813df421f6e17493f6772ee52b4b83a3 100644 (file)
@@ -200,7 +200,7 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd)
        struct snd_pcm *pcm = rtd->pcm;
        int ret;
 
-       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64));
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
 
index 319754cf62086ef86723a9df60c236d31edfab16..daf61abc3670f5d243040a53b3520cb9f1419764 100644 (file)
@@ -118,12 +118,8 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        if (snd_BUG_ON(!arg || !emu))
                return -ENXIO;
 
-       mutex_lock(&emu->register_mutex);
-
-       if (!snd_emux_inc_count(emu)) {
-               mutex_unlock(&emu->register_mutex);
+       if (!snd_emux_inc_count(emu))
                return -EFAULT;
-       }
 
        memset(&callback, 0, sizeof(callback));
        callback.owner = THIS_MODULE;
@@ -135,7 +131,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        if (p == NULL) {
                snd_printk(KERN_ERR "can't create port\n");
                snd_emux_dec_count(emu);
-               mutex_unlock(&emu->register_mutex);
                return -ENOMEM;
        }
 
@@ -148,8 +143,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        reset_port_mode(p, arg->seq_mode);
 
        snd_emux_reset_port(p);
-
-       mutex_unlock(&emu->register_mutex);
        return 0;
 }
 
@@ -195,13 +188,11 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg)
        if (snd_BUG_ON(!emu))
                return -ENXIO;
 
-       mutex_lock(&emu->register_mutex);
        snd_emux_sounds_off_all(p);
        snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port));
        snd_seq_event_port_detach(p->chset.client, p->chset.port);
        snd_emux_dec_count(emu);
 
-       mutex_unlock(&emu->register_mutex);
        return 0;
 }
 
index 7778b8e19782e24a3ca56a5aa5dff9e00bf33e4d..a0209204ae4892a490877c30eaf056c45cd8043a 100644 (file)
@@ -124,12 +124,10 @@ snd_emux_detach_seq(struct snd_emux *emu)
        if (emu->voices)
                snd_emux_terminate_all(emu);
                
-       mutex_lock(&emu->register_mutex);
        if (emu->client >= 0) {
                snd_seq_delete_kernel_client(emu->client);
                emu->client = -1;
        }
-       mutex_unlock(&emu->register_mutex);
 }
 
 
@@ -269,8 +267,8 @@ snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data,
 /*
  * increment usage count
  */
-int
-snd_emux_inc_count(struct snd_emux *emu)
+static int
+__snd_emux_inc_count(struct snd_emux *emu)
 {
        emu->used++;
        if (!try_module_get(emu->ops.owner))
@@ -284,12 +282,21 @@ snd_emux_inc_count(struct snd_emux *emu)
        return 1;
 }
 
+int snd_emux_inc_count(struct snd_emux *emu)
+{
+       int ret;
+
+       mutex_lock(&emu->register_mutex);
+       ret = __snd_emux_inc_count(emu);
+       mutex_unlock(&emu->register_mutex);
+       return ret;
+}
 
 /*
  * decrease usage count
  */
-void
-snd_emux_dec_count(struct snd_emux *emu)
+static void
+__snd_emux_dec_count(struct snd_emux *emu)
 {
        module_put(emu->card->module);
        emu->used--;
@@ -298,6 +305,12 @@ snd_emux_dec_count(struct snd_emux *emu)
        module_put(emu->ops.owner);
 }
 
+void snd_emux_dec_count(struct snd_emux *emu)
+{
+       mutex_lock(&emu->register_mutex);
+       __snd_emux_dec_count(emu);
+       mutex_unlock(&emu->register_mutex);
+}
 
 /*
  * Routine that is called upon a first use of a particular port
@@ -317,7 +330,7 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info)
 
        mutex_lock(&emu->register_mutex);
        snd_emux_init_port(p);
-       snd_emux_inc_count(emu);
+       __snd_emux_inc_count(emu);
        mutex_unlock(&emu->register_mutex);
        return 0;
 }
@@ -340,7 +353,7 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info)
 
        mutex_lock(&emu->register_mutex);
        snd_emux_sounds_off_all(p);
-       snd_emux_dec_count(emu);
+       __snd_emux_dec_count(emu);
        mutex_unlock(&emu->register_mutex);
        return 0;
 }
index 5a723df670b4608fc83ab79ccafb43af01c73895..a82ec53b8fb3b6f5e780a0f39b7173c23e96597a 100644 (file)
@@ -178,6 +178,7 @@ static const struct rc_config {
        { USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
        { USB_ID(0x041e, 0x3042), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 */
        { USB_ID(0x041e, 0x30df), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
+       { USB_ID(0x041e, 0x3237), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
        { USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
 };
 
index 83bddbdb90e92dad2b3a8927556efd05feb579cc..5293b5ac8b9d6022fce2eafa939781b733a01497 100644 (file)
@@ -1773,6 +1773,36 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       USB_DEVICE(0x0582, 0x0159),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "Roland", */
+               /* .product_name = "UA-22", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0001,
+                                       .in_cables = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 /* this catches most recent vendor-specific Roland devices */
 {
        .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
index 25b40d1199e64293a00b1cf95cd627cfe14e4038..cd7a654ed4f99e637523b5fa58b83e33aa0dd96d 100644 (file)
@@ -2,6 +2,9 @@
 # TI Baseport Config Options
 ##################################################
 CONFIG_CGROUPS=y
+# Needed by systemd based distributions like debian
+CONFIG_FHANDLE=y
+
 
 CONFIG_REGULATOR_GPIO=y
 
index dcc665228c71fd09f7b39c2486063d98f7176445..deb3569ab004ffc8904121695773ffd02d239140 100644 (file)
@@ -372,7 +372,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
        switch (type_len) {
        case KBUFFER_TYPE_PADDING:
                *length = read_4(kbuf, data);
-               data += *length;
                break;
 
        case KBUFFER_TYPE_TIME_EXTEND:
index d1b3a361e526d83d1ce011819d917e6f9c256f81..4039854560d0d5dffe32150562a6f11b2791033f 100644 (file)
@@ -1,8 +1,12 @@
 CC             = $(CROSS_COMPILE)gcc
-BUILD_OUTPUT   := $(PWD)
+BUILD_OUTPUT   := $(CURDIR)
 PREFIX         := /usr
 DESTDIR                :=
 
+ifeq ("$(origin O)", "command line")
+       BUILD_OUTPUT := $(O)
+endif
+
 turbostat : turbostat.c
 CFLAGS +=      -Wall
 CFLAGS +=      -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"'
index 26954a7d9b03a37acbf5415ee81e1ba7bae40493..4eec2d43610988abc444c87fb84d00c5973c99c6 100644 (file)
@@ -548,11 +548,10 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
        u32 val;
        u32 *reg;
 
-       offset >>= 1;
        reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg,
-                                 vcpu->vcpu_id, offset);
+                                 vcpu->vcpu_id, offset >> 1);
 
-       if (offset & 2)
+       if (offset & 4)
                val = *reg >> 16;
        else
                val = *reg & 0xffff;
@@ -561,13 +560,13 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
        vgic_reg_access(mmio, &val, offset,
                        ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
        if (mmio->is_write) {
-               if (offset < 4) {
+               if (offset < 8) {
                        *reg = ~0U; /* Force PPIs/SGIs to 1 */
                        return false;
                }
 
                val = vgic_cfg_compress(val);
-               if (offset & 2) {
+               if (offset & 4) {
                        *reg &= 0xffff;
                        *reg |= val << 16;
                } else {
@@ -1527,17 +1526,33 @@ int kvm_vgic_hyp_init(void)
                goto out_unmap;
        }
 
-       kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-                vctrl_res.start, vgic_maint_irq);
-       on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
-
        if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
                kvm_err("Cannot obtain VCPU resource\n");
                ret = -ENXIO;
                goto out_unmap;
        }
+
+       if (!PAGE_ALIGNED(vcpu_res.start)) {
+               kvm_err("GICV physical address 0x%llx not page aligned\n",
+                       (unsigned long long)vcpu_res.start);
+               ret = -ENXIO;
+               goto out_unmap;
+       }
+
+       if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
+               kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+                       (unsigned long long)resource_size(&vcpu_res),
+                       PAGE_SIZE);
+               ret = -ENXIO;
+               goto out_unmap;
+       }
+
        vgic_vcpu_base = vcpu_res.start;
 
+       kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
+                vctrl_res.start, vgic_maint_irq);
+       on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
+
        goto out;
 
 out_unmap:
@@ -1668,10 +1683,11 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
        if (addr + size < addr)
                return -EINVAL;
 
+       *ioaddr = addr;
        ret = vgic_ioaddr_overlap(kvm);
        if (ret)
-               return ret;
-       *ioaddr = addr;
+               *ioaddr = VGIC_ADDR_UNDEF;
+
        return ret;
 }
 
index 66112533b1e9cfac421ce3a6b9f4d9be72fea9a3..eed250e9c21895cd924a7852fba2b16427216204 100644 (file)
@@ -1549,8 +1549,8 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
        ghc->generation = slots->generation;
        ghc->len = len;
        ghc->memslot = gfn_to_memslot(kvm, start_gfn);
-       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
-       if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
+       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, NULL);
+       if (!kvm_is_error_hva(ghc->hva) && nr_pages_needed <= 1) {
                ghc->hva += offset;
        } else {
                /*